三次指数平滑法(Holt-Winters)

三次指数平滑法

https://blog.csdn.net/qq_32628233/article/details/51595479
​​
参数选择
​α,ß,γ的值都位于[0,1]之间,可以多试验几次以达到最佳效果。
​s,t,p初始值的选取对于算法整体的影响不是特别大,通常的取值为s0=x0,t0=x1-x0,累加时p=0,累乘时p=1.

HoltWinters模型有三个可调参数,我们的目的就是训练出有效的α,β, γ。我们有两种方法,一种就是自己取值来试试,一种就是采用数值优化的思想,比如前面我们提到的最小二乘来最小化误差来求参数(注意不一定能全局收敛!)我们就采用最小二乘法(L-BFGS)

参考这个,实现计算对应的参数
https://blog.csdn.net/u010665216/article/details/78051192?locationNum=11&fps=1

一次指数平滑

一次指数平滑法是一种特殊的加权平均法,对本时刻观察值和本时刻预测值赋予不同的权重,求得下一时刻预测值的方法。这种方法既不需要存储全部历史数据,也不需要存储一组数据,从而可以大大减少数据存储问题。其通式为:
在这里插入图片描述
Ft+1为 t+1时刻的预测值,xt 为t 时刻实际值,α为权值(也称为平滑系数),α越小,参考之前的时间点越多,α越大,参考之前的时间点越少。

根据通式,迭代计算得到:
在这里插入图片描述
由于(1−α)的取值在0到1之间,所以(1−α)n的值会越来越小,即离t+1时刻越久远的观测值,对t+1时刻的预测值的影响越小。

对离预测时刻较近的观察值赋予较大的权数,对离预测值较远的观察值赋予较小的权数,权数由近到远按指数规律递减,所以叫做指数平滑法

新预测值是根据预测误差对原预测值进行修正得到的。α的大小表明了修正的幅度。α值愈大,修正的幅度愈大,α值愈小,修正的幅度愈小。 因此,α值既代表了预测模型对时间序列数据变化的反应速度,又体现了预测模型修匀误差的能力。

在实际应用中,α值是根据时间序列的变化特性来选取的。 若时间序列的波动不大,比较平稳,则α应取小一些,如0.1 ~ 0.3 ;若时间序列具有迅速且明显的变动倾向, 则α应取大一些,如0.6 ~ 0.9。实质上,α是一个经验数据,通过多个值进行试算比较而定,哪个α值引起的预测误差小,就采用哪个。

一次指数平滑法比较简单,但也有问题。问题之一便是力图找到最佳的α值,以使均方差最小,这需要通过反复试验确定。预测的时间序列为一条直线,不能反映时间序列的趋势和季节性。

也可以这么计算:三次指数平滑法(Holt-Winters)_第1张图片

二次指数平滑

三次指数平滑法(Holt-Winters)_第2张图片

三次指数平滑

三次指数平滑法(Holt-Winters)_第3张图片
三次指数平滑法(Holt-Winters)_第4张图片
python3代码,一次指数平滑:

S1_1 = []
        for m in range(0, len(info_data_id)):
            S1_1_empty = []
            x = 0
            for n in range(0, 3):
                x = x + int(info_data_sales[m][n])
            x = x / 3
            S1_1_empty.append(x)
            S1_1.append(S1_1_empty)
        # print(S1_1)

        a = []  ##这是用来存放阿尔法的数组
        info_MSE = []  ##计算均方误差来得到最优的a(阿尔法)
        for i in range(0, len(info_data_sales)):
            v = input('请输入第' + str(i + 1) + '组数据的a:')
            a.append(v)

        for i in range(0, len(info_data_sales)):
            MSE = 0
            for j in range(0, len(info_data_sales[i])):
                S1_1[i].append(
                    float(a[i]) * int(info_data_sales[i][j]) + (1 - float(a[i])) * int(S1_1[i][j]))  ##计算预估值
                MSE = (int(S1_1[i][j]) - int(info_data_sales[i][j])) ** 2 + MSE
                # print(info_data_sales[i][j], S1_1[i][j])
            MSE = (MSE ** (1 / 2)) / int(len(info_data_sales[i]))  ##得到均方误差
            info_MSE.append(MSE)
        # print(info_MSE)
        # print(S1_1)
        for i in range(0, len(S1_1)):
            print('第' + str(i + 1) + '组的一次平滑预估值为:' + str(S1_1[i][len(S1_1[i]) - 1]) + ';均方误差为:' + str(info_MSE[i]))

