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/