本文为🔗365天深度学习训练营 中的学习记录博客
原作者:K同学啊|接辅导、项目定制
我的环境:
1.语言:python3.7
2.编译器:pycharm
3.深度学习环境:TensorFlow2.5.0
LSTM介绍:
LSTM(Long Short-Term Memory)是一种循环神经网络(RNN)的变种,专门用于解决长期依赖问题。它在处理序列数据时具有优异的性能。LSTM通过引入门控机制来控制信息的流动,从而有效地捕捉和处理长期依赖关系。它包含了一个称为“cell”的状态单元,以及三个门控单元:输入门、遗忘门和输出门。
在每个时间步骤中,LSTM接收一个输入和前一个时间步骤的隐藏状态,并计算新的隐藏状态和输出。以下是LSTM的工作方式:
- 输入门(Input Gate):决定哪些信息将会被更新并添加到cell中。它根据当前输入和前一个隐藏状态计算一个0到1之间的值,表示对应位置的信息的重要性。
- 遗忘门(Forget Gate):决定哪些旧的记忆应该被遗忘。它通过计算一个0到1之间的值,控制前一个cell状态中哪些信息需要保留下来。
- 更新cell状态:通过将输入门的输出与前一个cell状态相乘,再加上输入门的输出与当前输入的乘积,得到新的cell状态。
- 输出门(Output Gate):决定哪些cell状态的信息将被输出到下一个时间步骤的隐藏状态中。它通过计算一个0到1之间的值,控制cell状态的输出。
LSTM网络的这种结构可以有效地处理长期依赖关系,因为它可以选择性地保留和遗忘信息,并且在计算新的隐藏状态时具有良好的梯度流动特性。
一.前期工作
1、设置gpu、导入数据
import tensorflow as tf
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
gpus = tf.config.list_physical_devices("GPU")
df_1 = pd.read_csv('E:/TF环境/woodpine2.csv')
2、数据可视化
plt.rcParams['savefig.dpi'] = 500 #图像像素
plt.rcParams['figure.dpi'] = 500 #分辨率
fig, ax = plt.subplots(1,3,constrained_layout = True,figsize = (10,4))
sns.lineplot(data = df_1['Tem1'],ax = ax[0])
sns.lineplot(data = df_1['CO 1'],ax = ax[1])
sns.lineplot(data = df_1['Soot 1'],ax = ax[2])
plt.show()
plt.subplots(1,3)函数创建了一个包含1行3列的子图网格,即总共有3个子图。constrained_layout参数设置为True时,会自动调整子图之间的间距,使它们更加紧密地排列,以便不会重叠。figsize参数设置图形窗口的大小为10英寸(宽)× 4英寸(高),单位是英寸。
使用sns.lineplot()函数绘制线图。第一个子图显示了df_1中'Tem1'列的数据,第二个子图显示了df_1中'CO 1'列的数据,第三个子图显示了df_1中'Soot 1'列的数据
二、构建数据集
dataFrame = df_1.iloc[:,1:]
print(dataFrame)
1、设置X、y
width_X = 8
width_y = 1
X = []
y = []
in_start = 0
for _, _ in df_1.iterrows(): #迭代df_1中的每一行数据
in_end = in_start + width_X #提取8行特征
out_end = in_end + width_y #第1行作为预测
if out_end < len(dataFrame):
X_ = np.array(dataFrame.iloc[in_start:in_end, ])
X_ = X_.reshape((len(X_)*3))
y_ = np.array(dataFrame.iloc[in_end :out_end,0])
X.append(X_)
y.append(y_)
in_start += 1
X = np.array(X)
y = np.array(y)
print(X.shape)
print(y.shape)
取前八个时间段的Tem1、CO 1、Soot 1为X,第九个时间段的Tem 1 为y
2、归一化
from sklearn.preprocessing import MinMaxScaler
sc = MinMaxScaler(feature_range = (0,1))
X_scaled = sc.fit_transform(X)
X_scaled = X_scaled.reshape(len(X_scaled),width_X,3)
-
from sklearn.preprocessing import MinMaxScaler
: 导入MinMaxScaler
类,用于对数据进行最小-最大规范化的处理。 -
sc = MinMaxScaler(feature_range=(0,1))
: 创建一个MinMaxScaler
类的实例sc
,并指定特征范围为(0, 1)
,即将数据缩放到0到1的范围内。 -
X_scaled = sc.fit_transform(X)
: 使用fit_transform
方法对输入特征X
进行归一化处理。fit_transform
方法会首先计算数据的最小值和最大值,然后进行缩放处理,使得数据位于指定的特征范围内。 -
X_scaled = X_scaled.reshape(len(X_scaled), width_X, 3)
: 将归一化后的数据重新调整为原始形状。在这里,X_scaled
是一个三维数组,其中第一个维度表示样本数量,第二个维度表示每个样本的宽度,第三个维度表示每个特征的数量。由于之前对数据进行了扁平化处理,所以现在需要将其重新调整为原始形状。width_X
是之前定义的输入特征的宽度,这里将其设置为第二个维度的大小,而3
是由于之前将每个输入特征扩展了三倍,所以这里也需要对应调整为 3。
3、划分数据集
X_train = np.array(X_scaled[:5000]).astype('float64')
y_train = np.array(y[:5000]).astype('float64')
X_test = np.array(X_scaled[5000:]).astype('float64')
y_test = np.array(y[5000:]).astype('float64')
以X_train为例子,将X_scaled中的前5000个元素切片并转换为NumPy数组。然后使用astype('float64')将数组中的数据类型转换为浮点型(float64)。
三、构建模型
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Dense,LSTM
model_lstm = Sequential()
model_lstm.add(LSTM(units = 64, activation='relu',return_sequences=True,
input_shape = (X_train.shape[1],3)))
model_lstm.add(LSTM(units = 64,activation='relu'))
model_lstm.add(Dense(width_y))
units = 64:表示LSTM层中的神经元数量为64
activation='relu':表示LSTM层中的激活函数为ReLu
return_sequences=True:表示LSTM层返回完整的输出序列,而不仅仅是最后一个时间步的输出
input_shape:参数应该被设置为一个元组,其中第一个元素表示时间步数,第二个元素表示特征数
Dense(width_y)中的width_y是一个变量,它表示输出层的神经元数量。
四、模型训练
1、编译
model_lstm.compile(optimizer = tf.keras.optimizers.Adam(1e-3),
loss = 'mean_squared_error')
2、训练
history_lstm = model_lstm.fit(X_train,y_train,
batch_size = 64,
epochs = 40,
validation_data = (X_test,y_test),
validation_freq = 1)
五、评估
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False
plt.figure(figsize = (5,3),dpi = 120)
plt.plot(history_lstm.history['loss'], label = 'LSTM Training Loss')
plt.plot(history_lstm.history['val_loss'], label = 'LSTM Validation Loss')
plt.title('Training and Validation Loss')
plt.legend()
plt.show()
ptedicted_y_lstm = model_lstm.predict(X_test)
y_test_one = [i[0] for i in y_test]
ptedicted_y_lstm_one = [i[0] for i in ptedicted_y_lstm]
plt.figure(figsize = (5,3),dpi = 120)
plt.plot(y_test_one[:1000],color = 'red',label = '真实值')
plt.plot(ptedicted_y_lstm_one[:1000],color = 'blue',label = '预测值')
plt.title('Title')
plt.xlabel('X')
plt.ylabel('y')
plt.legend()
plt.show()
在本次学习中我被Cannot convert a symbolic Tensor (lstm/strided_slice:0) to a numpy array. This error may indicate that you're trying to pass a Tensor to a NumPy call, which is not supported这样的报错所困扰。原因是我的tensorflow版本所对应的nump以及numpy-base版本没有对应起来导致报错。重装版本即可正常运行。