## 长短期记忆网络（LSTM，Long Short-Term Memory）

### 第一种：使用前个三十天数据进行预测后一天的数据。

#### 模型结构

```Model: "sequential"
_________________________________________________________________
Layer (type)                 Output Shape              Param #
=================================================================
lstm (LSTM)                  (None, 30, 64)            16896
_________________________________________________________________
lstm_1 (LSTM)                (None, 30, 128)           98816
_________________________________________________________________
lstm_2 (LSTM)                (None, 32)                20608
_________________________________________________________________
dropout (Dropout)            (None, 32)                0
_________________________________________________________________
dense (Dense)                (None, 1)                 33
=================================================================
Total params: 136,353
Trainable params: 136,353
Non-trainable params: 0
_________________________________________________________________```

#### 代码：

```# 调用库
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from tensorflow import keras
from tensorflow.keras import layers
from sklearn.preprocessing import MinMaxScaler
#### 数据处理部分 ####
# 读入数据
# 时间戳长度
time_step = 30 # 输入序列长度
print(len(data))
# 划分训练集与验证集
data = data[['Value']]
train = data[0:1277]
valid = data[1278:1550]
test = data[1551:]
# 归一化
scaler = MinMaxScaler(feature_range=(0, 1))
# datas 切片数据 time_step要输入的维度 pred 预测维度
def scalerClass(datas,scaler,time_step,pred):
x, y = [], []
scaled_data = scaler.fit_transform(datas)
for i in range(time_step, len(datas) - pred):
x.append(scaled_data[i - time_step:i])
y.append(scaled_data[i: i + pred])
# 把x_train转变为array数组
x, y = np.array(x), np.array(y).reshape(-1, 1)  # reshape(-1,5)的意思时不知道分成多少行，但是是五列
return x,y
# 训练集 验证集 测试集 切片
x_train,y_train = scalerClass(train,scaler,time_step=time_step,pred=1)
x_valid, y_valid = scalerClass(valid,scaler,time_step=time_step,pred=1)
x_test, y_test = scalerClass(test,scaler,time_step=time_step,pred=1)
#### 建立神经网络模型 ####
model = keras.Sequential()
# model.compile(optimizer = 优化器，loss = 损失函数， metrics = ["准确率”])
# ”mse" 或者 tf.keras.losses.MeanSquaredError()
# monitor：要监测的数量。
# factor：学习速率降低的因素。new_lr = lr * factor
# patience：没有提升的epoch数，之后学习率将降低。
# verbose：int。0：安静，1：更新消息。
# mode：{auto，min，max}之一。在min模式下，当监测量停止下降时，lr将减少；在max模式下，当监测数量停止增加时，它将减少；在auto模式下，从监测数量的名称自动推断方向。
# min_delta：对于测量新的最优化的阀值，仅关注重大变化。
# cooldown：在学习速率被降低之后，重新恢复正常操作之前等待的epoch数量。
# min_lr：学习率的下限
learning_rate= keras.callbacks.ReduceLROnPlateau(monitor='val_loss', patience=3, factor=0.7, min_lr=0.00000001)
#显示模型结构
model.summary()
# 训练模型
history = model.fit(x_train, y_train,
batch_size = 128,
epochs=100,
validation_data=(x_valid, y_valid),
callbacks=[learning_rate])
# loss变化趋势可视化
plt.title('LSTM loss figure')
plt.plot(history.history['loss'],label='training loss')
plt.plot(history.history['val_loss'], label='val loss')
plt.legend(loc='upper right')
plt.show()
#### 预测结果分析&可视化 ####
# 输入测试数据,输出预测结果
y_pred = model.predict(x_test)
# 输入数据和标签,输出损失和精确度
model.evaluate(x_test)
scaler.fit_transform(pd.DataFrame(valid['Value'].values))
# 反归一化
y_pred = scaler.inverse_transform(y_pred.reshape(-1,1)[:,0].reshape(1,-1)) #只取第一列
y_test = scaler.inverse_transform(y_test.reshape(-1,1)[:,0].reshape(1,-1))

# 预测效果可视化
plt.figure(figsize=(16, 8))
plt.title('Predicted and real')
dict = {
'Predictions': y_pred[0],
'Value': y_test[0]
}
data_pd = pd.DataFrame(dict)
plt.plot(data_pd[['Value']],linewidth=3,alpha=0.8)
plt.plot(data_pd[['Predictions']],linewidth=1.2)
#plt.savefig('lstm.png', dpi=600)
plt.show()```

#### 预测后几天的数据和预测后一天原理是一样的

```# 调用库
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from tensorflow import keras
from tensorflow.keras import layers
from sklearn.preprocessing import MinMaxScaler
# 读入数据
time_step = 50 # 输入序列长度
# 划分训练集与验证集
data = data[['Value']]
train = data[0:1277]  #70%
valid = data[1278:1550] #15%
test = data[1551:] #15%
# 归一化
scaler = MinMaxScaler(feature_range=(0, 1))
# 定义一个切片函数
# datas 切片数据 time_step要输入的维度 pred 预测维度
def scalerClass(datas,scaler,time_step,pred):
x, y = [], []
scaled_data = scaler.fit_transform(datas)
for i in range(time_step, len(datas) - pred):
x.append(scaled_data[i - time_step:i])
y.append(scaled_data[i: i + pred])
# 把x_train转变为array数组
x, y = np.array(x), np.array(y).reshape(-1, 5)  # reshape(-1,5)的意思时不知道分成多少行，但是是五列
return x,y
# 训练集 验证集 测试集 切片
x_train,y_train = scalerClass(train,scaler,time_step=time_step,pred=5)
x_valid, y_valid = scalerClass(valid,scaler,time_step=time_step,pred=5)
x_test, y_test = scalerClass(test,scaler,time_step=time_step,pred=5)
# 建立网络模型
model = keras.Sequential()
learning_rate_reduction = keras.callbacks.ReduceLROnPlateau(monitor='val_loss', patience=3, factor=0.7, min_lr=0.000000005)
model.summary()
history = model.fit(x_train, y_train,
batch_size = 128,
epochs=30,
validation_data=(x_valid, y_valid),
callbacks=[learning_rate_reduction])
# loss变化趋势可视化
plt.title('LSTM loss figure')
plt.plot(history.history['loss'],label='training loss')
plt.plot(history.history['val_loss'], label='val loss')
plt.legend(loc='upper right')
plt.show()
#### 预测结果分析&可视化 ####
y_pred = model.predict(x_test)
model.evaluate(x_test)
scaler.fit_transform(pd.DataFrame(valid['Value'].values))
print(y_pred)
print(y_test)
# 预测效果可视化
# 反归一化
y_pred = scaler.inverse_transform(y_pred.reshape(-1,5)[:,0].reshape(1,-1)) #只取第一列
y_test = scaler.inverse_transform(y_test.reshape(-1,5)[:,0].reshape(1,-1))
plt.figure(figsize=(16, 8))
plt.title('Predicted and real')
dict_data = {
'Predictions': y_pred.reshape(1,-1)[0],
'Value': y_test[0]
}
data_pd = pd.DataFrame(dict_data)
plt.plot(data_pd[['Value']],linewidth=3,alpha=0.8)
plt.plot(data_pd[['Predictions']],linewidth=1.2)
plt.savefig('lstm.png', dpi=600)
plt.show()```