Transformer拆解01:Transformer为什么出现,RNN到底卡在哪里

Transformer拆解01:Transformer为什么出现,RNN到底卡在哪里

我是老计。想真正理解 Transformer,最好的起点不是直接背 Q、K、V,而是先问一句:在它出现之前,序列模型到底哪里不够用了?

2017年的论文《Attention Is All You Need》没有凭空发明一套复杂结构。它针对的是当时序列建模中的两个现实矛盾:循环网络必须按时间步顺序推进,难以把同一条序列充分并行;相隔很远的信息,要沿着很长的状态链传递,学习起来并不轻松。

Transformer真正改变的,不只是把RNN换成注意力,而是把序列中信息交互的路径,从一条按顺序传递的长链,改成了同一层内任意位置可以直接建立联系。

这篇先把这场变化的来龙去脉讲清。后面再拆注意力公式时,你就会知道每个零件为什么存在,而不是只记住一串矩阵运算。

一,序列数据难在哪里

一句话、一段语音、一串监控指标,都有一个共同特点:顺序会改变含义。

"我没有说他偷了钱"和"他说我没有偷钱",使用了相似的词,语义却完全不同。模型不仅要看每个元素是什么,还要理解:

  • 前后顺序是什么;
  • 当前元素依赖前面哪些信息;
  • 相隔很远的两个位置有没有关系;
  • 序列变长后,重要信息还能不能保留下来。

传统前馈神经网络接收固定长度输入,不天然表示这种逐步演进的状态。循环神经网络的思路很自然:像人读句子一样,从左到右读,每读一个词就更新一次"记忆"。

RNN的状态传递

一个最简单的循环网络可以写成:

text 复制代码
h_t = tanh(x_t W_x + h_{t-1} W_h + b)

其中:

  • x_t 是第 t 个位置的输入;
  • h_{t-1} 是读完前一个位置后的隐藏状态;
  • h_t 是当前的新状态;
  • W_x 和 W_h 是训练得到的权重。

它的直觉很好懂:当前理解等于当前输入,加上之前记住的东西,再经过一次非线性变换。

问题也埋在这里。要计算 h_6,必须先有 h_5;要有 h_5,必须先算 h_4。这条依赖链无法随意跳过。

二,第一个瓶颈,顺序计算限制并行

现代深度学习依靠 GPU 和其他并行硬件提高吞吐。矩阵越能成批计算,硬件越容易吃满。RNN的难处是,同一条序列内部存在严格的先后依赖。

为什么批次并行还不够

RNN并非完全不能并行。我们可以同时处理一个批次里的多条句子,也可以把每个时间步中的矩阵运算放到 GPU 上。但是,对同一条句子而言,第2步仍然要等第1步,第100步仍然要等第99步。

假设序列长度是1000,模型就要沿时间维度推进1000次。每一步可能很快,但关键路径仍然有1000级依赖。模型做大、数据增多以后,这种顺序性会直接限制训练效率。

Transformer的自注意力采用另一种计算组织方式。对同一层的所有位置,它可以先一次性生成整批 Q、K、V,再通过矩阵乘法计算位置之间的关系。所有位置在这一层中的表示,可以并行得到。

RNN的限制不是"用了循环"这么简单,而是同一条序列中的计算图存在无法消除的时间步依赖;自注意力把主要计算改造成更适合并行硬件的大矩阵运算。

这也是为什么 Transformer 在大规模训练中如此重要。模型能力当然关键,但能不能高效扩大训练规模,本身就是架构竞争力的一部分。

三,第二个瓶颈,长距离信息要走很远

再看另一个问题。假设句子开头出现一个主语,结尾的代词需要指向它。在循环网络里,开头的信息要经过每一个中间状态,才能传到结尾。

长链带来的困难

从位置1到位置100,信息要经过99次状态更新。每一次更新都会混入新输入并经过非线性变换。理论上,隐藏状态可以携带早期信息;实践中,网络要学会长期保存和使用这些信息并不容易。

