slug
从 RNN 到 Attention:一条被讲烂、却很少有人讲顺的演进线
type
Post
status
Published
date
Jun 3, 2026
tags
推荐
文字
summary
category
技术分享与前沿技术域认知
icon
password
很多人第一次接触 Transformer,是从那篇标题很狂的论文开始的——Attention Is All You Need。但如果你直接从 attention 切进去,大概率会陷进 Q、K、V 的矩阵乘法里,背下了公式,却答不上来一个最朴素的问题:
我们为什么需要 attention?它到底替谁擦了屁股?
我自己也是被这个问题卡了很久。后来发现,真正能把它讲通的方式,不是从公式出发,而是顺着一条因果链往下走:RNN 解决了什么、又留下了什么坑;Encoder-Decoder 接着补、又埋了新的雷;attention 怎么把这些雷一个个拆掉。这三步是一条连续的演进,每一步都是被上一步的缺陷逼出来的。
这篇文章想做的,就是把这条线讲顺。我会尽量少用公式,多用一个贯穿全文的场景——给老外当翻译

第一站:RNN,一个字一个字往后传记忆

先说 RNN 解决的问题。
CNN 擅长处理图像这种空间数据,它一眼就能"看全";但面对序列数据——一段话、一首歌、一组随时间变化的温度记录——它就力不从心了。序列的难点在于前后是有依赖的。"我喜欢吃苹果"这句话,如果只盯着"苹果"两个字,你不知道说的是水果还是手机;但加上前面的"吃",意思立刻就明确了。
RNN(Recurrent Neural Network)就是为这种前后关联的数据设计的。它的核心机制只有一句话:引入一个隐藏状态 h,让它充当"记忆",每处理一个时间步,就把当前的记忆更新一次、往后传一步。
这里有一个很容易被忽略、但面试常考的细节:把 RNN 那个循环箭头展开(unfold)之后,你会看到很多个时间步串成一条链,但所有时间步用的是同一套参数。这叫 weight sharing。它跟 CNN 共享卷积核是同一种思想——否则序列有多长你就得准备多少套参数,根本学不动。
那原始 RNN 的问题是什么?一句话:记忆力太差。序列一长,前面的信息就被遗忘了,就像你看一本小说,看到最后已经忘了第一章讲了什么。
但"记忆力差"这四个字太文艺了,它背后是一个具体的数学病根:梯度消失与梯度爆炸(vanishing / exploding gradient)。
直觉是这样的:信息要从第 1 步传到第 100 步,反向传播时梯度得沿着时间轴连乘很多次。如果那个权重矩阵的特征值小于 1,连乘一百次就趋近于 0——梯度消失,模型学不到长距离依赖;如果大于 1,就会指数级放大——梯度爆炸。所以 RNN 不是"不想记住",而是长距离的梯度在数学上根本传不回去
这里值得再往下挖一层,因为"梯度消失"这个词本身也很容易停留在名词层面。
先说梯度是干嘛的。模型训练的本质是"算错了往回改":前向时,信息从第 1 个词一路传到第 t 个词,吐出一个预测;反向时,发现预测错了,要算出"第 1 个词那里的参数该往哪个方向调、调多少"——这个信号就是梯度。关键在于,这个信号得从第 t 步沿着前向链路的反方向,一步步退回第 1 步
而每往回退一步,梯度都要乘上一次权重矩阵(更准确说,是权重和激活函数导数的组合)。退 (t-1) 步,就连乘 (t-1) 次。你想象一个小于 1 的数自乘很多次会怎样:
这就是梯度消失:只要每一步乘的那个值小于 1,连乘几十上百次后,传回最前面的梯度就趋近于 0。 梯度归零,等于在告诉模型"第 1 个词这里不用改"——可它明明该改。于是开头那些词的参数学不动,长距离的关联建立不起来。反过来,如果那个值大于 1,连乘就会指数级炸开,训练直接崩——这是它的孪生兄弟"梯度爆炸"。
所以一句话锁死因果:梯度反向传播时沿时间轴连乘权重,每项小于 1 就指数衰减、大于 1 就指数放大;距离越远,连乘次数越多,问题越严重。 "长距离"这三个字,数学上的来源就在这个连乘次数上。
有意思的是,这跟前面"传话游戏每传一次丢一点细节"是完全同构的——前向传话丢的是信息,反向传梯度丢的是"该怎么改"的信号。同一条链路,正反两个方向,都怕长。
后来的 LSTM 和 GRU 就是来救这个场的。它们的核心思路用一句话概括:给记忆开一条"高速公路",让梯度能近乎无损地直传过去。 LSTM 引入了一个 cell state 作为长期记忆的主干,再用 forget / input / output 三个 gate 来控制"忘多少、记多少、输出多少";关键在于 cell state 的更新是加法式的,而加法不会像连乘那样把梯度衰减掉。GRU 是它的简化版,只用两个 gate,参数更少、训练更快,效果常常能跟 LSTM 打平。
但不管是 RNN 还是它的改良版,有一个东西它们都还没解决。

