第九章(1):循环神经网络与pytorch示例(RNN实现股价预测)


欢迎大家来到安静到无声的 《基于pytorch的自然语言处理入门与实践》,如果对所写内容感兴趣请看《基于pytorch的自然语言处理入门与实践》系列讲解 - 总目录,同时这也可以作为大家学习的参考。欢迎订阅,请多多支持!

1. 概述

循环神经网络(Recurrent Neural Network,RNN)是一种基于神经网络的机器学习模型,主要用于处理序列数据。与传统的前馈神经网络不同,RNN引入了循环连接,使得模型能够捕捉到输入序列中的上下文信息和时间依赖关系。

假设给定一个序列, x 1 : T = ( x 1 , x 2 , … , x t , … , x T ) x_{1:T}=(x_{1},x_{2},\ldots,x_{t},\ldots,x_{T}) x1:T=(x1,x2,,xt,,xT),RNN神经网络通过下面公式更新带反馈边的隐藏层的活性值 h t h_t ht
h t = f ( h t − 1 , x t ) , \boldsymbol{h}_{t}=f(\boldsymbol{h}_{t-1},\boldsymbol{x}_{t}), ht=f(ht1,xt),

其中 h 0 = 0 {}_{\boldsymbol{h}_{0}=0} h0=0 f ( ⋅ ) f(\cdot) f()为一个非线性的函数,例如前馈神经网络。

下图给出了循环神经网络的示例,其中“延时器”为一个虚拟单元,记录神经元的最近一次或几次活性值。
第九章(1):循环神经网络与pytorch示例(RNN实现股价预测)-LMLPHP

从数学上讲,上文公式可以看成一个动力系统。隐藏层的活性值 h t h_t ht,在很多文献上也称为状态( State ) 或隐状态( Hidden State )。

2. 简单的循环神经网络

简单循环网络( Simple Recurrent Network,SRN)是一个非常简单的循环神经网络,只有一个隐藏层的神经网络. 在一个两层的前馈神经网络中,连接存在相邻的层与层之间,隐藏层的节点之间是无连接的。而简单循环网络增加了从隐藏层到隐藏层的反馈连接。

向量 x t ∈ R M {\boldsymbol{x}}_{t}\in\mathbb{R}^{M} xtRM表示在 t t t时刻的一个输入, h t ∈ R D h_t\in\mathbb{R}^D htRD表示一个隐藏层的状态,这时 h t h_t ht与当前时刻的 x t x_t xt有关系,而且也和上一时刻的 h t − 1 h_{t-1} ht1有关系,简单的循环神经网络在 t t t时刻的更新公式如下所示:
z t = U h t − 1 + W x t + b z_{t}=U\boldsymbol{h}_{t-1}+Wx_{t}+\boldsymbol{b} zt=Uht1+Wxt+b h t = f ( z t ) h_t=f(\boldsymbol{z}_t) ht=f(zt)其中 z t z_{t} zt为隐藏层的净输入, U ∈ R D × D U\in\mathbb{R}^{D\times D} URD×D为状态-状态的矩阵, W ∈ R D × M W\in\mathbb{R}^{D\times M} WRD×M为状态-输入的权重矩阵, b ∈ R D b\in\mathbb{R}^{D} bRD为偏置项, f ( ⋅ ) f(\cdot) f()为一个非线性的激活函数。上述公式可以和写为:
h t = f ( U h t − 1 + W x t + b ) . \boldsymbol{h}_{t}=f(\boldsymbol{Uh}_{t-1}+\boldsymbol{W}\boldsymbol{x}_{t}+\boldsymbol{b}). ht=f(Uht1+Wxt+b).

如果我们把每个时刻的状态都看作前馈神经网络的一层,循环神经网络可以看作在时间维度上权值共享的神经网络。下给出了按时间展开的循环神经网络。

第九章(1):循环神经网络与pytorch示例(RNN实现股价预测)-LMLPHP

3. RNN实现股价预测

建立RNN基于zgpa train.csv数据,建立RNN模型,预测股价。

  • 完成数据预处理,将序列数据转化为可用子RNN输入的数据
  • 对新数据zgpa_test.csv进行预测,可视化结果
    模型结构:RNN 输出有120个神经元,每次使用前8个数据预测第9个数据。
