一次、二次、三次指數平滑計算思想及代碼


一般常用到的指數平滑法為一次指數平滑、二次指數平滑和三次指數平滑,高次指數平滑一般比較難見到,因此本文着重介紹了一次、二次和三次指數平滑的特點與不同。

一次指數平滑一般應用於直線型數據,且一次指數平滑具有滯后性,可以說明有明顯的時間性、季節性。

二次指數平滑一般也應用於直線型,但是效果會比一次指數平滑好很多,也就相當於加強版的一次指數平滑。

三次指數平滑可以應用於拋物線型的數據,因為數據在二次平滑過后還是具有斜率,那么可以繼續使用三次指數平滑。

初值:不管什么指數平滑都會有個初值,假如數據大於20項,那么初值就可以認定為第一個數據,或者利用下列公式計算也行;假如數據小於20項,則初始值為:

低於20項一般取3,大於20的看着取就行了。

一次指數平滑:

一次指數平滑需要滯后一期,給定平滑系數,那么一次指數平滑的計算公式為:

預測第期的數值則是上一期的實際值與預測值的加權平均,預測公式為:

 

二次指數平滑:

給定平滑系數,那么二次指數平滑的計算公式為:

預測未來期的值的計算公式為:

其中:

三次指數平滑:

 給定平滑系數,那么三次指數平滑的計算公式為:

 

預測未來期的值的計算公式為:

 

其中:

下面舉例說明,數據如下:

253993

275396.2

315229.5

356949.6

400158.2

442431.7

495102.9

570164.8

640993.1

704250.4

767455.4

781807.8

776332.3

794161.7

834177.7

931651.5

1028390

1114914

133

88

150

123

404

107

674

403

243

257

900

1043

1156

895

1200

1038

1024

1283

引入均方誤差概念來判斷平滑系數是否准確:

要使最小則構成了一個關於的函數,由此可以得到最優的平滑系數,這里可以引入線性規划的思想來求得最優解

但是:

python沒有線性規划的包,所以就沒有細致的代碼寫出來了,不過經過手動計算嘗試這樣子是可行的

 

python3下編程,一次指數平滑代碼為:

 1         S1_1 = []
 2         for m in range(0, len(info_data_id)):
 3             S1_1_empty = []
 4             x = 0
 5             for n in range(0, 3):
 6                 x = x + int(info_data_sales[m][n])
 7             x = x / 3
 8             S1_1_empty.append(x)
 9             S1_1.append(S1_1_empty)
10         # print(S1_1)
11 
12         a = []  ##這是用來存放阿爾法的數組
13         info_MSE = []  ##計算均方誤差來得到最優的a(阿爾法)
14         for i in range(0, len(info_data_sales)):
15             v = input('請輸入第' + str(i + 1) + '組數據的a:')
16             a.append(v)
17 
18         for i in range(0, len(info_data_sales)):
19             MSE = 0
20             for j in range(0, len(info_data_sales[i])):
21                 S1_1[i].append(
22                     float(a[i]) * int(info_data_sales[i][j]) + (1 - float(a[i])) * int(S1_1[i][j]))  ##計算預估值
23                 MSE = (int(S1_1[i][j]) - int(info_data_sales[i][j])) ** 2 + MSE
24                 # print(info_data_sales[i][j], S1_1[i][j])
25             MSE = (MSE ** (1 / 2)) / int(len(info_data_sales[i]))  ##得到均方誤差
26             info_MSE.append(MSE)
27         # print(info_MSE)
28         # print(S1_1)
29         for i in range(0, len(S1_1)):
30             print('' + str(i + 1) + '組的一次平滑預估值為:' + str(S1_1[i][len(S1_1[i]) - 1]) + ';均方誤差為:' + str(info_MSE[i]))    

二次指數平滑代碼為:

 1         S2_1 = []
 2         S2_2 = []
 3         for m in range(0, len(info_data_id)):
 4             S2_1_empty = []
 5             x = 0
 6             for n in range(0, 3):
 7                 x = x + float(info_data_sales[m][n])
 8             x = x / 3
 9             S2_1_empty.append(x)