第二站:Encoder-Decoder,先听完,再闭眼复述

把 RNN 的思路往前推一步,会撞到一个新问题:如果输入和输出的长度不一样,而且不是逐字对应的,怎么办?
这正是翻译的场景。"欢迎来杭州"是 5 个字,翻成英文 "Welcome to Hangzhou" 是 3 个词,长度不同,语序还变了。普通 RNN 是"读一步、吐一步",输入几个 token 就输出几个,它没法处理这种不等长、不对齐的情况。
我当时卡在这里很久,直到把它想象成一个具体的翻译场景才通了。
想象翻译这件事由两个人合作完成:
Encoder 负责听。 朋友说"欢迎来杭州",他不急着开口,而是把整句话听完,在脑子里形成一个"我懂了"的印象。注意——他全程不说话,只负责听完、消化、形成一个内部状态。这个状态,术语叫 context vector,我习惯把它叫"印象"。
Decoder 负责说。 关键来了:他看不到原话,手里只有 Encoder 给的那个"印象",然后凭着这个印象,自回归地一个词一个词往外蹦——"Welcome"、"to"、"Hangzhou"——直到吐出结束符。
整个过程最关键的一句话是:先听完,再开口。Encoder 听的时候不输出,Decoder 输出的时候不再看原文,只看那个压缩后的印象。
正是这个"先把整句收成一个完整表示"的动作,让不等长翻译第一次成为可能。Decoder 不再被逐字对应绑死,它可以脱离原文的语序,按目标语言自由地重新组织。这是 Encoder-Decoder 实打实的功劳。
但你只要稍微想一下就会发现问题。
句子短,闭眼复述没问题。可如果朋友跟你说的是一整段话、三百个字,你听完闭上眼,还记得住开头说了啥吗?
记不住。因为那个"印象"——context vector——大小是固定的。你硬要把三百个字塞进一个固定大小的容器,前面的细节就会被挤掉、糊掉。这个毛病有个专门的名字:information bottleneck,信息瓶颈。
有意思的是,这跟上一站 RNN"看小说忘了第一章"是同一个病根,只是这次发作的位置变了——从"沿时间轴传不动",变成了"固定容器装不下"。

第三站:Attention,别闭眼了,允许你回头看

救场的想法,朴素到让人想拍大腿:
凭什么非要闭着眼复述?让 Decoder 边翻边回头看原文不就行了。
这就是 attention 的核心。它不再强求把所有信息压进一个印象里,而是让 Decoder 在生成每一个词的时候,回头扫一遍 Encoder 的所有时间步,动态地决定"这一刻,我该重点关注原文的哪几个位置"。
翻到 "Hangzhou" 这个词时,注意力会自动聚焦到原文的"杭州"上;翻 "Welcome" 时,聚焦到"欢迎"上。
这里有一个我自己最初理解错、后来才掰正的地方,值得专门拎出来说:
attention 不是"忘了哪里、才回头去找哪里"。它不是一种出了问题之后的补救。恰恰相反,它根本就不依赖那个压缩出来的印象了。每生成一个词,它都会主动地、重新地去原文里算一遍"相关度"——这是每一步都做、主动做的事,不是亡羊补牢。
所以更准确的说法是:它不是在修补压缩造成的损失,而是从一开始就不压缩了。 原文一直摊在桌上,随时可查。
如果用一个画面来形容,attention 干的事情就是把桌子掀了——它掀掉的,是"必须先把原文压缩成一个印象、再凭这个印象工作"这个前提。Decoder 不再要那个消化过的二手印象,它直接看一手原文。
这里还有一个容易说反的细节,顺手钉一下:Decoder 回头看的时候,是拿"当前已经翻到哪儿了"这个状态,去和原文每个位置算相关度的。也就是说,顺序是——先有当前状态 → 拿它和原文每个位置比对 → 加权汇总相关的部分 → 再生成下一个词。不是先知道下一个词、再去找它;下一个词恰恰是看完之后才生成出来的。