训练时,梯度也要沿很长的链反向传播。连续乘上许多导数和权重后,容易出现梯度逐渐变小或变大的问题,也就是常说的梯度消失和梯度爆炸。LSTM和GRU通过门控机制显著缓解了这个问题,但没有消除顺序计算,也没有让任意两个位置在同一层直接交换信息。

下面用一个简单 NumPy 实验观察现象。我们构造一个随机初始化的简单RNN,只改变第一个输入,看看这种变化传到后续位置时还剩多少。

python 复制代码
import numpy as np

print("NumPy", np.__version__)
rng = np.random.default_rng(7)
seq_len, d_in, d_hidden = 6, 4, 5
x = rng.normal(size=(seq_len, d_in))
wx = rng.normal(scale=0.2, size=(d_in, d_hidden))
wh = rng.normal(scale=0.2, size=(d_hidden, d_hidden))

def recurrent_forward(inputs):
    h = np.zeros(d_hidden)
    states = []
    for token in inputs:
        h = np.tanh(token @ wx + h @ wh)
        states.append(h.copy())
    return np.stack(states)

base = recurrent_forward(x)
changed_x = x.copy()
changed_x[0] += 0.5
changed = recurrent_forward(changed_x)
impact = np.linalg.norm(changed - base, axis=1)

print("RNN states shape:", base.shape)
print("Impact by position:", np.round(impact, 6))

运行环境:Python 3,NumPy 1.26.4,CPU。实际输出:

text 复制代码
NumPy 1.26.4
RNN states shape: (6, 5)
Impact by position: [0.44949  0.15     0.051675 0.020121 0.006679 0.001793]

这个特定随机示例里,第一个位置的变化传到后面时快速减弱。它不是对所有RNN都会遗忘的数学证明,权重、训练方法、门控结构都会改变结果。这个实验只帮助我们直观看见:早期信息在简单循环状态中需要逐步接力,每次接力都可能改变它。

四,自注意力改变了什么

自注意力不要求某个位置只能从相邻状态接收信息。它让每个位置都提出一个查询 Q,用自己的 Q 和所有位置的 K 计算相关度,再按相关度组合对应的 V。

信息路径从长链变成直连

在一层全局自注意力中,位置100可以直接关注位置1。两者的交互路径长度不再随距离增长,而是在这一层内完成。

用一个最小 NumPy 示例看形状:

python 复制代码
import numpy as np

rng = np.random.default_rng(7)
seq_len, d_model, d_k = 6, 4, 3
x = rng.normal(size=(seq_len, d_model))
wq = rng.normal(scale=0.2, size=(d_model, d_k))
wk = rng.normal(scale=0.2, size=(d_model, d_k))
wv = rng.normal(scale=0.2, size=(d_model, d_k))

q, k, v = x @ wq, x @ wk, x @ wv
scores = q @ k.T / np.sqrt(d_k)
scores -= scores.max(axis=-1, keepdims=True)
weights = np.exp(scores)
weights /= weights.sum(axis=-1, keepdims=True)
out = weights @ v

print("Q/K/V:", q.shape, k.shape, v.shape)
print("Scores:", scores.shape)
print("Output:", out.shape)
print("Attention row sums:", np.round(weights.sum(axis=-1), 6))

实际输出:

text 复制代码
Q/K/V: (6, 3) (6, 3) (6, 3)
Scores: (6, 6)
Output: (6, 3)
Attention row sums: [1. 1. 1. 1. 1. 1.]

输入有6个位置,每个位置都和6个位置计算关系,所以注意力分数矩阵是 [6, 6]。每一行做 Softmax 后和为1,表示当前查询位置把多少注意力分给每个信息来源。最后用这些权重组合 V,得到每个位置的新表示。

并行与长距离联系同时改善

这套结构带来两个直接变化:

  • 所有位置的 Q、K、V 可以用矩阵乘法批量计算;
  • 任意两个位置在同一注意力层里可以直接建立联系。

