Holt-Winters模型
a基本原理:
该方法有点类似于MA(移动平均)的思路,是对MA的优化。主要因为MA的参数数量过多时,计算时间慢,且计算复杂。Holt-Winters利用三次指数平滑法,将历史时序数据输入三个递推序列,再由三个序列的递推值来推算出预测数据的值。该模型的目的是训练出三次指数平滑法三个因数的最有效的取值,之后就可以继续预测了。
该方法可以有效的预测有线性趋势和周期波动的非平稳序列。
b模型原理:
简单指数平滑:
二次指数平滑:
三次指数平滑:
在二次指数平滑的基础上加入了季节性(周期性)特征指数平滑队列。
季节性被定义为时间序列数据的趋势,它表现出每一个周期重复自身的行为,就像任何周期函数一样。
在自然界中有两种不同类型的三次指数平滑,它们是“累加性”三次指数平滑和“累乘性”三次指数平滑。
c算法入口:
scipy.optimize.fmin_l_bfgs_b(func,x0,args=(),bounds=None, *args)
fmin_l_bfgs_b函数是用来进行L-BFGS优化的,利用最小二乘法来优化参数
func为原函数
x0为模型的初始参数
args为传入func的参数
bounds为模型参数的取值范围
d实例参考:
'''
Holt-Winters模型模板
使用最小二乘法来找出最优alpha,beta,Gamma
'''
from sys import exit
from math import sqrt
from numpy import array
from scipy.optimize import fmin_l_bfgs_b
# 均方根误差函数(最小二乘法)
def RMSE(params, *args): # args=[X,type,(m)]
X = args[0]
type = args[1]
if type == 'linear': # 若趋势是线性的(非周期)
try: # 设定参数初始化值和S0、B0、F0值
alpha, beta = params
s = [X[0]]
b = [X[1] - X[0]]
f = [s[0] + b[0]]
# 利用历史数据递推迭代
for i in range(len(X)):
s.append(alpha * X[i] + (1 - alpha) * (s[i] + b[i]))
b.append(beta * (s[i + 1] - s[i]) + (1 - beta) * b[i])
f.append(s[i + 1] + b[i + 1])
except: # 参数有误
print('params error')
else: # 趋势非线性(周期)
try: # 设定参数初始化值和S0、B0值,m为需要预测的时间长度
alpha, beta, gamma = params
m = args[2]
s = [sum(X[0:m]) / float(m)]
b = [(sum(X[m:2 * m]) - sum(X[0:m])) / m ** 2]
if type == 'additive': # 加法性
# 设定c0、F0值
c = [X[i] - s[0] for i in range(m)]
f = [s[0] + b[0] + c[0]]
# 利用历史数据递推迭代
for i in range(len(X)):
s.append(alpha * (X[i] - s[i]) + (1 - alpha) * (s[i] + b[i]))
b.append(beta * (s[i + 1] - s[i]) + (1 - beta) * b[i])
c.append(gamma * (X[i] - s[i] - b[i]) + (1 - gamma) * c[i])
f.append(c[i + 1] + b[i + 1] + s[i + 1])
elif type == 'multiplicative': # 乘法性
# 设定c0、F0值
c = [X[i] / s[0] for i in range(m)]
f = [(s[0] + b[0]) * c[0]]
# 利用历史数据递推迭代
for i in range(len(X)):
s.append(alpha * (X[i] / c[i]) + (1 - alpha) * (s[i] + b[i]))
b.append(beta * (s[i + 1] - s[i]) + (1 - beta) * b[i])
s.append(gamma * (X[i] / (s[i] + b[i])) + (1 - gamma) * c[i])
f.append((c[i + 1] + b[i + 1]) * s[i + 1])
else: # type类型有误
exit('Type must be either linear, additive or multiplicative')
except: # 参数或args有误
print('params or args error')
# 计算均方根误差
rmse = sqrt(sum([(m - n) ** 2 for m, n in zip(X, f[:-1])]) / len(X))
return rmse
def linear(x, fc, alpha=None, beta=None): # 趋势线性,fc为要预测数据的数量
X = x[:]
if (alpha == None or beta == None):
initial_values = array([0.3, 0.1]) # 如果alpha或beta存在None,那重新一个随机值
boundaries = [(0, 1), (0, 1)] # alpha和beta的取值范围
type = 'linear'
parameters = fmin_l_bfgs_b(RMSE, x0=initial_values, args=(X, type), bounds=boundaries, approx_grad=True)
alpha, beta = parameters[0] # 获得最优的alpha和beta
# 初始化s,b,f队列,准备预测[len(X)+1,len(X)+fc]这一段数据
s = [X[0]]
b = [X[1] - X[0]]
f = [s[0] + b[0]]
for i in range(len(X) + fc):
if i == len(X): # 如果历史数据已用完,则添加最近的预测数据的x
X.append(s[-1] + b[-1])
s.append(alpha * X[i] + (1 - alpha) * (s[i] + b[i]))
b.append(beta * (s[i + 1] - s[i]) + (1 - beta) * b[i])
f.append(s[i + 1] + b[i + 1])
rmse = sqrt(sum([(m - n) ** 2 for m, n in zip(X[:-fc], X[:-fc - 1])]) / len(X[:-fc]))
return X[-fc:], alpha, beta, rmse # 输出预测值,alpha,beta,最小均方根误差
def additive(x, m, fc, alpha=None, beta=None, gamma=None): # 累加性
X = x[:]
if (alpha == None or beta == None or gamma == None):
initial_values = array([0.3, 0.1, 0.1]) # 如果alpha或beta存在None,那重新一个随机值
boundaries = [(0, 1), (0, 1), (0, 1)] # alpha和beta、gamma的取值范围
type = 'additive'
parameters = fmin_l_bfgs_b(RMSE, x0=initial_values, args=(X, type, m), bounds=boundaries, approx_grad=True)
alpha, beta, gamma = parameters[0] # 获得最优的alpha和beta、gamma
# 初始化s,b,c,f队列,准备预测[len(X)+1,len(X)+fc]这一段数据
s = [sum(X[0:m]) / float(m)]
b = [(sum(X[m:2 * m]) - sum(X[0:m])) / m ** 2]
c = [X[i] - s[0] for i in range(m)]
f = [s[0] + b[0] + c[0]]
for i in range(len(X) + fc):
if i == len(X): # 如果历史数据已用完,则添加最近的预测数据的x
X.append(s[-1] + b[-1] + c[-m])
s.append(alpha * (X[i] - c[i]) + (1 - alpha) * (s[i] + b[i]))
b.append(beta * (s[i + 1] - s[i]) + (1 - beta) * b[i])
c.append(gamma * (X[i] - s[i] - b[i]) + (1 - gamma) * c[i])
f.append(c[i + 1] + b[i + 1] + s[i + 1])
rmse = sqrt(sum([(m - n) ** 2 for m, n in zip(X[:-fc], f[:-fc - 1])]) / len(X[:-fc]))
return X[-fc:], alpha, beta, gamma, rmse # 输出预测值,alpha,beta,gamma最小均方根误差
def multiplicative(x, m, fc, alpha=None, beta=None, gamma=None): # 累乘性
X = x[:]
if (alpha == None or beta == None or gamma == None):
initial_values = array([0.0, 1.0, 0.0]) # 如果alpha或beta存在None,那重新一个随机值
boundaries = [(0, 1), (0, 1), (0, 1)] # alpha和beta、gamma的取值范围
type = 'multiplicative'
parameters = fmin_l_bfgs_b(RMSE, x0=initial_values, args=(X, type, m), bounds=boundaries, approx_grad=True)
alpha, beta, gamma = parameters[0] # 获得最优的alpha和beta、gamma
# 初始化s,b,c,f队列,准备预测[len(X)+1,len(X)+fc]这一段数据
s = [sum(X[0:m]) / float(m)]
b = [(sum(X[m:2 * m]) - sum(X[0:m])) / m ** 2]
c = [X[i] / s[0] for i in range(m)]
f = [(s[0] + b[0]) * c[0]]
for i in range(len(X) + fc):
if i == len(X): # 如果历史数据已用完,则添加最近的预测数据的x
X.append((s[-1] + b[-1]) * c[-m])
s.append(alpha * (X[i] / c[i]) + (1 - alpha) * (s[i] + b[i]))
b.append(beta * (s[i + 1] - s[i]) + (1 - beta) * b[i])
c.append(gamma * (X[i] / (s[i] + b[i])) + (1 - gamma) * c[i])
f.append((s[i + 1] + b[i + 1]) * c[i + 1])
rmse = sqrt(sum([(m - n) ** 2 for m, n in zip(X[:-fc], f[:-fc - 1])]) / len(X[:-fc]))
return X[-fc:], alpha, beta, gamma, rmse # 输出预测值,alpha,beta,gamma最小均方根误差
e参考文献:
Holt-Winters模型原理分析及代码实现(python) https://blog.csdn.net/u010665216/article/details/78051192
Holt-Winters与时间序列预测 https://www.jianshu.com/p/fcd20a048adb
时间序列分析之指数平滑法(holt-winters及代码)https://zhuanlan.zhihu.com/p/43353740