大家好,这里是七七,今天来介绍的是LSTM模型实现代码。
import pandas as pd
import numpy as np
from keras.models import Sequential
from keras.layers import LSTM,Dense
from sklearn.preprocessing import MinMaxScaler
from sklearn.metrics import mean_squared_error,mean_absolute_error,r2_score
from math import sqrt
import matplotlib.pyplot as plt
plt.rcParams['font.sans-serif'] = [u'simHei']
plt.rcParams['axes.unicode_minus'] = False
file_path="./out/result.csv"
df=pd.read_csv(file_path)
print(df.head(5))
df['销售日期']=pd.to_datetime(df['销售日期'])
df.set_index('销售日期',inplace=True)
list_test=['花叶类','花菜类','水生根茎类','茄类','辣椒类','食用菌']
i=4
print(i)
df = df[df['品类'] == list_test[i]]
#数据归一化
scaler=MinMaxScaler(feature_range=(0,1))
scaled_data=scaler.fit_transform(df['批发价格(元/千克)'].values.reshape(-1,1))
train_size=int(len(scaled_data)*1)
train=scaled_data[0:train_size,:]
#转换数据格式为符合LSTM输入要求
def create_dataset(dataset,look_back=1):
dataX,dataY=[],[]
for i in range(len(dataset)-look_back-1):
a=dataset[i:(i+look_back),0]
dataX.append(a)
dataY.append(dataset[i+look_back,0])
return np.array(dataX),np.array(dataY)
look_back=30
trainX,trainY=create_dataset(train,look_back)
pre_X=train[-30:]
pre_X=[item for sublist in pre_X for item in sublist]
pre_X=np.array([[pre_X]])
#构建LSTM模型
model=Sequential()
model.add(LSTM(6,input_shape=(1,look_back)))
model.add(Dense(7))
model.compile(loss='mean_squared_error',optimizer='adam')
history=model.fit(trainX,trainY,epochs=50,batch_size=1,verbose=2)
trainPredict=model.predict(trainX)
trainPredict=scaler.inverse_transform(trainPredict)
trainY=scaler.inverse_transform([trainY])
pre_Y=model.predict(pre_X)
pre_Y=scaler.inverse_transform(pre_Y)
#计算R方、MSE、RMES、和MAE
mse=mean_squared_error(trainY[0],trainPredict[:,0])
rmse=sqrt(mse)
mae=mean_absolute_error(trainY[0],trainPredict[:,0])
r2=r2_score(trainY[0],trainPredict[:,0])
print(f'R2:{r2}, MSE:{mse}, RMSE:{rmse}, MAE:{mae}')
print(f"预测未来七天{list_test[i]}的销量:{pre_Y[0,:]}")
#创建一个figure和axes对象
fig,ax=plt.subplots(figsize=(12,6))
ax.plot(trainY[0],label=f'{list_test[i]}实际进价')
ax.plot(trainPredict[:,0],label=f'{list_test[i]}实际进价')
ax.set_xlabel('Time')
ax.set_ylabel('Value')
ax.legend()
ax.set_title(f'{list_test[i]}LSTM预测结果图')
ax.grid()
fig.savefig(f"./rst2/{list_test[i]}Loss.png")
fig.show()
#创建一个新的figure和axes对象
fig,ax=plt.subplots(figsize=(12,6))
loss_history=history.history['loss']
ax.plot(loss_history,label='Loss')
ax.set_xlabel('Epoch')
ax.set_ylabel('Loss')
ax.legend()
ax.set_title('Loss Over Training Epochs')
ax.grid()
fig.savefig(f"./rst2/{list_test[i]}LSTM预测结果图.png")
fig.show()
from keras.models import Sequential
Keras 是一个用于构建深度学习模型的高级库。
Sequential
?类是 Keras 中最简单的一种模型类型,它允许我们按顺序堆叠各种网络层。通过将层实例添加到?Sequential
?对象中,我们可以构建基本的前馈神经网络模型。
scaler=MinMaxScaler(feature_range=(0,1))
scaled_data=scaler.fit_transform(df['批发价格(元/千克)'].values.reshape(-1,1))
`fit_transform`是一个数据预处理的方法,常用于机器学习算法中的数据准备阶段。
在使用预处理方法对数据进行转换之前,需要对预处理器进行拟合操作,以便它可以学习数据的特征。`fit_transform`方法是`fit`和`transform`方法的集合,用于将模型拟合并应用于数据转换的一步。
具体地说,在使用 `fit_transform` 进行数据预处理时,它会在一步中对数据进行拟合和转换,即先把算法应用到数据集的训练集上,从而确定算法所需的参数(均值、标准差等),然后将这些参数用于训练集和测试集或新的数据集上,以完成数据标准化或归一化等操作。
需要注意的是,`fit_transform` 只能应用于训练集数据,而不能应用于测试集数据。因此,在机器学习中,通常会先对训练集进行拟合,然后再用这些学到的参数对测试集进行转换。这样可以确保测试数据集与训练数据集的转换方式相同,从而保持模型性能的一致性。
`values.reshape(-1,1)` 是一个 NumPy 数组的方法,用于将数组转换为指定形状的二维数组。
在这个特定的代码中,`values` 是一个一维数组(或矩阵),`.reshape(-1,1)` 的作用是将这个一维数组转换为一个列向量,也就是将它的形状从 `(n,)` 变为 `(n,1)`,其中 `n` 是原始数组的长度。
具体而言,`.reshape(-1,1)` 的 `-1` 参数表示行数自动计算,而 `1` 表示列数为 1。通过使用这个方法,将一维数组转换为列向量,可以适应某些机器学习算法和库的需求,同时也可以方便地进行数据处理和操作。
举例来说,如果原始数组的长度为 10,那么通过 `.reshape(-1,1)` 就可以将它转换为一个 10 行 1 列的二维数组,其中每一行都包含一个原始数组的元素。
总结起来,`values.reshape(-1,1)` 的作用是将一维数组转换为列向量的二维数组,其中行数由数据自动计算,而列数固定为 1。
pre_X=[item for sublist in pre_X for item in sublist]
这段代码是一个列表推导式,用于将嵌套的二维列表展开为一个一维列表。
首先,pre_X
?是一个嵌套的二维列表,包含有多个子列表。每个子列表可能包含不同数量的元素。
列表推导式?[item for sublist in pre_X for item in sublist]
?的作用是将?pre_X
?中每个子列表的所有元素依次展开,并将它们合并到一个新的列表中。具体来说,它的语法如下:
[item for sublist in pre_X for item in sublist]?
其中,item
?是变量名,表示子列表中的每个元素;sublist
?是变量名,表示原始列表?pre_X
?中的每个子列表。循环的顺序是按照代码中的从左到右的顺序。
因此,列表推导式将遍历?pre_X
?中的每个子列表,对于每个子列表,将子列表中的所有元素添加到一个新列表中。最终得到的是一个展平后的一维列表,其中包含了所有子列表中的元素,顺序与子列表在原始列表中出现的顺序相同。
例如,以下代码将一个包含多个子列表的列表?pre_X
?展开为一个一维列表?flat_list
:
pre_X = [[1, 2], [3], [4, 5, 6]]
flat_list = [item for sublist in pre_X for item in sublist]
print(flat_list)
# Output: [1, 2, 3, 4, 5, 6]
需要注意的是,展开后得到的一维列表与原始列表的元素顺序是一致的,但是子列表之间的相对顺序已经改变了。这是因为,对于展开后得到的一维列表来说,元素之间的次序是按照子列表的出现顺序排列的。
#构建LSTM模型
model=Sequential()
model.add(LSTM(6,input_shape=(1,look_back)))
model.add(Dense(7))
model.compile(loss='mean_squared_error',optimizer='adam')
history=model.fit(trainX,trainY,epochs=50,batch_size=1,verbose=2)
trainPredict=model.predict(trainX)
trainPredict=scaler.inverse_transform(trainPredict)
trainY=scaler.inverse_transform([trainY])
pre_Y=model.predict(pre_X)
pre_Y=scaler.inverse_transform(pre_Y)
这段代码是用于构建、训练和预测基于LSTM的模型。
首先,通过`Sequential()`函数创建了一个序列模型。序列模型是一种简单的线性堆叠模型,我们可以通过添加不同的层来构建模型。
接下来,使用`model.add(LSTM(6, input_shape=(1, look_back)))`添加了一个LSTM层。LSTM是一种递归神经网络结构,适用于处理具有时间依赖性的序列数据。在这里,输入数据的形状是`(1, look_back)`,表示每个样本有1个时间步长(每个数据点作为一个时间步长)和`look_back`个特征。
然后,使用`model.add(Dense(7))`添加了一个全连接层。这层有7个神经元,用于将LSTM层的输出映射到预测值的输出维度。
接下来,通过`model.compile()`函数编译了模型,指定了损失函数为均方误差(mean squared error)和优化器为Adam。
然后,通过`model.fit()`函数对模型进行训练。`trainX`是训练集的输入特征,`trainY`是训练集的目标值。`epochs`参数表示迭代的次数,`batch_size`表示每次迭代中使用的样本数量,`verbose=2`表示显示训练过程的详细信息。
接下来,使用训练好的模型对训练集进行预测,通过`model.predict()`函数得到训练集的预测结果`trainPredict`。然后,使用`scaler.inverse_transform()`函数将预测结果转换回原始数据的规模。
最后,使用训练好的模型对`pre_X`进行预测,得到预测结果`pre_Y`。同样,使用`scaler.inverse_transform()`函数将预测结果转换回原始数据的规模。
值得注意的是,上述代码中缺少了数据的预处理步骤,如数据的归一化、窗口处理等。在进行模型构建和训练之前,一般需要先对数据进行预处理以符合模型的输入要求,并确保训练过程的稳定性和效果。请根据实际情况进行适当的数据处理和模型调整。
model.add(LSTM(6,input_shape=(1,look_back)))
这段代码是用于在模型中添加LSTM层。具体来说,model.add(LSTM(6, input_shape=(1, look_back)))
将一个LSTM层添加到模型中。
LSTM层是一种递归神经网络层,适用于处理具有时间依赖性的序列数据。参数6
表示LSTM层中的神经元数量,这是一个可以调整的超参数,用于控制模型的复杂度和表示能力。input_shape=(1, look_back)
表示每个样本有1个时间步长(每个数据点作为一个时间步长)和look_back
个特征。
`Dense`是Keras中的一个层类型,也被称为全连接层或密集层。Dense层将输入数据连接到下一层的每个神经元,它是一种最常见的神经网络层之一。
在Dense层中,每个输入神经元都与每个输出神经元相连,形成一个完全连接的结构。每个连接上都有一个权重,模型将通过训练过程来学习和优化这些权重。
在深度学习模型中,Dense层通常用于将高维的输入数据转换为更低维度的表示或进行分类、回归等任务。每个神经元都会计算其输入和对应的权重的加权和,并通过激活函数对结果进行非线性变换。
在代码中,使用`model.add(Dense(7))`添加了一个Dense层,该层包含了7个神经元。这个Dense层通常用于将LSTM层的输出映射到预测结果的输出维度,以完成具体任务的预测和推断。
model.compile(loss='mean_squared_error',optimizer='adam')
`model.compile()`函数用于配置模型的训练方法,其中包括损失函数、优化器和性能指标等。
`loss='mean_squared_error'`指定训练过程中使用的损失函数是均方误差(mean squared error),也称为MSE。
`optimizer='adam'`指定训练过程中使用的优化器为Adam。Adam是一种常用的随机梯度下降优化算法,它结合了梯度下降和自适应学习率的优点,在实践中表现较好。Adam根据动量和梯度二阶矩估计来自适应地调整每个参数的学习率,从而加速收敛并提高模型的泛化性能。
history=model.fit(trainX,trainY,epochs=50,batch_size=1,verbose=2)
这段代码使用`model.fit()`函数来训练模型。下面是对参数的解释:
- `trainX`:训练数据的输入特征,是一个二维数组,shape为`(样本数量, 特征数量)`。
- `trainY`:训练数据的标签,是一个一维数组或二维数组,shape取决于问题的性质。
- `epochs=50`:训练迭代的轮数,即将整个训练数据集输入模型并更新参数的次数。
- `batch_size=1`:批量大小,表示每次更新模型参数时使用的训练样本数量。
- `verbose=2`:日志输出模式,其中`0`表示不输出日志,`1`表示输出进度条,`2`表示每个epoch输出一行日志。
`model.fit()`函数将根据指定的训练数据和参数进行模型训练,返回一个`History`对象。该对象包含了训练过程中的损失和指标的记录,可以用于后续的可视化和评估。
在训练过程中,模型会根据训练数据逐渐优化参数,通过反向传播和梯度下降算法,调整模型的权重和偏置,以使损失函数最小化。训练的轮数(epochs)和批量大小(batch_size)是需要根据具体问题和数据集的大小进行调整的超参数,可以通过尝试不同的值来找到最佳的训练效果。
代码5