QUESTION

RNN的输入、隐藏状态、输出形状和主要缺陷是什么?

A

沿时间步追踪x、h、output和hn,理解共享参数、序列输出以及长期依赖问题。

DETAILED ANSWER

直接结论

RNN在每个时间步同时接收当前输入x_t和上一时间步隐藏状态h_(t-1),生成新的h_t。同一套参数沿时间重复使用,因此能够传递历史信息,但也带来难并行、长期依赖和梯度消失或爆炸问题。

一个时间步发生了什么

z_t = W_ih × x_t + W_hh × h_(t-1) + 偏置
h_t = tanh(z_t)
  • x_t:当前token的Embedding。
  • h_(t-1):上一时间步的隐藏状态。
  • h_t:融合当前输入和历史信息后的新状态。
  • W_ih:处理当前输入。
  • W_hh:处理上一隐藏状态,并在所有时间步共享。

seq_len和PyTorch形状

seq_len表示一个样本包含多少个时间步;对文本来说,通常就是序列中的token数量。

PyTorch默认输入形状:

[seq_len, batch, input_size]

初始隐藏状态:

[num_layers, batch, hidden_size]

输出:

output:[seq_len, batch, hidden_size]
hn:[num_layers, batch, hidden_size]

output保存最后一层RNN在所有时间步的隐藏状态;hn保存每一层最后一个时间步的隐藏状态。对单向RNN有:

output[-1] = hn[-1]

文本生成为什么每个位置都要输出

文本生成需要在每个时间步预测下一个词:

RNN输出:[seq_len, batch, hidden_size]
展平:[seq_len × batch, hidden_size]
全连接层:[seq_len × batch, vocab_size]

这相当于为序列中的每个位置分别完成一次词表分类。

RNN的主要缺陷

  • 长序列反向传播容易出现梯度消失或爆炸。
  • 难以学习相距很远的信息依赖。
  • 当前时间步依赖上一时间步,难以充分并行。
  • 序列越长,训练和推理通常越慢。

面试口述

RNN在每个时间步同时接收当前输入和上一时刻隐藏状态,通过共享参数更新当前隐藏状态,因此能够保存历史信息。训练时使用BPTT沿时间反向传播。但长序列中的梯度需要连续经过循环权重和激活函数,容易出现梯度消失或爆炸,而且时间步之间存在依赖,无法充分并行。