一般常用到的指数平滑法为一次指数平滑、二次指数平滑和三次指数平滑,高次指数平滑一般比较难见到,因此本文着重介绍了一次、二次和三次指数平滑的特点与不同。
一次指数平滑一般应用于直线型数据,且一次指数平滑具有滞后性,可以说明有明显的时间性、季节性。
二次指数平滑一般也应用于直线型,但是效果会比一次指数平滑好很多,也就相当于加强版的一次指数平滑。
三次指数平滑可以应用于抛物线型的数据,因为数据在二次平滑过后还是具有斜率,那么可以继续使用三次指数平滑。
初值:不管什么指数平滑都会有个初值,假如数据大于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 = 020 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 + MSE24 # 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 = 040 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 + MSE47 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 / 310 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 = 053 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 + MSE60 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% |
由此可见预测效果非常好
文章出处:https://www.cnblogs.com/TTyb/p/5716125.html
附上完整代码:
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 = 0105 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 + MSE112 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 = 0137 for n in range(0, 3):138 x = x + float(info_data_sales[m][n])139 x = x / 3140 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 = 0183 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 + MSE190 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]))