机器学习 Pytorch实现案例 LSTM案例(航班人数预测)

Pytorch学习案例之一。
step 1、确定数据来源
数据来源于seaborn的内置数据集

import torch
import torch.nn as nn

import seaborn as sns
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
%matplotlib inline

打印seaborn的内置数据集,包含这个航天人数预测的数据集,也包含我们熟悉的泰坦尼克的数据集。

sns.get_dataset_names()

在这里插入图片描述

查看数据集包含的信息:

flight_data = sns.load_dataset("flights")
flight_data.head()

在这里插入图片描述

flight_data.shape

(144,3)表明有12年的数据。
step 2、数据探索(可视化)

fig_size = plt.rcParams["figure.figsize"]
fig_size[0] = 15
fig_size[1] = 5
plt.rcParams["figure.figsize"] = fig_size  # 图片大小

plt.title('Month vs Passenger')
plt.ylabel('Total Passengers')
plt.xlabel('Months')
plt.grid(True)
plt.autoscale(axis='x',tight=True)
plt.plot(flight_data['passengers'])  # 只画一列

在这里插入图片描述

step 3、数据处理

flight_data.columns

在这里插入图片描述

将passengers 转化为 float 类型

all_data = flight_data['passengers'].values.astype(float)
print(all_data)

在这里插入图片描述

test_data_size = 12

train_data = all_data[:-test_data_size]  # 训练集
test_data = all_data[-test_data_size:]  # 测试集

print(len(train_data))  # 训练
print(len(test_data))   # 测试数据

在这里插入图片描述

标准化数据以进行时间序列预测非常重要

from sklearn.preprocessing import MinMaxScaler  # 标准化

scaler = MinMaxScaler(feature_range=(-1, 1))
train_data_normalized = scaler.fit_transform(train_data .reshape(-1, 1))
# 查看标准化的数据
print(train_data_normalized[:5])
print(train_data_normalized[-5:])

在这里插入图片描述

PyTorch模型是使用张量训练的。要将数据集转换为张量,我们可以简单地将数据集传递给FloatTensor对象的构造函数

train_data_normalized = torch.FloatTensor(train_data_normalized).view(-1) 
# 将数据加工成pytorch的变量
train_data_normalized  # 查看数据

在这里插入图片描述

接下来,我们将定义一个名为的函数create_inout_sequences。该函数将接受原始输入数据,并将返回一个元组列表。在每个元组中,第一个元素将包含与12个月内旅行的乘客数量相对应的12个项目的列表,第二个元组元素将包含一个项目,即在12 + 1个月内的乘客数量。

train_window = 12  # 每次训练的个数

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

该函数2个变量,分别为 input_data 以及 tw(表示train_window),label表示预测的

train_inout_seq = create_inout_sequences(train_data_normalized, train_window)

在这里 input 2个变量,train data的归一化数据,以及训练的windows
查看数据

train_inout_seq[:5]

在这里插入图片描述

step 4、定义pytorch的LSTM的训练模型
LSTM该类的构造函数接受三个参数:
input_size:对应于输入中的要素数量。尽管我们的序列长度为12,但每个月我们只有1个值,即乘客总数,因此输入大小为1。
hidden_layer_size:指定隐藏层的数量以及每层中神经元的数量。我们将有一层100个神经元。
output_size:输出中的项目数,由于我们要预测未来1个月的乘客人数,因此输出大小为1。
接下来,在构造函数中,我们创建变量hidden_layer_size,lstm,linear,和hidden_cell。

LSTM算法接受三个输入:先前的隐藏状态,先前的单元状态和当前输入。该hidden_cell变量包含先前的隐藏状态和单元状态。的lstm和linear层变量用于创建LSTM和线性层。
pass:上面标黄的不是很明白

class LSTM(nn.Module):
    def __init__(self, input_size=1, hidden_layer_size=100, output_size=1):
        super().__init__()
        self.hidden_layer_size = hidden_layer_size
		# 隐藏层
        self.lstm = nn.LSTM(input_size, hidden_layer_size)

        self.linear = nn.Linear(hidden_layer_size, output_size)

        self.hidden_cell = (torch.zeros(1,1,self.hidden_layer_size),
                            torch.zeros(1,1,self.hidden_layer_size))

    def forward(self, input_seq):
        lstm_out, self.hidden_cell = self.lstm(input_seq.view(len(input_seq) ,1, -1), self.hidden_cell)
        predictions = self.linear(lstm_out.view(len(input_seq), -1))
        return predictions[-1]
model = LSTM()
loss_function = nn.MSELoss()
optimizer = torch.optim.Adam(model.parameters(), lr=0.001)
print(model)

在这里插入图片描述

训练模型

epochs = 150

# inout_seq 是准备好的训练数据
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))

        y_pred = model(seq)

        single_loss = loss_function(y_pred, labels)  #损失函数
        single_loss.backward() #前向
        optimizer.step()

    if i%25 == 1:
        print(f'epoch: {i:3} loss: {single_loss.item():10.8f}')

step 5、模型预测
预测的 idea
该test_inputs项目将包含12个项目。在for循环内,这12个项目将用于对测试集中的第一个项目进行预测,即项目编号133。然后将预测值附加到test_inputs列表中。在第二次迭代中,最后12个项目将再次用作输入,并将进行新的预测,然后将其test_inputs再次添加到列表中。for由于测试集中有12个元素,因此该循环将执行12次。在循环末尾,test_inputs列表将包含24个项目。最后12个项目将是测试集的预测值。
非常重要

fut_pred = 12

test_inputs = train_data_normalized[-train_window:].tolist()  # 最后12个
print(test_inputs)
model.eval()
# 预测的值为12个
for i in range(fut_pred):
    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))
        test_inputs.append(model(seq).item())

model.eval() 作用
相信各位在pytorch的模型训练/预测代码中总会看到model.eval (),那这个函数到底是什么意思呢? 在模型中,我们通常会加上Dropout层和batch normalization层,在模型预测阶段,我们需要将这些层设置到预测模式,model.eval ()就是帮我们一键搞定的,如果在预测的时候忘记使用model.eval (),会导致不一致的预测结果。
模型结果(包含在test_input中)
我们选用train的后12个作为input,将结果添加到input中去,最终获得24个值,其中后12个为预测的值。

test_inputs[fut_pred:]

在这里插入图片描述
通过反归一化,获得实际的预测值

actual_predictions = scaler.inverse_transform(np.array(test_inputs[train_window:] ).reshape(-1, 1))
print(actual_predictions)

在这里插入图片描述

step 6、预测结果可视化

x = np.arange(132, 144, 1)
# print(x)
plt.title('Month vs Passenger')
plt.ylabel('Total Passengers')
plt.grid(True)
plt.autoscale(axis='x', tight=True)
plt.plot(flight_data['passengers'])
plt.plot(x,actual_predictions)
plt.show()

在这里插入图片描述

将范围放大

plt.title('Month vs Passenger')
plt.ylabel('Total Passengers')
plt.grid(True)
plt.autoscale(axis='x', tight=True)

plt.plot(flight_data['passengers'][-train_window:])
plt.plot(x,actual_predictions)
plt.show()

在这里插入图片描述

该项目原始参考链接(国外项目):
https://stackabuse.com/time-series-prediction-using-lstm-with-pytorch-in-python/

猜你喜欢

转载自blog.csdn.net/weixin_45492560/article/details/121316540