10             S2_1.append(S2_1_empty)
11             S2_2.append(S2_1_empty)
12         # print(S2_2)
13         a = []  ##這是用來存放阿爾法的數組
14         info_MSE = []  ##計算均方誤差來得到最優的a(阿爾法)
15         for i in range(0, len(info_data_sales)):
16             v = float(input('請輸入第' + str(i + 1) + '組數據的a:'))
17             a.append(v)
18 
19         ##下面是計算一次指數平滑的值
20         S2_1_new1 = []
21         for i in range(0, len(info_data_sales)):
22             S2_1_new = [[]] * len(info_data_id)
23             for j in range(0, len(info_data_sales[i])):
24                 if j == 0:
25                     S2_1_new[i].append(
26                         float(a[i]) * float(info_data_sales[i][j]) + (1 - float(a[i])) * float(S2_1[i][j]))
27                 else:
28                     S2_1_new[i].append(float(a[i]) * float(info_data_sales[i][j]) + (1 - float(a[i])) * float(
29                         S2_1_new[i][j - 1]))  ##計算一次指數的值
30             S2_1_new1.append(S2_1_new[i])
31         # print(S2_1_new1)
32         # print(len(S2_1_new1[i]))
33 
34         ##下面是計算二次指數平滑的值
35         S2_2_new1 = []
36         info_MSE = []  ##計算均方誤差來得到最優的a(阿爾法)
37         for i in range(0, len(info_data_sales)):
38             S2_2_new = [[]] * len(info_data_id)
39             MSE = 0
40             for j in range(0, len(info_data_sales[i])):
41                 if j == 0:
42                     S2_2_new[i].append(float(a[i]) * float(S2_1_new1[i][j]) + (1 - float(a[i])) * float(S2_2[i][j]))
43                 else:
44                     S2_2_new[i].append(float(a[i]) * float(S2_1_new1[i][j]) + (1 - float(a[i])) * float(
45                         S2_2_new[i][j - 1]))  ##計算二次指數的值
46                 MSE = (int(S2_2_new[i][j]) - int(info_data_sales[i][j])) ** 2 + MSE
47             MSE = (MSE ** (1 / 2)) / int(len(info_data_sales[i]))
48             info_MSE.append(MSE)
49             S2_2_new1.append(S2_2_new[i])
50         # print(S2_2_new1)
51         # print(len(S2_2_new1[i]))
52 
53         ##下面是計算At、Bt以及每個預估值Xt的值,直接計算預估值,不一一列舉Xt的值了
54         u = input('你要預估多少期?')
55         Xt = []
56         for i in range(0, len(info_data_sales)):
57             At = (float(S2_1_new1[i][len(S2_1_new1[i]) - 1]) * 2 - float(S2_2_new1[i][len(S2_2_new1[i]) - 1]))
58             Bt = (float(a[i]) / (1 - float(a[i])) * (
59             float(S2_1_new1[i][len(S2_1_new1[i]) - 1]) - float(S2_2_new1[i][len(S2_2_new1[i]) - 1])))
60             Xt.append(At + Bt * int(u))
61             print('' + str(i + 1) + '組的二次平滑預估值為:' + str(Xt[i]) + ';均方誤差為:' + str(info_MSE[i]))

三次指數平滑代碼為:

 

 1         S3_1 = []
 2         S3_2 = []
 3         S3_3 = []
 4         for m in range(0, len(info_data_id)):
 5             S3_1_empty = []
 6             x = 0
 7             for n in range(0, 3):
 8                 x = x + float(info_data_sales[m][n])
 9             x = x / 3
