Pytorch 第十一回:循环神经网络——RNN模型

本次开启深度学习第十一回,基于Pytorch的RNN循环神经网络模型。前面我们已经分享过线性神经网络、多层神经网络和卷积神经网络。接下来,开始学习循环神经网络。本回分享的第一个循环神经网络,叫做RNN模型。在本回中,设计通过RNN模型来对股票收盘价格进行预测。接下来给大家分享具体思路。
本次学习,借助的平台是PyCharm 2024.1.3,python版本3.11 numpy版本是1.26.4,pytorch版本2.0.0+cu118,d2l的版本是1.0.3


前言

讲述模型前,先讲述两个概念,统一下思路:

1、RNN

RNN(Recurrent Neural Network)翻译成中文就是循环神经网络。RNN通过加入状态变量使模型可存储过去的信息,再结合当前的输入,从而形成完整的输入数据。因此RNN模型可以很好地处理序列数据。

2、隐藏层

RNN的‌隐藏层‌是RNN模型的核心机制。隐藏层不仅用于处理当前输入,还通过‌记忆历史信息‌,实现对序列数据的动态建模。
RNN的隐藏层在每个时间步接收两个输入:‌一个是当前时刻的输入‌;另一个是‌前一时刻的隐藏状态‌,即历史信息的压缩表示。之后,RNN模型通过权重矩阵和非线性激活函数(如 tanh 或 ReLU),将这两个输入融合为新的隐藏状态。

3、隐藏状态

隐藏状态是RNN处理序列数据的“记忆单元”,通过动态的方式更新、传递历史数据,从而使RNN模型能够分析出序列中的时序关联关系。
注:
1)在每个时间步中,隐藏状态是当前输入和过去所有输入的压缩表示,表达了序列的上下文关系。
2)隐藏状态保存了从序列起始位置到当前时间步的所有历史数据,并进行动态更新,从而反映输入的变化。

4、RNN 对比 CNN

1)应用上:RNN,常用来处理序列数据的;CNN主要用于图像处理。
RNN的特点是具有循环结构,可以记住历史信息,因此常用来处理时间序列或者自然语言。CNN通过卷积核提取空间特征,比如边缘、纹理等,因此主要用于图像处理。
2)结构上,RNN是循环反馈的,而CNN是层级递进,。RNN的每个时间步会处理输入,并且隐藏层的状态会传递到下一个时间步,这样就有了记忆能力。而CNN是通过卷积层、池化层这些来逐步减少数据维度,提取特征。
3)信号输入上,RNN的输入是可变长度的序列,CNN通常处理固定大小的输入。
4)参数共享上,RNN的参数在时间步之间共享,也就是每个时间步用的都是同一组参数,这样处理变长序列时更高效;CNN的卷积核在图像的不同位置共享参数,这样减少参数数量并捕捉空间局部特征。

闲言少叙,直接展示逻辑,先上引用:

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import torch
from torch import nn
import time

一、数据准备

1、读取数据

首先,从csv文件中读取股票的收盘价格。csv文件可以从本人分享的资源中下载。

data_csv = pd.read_csv('./stock_data.csv', usecols=[3])

价格的趋势图如下所示:
在这里插入图片描述

2、数据预处理

为方便处理数据,这里将数据进行归一化。

data_csv = data_csv.dropna()  
dataset = data_csv.values
dataset = dataset.astype('float32')
max_value = np.max(dataset)
min_value = np.min(dataset)
interval = max_value - min_value
dataset = list(map(lambda x: x / interval, dataset))

3、数据划分

进行数据预测时,设计用前三天的数据预测今天的数据。因此需要将数据进行一个划分,即三天前的数据集data_X和当天的数据集data_Y 。代码如下:

def optimize_dataset(dataset, primitive=3):
    dataX, dataY = [], []
    for i in range(len(dataset) - primitive):
        a = dataset[i:(i + primitive)]
        dataX.append(a)
        dataY.append(dataset[i + primitive])
    return np.array(dataX), np.array(dataY)
data_X, data_Y = optimize_dataset(dataset)

获得数据后,需要将数据划分为训练集和测试集。这里取数据的百分之七十作为训练集,剩下的百分之三十作为测试集。

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:]

