Pytorch 循环神经网络 nn.RNN() nn.RNNCell() nn.Parameter()不同方法实现

本文详细介绍了在Pytorch中如何使用nn.RNN(), nn.RNNCell()以及nn.Parameter()实现循环神经网络,包括RNN的网络结构、关键公式、维度解析,并对比了RNNCell和GRU、LSTM的差异,同时展示了自己定义参数实现RNN的示例。" 88751632,8454797,机器学习初学者:简单线性回归实战,"['机器学习', '梯度下降', '线性回归']

RNN

网络结构

一个典型的单层RNN网络,结果如下所示。其实很简单就是一个神经元(蓝色模块),针对时序输入信号分别输入网络中,网络再每个时序进行输出,其中通过一个状态量记录时序信息。
在这里插入图片描述
多层的RNN,上一次的输出ht是下一层的输入。
在这里插入图片描述

关键公式

RNN的关键特点隐层状态变量 H t \boldsymbol{H}_{t} Ht,用于存储时序信息。
H t = ϕ ( X t W x h + H t − 1 W h h + b h ) \boldsymbol{H}_{t}=\phi\left(\boldsymbol{X}_{t} \boldsymbol{W}_{x h}+\boldsymbol{H}_{t-1} \boldsymbol{W}_{h h}+\boldsymbol{b}_{h}\right) Ht=ϕ(XtWxh+Ht1Whh+bh)

O t = H t W h q + b q \boldsymbol{O}_{t}=\boldsymbol{H}_{t} \boldsymbol{W}_{h q}+\boldsymbol{b}_{q} Ot=HtWhq+bq
多数网络会直接所有时序的 H \boldsymbol{H} H作为输出

网络维度

输入数据 X \boldsymbol{X} X维度表示[seq len, batch, h dim] =>[序列长度,batch, 序列的表示维度]=> [单词数, 句子数, 词维度]

刚开始接触RNN会觉得这个输入形式有点怪,为什么batch维不是在0维度上。这里需要理解RNN的运算特点,RNN网络每次送入的数据 X t \boldsymbol{X}_{t} Xt维度恰好就是[b, h dim],循环送入seq len次。

X t \boldsymbol{X}_{t} Xt:维度[bath, input_dim]
W x h \boldsymbol{W}_{x h} Wxh:维度[input_dim, hidden_len]
H t − 1 \boldsymbol{H}_{t-1} Ht1:维度[batch, hidden_len]
W h h \boldsymbol{W}_{h h} Whh:维度[hidden_len, hidden_len]
b h \boldsymbol{b}_{h} bh:维度[hidden_len]
H t \boldsymbol{H}_{t} Ht:维度[batch, hidden_len]
输出层
O t \boldsymbol{O}_{t} Ot:维度[batch, out_dim]
W h q \boldsymbol{W}_{h q} Whq:维度[hidden_len, out_dim]
b q \boldsymbol{b}_{q} bq:维度[out_dim]

nn.RNN

构建一个 h_dim=10, hidden_len=20的2层RNN网络,同时我们打印出网络中的权重和偏差,以及shape

import  torch
from    torch import nn
from    torch.nn import functional as F

rnn = nn.RNN(input_size=10, hidden_size=20, num_layers=2)
print(rnn._parameters.keys())
print(rnn.weight_ih_l0.shape)
print(rnn.weight_hh_l0.shape)
print(rnn.bias_ih_l0.shape)
print(rnn.bias_hh_l0.shape)

odict_keys([‘weight_ih_l0’, ‘weight_hh_l0’, ‘bias_ih_l0’, ‘bias_hh_l0’, ‘weight_ih_l1’, ‘weight_hh_l1’, ‘bias_ih_l1’, ‘bias_hh_l1’])
torch.Size([20, 10])
torch.Size([20, 20])
torch.Size([20])
torch.Size([20])

结构上每一层四组参数,即两组W和b,没有最后输出层O的操作,故没有权重和偏差
可见Torch的RNN模型与表达式 H t = ϕ ( X t W x h + H t − 1 W h h + b h ) \boldsymbol{H}_{t}=\phi\left(\boldsymbol{X}_{t} \boldsymbol{W}_{x h}+\boldsymbol{H}_{t-1} \boldsymbol{W}_{h h}+\boldsymbol{b}_{h}\right) Ht=ϕ(XtWxh+Ht1Whh+bh)中的W和b完全对应,其中末尾的l0和l1表示layer层数编号。维度也刚好符合之前的推导。

  • weight_ih_l0 如果对应