10             S3_1_empty.append(x)
11             S3_1.append(S3_1_empty)
12             S3_2.append(S3_1_empty)
13             S3_3.append(S3_1_empty)
14         # print(S3_1)
15         a = []  ##這是用來存放阿爾法的數組
16         info_MSE = []  ##計算均方誤差來得到最優的a(阿爾法)
17         for i in range(0, len(info_data_sales)):
18             v = float(input('請輸入第' + str(i + 1) + '組數據的a:'))
19             a.append(v)
20 
21         ##下面是計算一次指數平滑的值
22         S3_1_new1 = []
23         for i in range(0, len(info_data_sales)):
24             S3_1_new = [[]] * len(info_data_id)
25             for j in range(0, len(info_data_sales[i])):
26                 if j == 0:
27                     S3_1_new[i].append(
28                         float(a[i]) * float(info_data_sales[i][j]) + (1 - float(a[i])) * float(S3_1[i][j]))
29                 else:
30                     S3_1_new[i].append(float(a[i]) * float(info_data_sales[i][j]) + (1 - float(a[i])) * float(
31                         S3_1_new[i][j - 1]))  ##計算一次指數的值
32             S3_1_new1.append(S3_1_new[i])
33 
34         ##下面是計算二次指數平滑的值
35         S3_2_new1 = []
36         info_MSE = []  ##計算均方誤差來得到最優的a(阿爾法)
37         for i in range(0, len(info_data_sales)):
38             S3_2_new = [[]] * len(info_data_id)
39             for j in range(0, len(info_data_sales[i])):
40                 if j == 0:
41                     S3_2_new[i].append(float(a[i]) * float(S3_1_new1[i][j]) + (1 - float(a[i])) * float(S3_2[i][j]))
42                 else:
43                     S3_2_new[i].append(float(a[i]) * float(S3_1_new1[i][j]) + (1 - float(a[i])) * float(
44                         S3_2_new[i][j - 1]))  ##計算二次指數的值
45             S3_2_new1.append(S3_2_new[i])
46 
47         ##下面是計算二次指數平滑的值
48         S3_3_new1 = []
49         info_MSE = []  ##計算均方誤差來得到最優的a(阿爾法)
50         for i in range(0, len(info_data_sales)):
51             S3_3_new = [[]] * len(info_data_id)
52             MSE = 0
53             for j in range(0, len(info_data_sales[i])):
54                 if j == 0:
55                     S3_3_new[i].append(float(a[i]) * float(S3_2_new1[i][j]) + (1 - float(a[i])) * float(S3_3[i][j]))
56                 else:
57                     S3_3_new[i].append(float(a[i]) * float(S3_2_new1[i][j]) + (1 - float(a[i])) * float(
58                         S3_3_new[i][j - 1]))  ##計算三次指數的值
59                 MSE = (int(S3_3_new[i][j]) - int(info_data_sales[i][j])) ** 2 + MSE
60             MSE = (MSE ** (1 / 2)) / int(len(info_data_sales[i]))
61             info_MSE.append(MSE)
62             S3_3_new1.append(S3_3_new[i])
63             # print(S3_3_new1)
64 
65         ##下面是計算At、Bt、Ct以及每個預估值Xt的值,直接計算預估值,不一一列舉Xt的值了
66         u = input('你要預估多少期?')
67         Xt = []
68         for i in range(0, len(info_data_sales)):
69             At = (
70             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(
71                 S3_3_new1[i][len(S3_3_new1[i]) - 1]))
72             Bt = ((float(a[i]) / (2 * ((1 - float(a[i])) ** 2))) * ((6 - 5 * float(a[i])) * (
73             float(S3_1_new1[i][len(S3_1_new1[i]) - 1]) - 2 * (5 - 4 * float(a[i])) * float(
74                 S3_2_new1[i][len(S3_2_new1[i]) - 1]) + (4 - 3 * float(a[i])) * float(
75                 S3_3_new1[i][len(S3_3_new1[i]) - 1]))))
76             Ct = (((float(a[i])) ** 2) / (2 * ((1 - float(a[i])) ** 2))) * (
77             float(S3_1_new1[i][len(S3_1_new1[i]) - 1]) - float(S3_2_new1[i][len(S3_2_new1[i]) - 1])*2 + float(
78                 S3_3_new1[i][len(S3_3_new1[i]) - 1]))
79             Xt.append(At + Bt * int(u) + Ct * (int(u) ** 2))
80             print('' + str(i + 1) + '組的三次平滑預估值為:' + str(Xt[i]) + ';均方誤差為:' + str(info_MSE[i]))

由於注釋寫得很清楚了,就不一段一段的解釋了

明顯看出數列為線性的數列,所以用二次指數平滑會更好

得到的二次平滑結果如下:

誤差判斷:

誤差判斷

預估值

實際值

誤差

數列1

