赞
踩
本文尝试应用长短期记忆(LSTM,Long Short-Term Memory)神经网络模型对月度时序数据进行预测,样本时序数据时间跨度2017年1月至今,同时对多个目标变量时序数据进行预测。本文主要参考了《python预测之美》部分章节内容,暂不做详尽的理论说明与代码解释,仅做个人积累记录使用,如有侵权或不合规请及时联系处理~
目录
本例样本数据为多变量月度时序数据宽表,读取时序数据后将“年月”字段设置为索引。
- import pandas as pd
-
- #加载数据
- ts_data0 = pd.read_excel("C:/Users/admin/Desktop/data.xlsx",sheet_name='目标变量宽表')
- ts_data0['年月']=ts_data0['年月'].astype(object)
- ts_data0['年月'] = pd.to_datetime(ts_data0['年月'],format='%Y%m')
- tmp =ts_data0.set_index('年月')
将目标变量时序数据进行z-score标准化处理,消除各变量间量纲差异可能带来的影响。
- import numpy as np
-
- #数据预处理
- vmean = tmp.apply(lambda x:np.mean(x))
- vstd = tmp.apply(lambda x:np.std(x))
- t0 = tmp.apply(lambda x:(x-np.mean(x))/np.std(x)).values #z-score标准化
本例样本数据初始结构为二维表,索引为“年月”,共15列数据(目标变量),样本时序数据以12个月为一个波动周期。因此设置LSTM模型输入输出变量数dim=15,设置LSTM模型往前依赖的时序数据期数SEQLEN=15(稍大于周期月数12);
用于LSTM建模的输入数据需要整理成3维结构(数据块个数×SEQLEN个数据记录×dim个变量),输出仍为2维数据集。用前15(SEQLEN)条时序数据预测第16条数据;单个样本数据块为相邻15条15(dim)列,用以对第16条15(dim)列数据进行预测;验证集为5(test_len)个数据块,据此推导训练集大小;下期待预测的输入为最后15条15列数据。
- #参数
- dim= 15#预测变量数
- SEQLEN = 15#依赖前期数据期数
- test_len=5
-
- #划分训练集与验证集
- X_train = np.zeros((t0.shape[0]-SEQLEN-test_len, SEQLEN, dim))#三维
- Y_train = np.zeros((t0.shape[0]-SEQLEN-test_len, dim),)#二维
- for i in range(SEQLEN, t0.shape[0]-test_len):
- Y_train[i-SEQLEN] = t0[i]
- X_train[i-SEQLEN] = t0[(i-SEQLEN):i]
-
- X_test = np.zeros((test_len, SEQLEN, dim))
- Y_test = np.zeros((test_len, dim),)
- for i in range(t0.shape[0]-test_len,t0.shape[0]):
- Y_test[i-t0.shape[0]+test_len] = t0[i]
- X_test[i-t0.shape[0]+test_len] = t0[(i-SEQLEN):i]
-
- #下期数据预测输入
- X_pred = np.zeros((1, SEQLEN, dim))
- X_pred[0]=t0[t0.shape[0]-SEQLEN:t0.shape[0]]
-
- print(X_pred)
样本数据块预览,输入LSTM模型的其中一个样本数据块为15条相邻记录×15个变量。
在训练集上完成模型训练,设置隐含层神经元数量为45,初始迭代次数为2000次,每批次处理5个样本数据块。
- from keras.layers import LSTM, Dense
- from keras.models import Sequential
-
- #训练LSTM模型
- model = Sequential()
- model.add(LSTM(45, input_shape=(SEQLEN, dim),activation='relu',recurrent_dropout=0.01))
- model.add(Dense(dim,activation='linear'))
- model.compile(loss = 'mean_squared_error', optimizer = 'rmsprop')
- history = model.fit(X_train, Y_train, epochs=2000, batch_size=5, validation_split=0)
迭代过程示例,损失函数loss逐渐下降,越往后降得越慢,直至收敛。
绘图直观观察损失函数loss下降、收敛过程
- import matplotlib.pyplot as plt
-
- #绘制损失函数
- plt.figure(figsize=(15,5))
- plt.plot(history.history['loss'], label='train')
- plt.legend()
- plt.show()
如图所示,本例损失函数loss值在迭代次数达到500以后已趋收敛,可将模型迭代次数调整为稍高于500,提高性能。
输出测试集预测结果,需对结果进行z-score标准化还原。
- #模型预测结果标准化还原
- pred_test=model.predict(X_test)*vstd.values+vmean.values
- preddf=model.predict(X_pred)*vstd.values+vmean.values
- pred = np.vstack((pred_test,preddf))
依次输出15个目标变量在各自测试集上的模型预测准确率,绘制15个目标变量实际值与预测值的曲线对比图(画布形状:15行1列)。
- import matplotlib.pyplot as plt
- import matplotlib
- from matplotlib.font_manager import FontProperties
- font = FontProperties(fname=r"c:\windows\fonts\simsun.ttc", size=14)
-
- #模型预测结果评估
- ts_data=tmp.copy()
- cols = ts_data.columns
- m = SEQLEN+1
- xts = tmp.index[-m::1]
-
- fig, axes = plt.subplots(15,1,figsize=(15,80))
- index = 0
- for ax in axes.flatten():
- ax.plot(range(m),ts_data[cols].iloc[-m:,index],'-',c='lightgray',linewidth=2,label="real")
- ax.plot(range(m-test_len-1,m),pred[:,index],'o--',c='black',linewidth=2,label="predict")
- ax.set_xticks(np.arange(0, m, step=1))
- ax.set_xticklabels(xts,rotation=50)
- ax.set_ylabel(cols[index],fontproperties=font)
- ax.legend()
- result_ts=ts_data[cols].iloc[-(m-10):,index]
- result_pred=pd.Series(pred[:,index],index=ts_data[cols].iloc[-(m-10):,index].index,name='pred')
- result = pd.concat([result_ts, result_pred], axis=1)
- result['accur']=100-abs((result['pred']-result[cols[index]])*100/result[cols[index]])
- print(result)
- index = index + 1
- plt.tight_layout()
- plt.show()
结果预览,其中一个目标变量的预测准确率。
该变量相应实际值与预测值曲线对比图。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。