循环神经网络 (RNN):处理序列数据的逻辑
📂 所属阶段:第二阶段 — 深度学习与序列模型(进阶篇)
🔗 相关章节:PyTorch 基础 · 长短时记忆网络 LSTM/GRU
1. 为什么需要 RNN?
1.1 传统神经网络的局限
传统的全连接网络(Dense)或卷积网络(CNN),本质上都是独立处理每个输入样本的——不管输入文本里的词是怎么排列的,只要词频差不多,输出的特征向量就可能重合。
文本序列:"这部电影 难看" vs "这部电影 好看"
传统网络只会统计「电影」「这」「部」这些词,甚至可能把两个句子的特征向量做得几乎一样,完全没法区分「好看」和「难看」的语义差异!
1.2 RNN 的核心突破:加入「记忆」
RNN(Recurrent Neural Network)的名字里就藏着秘密——循环复用同一个神经元单元,同时引入了一个叫「隐藏状态(Hidden State)」的东西,用来存储「之前看到的信息」。
我们可以把RNN按时间步展开来看(时间步对应序列里的每个元素,比如文本里的第t个词):
每个时间步的处理逻辑都一样:
- 拿当前输入
x_t和上一步的记忆h_{t-1} - 过同一个RNN单元,生成新的记忆
h_t和当前输出y_t
RNN 单元的隐藏状态更新,通常用 tanh 函数(双曲正切)来归一化,避免数值过大或过小: 新记忆 = tanh( 输入权重 × 当前输入 + 记忆权重 × 旧记忆 + 偏置 )
2. RNN 的致命问题
虽然RNN解决了「独立处理」的问题,但它有两个天然的硬伤,导致长序列任务里基本不用原生RNN。
2.1 梯度消失与爆炸
训练神经网络的核心是「反向传播梯度」——从输出层往回走,计算每个权重对最终损失的影响,然后更新权重。
但RNN是循环复用同一个单元的,反向传播时梯度会沿着时间步连乘N次(N是序列长度):
- 如果权重矩阵的特征值都小于1:梯度连乘后会越来越小,趋近于0——这就是「梯度消失」,模型学不到很久之前的信息
- 如果权重矩阵的特征值都大于1:梯度连乘后会越来越大,趋近于无穷——这就是「梯度爆炸」,训练时Loss会直接跳成NaN
"我出生在中国……(1000字完全不相关的内容)……我会说___"
原生RNN大概率会把第一个分句的「中国」忘得一干二净,很难填出「中文」!
2.2 其他小问题
除了这两个核心问题,原生RNN还有训练效率低(因为必须按时间步串行处理,没法像CNN那样并行化大部分层)、对初始记忆敏感等小瑕疵。
3. PyTorch RNN 快速实现
虽然原生RNN不常用,但它是LSTM/GRU的基础,我们还是得先学会用PyTorch写一个简单的文本分类器。
3.1 单向 RNN 文本分类器
3.2 双向 RNN 文本分类器
有时候,一个词的语义不仅和前面的词有关,还和后面的词有关——比如「我今天很___,因为没吃到火锅」,空里的词肯定和后面的「没吃到火锅」是负相关的。
双向RNN就是同时跑两个RNN:
- 前向RNN:从左到右看序列
- 后向RNN:从右到左看序列
最后把两个RNN的最后隐藏状态拼接起来,作为整个句子的特征。
4. 小结与速查
4.1 核心知识点回顾
- RNN的作用:解决传统网络「独立处理序列元素」的问题,引入「记忆」
- 展开图理解:按时间步展开后,每个时间步复用同一个单元
- 致命问题:梯度消失(学不到长依赖)、梯度爆炸(训练不稳定)
- 改进方向:LSTM/GRU解决梯度消失,梯度裁剪解决梯度爆炸
4.2 PyTorch RNN 速查
原生RNN在长序列任务(比如长文本分类、机器翻译)里效果很差,真正写项目时直接用LSTM或GRU!下一篇我们就讲LSTM。
🔗 扩展阅读