1193179

1192201

0.08%

數列2

1250

1371

9.68%

 由此可見預測效果非常好

附上完整代碼:

 

  1 from openpyxl import load_workbook
  2 import xlsxwriter
  3 
  4 if __name__ == '__main__':
  5     judge = input('請選擇使用幾次指數平滑:一次請按1;二次請按2;三次請按3:')
  6     ##這里是打開excel將數據儲存到數組里面
  7     wb = load_workbook(filename=r'C:\Users\Administrator\Desktop\data.xlsx')  ##讀取路徑
  8     ws = wb.get_sheet_by_name("Sheet1")  ##讀取名字為Sheet1的sheet表
  9     info_data_id = []
 10     info_data_sales = []
 11 
 12     for row_A in range(1, 3):  ## 遍歷第1行到2行
 13         id = ws.cell(row=row_A, column=1).value  ## 遍歷第1行到2行,第1列
 14         info_data_id.append(id)
 15     for row_num_BtoU in range(1, len(info_data_id) + 1):  ## 遍歷第1行到2行
 16         row_empty = []  ##建立一個空數組作為臨時儲存地,每次換行就被清空
 17         for i in range(2, 20):  ## 遍歷第1行到2行,第1到19列
 18             data = ws.cell(row=row_num_BtoU, column=i).value
 19             if data == None:
 20                 pass
 21             else:
 22                 row_empty.append(data)  ##將單元格信息儲存進去
 23         info_data_sales.append(row_empty)  ##row_empty每次儲存完1到19列后壓給info_data_sales,然后row_empty被清空
 24     # print(info_data_id)
 25     # print(info_data_sales)
 26     if judge == '1':
 27         ##############################下面是計算St(1)下面寫為S1_t_######################################
 28         print('你選擇了一次指數平滑預測')
 29         ##一次指數平滑的初值為S1_1,用S1_1來儲存每一組數據的一次平滑的數值
 30         S1_1 = []
 31         for m in range(0, len(info_data_id)):
 32             S1_1_empty = []
 33             x = 0
 34             for n in range(0, 3):
 35                 x = x + int(info_data_sales[m][n])
 36             x = x / 3
 37             S1_1_empty.append(x)
 38             S1_1.append(S1_1_empty)
 39         # print(S1_1)
 40 
 41         a = []  ##這是用來存放阿爾法的數組
 42         info_MSE = []  ##計算均方誤差來得到最優的a(阿爾法)
 43         for i in range(0, len(info_data_sales)):
 44             v = input('請輸入第' + str(i + 1) + '組數據的a:')
 45             a.append(v)
 46 
 47         for i in range(0, len(info_data_sales)):
 48             MSE = 0
 49             for j in range(0, len(info_data_sales[i])):
 50                 S1_1[i].append(
 51                     float(a[i]) * int(info_data_sales[i][j]) + (1 - float(a[i])) * int(S1_1[i][j]))  ##計算預估值
 52                 MSE = (int(S1_1[i][j]) - int(info_data_sales[i][j])) ** 2 + MSE
 53                 # print(info_data_sales[i][j], S1_1[i][j])
 54             MSE = (MSE ** (1 / 2)) / int(len(info_data_sales[i]))  ##得到均方誤差
 55             info_MSE.append(MSE)
 56         # print(info_MSE)
 57         # print(S1_1)
 58         for i in range(0, len(S1_1)):
 59             print('' + str(i + 1) + '組的一次平滑預估值為:' + str(S1_1[i][len(S1_1[i]) - 1]) + ';均方誤差為:' + str(info_MSE[i]))
 60 
 61     if judge == '2':
 62         ##############################下面是計算St(2)下面寫為S2_t_######################################
 63         print('你選擇了二次指數平滑預測')
 64 
 65         ##二次指數平滑的初值為S2_1,用S2_1_new來儲存每一組數據的一次平滑的數值
 66         S2_1 = []
 67         S2_2 = []
 68         for m in range(0, len(info_data_id)):
 69             S2_1_empty = []
 70             x = 0
 71             for n in range(0, 3):
 72                 x = x + float(info_data_sales[m][n])
 73             x = x / 3
 74             S2_1_empty.append(x)
 75             S2_1.append(S2_1_empty)
 76             S2_2.append(S2_1_empty)
 77         # print(S2_2)
 78         a = []  ##這是用來存放阿爾法的數組
 79         info_MSE = []  ##計算均方誤差來得到最優的a(阿爾法)
 80         for i in range(0, len(info_data_sales)):
 81             v = float(input('請輸入第' + str(i + 1) + '組數據的a:'))
 82             a.append(v)
 83 
 84         ##下面是計算一次指數平滑的值
 85         S2_1_new1 = []
 86         for i in range(0, len(info_data_sales)):
 87             S2_1_new = [[]] * len(info_data_id)
 88             for j in range(0, len(info_data_sales[i])):
 89                 if j == 0:
 90                     S2_1_new[i].append(
 91                         float(a[i]) * float(info_data_sales[i][j]) + (1 - float(a[i])) * float(S2_1[i][j]))
 92                 else:
 93                     S2_1_new[i].append(float(a[i]) * float(info_data_sales[i][j]) + (1 - float(a[i])) * float(
 94                         S2_1_new[i][j - 1]))  ##計算一次指數的值
 95             S2_1_new1.append(S2_1_new[i])
 96         # print(S2_1_new1)
 97         # print(len(S2_1_new1[i]))
 98 
 99         ##下面是計算二次指數平滑的值
