找回密码
 会员注册
查看: 25|回复: 0

模型实现基于Python的LSTM网络实现单特征预测回归任务(TensorFlow)

[复制链接]

2万

主题

0

回帖

6万

积分

超级版主

积分
64098
发表于 2024-9-12 16:30:44 | 显示全部楼层 |阅读模式
单特征:数据集中只包含2列,时间列+价格列,仅利用价格来预测价格目录一、数据集二、任务目标三、代码实现、1、创建配置类,将LSTM的各个超参数声明为变量,便于后续使用2、从本地路径中读取数据文件3、划分数据集4、数据归一化 5、创建时间序列数据(1)训练集(2)测试集6、调整数据形状以适应LSTM的输入要求7、定义LSTM网络(1)创建顺序模型实例(2)添加LSTM层(3)添加全连接层8、编译LSTM模型9、训练模型10、模型预测11、数据反归一化12、绘制图像一、数据集自建数据集--【load.xlsx】。包含2列:date列(时间列,记录2022年6月2日起始至2023年12月31日为止,日度数据)price列(价格列,记录日度数据对应的某品牌衣服的价格,浮点数)二、任务目标实现基于时间序列的单特征价格预测三、代码实现、1、创建配置类,将LSTM的各个超参数声明为变量,便于后续使用timestep:时间步长,滑动窗口大小feature_size:每个步长对应的特征数量,这里只使用1维,即每天的价格数据batch_size:批次大小,即一次性送入多少个数据(一时间步长为单位)进行训练output_size:单输出任务,输出层为1,预测未来1天的价格hidden_size:隐藏层大小,即神经元个数num_layers:神经网络的层数learning_rate:学习率epochs:迭代轮数,即总共要让神经网络训练多少轮,全部数据训练一遍成为一轮best_loss:记录损失activation='relu':定义激活函数使用reluclassConfig():timestep=7#时间步长,滑动窗口大小feature_size=1#每个步长对应的特征数量,这里只使用1维,每天的价格数据batch_size=1#批次大小output_size=1#单输出任务,输出层为1,预测未来1天的价格hidden_size=128#隐藏层大小num_layers=1#lstm的层数learning_rate=0.0001#学习率epochs=500#迭代轮数model_name='lstm'#模型名best_loss=0#记录损失activation='relu'#定义激活函数config=Config()2、从本地路径中读取数据文件read_excel函数读取Excel文件(read_csv用来读取csv文件),读取为DataFrame对象index_col='date'将'date'列设置为DataFrame的索引.values属性获取price列的值,pandas会将对应数据转换为NumPy类型的一维数组#字符串前的r表示一个"原始字符串",rawstring#文件路径中包含多个反斜杠。如果我们不使用原始字符串(即不使用r前缀),那么Python会尝试解析\U、\N等作为转义序列,这会导致错误data=pd.read_excel(r'E:\load.xlsx',index_col='date')#print(data)prices=data['price'].values#print(prices)打印data:打印prices:3、划分数据集按照9:1的比例将数据划分为训练集和测试集train_test_split是一个常用于数据集分割的函数,通常在机器学习中用于将数据分为训练集和测试集shuffle参数的作用是控制数据在分割前是否需要随机打乱当设置为True时,数据会被随机打乱,然后按照指定的比例分割成训练集和测试集当shuffle=False时,数据将按照它们原有的顺序直接分割。这意味着数据集中的元素将保持它们在原始数据集中的相对顺序在时间序列数据的情况下,这通常是必须的,因为时间序列数据具有时间依赖性,如果随机打乱,会破坏数据的时间顺序,从而影响模型学习到的时间依赖关系train,test=train_test_split(prices,test_size=0.1,shuffle=False)'运行运行 打印训练集train的部分数据(一维数组):4、数据归一化归一化:将原始数据的大小转化为[0,1]之间,采用最大-最小值归一化数值过大,造成神经网络计算缓慢在多特征任务中,存在多个特征属性,但神经网络会认为数值越小的,影响越小。所以可能关键属性A的值很小,不重要属性B的值却很大,造成神经网络的混淆scikit-learn的转换器通常期望输入是二维的,其中每一行代表一个样本,每一列代表一个特征prices.reshape(-1,1) 用于确保prices是一个二维数组,即使它只有一个特征列-1的意思是让NumPy 自动计算该轴上的元素数量,以保持原始数据的元素总数不变fit方法计算了数据中每个特征的最小值和最大值,这些值将被用于缩放transform方法使用这些统计数据来实际缩放数据,将其转换到[0,1]范围内在训练集上使用fit_transform拟合缩放器,然后在测试集上使用transform以确保使用相同的缩放参数transform方法使用从训练数据中学习到的最小值和最大值(从训练数据中得到的相同缩放参数)来转换测试数据,确保测试数据使用相同的缩放参数这样做的目的是保持训练集和测试集的一致性,这样模型在预测时使用的输入数据与训练时看到的输入数据具有相同的尺度避免数据泄露:如果在测试集上使用fit方法,那么测试集的数据将影响模型的训练过程,这可能导致模型过度拟合到测试集,从而影响模型的泛化能力#确保训练集和测试集的形状是二维数组train=train.reshape(-1,1)test=test.reshape(-1,1)scaler=MinMaxScaler(feature_range=(0,1))train_scaled=scaler.fit_transform(train)#对训练数据进行拟合和转换test_scaled=scaler.transform(test)#使用同样的缩放参数转换测试数据#print(train_prices)打印归一化后的训练集价格数据(二维数组): 5、创建时间序列数据(1)训练集通过滑动窗口移动获取数据,时间步内数据作为特征数据,时间步外1个数据作为标签数据通过序列的切片实现特征和标签的划分通过np.array将数据转化为NumPy数组#创建时间序列数据X_train,y_train=[],[]foriinrange(len(train_scaled)-config.timestep):#从当前索引i开始,取sequence_length个连续的价格数据点,并将其作为特征添加到列表X_train中。X_train.append(train_scaled[i:i+config.timestep])#将紧接着这sequence_length个时间点的下一个价格数据点作为目标添加到列表y_train中。y_train.append(train_scaled[i+config.timestep])X_train=np.array(X_train)print(X_train)y_train=np.array(y_train)print(y_train)打印特征数据: 三维数组,X_train是由多个二维数组(即多个时间步长的数据)组成的,加之本身是一个列表每次迭代都会从train_scaled 中取出一个长度为config.timestep的连续子序列,并将其添加到X列表中由于train_scaled本身是一个二维数组,所以每次取出的子序列也是一个二维数组,形状大致为[config.timestep,features]当多个这样的二维数组被添加到X列表中时,X_train就变成了一个列表的列表,其中每个内部列表都是一个二维数组它的形状将是[n_samples-config.timestep,config.timestep,features],这是一个三维数组打印标签数据:二维数组,y_train 是由单个数据点(即单个时间步长的数据)组成的,所以它保持为二维数组从train_scaled 中取出一个单独的数据点(即一个二维数组中的一行),并将其添加到y列表中y列表中的每个元素都是一个一维数组(或可以看作是一个具有多个特征的向量)它的形状将是[n_samples-config.timestep,features],这仍然是一个二维数组(2)测试集测试集同训练集的设置一样X_test,y_test=[],[]foriinrange(len(test_scaled)-config.timestep):X_test.append(test_scaled[i:i+config.timestep])y_test.append(test_scaled[i+config.timestep])X_test,y_test=np.array(X_test),np.array(y_test)6、调整数据形状以适应LSTM的输入要求将时间序列数据从原始的形状转换成一个三维数组,这是LSTM网络所期望的输入格式,(样本数量,时间步长,特征数量)第一个维度(X_train.shape[0]或X_test.shape[0]):表示样本的数量,即有多少个时间序列第二个维度(X_train.shape[1]或X_test.shape[1]):表示每个时间序列中的时间步长数量,即序列的长度第三个维度(config.feature_size):表示每个时间步长中的特征数量shape属性是一个NumPy数组或PandasDataFrame等数据结构的方法,它返回数据的形状,即各个维度的大小X_train.shape[0]或X_test.shape[0]:第一个元素表示数组的第一维大小,通常对应于样本的数量(即有多少个时间序列数据点)X_train.shape[1]或X_test.shape[1]:第二个元素表示数组的第二维大小,通常对应于每个时间序列中的时间步长数量(即每个序列包含多少个时间点)X_train=X_train.reshape((X_train.shape[0],X_train.shape[1],config.feature_size))X_test=X_test.reshape((X_test.shape[0],X_test.shape[1],config.feature_size))打印测试集特征X_train数据:7、定义LSTM网络(1)创建顺序模型实例model=Sequential()(2)添加LSTM层LSTM:这是Keras中提供的LSTM层的类。通过调用这个类,创建一个LSTM层activation=config.activation:这设置了LSTM层中使用的激活函数units=config.hidden_size:这设置了LSTM层中的隐藏单元数量input_shape=(config.timestep,config.feature_size):这定义了输入数据的形状,是一个元组告诉模型,输入数据应该是一个形状为[batch_size,config.timestep,config.feature_size]的三维其中batch_size是批次中样本的数量,它在模型训练时会自动确定(根据你传递给模型的批次数据大小)model.add(LSTM(activation=config.activation,units=config.hidden_size,input_shape=(config.timestep,config.feature_size))) LSTM层的输出是一个三维张量,其形状通常为(seq_len,batch_size,num_directions*hidden_size)seq_len表示序列长度,即时间序列展开的步数batch_size表示数据批次的大小,即一次性输入到LSTM层的数据样本数量num_directions*hidden_size表示隐藏层的输出特征维度对于单向LSTM,num_directions为1对于双向LSTM,num_directions为2。hidden_size则是隐藏层节点数,即LSTM单元中隐藏状态的维度含义:LSTM层的输出包含了每个时间步的隐藏状态(3)添加全连接层Dense:是Keras中用于创建全连接层的类,也就是每个输入节点与输出节点之间都连接有一个权重config.output_size:指定了该全连接层的输出单元数量model.add(Dense(config.output_size))由于此例中,全连接层的大小为1,因此LSTM层输出的三维张量在经过全连接层后将被压缩成一个二维张量(batch_size,1)这样的形状8、编译LSTM模型model.compile():这个方法是Keras模型的一个函数,用于配置模型训练前的参数optimizer='adam':这里指定了使用Adam优化器来训练模型loss='mean_squared_error':这里指定了损失函数为均方误差(MeanSquaredError,MSE)model.compile(optimizer='adam',loss='mean_squared_error')9、训练模型model.fit():是Keras模型的一个函数,用于训练模型。它将根据提供的训练数据X_train和对应的标签y_train,通过多次迭代(epochs)来训练模型。x=X_train:指定了训练数据的输入y=y_train:指定了训练数据的标签(或目标值)epochs=config.epochs:指定了训练过程中数据集的完整遍历次数。batch_size=config.batch_size:指定了每次更新模型时使用的样本数verbose=2:控制训练过程中的日志输出。verbose=2表示每个epoch输出一行日志,显示训练过程中的损失值和评估指标(如果在编译时指定了评估指标)history对象是一个记录训练过程中信息的字典,包含了训练过程中的损失值和评估指标(如果有的话)history=model.fit(x=X_train,y=y_train,epochs=config.epochs,batch_size=config.batch_size,verbose=2)10、模型预测model.predict():是Keras模型的一个函数,它根据提供的输入数据,给出模型对于这些数据的预测结果predictions=model.predict(X_test)11、数据反归一化当模型训练完成后并进行预测时,预测出的值会是缩放后的值(即按照训练数据缩放的比例)为了得到原始的比例或范围,需要使用缩放器的inverse_transform方法来将这些缩放后的值转换回原始的比例或范围这里的关键点是:归一化时需要fit方法来确定缩放参数,而反归一化时,由于已经知道了这些参数,只需要使用inverse_transform方法来逆转归一化过程。无论是训练集、测试集还是预测值,它们都使用相同的inverse_transform方法,因为它们都需要从相同的[0,1]范围转换回原始的范围反归一化这里没有使用fit方法,因为反归一化不需要重新计算任何参数,它只是逆转之前归一化的过程y_test_true_unnormalized=scaler.inverse_transform(y_test)y_test_preds_unnormalized=scaler.inverse_transform(predictions)确保模型的预测结果和真实的测试集标签都在同一个比例或范围内,从而可以准确地评估模型的性能,并以更直观、更易于理解的方式呈现预测结果12、绘制图像#设置图形的大小为10x5单位plt.figure(figsize=(10,5))#绘制真实的测试集标签,使用圆圈('o')作为标记,并命名为'TrueValues'plt.plot(y_test_true_unnormalized,label='TrueValues',marker='o')#绘制模型的预测值,使用叉号('x')作为标记,并命名为'Predictions'plt.plot(y_test_preds_unnormalized,label='Predictions',marker='x')#设置图形的plt.title('ComparisonofTrueValuesandPredictions')#设置x轴的标签plt.xlabel('TimeSteps')#设置y轴的标签plt.ylabel('Prices')#显示图例plt.legend()#显示图形plt.show()
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 会员注册

本版积分规则

QQ|手机版|心飞设计-版权所有:微度网络信息技术服务中心 ( 鲁ICP备17032091号-12 )|网站地图

GMT+8, 2024-12-26 12:18 , Processed in 0.819860 second(s), 25 queries .

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表