//
//  OpenForecast - open source, general-purpose forecasting package.
//  Copyright (C) 2002-2011  Steven R. Gould
//
//  This library is free software; you can redistribute it and/or
//  modify it under the terms of the GNU Lesser General Public
//  License as published by the Free Software Foundation; either
//  version 2.1 of the License, or (at your option) any later version.
//
//  This library is distributed in the hope that it will be useful,
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
//  Lesser General Public License for more details.
//
//  You should have received a copy of the GNU Lesser General Public
//  License along with this library; if not, write to the Free Software
//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
//

package net.sourceforge.openforecast.models;


import java.util.Iterator;

import net.sourceforge.openforecast.ForecastingModel;
import net.sourceforge.openforecast.DataPoint;
import net.sourceforge.openforecast.DataSet;


/**
 * This class implements a variety of methods that are common across all
 * forecasting models. In particular, the calculation of the accuracy
 * indicators can be generalized, and is therefore implemented in
 * the method, calculateAccuracyIndicators.
 * @since 0.3
 * @author Steven R. Gould
 * @see #calculateAccuracyIndicators
 */
public abstract class AbstractForecastingModel implements ForecastingModel
{
    /**
     * The maximum tolerance permitted when comparing two double precision
     * numbers for equality. In other words, if two numbers are different
     * by less than the value of TOLERANCE, then they are considered equal.
     */
    static double TOLERANCE = 0.00000001;
    
    /**
     * The accuracy indicators, or measures of accuracy, obtained by applying
     * this forecasting model to the initial data set. Initialized following a
     * call to init.
     */
    protected AccuracyIndicators accuracyIndicators = new AccuracyIndicators();
    
    /**
     * Remembers whether this model has been properly initialized.
     */
    protected boolean initialized = false;
    
    /**
     * Default constructor.
     */
    protected AbstractForecastingModel()
    {
    }
    
    /**
     * Returns the Akaike Information Criteria obtained from applying the current
     * forecasting model to the initial data set to try and predict each data
     * point. The result is an indication of the accuracy of the model when
     * applied to your initial data set - the smaller the Akaike Information
     * Criteria (AIC), the more accurate the model.
     * @return the Akaike Information Criteria (AIC) when the current model was
     *         applied to the initial data set.
     * @throws ModelNotInitializedException if getAIC is called before the
     *         model has been initialized with a call to init.
     * @since 0.5
     */
    public double getAIC()
    {
        if ( !initialized )
            throw new ModelNotInitializedException();
        
        return accuracyIndicators.getAIC();
    }
    
    /**
     * Returns the bias - the arithmetic mean of the errors - obtained from
     * applying the current forecasting model to the initial data set to try
     * and predict each data point. The result is an indication of the accuracy
     * of the model when applied to your initial data set - the smaller the
     * bias, the more accurate the model.
     * @return the bias - mean of the errors - when the current model was
     *         applied to the initial data set.
     * @throws ModelNotInitializedException if getBias is called before the
     *         model has been initialized with a call to init.
     */
    public double getBias()
    {
        if ( !initialized )
            throw new ModelNotInitializedException();
        
        return accuracyIndicators.getBias();
    }
    
    /**
     * Returns the mean absolute deviation obtained from applying the current
     * forecasting model to the initial data set to try and predict each data
     * point. The result is an indication of the accuracy of the model when
     * applied to your initial data set - the smaller the Mean Absolute
     * Deviation (MAD), the more accurate the model.
     * @return the mean absolute deviation (MAD) when the current model was
     *         applied to the initial data set.
     * @throws ModelNotInitializedException if getMAD is called before the
     *         model has been initialized with a call to init.
     */
    public double getMAD()
    {
        if ( !initialized )
            throw new ModelNotInitializedException();
        
        return accuracyIndicators.getMAD();
    }
    
    /**
     * Returns the mean absolute percentage error obtained from applying the
     * current forecasting model to the initial data set to try and predict
     * each data point. The result is an indication of the accuracy of the
     * model when applied to the initial data set - the smaller the Mean
     * Absolute Percentage Error (MAPE), the more accurate the model.
     * @return the mean absolute percentage error (MAPE) when the current model
     *         was applied to the initial data set.
     * @throws ModelNotInitializedException if getMAPE is called before the
     *         model has been initialized with a call to init.
     */
    public double getMAPE()
    {
        if ( !initialized )
            throw new ModelNotInitializedException();
        
        return accuracyIndicators.getMAPE();
    }
    