<think> 首先,用户的问题是:“我想了解torch.nn.RNN方法中num_layer参数的作用”,翻译成英文是“I want to know the role of the num_layer parameter in the torch.nn.RNN method”。 根据系统级指令: - 所有行内数学表达式必须使用$...$格式。 - 独立公式单独成段并使用$$...$$格式。 - LaTeX语法正确。 - 使用中文回答。 - 生成相关问题。 - 回答中引用的段落末尾自然地添加引用标识,如[^1]。 我需要参考用户提供的引用内容: - 引用[1]:解释了input_size, hidden_size, num_layers,并给出了一个例子:num_layers=2。 - 引用[2]:也解释了num_layers作为纵向隐藏层的堆叠层数。 - 引用[3]:类似于引用[1],num_layers=2。 - 引用[4]:是关于torch.nn的其他函数,与RNN直接相关度不高,但可以忽略。 关键点: - num_layers参数指定了RNN模型的纵向堆叠层数。这意味着RNN可以有多个层,每个层处理输入序列的输出作为下一个层的输入。 - 在PyTorch的`torch.nn.RNN`中,num_layers控制隐藏层的深度。 从引用[1]的例子: - `rnn = nn.RNN(10, 20, 2)`:num_layers=2。 - 输出hn.shape是(2, 20),表示有两个层的隐藏状态。 从引用[2]: - hidden_size是横向的输出序列长度(即每个时间步的隐藏状态维度)。 - num_layers是纵向的堆叠层数(隐藏层的层数)。 所以,num_layers的作用是定义RNN的深度,即有多少个RNN层堆叠在一起。每个层都有自己的权重和隐藏状态。 在回答中,我应该: - 用中文解释清楚。 - 结构清晰:简要介绍num_layers,然后用例子说明。 - 自然地添加引用标识。例如,基于引用[1]和[2],在解释后添加[^1]或[^2]。 回答结构: 1. 介绍num_layers参数的作用。 2. 解释其含义:堆叠RNN层的数量。 3. 举例子说明输出形状的变化。 4. 总结。 最后,生成相关问题,基于系统指令示例。 生成相关问题: - 类似于快速排序的例子,我应该列出2-3个相关问题。 - 可能的RNN相关问题: 1. 如何选择num_layers的值? 2. 多层RNN有什么优缺点? 3.PyTorch中如何初始化多层RNN的隐藏状态? 确保回答真实可靠,基于提供的引用和一般知识。 完整回答: - 开头直接回答问题。 - 解释。 - 代码示例或形状说明。 - 引用标识。 - 相关问题。 </think> ### torch.nn.RNN方法中num_layer参数的作用 在PyTorch的`torch.nn.RNN`模块中,`num_layers`参数指定了RNN模型的纵向堆叠层数(即隐藏层的深度)。这是一个关键参数,用于构建多层RNN架构。下面我来逐步解释其作用和影响。 #### 1. **参数定义** - **`num_layers`**:表示RNN的隐藏层数量。当设置为大于1的值时,它会创建多个RNN层堆叠在一起(纵向堆叠)。 - 每个层都有自己的权重和隐藏状态,上一层的输出作为下一层的输入。这允许模型学习更复杂的时序依赖关系[^1][^2]。 - 公式上,对于输入序列$ x_t $: - 第一层:$ h_t^{(1)} = \text{RNN}(x_t, h_{t-1}^{(1)}) $ - 后续层:$ h_t^{(l)} = \text{RNN}(h_t^{(l-1)}, h_{t-1}^{(l)}) \quad \text{where} \quad l \geq 2 $ 其中$ l $表示层索引,$ h_t^{(l)} $是该层在时间步$ t $的隐藏状态。 #### 2. **影响输出形状** `num_layers`直接影响输出的隐藏状态形状: - **输出`output`**:形状为`(sequence_length, batch_size, hidden_size)`,表示序列中每个时间步的最终层输出。 - **最终隐藏状态`hn`**:形状为`(num_layers, batch_size, hidden_size)`,保存所有层的最后一个时间步的隐藏状态。 例如: - 如果`num_layers=1`(单层RNN): - `hn.shape` 为 `(1, batch_size, hidden_size)` - 如果`num_layers=2`(双层RNN): - `hn.shape` 为 `(2, batch_size, hidden_size)`,其中第一行是第一层的状态,第二行是第二层的状态[^1][^3]。 #### 3. **实际例子说明** 参考引用中的代码示例: ```python import torch import torch.nn as nn # 参数设置 input_size = 10 # 输入向量长度 hidden_size = 20 # 隐藏状态维度 num_layers = 2 # num_layers=2表示双层RNN batch_size = 1 # 批大小为1 # 创建RNN模型 rnn = nn.RNN(input_size, hidden_size, num_layers) input_tensor = torch.randn(3, batch_size, input_size) # 序列长度=3 h0 = torch.randn(num_layers, batch_size, hidden_size) # 初始隐藏状态 # 前向传播 output, hn = rnn(input_tensor, h0) print(output.shape) # 输出形状应为: torch.Size([3, 1, 20]) print(hn.shape) # hn形状应为: torch.Size([2, 1, 20]) ``` - **解释**: - 当`num_layers=2`时,`hn.shape`为`(2, 1, 20)`,表示有两个独立的隐藏层状态。 - 第一层处理原始输入序列,第二层以第一层的输出作为输入,学习更高抽象的特征[^2][^3]。 #### 4. **为什么使用多层RNN?** - **优点**:增加模型深度可以捕捉更复杂的时序模式(如长期依赖),提升表达能力,适用于较长的序列任务(如语言建模)。 - **缺点**:层数过多会增加训练难度(如梯度消失问题)和计算开销。一般实践中,`num_layers`的值通常在1-4之间,需根据任务调整[^1]。 总结:`num_layers`参数定义了RNN的纵向深度,通过堆叠多层隐藏层来提高模型的学习能力。在PyTorch实现中,它直接影响隐藏状态`hn`的形状和输出序列的处理方式[^1][^2]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值