📄 abstracttimebasedmodel.java
字号:
//// OpenForecast - open source, general-purpose forecasting package.// Copyright (C) 2002-2004 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.Comparator;import java.util.Iterator;import java.util.SortedMap;import java.util.TreeMap;import net.sourceforge.openforecast.ForecastingModel;import net.sourceforge.openforecast.DataPoint;import net.sourceforge.openforecast.DataSet;import net.sourceforge.openforecast.Observation;/** * A time based forecasting model is the base class that implements much of * the common code for models based on a time series. In particular, it was * designed to support the needs of the Weighted Moving Average, as well as * the Single, Double and Triple Exponential Smoothing models. * * <p>These models have an advantage over other forecasting models in that * they smooth out peaks and troughs (or valleys) in a set of observations. * However, they also have several disadvantages. In particular these models * do not produce an actual equation. Therefore, they often are not all that * useful as medium-long range forecasting tools. They can only reliably be * used to forecast a few periods into the future. * @author Steven R. Gould * @since 0.4 */public abstract class AbstractTimeBasedModel extends AbstractForecastingModel{ /** * The name of the independent (time) variable used in this model. */ private String timeVariable = null; /** * Initialized to the time difference (in whatever units time is reported * in) between two consecutive data points. You could also think of this * as the "delta time" between data points. */ private double timeDiff = 0.0; /** * Stores the minimum number of prior periods of data required to produce a * forecast. Since this varies depending on the details of the model, any * subclass must call setMinimumNumberOfPeriods - usually from the * constructor - before init is invoked to provide the correct information. */ private int minPeriods = 0; /** * The observed values are stored for future reference. In this model, * unlike most others, we store all observed values. This is because these * models don't derive any formula from the data, so the values may be * needed later in order to derive future forecasts. */ private DataSet observedValues; /** * The forecast values are stored to save recalculation. In this model, * unlike most others, we store all forecast values. This is because these * models don't derive any formula from the data. */ private DataSet forecastValues; /** * The minimum value of the independent variable supported by this * forecasting model. This is dependent on the data set used to * initialize the model. * @see #maxIndependentValue */ private double minTimeValue; /** * The maximum value of the independent variable supported by this * forecasting model. This is dependent on the data set used to * initialize the model. * @see #minTimeValue */ private double maxTimeValue; /** * Constructs a new time based forecasting model. For a valid model to be * constructed, you should call init and pass in a data set containing a * series of data points. The data set should also have the time variable * initialized to the independent time variable name. */ public AbstractTimeBasedModel() { } /** * Constructs a new time based forecasting model, using the named variable * as the independent (time) variable. * @param timeVariable the name of the independent variable to use as the * time variable in this model. * @deprecated As of 0.4, replaced by {@link #AbstractTimeBasedModel}. */ public AbstractTimeBasedModel( String timeVariable ) { this.timeVariable = timeVariable; } /** * Returns the current number of periods used in this model. This is also * the minimum number of periods required in order to produce a valid * forecast. Since this varies depending on the details of the model, any * subclass must override this to provide the correct information. * @return the minimum number of periods used in this model. */ protected abstract int getNumberOfPeriods(); /** * Used to initialize the time based model. This method must be called * before any other method in the class. Since the time based model does * not derive any equation for forecasting, this method uses the input * DataSet to calculate forecast values for all values of the independent * time variable within the initial data set. * @param dataSet a data set of observations that can be used to initialize * the forecasting parameters of the forecasting model. */ public void init( DataSet dataSet ) { initTimeVariable( dataSet ); if ( dataSet == null || dataSet.size() == 0 ) throw new IllegalArgumentException("Data set cannot be empty in call to init."); int minPeriods = getNumberOfPeriods(); if ( dataSet.size() < minPeriods ) throw new IllegalArgumentException("Data set too small. Need " +minPeriods +" data points, but only " +dataSet.size() +" passed to init."); observedValues = new DataSet( dataSet ); observedValues.sort( timeVariable ); // Check that intervals between data points are consistent // i.e. check for complete data set Iterator it = observedValues.iterator(); DataPoint dp = (DataPoint)it.next(); // first data point double lastValue = dp.getIndependentValue(timeVariable); dp = (DataPoint)it.next(); // second data point double currentValue = dp.getIndependentValue(timeVariable); // Create data set in which to save new forecast values forecastValues = new DataSet(); // Determine "standard"/expected time difference between observations timeDiff = currentValue - lastValue; // Min. time value is first observation time minTimeValue = lastValue; while ( it.hasNext() ) { lastValue = currentValue; // Get next data point dp = (DataPoint)it.next(); currentValue = dp.getIndependentValue(timeVariable); double diff = currentValue - lastValue; if ( Math.abs(timeDiff - diff) > TOLERANCE ) throw new IllegalArgumentException( "Inconsistent intervals found in time series, using variable '"+timeVariable+"'" ); try { initForecastValue( currentValue ); } catch (IllegalArgumentException ex) { // We can ignore these during initialization } } // Create test data set for determining accuracy indicators // - same as input data set, but without the first n data points DataSet testDataSet = new DataSet( observedValues ); int count = 0; while ( count++ < minPeriods ) testDataSet.remove( (testDataSet.iterator()).next() ); // Calculate accuracy calculateAccuracyIndicators( testDataSet ); } /** * Initializes the time variable from the given data set. If the data set * does not have a time variable explicitly defined, then provided there * is only one independent variable defined for the data set that is used * as the time variable. If more than one independent variable is defined * for the data set, then it is not possible to take an educated guess at * which one is the time variable. In this case, an * IllegalArgumentException will be thrown. * @param dataSet the data set to use to initialize the time variable. * @throws IllegalArgumentException If more than one independent variable * is defined for the data set and no time variable has been specified. To * correct this, be sure to explicitly specify the time variable in the * data set passed to {@link #init}. */ protected void initTimeVariable( DataSet dataSet ) throws IllegalArgumentException { if ( timeVariable == null ) { // Time variable not set, so look at independent variables timeVariable = dataSet.getTimeVariable(); if ( timeVariable == null ) { String[] independentVars = dataSet.getIndependentVariables(); if ( independentVars.length != 1 ) throw new IllegalArgumentException("Unable to determine the independent time variable for the data set passed to init for "+toString()+". Please use DataSet.setTimeVariable before invoking model.init."); timeVariable = independentVars[0]; } } }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -