从零开始应用LSTM网络
Posted 彭祥.
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了从零开始应用LSTM网络相关的知识,希望对你有一定的参考价值。
数据预处理
该部分包含生成差分数据,归一化,数据缩放,生成监督数据集等。
将数据转换成有监督数据
# coding=utf-8
from pandas import read_csv
from datetime import datetime
from pandas import DataFrame
from pandas import concat
# load data
def parser(x):
return datetime.strptime(x, '%Y/%m/%d')
series = read_csv("data_set\\shampoo-sales.csv", header=0, parse_dates=[0], index_col=0, squeeze=True,
date_parser=parser)
'''
将数据转换成有监督数据
即包含input output
训练的目的就是找到训练数据input和output的关系
此处的input是t时间步的数据,output为t+1时间步的数据
具体实现就是将整体的时间数据向后滑动一格,和原始数据拼接,就是有监督的数据
'''
# 这个函数说了一大堆,简单说就是把data数组重新构造成两两一组的二维数组,每个数据对格式是[0,n],[n,n+1],[n+1,n+2],
# 第一组数据用0补全,即为[0,n],这就是所谓的监督学习数据
def timeseries_to_supervised(data, lag=1): # lag表示的是当前的值只与历史lag个时间步长的值有关,也就是用lag个数据预测下一个
df = DataFrame(data)
colums = [df.shift(i) for i in range(1, lag + 1)] # 原始数据时间窗向后移动lag步长
colums.append(df) # 拼接数据
df = concat(colums, axis=1) # 横向拼接重塑数据,格式:input putput
df.fillna(0, inplace=True) # 由于数据整体向后滑动lag后,前面的lag个数据是Na形式,用0来填充
return df
X = series.values
supervised = timeseries_to_supervised(X, 1)
print(supervised.head())
原数据:
转换为监督数据后:
数据缩放
# coding=utf-8
from pandas import read_csv
from pandas import datetime
from pandas import Series
from sklearn.preprocessing import MinMaxScaler
# load data
def parser(x):
return datetime.strptime(x, '%Y/%m/%d')
series = read_csv('data_set/shampoo-sales.csv', header=0, parse_dates=[0], index_col=0, squeeze=True,
date_parser=parser)
print (series.head())
# 所谓缩放,就是把一组数组中的数字都变成[-1,1]范围的数字,取数组中最大的那个数组,令其为1,最小的数字,令其为-1,
# 剩下的数字根据比例关系,在[-1,1]中给其找一个对应值
# 缩放
X = series.values
X = X.reshape(len(X), 1) # MinMaxScaler函数需要矩阵作为输入,所以reshape数据为矩阵,因为是一维数组,所以生成的是n行1列的一个矩阵
scaler = MinMaxScaler(feature_range=(-1, 1)) # 定义缩放范围,-1,1是数据缩放的范围
scaler = scaler.fit(X) # 调用缩放数据的fun
scalered_X = scaler.transform(X)#转换成一个[-1,1]区间的矩阵
scalered_series = Series(scalered_X[:, 0])#把矩阵序列化成列表
print (scalered_series)
# 逆缩放,反着来一遍,转换回去
inverted_X = scaler.inverse_transform(scalered_X)#把数值为[-1,1]之间的矩阵转换成正常数据的矩阵
inverted_series = Series(inverted_X[:, 0])#把矩阵转换成列表
print (inverted_series.head())
搭建网络
从0开始实现深度学习网络
我们搭建网络并训练的流程为:
读取数据,如读取时间序列,图片等
数据预处理,如将其转换为监督数据,数据归一化,缩放等,划分数据集
搭建模型,设置网络层结构,设置参数,神经元个数等
编译模型,设置批次大小,损失函数,优化器等
训练模型,设置迭代次数,批次大小传入数据等
保存模型,如参数权值等
模型预测数据,使用已保存模型进行数据预测
模型评估,设置评估函数
结果分析,如通过图像。
数据读取,使用的是numpy的read_csv
# 读取时间数据的格式化
def parser(x):
return datetime.strptime(x, '%Y/%m/%d')
# 加载数据
series = read_csv('data_set/shampoo-sales.csv',
header=0, parse_dates=[0], index_col=0, squeeze=True,
date_parser=parser)
转换为差分数据,即将数据变为稳定的
# 转换成差分数据
def difference(dataset, interval=1):
diff = list()
for i in range(interval, len(dataset)):
value = dataset[i] - dataset[i - interval]
diff.append(value)
return Series(diff)
diff_values = difference(raw_values, 1)#转换成差分数据
转换为有监督数据,即input,output形式
# 转换成有监督数据
def timeseries_to_supervised(data, lag=1):
df = DataFrame(data)
columns = [df.shift(i) for i in range(1, lag + 1)] # 数据滑动一格,作为input,df原数据为output
columns.append(df)
df = concat(columns, axis=1)
df.fillna(0, inplace=True)
return df
# 让数据变成稳定的
# 把稳定的数据变成有监督数据
supervised = timeseries_to_supervised(diff_values, 1)
划分训练集测试集
# 数据拆分:训练数据、测试数据,前24行是训练集,后12行是测试集
train, test = supervised_values[0:-12], supervised_values[-12:]
数据缩放至-1到1之间
# 缩放
def scale(train, test):
# 根据训练数据建立缩放器
scaler = MinMaxScaler(feature_range=(-1, 1))
scaler = scaler.fit(train)
# 转换train data
train = train.reshape(train.shape[0], train.shape[1])
train_scaled = scaler.transform(train)
# 转换test data
test = test.reshape(test.shape[0], test.shape[1])
test_scaled = scaler.transform(test)
return scaler, train_scaled, test_scaled
scaler, train_scaled, test_scaled = scale(train, test)
模型训练,这里批次大小设置为1,即每次训练一个数据,使用手写循环调用fit,从而没训练一次数据便完成一次权值更新
def fit_lstm(train, batch_size, nb_epoch, neurons):
X, y = train[:, 0:-1], train[:, -1]
X = X.reshape(X.shape[0], 1, X.shape[1])
model = Sequential()
# 添加LSTM层
model.add(LSTM(neurons, batch_input_shape=(batch_size, X.shape[1], X.shape[2]), stateful=True))
model.add(Dense(1)) # 输出层1个node
# 编译,损失函数mse+优化算法adam
model.compile(loss='mean_squared_error', optimizer='adam')
for i in range(nb_epoch):
# 按照batch_size,一次读取batch_size个数据
model.fit(X, y, epochs=1, batch_size=batch_size, verbose=0, shuffle=False)
model.reset_states() #更新权值
print("当前计算次数:"+str(i))
return model
lstm_model = fit_lstm(train_scaled, 1, 1500, 1) # 训练数据,batch_size,epoche次数, 神经元个数
预测数据
# 预测
train_reshaped = train_scaled[:, 0].reshape(len(train_scaled), 1, 1)#训练数据集转换为可输入的矩阵
lstm_model.predict(train_reshaped, batch_size=1)#用模型对训练数据矩阵进行预测
预测数据并完成性能分析
predictions = list()
for i in range(len(test_scaled)):#根据测试数据进行预测,取测试数据的一个数值作为输入,计算出下一个预测值,以此类推
# 1步长预测
X, y = test_scaled[i, 0:-1], test_scaled[i, -1]
yhat = forcast_lstm(lstm_model, 1, X)
# 逆缩放
yhat = invert_scale(scaler, X, yhat)
# 逆差分
yhat = inverse_difference(raw_values, yhat, len(test_scaled) + 1 - i)
predictions.append(yhat)
expected = raw_values[len(train) + i + 1]
print('Moth=%d, Predicted=%f, Expected=%f' % (i + 1, yhat, expected))
print(predictions)
# 性能报告
rmse = sqrt(mean_squared_error(raw_values[-12:], predictions))
print('Test RMSE:%.3f' % rmse)
# 绘图
pyplot.plot(raw_values[-12:])
pyplot.plot(predictions)
pyplot.show()
以上是关于从零开始应用LSTM网络的主要内容,如果未能解决你的问题,请参考以下文章
多图+公式全面解析RNN,LSTM,Seq2Seq,Attention注意力机制