这正好对应前面 RNN 的两个瓶颈。但要注意,Transformer不是因为完全理解顺序才不需要循环。去掉循环之后,模型反而失去了天然的位置信息,所以必须额外加入位置编码。后面第09篇会专门拆这个问题。

五,比较架构,不能只看一句能否并行

说RNN难并行、注意力能并行,方向没错,但还不够精确。原始论文比较序列层时,至少看了三个维度:单层计算复杂度、必须顺序执行的操作数量、任意两个位置之间的最长信息路径。

顺序操作数量

循环层的第 t 个状态依赖第 t-1 个状态,所以长度为 n 的序列,关键路径上要依次完成 n 次状态更新。自注意力层可以一次构造整批Q、K、V和关系矩阵,从序列维度看,主要计算不需要按位置逐个等待。

这个差异解释的是单层内部的并行性,不代表Transformer的所有步骤都能同时完成。多层网络仍要第1层完成后再进入第2层;GPT生成时也必须等上一个Token生成,才能继续生成下一个。

信息路径长度

循环网络中,位置1的信息要影响位置 n,需要沿隐藏状态走过接近 n 步。在一层全局自注意力中,位置1和位置 n 可以直接计算相关度,因此最长路径可以缩短到常数级。

路径短不等于一定学得好,但它减少了信息和梯度必须经过的中间节点。对于需要跨越很长距离建立关系的任务,这是一项重要的结构优势。

计算复杂度并非永远更低

标准全局自注意力的主要关系计算,复杂度可写成 O(n?d);简单循环层通常写成 O(nd?),其中 n 是序列长度、d 是隐藏维度。

这意味着结果取决于 n 和 d 的相对大小:

  • 当序列长度相对隐藏维度不大时,注意力的大矩阵计算适合并行硬件,优势明显;
  • 当序列极长时,n? 会成为沉重负担,注意力矩阵的计算和显存压力迅速增大;
  • 理论复杂度不能直接等同于实际速度,硬件利用率、内存访问、批次大小和实现方式都会影响结果。

Transformer的关键优势不是所有情况下算得更少,而是它减少了序列方向上的等待和远距离交互路径,把大量工作变成硬件更擅长的大矩阵运算。

六,为什么当时不是简单换成卷积

循环网络不是序列建模的唯一旧路线。卷积神经网络也能并行处理序列,而且很擅长提取局部模式。那为什么Transformer没有只靠一层层卷积解决问题?

卷积的关系范围通常先从局部开始

一个宽度为3的卷积核,一层只能直接看到相邻位置。想让相隔很远的两个Token交换信息,需要堆叠更多层、扩大卷积核,或使用空洞卷积。卷积当然可以构造很大的感受野,但信息路径会受到核大小和层数影响。

自注意力在一层内就能让每个位置观察所有位置,而且权重由当前输入内容动态决定。卷积更像拿固定形状的窗口扫过序列;注意力更像每个位置根据当前内容,临时决定该向谁取信息。

两者并非只能二选一

卷积具有强局部归纳偏置,在图像、语音和局部模式明显的任务中很有价值;注意力擅长灵活建立全局关系,但计算代价更高。后来的许多模型会把卷积、注意力或其他序列模块结合起来。

因此,Transformer的出现不意味着循环和卷积思想从此错误。它提供的是另一种更适合扩大训练规模、建立全局内容相关联系的组织方式。工程选型仍然要看序列长度、数据规模、硬件和任务特征。

七,Transformer没有免费午餐

讲到这里,很容易得出"Transformer全面优于RNN"的简单结论。这个说法并不严谨。

注意力的二次复杂度

标准全局自注意力需要构造序列长度乘序列长度的分数矩阵。序列长度从 n 增长到 2n,分数元素数量会从 n? 增长到 4n?。长上下文下,计算量和显存压力会迅速增大。

