时间序列-LSTM-pytorch

498 阅读2分钟

通过LSTM 做时间序列的 预测

完整体现了 神经网络 训练模型的全过程,

1. 读取数据:

image.png

2. 查看数据

import matplotlib.pyplot as plt
import seaborn as sns

sns.set_style("darkgrid")
plt.figure(figsize = (15,9))
plt.plot(training_set[['Passengers']])

plt.xticks(range(0,training_set.shape[0],20), training_set['Month'].loc[::20], rotation=45)  # x 轴 

plt.title("airline-passengers",fontsize=18, fontweight='bold')
plt.xlabel('Date',fontsize=18)
plt.ylabel('Passengers',fontsize=18)
plt.show()

image.png

3. 数据的归一化

from sklearn.preprocessing import MinMaxScaler

scaler = MinMaxScaler(feature_range=(-1, 1))
scaler_data = scaler.fit_transform(training_set['Passengers'].values.reshape(-1,1))

image.png

4. 构造自己的 dataset

from torch.utils.data import Dataset, DataLoader,random_split
class MyDataset(Dataset): 
    # 传入  数据,
    def __init__(self, data_source,seq_length):
        self.data_source = data_source  # 输入的数据
        self.seq = seq_length       # 数据的尺度, 
         
    
    # 根据索引 返回 x 和 y  也叫 输入特征 和对应的标签 
    # 初步逻辑是 使用前三个数据,预测第四个数据 
    def __getitem__(self, index): 
        
        x=self.data_source[index : index + self.seq ] 
        y= self.data_source[ index + self.seq ] 
        
        x_Tensor = torch.from_numpy(x).type(torch.Tensor)
        y_Tensor = torch.from_numpy(x).type(torch.Tensor)
        return ( x_Tensor, y_Tensor  )
    
    # 返回数据集的长度
    def __len__(self):  
        return (len(self.data_source) - self.seq ) 

5. 加载数据集合 读取数据

这里的时间序列 模型 方法是 用前三个数据 预测第四个数据, 也就是说 x = [0:3] y = [3] x : (3,1)
y : (1,1) 的格式

# Define dataset 
my_dataset = MyDataset(data_source=scaler_data ,seq_length=3)

data_all_loader = DataLoader(dataset=my_dataset, # 传递数据集
                          batch_size=5 , #一个小批量容量是多少
                          shuffle=True , # 数据集顺序是否要打乱,一般是要的。测试数据集一般没必要
                          num_workers=0) # 需要几个进程来一次性读取这个小批量数据


查看 训练的源数据

这里虽然数据量小,依然采用了 大量数据加载的方式 一个batch的加载,一次输入 5个数据

image.png

6. 划分数据集 和测试集

image.png

使用dataloader 加载数据集

batch_size=5
train_loader = DataLoader(
        train_data, batch_size=batch_size, shuffle=True, num_workers=0
    )
test_loader = DataLoader(
    test_data, batch_size=batch_size, shuffle=True, num_workers=0
    )

构建模型 LSTM

input_dim = 1    # 输入的 x 的纬度 ( 特征项 )  输入数据的特征维数 
hidden_dim = 32    #  隐藏层的大小   LSTM中隐层的维度 
num_layers = 2   #   循环神经网络的层数 
output_dim = 1  #  输出的纬度 
num_epochs = 100  # 训练的次数 


# 1. 模型的 实例化 
model = LSTM(input_dim=input_dim, hidden_dim=hidden_dim, output_dim=output_dim, num_layers=num_layers)
#  2. 设置损失函数 
criterion = torch.nn.MSELoss()
# 3. 设置 学习率
learning_rate = 0.01
# 4. 设置 优化器 
optimiser = torch.optim.Adam(model.parameters(), lr=learning_rate)

训练模型



import time

hist = np.zeros(num_epochs)
start_time = time.time()

for epoch in range(num_epochs):
    for batch_index, (batch_x_train, batch_y_train) in enumerate(train_loader):
         #  已经 是 tensor 格式 
        y_train_pred = model(batch_x_train)
        #print( batch_y_train.shape , y_train_pred.shape)  # torch.Size([5, 3, 1]) torch.Size([5, 3, 1])
        loss = criterion(y_train_pred, batch_y_train)
       # print("Epoch ", t, "MSE: ", loss.item())
        hist[ epoch ] = loss.item()
        optimiser.zero_grad()
        loss.backward()
        optimiser.step()
 
        
    if epoch % 50 == 0:
        print('epoch {}, loss {}'.format(epoch, loss.item()))
    
training_time = time.time()-start_time
print("Training time: {}".format(training_time))

image.png

模型结果可视化

image.png

使用测试集 数据进行验证

y_pred=[]
y_test=[]
for batch_index, (batch_x_test, batch_y_test) in enumerate(test_loader):
         #  已经 是 tensor 格式 
        
    y_test_pred = model(batch_x_test)
    y_pred.append(y_test_pred)
    y_test.append(batch_y_test)

image.png


#  测试集 预测的 y 结果 
y_p_all=[i.detach().numpy().reshape(-1).tolist()     for i  in y_pred ]
y_p_all_list=sum(y_p_all,[] )
len(y_p_all_list)
# 测试集 实际的 y 的值 
y_t_all=[i.detach().numpy().reshape(-1).tolist()     for i  in y_test ]
y_t_all_list=sum(y_t_all,[] )
len(y_t_all_list)

将 归一化的数据 还原 回去 进行比较

predict = pd.DataFrame(scaler.inverse_transform(      np.array(y_p_all_list).reshape(-1,1)    ))  # 预测值 
original = pd.DataFrame(scaler.inverse_transform(      np.array(y_t_all).reshape(-1,1)         ))  # 真实值
import seaborn as sns
sns.set_style("darkgrid")    

fig = plt.figure()
fig.subplots_adjust(hspace=0.2, wspace=0.2)

plt.subplot(1, 2, 1)
ax = sns.lineplot(x = predict.index, y = predict[0], label="Training Prediction (LSTM)", color='tomato')
ax = sns.lineplot(x = original.index, y = original[0], label="Data original", color='royalblue')

ax.set_title('data value', size = 14, fontweight='bold')
ax.set_xlabel("Days", size = 14)
ax.set_ylabel("value y ", size = 14)
ax.set_xticklabels('', size=10)


plt.subplot(1, 2, 2)
ax = sns.lineplot(data=hist, color='royalblue')
ax.set_xlabel("Epoch", size = 14)
ax.set_ylabel("Loss", size = 14)
ax.set_title("Training Loss", size = 14, fontweight='bold')
fig.set_figheight(6)
fig.set_figwidth(16)

image.png

最后贴上 LSTM 的 架构图

blog.csdn.net/baidu_38963… lstm原理原文链接

image.png 代码 和 数据 已上传 github 欢迎交流。github.com/jevy146/tim…