十大网站app排行榜,广州做seo的公司,网站建站建设多少钱,pcms网站开发开发前准备#xff1a;
环境管理#xff1a;Anaconda python: 3.8 显卡#xff1a;NVIDIA3060 pytorch: 到官网选择conda版本#xff0c;使用的是CUDA11.8 编译器#xff1a; PyCharm
简述#xff1a;
本次使用seaborn库中的flights数据集来做试验#xff0c;我们通过…开发前准备
环境管理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_homeC:/Users/51699/Desktop/seaborn-data, cacheTrue)
# 打印一下前5行数据看看是个什么造型的数据
print(大概结构----)
print(flight_data.head())
# 打印数据形状结果是144,3144/1212表示是有12年的数据
print(数据形状---)
print(flight_data.shape)可以看到打印出来的数据结构包含年份月份乘客信息。flight_data 的数据类型是DataFrame。数据形状是一个144行3列的矩阵144/1212表示这里总共有12年的数据144个月。
下面从数据集中获取列名并从中取出乘客的数据
print(列名信息---------------------------------------------------------------------------)
print(columns)
# 获取passengers列下的所有数据,并转化为浮点数
all_data flight_data[passengers].values.astype(float)
print(乘客数量数据---------------------------------------------------------------------------)
print(all_data)下面需要把144条数据的后12条作为测试数据144-12132条数据作为训练数据。然后把切分好的数据做归一化处理消除特征关系。可以看出下面的打印内容所有数据都被限制到了-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_size1, hidden_layer_size100, output_size1):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(), lr0.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(fepoch: {i:3} loss: {single_loss.item():10.8f})
print(fepoch: {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.80.70.2…一直到第365 ] 0.8表示x中的第一行标签值其含义是第四天的人数。 神经网络的结构大概如上红色箭头表示上一次训练隐含层的输入红框表示输入层参数可以看出来还是要输入一个三维的张量其中一维是输入层输入的另外两个是上个时刻隐含层输入的。