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

news/2024/5/20 18:09:55

单特征:数据集中只包含2列,时间列+价格列,仅利用价格来预测价格

目录

一、数据集

二、任务目标

三、代码实现

1、从本地路径中读取数据文件

2、数据归一化

3、创建配置类,将LSTM的各个超参数声明为变量,便于后续使用

4、创建时间序列数据

5、划分数据集

6、定义LSTM网络

(1)创建顺序模型实例

(2)添加LSTM层

(3)添加全连接层

7、编译LSTM模型

8、训练模型

9、模型预测

10、数据反归一化

11、绘制图像

12、完整版代码


一、数据集

自建数据集--【load.xlsx】。包含2列:

  • date列时间列,记录2022年6月2日起始至2023年12月31日为止,日度数据
  • price列价格列,记录日度数据对应的某品牌衣服的价格,浮点数)

二、任务目标

实现基于时间序列的单特征价格预测

三、代码实现

1、从本地路径中读取数据文件

  • read_excel函数读取Excel文件(read_csv用来读取csv文件),读取为DataFrame对象
  • index_col='date''date'列设置为DataFrame的索引
  • .values属性获取price列的值,pandas会将对应数据转换为NumPy数组
# 字符串前的r表示一个"原始字符串",raw string
# 文件路径中包含多个反斜杠。如果我们不使用原始字符串(即不使用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:

2、数据归一化

  • 归一化:将原始数据的大小转化为[0,1]之间,采用最大-最小值归一化
    • 数值过大,造成神经网络计算缓慢
    • 在多特征任务中,存在多个特征属性,但神经网络会认为数值越小的,影响越小。所以可能关键属性A的值很小,不重要属性B的值却很大,造成神经网络的混淆
  • scikit-learn的转换器通常期望输入是二维的,其中每一行代表一个样本,每一列代表一个特征
    • prices.reshape(-1, 1) 用于确保 prices 是一个二维数组,即使它只有一个特征列
    • -1的意思是让 NumPy 自动计算该轴上的元素数量,以保持原始数据的元素总数不变
    • fit方法计算了数据中每个特征的最小值和最大值,这些值将被用于缩放
    • transform方法使用这些统计信息来实际缩放数据,将其转换到 [0, 1] 范围内
scaler = MinMaxScaler(feature_range=(0, 1))
scaled_prices = scaler.fit_transform(prices.reshape(-1, 1)) # 二维数组
# print(scaled_prices)

打印归一化后的价格数据:

3、创建配置类,将LSTM的各个超参数声明为变量,便于后续使用

  • timestep:时间步长,滑动窗口大小
  • feature_size:每个步长对应的特征数量,这里只使用1维,即每天的价格数据
  • batch_size:批次大小,即一次性送入多少个数据(一时间步长为单位)进行训练
  • output_size:单输出任务,输出层为1,预测未来1天的价格
  • hidden_size:隐藏层大小,即神经元个数
  • num_layers:神经网络的层数
  • learning_rate:学习率
  • epochs:迭代轮数,即总共要让神经网络训练多少轮,全部数据训练一遍成为一轮
  • best_loss:记录损失
  • activation = 'relu':定义激活函数使用relu
class Config():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()

4、创建时间序列数据

  • 通过滑动窗口移动获取数据,时间步内数据作为特征数据,时间步外1个数据作为标签数据
  • 通过序列的切片实现特征和标签的划分
  • 通过np.array将数据转化为NumPy数组

# 创建时间序列数据
X, y = [], []
for i in range(len(scaled_prices) - config.timestep):# 从当前索引i开始,取sequence_length个连续的价格数据点,并将其作为特征添加到列表 X 中。X.append(scaled_prices[i: i + config.timestep])# 将紧接着这sequence_length个时间点的下一个价格数据点作为目标添加到列表y中。y.append(scaled_prices[i + config.timestep])
X = np.array(X)
print(X)
y = np.array(y)
print(y)

打印特征数据: 

  • 三维数组,X 是由多个二维数组(即多个时间步长的数据)组成的,加之本身是一个列表
  • 每次迭代都会从 scaled_prices 中取出一个长度为 config.timestep 的连续子序列,并将其添加到 X 列表中
  • 由于 scaled_prices 本身是一个二维数组,所以每次取出的子序列也是一个二维数组,形状大致为 [config.timestep, features]
  • 当多个这样的二维数组被添加到 X 列表中时,X 就变成了一个列表的列表,其中每个内部列表都是一个二维数组
  • 它的形状将是 [n_samples - config.timestep, config.timestep, features],这是一个三维数组

打印标签数据:

  • 二维数组,y 是由单个数据点(即单个时间步长的数据)组成的,所以它保持为二维数组
  • 从 scaled_prices 中取出一个单独的数据点(即一个二维数组中的一行),并将其添加到 y 列表中
  • y 列表中的每个元素都是一个一维数组(或可以看作是一个具有多个特征的向量)
  • 它的形状将是 [n_samples - config.timestep, features],这仍然是一个二维数组

5、划分数据集

  • 按照9:1的比例划分训练集和测试集
  • train_test_split:是sklearn.model_selection模块中的一个函数,用于将数据集随机划分为训练集和测试集
  • shuffle=False:表示在划分数据之前不进行随机打乱,意味着数据会按照其原始顺序进行划分
  • 因为时间序列数据具有时序性,用过去时间数据预测新时间数据,要保证时间有序
  • 测试数据为时间序列的末尾数据
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.1, shuffle=False)

6、定义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)这样的形状

7、编译LSTM模型

  • model.compile():这个方法是Keras模型的一个函数,用于配置模型训练前的参数
  • optimizer='adam':这里指定了使用Adam优化器来训练模型
  • loss='mean_squared_error':这里指定了损失函数为均方误差(Mean Squared Error, MSE)
model.compile(optimizer='adam', loss='mean_squared_error')

8、训练模型

  • 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)

9、模型预测

  • model.predict():是 Keras 模型的一个函数,它根据提供的输入数据,给出模型对于这些数据的预测结果
predictions = model.predict(X_test)

10、数据反归一化

  • 当模型训练完成后并进行预测时,预测出的值会是缩放后的值(即按照训练数据缩放的比例)
  • 为了得到原始的比例或范围,需要使用缩放器的 inverse_transform 方法来将这些缩放后的值转换回原始的比例或范围
y_test_true_unnormalized = scaler.inverse_transform(y_test)
y_test_preds_unnormalized = scaler.inverse_transform(predictions)
  • 确保模型的预测结果和真实的测试集标签都在同一个比例或范围内,从而可以准确地评估模型的性能,并以更直观、更易于理解的方式呈现预测结果

11、绘制图像

# 设置图形的大小为10x5单位
plt.figure(figsize=(10, 5))# 绘制真实的测试集标签,使用圆圈('o')作为标记,并命名为'True Values' 
plt.plot(y_test_true_unnormalized, label='True Values', marker='o')# 绘制模型的预测值,使用叉号('x')作为标记,并命名为'Predictions' 
plt.plot(y_test_preds_unnormalized, label='Predictions', marker='x')# 设置图形的标题
plt.title('Comparison of True Values and Predictions')# 设置x轴的标签
plt.xlabel('Time Steps')# 设置y轴的标签
plt.ylabel('Prices')# 显示图例 
plt.legend()# 显示图形
plt.show()

12、完整版代码

import pandas as pd
import numpy as np
from sklearn.metrics import r2_score
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import MinMaxScaler
from matplotlib import pyplot as plt
from keras.models import Sequential
from keras.layers import LSTM, Dense, Dropoutclass Config():timestep = 7hidden_size = 128batch_size = 1output_size = 1epochs = 500feature_size = 1activation = 'relu'
config = Config()# dataframe对象
qy_data = pd.read_excel(r'E:\load.xlsx', index_col='date')
# print(qy_data)
# numpy数组 一维
prices = qy_data['price'].values
# print(prices)scaler = MinMaxScaler()
# 归一化后变成二维数组
scaled_prices = scaler.fit_transform(prices.reshape(-1, 1))
# print(scaled_prices)# Create time series data
X, y = [], []
for i in range(len(scaled_prices) - config.timestep):X.append(scaled_prices[i: i + config.timestep])y.append(scaled_prices[i + config.timestep])
X = np.array(X)
# print(X)
y = np.array(y)
# print(y)# Train-test split
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.1, shuffle=False)# Define the LSTM mode
model = Sequential()
model.add(LSTM(activation=config.activation, units=config.hidden_size, input_shape=(config.timestep, config.feature_size)))
model.add(Dense(config.output_size))# Compile the model
# adam默认学习率是0.01
model.compile(optimizer='adam', loss='mean_squared_error')model.save('LSTM.h5')# Train the model
history = model.fit(x=X_train, y=y_train, epochs=config.epochs, batch_size=config.batch_size, verbose=2)# Predictions
predictions = model.predict(X_test)# Inverse transform predictions and true values
y_test_true_unnormalized = scaler.inverse_transform(y_test)
y_test_preds_unnormalized = scaler.inverse_transform(predictions)# Plot true values and predictions
plt.figure(figsize=(10, 5))
plt.plot(y_test_true_unnormalized, label='True Values', marker='o')
plt.plot(y_test_preds_unnormalized, label='Predictions', marker='x')
plt.title('Comparison of True Values and Predictions')
plt.xlabel('Time Steps')
plt.ylabel('Prices')
plt.legend()
plt.show()

http://www.mrgr.cn/p/27321718

相关文章

如何让加快OpenHarmony编译速度?

OpenHarmony 有两种编译方式,一种是通过 hb 工具编译,一种是通过 build.sh 脚本编译。本文笔者将提升 build.sh 方式编译速度的方法整理如下: 因为笔者只用 build.sh 脚本编译,没用过 hb 工具,好像下面的选项也可以用于…

容灾演练双月报|郑大一附院数据级容灾演练切换

了解更多灾备行业动态 守护数字化时代业务连续 目录 CONTENTS 01 灾备法规政策 02 热点安全事件 03 容灾演练典型案例 01 灾备法规政策 3月19日,工信部发布《工业和信息化部办公厅关于做好2024年信息通信业安全生产和网络运行安全工作的通知》。明确提出“…

llama.cpp制作GGUF文件及使用

llama.cpp的介绍 llama.cpp是一个开源项目,由Georgi Gerganov开发,旨在提供一个高性能的推理工具,专为在各种硬件平台上运行大型语言模型(LLMs)而设计。这个项目的重点在于优化推理过程中的性能问题,特别是…

我们的小程序每天早上都白屏,真相是。。。

大家好,我是程序员鱼皮。最近我们在内测一款面试刷题小程序,没错,就是之前倒下的 “面试鸭”! 在我们的内测交流群中,每天早上都会有同学反馈:打开小程序空白,没任何内容且登录不上。 然后过了…

开源离线AI笔记应用

前言 Reor 是一款人工智能驱动的桌面笔记应用程序,它能自动链接相关笔记、回答笔记中的问题并提供语义搜索。所有内容都存储在本地,支持 Windows、Linux 和 MacOS。Reor 站在 Ollama、Transformers.js 和 LanceDB 等巨头的肩膀上,使 LLM 和嵌…

iceoryx源码阅读(二)——共享内存管理

目录1 共享内存模型2 获取共享内存2.1 MemoryManager::getChunk2.2 MemPool::getChunk3 释放共享内存3.1 SharedChunk::freeChunk3.2 MemPool::freeChunk4 总结 基于共享内存通信的核心在于共享内存的管理,包括共享内存的分配、释放。 1 共享内存模型 iceoryx先将整块共享内存…

iceoryx源码阅读(一)——全局概览

一、什么是iceoryx iceoryx是一套基于共享内存实现的进程间通信组件。 二、源码结构 iceoryx源码包括若干工程,整理如下表所示:下图展示了主要项目之间的依赖(FROM:iceoryx(冰羚)-Architecture):三、iceoryx应用程序结构 iceoryx应用程序有三类进程,分别为Publisher、Su…

Linux字符设备驱动(一) - 框架

字符设备是Linux三大设备之一(另外两种是块设备,网络设备),字符设备就是字节流形式通讯的I/O设备,绝大部分设备都是字符设备,常见的字符设备包括鼠标、键盘、显示器、串口等等,当我们执行ls -l /dev的时候,就能看到大量…

1.4 初探JdbcTemplate操作

