RNN实战具体跑的代码

一、首先先上代码:这个是接pytorch API的调用代码

import torch
import torch.nn as nn
bs, T = 2,3#批次大小,输入序列长度
input_size,hidden_size=2,3#输入特征大小,隐含层特征大小
input = torch.randn(bs,T, input_size)
h_prev = torch.zeros(bs, hidden_size)#初始隐含状态

#step1:调用pytorch API
rnn = nn.RNN(input_size,hidden_size,batch_first=True)
rnn_output,state_final = rnn(input,h_prev.unsqueeze(0))
print(rnn_output)
print(state_final)

参数解释一下:

1、bs(batch_size):就每个批次输入的数据量

2、T(也就是序列长度):

如果是纯时间序列预测的模型,那么在纯时间序列模型中,T。时间步数代表着历史数据中的每个时间点,而模型通过学习这些历史数据来预测未来的结果。

假设我们有一段时间内的房价数据,每个月记录一个时间点的房价。我们想要根据过去几个月的房价数据来预测下个月的房价。在这种情况下,时间步数就是过去几个月的数量。

举个例子,假设我们有过去 12 个月的房价数据,现在想要预测下个月的房价。那么在这个例子中,时间步数就是 12。我们可以用过去 12 个月的房价数据作为输入特征,然后预测下个月的房价作为模型的输出。

        如果是NLP模型的话:

举个例子,假设我们要用RNN模型来预测一个句子中的下一个单词。我们可以将句子分割成单词,并按照单词的顺序依次输入到模型中。在这个例子中,每个时间步对应着句子中的一个单词。

考虑句子:"The cat is sitting on the mat.",如果我们按照单词的顺序将其输入到RNN模型中,则每个单词对应一个时间步。例如:

  • 时间步 1:输入单词 "The"
  • 时间步 2:输入单词 "cat"
  • 时间步 3:输入单词 "is"
  • 时间步 4:输入单词 "sitting"
  • 时间步 5:输入单词 "on"
  • 时间步 6:输入单词 "the"
  • 时间步 7:输入单词 "mat"

在这个例子中,整个句子被分成了7个时间步,每个时间步上都有相应的输入数据。模型在每个时间步上接收输入并产生输出,从而对整个序列进行处理。

3、layer 层

  • input_size输入特征的维度大小。

  • hidden_size:隐含层(隐藏层)的特征维度大小。

  • input:输入数据,形状为(batch_size, sequence_length, input_size)。

  • h_prev:初始隐含状态,形状为(batch_size, hidden_size)。在这里,初始隐含状态被初始化为全零张量。

  • rnn_output:这是 RNN 模型的输出结果。它是一个张量,包含了每个时间步的隐含状态的输出。形状为 (batch_size, sequence_length, hidden_size),其中 batch_size 表示批次大小,sequence_length 表示序列长度,hidden_size 表示隐含状态的特征维度大小。

  • state_final:这是 RNN 模型的最终隐含状态。它表示 RNN 模型在整个序列上的最后一个时间步的隐含状态。形状为 (num_layers, batch_size, hidden_size),其中 num_layers 表示 RNN 模型的层数,通常为 1。

以上解释还是有些抽象,我举个例子:

import torch
import torch.nn as nn

# 输入数据 input,形状为 (3, 5, 1),表示 3 个样本,每个样本序列长度为 5,每个时间步的输入特征维度为 1
input = torch.randn(3, 5, 1)

# 初始隐含状态 h_prev,形状为 (3, 10),表示 3 个样本,隐含状态的特征维度为 10
h_prev = torch.zeros(3, 10)

# 定义 RNN 模型
rnn = nn.RNN(input_size=1, hidden_size=10, batch_first=True)

# 将输入数据和初始隐含状态输入到 RNN 模型中
rnn_output, state_final = rnn(input, h_prev.unsqueeze(0))

# 输出结果 rnn_output 的形状为 (3, 5, 10),表示 3 个样本,每个样本序列长度为 5,每个时间步的隐含状态的特征维度为 10
# 最终的隐含状态 state_final 的形状为 (1, 3, 10),表示 1 层 RNN 模型,3 个样本,隐含状态的特征维度为 10

这里的 rnn_output 包含了每个时间步的隐含状态的输出,state_final 是整个序列上最后一个时间步的隐含状态。h_prev.unsqueeze(0)这个什么意思?

h_prev.unsqueeze(0)表示对初始隐含状态 h_prev 进行操作,使用 unsqueeze(0) 方法在第 0 维度上增加一个维度。

具体来说,假设 h_prev 的形状是 (3, 10),其中 3 是批次大小,10 是隐含状态的特征维度。那么使用 unsqueeze(0) 方法之后,h_prev 的形状将变为 (1, 3, 10)

这个操作是为了符合 RNN 模型接受初始隐含状态的要求。在 PyTorch 中,RNN 模型期望初始隐含状态的形状为 (num_layers, batch_size, hidden_size),其中 num_layers 是 RNN 模型的层数,通常为 1。因此,我们需要对初始隐含状态进行相应的维度调整,以适应模型的输入要求。

所以,h_prev.unsqueeze(0) 的作用是将原始的初始隐含状态 h_prev 转换为符合 RNN 模型输入要求的形状。

二、手写一个rnn_forward函数,实现RNN计算原理

解释一下这里的ht到底是什么意思RNN实战具体跑的代码_第1张图片在这个公式中,ht​ 表示RNN模型在时间步 t 的隐含状态,通常也被称为隐藏状态或者记忆状态。RNN(循环神经网络)的核心是根据当前的输入xt​ 和前一个时间步的隐含状态 ℎt−1来计算当前时间步的隐含状态 ht​。

RNN实战具体跑的代码_第2张图片

具体来说:会有一个叠加的过程

  • xt​ 是当前时间步的输入,通常是一个特征向量。
  • Wih​ 是输入到隐含层的权重矩阵。
  • bih​ 是输入到隐含层的偏置向量。
  • Whh​ 是隐含层到隐含层的权重矩阵。
  • bhh​ 是隐含层到隐含层的偏置向量。
  • tanh 是双曲正切函数,用于加入非线性。
    #step2: 手写一个RNN forward,实现RNN的计算原理
    def run_forward(input,weight_ih,weitht_hh,bias_ih,bias_hh,h_prev):
        bs, T, input_size = input.shape
        h_dim = weight_ih.shape[0]
        h_out = torch.zeros(bs, T, h_dim)#初始化一个输出(状态)矩阵
    
        for t in range(T):
            x = input[:,t,:].unsqueeze(2)#获取当前时刻输入特征,bs*input_size*1
            w_ih_batch = weight_ih.unsqueeze(0).tile(bs,1,1)#ba*h_dim*input_size
            w_hh_batch = weight_hh.unsqueeze(0),tile(bs,1,1)#bs*h_dim
    
            w_times_x = torch.bmm(w_ih_batch,x).squeeze(-1)#bs*h_dim
            w_times_h = torch.bmm(w_hh_batch,h_prev.unsqueeze(2).squeeze(-1))#bs*h_dim
            h_prev = torch.tanh(w_times_h+bias_ih+weitht_hh)
    
            h_out[:,t,:] = h_prev
        return h_out,h_prev.unsqueeze(0)

    最后得到的就是ht

你可能感兴趣的:(rnn,人工智能,深度学习)