循环神经网络 (RNN)
循环神经网络(Recurrent Neural Network,RNN) 是一种专门处理序列数据(如文本、语音、时间序列)的神经网络。
与传统的前馈神经网络不同,RNN 具有"记忆"能力,能够保存之前步骤的信息。
循环神经网络能够利用前一步的隐藏状态(Hidden State)来影响当前步骤的输出,从而捕捉序列中的时序依赖关系。

RNN 的核心思想
RNN 的核心在于循环连接(Recurrent Connection),即网络的输出不仅取决于当前输入,还取决于之前所有时间步的输入。这种结构使 RNN 能够处理任意长度的序列数据。
传统神经网络:输入和输出是独立的(例如图像分类,单张图片之间无关联)。
RNN:通过循环连接(Recurrent Connection)将上一步的隐藏状态传递到下一步,形成"记忆"。
•
每一步的输入 = 当前数据 + 上一步的隐藏状态。
•
输出不仅依赖当前输入,还依赖之前所有步骤的上下文。
就像人阅读句子时,理解当前单词会依赖前面读过的内容(例如"他打开了__",你会预测"门"或"书")。
实例
代码块
Python
# 简单的 RNN 单元实现示例
import numpy as np
class SimpleRNN:
def __init__(self, input_size, hidden_size):
self.Wx = np.random.randn(hidden_size, input_size) # 输入权重
self.Wh = np.random.randn(hidden_size, hidden_size) # 隐藏状态权重
self.b = np.zeros((hidden_size, 1)) # 偏置项
def forward(self, x, h_prev):
h_next = np.tanh(np.dot(self.Wx, x) + np.dot(self.Wh, h_prev) + self.b)
return h_next
RNN 的工作机制
RNN 在每个时间步 t 执行以下计算:
接收当前输入 xₜ 和前一时刻的隐藏状态 hₜ₋₁
计算新的隐藏状态 hₜ = f(Wₕₕ·hₜ₋₁ + Wₓₕ·xₜ + b)
产生输出 yₜ = g(Wₕᵧ·hₜ + c)
其中 f 和 g 通常是激活函数(如 tanh 或 softmax)。
RNN 的优缺点
优点:
•
能够处理变长序列
•
理论上可以记住任意长度的历史信息
•
参数共享(同一组权重用于所有时间步)
缺点:
•
梯度消失/爆炸问题(难以学习长期依赖)
•
计算效率较低(无法并行处理时间步)
长短期记忆网络(LSTM)
LSTM(Long Short-Term Memory)是 RNN 的一种改进架构,专门设计来解决标准 RNN 的长期依赖问题。
2.1 LSTM 的核心结构
LSTM 引入了三个门控机制和一个记忆单元:
#AzPQAaHAmIPZ text { white-space: pre; }#AzPQAaHAmIPZ .fb0 { stroke: var(--N900-FG, 0.15); }#AzPQAaHAmIPZ .fb0 {stroke: rgba(31,35,41, 0.15)}#AzPQAaHAmIPZ .fx0 { stroke-miterlimit: 10; }#AzPQAaHAmIPZ .fx0 {stroke-miterlimit: 10}#AzPQAaHAmIPZ .fa1 { fill: rgb(187, 191, 196); }#AzPQAaHAmIPZ .fa1 {fill: rgb(187, 191, 196)}#AzPQAaHAmIPZ .fx1 { font: 400 12px MonospacedNumber, LarkHackSafariFont, LarkEmojiFont, LarkChineseQuote, -apple-system, BlinkMacSystemFont, "Helvetica Neue", Tahoma, "PingFang SC", "Microsoft Yahei", Arial, "Hiragino Sans GB", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"; }#AzPQAaHAmIPZ .fx1 {font-style: normal}#AzPQAaHAmIPZ .fx2 { text-anchor: middle; }#AzPQAaHAmIPZ .fx2 {text-anchor: middle}#AzPQAaHAmIPZ .fx3 { dominant-baseline: central; }#AzPQAaHAmIPZ .fx3 {dominant-baseline: central}#AzPQAaHAmIPZ .fx4 { stroke: none; }#AzPQAaHAmIPZ .fx4 {stroke: none}#AzPQAaHAmIPZ .fc0 { fill: var(--text-caption); }#AzPQAaHAmIPZ .fc0 {fill: #646a73}#AzPQAaHAmIPZ .fa2 { fill: var(--text-link-disabled); }#AzPQAaHAmIPZ .fa2 {fill: rgb(187, 191, 196)}#AzPQAaHAmIPZ .fa3 { fill: rgb(59, 58, 56); }#AzPQAaHAmIPZ .fa3 {fill: rgb(59, 58, 56)}#AzPQAaHAmIPZ .fx5 { font: 700 14px MonospacedNumber, LarkHackSafariFont, LarkEmojiFont, LarkChineseQuote, -apple-system, BlinkMacSystemFont, "Helvetica Neue", Tahoma, "PingFang SC", "Microsoft Yahei", Arial, "Hiragino Sans GB", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"; }#AzPQAaHAmIPZ .fx5 {font-style: normal}#AzPQAaHAmIPZ .fx6 { text-anchor: start; }#AzPQAaHAmIPZ .fx6 {text-anchor: start}#AzPQAaHAmIPZ .fx7 { dominant-baseline: alphabetic; }#AzPQAaHAmIPZ .fx7 {dominant-baseline: alphabetic}#AzPQAaHAmIPZ .fc1 { fill: rgb(255, 255, 255); }#AzPQAaHAmIPZ .fc1 {fill: rgb(255, 255, 255)}#AzPQAaHAmIPZ .fx8 { font: 400 14px MonospacedNumber, LarkHackSafariFont, LarkEmojiFont, LarkChineseQuote, -apple-system, BlinkMacSystemFont, "Helvetica Neue", Tahoma, "PingFang SC", "Microsoft Yahei", Arial, "Hiragino Sans GB", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"; }#AzPQAaHAmIPZ .fx8 {font-style: normal}#AzPQAaHAmIPZ .fc2 { fill: rgb(51, 51, 51); }#AzPQAaHAmIPZ .fc2 {fill: rgb(51, 51, 51)}#AzPQAaHAmIPZ .fb1 { fill: var(--N900-FG, 0.15); }#AzPQAaHAmIPZ .fb1 {fill: rgba(31,35,41, 0.15)}#AzPQAaHAmIPZ .fb2 { fill: rgb(212, 212, 212); }#AzPQAaHAmIPZ .fb2 {fill: rgb(212, 212, 212)}#AzPQAaHAmIPZ .fb3 { fill: rgb(232, 234, 246); }#AzPQAaHAmIPZ .fb3 {fill: rgb(232, 234, 246)}#AzPQAaHAmIPZ .fa4 { fill: var(--bg-body); }#AzPQAaHAmIPZ .fa4 {fill: #fff}AB12345组件功能输入门遗忘门输出门记忆单元控制新信息的流入决定丢弃哪些旧信息控制输出的信息量保存长期状态
实例
代码块
Python
# LSTM 单元的基本实现
class LSTMCell:
def __init__(self, input_size, hidden_size):
# 组合所有门的权重
self.W = np.random.randn(4*hidden_size, input_size+hidden_size)
self.b = np.random.randn(4*hidden_size, 1)
def forward(self, x, h_prev, c_prev):
LSTM 如何解决长期依赖问题
选择性记忆:遗忘门可以决定保留或丢弃特定信息
梯度通路:记忆单元提供了相对直接的梯度传播路径
信息保护:记忆内容不会被每个时间步的操作直接修改
门控循环单元(GRU)
GRU(Gated Recurrent Unit)是 LSTM 的简化版本,在保持相似性能的同时减少了参数数量。
GRU 的核心结构
GRU 合并了 LSTM 的某些组件:
实例
代码块
Python
GRU vs LSTM
双向 RNN 架构
双向 RNN(Bi-RNN)
Bi-RNN 包含两个独立的 RNN 层:
双向 RNN 通过同时考虑过去和未来的上下文信息,增强了序列建模能力。
前向层:按时间顺序处理序列
反向层:按时间逆序处理序列
最终输出是这两个方向输出的组合(通常为拼接或求和)。
双向 RNN 的应用场景
自然语言处理:词性标注、命名实体识别
语音识别:利用前后语境提高准确率
生物信息学:蛋白质结构预测
时间序列预测:考虑历史与未来趋势
双向 LSTM/GRU
现代应用中,双向 RNN 通常使用 LSTM 或 GRU 作为基础单元:
实例
代码块
Plain Text
from tensorflow.keras.layers import Bidirectional, LSTM
model.add(Bidirectional(LSTM(64))) # 创建双向LSTM层
总结与进阶学习
RNN 及其变体是处理序列数据的强大工具。要深入掌握:
理解梯度在 RNN 中的传播方式
学习注意力机制如何增强 RNN
探索 Transformer 架构与 RNN 的关系
实践各种序列建模任务(机器翻译、语音合成等)