4、类型转换

获得训练集和测试集后,为符合训练需求,需要修改其数据格式。并将数据转换为tensor类型。

train_X = train_X.reshape(-1, 1, 3)
train_Y = train_Y.reshape(-1, 1, 1)
test_X = test_X.reshape(-1, 1, 3)
train_x = torch.from_numpy(train_X)
train_y = torch.from_numpy(train_Y)
test_x = torch.from_numpy(test_X)

二、数据模型

1.定义RNN模型

这里定义的RNN模型由pytorch自带的rnn函数和全连接层组成。

class rnn_net(nn.Module):
    def __init__(self, channels_in, channels_hidden, channels_out=1):
        super(rnn_net, self).__init__()

        self.rnn = nn.RNN(channels_in, channels_hidden)  
        self.connect = nn.Linear(channels_hidden, channels_out)  

    def forward(self, x):
        x, _ = self.rnn(x)  
        a, b, c = x.shape
        x = x.view(a * b, c)  
        x = self.connect(x)
        x = x.view(a, b, -1)
        return x

2.定义损失函数和优化函数

定义计算均方误差损失函数;定义Adam优化器,学习率设定为0.01。

loss_f = nn.MSELoss()
optimizer = torch.optim.Adam(forecast_net.parameters(), lr=1e-2)

三、模型训练

1、实例化模型

这里实例化了一个输入为3个数据,隐藏层为6层的RNN模型。

device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
print("device=", device)
forecast_net = rnn_net(3, 6).to(device)

注:
为节省时间,本次采用GPU进行训练。如果想知道如何采用GPU进行训练,可以查看第六回内容。

2、模型训练

进行1000次迭代训练,代码如下:

for k in range(1000):
    train_x = train_x.to(device)
    train_y = train_y.to(device)
    out = forecast_net(train_x)
    loss = loss_f(out, train_y).to(device)
    optimizer.zero_grad()
    loss.backward()
    optimizer.step()
    time_consume = time.time() - time1
    if (k + 1) % 100 == 0:  #
        print('Epoch:	{},	Loss:	{:.5f},consume time:{:.3f}s'.format(k + 1, loss, time_consume))

3、输出展示

Epoch:100,	Loss:0.00024,	consume time:2.022s
Epoch:200,	Loss:0.00013,	consume time:3.585s
Epoch:300,	Loss:0.00010,	consume time:5.172s
Epoch:400,	Loss:0.00010,	consume time:6.816s
Epoch:500,	Loss:0.00009,	consume time:8.384s
Epoch:600,	Loss:0.00009,	consume time:9.932s
Epoch:700,	Loss:0.00008,	consume time:11.494s
Epoch:800,	Loss:0.00008,	consume time:13.055s
Epoch:900,	Loss:0.00008,	consume time:14.618s
Epoch:1000,	Loss:0.00008,	consume time:16.165s

从输出结果可以看出,训练集的训练精度较高。

4、预测收盘价格

接着使用训练好的模型预测股票的收盘价格。

forecast_net = forecast_net.eval()  
data_X = data_X.reshape(-1, 1, 3)
data_X = torch.from_numpy(data_X)
pred_data = data_X.to(device)
y_pred= forecast_net(pred_data).to("cpu")
y_pred = y_pred.view(-1).data.numpy()

plt.figure("股票数据预测")
plt.plot(y_pred, 'r', label='forecast data')
plt.plot(dataset, 'g', label='real data')
plt.legend(loc='best')
plt.show()

生成股票收盘预测趋势与实际收盘趋势的对比图,对比图如下所示:
在这里插入图片描述
从上图可以看出:RNN模型在此数据集的应用较好,预测结果与实际结果重合度较高。

总结

1)数据准备:准备收盘趋势的训练集和预测集;
2)模型准备:定义RNN模型、损失函数和优化器;
3)数据训练:实例化模型并训练,并生成股票收盘趋势与实际收盘趋势的对比图。

Logo

助力广东及东莞地区开发者,代码托管、在线学习与竞赛、技术交流与分享、资源共享、职业发展,成为松山湖开发者首选的工作与学习平台

更多推荐