class TeaLeaves::ExponentialSmoothingForecast
Attributes
alpha[R]
beta[R]
gamma[R]
model_parameters[R]
seasonality[R]
trend[R]
Public Class Methods
new(time_series, period, opts={})
click to toggle source
# File lib/tealeaves/exponential_smoothing_forecast.rb, line 73 def initialize(time_series, period, opts={}) @time_series = time_series @period = period @alpha = opts[:alpha] @beta = opts[:beta] @gamma = opts[:gamma] @trend = opts[:trend] @seasonality = opts[:seasonality] @seasonality_strategy = case @seasonality when :none NoSeasonalityStrategy.new(@period, opts[:gamma]) when :additive AdditiveSeasonalityStrategy.new(@period, opts[:gamma]) when :multiplicative MultiplicativeSeasonalityStrategy.new(@period, opts[:gamma]) end calculate_one_step_ahead_forecasts end
Public Instance Methods
improve(opts)
click to toggle source
# File lib/tealeaves/exponential_smoothing_forecast.rb, line 93 def improve(opts) new_opts = {:alpha => @alpha, :beta => @beta, :gamma => @gamma, :trend => @trend, :seasonality => @seasonality}.merge(opts) self.class.new(@time_series, @period, new_opts) end
initial_level()
click to toggle source
# File lib/tealeaves/exponential_smoothing_forecast.rb, line 100 def initial_level @initial_level ||= @time_series.take(@period).inject(&:+).to_f / @period end
initial_parameters()
click to toggle source
# File lib/tealeaves/exponential_smoothing_forecast.rb, line 114 def initial_parameters { :level => initial_level, :trend => initial_trend, :seasonality => initial_seasonal_indices, :index => @seasonality_strategy.start_index } end
initial_seasonal_indices()
click to toggle source
# File lib/tealeaves/exponential_smoothing_forecast.rb, line 109 def initial_seasonal_indices operation = @seasonality == :multiplicative ? :/ : :- @time_series.take(@period).map {|v| v.to_f.send(operation, initial_level) } end
initial_trend()
click to toggle source
# File lib/tealeaves/exponential_smoothing_forecast.rb, line 104 def initial_trend period_1, period_2 = @time_series.each_slice(@period).take(2) period_1.zip(period_2).map {|(a,b)| (b - a) / @period.to_f }.inject(&:+) / @period end
mean_squared_error()
click to toggle source
Returns the mean squared error of the forecast.
# File lib/tealeaves/exponential_smoothing_forecast.rb, line 131 def mean_squared_error return @mean_squared_error if @mean_squared_error numerator = errors.drop(@seasonality_strategy.start_index).map {|i| i ** 2 }.inject(&:+) @mean_squared_error = numerator / (errors.size - @seasonality_strategy.start_index).to_f end
predict(n=nil)
click to toggle source
# File lib/tealeaves/exponential_smoothing_forecast.rb, line 122 def predict(n=nil) if n.nil? forecast(@model_parameters).first else (1..n).map {|i| forecast(@model_parameters, i).first } end end
Private Instance Methods
calculate_one_step_ahead_forecasts()
click to toggle source
# File lib/tealeaves/exponential_smoothing_forecast.rb, line 140 def calculate_one_step_ahead_forecasts forecasts = [nil] * @seasonality_strategy.start_index parameters = initial_parameters (@seasonality_strategy.start_index...@time_series.size).each do |i| forecast, parameters = forecast(parameters) forecasts << forecast end parameters[:index] -= 1 @model_parameters = parameters @one_step_ahead_forecasts = forecasts end
forecast(parameters, n=1)
click to toggle source
# File lib/tealeaves/exponential_smoothing_forecast.rb, line 152 def forecast(parameters, n=1) new_params = {} new_params[:level] = new_level(parameters) new_params[:trend] = new_trend(parameters, new_params[:level]) new_params[:seasonality] = new_seasonality(parameters, new_params[:level]) new_params[:index] = parameters[:index] + 1 pre_forecast = case @trend when :none parameters[:level] when :additive parameters[:level] + (n * parameters[:trend]) when :multiplicative parameters[:level] * (parameters[:trend] ** n) end forecast = @seasonality_strategy.apply(pre_forecast, parameters, n) [forecast, new_params] end
new_level(parameters)
click to toggle source
# File lib/tealeaves/exponential_smoothing_forecast.rb, line 172 def new_level(parameters) @alpha * p(parameters) + (1 - @alpha) * q(parameters) end
new_seasonality(parameters, new_level)
click to toggle source
# File lib/tealeaves/exponential_smoothing_forecast.rb, line 182 def new_seasonality(parameters, new_level) @seasonality_strategy.new_values(@time_series[parameters[:index]], parameters, new_level) end
new_trend(parameters, new_level)
click to toggle source
# File lib/tealeaves/exponential_smoothing_forecast.rb, line 176 def new_trend(parameters, new_level) unless @trend == :none @beta * r(parameters, new_level) + (1 - @beta) * parameters[:trend] end end
p(params)
click to toggle source
# File lib/tealeaves/exponential_smoothing_forecast.rb, line 188 def p(params) @seasonality_strategy.p(@time_series[params[:index]], params) end
q(params)
click to toggle source
# File lib/tealeaves/exponential_smoothing_forecast.rb, line 192 def q(params) case @trend when :none params[:level] when :additive params[:level] + params[:trend] when :multiplicative params[:level] * params[:trend] end end
r(params, new_level)
click to toggle source
# File lib/tealeaves/exponential_smoothing_forecast.rb, line 203 def r(params, new_level) case @trend when :additive new_level - params[:level] when :multiplicative new_level / params[:level] end end