【问题标题】:Estimating Holt-Winters smoothing coefficients in Java在 Java 中估计 Holt-Winters 平滑系数
【发布时间】:2012-09-16 02:27:17
【问题描述】:

我正在开发一个用 Java 编写的系统,该系统能够使用历史数据进行预测。使用的算法是this Holt-Winters implementation(乘法季节性)的Java 端口。

我有几个要分析的时间序列,我们需要为这些时间序列设置不同的平滑系数。目前该算法似乎运行良好,唯一的问题是如何确定平滑系数(alpha、beta、gamma)的最合理值。

我知道我需要某种非线性优化,但我根本不是数学家,所以我有点迷失在所有这些理论和概念中。

编辑

我有很多不同的时间序列要分析,我想知道是否有标准/足够好的技术(图书馆会更好)来计算我应该提供给 Holt-Winters 算法的平滑参数.

【问题讨论】:

    标签: java statistics time-series


    【解决方案1】:

    你看过JMulTi吗?

    This SO question 可能与您非常相关。

    任何研究 Holt-Winters 的人都应该查看 Prof. Hyndman's site。 他是一位领域专家,也是 R 中forecast() 库的创建者。

    你说你想更好地理解这项技术。好消息是 Hyndman 正在编写一本教科书,我们可以免费查阅。 Holt-winters的具体章节在:http://otexts.com/fpp/7/5/

    我知道你想在 Java 中使用它,但如果 R​​ 是一个选项,你应该试一试。 (有些人建议从 R 编写并将其读入您的 Java 程序。)

    更新:

    如果是你关心的初始硬件参数,我只能想到ets包,它实现了最大似然搜索来得到参数。如果找不到 Java 实现,最好的办法可能是使用 JRI (rJava) 并在其中调用 etsHoltWinters

    希望对您有所帮助。

    【讨论】:

    • 感谢您的回答,我知道 Hyndman 教授的工作,我发现的几乎所有内容都将我重定向到他的网站。关键是我已经有一个 Holt-Winters impl 正在工作,我想知道的是如何进行非线性优化来计算硬件算法的平滑参数
    • 更新了我的回复,强调为平滑参数 α、β 和 Γ 找到好的初始值。
    • 我会接受这个,因为这似乎是一个合理的答案,即使不是我所期望的
    【解决方案2】:

    您可以使用 Apache 实现的 Nelder Mead Optimizer (SimplexOptimizer)

    double[] dataPoints = {
                141, 53, 78, 137, 182, 161, 177,
                164, 70, 67, 129, 187, 161, 136,
                167, 57, 61, 159, 158, 152, 169,
                181, 65, 60, 146, 186, 180, 181,
                167, 70, 62, 170, 193, 167, 176,
                149, 69, 68, 168, 181, 200, 179,
                181, 83, 72, 157, 188, 193, 173,
                184, 61, 59, 158, 158, 143, 208,
                172, 82, 86, 158, 194, 193, 159
    };
    
    NelderMeadOptimizer.Parameters op = NelderMeadOptimizer.optimize(dataPoints, 7);
    op.getAlpha(); 
    op.getBeta(); 
    op.getGamma();
    

    现在您需要 NelderMeadOptimizer:

    import org.apache.commons.math3.analysis.MultivariateFunction;
    import org.apache.commons.math3.optim.InitialGuess;
    import org.apache.commons.math3.optim.MaxEval;
    import org.apache.commons.math3.optim.MaxIter;
    import org.apache.commons.math3.optim.PointValuePair;
    import org.apache.commons.math3.optim.nonlinear.scalar.GoalType;
    import org.apache.commons.math3.optim.nonlinear.scalar.MultivariateFunctionMappingAdapter;
    import org.apache.commons.math3.optim.nonlinear.scalar.ObjectiveFunction;
    import org.apache.commons.math3.optim.nonlinear.scalar.noderiv.NelderMeadSimplex;
    import org.apache.commons.math3.optim.nonlinear.scalar.noderiv.SimplexOptimizer;
    
    import java.util.List;
    
    public class NelderMeadOptimizer {
    
        // configuration
        private static final double minValueForOptimizedParameters = 0.001;
        private static final double maxValueForOptimizedParameters = 0.99;
        private static final double simplexRelativeThreshold = 0.0001;
        private static final double simplexAbsoluteThreshold = 0.0001;
    
        private static final double DEFAULT_LEVEL_SMOOTHING = 0.01;
        private static final double DEFAULT_TREND_SMOOTHING = 0.01;
        private static final double DEFAULT_SEASONAL_SMOOTHING = 0.01;
    
        private static final int MAX_ALLOWED_NUMBER_OF_ITERATION = 1000;
        private static final int MAX_ALLOWED_NUMBER_OF_EVALUATION = 1000;
    
        /**
         *
         * @param dataPoints the observed data points
         * @param seasonLength the amount of data points per season
         * @return the optimized parameters
         */
        public static Parameters optimize(double[] dataPoints, int seasonLength) {
            MultivariateFunctionMappingAdapter costFunc = getCostFunction(dataPoints, seasonLength);
            double[] initialGuess = getInitialGuess(dataPoints, seasonLength);
            double[] optimizedValues = optimize(initialGuess, costFunc);
            double alpha = optimizedValues[0];
            double beta = optimizedValues[1];
            double gamma = optimizedValues[2];
            return new Parameters(alpha, beta, gamma);
        }
    
        /**
         * Optimizes parameters using the Nelder-Mead Method
         * @param initialGuess initial guess / state required for Nelder-Mead-Method
         * @param costFunction which defines that the Mean Squared Error has to be minimized
         * @return the optimized values
         */
        private static double[] optimize(double[] initialGuess, MultivariateFunctionMappingAdapter costFunction) {
            double[] result;
    
            SimplexOptimizer optimizer = new SimplexOptimizer(simplexRelativeThreshold, simplexAbsoluteThreshold);
    
            PointValuePair unBoundedResult = optimizer.optimize(
                    GoalType.MINIMIZE,
                    new MaxIter(MAX_ALLOWED_NUMBER_OF_ITERATION),
                    new MaxEval(MAX_ALLOWED_NUMBER_OF_EVALUATION),
                    new InitialGuess(initialGuess),
                    new ObjectiveFunction(costFunction),
                    new NelderMeadSimplex(initialGuess.length));
    
            result = costFunction.unboundedToBounded(unBoundedResult.getPoint());
            return result;
        }
    
    
        /**
         * Defines that the Mean Squared Error has to be minimized
         * in order to get optimized / good parameters for alpha, betta and gamma.
         * It also defines the minimum and maximum values for the parameters to optimize.
         * @param dataPoints the data points
         * @param seasonLength the amount of data points per season
         * @return a cost function  {@link MultivariateFunctionMappingAdapter} which
         * defines that the Mean Squared Error has to be minimized
         * in order to get optimized / good parameters for alpha, betta and gamma
         */
        private static MultivariateFunctionMappingAdapter getCostFunction(final double[] dataPoints, final int seasonLength) {
    
            MultivariateFunction multivariateFunction = new MultivariateFunction() {
                @Override
                public double value(double[] point) {
                    double alpha = point[0];
                    double beta = point[1];
                    double gamma = point[2];
    
                    if (beta >= alpha) {
                        return Double.POSITIVE_INFINITY;
                    }
    
                    List<Double> predictedValues = TripleExponentialSmoothing.getSmoothedDataPointsWithPredictions(dataPoints, seasonLength, alpha, beta, gamma, 1);
    
                    predictedValues.remove(predictedValues.size()-1);
    
                    double meanSquaredError = getMeanSquaredError(dataPoints, predictedValues);
                    return meanSquaredError;
                }
            };
    
            double[][] minMax = getMinMaxValues();
            return new MultivariateFunctionMappingAdapter(multivariateFunction, minMax[0], minMax[1]);
        }
    
        /**
         * Generates an initial guess/state required for Nelder-Mead-Method.
         * @param dataPoints the data points
         * @param seasonLength the amount of data points per season
         * @return array containing initial guess/state required for Nelder-Mead-Method
         */
        public static double[] getInitialGuess(double[] dataPoints, int seasonLength){
            double[] initialGuess = new double[3];
            initialGuess[0] = DEFAULT_LEVEL_SMOOTHING;
            initialGuess[1] = DEFAULT_TREND_SMOOTHING;
            initialGuess[2] = DEFAULT_SEASONAL_SMOOTHING;
            return initialGuess;
        }
    
        /**
         * Get minimum and maximum values for the parameters alpha (level coefficient),
         * beta (trend coefficient) and gamma (seasonality coefficient)
         * @return array containing all minimum and maximum values for the parameters alpha, beta and gamma
         */
        private static double[][] getMinMaxValues() {
            double[] min = new double[3];
            double[] max = new double[3];
            min[0] = minValueForOptimizedParameters;
            min[1] = minValueForOptimizedParameters;
            min[2] = minValueForOptimizedParameters;
    
            max[0] = maxValueForOptimizedParameters;
            max[1] = maxValueForOptimizedParameters;
            max[2] = maxValueForOptimizedParameters;
            return new double[][]{min, max};
        }
    
    
        /**
         * Compares observed data points from the past and predicted data points
         * in order to calculate the Mean Squared Error (MSE)
         * @param observedData the observed data points from the past
         * @param predictedData the predicted data points
         * @return the Mean Squared Error (MSE)
         */
        public static double getMeanSquaredError(double[] observedData, List<Double> predictedData){
            double sum = 0;
    
            for(int i=0; i<observedData.length; i++){
                double error = observedData[i] - predictedData.get(i);
                double sumSquaredError = error * error; // SSE
                sum += sumSquaredError;
            }
    
            return sum / observedData.length;
        }
    
        /**
         * Holds the parameters alpha (level coefficient), beta (trend coefficient)
         * and gamma (seasonality coefficient) for Triple Exponential Smoothing.
         */
        public static class Parameters {
            public final double alpha;
            public final double beta;
            public final double gamma;
    
            public Parameters(double alpha, double beta, double gamma) {
                this.alpha = alpha;
                this.beta = beta;
                this.gamma = gamma;
            }
    
            public double getAlpha() {
                return alpha;
            }
    
            public double getBeta() {
                return beta;
            }
    
            public double getGamma() {
                return gamma;
            }
        };
    }
    

    【讨论】:

      猜你喜欢
      • 2023-04-11
      • 2019-11-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-06-27
      • 1970-01-01
      • 1970-01-01
      • 2011-08-17
      相关资源
      最近更新 更多