/** * For the given value of the alpha smoothing constant, returns the best fit model where the value * of the beta (trend) smoothing constant is between betaMin and betaMax. This method will * continually try to refine the estimate of beta until a tolerance of less than betaTolerance is * achieved. * * <p>Note that the descriptions of the parameters below include a discussion of valid values. * However, since this is a private method and to help improve performance, we don't provide any * validation of these parameters. Using invalid values may lead to unexpected results. * * @param dataSet the data set for which a best fit model is required. * @param alpha the (fixed) value of the alpha smoothing constant to use for the best fit model. * @param betaMin the minimum value of the beta (trend) smoothing constant accepted in the * resulting best fit model. Must be greater than (or equal to) 0.0 and less than betaMax. * @param betaMax the maximum value of the beta (trend) smoothing constant accepted in the * resulting best fit model. Must be greater than betaMin and less than (or equal to) 1.0. * @param betaTolerance the tolerance within which the beta value is required. Must be * considerably less than 1.0. However, note that the smaller this value the longer it will * take to diverge on a best fit model. */ private static TripleExponentialSmoothingModel findBestBeta( DataSet dataSet, double alpha, double betaMin, double betaMax, double betaTolerance) { int stepsPerIteration = 10; if (betaMin < 0.0) betaMin = 0.0; if (betaMax > 1.0) betaMax = 1.0; TripleExponentialSmoothingModel bestModel = new TripleExponentialSmoothingModel(alpha, betaMin, 0.0); bestModel.init(dataSet); double initialMSE = bestModel.getMSE(); boolean betaImproving = true; double betaStep = (betaMax - betaMin) / stepsPerIteration; double beta = betaMin + betaStep; for (; beta <= betaMax || betaImproving; ) { TripleExponentialSmoothingModel model = new TripleExponentialSmoothingModel(alpha, beta, 0.0); model.init(dataSet); if (model.getMSE() < bestModel.getMSE()) bestModel = model; else betaImproving = false; beta += betaStep; if (beta > 1.0) betaImproving = false; } // If we're making progress, then try to refine the beta estimate if (bestModel.getMSE() < initialMSE && betaStep > betaTolerance) { // Can this be further refined - improving efficiency - by // only searching in the range beta-betaStep/2 to // beta+betaStep/2 ? return findBestBeta( dataSet, bestModel.getAlpha(), bestModel.getBeta() - betaStep, bestModel.getBeta() + betaStep, betaTolerance); } return bestModel; }