【Python实战进阶】——深度学习网络之LSTM理论与实战
🍉CSDN小墨&晓末:https://blog.csdn.net/jd1813346972
个人介绍: 研二|统计学|干货分享
擅长Python、Matlab、R等主流编程软件
累计十余项国家级比赛奖项,参与研究经费10w、50w级横向
文章目录
- 1 LSTM原理
- 2 案例演示
- 2.1 目标
- 2.2 代码演示
- 2.2.1 加载包
- 2.2.2 读取数据并进行数据预处理
- 2.2.3 归一化并构建训练集和测试集
- 2.2.4 构建并训练LSTM模型
- 2.2.5 评估训练集效果
- 2.2.6 评估验证集效果
- 2.2.7 结果可视化
- 3 完整代码
该篇文章主要讲解了深度学习网络之LSTM原理,并通过实例数据利用Python演示了基于Kears的该模型运用,包括数据预处理、数据归一化和反归一化、训练集测试集构建、模型训练预测、结果可视化等,可借鉴参考,由于本篇文章展示的单变量预测方式,多变量预测可从训练集和测试集构建中的函数定义进行修改。
1 LSTM原理
LSTM(Long Short-Term Memory)是长短期记忆网络是一种经过优化的循环神经网络,相较于传统的RNN网络,它创新性地引入了门控单元机制,包括输入门、输出门和遗忘门。这些门控单元赋予LSTM网络类似人脑的记忆功能,使其在时间序列处理上能够长时间存储并维护数据信息。通过门控单元的精确调控,LSTM网络能够智能地筛选和保留关键信息,从而更有效地挖掘时间和信息之间的深层联系。门控单元的引入不仅解决了RNN网络在处理长时间序列时遇到的记忆衰退问题,同时也显著缓解了梯度消失和梯度爆炸等挑战。下图展示了LSTM网络的结构示意图,直观地呈现了其内部机制和工作原理。
图中 f t f_t ft、 i t i_t it、 O t O_t Ot为遗忘门、输入门、输出门; g t g_t gt、 h t h_t ht为临时细胞状态和隐藏状态。遗忘门运用Sigmoid激活函数来评估上一时刻的隐藏状态是否应当更新至当前的细胞状态。当激活值为1时,遗忘门将保留上一时刻的信息;而当激活值为0时,它将忽略或丢弃上一时刻的信息。输入门则负责筛选并构建新的细胞状态向量,以补充或更新细胞状态。输出门则负责调控细胞状态的输出,并将其传递至下一个细胞状态。LSTM网络的更新过程遵循以下公式:
为 W f W_f Wf、 W i W_i Wi、 W g W_g Wg、 b f b_f bf、 b i b_i bi、 b g b_g bg遗忘门、输入门、临时细胞状态的权重和偏置。
2 案例演示
2.1 目标
有2014年1月1日到2020年7月20日重庆市天气日AQI数据,基于 Keras(一个基于 TensorFlow 和 Theano 的深度学习库)。对AQI进行一步LSTM预测。
2.2 代码演示
2.2.1 加载包
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from sklearn.preprocessing import MinMaxScaler
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import LSTM, Dense
from numpy import concatenate
import matplotlib.pyplot as plt
import seaborn as sns
from sklearn.metrics import mean_squared_error
from sklearn.metrics import mean_squared_error, mean_absolute_error
plt.rcParams['font.sans-serif']=['SimHei'] #用来正常显示中文标签
plt.rcParams['axes.unicode_minus']=False #用来正常显示负号
font2 = {
'weight' : 'normal',
'size' : 10,
}
2.2.2 读取数据并进行数据预处理
data=pd.read_excel(r"重庆天气数据.xlsx",sheet_name=0,keep_default_na=True,header=0)#读取数据
data['日期'] = pd.to_datetime(data['日期'],format='%Y%m%d')
data1=data
data1.index = pd.to_datetime(data1['日期'],format='%Y%m%d')
all_dates = pd.date_range(start=data.index.min(), end=data.index.max(), freq='D') # 构造完整日期范围
data1 = data1.reindex(all_dates.date) # 重新索引数据框,补齐缺失日期
2.2.3 归一化并构建训练集和测试集
dataset =data1.iloc[:, 1].values.reshape(-1, 1)
# 对数据进行归一化处理
scaler = MinMaxScaler(feature_range=(0, 1))
scaled_data = scaler.fit_transform(dataset)
##测试集4周,其余数据分训练集和验证集8:2
##构建训练集、验证集和测试集
week_days=7
time_steps =30
train_scaled_data=scaled_data[:int((len(scaled_data))*0.8)]
test_scaled_data=scaled_data[-(len(scaled_data)-(int((len(scaled_data))*0.8))+time_steps):]
#利用全数据进行模型拟合
def create_dataset(time_series, time_steps=1):
X, y = [], []
for i in range(len(time_series) - time_steps):
X.append(time_series[i:(i + time_steps), 0])
y.append(time_series[i + time_steps, 0])
return np.array(X), np.array(y)
X_train, y_train = create_dataset(train_scaled_data, time_steps)#训练集
X_test, y_test = create_dataset(test_scaled_data, time_steps) #测试集
2.2.4 构建并训练LSTM模型
model = Sequential()
model.add(LSTM(units=50, return_sequences=True, input_shape=(time_steps, 1)))
model.add(LSTM(units=50))
model.add(Dense(units=1))
model.compile(optimizer='adam', loss='mean_squared_error')
model.fit(X_train, y_train, epochs=100, batch_size=32)
2.2.5 评估训练集效果
y_train_pred = model.predict(X_train)
#反标准化
y_train_pred = scaler.inverse_transform(y_train_pred)
y_train = scaler.inverse_transform([y_train])
# 计算评估指标(例如均方根误差、平均绝对误差)
y_train_pred = concatenate(y_train_pred)
y_train = concatenate(y_train)
rmse = np.sqrt(np.mean((y_train - y_train_pred) ** 2))
mae =np.mean(abs(y_train- y_train_pred))
print("RMSE:", rmse)
print("MAE:", mae)
运行结果:
RMSE: 22.725637966946724
MAE: 16.627509833900792
2.2.6 评估验证集效果
y_test_pred = model.predict(X_test)
y_test_pred = scaler.inverse_transform(y_test_pred)
y_test = scaler.inverse_transform([y_test])
prediction1 = concatenate(y_test_pred)
# 计算评估指标(例如均方根误差、平均绝对误差)
rmse = np.sqrt(np.mean((y_test - prediction1) ** 2))
mae =np.mean(abs(y_test- prediction1))
print("RMSE:", rmse)
print("MAE:", mae)
运行结果:
RMSE: 23.673333373871603
MAE: 17.643125378762008
2.2.7 结果可视化
plt.plot(data1.index[time_steps:int((len(scaled_data))*0.8)],y_train.flatten(), linewidth=2,label='Actual_t')
plt.plot(data1.index[time_steps:int((len(scaled_data))*0.8)],y_train_pred.flatten(), linewidth=2,label='Fitted_t')
plt.plot(data1.index[-(len(scaled_data)-int((len(scaled_data))*0.8)):],y_test.flatten(),linewidth=2, label='Actual_p')
plt.plot(data1.index[-(len(scaled_data)-int((len(scaled_data))*0.8)):],prediction1.flatten(), linewidth=2,label='Fitted_p')
plt.xlim(min(data1.index), max(data1.index))
plt.title('重庆天气AQI数据LSTM建模结果')
plt.xlabel('时间')
plt.ylabel('AQI')
plt.legend()
plt.show()
运行结果:
根据结果现实,模型性能良好。
3 完整代码
##读取包
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from sklearn.preprocessing import MinMaxScaler
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import LSTM, Dense
from numpy import concatenate
import matplotlib.pyplot as plt
import seaborn as sns
from sklearn.metrics import mean_squared_error
from sklearn.metrics import mean_squared_error, mean_absolute_error
plt.rcParams['font.sans-serif']=['SimHei'] #用来正常显示中文标签
plt.rcParams['axes.unicode_minus']=False #用来正常显示负号
font2 = {
'weight' : 'normal',
'size' : 10,
}
##数据处理
data=pd.read_excel(r"重庆天气数据.xlsx",sheet_name=0,keep_default_na=True,header=0)#读取数据
data['日期'] = pd.to_datetime(data['日期'],format='%Y%m%d')
data1=data
data1.index = pd.to_datetime(data1['日期'],format='%Y%m%d')
all_dates = pd.date_range(start=data.index.min(), end=data.index.max(), freq='D') # 构造完整日期范围
data1 = data1.reindex(all_dates.date) # 重新索引数据框,补齐缺失日期
##AQI预测
##构建LSTM模型
#提取销量数据列作为特征
dataset =data1.iloc[:, 1].values.reshape(-1, 1)
# 对数据进行归一化处理
scaler = MinMaxScaler(feature_range=(0, 1))
scaled_data = scaler.fit_transform(dataset)
##测试集4周,其余数据分训练集和验证集8:2
##构建训练集、验证集和测试集
week_days=7
time_steps =30
train_scaled_data=scaled_data[:int((len(scaled_data))*0.8)]
test_scaled_data=scaled_data[-(len(scaled_data)-(int((len(scaled_data))*0.8))+time_steps):]
#利用全数据进行模型拟合
def create_dataset(time_series, time_steps=1):
X, y = [], []
for i in range(len(time_series) - time_steps):
X.append(time_series[i:(i + time_steps), 0])
y.append(time_series[i + time_steps, 0])
return np.array(X), np.array(y)
X_train, y_train = create_dataset(train_scaled_data, time_steps)#训练集
X_test, y_test = create_dataset(test_scaled_data, time_steps) #测试集
#构建并训练LSTM模型:
model = Sequential()
model.add(LSTM(units=50, return_sequences=True, input_shape=(time_steps, 1)))
model.add(LSTM(units=50))
model.add(Dense(units=1))
model.compile(optimizer='adam', loss='mean_squared_error')
model.fit(X_train, y_train, epochs=100, batch_size=32)
y_train_pred = model.predict(X_train)
#反标准化
y_train_pred = scaler.inverse_transform(y_train_pred)
y_train = scaler.inverse_transform([y_train])
# 计算评估指标(例如均方根误差、平均绝对误差)
y_train_pred = concatenate(y_train_pred)
y_train = concatenate(y_train)
rmse = np.sqrt(np.mean((y_train - y_train_pred) ** 2))
mae =np.mean(abs(y_train- y_train_pred))
print("RMSE:", rmse)
print("MAE:", mae)
'''
LSTM
RMSE: 22.725637966946724
MAE: 16.627509833900792
'''
##验证集
y_test_pred = model.predict(X_test)
y_test_pred = scaler.inverse_transform(y_test_pred)
y_test = scaler.inverse_transform([y_test])
prediction1 = concatenate(y_test_pred)
# 计算评估指标(例如均方根误差、平均绝对误差)
rmse = np.sqrt(np.mean((y_test - prediction1) ** 2))
mae =np.mean(abs(y_test- prediction1))
print("RMSE:", rmse)
print("MAE:", mae)
'''
RMSE: 23.673333373871603
MAE: 17.643125378762008
'''
##绘图
plt.plot(data1.index[time_steps:int((len(scaled_data))*0.8)],y_train.flatten(), linewidth=2,label='Actual_t')
plt.plot(data1.index[time_steps:int((len(scaled_data))*0.8)],y_train_pred.flatten(), linewidth=2,label='Fitted_t')
plt.plot(data1.index[-(len(scaled_data)-int((len(scaled_data))*0.8)):],y_test.flatten(),linewidth=2, label='Actual_p')
plt.plot(data1.index[-(len(scaled_data)-int((len(scaled_data))*0.8)):],prediction1.flatten(), linewidth=2,label='Fitted_p')
plt.xlim(min(data1.index), max(data1.index))
plt.title('重庆天气AQI数据LSTM建模结果')
plt.xlabel('时间')
plt.ylabel('AQI')
plt.legend()
plt.show()