100         S2_2_new1 = []
101         info_MSE = []  ##計算均方誤差來得到最優的a(阿爾法)
102         for i in range(0, len(info_data_sales)):
103             S2_2_new = [[]] * len(info_data_id)
104             MSE = 0
105             for j in range(0, len(info_data_sales[i])):
106                 if j == 0:
107                     S2_2_new[i].append(float(a[i]) * float(S2_1_new1[i][j]) + (1 - float(a[i])) * float(S2_2[i][j]))
108                 else:
109                     S2_2_new[i].append(float(a[i]) * float(S2_1_new1[i][j]) + (1 - float(a[i])) * float(
110                         S2_2_new[i][j - 1]))  ##計算二次指數的值
111                 MSE = (int(S2_2_new[i][j]) - int(info_data_sales[i][j])) ** 2 + MSE
112             MSE = (MSE ** (1 / 2)) / int(len(info_data_sales[i]))
113             info_MSE.append(MSE)
114             S2_2_new1.append(S2_2_new[i])
115         # print(S2_2_new1)
116         # print(len(S2_2_new1[i]))
117 
118         ##下面是計算At、Bt以及每個預估值Xt的值,直接計算預估值,不一一列舉Xt的值了
119         u = input('你要預估多少期?')
120         Xt = []
121         for i in range(0, len(info_data_sales)):
122             At = (float(S2_1_new1[i][len(S2_1_new1[i]) - 1]) * 2 - float(S2_2_new1[i][len(S2_2_new1[i]) - 1]))
123             Bt = (float(a[i]) / (1 - float(a[i])) * (
124             float(S2_1_new1[i][len(S2_1_new1[i]) - 1]) - float(S2_2_new1[i][len(S2_2_new1[i]) - 1])))
125             Xt.append(At + Bt * int(u))
126             print('' + str(i + 1) + '組的二次平滑預估值為:' + str(Xt[i]) + ';均方誤差為:' + str(info_MSE[i]))
127 
128     if judge == '3':
129         ##############################下面是計算St(3)下面寫為S3_t_######################################
130         print('你選擇了三次指數平滑預測')
131         S3_1 = []
132         S3_2 = []
133         S3_3 = []
134         for m in range(0, len(info_data_id)):
135             S3_1_empty = []
136             x = 0
137             for n in range(0, 3):
138                 x = x + float(info_data_sales[m][n])
139             x = x / 3
140             S3_1_empty.append(x)
141             S3_1.append(S3_1_empty)
142             S3_2.append(S3_1_empty)
143             S3_3.append(S3_1_empty)
144         # print(S3_1)
145         a = []  ##這是用來存放阿爾法的數組
146         info_MSE = []  ##計算均方誤差來得到最優的a(阿爾法)
147         for i in range(0, len(info_data_sales)):
148             v = float(input('請輸入第' + str(i + 1) + '組數據的a:'))
149             a.append(v)
150 
151         ##下面是計算一次指數平滑的值
152         S3_1_new1 = []
153         for i in range(0, len(info_data_sales)):
154             S3_1_new = [[]] * len(info_data_id)
155             for j in range(0, len(info_data_sales[i])):
156                 if j == 0:
157                     S3_1_new[i].append(
158                         float(a[i]) * float(info_data_sales[i][j]) + (1 - float(a[i])) * float(S3_1[i][j]))
159                 else:
160                     S3_1_new[i].append(float(a[i]) * float(info_data_sales[i][j]) + (1 - float(a[i])) * float(
161                         S3_1_new[i][j - 1]))  ##計算一次指數的值
162             S3_1_new1.append(S3_1_new[i])
163 
164         ##下面是計算二次指數平滑的值
165         S3_2_new1 = []
166         info_MSE = []  ##計算均方誤差來得到最優的a(阿爾法)
167         for i in range(0, len(info_data_sales)):
168             S3_2_new = [[]] * len(info_data_id)
169             for j in range(0, len(info_data_sales[i])):
170                 if j == 0:
171                     S3_2_new[i].append(float(a[i]) * float(S3_1_new1[i][j]) + (1 - float(a[i])) * float(S3_2[i][j]))
172                 else:
173                     S3_2_new[i].append(float(a[i]) * float(S3_1_new1[i][j]) + (1 - float(a[i])) * float(
174                         S3_2_new[i][j - 1]))  ##計算二次指數的值
175             S3_2_new1.append(S3_2_new[i])
176 
177         ##下面是計算二次指數平滑的值
178         S3_3_new1 = []
179         info_MSE = []  ##計算均方誤差來得到最優的a(阿爾法)
180         for i in range(0, len(info_data_sales)):
181             S3_3_new = [[]] * len(info_data_id)
182             MSE = 0
183             for j in range(0, len(info_data_sales[i])):
184                 if j == 0:
185                     S3_3_new[i].append(float(a[i]) * float(S3_2_new1[i][j]) + (1 - float(a[i])) * float(S3_3[i][j]))
186                 else:
187                     S3_3_new[i].append(float(a[i]) * float(S3_2_new1[i][j]) + (1 - float(a[i])) * float(
188                         S3_3_new[i][j - 1]))  ##計算三次指數的值
189                 MSE = (int(S3_3_new[i][j]) - int(info_data_sales[i][j])) ** 2 + MSE
190             MSE = (MSE ** (1 / 2)) / int(len(info_data_sales[i]))
191             info_MSE.append(MSE)
192             S3_3_new1.append(S3_3_new[i])
193             # print(S3_3_new1)
194 
195         ##下面是計算At、Bt、Ct以及每個預估值Xt的值,直接計算預估值,不一一列舉Xt的值了
196         u = input('你要預估多少期?')
197         Xt = []
198         for i in range(0, len(info_data_sales)):
199             At = (
200             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(
201                 S3_3_new1[i][len(S3_3_new1[i]) - 1]))
202             Bt = ((float(a[i]) / (2 * ((1 - float(a[i])) ** 2))) * ((6 - 5 * float(a[i])) * (
203             float(S3_1_new1[i][len(S3_1_new1[i]) - 1]) - 2 * (5 - 4 * float(a[i])) * float(
204                 S3_2_new1[i][len(S3_2_new1[i]) - 1]) + (4 - 3 * float(a[i])) * float(
205                 S3_3_new1[i][len(S3_3_new1[i]) - 1]))))
206             Ct = (((float(a[i])) ** 2) / (2 * ((1 - float(a[i])) ** 2))) * (
207             float(S3_1_new1[i][len(S3_1_new1[i]) - 1]) - float(S3_2_new1[i][len(S3_2_new1[i]) - 1])*2 + float(
208                 S3_3_new1[i][len(S3_3_new1[i]) - 1]))
209             Xt.append(At + Bt * int(u) + Ct * (int(u) ** 2))
210             print('' + str(i + 1) + '組的三次平滑預估值為:' + str(Xt[i]) + ';均方誤差為:' + str(info_MSE[i]))

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM