pytorch+LSTM实现使用单参数预测,以及多参数预测(代码注释版)

开发前准备:

环境管理:Anaconda
python: 3.8
显卡:NVIDIA3060
pytorch: 到官网选择conda版本,使用的是CUDA11.8
编译器: PyCharm

简述:

本次使用seaborn库中的flights数据集来做试验,我们通过获取其中年份月份与坐飞机的人数关系,来预测未来月份的坐飞机人数。(注意:很多信息都在注释里有,所以就不会详细解释,多看注释)

需要导入的模块

import torch
import torch.nn as nnimport seaborn as sns
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
# 使用from而不是import是因为 我们只需要导入MinMaxScaler类,而不需要访问该模块中的其他函数或变量
from sklearn.preprocessing import MinMaxScaler
# 自定义的模块,用来写构造lstm的
import method

获取数据集与处理

有两种方式获取,一种是从网上拉取,一种是下载到本地,因为网络问题,所以我就下载到了本地,联网获取的方式也有,只不过被注释了。

# 获取到seaborn数据集
# dataset_names = sns.get_dataset_names()
# 打印数据集名称
# for name in dataset_names:
#     print(name)
# 因为下载总是报错,所以从本地加载
# 使用其中的飞行数据集,获取到的数据类型是Pandas中的DataFrame
flight_data = sns.load_dataset("flights", data_home='C:/Users/51699/Desktop/seaborn-data', cache=True)
# 打印一下前5行数据,看看是个什么造型的数据
print("大概结构----")
print(flight_data.head())
# 打印数据形状,结果是(144,3),144/12=12,表示是有12年的数据,
print("数据形状---")
print(flight_data.shape)

在这里插入图片描述
在这里插入图片描述
可以看到打印出来的数据结构,包含年份,月份,乘客信息。flight_data 的数据类型是DataFrame。数据形状,是一个144行,3列的矩阵,144/12=12,表示这里总共有12年的数据,144个月。

下面从数据集中获取列名,并从中取出乘客的数据

print("列名信息---------------------------------------------------------------------------")
print(columns)
# 获取passengers列下的所有数据,并转化为浮点数
all_data = flight_data['passengers'].values.astype(float)
print("乘客数量数据---------------------------------------------------------------------------")
print(all_data)

在这里插入图片描述

下面需要把144条数据的后12条作为测试数据,144-12=132条数据作为训练数据。然后把切分好的数据,做归一化处理,消除特征关系。可以看出下面的打印内容,所有数据都被限制到了-1和1之间。

# 数据总量为144,我们使用前132条作为训练,后12条用来做测试,所以需要把数据分为训练集和测试集
test_data_size = 12
# 将all_data中除了最后test_data_size个元素之外的所有元素作为训练集,赋值给变量train_data
train_data = all_data[:-test_data_size]
print("训练集长度---")
print(len(train_data))
# 将all_data中最后test_data_size个元素作为测试集,赋值给变量test_data
test_data = all_data[-test_data_size:]
print("测试集长的胡---")
print(len(test_data))
# 归一化处理把乘客数量缩小到-1和1之间 目的是将不同特征的数据量纲统一,消除特征之间的量纲影响,使得不同特征之间具有可比性
scaler = MinMaxScaler(feature_range=(-1, 1))
train_data_normalized = scaler.fit_transform(train_data.reshape(-1, 1))
print("归一化后的前5条和后5条数据---------------------------------------------------------------------------")
print(train_data_normalized[:5])
print(train_data_normalized[-5:])

在这里插入图片描述
把归一化后的乘客数据,转化为tensor张量,只有张量才能让GPU运算

# 把归一化后的乘客数据,转化为tensor张量,因为PyTorch模型都是要使用tensor张量训练,其中参数-1表示,根据数据自动推断维度的大小。
# 这意味着PyTorch将根据数据的长度和形状来动态确定张量的维度。
train_data_normalized = torch.FloatTensor(train_data_normalized).view(-1)
print("乘客np转化为PyTorch张量---------------------------------------------------------------------------")
print(train_data_normalized)

在这里插入图片描述

到目前为止,我们已经有了一个一维的张量,接下来就需要制作训练集,训练集一般包含训练的数据,和这组训练数据对应的标签。因为一年有12个月,所以我们就取数据中的第1个到第12个作为训练的数据,第13个作为标签,这就是第一组数据。第二组我们取第2个到第13个数据作为训练数据,第14个作为标签,这就是第二组数据,依次类推,我们就有132组训练数据。

# 将我们的训练数据转换为序列和相应的标签,可以使用任何序列长度,这取决于领域知识。然而,在我们的数据集中,由于我们有每月的数据且一年有12个月,因此使用序列长度为12是方便的
train_window = 12
# 从下面的打印可以看出,第一个tensor中的第一个是训练数组,内容是1-12月的值;第二个是标签数组,内容是13月的值。
# 第二个tensor中的第一个训练数组是2-13月的值,第二个标签数组是14月的值
# 训练集总数是132,每12个为一组,第13个是标签,每次往后移动一个数字,所以有132组
train_inout_seq = method.create_inout_sequences(train_data_normalized, train_window)
print("训练的序列和相应的标签:-------------------------------------------------------------------")
print(train_inout_seq)

其中method.create_inout_sequences是另外一个自定义模块里的方法

# 将我们的训练数据转换为序列和相应的标签
def create_inout_sequences(input_data, tw):inout_seq = []L = len(input_data)for i in range(L - tw):train_seq = input_data[i:i + tw]train_label = input_data[i + tw:i + tw + 1]inout_seq.append((train_seq, train_label))return inout_seq

红色框内的是训练数据,蓝色的是标签
在这里插入图片描述

定义模型类

下面继续在method模块中,定义我们的类LSTM。其中lstm_out, self.hidden_cell = self.lstm(input_seq.view(len(input_seq), 1, -1), self.hidden_cell)相,其实就是pytorch的impose函数,他要接收一个三维的向量,因为LSTM的隐含层是需要接收三个参数的。

# 定义LSTM模型
class LSTM(nn.Module):# 构造函数,初始化网络使用# input_size:对应于输入中特征的数量。虽然我们的序列长度为12,但每个月只有1个值,即乘客总数,因此输入大小将为1# hidden_layer_size:指定每层神经元的数量。我们将有一个100个神经元的隐藏层# output_size:输出中项目的数量,由于我们想要预测未来1个月内乘客人数,因此输出大小将为1def __init__(self, input_size=1, hidden_layer_size=100, output_size=1):super().__init__()self.hidden_layer_size = hidden_layer_sizeself.lstm = nn.LSTM(input_size, hidden_layer_size)def forward(self, input_seq):# self.lstm是已经被实例化过的lstm,第一个参数是输入的序列,第二个参数是隐藏层的状态,隐式调用了向前传播函数,本质就是input方法# 返回值lstm_out是最终的输出,hidden_cell是隐藏层的状态# print(input_seq.view(len(input_seq), 1, -1))# input_seq.view(len(input_seq), 1, -1)需要转化为3维张量,因为LSTM的隐含层是接收三个参数的lstm_out, self.hidden_cell = self.lstm(input_seq.view(len(input_seq), 1, -1), self.hidden_cell)# self.linear是一个全连接(线性)神经网络层predictions = self.linear(lstm_out.view(len(input_seq), -1))# 返回线性层输出张量中的最后一个元素作为最终地预测值return predictions[-1]

初始化模型信息

接下来就要声明LSTM类,以及一些初始化,关于损失函数和步长的更新方法都在注释里有解释。

# 创建一个LSTM模型对象,用于处理序列数据
model = method.LSTM()
# 创建一个均方误差损失函数对象,用于计算预测值与真实值之间的差异
loss_function = nn.MSELoss()
# 创建一个Adam优化器对象,用于更新模型参数以最小化损失函数
optimizer = torch.optim.Adam(model.parameters(), lr=0.001)
# 在PyTorch中定义一个全连接(线性)神经网络层,并将其添加到模型中
model.add_module('linear', nn.Linear(100, 1))
print("模型信息:---")
print(model)

在这里插入图片描述

训练模型

训练模型,每一组模型训练的时候,都要清除前面一组训练留下的隐含层信息,梯度清零的主要原因是为了梯度消失和梯度爆炸问题。y_pred = model(seq)就是调用了上面LSTM类中的forward,

epochs = 150
for i in range(epochs):for seq, labels in train_inout_seq:  # 遍历训练数据optimizer.zero_grad()  # 梯度清零model.hidden_cell = (torch.zeros(1, 1, model.hidden_layer_size),torch.zeros(1, 1, model.hidden_layer_size))  # 初始化隐藏层状态(不是参数)# print(seq)# print(labels)y_pred = model(seq)  # 模型前向传播single_loss = loss_function(y_pred, labels)  # 计算损失函数single_loss.backward()  # 反向传播求梯度optimizer.step()  # 更新参数if i % 25 == 1:  # 每25个epoch打印损失print(f'epoch: {i:3} loss: {single_loss.item():10.8f}')
print(f'epoch: {i:3} loss: {single_loss.item():10.10f}')  # 打印最终损失

LSTM类中的forward方法里的input_seq.view(len(input_seq), 1, -1)变形后如下,这些就是第一轮要进入到LSTM中训练的数据,每次进入一个,总共进入12次,正向传播,然后返回一个均方误差,用来和标签值计算损失,计算梯度,反向传播更新隐含层中的参数权重。
在这里插入图片描述
下图就是第一组数据的训练过程
在这里插入图片描述
下面是每25组数据训练完后和标签的误差值
在这里插入图片描述

测试预测

下面是测试集代码,注释写的很清晰了,就不过多赘述了

# 预测测试集中的乘客数量
fut_pred = 12
# 获取最后12个月的数据
test_inputs = train_data_normalized[-train_window:].tolist()
print(test_inputs)
# 将模型设置为评估模式
model.eval()
for i in range(fut_pred):# 将输入数据转换为PyTorch张量seq = torch.FloatTensor(test_inputs[-train_window:])# 隐藏层状态清零with torch.no_grad():model.hidden = (torch.zeros(1, 1, model.hidden_layer_size),torch.zeros(1, 1, model.hidden_layer_size))print(seq)# 第一次循环,会预测出第13个月的乘客数量# 第二次循环,会把第一次预测的结果,作为12月# tensor([0.1253, 0.0462, 0.3275, 0.2835, 0.3890, 0.6176, 0.9516, 1.0000, 0.5780,#         0.3319, 0.1341, 0.3231])# tensor([0.0462, 0.3275, 0.2835, 0.3890, 0.6176, 0.9516, 1.0000, 0.5780, 0.3319,#         0.1341, 0.3231, 0.2997])test_inputs.append(model(seq).item())
# 将预测结果还原到原始数据范围
actual_predictions = scaler.inverse_transform(np.array(test_inputs[train_window:] ).reshape(-1, 1))
print(actual_predictions)

下面是往后预测是12个月的数据
在这里插入图片描述

多参数预测

上面的试验,用的是单参数,但是为了让模型的拟合性更好,肯定是要使用多参数,那么上面的LSTM类中的__init__方法,input_size就需要改变,比如我们现在要预测每天坐飞机的人数,有机票价格,天气,湿度三个条件,数据量为一年。因为是三个特征值,那么input_size就是3,那么我们用3天来做序列长度,那么训练集应该是
训练值x=[
[ [0.1,0.2,0.3] ,[0.4,0.5,0.6] ,[0.7,0.8,0.9] ] ,//第一天,第二天,第三天
[ [0.4,0.5,0.6] ,[0.7,0.8,0.9] ,[0.11,0.12,0.13] ],//第二天,第三天,第四天

一直到第363行。就是第363天,因为366天没有数据
]
标签值y=[ 0.8,0.7,0.2…一直到第365 ]
0.8表示x中的第一行标签值,其含义是第四天的人数。
在这里插入图片描述
神经网络的结构大概如上,红色箭头表示上一次训练隐含层的输入,红框表示输入层参数,可以看出来,还是要输入一个三维的张量,其中一维是输入层输入的,另外两个是上个时刻隐含层输入的。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/181236.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

ConnectionError: HTTPSConnectionPool

ConnectionError: HTTPSConnectionPool(host‘zbbfxstatic.figtingdream.com’, port443): Max retries exceeded with url: /api/cache (Caused by NewConnectionError(‘<urllib3.connection.HTTPSConnection object at 0x00000249795AD9A0>: Failed to establish a ne…

游戏开发中的“御用中介“

点击上方亿元程序员关注和★星标 引言 大家好&#xff0c;我是亿元程序员&#xff0c;一位有着8年游戏行业经验的主程。 本系列是《和8年游戏主程一起学习设计模式》&#xff0c;让糟糕的代码在潜移默化中升华&#xff0c;欢迎大家关注分享收藏订阅。 游戏开发中的"御用…

【Redis】String字符串类型-常用命令

文章目录 String字符串类型常用命令setgetMGETMSET 计数命令INCRINCRBYDECRDECRBYINCRBYFLOAT 其它命令APPENDGETRANGESETRANGESTRLEN 命令总结 String字符串类型 1&#xff09;⾸先Redis中所有的键的类型都是字符串类型 2&#xff09;字符串类型的值&#xff08;value&#…

2.2整式的加减(第1课时)——合并同类项教学及作业设计

【学习目标】 1&#xff0e;理解同类项的概念&#xff0c;并能正确辨别同类项&#xff0e; 2&#xff0e;理解合并同类项的依据是乘法分配律&#xff0c;掌握合并同类项的方法&#xff0e; 知识点归纳&#xff1a; ★合并同类项后&#xff0c;所得的项的系数是___________…

Linux学习第28天:Platform设备驱动开发(二): 专注与分散

Linux版本号4.1.15 芯片I.MX6ULL 大叔学Linux 品人间百味 思文短情长 三、硬件原理图分析 四、驱动开发 1、platform设备与驱动程序开发 53 /* 54 * 设备资源信息&#xff0c;也就是 LED0 所使用的所有寄存器 55 */ 56 static str…

堆叠注入 [GYCTF2020]Blacklist1

打开题目 判断注入点 输入1&#xff0c;页面回显 输入1 页面报错 输入 1 # 页面正常&#xff0c;说明是单引号的字符型注入 我们输入1; show databases; # 说明有6个数据库 1; show tables; # 说明有三个表 我们直接查看FlagHere的表结构 1;desc FlagHere&#xff1b;# 发…

【Hadoop】Apache Hadoop YARN

&#x1f984; 个人主页——&#x1f390;开着拖拉机回家_Linux,Java基础学习,大数据运维-CSDN博客 &#x1f390;✨&#x1f341; 感谢点赞和关注 &#xff0c;每天进步一点点&#xff01;加油&#xff01; 目录 一、YARN概述 二、YARN基础架构 2.1 ResourceManager&#x…

[100天算法】-有序矩阵中第K小的元素(day 58)

题目描述 给定一个 n x n 矩阵&#xff0c;其中每行和每列元素均按升序排序&#xff0c;找到矩阵中第 k 小的元素。 请注意&#xff0c;它是排序后的第 k 小元素&#xff0c;而不是第 k 个不同的元素。示例&#xff1a;matrix [[ 1, 5, 9],[10, 11, 13],[12, 13, 15] ], k …

基础知识:位运算

基础知识&#xff1a;位运算 1. 两类表达式 1. 两类表达式

展开一个结构加法等式

4a6 4a8 - - - - - 1 - 1 - - - 1 - 1 - - 1 - - 1 - - 1 - - 1 - - - - 在5-1的方向上具体展开4a64a8 25 19 19 19 19 19 19 19 25 19 19 19 19 19 19 19 1 10 10 10 10 10 10 10 1 10 10 10 10 10 10 10 …

全网最详细的【shell脚本的入门】

&#x1f3c5;我是默&#xff0c;一个在CSDN分享笔记的博主。&#x1f4da;&#x1f4da; ​ &#x1f31f;在这里&#xff0c;我要推荐给大家我的专栏《Linux》。&#x1f3af;&#x1f3af; &#x1f680;无论你是编程小白&#xff0c;还是有一定基础的程序员&#xff0c;这…

蓝桥杯每日一题2023.11.5

题目描述 方格分割 - 蓝桥云课 (lanqiao.cn) 题目分析 对于每个图我们可以从中间开始搜索&#xff0c;如果到达边界点就说明找到了一种对称的方法&#xff0c;我们可以直接对此进行答案记录每次进行回溯就会找到不同的图像&#xff0c;如果是一样的图像则算一种情况&#xff…

初识Vue 输出Hello World 及注意事项

在我们还没接触Vue之前&#xff0c;我同学常说我可以直接在元素里输出JS的表达式吗&#xff1f;肯定是不太行。当我们接触vue.js后&#xff0c;这个想法成了现实。 每当我们学习一门新的语言或者框架时&#xff0c;我们都习惯打印一个“hello world”&#xff0c;在我们vue当中…

Docker 安装ELK7.7.1

(注&#xff1a;在安装之前&#xff0c;本方法必须安装jdk1.8以上版本) (注&#xff1a;如果在虚拟机下用可以直接按方法走即可&#xff0c;如果是想进行备份后在别的机器上进行相关操作&#xff0c;必须把所有带有172.17.0.6、192.168.8.166:9200和端口号都改成你自己的方可使…

使用 curator 连接 zookeeper 集群 Invalid config event received

dubbo整合zookeeper 如图&#xff0c;错误日志 2023-11-04 21:16:18.699 ERROR 7459 [main-EventThread] org.apache.curator.framework.imps.EnsembleTracker Caller0 at org.apache.curator.framework.imps.EnsembleTracker.processConfigData(EnsembleTracker.java…

MTK联发科、高通、紫光展锐手机SOC平台型号汇总(含详细参数)

MediaTek联发科手机平台汇总&#xff1a; Qualcomm高通SOC平台汇总&#xff1a; 紫光展锐SOC平台汇总&#xff1a; 新移科技已成功研发手机SOC平台&#xff1a; 联发科平台&#xff1a; MTK6739、MTK6761、MTK6762、MTK6765、MTK8788、MTK6853、MTK6873、MTK6833、MTK6877、…

试试流量回放,不用人工写自动化测试case了

大家好&#xff0c;我是洋子&#xff0c;接触过接口自动化测试的同学都知道&#xff0c;我们一般要基于某种自动化测试框架&#xff0c;编写自动化case&#xff0c;编写自动化case的依据来源于接口文档&#xff0c;对照接口文档里面的请求参数进行人工添加接口自动化case 其实…

DB-GPT介绍

DB-GPT介绍 引言DB-GPT项目简介DB-GPT架构关键特性私域问答&数据处理多数据源&可视化自动化微调Multi-Agents&Plugins多模型支持与管理隐私安全支持数据源 子模块DB-GPT-Hub微调参考文献 引言 随着数据量的不断增长和数据分析的需求日益增多&#xff0c;将自然语言…

Git(七).git 文件夹瘦身,GitLab 永久删除文件

目录 一、问题背景二、问题复现2.1 新建项目2.2 上传大文件2.3 上传结果 三、解决方案3.1 GitLab备份与还原1&#xff09;备份2&#xff09;还原 3.2 删除方式一&#xff1a;git filter-repo 命令【推荐】1&#xff09;安装2&#xff09;删除本地仓库文件3&#xff09;重新关联…

3款免费又好用的 Docker 可视化管理工具

前言 Docker提供了命令行工具&#xff08;Docker CLI&#xff09;来管理Docker容器、镜像、网络和数据卷等Docker组件。我们也可以使用可视化管理工具来更方便地查看和管理Docker容器、镜像、网络和数据卷等Docker组件。今天我们来介绍3款免费且好用的 Docker 可视化管理工具。…