【图解】RNN模型结构详解、教程

一、图解RNN神经网络

注意点:rnn网络权重矩阵h是自带激活函数的默认tanh

参数表如下:

二、参考学习过的博客

Pytorch循环神经网络(RNN)快速入门与实战_torch rnn-CSDN博客

这个文章中的batch_first=true输入的参数是错的,不要看他的代码,他那个hidden_prev 压根自己没搞懂怎么回事。

这个博客提供了两种应用及两种RNN连接方式

第一种:

如,现在要用RNN做房价预测。如果目标是 输入今年1-6月的房价,输出是7-12月的房价,那可以直接将隐含层的输出作为网络输出。

第二种:

如果目标是 输入今年1-12月份的房价,输出是预测的明年1月的房价,那此时循环神经网络经过隐含层后,可以接入一个全连接层,也可以将最后时刻隐含层的输出作为网络输出,分别如下图(a)(b)所示。

初学者入门,使用pytorch构建RNN网络

深度学习之RNN(循环神经网络)-CSDN博客

PyTorch基础入门七:PyTorch搭建循环神经网络(RNN)_rnn代码pytorch-CSDN博客

RNN应用想法:RNN+PID控制调参->提高PID稳定性及其响应速度

三、nn.rnn运算过程

import torch
import torch.nn as nn

# 输入数据
x = torch.tensor([[[1.0], [2.0], [3.0]], [[4.0], [5.0], [6.0]]], dtype=torch.float32)
# 初始隐藏状态
h0 = torch.zeros(1, 2, 2)  # batch_size=2

# 定义简单的RNN模型
rnn = nn.RNN(input_size=1, hidden_size=2, batch_first=True)

# 循环遍历时间步
out, _ = rnn(x, h0)
print("Output shape:", out.shape)
print("Output values:")
print(out)

当执行 out, _ = rnn(x, h0) 时,RNN 模型会按照序列长度遍历每个时间步,计算每个时间步的输出和隐藏状态。具体步骤如下:

  1. 初始状态设置: 初始隐藏状态 h0 的形状为 [1, 2, 2],表示有两个样本,每个样本的隐藏状态大小为 2。
  2. 循环遍历时间步: RNN 层会按照序列长度遍历每个时间步。在每个时间步,它会接收输入 x 中的一个序列元素,并使用当前时间步的输入和前一个时间步的隐藏状态来计算当前时间步的输出和隐藏状态。
  3. 计算输出和隐藏状态: 在每个时间步,RNN 层会执行以下计算:
    • 将当前时间步的输入 x[:, t, :](其中 t 是当前时间步的索引)和前一个时间步的隐藏状态作为输入,计算当前时间步的输出和隐藏状态。
    • 输出 out[:, t, :] 的形状为 [2, 2],表示当前时间步的输出。其中,2 表示 batch size,2 表示隐藏状态的大小。
    • 隐藏状态 _[:, :, :] 的形状与 h0 相同,表示当前时间步的隐藏状态,它将作为下一个时间步的输入隐藏状态。
  1. 下一个序列数据计算:

1. h0 是一个张量,因此在每次计算下一个序列数据时,都需要重新创建一个新的初始隐藏状态 h0,并将其与当前序列的最终隐藏状态相等。

2. 当处理完当前序列的所有时间步后,如果有下一个序列数据,那么下一个序列的初始隐藏状态 h0 将会根据上一个序列的最终隐藏状态来更新。下面举个例子:

在这个例子中,我们首先处理第一个序列 x1,得到输出 out1 和最终隐藏状态 h1。然后,我们将 h1 作为第二个序列 x2 的初始隐藏状态,并处理第二个序列,得到输出 out2。这样就实现了上一个序列的最终隐藏状态传递给下一个序列的初始隐藏状态。

import torch
import torch.nn as nn

# 输入数据(两个序列)
x1 = torch.tensor([[[1.0], [2.0], [3.0]]], dtype=torch.float32)  # 第一个序列
x2 = torch.tensor([[[4.0], [5.0], [6.0]]], dtype=torch.float32)  # 第二个序列
# 初始隐藏状态
h0 = torch.zeros(1, 1, 2)  # 初始隐藏状态

# 定义简单的RNN模型
rnn = nn.RNN(input_size=1, hidden_size=2, batch_first=True)

# 处理第一个序列数据
out1, h1 = rnn(x1, h0)
print("Output for sequence 1:", out1)

# 处理第二个序列数据,将上一个序列的最终隐藏状态传递给下一个序列的初始隐藏状态
out2, _ = rnn(x2, h1)
print("Output for sequence 2:", out2)

总的来说,在每次计算下一个序列数据时,初始隐藏状态 h0 并不会发生实际的改变,而是根据上一个序列的最终隐藏状态重新创建一个新的初始隐藏状态,用于处理下一个序列数据。

四、RNN数据输入、输出

1. 输入

