LSTM原理及实现(二)
在一篇中着核心要素简述了LSTM算法的原理,本篇中将在本人做过一些前置处理的数据集上实现LSTM的一个实际应用案例。该数据集是一段时间内的时序数据,数据做过脱敏处理,列特征标识为A,B,C,其三者间存在一点关系影响,本案例将基于LSTM算法实现多变量时间序列的重构+预测。
数据集:https://download.csdn.net/download/weixin_44162104/11200183
完整代码:https://github.com/521bibi/LSTMdemo
数据读取
class XLSReader(object):
def __init__(self):
file = 'E:\pyProjects\LSTMdemo\data\LSTMdemo.xlsx'
self.xls_read = pd.read_excel(file,header=None,parse_dates=[0])
def read(self):
xls_data = self.xls_read
parse_data = self.parse_xls(xls_data)
return parse_data
def parse_xls(self,content):
parse_data = content.iloc[1:,:4]
# parse_data[0] = pd.to_datetime(parse_data[0], format="%Y/%m/%d %H:%M:%S")
parse_data.set_index(0, inplace=True)
return parse_data
构建Excel读取函数XLSReader,读取目标数据集,将第一列时间轴数据作为行名,A,B,C作为列名。
reader = XLSReader()
df_result = reader.read()
print(df_result)
数据预处理
缺省值处理
# nan to mean
df_result = df_result.fillna(df_result.mean()[:3])
归一化处理
values = df_result.values
# ensure all data is float
values = values.astype('float32')
# normalize features
scaler = MinMaxScaler(feature_range=(0, 1))
scaled = scaler.fit_transform(values)
建模训练
输入
# split into train and test sets
splitpoint = 450
train = scaled[:splitpoint,:]
test = scaled[splitpoint:,:]
将数据集切分为训练集和验证集
# split into input and output
train_X,train_y = train[:-1,:3],train[1:,0]
test_X, test_y = test[:-1, :3], test[1:, 0]
以A,B,C作为特征输入,预测下一时刻的A列数据。本例demo只对A列数据做重构,其余两列基本一模一样。
# reshape input to be 3D(samples,timesteps,features)
train_X = train_X.reshape(train_X.shape[0],1,train_X.shape[1])
test_X = test_X.reshape(test_X.shape[0], 1, test_X.shape[1])
# print(self.train_X.shape,self.train_y.shape,test_X.shape,test_y.shape)
将输入转为Keras中LSTM的API的标准输入格式,第二维设置为1是设置本例的LSTM步长为1,上一时刻对下一时刻的预测,对数据集的观测,我们可以知道以天为周期同样存在很强关系,设置步长为24的训练结果可以与此对比,哪种模型更佳。(本例旨在介绍LSTM的实例应用,在此不做对比了)
模型搭建
# design network
model = Sequential()
# model.add(LSTM(10, input_shape=(train_X.shape[1], train_X.shape[2])))
model.add(LSTM(4, input_shape=(train_X.shape[1], train_X.shape[2]),return_sequences=True))
model.add(LSTM(4, return_sequences=False))
model.add(Dense(1))
model.compile(loss='mae', optimizer='adam')
通过多次人工试验,建立了两层LSTM结构,第一层和第二层都设置的4个LSTMcell单元,代价函数采用mae,优化器采用adam算法。
模型训练和保存
# fit network
history = model.fit(train_X, train_y, nb_epoch=20, batch_size=1,validation_data=(test_X, test_y), verbose=2,shuffle=False)
model.save("currentlstm.h5")
#plot history
plt.plot(history.history['loss'],label='train')
plt.plot(history.history['val_loss'], label='test')
plt.legend()
plt.show()
这里设置了迭代20次,并将训练集和验证集上的损失函数MAE作图展示。
拟合效果
plt.figure(figsize=(16,8))
train_predict = model.predict(train_X)
test_predict = model.predict(test_X)
plt.plot(scaled[1:,0], c='b')
plt.plot([x for x in train_predict], c='g')
plt.plot([None for _ in train_predict] + [x for x in test_predict], c='y')
plt.show()
归一化数据集上的拟合效果,其中绿色为训练集拟合效果,黄色是验证集。
模型应用和预测
数据重构
#download model
model = load_model('currentlstm.h5')
plt.figure(figsize=(24,12))
current_predict = model.predict(current_X)
归一化反转
# 归一化反转
from numpy import concatenate
# invert scaling for forecast
inv_yhat = concatenate((currentA_predict,currentB_predict,currentC_predict), axis=1)
current_X = inv_yhat
inv_yhat = scaler.inverse_transform(inv_yhat)
预测
for i in range(12):
# reshape input to be 3D(samples,timesteps,features)
current_X = current_X.reshape(current_X.shape[0],1,current_X.shape[1])
#download model
model = load_model('currentlstm.h5')
currentA_predict = model.predict(current_X)
# print(currentA_predict)
model = load_model('currentB_lstm.h5')
currentB_predict = model.predict(current_X)
# print(currentB_predict)
model = load_model('currentC_lstm.h5')
currentC_predict = model.predict(current_X)
# print(currentC_predict)
# 归一化反转
from numpy import concatenate
# invert scaling for forecast
inv_yhat = concatenate((currentA_predict,currentB_predict,currentC_predict), axis=1)
current_X = inv_yhat
inv_yhat = scaler.inverse_transform(inv_yhat)
# print(inv_yhat)
current_predict = np.row_stack((current_predict, inv_yhat))
# print("%d:"%i,current_X)
print('数据处理中: {:.2%}'.format((i+1) /12))
此前本人已经对数据集的A,B,C三个时序的模型训练调试了多次,最终择优确定了模型,在此demo中就忽略了其他两列数据的模型训练,方法和对A类似,只是得到的模型结构和参数不一致。
预测采用循环滚动的预测方式,我们要预测未来12个小时的时序值,模型每次输入为上一时刻A,B,C三个数据,因此要不停滚动得到每一个时刻的三项数据。