二次指数平滑代码:

S2_1 = []
        S2_2 = []
        for m in range(0, len(info_data_id)):
            S2_1_empty = []
            x = 0
            for n in range(0, 3):
                x = x + float(info_data_sales[m][n])
            x = x / 3
            S2_1_empty.append(x)
            S2_1.append(S2_1_empty)
            S2_2.append(S2_1_empty)
        # print(S2_2)
        a = []  ##这是用来存放阿尔法的数组
        info_MSE = []  ##计算均方误差来得到最优的a(阿尔法)
        for i in range(0, len(info_data_sales)):
            v = float(input('请输入第' + str(i + 1) + '组数据的a:'))
            a.append(v)

        ##下面是计算一次指数平滑的值
        S2_1_new1 = []
        for i in range(0, len(info_data_sales)):
            S2_1_new = [[]] * len(info_data_id)
            for j in range(0, len(info_data_sales[i])):
                if j == 0:
                    S2_1_new[i].append(
                        float(a[i]) * float(info_data_sales[i][j]) + (1 - float(a[i])) * float(S2_1[i][j]))
                else:
                    S2_1_new[i].append(float(a[i]) * float(info_data_sales[i][j]) + (1 - float(a[i])) * float(
                        S2_1_new[i][j - 1]))  ##计算一次指数的值
            S2_1_new1.append(S2_1_new[i])
        # print(S2_1_new1)
        # print(len(S2_1_new1[i]))

        ##下面是计算二次指数平滑的值
        S2_2_new1 = []
        info_MSE = []  ##计算均方误差来得到最优的a(阿尔法)
        for i in range(0, len(info_data_sales)):
            S2_2_new = [[]] * len(info_data_id)
            MSE = 0
            for j in range(0, len(info_data_sales[i])):
                if j == 0:
                    S2_2_new[i].append(float(a[i]) * float(S2_1_new1[i][j]) + (1 - float(a[i])) * float(S2_2[i][j]))
                else:
                    S2_2_new[i].append(float(a[i]) * float(S2_1_new1[i][j]) + (1 - float(a[i])) * float(
                        S2_2_new[i][j - 1]))  ##计算二次指数的值
                MSE = (int(S2_2_new[i][j]) - int(info_data_sales[i][j])) ** 2 + MSE
            MSE = (MSE ** (1 / 2)) / int(len(info_data_sales[i]))
            info_MSE.append(MSE)
            S2_2_new1.append(S2_2_new[i])
        # print(S2_2_new1)
        # print(len(S2_2_new1[i]))

        ##下面是计算At、Bt以及每个预估值Xt的值,直接计算预估值,不一一列举Xt的值了
        u = input('你要预估多少期?')
        Xt = []
        for i in range(0, len(info_data_sales)):
            At = (float(S2_1_new1[i][len(S2_1_new1[i]) - 1]) * 2 - float(S2_2_new1[i][len(S2_2_new1[i]) - 1]))
            Bt = (float(a[i]) / (1 - float(a[i])) * (
            float(S2_1_new1[i][len(S2_1_new1[i]) - 1]) - float(S2_2_new1[i][len(S2_2_new1[i]) - 1])))
            Xt.append(At + Bt * int(u))
            print('第' + str(i + 1) + '组的二次平滑预估值为:' + str(Xt[i]) + ';均方误差为:' + str(info_MSE[i]))

三次指数平滑代码:

