pytorch RNN用于时间序列的分析

本文参考书籍《深度学习入门之pytorch》

首先看一下我们的数据集:

可以看出数据有递增的趋势,但是有很大的波动性。这里我们尝试用rnn来解决。

贴一下代码:

# -*- coding: utf-8 -*-
"""
Created on Tue Oct  9 11:28:39 2018

@author: www
"""

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt


data_csv = pd.read_csv(r'E:\data\data.csv', usecols=[1])

plt.plot(data_csv)

#首先我们进行预处理,将数据中 na 的数据去掉,然后将数据标准化到 0 ~ 1 之间。
data_csv = data_csv.dropna()
dataset = data_csv.values
dataset = dataset.astype('float32')
max_value = np.max(dataset)
min_value = np.min(dataset)
scalar = max_value - min_value
dataset = list(map(lambda x: x / scalar, dataset))

'''
接着我们进行数据集的创建,我们想通过前面几个月的流量来预测当月的流量,
比如我们希望通过前两个月的流量来预测当月的流量,我们可以将前两个月的流量
当做输入,当月的流量当做输出。同时我们需要将我们的数据集分为训练集和测试
集,通过测试集的效果来测试模型的性能,这里我们简单的将前面几年的数据作为
训练集,后面两年的数据作为测试集。
'''
def create_dataset(dataset, look_back=2):
    dataX, dataY = [], []
    for i in range(len(dataset) - look_back):
        a = dataset[i:(i + look_back)]
        dataX.append(a)
        dataY.append(dataset[i + look_back])
    return np.array(dataX), np.array(dataY)
    
# 创建好输入输出
data_X, data_Y = create_dataset(dataset)

# 划分训练集和测试集,70% 作为训练集
train_size = int(len(data_X) * 0.7)
test_size = len(data_X) - train_size
train_X = data_X[:train_size]
train_Y = data_Y[:train_size]
test_X = data_X[train_size:]
test_Y = data_Y[train_size:]

'''
最后,我们需要将数据改变一下形状,因为 RNN 读入的数据维度是 
(seq, batch, feature),所以要重新改变一下数据的维度,这里只有一个序列,
所以 batch 是 1,而输入的 feature 就是我们希望依据的几个月份,这里我们
定的是两个月份,所以 feature 就是 2.
'''    
import torch

train_X = train_X.reshape(-1, 1, 2)
train_Y = train_Y.reshape(-1, 1, 1)
test_X = test_X.reshape(-1, 1, 2)

train_x = torch.from_numpy(train_X)
train_y = torch.from_numpy(train_Y)
test_x = torch.from_numpy(test_X)

from torch import nn
from torch.autograd import Variable

#定义模型
class lstm_reg(nn.Module):
     def __init__(self, input_size, hidden_size, output_size=1, num_layers=2):
          super(lstm_reg, self).__init__()
          
          self.rnn = nn.LSTM(input_size, hidden_size, num_layers)
          self.reg = nn.Linear(hidden_size, output_size)
          
     def forward(self, x):
          x, _ = self.rnn(x) 
          s, b, h = x.shape  #(seq, batch, hidden)
          x = x.view(s*b, h) #转化为线性层的输入方式
          x = self.reg(x)
          x = x.view(s, b, -1)
          return x
#定义好网络结构,输入的维度是 2,因为我们使用两个月的流量作为输入,隐藏层的维度可以任意指定,这里我们选的 4
net = lstm_reg(2, 4)
criterion = nn.MSELoss()
optimizer = torch.optim.Adam(net.parameters(), lr=1e-2)

#开始训练
for e in range(1000):
     var_x = Variable(train_x)
     var_y = Variable(train_y)
     #前向传播
     out = net(var_x)
     loss = criterion(out, var_y)
     #反向传播
     optimizer.zero_grad()
     loss.backward()
     optimizer.step()
     if (e+1)%100==0:
          print('Epoch:{}, Loss:{:.5f}'.format(e+1, loss.item()))
     
#训练完成之后,我们可以用训练好的模型去预测后面的结果
net = net.eval()
data_X = data_X.reshape(-1, 1, 2)
data_X = torch.from_numpy(data_X)
var_data = Variable(data_X)
pred_test = net(var_data) # 测试集的预测结果

# 改变输出的格式
pred_test = pred_test.view(-1).data.numpy()

# 画出实际结果和预测的结果
plt.plot(pred_test, 'r', label='prediction')
plt.plot(dataset, 'b', label='real')
plt.legend(loc='best')

网络定义很简单,一层是lstm层,一层是线性层,注意我们需要使用view来重新排列,因为nn.LInear不接受三维的输入,只接受两维的输入,所以我们可以先将前面两维合并到一起,然后经过线性层之后再把它们分开,最后输出结果。建立数据时依赖前面两个月的流量来预测第三个月的流量,所以输入的维度是2.

从预测结果可以看出,Lstm得到了比较理想的预测结果,相比与线性回归等算法,循环神经网络能更好的处理序列数据。

评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值