这也是后来高效注意力、稀疏注意力、FlashAttention等方法不断发展的原因。FlashAttention主要改变注意力计算的内存访问方式,并不把标准注意力的数学定义换掉;具体细节留到收官篇。

其他代价

Transformer还要面对:

  • 没有循环带来的天然顺序,需要显式位置表示;
  • 大矩阵计算适合并行硬件,但对硬件和内存系统也提出更高要求;
  • 在小数据、短序列、低资源或流式场景中,RNN及其变体仍可能有合理位置;
  • 全局直连不等于模型天然拥有无限记忆,上下文窗口、训练数据和模型容量仍然限制能力。

Transformer赢下主流,不是因为它没有代价,而是因为它把主要计算组织成了更容易扩大规模的形式,并显著缩短了序列中远距离信息的交互路径。

八,常见误区

误区一:RNN完全不能并行

更准确地说,RNN在批次维度和单步矩阵运算上可以并行,但同一条序列的时间步依赖限制了序列内部并行。

误区二:Transformer彻底解决长距离依赖

它缩短了信息路径,使远距离位置能直接交互,但能否真正学会并使用长距离关系,还受训练数据、参数、位置表示和上下文长度影响。

误区三:注意力没有顺序

注意力计算本身如果不加入位置信息,对输入顺序并不敏感。Transformer需要位置编码或RoPE等机制补充顺序。

误区四:有了Transformer,RNN就没有价值

技术选型看场景。Transformer适合大规模并行和复杂长序列建模,但在资源受限、在线流式和特定时序任务中,循环或状态空间类方法仍可能更合适。

小结

Transformer出现之前,循环网络用隐藏状态逐步传递序列信息,思路自然,却带来两类核心限制:同一条序列必须按时间步推进,限制训练并行;远距离信息要经过长状态链,训练和保留都更困难。 LSTM和GRU缓解长期依赖,但没有消除序列内部的顺序计算。

自注意力让所有位置批量生成Q、K、V,并通过矩阵运算建立位置间关系。它把主要计算变成适合并行硬件的大矩阵运算,也让远距离位置在同一层直接联系。但它需要显式位置表示,标准全局注意力还要承担随序列长度二次增长的分数矩阵成本。

下一篇,我们先不钻QKV公式,而是把整台Transformer从输入到输出看一遍,建立一张不会迷路的全景地图。

延伸阅读

(本文为技术学习与经验分享,代码用于理解机制。框架与实现可能随版本变化,具体用法请以官方最新文档为准。)

版权声明:本文版权归作者老计个人所有。欢迎个人学习阅读,未经授权,禁止转载、摘编、搬运或用于任何商业用途,违者将追究责任。转载请联系作者Jich。

相关推荐
zcg19424 小时前
通过UE制作segment和depth数据
人工智能·深度学习
Yolanda_20227 小时前
week3深度学习处理文本(上)
人工智能·深度学习
Smoothcloud润云7 小时前
GPU算力平台推荐:复现实验时,如何判断租用资源是否合适?
服务器·人工智能·深度学习·gpu算力·gpu
合尘猫8 小时前
6GB 笔记本本地跑 Z-Image Turbo:一次从 cu121 到 cu130 的踩坑记录
人工智能·ai·大模型·本地部署
赤龙ERP8 小时前
ERP周报:连接器开闸、国产GPU进场与智能工厂253家
数据库·人工智能·大模型·rpa·erp·企业数字化·builderpattern
dozenyaoyida8 小时前
AI与大模型新闻日报 | 2026-10-30
人工智能·ai·chatgpt·大模型·新闻
Rocky Ding*8 小时前
深入浅出Xiaomi-Lens-0技术解析:像素监督如何改变视觉推理
论文阅读·人工智能·深度学习·机器学习·aigc·多模态·ai-native
默|笙9 小时前
【AI应用】认识机器学习与深度学习
人工智能·深度学习·机器学习
JAVA_AI人工智能项目实战9 小时前
深度学习实验笔记
人工智能·深度学习·语言模型·自然语言处理