S3_1 = []
        S3_2 = []
        S3_3 = []
        for m in range(0, len(info_data_id)):
            S3_1_empty = []
            x = 0
            for n in range(0, 3):
                x = x + float(info_data_sales[m][n])
            x = x / 3
            S3_1_empty.append(x)
            S3_1.append(S3_1_empty)
            S3_2.append(S3_1_empty)
            S3_3.append(S3_1_empty)
        # print(S3_1)
        a = []  ##这是用来存放阿尔法的数组
        info_MSE = []  ##计算均方误差来得到最优的a(阿尔法)
        for i in range(0, len(info_data_sales)):
            v = float(input('请输入第' + str(i + 1) + '组数据的a:'))
            a.append(v)

        ##下面是计算一次指数平滑的值
        S3_1_new1 = []
        for i in range(0, len(info_data_sales)):
            S3_1_new = [[]] * len(info_data_id)
            for j in range(0, len(info_data_sales[i])):
                if j == 0:
                    S3_1_new[i].append(
                        float(a[i]) * float(info_data_sales[i][j]) + (1 - float(a[i])) * float(S3_1[i][j]))
                else:
                    S3_1_new[i].append(float(a[i]) * float(info_data_sales[i][j]) + (1 - float(a[i])) * float(
                        S3_1_new[i][j - 1]))  ##计算一次指数的值
            S3_1_new1.append(S3_1_new[i])

        ##下面是计算二次指数平滑的值
        S3_2_new1 = []
        info_MSE = []  ##计算均方误差来得到最优的a(阿尔法)
        for i in range(0, len(info_data_sales)):
            S3_2_new = [[]] * len(info_data_id)
            for j in range(0, len(info_data_sales[i])):
                if j == 0:
                    S3_2_new[i].append(float(a[i]) * float(S3_1_new1[i][j]) + (1 - float(a[i])) * float(S3_2[i][j]))
                else:
                    S3_2_new[i].append(float(a[i]) * float(S3_1_new1[i][j]) + (1 - float(a[i])) * float(
                        S3_2_new[i][j - 1]))  ##计算二次指数的值
            S3_2_new1.append(S3_2_new[i])

        ##下面是计算二次指数平滑的值
        S3_3_new1 = []
        info_MSE = []  ##计算均方误差来得到最优的a(阿尔法)
        for i in range(0, len(info_data_sales)):
            S3_3_new = [[]] * len(info_data_id)
            MSE = 0
            for j in range(0, len(info_data_sales[i])):
                if j == 0:
                    S3_3_new[i].append(float(a[i]) * float(S3_2_new1[i][j]) + (1 - float(a[i])) * float(S3_3[i][j]))
                else:
                    S3_3_new[i].append(float(a[i]) * float(S3_2_new1[i][j]) + (1 - float(a[i])) * float(
                        S3_3_new[i][j - 1]))  ##计算三次指数的值
                MSE = (int(S3_3_new[i][j]) - int(info_data_sales[i][j])) ** 2 + MSE
            MSE = (MSE ** (1 / 2)) / int(len(info_data_sales[i]))
            info_MSE.append(MSE)
            S3_3_new1.append(S3_3_new[i])
            # print(S3_3_new1)

        ##下面是计算At、Bt、Ct以及每个预估值Xt的值,直接计算预估值,不一一列举Xt的值了
        u = input('你要预估多少期?')
        Xt = []
        for i in range(0, len(info_data_sales)):
            At = (
            float(S3_1_new1[i][len(S3_1_new1[i]) - 1]) * 3 - float(S3_2_new1[i][len(S3_2_new1[i]) - 1]) * 3 + float(
                S3_3_new1[i][len(S3_3_new1[i]) - 1]))
            Bt = ((float(a[i]) / (2 * ((1 - float(a[i])) ** 2))) * ((6 - 5 * float(a[i])) * (
            float(S3_1_new1[i][len(S3_1_new1[i]) - 1]) - 2 * (5 - 4 * float(a[i])) * float(
                S3_2_new1[i][len(S3_2_new1[i]) - 1]) + (4 - 3 * float(a[i])) * float(
                S3_3_new1[i][len(S3_3_new1[i]) - 1]))))
            Ct = (((float(a[i])) ** 2) / (2 * ((1 - float(a[i])) ** 2))) * (
            float(S3_1_new1[i][len(S3_1_new1[i]) - 1]) - float(S3_2_new1[i][len(S3_2_new1[i]) - 1])*2 + float(
                S3_3_new1[i][len(S3_3_new1[i]) - 1]))
            Xt.append(At + Bt * int(u) + Ct * (int(u) ** 2))
            print('第' + str(i + 1) + '组的三次平滑预估值为:' + str(Xt[i]) + ';均方误差为:' + str(info_MSE[i]))

