趋势预测方法(五)Holt-Winters模型_时序递推预测

本文详细介绍了Holt-Winters模型,这是一种适用于有线性趋势和周期性变化的时间序列预测方法。通过三次指数平滑,模型能够处理季节性数据。文章提供了Python代码示例,包括线性、累加性和累乘性三种情况,并利用最小二乘法优化参数,以求得最佳预测效果。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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

评论 12
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值