import pandas as pd
import numpy as np
data = pd.read_csv(r'./zgpa_train.csv')
data.head()

第九章(1):循环神经网络与pytorch示例(RNN实现股价预测)-LMLPHP

price = data.loc[:,'close']
price.head()
0    28.78
1    29.23
2    29.26
3    28.50
4    28.67
Name: close, dtype: float64
#归一化处理
price_norm = price/max(price)

%matplotlib inline
from matplotlib import pyplot as plt
fig1 = plt.figure(figsize=(8,5))
plt.plot(price)
plt.title('close price')
plt.xlabel('time')
plt.ylabel('price')
plt.show()

第九章(1):循环神经网络与pytorch示例(RNN实现股价预测)-LMLPHP

#define X and y
#define method to extract X and y
def extract_data(data,time_step):
    X = []
    y = []
    #0,1,2,3...9:10个样本;time_step=8;0,1...7;1,2...8;2,3...9三组(两组样本)
    for i in range(len(data)-time_step):
        X.append([a for a in data[i:i+time_step]])
        y.append(data[i+time_step])
    X = np.array(X)
    X = X.reshape(X.shape[0],X.shape[1],1)
    return X, y
time_step = 8
X,y = extract_data(price_norm,time_step)


# 转换为Tensor
import torch
input_data = torch.tensor(X, dtype=torch.float32)
target_data = torch.tensor(y, dtype=torch.float32).unsqueeze(-1)
# 定义RNN模型
import torch.nn as nn
class RNN(nn.Module):
    def __init__(self, input_size, hidden_size, output_size):  #分别是输入,隐藏和输出的维度
        super(RNN, self).__init__()

        self.hidden_size = hidden_size

        self.rnn = nn.RNN(input_size, hidden_size, batch_first=True)
        self.fc = nn.Linear(hidden_size, output_size)

    def forward(self, x):
        out, _ = self.rnn(x)
        out = self.fc(out[:, -1, :])
        return out


input_size = 1
hidden_size = 120
output_size = 1

# 创建模型实例
rnn = RNN(input_size, hidden_size, output_size)
criterion = nn.MSELoss()
optimizer = torch.optim.Adam(rnn.parameters(), lr=0.01)

# 训练模型
num_epochs = 1000
for epoch in range(num_epochs):
    outputs = rnn(input_data)
    loss = criterion(outputs, target_data)

    optimizer.zero_grad()
    loss.backward()
    optimizer.step()

    if (epoch+1) % 100 == 0:
        print(f"Epoch [{epoch+1}/{num_epochs}], Loss: {loss.item():.10f}")


Epoch [100/1000], Loss: 0.0004473718
Epoch [200/1000], Loss: 0.0006229825
Epoch [300/1000], Loss: 0.0003415935
Epoch [400/1000], Loss: 0.0002980608
Epoch [500/1000], Loss: 0.0002818418
Epoch [600/1000], Loss: 0.0002672504
Epoch [700/1000], Loss: 0.0002543367
Epoch [800/1000], Loss: 0.0002437856
Epoch [900/1000], Loss: 0.0002345658
Epoch [1000/1000], Loss: 0.0002437943
predict = rnn(input_data)
predict_out = []
for i in predict:
    predict_out.append(i)
    
fig2 = plt.figure(figsize=(8,5))
plt.plot(y,label='real price')
plt.plot(predict_out,label='predict price')
plt.title('close price')
plt.xlabel('time')
plt.ylabel('price')
plt.legend()
plt.show()

第九章(1):循环神经网络与pytorch示例(RNN实现股价预测)-LMLPHP

--------推荐专栏--------
🔥 手把手实现Image captioning
💯CNN模型压缩
💖模式识别与人工智能(程序与算法)
🔥FPGA—Verilog与Hls学习与实践
💯基于Pytorch的自然语言处理入门与实践

参考

邱锡鹏,神经网络与深度学习,机械工业出版社,https://nndl.github.io/, 2020.

07-13 22:42