完整代码:

from openpyxl import load_workbook
import xlsxwriter

if __name__ == '__main__':
    judge = input('请选择使用几次指数平滑:一次请按1;二次请按2;三次请按3:')
    ##这里是打开excel将数据储存到数组里面
    wb = load_workbook(filename=r'C:\Users\Administrator\Desktop\data.xlsx')  ##读取路径
    ws = wb.get_sheet_by_name("Sheet1")  ##读取名字为Sheet1的sheet表
    info_data_id = []
    info_data_sales = []

    for row_A in range(1, 3):  ## 遍历第1行到2行
        id = ws.cell(row=row_A, column=1).value  ## 遍历第1行到2行,第1列
        info_data_id.append(id)
    for row_num_BtoU in range(1, len(info_data_id) + 1):  ## 遍历第1行到2行
        row_empty = []  ##建立一个空数组作为临时储存地,每次换行就被清空
        for i in range(2, 20):  ## 遍历第1行到2行,第1到19列
            data = ws.cell(row=row_num_BtoU, column=i).value
            if data == None:
                pass
            else:
                row_empty.append(data)  ##将单元格信息储存进去
        info_data_sales.append(row_empty)  ##row_empty每次储存完1到19列后压给info_data_sales,然后row_empty被清空
    # print(info_data_id)
    # print(info_data_sales)
    if judge == '1':
        ##############################下面是计算St(1)下面写为S1_t_######################################
        print('你选择了一次指数平滑预测')
        ##一次指数平滑的初值为S1_1,用S1_1来储存每一组数据的一次平滑的数值
        S1_1 = []
        for m in range(0, len(info_data_id)):
            S1_1_empty = []
            x = 0
            for n in range(0, 3):
                x = x + int(info_data_sales[m][n])
            x = x / 3
            S1_1_empty.append(x)
            S1_1.append(S1_1_empty)
        # print(S1_1)

        a = []  ##这是用来存放阿尔法的数组
        info_MSE = []  ##计算均方误差来得到最优的a(阿尔法)
        for i in range(0, len(info_data_sales)):
            v = input('请输入第' + str(i + 1) + '组数据的a:')
            a.append(v)

        for i in range(0, len(info_data_sales)):
            MSE = 0
            for j in range(0, len(info_data_sales[i])):
                S1_1[i].append(
                    float(a[i]) * int(info_data_sales[i][j]) + (1 - float(a[i])) * int(S1_1[i][j]))  ##计算预估值
                MSE = (int(S1_1[i][j]) - int(info_data_sales[i][j])) ** 2 + MSE
                # print(info_data_sales[i][j], S1_1[i][j])
            MSE = (MSE ** (1 / 2)) / int(len(info_data_sales[i]))  ##得到均方误差
            info_MSE.append(MSE)
        # print(info_MSE)
        # print(S1_1)
        for i in range(0, len(S1_1)):
            print('第' + str(i + 1) + '组的一次平滑预估值为:' + str(S1_1[i][len(S1_1[i]) - 1]) + ';均方误差为:' + str(info_MSE[i]))

    if judge == '2':
        ##############################下面是计算St(2)下面写为S2_t_######################################
        print('你选择了二次指数平滑预测')

        ##二次指数平滑的初值为S2_1,用S2_1_new来储存每一组数据的一次平滑的数值
        S2_1 = []
        S2_2 = []
        for m in range(0, len(info_data_id)):
            S2_1_empty = []
            x = 0
            for n in range(0, 3):
                x = x + float(info_data_sales[m][n])
            x = x / 3
            S2_1_empty.append(x)
            S2_1.append(S2_1_empty)
            S2_2.append(S2_1_empty)
        # print(S2_2)
        a = []  ##这是用来存放阿尔法的数组
        info_MSE = []  ##计算均方误差来得到最优的a(阿尔法)
        for i in range(0, len(info_data_sales)):
            v = float(input('请输入第' + str(i + 1) + '组数据的a:'))
            a.append(v)

        ##下面是计算一次指数平滑的值
        S2_1_new1 = []
        for i in range(0, len(info_data_sales)):
            S2_1_new = [[]] * len(info_data_id)
            for j in range(0, len(info_data_sales[i])):
                if j == 0:
                    S2_1_new[i].append(
                        float(a[i]) * float(info_data_sales[i][j]) + (1 - float(a[i])) * float(S2_1[i][j]))
                else:
                    S2_1_new[i].append(float(a[i]) * float(info_data_sales[i][j]) + (1 - float(a[i])) * float(
                        S2_1_new[i][j - 1]))  ##计算一次指数的值
            S2_1_new1.append(S2_1_new[i])
        # print(S2_1_new1)
        # print(len(S2_1_new1[i]))

        ##下面是计算二次指数平滑的值
        S2_2_new1 = []
        info_MSE = []  ##计算均方误差来得到最优的a(阿尔法)
        for i in range(0, len(info_data_sales)):
            S2_2_new = [[]] * len(info_data_id)
            MSE = 0
            for j in range(0, len(info_data_sales[i])):
                if j == 0:
                    S2_2_new[i].append(float(a[i]) * float(S2_1_new1[i][j]) + (1 - float(a[i])) * float(S2_2[i][j]))
                else:
                    S2_2_new[i].append(float(a[i]) * float(S2_1_new1[i][j]) + (1 - float(a[i])) * float(
                        S2_2_new[i][j - 1]))  ##计算二次指数的值
                MSE = (int(S2_2_new[i][j]) - int(info_data_sales[i][j])) ** 2 + MSE
            MSE = (MSE ** (1 / 2)) / int(len(info_data_sales[i]))
            info_MSE.append(MSE)
            S2_2_new1.append(S2_2_new[i])
        # print(S2_2_new1)
        # print(len(S2_2_new1[i]))

        ##下面是计算At、Bt以及每个预估值Xt的值,直接计算预估值,不一一列举Xt的值了
        u = input('你要预估多少期?')
        Xt = []
        for i in range(0, len(info_data_sales)):
            At = (float(S2_1_new1[i][len(S2_1_new1[i]) - 1]) * 2 - float(S2_2_new1[i][len(S2_2_new1[i]) - 1]))
            Bt = (float(a[i]) / (1 - float(a[i])) * (
            float(S2_1_new1[i][len(S2_1_new1[i]) - 1]) - float(S2_2_new1[i][len(S2_2_new1[i]) - 1])))
            Xt.append(At + Bt * int(u))
            print('第' + str(i + 1) + '组的二次平滑预估值为:' + str(Xt[i]) + ';均方误差为:' + str(info_MSE[i]))

    if judge == '3':
        ##############################下面是计算St(3)下面写为S3_t_######################################
        print('你选择了三次指数平滑预测')
        S3_1 = []
        S3_2 = []
        S3_3 = []
        for m in range(0, len(info_data_id)):
            S3_1_empty = []
            x = 0
            for n in range(0, 3):
                x = x + float(info_data_sales[m][n])
            x = x / 3
            S3_1_empty.append(x)
            S3_1.append(S3_1_empty)
            S3_2.append(S3_1_empty)
            S3_3.append(S3_1_empty)
        # print(S3_1)
        a = []  ##这是用来存放阿尔法的数组
        info_MSE = []  ##计算均方误差来得到最优的a(阿尔法)
        for i in range(0, len(info_data_sales)):
            v = float(input('请输入第' + str(i + 1) + '组数据的a:'))
            a.append(v)

        ##下面是计算一次指数平滑的值
        S3_1_new1 = []
        for i in range(0, len(info_data_sales)):
            S3_1_new = [[]] * len(info_data_id)
            for j in range(0, len(info_data_sales[i])):
                if j == 0:
                    S3_1_new[i].append(
                        float(a[i]) * float(info_data_sales[i][j]) + (1 - float(a[i])) * float(S3_1[i][j]))
                else:
                    S3_1_new[i].append(float(a[i]) * float(info_data_sales[i][j]) + (1 - float(a[i])) * float(
                        S3_1_new[i][j - 1]))  ##计算一次指数的值
            S3_1_new1.append(S3_1_new[i])

        ##下面是计算二次指数平滑的值
        S3_2_new1 = []
        info_MSE = []  ##计算均方误差来得到最优的a(阿尔法)
        for i in range(0, len(info_data_sales)):
            S3_2_new = [[]] * len(info_data_id)
            for j in range(0, len(info_data_sales[i])):
                if j == 0:
                    S3_2_new[i].append(float(a[i]) * float(S3_1_new1[i][j]) + (1 - float(a[i])) * float(S3_2[i][j]))
                else:
                    S3_2_new[i].append(float(a[i]) * float(S3_1_new1[i][j]) + (1 - float(a[i])) * float(
                        S3_2_new[i][j - 1]))  ##计算二次指数的值
            S3_2_new1.append(S3_2_new[i])

        ##下面是计算二次指数平滑的值
        S3_3_new1 = []
        info_MSE = []  ##计算均方误差来得到最优的a(阿尔法)
        for i in range(0, len(info_data_sales)):
            S3_3_new = [[]] * len(info_data_id)
            MSE = 0
            for j in range(0, len(info_data_sales[i])):
                if j == 0:
                    S3_3_new[i].append(float(a[i]) * float(S3_2_new1[i][j]) + (1 - float(a[i])) * float(S3_3[i][j]))
                else:
                    S3_3_new[i].append(float(a[i]) * float(S3_2_new1[i][j]) + (1 - float(a[i])) * float(
                        S3_3_new[i][j - 1]))  ##计算三次指数的值
                MSE = (int(S3_3_new[i][j]) - int(info_data_sales[i][j])) ** 2 + MSE
            MSE = (MSE ** (1 / 2)) / int(len(info_data_sales[i]))
            info_MSE.append(MSE)
            S3_3_new1.append(S3_3_new[i])
            # print(S3_3_new1)

        ##下面是计算At、Bt、Ct以及每个预估值Xt的值,直接计算预估值,不一一列举Xt的值了
        u = input('你要预估多少期?')
        Xt = []
        for i in range(0, len(info_data_sales)):
            At = (
            float(S3_1_new1[i][len(S3_1_new1[i]) - 1]) * 3 - float(S3_2_new1[i][len(S3_2_new1[i]) - 1]) * 3 + float(
                S3_3_new1[i][len(S3_3_new1[i]) - 1]))
            Bt = ((float(a[i]) / (2 * ((1 - float(a[i])) ** 2))) * ((6 - 5 * float(a[i])) * (
            float(S3_1_new1[i][len(S3_1_new1[i]) - 1]) - 2 * (5 - 4 * float(a[i])) * float(
                S3_2_new1[i][len(S3_2_new1[i]) - 1]) + (4 - 3 * float(a[i])) * float(
                S3_3_new1[i][len(S3_3_new1[i]) - 1]))))
            Ct = (((float(a[i])) ** 2) / (2 * ((1 - float(a[i])) ** 2))) * (
            float(S3_1_new1[i][len(S3_1_new1[i]) - 1]) - float(S3_2_new1[i][len(S3_2_new1[i]) - 1])*2 + float(
                S3_3_new1[i][len(S3_3_new1[i]) - 1]))
            Xt.append(At + Bt * int(u) + Ct * (int(u) ** 2))
            print('第' + str(i + 1) + '组的三次平滑预估值为:' + str(Xt[i]) + ';均方误差为:' + str(info_MSE[i]))

参考:
https://blog.csdn.net/qq_32628233/article/details/51595479
https://www.cnblogs.com/TTyb/p/5716125.html
https://blog.csdn.net/my_learning_road/article/details/81191188

你可能感兴趣的:(三次指数平滑法(Holt-Winters))