3.1.6 RNN 的 API 使用 — 详细讲解一、概述PyTorch 提供了torch.nn.RNN模块用于构建循环神经网络Recurrent Neural Network。该模块是 PyTorch 对 RNN 的标准实现功能强大具备以下核心能力支持单层或多层堆叠通过num_layers控制支持双向 RNN通过bidirectional控制可同时捕捉前向和后向的序列依赖适用于各类序列建模任务文本分类、序列标注、命名实体识别、时间序列预测等该模块是传统 RNN 的基础组件理解其 API 是后续学习 LSTM、GRU 的前提。二、构造函数参数详解torch.nn.RNN(input_size,# 必填输入特征维度hidden_size,# 必填隐藏状态维度num_layers1,# RNN 层数nonlinearitytanh,# 激活函数biasTrue,# 是否使用偏置batch_firstFalse,# 批次维度是否在第一维dropout0.0,# 层间 dropout 概率bidirectionalFalse,# 是否双向deviceNone,# 设备dtypeNone,# 数据类型)各参数详细说明参数类型默认值详细说明input_sizeint必填每个时间步输入的特征维度。在 NLP 任务中通常是词向量的维度。例如若使用 300 维的 Word2Vec 词向量则input_size300若使用 PyTorch 的nn.Embedding(vocab_size, 128)则input_size128hidden_sizeint必填隐藏状态的维度。这个值决定了 RNN 的记忆容量——越大模型表达能力越强但参数量和过拟合风险也随之增加。合理的值通常在 128~1024 之间需根据任务复杂度调整num_layersint1RNN 的堆叠层数。当num_layers ≥ 2时第 i 层的输出会作为第 i1 层的输入形成深层 RNN。深层 RNN 能学习更抽象的时序特征但也会加重梯度消失问题nonlinearitystrtanh激活函数可选tanh或relu。tanh是 RNN 的传统选择输出范围 [-1,1]relu可在一定程度上缓解梯度消失但可能导致神经元死亡biasboolTrue是否在线性变换中使用偏置项bbb。计算隐藏状态时公式为httanh(WihxtbihWhhht−1bhh)h_t \tanh(W_{ih}x_t b_{ih} W_{hh}h_{t-1} b_{hh})httanh(WihxtbihWhhht−1bhh)关闭后则无偏置项batch_firstboolFalse控制输入和输出张量的维度排列顺序。默认(seq_len, batch, feature)设为True则变为(batch, seq_len, feature)。强烈建议设为 True这样与 DataLoader 的输出格式一致代码更直观dropoutfloat0.0Dropout 概率用于防止过拟合。仅当num_layers ≥ 2时才生效且只作用于除最后一层之外的所有层之间的连接。原理是在训练时随机将一部分神经元的输出置零bidirectionalboolFalse是否为双向 RNN。设为True后模型会同时学习正向序列和反向序列两个方向的信息num_directions从 1 变为 2隐藏状态维度会翻倍devicestr或torch.deviceNone模块运行的设备。如cuda、cuda:0、cpu。若不指定模块将在当前默认设备上创建参数dtypetorch.dtypeNone模块参数的数据类型。如torch.float32默认、torch.float64。混合精度训练时可设为torch.float16三、输入与输出详解3.1 调用方式rnntorch.nn.RNN(input_size,hidden_size,...)output,h_nrnn(input,h_0)# h_0 是可选的初始隐藏状态3.2 输入参数参数形状batch_firstFalse形状batch_firstTrue说明input(seq_len, batch_size, input_size)(batch_size, seq_len, input_size)输入序列。seq_len是序列长度如句子中的词数batch_size是批次大小input_size是每个时间步的特征维度h_0可选(num_layers × num_directions, batch_size, hidden_size)同左初始隐藏状态。若不传入PyTorch 自动初始化为全零张量。当需要状态传递如生成式解码时显式传入注意h_0的第一维 num_layers × num_directions。单向时num_directions 1双向时num_directions 2。3.3 输出参数参数形状batch_firstFalse形状batch_firstTrue说明output(seq_len, batch_size, num_directions × hidden_size)(batch_size, seq_len, num_directions × hidden_size)每个时间步的隐藏状态仅包含最后一层的所有时间步输出。如果bidirectionalTrue每个时间步的最后一维是正向和反向隐藏状态的拼接h_n(num_layers × num_directions, batch_size, hidden_size)同左最后一个时间步的隐藏状态。包含所有层、所有方向的最终状态。可用于初始化下一个 batch 的h_0实现跨 batch 状态传递3.4output与h_n的关系单层单向output[:, -1, :] h_n[0]——output的最后一个时间步等于h_n的最后一层多层单向output[:, -1, :] h_n[-1]——output的最后一个时间步等于h_n的最后一层单层双向output每个时间步 (正向隐状态, 反向隐状态)h_n[0] 正向最后一个时间步h_n[1] 反向第一个时间步即反向视角的最后一个多层双向h_n按层和方向交错排列顺序为(L1正, L1反, L2正, L2反, ...)四、四种常见结构配置4.1 单层单向 — 最基础importtorch.nnasnn rnnnn.RNN(input_size128,hidden_size256,num_layers1,batch_firstTrue)# 输入输出形状# input : (batch, seq_len, 128)# output : (batch, seq_len, 256)# h_n : (1, batch, 256)特点结构最简单参数量最少训练最快。适用场景短文本分类、简单序列标注等不需要深层语义理解的任务。4.2 多层单向 — 深度堆叠rnnnn.RNN(input_size128,hidden_size256,num_layers3,batch_firstTrue)# 输入输出形状# input : (batch, seq_len, 128)# output : (batch, seq_len, 256)# h_n : (3, batch, 256)特点通过堆叠多层 RNN每一层学习不同粒度的时序特征——低层学局部模式高层学全局依赖。注意事项层数过多会显著增加训练时间深度增加会加重梯度消失问题通常 LSTM/GRU 更适合深层堆叠建议配合dropout使用如dropout0.3对层间连接进行正则化适用场景较长序列的建模任务需要多层次时序特征提取。4.3 单层双向 — 双向上下文rnnnn.RNN(input_size128,hidden_size256,num_layers1,bidirectionalTrue,batch_firstTrue)# 输入输出形状# input : (batch, seq_len, 128)# output : (batch, seq_len, 512) ← 256 × 2正向反向拼接# h_n : (2, batch, 256) ← 1层 × 2方向特点模型同时从正向从左到右和反向从右到左处理序列每个时间步都能感知完整上下文。工作原理正向 RNN 按x1→x2→⋯→xTx_1 \to x_2 \to \dots \to x_Tx1→x2→⋯→xT处理反向 RNN 按xT→xT−1→⋯→x1x_T \to x_{T-1} \to \dots \to x_1xT→xT−1→⋯→x1处理每个时间步ttt的输出 [正向隐状态, 反向隐状态]拼接后维度翻倍适用场景命名实体识别NER判断一个词是否是人名/地名时需要看上下文文本分类需要整句的全面语义机器翻译的编码器4.4 多层双向 — 最强配置rnnnn.RNN(input_size128,hidden_size256,num_layers3,bidirectionalTrue,batch_firstTrue)# 输入输出形状# input : (batch, seq_len, 128)# output : (batch, seq_len, 512) ← 256 × 2# h_n : (6, batch, 256) ← 3层 × 2方向特点多层 双向代表 RNN 家族中最强的表示能力。低层的双向 RNN 捕获局部上下文高层的双向 RNN 在此基础上学习更全局的语义。注意事项参数量大需要在较大的数据集上训练通常需要配合 Dropout 和 Early Stopping 防止过拟合在实际工程中多层双向 LSTM/GRU 比多层双向 RNN 更常用因为 RNN 的梯度消失问题五、完整代码示例5.1 单层单向 RNN — 基础用法importtorchimporttorch.nnasnn# 超参数 batch_size16seq_len20# 序列长度如一个句子有 20 个词input_size128# 词向量维度hidden_size256# 隐藏层维度num_layers2# 堆叠 2 层# 创建 RNN 层 rnnnn.RNN(input_sizeinput_size,hidden_sizehidden_size,num_layersnum_layers,nonlinearitytanh,biasTrue,batch_firstTrue,# 推荐设为 Truedropout0.3,# 层间 Dropout仅 2 层及以上生效bidirectionalFalse,)# 构造输入数据 xtorch.randn(batch_size,seq_len,input_size)# (16, 20, 128)# 可选初始隐藏状态 h0torch.zeros(num_layers,batch_size,hidden_size)# (2, 16, 256)# 前向传播 output,hnrnn(x,h0)print(foutput shape:{output.shape})# torch.Size([16, 20, 256])print(fhn shape:{hn.shape})# torch.Size([2, 16, 256])# 取最后一个时间步 # 常用于文本分类任务中取 句子级 表示last_outputoutput[:,-1,:]# (16, 256)# ↓ 可接入全连接层进行分类# logits nn.Linear(256, num_classes)(last_output)5.2 双向 RNN — 完整上下文感知# 双向 RNN 示例 bi_rnnnn.RNN(input_size128,hidden_size256,num_layers2,batch_firstTrue,bidirectionalTrue,# 开启双向dropout0.3,)xtorch.randn(16,20,128)# (batch, seq_len, input_size)output,hnbi_rnn(x)print(foutput shape:{output.shape})# torch.Size([16, 20, 512]) — 256 × 2print(fhn shape:{hn.shape})# torch.Size([4, 16, 256]) — 2层 × 2方向# 提取双向信息 # output[:, :, :256] → 正向每个时间步的隐藏状态# output[:, :, 256:] → 反向每个时间步的隐藏状态## 注意反向的第一个位置对应原始序列的最后一个词# output[:, -1, :256] → 正向最后一个时间步序列末尾# output[:, 0, 256:] → 反向最后一个时间步序列开头# 文本分类场景拼接正反向最后一个状态 forward_lastoutput[:,-1,:256]# (16, 256) 正向末端backward_lastoutput[:,0,256:]# (16, 256) 反向末端 反向视角的最后combinedtorch.cat([forward_last,backward_last],dim1)# (16, 512)# ↓ 接入分类器# logits nn.Linear(512, num_classes)(combined)5.3 不传 h_0 的简化写法# 大部分场景下不需要显式传入 h_0PyTorch 会自动初始化为全零rnnnn.RNN(128,256,num_layers2,batch_firstTrue)xtorch.randn(16,20,128)output,hnrnn(x)# 自动使用全零的初始隐藏状态# output: (16, 20, 256)# hn: (2, 16, 256)六、关键注意事项6.1batch_first建议设为TruePyTorch RNN 模块的默认输入格式为(seq_len, batch, feature)这与常见的DataLoader输出格式(batch, seq_len, feature)不一致容易造成混淆。建议统一设置batch_firstTrue让数据流转更加直观。6.2dropout仅在多层时生效# num_layers1 时dropout 参数被忽略rnnnn.RNN(128,256,num_layers1,dropout0.5)# ← 这个 dropout 不会生效# num_layers≥2 时dropout 作用于层间连接除最后一层外rnnnn.RNN(128,256,num_layers3,dropout0.3)# ← 在第 1→2、第 2→3 之间施加 dropout6.3 输出output只包含最后一层如果你需要访问所有中间层的输出output满足不了这个需求。但通常这不是问题因为分类任务只需最后一层最后一个时间步序列标注需用最后一层所有时间步如果需要中间层输出做特征融合需自行改写模块6.4 双向 RNN 时输出维度翻倍# 单向output 最后一维 hidden_sizernnnn.RNN(128,256,bidirectionalFalse)# output: (..., 256)# 双向output 最后一维 hidden_size × 2rnnnn.RNN(128,256,bidirectionalTrue)# output: (..., 512)务必注意当 RNN 后接全连接层时全连接层的in_features需要匹配翻倍后的维度6.5h_0的初始化大多数任务中可以用全零初始化省去传h_0的麻烦。但在以下场景中建议显式初始化状态传递stateful RNN将上一个 batch 的h_n.detach()作为下一个 batch 的h_0特殊初始化策略如使用 Xavier/Kaiming 初始化6.6 梯度消失与梯度爆炸这是 RNN 最核心的缺陷。虽然本节讲的是 API 使用但必须了解传统 RNNtorch.nn.RNN在长序列上容易出现梯度消失或梯度爆炸。这是后续引入 LSTM 和 GRU 的根本原因。在实际项目中长序列任务推荐优先使用 LSTM 或 GRU。七、参数维度速查表配置输入形状(batch_firstTrue)输出output形状h_n形状单层单向(B, S, I)(B, S, H)(1, B, H)多层单向(B, S, I)(B, S, H)(L, B, H)单层双向(B, S, I)(B, S, 2H)(2, B, H)多层双向(B, S, I)(B, S, 2H)(2L, B, H)B batch_size, S seq_len, I input_size, H hidden_size, L num_layers八、与后续内容的关系本节讲完 RNN 的 API 后下一节3.1.7存在问题将深入剖析 RNN 的核心缺陷——长期依赖建模困难其根源在于梯度消失反向传播中早期时间步的梯度经过多次tanh导数的连乘每项 ≤1指数级衰减至 0导致模型只能学到短期依赖梯度爆炸若权重过大梯度指数级增长参数更新极不稳定这两个问题直接引出了LSTM第 3.2 节和GRU第 3.3 节它们通过精巧的门控机制有效缓解了上述缺陷成为实际应用中的主流选择。
NLP系列之RNN 的 API 使用 — 详细讲解
3.1.6 RNN 的 API 使用 — 详细讲解一、概述PyTorch 提供了torch.nn.RNN模块用于构建循环神经网络Recurrent Neural Network。该模块是 PyTorch 对 RNN 的标准实现功能强大具备以下核心能力支持单层或多层堆叠通过num_layers控制支持双向 RNN通过bidirectional控制可同时捕捉前向和后向的序列依赖适用于各类序列建模任务文本分类、序列标注、命名实体识别、时间序列预测等该模块是传统 RNN 的基础组件理解其 API 是后续学习 LSTM、GRU 的前提。二、构造函数参数详解torch.nn.RNN(input_size,# 必填输入特征维度hidden_size,# 必填隐藏状态维度num_layers1,# RNN 层数nonlinearitytanh,# 激活函数biasTrue,# 是否使用偏置batch_firstFalse,# 批次维度是否在第一维dropout0.0,# 层间 dropout 概率bidirectionalFalse,# 是否双向deviceNone,# 设备dtypeNone,# 数据类型)各参数详细说明参数类型默认值详细说明input_sizeint必填每个时间步输入的特征维度。在 NLP 任务中通常是词向量的维度。例如若使用 300 维的 Word2Vec 词向量则input_size300若使用 PyTorch 的nn.Embedding(vocab_size, 128)则input_size128hidden_sizeint必填隐藏状态的维度。这个值决定了 RNN 的记忆容量——越大模型表达能力越强但参数量和过拟合风险也随之增加。合理的值通常在 128~1024 之间需根据任务复杂度调整num_layersint1RNN 的堆叠层数。当num_layers ≥ 2时第 i 层的输出会作为第 i1 层的输入形成深层 RNN。深层 RNN 能学习更抽象的时序特征但也会加重梯度消失问题nonlinearitystrtanh激活函数可选tanh或relu。tanh是 RNN 的传统选择输出范围 [-1,1]relu可在一定程度上缓解梯度消失但可能导致神经元死亡biasboolTrue是否在线性变换中使用偏置项bbb。计算隐藏状态时公式为httanh(WihxtbihWhhht−1bhh)h_t \tanh(W_{ih}x_t b_{ih} W_{hh}h_{t-1} b_{hh})httanh(WihxtbihWhhht−1bhh)关闭后则无偏置项batch_firstboolFalse控制输入和输出张量的维度排列顺序。默认(seq_len, batch, feature)设为True则变为(batch, seq_len, feature)。强烈建议设为 True这样与 DataLoader 的输出格式一致代码更直观dropoutfloat0.0Dropout 概率用于防止过拟合。仅当num_layers ≥ 2时才生效且只作用于除最后一层之外的所有层之间的连接。原理是在训练时随机将一部分神经元的输出置零bidirectionalboolFalse是否为双向 RNN。设为True后模型会同时学习正向序列和反向序列两个方向的信息num_directions从 1 变为 2隐藏状态维度会翻倍devicestr或torch.deviceNone模块运行的设备。如cuda、cuda:0、cpu。若不指定模块将在当前默认设备上创建参数dtypetorch.dtypeNone模块参数的数据类型。如torch.float32默认、torch.float64。混合精度训练时可设为torch.float16三、输入与输出详解3.1 调用方式rnntorch.nn.RNN(input_size,hidden_size,...)output,h_nrnn(input,h_0)# h_0 是可选的初始隐藏状态3.2 输入参数参数形状batch_firstFalse形状batch_firstTrue说明input(seq_len, batch_size, input_size)(batch_size, seq_len, input_size)输入序列。seq_len是序列长度如句子中的词数batch_size是批次大小input_size是每个时间步的特征维度h_0可选(num_layers × num_directions, batch_size, hidden_size)同左初始隐藏状态。若不传入PyTorch 自动初始化为全零张量。当需要状态传递如生成式解码时显式传入注意h_0的第一维 num_layers × num_directions。单向时num_directions 1双向时num_directions 2。3.3 输出参数参数形状batch_firstFalse形状batch_firstTrue说明output(seq_len, batch_size, num_directions × hidden_size)(batch_size, seq_len, num_directions × hidden_size)每个时间步的隐藏状态仅包含最后一层的所有时间步输出。如果bidirectionalTrue每个时间步的最后一维是正向和反向隐藏状态的拼接h_n(num_layers × num_directions, batch_size, hidden_size)同左最后一个时间步的隐藏状态。包含所有层、所有方向的最终状态。可用于初始化下一个 batch 的h_0实现跨 batch 状态传递3.4output与h_n的关系单层单向output[:, -1, :] h_n[0]——output的最后一个时间步等于h_n的最后一层多层单向output[:, -1, :] h_n[-1]——output的最后一个时间步等于h_n的最后一层单层双向output每个时间步 (正向隐状态, 反向隐状态)h_n[0] 正向最后一个时间步h_n[1] 反向第一个时间步即反向视角的最后一个多层双向h_n按层和方向交错排列顺序为(L1正, L1反, L2正, L2反, ...)四、四种常见结构配置4.1 单层单向 — 最基础importtorch.nnasnn rnnnn.RNN(input_size128,hidden_size256,num_layers1,batch_firstTrue)# 输入输出形状# input : (batch, seq_len, 128)# output : (batch, seq_len, 256)# h_n : (1, batch, 256)特点结构最简单参数量最少训练最快。适用场景短文本分类、简单序列标注等不需要深层语义理解的任务。4.2 多层单向 — 深度堆叠rnnnn.RNN(input_size128,hidden_size256,num_layers3,batch_firstTrue)# 输入输出形状# input : (batch, seq_len, 128)# output : (batch, seq_len, 256)# h_n : (3, batch, 256)特点通过堆叠多层 RNN每一层学习不同粒度的时序特征——低层学局部模式高层学全局依赖。注意事项层数过多会显著增加训练时间深度增加会加重梯度消失问题通常 LSTM/GRU 更适合深层堆叠建议配合dropout使用如dropout0.3对层间连接进行正则化适用场景较长序列的建模任务需要多层次时序特征提取。4.3 单层双向 — 双向上下文rnnnn.RNN(input_size128,hidden_size256,num_layers1,bidirectionalTrue,batch_firstTrue)# 输入输出形状# input : (batch, seq_len, 128)# output : (batch, seq_len, 512) ← 256 × 2正向反向拼接# h_n : (2, batch, 256) ← 1层 × 2方向特点模型同时从正向从左到右和反向从右到左处理序列每个时间步都能感知完整上下文。工作原理正向 RNN 按x1→x2→⋯→xTx_1 \to x_2 \to \dots \to x_Tx1→x2→⋯→xT处理反向 RNN 按xT→xT−1→⋯→x1x_T \to x_{T-1} \to \dots \to x_1xT→xT−1→⋯→x1处理每个时间步ttt的输出 [正向隐状态, 反向隐状态]拼接后维度翻倍适用场景命名实体识别NER判断一个词是否是人名/地名时需要看上下文文本分类需要整句的全面语义机器翻译的编码器4.4 多层双向 — 最强配置rnnnn.RNN(input_size128,hidden_size256,num_layers3,bidirectionalTrue,batch_firstTrue)# 输入输出形状# input : (batch, seq_len, 128)# output : (batch, seq_len, 512) ← 256 × 2# h_n : (6, batch, 256) ← 3层 × 2方向特点多层 双向代表 RNN 家族中最强的表示能力。低层的双向 RNN 捕获局部上下文高层的双向 RNN 在此基础上学习更全局的语义。注意事项参数量大需要在较大的数据集上训练通常需要配合 Dropout 和 Early Stopping 防止过拟合在实际工程中多层双向 LSTM/GRU 比多层双向 RNN 更常用因为 RNN 的梯度消失问题五、完整代码示例5.1 单层单向 RNN — 基础用法importtorchimporttorch.nnasnn# 超参数 batch_size16seq_len20# 序列长度如一个句子有 20 个词input_size128# 词向量维度hidden_size256# 隐藏层维度num_layers2# 堆叠 2 层# 创建 RNN 层 rnnnn.RNN(input_sizeinput_size,hidden_sizehidden_size,num_layersnum_layers,nonlinearitytanh,biasTrue,batch_firstTrue,# 推荐设为 Truedropout0.3,# 层间 Dropout仅 2 层及以上生效bidirectionalFalse,)# 构造输入数据 xtorch.randn(batch_size,seq_len,input_size)# (16, 20, 128)# 可选初始隐藏状态 h0torch.zeros(num_layers,batch_size,hidden_size)# (2, 16, 256)# 前向传播 output,hnrnn(x,h0)print(foutput shape:{output.shape})# torch.Size([16, 20, 256])print(fhn shape:{hn.shape})# torch.Size([2, 16, 256])# 取最后一个时间步 # 常用于文本分类任务中取 句子级 表示last_outputoutput[:,-1,:]# (16, 256)# ↓ 可接入全连接层进行分类# logits nn.Linear(256, num_classes)(last_output)5.2 双向 RNN — 完整上下文感知# 双向 RNN 示例 bi_rnnnn.RNN(input_size128,hidden_size256,num_layers2,batch_firstTrue,bidirectionalTrue,# 开启双向dropout0.3,)xtorch.randn(16,20,128)# (batch, seq_len, input_size)output,hnbi_rnn(x)print(foutput shape:{output.shape})# torch.Size([16, 20, 512]) — 256 × 2print(fhn shape:{hn.shape})# torch.Size([4, 16, 256]) — 2层 × 2方向# 提取双向信息 # output[:, :, :256] → 正向每个时间步的隐藏状态# output[:, :, 256:] → 反向每个时间步的隐藏状态## 注意反向的第一个位置对应原始序列的最后一个词# output[:, -1, :256] → 正向最后一个时间步序列末尾# output[:, 0, 256:] → 反向最后一个时间步序列开头# 文本分类场景拼接正反向最后一个状态 forward_lastoutput[:,-1,:256]# (16, 256) 正向末端backward_lastoutput[:,0,256:]# (16, 256) 反向末端 反向视角的最后combinedtorch.cat([forward_last,backward_last],dim1)# (16, 512)# ↓ 接入分类器# logits nn.Linear(512, num_classes)(combined)5.3 不传 h_0 的简化写法# 大部分场景下不需要显式传入 h_0PyTorch 会自动初始化为全零rnnnn.RNN(128,256,num_layers2,batch_firstTrue)xtorch.randn(16,20,128)output,hnrnn(x)# 自动使用全零的初始隐藏状态# output: (16, 20, 256)# hn: (2, 16, 256)六、关键注意事项6.1batch_first建议设为TruePyTorch RNN 模块的默认输入格式为(seq_len, batch, feature)这与常见的DataLoader输出格式(batch, seq_len, feature)不一致容易造成混淆。建议统一设置batch_firstTrue让数据流转更加直观。6.2dropout仅在多层时生效# num_layers1 时dropout 参数被忽略rnnnn.RNN(128,256,num_layers1,dropout0.5)# ← 这个 dropout 不会生效# num_layers≥2 时dropout 作用于层间连接除最后一层外rnnnn.RNN(128,256,num_layers3,dropout0.3)# ← 在第 1→2、第 2→3 之间施加 dropout6.3 输出output只包含最后一层如果你需要访问所有中间层的输出output满足不了这个需求。但通常这不是问题因为分类任务只需最后一层最后一个时间步序列标注需用最后一层所有时间步如果需要中间层输出做特征融合需自行改写模块6.4 双向 RNN 时输出维度翻倍# 单向output 最后一维 hidden_sizernnnn.RNN(128,256,bidirectionalFalse)# output: (..., 256)# 双向output 最后一维 hidden_size × 2rnnnn.RNN(128,256,bidirectionalTrue)# output: (..., 512)务必注意当 RNN 后接全连接层时全连接层的in_features需要匹配翻倍后的维度6.5h_0的初始化大多数任务中可以用全零初始化省去传h_0的麻烦。但在以下场景中建议显式初始化状态传递stateful RNN将上一个 batch 的h_n.detach()作为下一个 batch 的h_0特殊初始化策略如使用 Xavier/Kaiming 初始化6.6 梯度消失与梯度爆炸这是 RNN 最核心的缺陷。虽然本节讲的是 API 使用但必须了解传统 RNNtorch.nn.RNN在长序列上容易出现梯度消失或梯度爆炸。这是后续引入 LSTM 和 GRU 的根本原因。在实际项目中长序列任务推荐优先使用 LSTM 或 GRU。七、参数维度速查表配置输入形状(batch_firstTrue)输出output形状h_n形状单层单向(B, S, I)(B, S, H)(1, B, H)多层单向(B, S, I)(B, S, H)(L, B, H)单层双向(B, S, I)(B, S, 2H)(2, B, H)多层双向(B, S, I)(B, S, 2H)(2L, B, H)B batch_size, S seq_len, I input_size, H hidden_size, L num_layers八、与后续内容的关系本节讲完 RNN 的 API 后下一节3.1.7存在问题将深入剖析 RNN 的核心缺陷——长期依赖建模困难其根源在于梯度消失反向传播中早期时间步的梯度经过多次tanh导数的连乘每项 ≤1指数级衰减至 0导致模型只能学到短期依赖梯度爆炸若权重过大梯度指数级增长参数更新极不稳定这两个问题直接引出了LSTM第 3.2 节和GRU第 3.3 节它们通过精巧的门控机制有效缓解了上述缺陷成为实际应用中的主流选择。