实战目的 掌握Spring框架中JdbcTemplate的使用,实现对数据库的基本操作。理解数据库连接池的工作原理及其在实际开发中的重要性。通过实际操作,加深对Spring框架中ORM(对象关系映射)的理解。 关键技术点 JdbcTemplate操作&…

重发布和路由策略

重发布 在同一个网络拓扑结构中,如果存在多种不同的路由协议,由于不同路由协议的机理各有不同,对路由的处理也不相同,这就在网络中造成了路由信息的隔离,在路由协议的边界设备上,将某种路由协议的路由信息引…

Java中的线程

一、创建线程的几种方式? ① 通过继承Thread类并重写run方法 ,实现简单但不可以继承其他类 Thread底层也是实现了Runnable接口,重写的是run而不是start方法 ②实现Runnable接口并重写run方法, 避免了单继承的局限性&#xff…

PVE安装Windows 95报错 while initializing device IOS

安装Win95重启后报错信息如下图,重启一直报错 while initializing device IOS,查了下报错原因说是 CPU频率太高导致,需要安装AMDK6UPD.EXE补丁包 下载地址 https://zhangka.lanzouw.com/igW0S1y8p5pe 打补丁操作流程: 1)将下载的iso文件加载到新光盘中 2)重启到dos环境…

迅饶科技 X2Modbus 网关 AddUser 任意用户添加漏洞复现

0x01 产品简介 X2Modbus是上海迅饶自动化科技有限公司Q开发的一款功能很强大的协议转换网关, 这里的X代表各家不同的通信协议, 2是T0的谐音表示转换, Modbus就是最终支持的标准协议是Modbus协议。用户可以根据现场设备的通信协议进行配置,转成标准的Modbus协议。在PC端仿真…

# IDEA 复制项目 Module 出现 不同模块下的 Product 类报错

IDEA 复制项目 Module 出现 不同模块下的 Product 类报错 我们 用 IDEA 复制项目 Module 出现 不同模块下的 Product 类报错,发现复制的 module 名称没有改变或者 java 文件夹后面还有原项目 source root 字样,maven 父子项目没有标识等问题。 解决方法…

【前端】实现表格简单操作

简言 表格合并基础篇 本篇是在上一章的基础上实现,实现了的功能有添加行、删除行、逆向选区、取消合并功能。 功能实现 添加行 添加行分为在上面添加和在下面追加行。 利用 insertAdjacentElement 方法实现,该方法可以实现从前插入元素和从后插入元…

12 华三的二层链路聚合

12 华三的二层链路聚合 配置思路 1. 配置二层静态聚合组 (1) 进入系统视图。 system-view (2) 创建二层聚合接口,并进入二层聚合接口视图。 interface bridge-aggregation interface-number [ lite ] 创建二层聚合接口后,系统将自动生成…

苍穹外卖Day06笔记

疯玩了一个月,效率好低,今天开始捡起来苍穹外卖~ 1. 为什么不需要单独引入HttpClient的dependency? 因为我们在sky-common的pom.xml中已经引入了aliyun-sdk-oss的依赖,而这个依赖低层就引入了httpclinet的依赖,根据依…

Linux 文件

文章目录 文件操作回顾(C/C)系统调用接口 管理文件认识一切皆文件C/C的文件操作函数与系统调用接口的关系……重定向与缓冲区 -- 认识重定向与缓冲区 -- 理解使用重定向缓冲区实现一个简单的Shell(加上重定向)标准输出和标准错误(在重定向下的意义) 磁盘文件磁盘存储文件操作系…

docker-compose安装es+kibana 8.12.2

小伙伴们,你们好,我是老寇,我又回来辣,几个月不见甚是想念啊!!! 因云平台需要改造,es7升级为es8,所以记录一下,es8需要开启ssl认证,需要配置证书…

第147天:免杀对抗-C2远控篇CC++ShellCode定性分析生成提取Loader加载模式编译执行

https://blog.csdn.net/qq_29948489/article/details/136180966 #C2远控-ShellCode-认知&环境 1.创建工程时关闭SDL检查 2.属性->C/C++->代码生成->运行库->多线程 (/MT)如果是debug则设置成MTD 3.属性->C/C++->代码生成->禁用安全检查GS 4.关闭生成清…