那个"压缩",到底是功臣还是罪魁

走到这里,可以回头给 Encoder 那个"压缩成固定向量"的动作做个盖棺定论了。
如果只盯着信息瓶颈,你会说它是罪魁:压缩有损耗、固定长度装不下长句、泛化能力差。这些都对,这是它的
但别忘了它的。回想一下最开始那个让人卡住的问题——普通 RNN 为什么翻不了"欢迎来杭州"?因为输入输出不等长、语序还变,逐字对应是死路。是谁解决的?正是 Encoder 这个"先听完、压缩成一个完整表示"的动作。没有这步压缩,连"不等长翻译"这件事本身都不成立。
所以这里藏着一个很漂亮的张力:
把整句压缩成一个固定向量,既是让不等长翻译成为可能的那把钥匙,又是埋下信息瓶颈的那颗雷。同一个动作,同时是功臣,也是罪魁。
而 attention 真正高明的地方,恰恰在于它只拆掉了罪、保住了功。它没有退回到 RNN 逐字对应的老路——功还在,Decoder 依然能脱离原文语序自由生成;但它取消了"压缩成单个向量"这个有损环节——罪没了,原文随时可查。
这也是为什么我说,从 RNN 到 Transformer 是一条演进,而不是一次推翻重来。每一代都站在上一代的肩膀上,留下好的、拆掉坏的。

收尾:为什么 RNN 最终被删掉了

把这条线连起来,其实就一句话:
RNN(一个字一个字翻,处理不了不等长)→ Encoder-Decoder(先听完再复述,但记不住长句)→ Attention(允许边翻边回头看,瓶颈解除)→ Transformer(既然全靠回头看,RNN 那条链路根本多余,直接删掉)。
最后这一步的逻辑特别自然:既然 Decoder 每生成一个词都要回头看全部原文,那 RNN 那套"按时间一步步往后传记忆"的笨办法,其实已经没什么用了。于是 2017 年有人干脆把它推到极致——把 RNN 全删掉,只留 attention。Encoder-Decoder 这个框架保留了下来,但内部的 RNN 被换成了纯粹的 self-attention。论文标题,就叫 Attention Is All You Need
这条线讲到这里,下一站就很清楚了:attention 说"回头看原文、算相关度",那这个相关度到底是怎么算出来的?答案是三个矩阵——Q、K、V。其实前面已经摸到门了:那个"拿当前状态去和原文每个位置比对"里,"当前状态"就是 Q,"原文每个位置"就是 K,比完之后真正取回来的内容就是 V。
但那是另一篇文章的事了。
如果你能把今天这条线——从"为什么需要"到"病根在哪"再到"怎么解决"——用自己的话顺下来,那么当面试官问你"为什么会有 Transformer"的时候,你给出的就不是一串背诵的概念,而是一条有因果、有张力的故事线。这两者之间的差距,比想象中大得多。
 
 
 
 
如何理解 API 学习笔记:Gradient 为什么指向最陡方向
Loading...
盛溪
盛溪
盛溪的学习&生活博客
Announcement
🌟 欢迎来到盛溪的博客!🌟
大家好,我是盛溪。在这里,我将分享我的生活感悟、学习心得以及其他一些有趣的发现。希望我的文章能为你的生活带来一点启发和乐趣。
邮箱: felixwindsor3344@gmail.com
微信号: felix_windsor
📅 更新通知:
  • 我会定期更新博客,分享新的内容。
💬 互动环节:
  • 如果你有任何问题或想法,欢迎在评论区留言。我非常期待与你的互动!
📚 推荐阅读:
  • 不定期推荐一些我觉得有价值的书籍或资源,希望能对你有所帮助。
感谢你的访问和支持,希望你能常来逛逛!
盛溪敬上