一般常用到的指数平滑法为一次指数平滑、二次指数平滑和三次指数平滑,高次指数平滑一般比较难见到,因此本文着重介绍了一次、二次和三次指数平滑的特点与不同。
一次指数平滑一般应用于直线型数据,且一次指数平滑具有滞后性,可以说明有明显的时间性、季节性。
二次指数平滑一般也应用于直线型,但是效果会比一次指数平滑好很多,也就相当于加强版的一次指数平滑。
三次指数平滑可以应用于抛物线型的数据,因为数据在二次平滑过后还是具有斜率,那么可以继续使用三次指数平滑。
初值:不管什么指数平滑都会有个初值,假如数据大于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]) + ';均方误差为:'
二次指数平滑代码为:
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]) + ';均方误差为:'
三次指数平滑代码为:
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]) + ';均方误差为:'
由于注释写得很清楚了,就不一段一段的解释了
明显看出数列为线性的数列,所以用二次指数平滑会更好
得到的二次平滑结果如下:
误差判断:
误差判断 | 预估值 | 实际值 | 误差 |
数列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]) + ';均方误差为:'