    /**
     * Returns the mean square of the errors (MSE) obtained from applying the
     * current forecasting model to the initial data set to try and predict
     * each data point. The result is an indication of the accuracy of the
     * model when applied to your initial data set - the smaller the Mean
     * Square of the Errors, the more accurate the model.
     * @return the mean square of the errors (MSE) when the current model was
     *         applied to the initial data set.
     * @throws ModelNotInitializedException if getMSE is called before the
     *         model has been initialized with a call to init.
     */
    public double getMSE()
    {
        if ( !initialized )
            throw new ModelNotInitializedException();
        
        return accuracyIndicators.getMSE();
    }
    
    /**
     * Returns the Sum of Absolute Errors (SAE) obtained by applying the
     * current forecasting model to the initial data set. Initialized following
     * a call to init.
     * @return the sum of absolute errors (SAE) obtained by applying this
     *         forecasting model to the initial data set.
     * @throws ModelNotInitializedException if getSAE is called before the
     *         model has been initialized with a call to init.
     */
    public double getSAE()
    {
        if ( !initialized )
            throw new ModelNotInitializedException();
        
        return accuracyIndicators.getSAE();
    }
    
    /**
     * Using the current model parameters (initialized in init), apply the
     * forecast model to the given data set. Each data point in the data set
     * must have valid values for the independent variables. Upon return, the
     * value of the dependent variable will be updated with the forecast
     * values computed.
     *
     * This method is provided as a convenience method, and iterates through the
     * data set invoking forecast(DataPoint) to do the actual forecast for each
     * data point. In general, it is not necessary to override this method.
     * However, if a subclass can provide a more efficient approach then it is
     * recommended that the subclass provide its own implementation.
     * @param dataSet the set of data points for which forecast values (for
     *        the dependent variable) are required.
     * @return the same data set passed in but with the dependent values
     *         updated to contain the new forecast values.
     * @throws ModelNotInitializedException if getMSE is called before the
     *         model has been initialized with a call to init.
     */
    public DataSet forecast( DataSet dataSet )
    {
        if ( !initialized )
            throw new ModelNotInitializedException();
        
        Iterator it = dataSet.iterator();
        while ( it.hasNext() )
            {
                DataPoint dp = it.next();
                dp.setDependentValue( forecast(dp) );
            }
        
        return dataSet;        
    }
    
    /**
     * A helper method to calculate the various accuracy indicators when
     * applying the given DataSet to the current forecasting model.
     * @param dataSet the DataSet to use to evaluate this model, and to
     *        calculate the accuracy indicators against.
     */
    protected void calculateAccuracyIndicators( DataSet dataSet )
    {
        // Note that the model has been initialized
        initialized = true;
        
        // Reset various helper summations
        double sumErr = 0.0;
        double sumAbsErr = 0.0;
        double sumAbsPercentErr = 0.0;
        double sumErrSquared = 0.0;
        
        // Obtain the forecast values for this model
        DataSet forecastValues = new DataSet( dataSet );
        forecast( forecastValues );
        
        // Calculate the Sum of the Absolute Errors
        Iterator it = dataSet.iterator();
        Iterator itForecast = forecastValues.iterator();
        while ( it.hasNext() )
            {
                // Get next data point
                DataPoint dp = it.next();
                double x = dp.getDependentValue();
                
                // Get next forecast value
                DataPoint dpForecast = itForecast.next();
                double forecastValue = dpForecast.getDependentValue();
                
                // Calculate error in forecast, and update sums appropriately
                double error = forecastValue - x;
                sumErr += error;
                sumAbsErr += Math.abs( error );
                sumAbsPercentErr += Math.abs( error / x );
                sumErrSquared += error*error;
            }
        
        // Initialize the accuracy indicators
        int n = dataSet.size();
        int p = getNumberOfPredictors();

        accuracyIndicators.setAIC( n*Math.log(2*Math.PI)
                   + Math.log(sumErrSquared/n)
                   + 2 * ( p+2 ) );
        accuracyIndicators.setBias( sumErr / n );
        accuracyIndicators.setMAD( sumAbsErr / n );
        accuracyIndicators.setMAPE( sumAbsPercentErr / n );
        accuracyIndicators.setMSE( sumErrSquared / n );
        accuracyIndicators.setSAE( sumAbsErr );
    }
}
// Local Variables:
// tab-width: 4
// End:

 

Ads help maintain this website.