# 定义RNN模型
class RNNCustom(nn.Module):
    def __init__(self, input_size, hidden_size, output_size):
        super(RNNCustom, 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):
        h0 = torch.zeros(1, x.size(0), self.hidden_size)
        out, _ = self.rnn(x, h0)
        out = self.fc(out[:, -1, :])
        return out

batch_first=True

x[batch_size, sequence_length, input_size],即批量大小、序列长度、输入数据维度。

h0[num_layers * num_directions, batch_size, hidden_size],即层数乘以方向数、批量大小、隐藏层大小。

batch_first=False

  • x [sequence_length, batch_size, input_size],即序列长度、批量大小、输入数据维度。
  • h0[num_layers * num_directions, batch_size, hidden_size],即层数乘以方向数、批量大小、隐藏层大小。

2. 输出

out[batch size,sequence_lengthhidden_size]

__ 是 RNN 在最后一个时间步的隐藏状态,其形状与初始隐藏状态 h0 相同, batch size,序列长度(因为我们是按照 batch_first=True 的方式计算的),隐藏状态的大小。 _ 中的参数是模型在最后一个时间步的隐藏状态值,可以在需要时用于下一个序列的预测或其他操作。

五、单、双向RNN

循环神经网络的改进:多层RNN、双向RNN与预训练-CSDN博客

如果是单向RNN当输出b3的时候模型已经理解过了a3之前的输入

如果是双向RNN当输出b3时模型已经理解过了所有的输入

在RNN中,方向数指的是RNN的方向数量,通常有两种情况:

  1. 单向RNN:只有一个方向,即从序列的第一个元素到最后一个元素的方向。
  2. 双向RNN:有两个方向,分别是从序列的第一个元素到最后一个元素的方向和从最后一个元素到第一个元素的方向。

在双向RNN中,隐藏层的输出是由正向和反向两个方向的隐藏状态拼接而成的。因此,当使用双向RNN时,隐藏状态的形状中会包含方向数这一维度。


在PyTorch中,可以通过nn.RNNnn.LSTM等模块来定义双向RNN。这些模块具有一个bidirectional参数,当设置为True时,表示创建一个双向的RNN。以下是一个使用双向LSTM的示例:

import torch
import torch.nn as nn

# 定义双向LSTM
input_size = 10
hidden_size = 20
num_layers = 2
batch_size = 3
seq_length = 5

lstm = nn.LSTM(input_size=input_size, hidden_size=hidden_size, num_layers=num_layers, bidirectional=True, batch_first=True)

# 创建输入数据
x = torch.randn(batch_size, seq_length, input_size)

# 初始化隐藏状态
h0 = torch.randn(num_layers * 2, batch_size, hidden_size)  # 注意隐藏状态的维度是层数乘以2

# 前向计算
output, (hn, cn) = lstm(x, (h0, h0))

print("Output shape:", output.shape)
print("Hidden state shape:", hn.shape)

nn.RNN新序列数据进入会清空h0么?

在每个序列数据进入RNN模型之前,都会将隐藏状态h0初始化为零向量。然后,对于每个序列数据,RNN模型将其输入序列数据和当前的隐藏状态进行计算,并输出新的隐藏状态。在这个过程中,隐藏状态h0的值会随着每个序列数据的输入而更新,但不会在每次计算之间清空为零。

换句话说,隐藏状态h0在整个self.rnn(x, h0)计算的过程中会被无限计算下去,而不会在每次输入新的序列数据时被清空为零。这样做的目的是为了在处理序列数据时保留之前序列的信息,并将其传递到下一个序列中。

六、RNN应用案例

RNN(循环神经网络)在自然语言处理(NLP)、时间序列预测、语音识别等领域有许多应用案例。以下是一些常见的应用案例:

  1. 语言建模:RNN 可用于生成文本,包括生成诗歌、故事等。通过训练一个 RNN 模型,可以学习语言的概率分布,并生成类似人类语言的文本。
  2. 机器翻译:RNN 在机器翻译中广泛应用。通过将输入语句编码成一个固定长度的向量,然后将该向量解码成目标语言的句子,可以实现不同语言之间的翻译。
  3. 情感分析:RNN 可以用于情感分析,即分析文本中的情感倾向。通过训练一个 RNN 模型,可以判断一段文本是正面的、负面的还是中性的。
  4. 时间序列预测:RNN 可以用于时间序列数据的预测,如股票价格预测、天气预测等。通过训练一个 RNN 模型,可以学习时间序列数据中的模式,并用于未来数据的预测。
  5. 语音识别:RNN 在语音识别中也有广泛应用。通过将语音信号转换成特征向量序列,并输入到 RNN 模型中进行处理,可以实现语音识别的功能。
  6. 手写识别:RNN 可以用于手写识别,如识别手写数字、汉字等。通过训练一个 RNN 模型,可以识别手写输入的内容。

七、RNN缺点

李宏毅:不容易被平行化(读取数据必须是按顺序输入然后理解)

  • 26
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

AIScholar_lrm

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值