Before “attention is all you need”
在“注意力就是一切”之前
昨天好像随口说了“要继续讲 Transformer”,结果今天自己就被这个 flag 绑住了,像得了“承诺强迫症”似的,不写完都睡不着。半夜爬起来把这篇写了,反正也没几个人会看,写与不写,好像也没什么区别,但对我来说,某种完成感总还是重要的。
之前的系列讲到了 word embeddings —— 词向量。如果你已经对词向量有了基本理解,那我们就可以往更深的地方走了。不过,要真正理解《Attention is All You Need》,还得跨过一段不小的认知门槛。我想试试看,能不能用接下来几篇帖子,把那道门一点点拆掉。
我自己的旧帖子,现在几乎都搜不到了。可能是因为吐槽太多,结构也太自由奔放了。我这人写东西容易跑题,吐槽停不下来,所以若你是有心人,建议收藏。否则它们大概率会像宇宙背景辐射一样散落无踪。
我也从不引用自己的旧文 —— 因为,我实在,搜不到它们了。
要走进 Transformer 的世界,LSTM(Long Short-Term Memory)就是你绕不开的一块台阶。它是一种专门为“序列”设计的神经网络结构,也是 GPT、BERT 这类大型语言模型的认知前传。如果说 Transformer 是高铁,那 LSTM 就是你理解这个系统的第一站台。
LSTM 是什么、怎么工作的?这个问题你可以直接问 AI,我这里不打算赘述公式,而是讲点能把它“讲成一个故事”的东西。真正要理解 LSTM,得抓住它的核心机制:门控记忆。说白了,它的任务就是:记什么?忘什么?
最好的学习方式不是死读原理,而是做一个 LSTM 的小实验。非常简单,用 vibe coding 都可以跑起来。我建议你拿一首短诗作为训练数据,用下面我写的 prompt 就能完成。等你跑一遍实验,哪怕只是看着它学会了生成几句新诗,你对“门控记忆”的理解就不再是理论上的,而是体验上的。一旦你完成这个 lab,后面的 attention、transformer 就容易多了。
LSTM 内部有几扇门:忘记门、输入门、候选记忆、输出门。你可以把它想象成一个“有选择性记忆的人”。说实话,我写这个系列的时候,notion笔记、论文、草稿堆成山,我也得像一个 LSTM 一样,挑选哪些信息保留,哪些可以丢,哪些要编织成故事线讲给你听。这种选取和组织,本身就是一种“门控记忆”。
顺便插个段子,我这套讲法其实特别像成都的“龙门阵”——小时候暑假经常去成都,最爱跑到茶馆发呆,听一群老头子在那里摆龙门阵。那时候听得晕,现在却越听越觉得有味道。你就把我写的这篇也当成一场技术龙门阵来听,轻松但不浅薄,笑着也能学点真东西。
回到正题:LSTM 的门控到底怎么工作?它不是拍脑袋决定“要不要记”,而是数学决定的。每一个门都会输出一个在 0 到 1 之间的权重向量,就像水龙头的开合度,决定当前的信息要流多少进去、流多少出来、保留多少、忘掉多少。输入是当前的词向量 xt 和上一个隐藏状态 ht−1,输出是一个实数向量,代表每一维的信息保留程度。
我知道有人对公式有执念(比如我),但推特这种地方懒得搞公式渲染,我就不摆公式了。如果你非要看那套 ft=σ(Wx+Uh+b) 的结构,自己查。这里我们只记一件事:LSTM 是有记忆的人,它的记忆,是动态调控出来的。
词向量维度 vs. 隐藏状态维度。
好,这里我得插播一个我认为非常重要的概念:词向量维度 vs. 隐藏状态维度。
我们之前讲词向量(word embedding)的时候说过,维度一般在 100 到 300 之间,有的更高。但在使用 LSTM、GRU、Transformer 这类模型时,会出现另一个维度:隐藏状态维度(hidden state dimension)。你一看,有时候居然设成 512维,比词向量还高。这就值得讲讲为什么了。
先不着急理解那些术语,你只要知道:隐藏状态是模型在每个时间点对上下文的“理解状态”。所谓 512 维,就是模型每处理一个词,就生成一个长度为 512 的向量,用来“记住”它此刻对这句话的综合认知。
我就问你一句实话:你觉得“上下文”好理解吗?你想想你写的作文、做的阅读理解、还有你自己写过的那些乱七八糟但又想表达得清楚的文章。
认字容易,写句子难。
认识“爱”、“自由”、“结构”这些词大家都会,但要你写出一段有逻辑、有情绪、有层次的文章,能做到的有多少?上下文不是简单几个词拼一起,而是一个更高维的结构系统。
所以 LSTM 需要做一件难事:把一个 10 到 30 个词的句子压缩成一个向量表达,也就是所谓的context vector。如果你只用一个 100 维的空间去装这堆词的信息,是装不下的。维度越高,能保留的信息越多,压缩失真就越小。
那为啥用 512 呢?这是深度学习实践里一种“轻量但强大”的标准设置。它不会太大,也不会太小,特别适合像中等长度的翻译、摘要生成这种任务。你可能觉得 512 听起来很多,但别忘了 Transformer 随便一层都是几千万参数,512 在整个模型规模里根本不算什么。PyTorch、TensorFlow 这些框架早就对这种向量运算做了高度优化,训练速度并不会因为 512 而成为负担,而表达力却能大幅提升。
总结一句话:词向量告诉你“每个词是啥”,隐藏状态告诉你“现在整句话讲到了哪一步”。后者更难,也更值钱。
现在我们在插播的过程中,再来插播一节英语课:
我问你个问题:下一个词,是不是由上一个词决定的?来,举个最简单的英语对话:
A:Is she Susan? B:Yes, she —. / No, she —. 你如果考过高考,应该知道这俩空格填什么: 第一个填 is, 第二个填 isn’t。 你有没有发现:“is” 或 “isn’t” 的选择,是上下文在起作用? 它完全依赖于前面的那个 “Yes” 还是 “No”。而且还得有一个 yes/no 问句作为背景,比如 “Is she Susan?”。 离开上下文,这两个词就失去了判定依据。
语法课插播完毕,我们回到刚才的 512 维隐藏状态。
你要理解的是:隐藏状态最难理解的地方,在于它是一种时间递归结构。
你看它的写法:h_t。只要有 t,那你就知道一定有 h_t−1,甚至还有 h_t+1。LSTM(或者 RNN)天生就是个“时间展开的神经网络”,每处理一个词,就会生成一个隐藏状态 h_t,然后把它作为“上下文记忆”传给下一个词的计算。
也就是说:当前词的理解,不是孤立的,而是由“当前词向量 + 上一个状态”一起决定的。
这就叫做:逐词递归。(我起的)
你可以把 LSTM 想象成一个逐词笔记员:每看到一个词,就更新一下自己的理解笔记,然后带着这份笔记去看下一个词。
于是,每一个 h_t都变成了“我读到当前为止的全部理解”。而最后一个隐藏状态 h_T,也就成了对整个句子的压缩表达——也就是我们说的 context vector。
理解了这个,你就基本可以通关 Seq2Seq 的 Encoder–Decoder 架构了。
输入序列 → [Encoder RNN] → Context Vector → [Decoder RNN] → 输出序列
输入序列 → [编码器 RNN] → 上下文向量 → [解码器 RNN] → 输出序列
这个架构最基础的形式是:两个 RNN(通常是两个 LSTM)连在一起,一个是 Encoder,一个是 Decoder。Encoder 把输入序列吃进去,输出一堆隐藏状态 h1,...,hT,但原始版本只取最后一个隐藏状态 hT 当作上下文(context vector)传给 Decoder,用作其初始状态。
你看,这就是最“神经”的地方——整个输出的生成过程,竟然只靠 Encoder 的最后一个隐藏状态。这就显然有问题嘛。你想,句子的前面信息就这么全丢了?记忆靠最后一个 snapshot 扛住全局?于是,我们就该正式引出 Attention 机制了。
"注意力是所有你需要的东西"
昨天我们聊到了 LSTM 的一个致命弱点:上下文向量(Context Vector)瓶颈。模型读完整段话后,只留下一个固定维度的向量,比如 512 维,作为整段输入的“总结快照”,传给 decoder 生成输出。
听起来很精妙,但你仔细一想——这不有大问题吗?
现实里,没有人能把一整篇文章,压缩成最后一个词的脑内快照,然后靠这个词就复述出原文的全部细节。你读完《百年孤独》,难道靠最后一个“死”字就能讲清楚故事?那只能叫语义压缩事故。
如果你在大学学过英语系的一门经典课叫 Extensive Reading(泛读),你就会体会到,人类在处理长文本时,其实是在分配注意力。不是逐字记忆,而是有策略地“扫”、“跳”、“聚焦”,有些地方一眼带过,有些段落反复咀嚼。你可能记不住每个字,但你能记得哪些地方重要,甚至能反推作者意图。
反过来看,大多数人读完一篇长文,每个字都认识,最后一句也能复述,但你问他到底在说什么?——茫然。
这种“句读正确,认知失效”的状态,正是没有形成注意力分配策略的体现。
所以,终于要说那句经典台词了:Attention is all you need.
是不是你也听了很多次,但从来没想明白这句话真正的技术含义?今天我们就来掰开揉碎讲讲这个“注意力”到底是个什么玩意。
我试图把这套“技术龙门阵”写成像美剧——每一集有剧情推进,但你单看一集也能跟得上。当然,像追《黑镜》一样,如果你能把我过去的推文收藏起来、按顺序刷,那会更有味道。挺好玩的。
好,回到正题。注意力机制(Attention),你得和 LSTM 的门控机制(Gating)并列着看,才能真的抓住它们的区别。LSTM 是靠时间序列把信息一个个传下去,像接力赛;而 Attention 是直接在所有词之间画连接线,像脑图。
要我开一门 NLP 的硕士课程,光讲这个 Attention + LSTM 的对照就能讲一整周。但要用“龙门阵”的方式来说故事,那我就只提炼一个主线:语言到底是按时间走,还是按结构展开?
在进入结束前,你可以先视觉上熟悉一下 Self-Attention 的核心过程。推荐你看一下 3Blue1Brown 的那个经典视频,在 3:56 到 4:28 这段时间里,他用动态可视化展示了 Attention 的工作方式。我截了一张图,但更建议你反复播放这段,体会“词与词之间互相观看并调整”的动态过程。每一个词都在根据其他词的位置、语义和关联程度,调整自己的向量表示,形成一种集体协商的注意力结构。
这其实就是 Self-Attention 的本质:所有词一起看所有词。这个过程是并行进行的,和 LSTM 的链式 Context Vector 生成方式形成鲜明对比。在 LSTM 中,当前的隐藏状态 h_t 决定下一个状态 h_{t+1},像是一个刚学英文的小孩,一个字一个字慢慢读,靠记住前面的词来猜后面的词。这就是时间链式的信息传递路径。
而在 Self-Attention 中,没有这种线性依赖。每一个词都会同时读取其他所有词的信息,比如在句子 “I love you” 中,"love" 同时看 "I" 和 "you";"you" 也在同时看 "I" 和 "love"。”you”也在看。所有词彼此发出 Query,计算相似度,再对他人的 Value 加权融合,这个机制是并发进行的,不是先后顺序的。
而且这不是简单的“看一眼”,而是多头注意力机制(Multi-Head Attention):每个词会从多个角度、多个子空间去看其他词——有的头关注句法结构,有的头关注情感关系,有的关注位置依赖。你可以理解为每个词长了好几只眼睛,每只眼睛都看不同的维度,然后一起决定该怎么表达自己。
这就是为什么我们说,Self-Attention 是一种更高级的“全局感知机制”,相比起逐词递推的 LSTM,它更像是进入了一个同时交流、同时思考的语言空间。
两个灯谜和语言的二元性
我们先从两个灯谜讲起。
第一种,接龙灯谜:你来对对子,我出一句,你接一句。比如“天王盖地虎”,你接“宝塔镇河妖”。这类灯谜考验的是你能否根据前文接出下一句,像是语言的接龙游戏。
第二种,填空灯谜:你读一句话,里面挖了个空,考你是否能补全。例如:“I ___ you.” 这就像我们熟悉的完形填空题,考察的是你对语义结构的整体把握。
这两种灯谜,正好对应大语言模型的两种训练范式:
接龙灯谜 → 自回归建模(Autoregressive):给定前文,预测下一个词(如 GPT);
填空灯谜 → 自编码建模(Masked Language Modeling):给定整句,遮住部分词,推测其内容(如 BERT)。
要理解这两种范式的底层哲学,我们需要回顾我前两天写的两个核心话题:
语言的“线性幻觉”‣
语言的“线性幻觉” —— 索绪尔与乔姆斯基‣
语言的“线性幻觉”指的是:我们说话、写作时必须逐字展开,但这并不意味着我们的理解是线性的。我们并不是“一个字一个字地堆叠意义”,而是在人脑中形成一种结构性的认知跳跃与整体感知。
从语言学的两个传统看:
乔姆斯基代表的生成语法派,强调语言是一个按规则递归展开的序列系统。这是一种偏向线性的语言观。
索绪尔为代表的结构主义语言学,则强调意义来自词与词之间的结构关系网,而非词本身。这是一种偏向结构的语言观。
但真正深刻的是:
语言并非二选一,它本身就是“线性 / 结构”二元性的复合体。
我们必须一个词一个词地说,但我们不是一个词一个词地理解。字与字之间,也不是靠顺序压缩记忆,而是通过结构联结、语义跳跃、上下文重建,完成“理解”的行为。
所以,这两种语言建模范式并不是技术选型的权宜之计,而是从语言的本质中自然推导出来的两种认知建模路径。语言是线性的,因为我们只能线性输出;语言是结构的,因为我们只有结构才能理解。缺一不可。
那么,这两种“语言灯谜”究竟是怎么用的呢?
用最简单的话来说,填空式灯谜(也就是自编码语言建模)通常应用于理解类任务。用于读懂句子。以 BERT 为例,模型接收完整的句子,中间挖空一个词,让它通过前后语境来猜测缺失内容。常见任务包括情感分类、问答匹配、文本判断等。最终输出的是一组分类概率,比如“正面情绪:80%,负面情绪:20%”,这表示模型已经从上下文中提取出结构性信息,完成了“读懂句子”的动作。
而接龙式灯谜(也就是自回归语言建模)则用于生成类任务,代表模型如 GPT。用于把话说下去。它的任务是:给定前几个词,预测下一个最可能的词。比如输入是 "I love",模型可能给出“you” 的概率为 42%,"myself" 为 18%,"this" 为 14%。这些概率可通过采样方法(如 Top-1、Top-k、Top-p 或 Temperature)生成文本,适用于写作、对话、翻译等实际语言生产场景。
我们设计这两种灯谜范式,并不是出于技术分类的目的,而是为了建模语言的两个基本世界:一个是“如何说话”,即语言生成的世界;另一个是“如何听懂话”,即语言理解的世界。它们并非对立,而是互为补充,像语言智能的左手与右手,共同撑起大模型的语义桥梁。
这也正如语言本身的二元性——语言既是线性的,又是结构的。我们必须一个字一个字地说出语言,这是线性;但我们理解语言,并不是逐字积累,而是借助上下文和语法结构进行重建,这是结构。同样地,自回归和自编码两个范式也缺一不可。
在实际任务中,这种协同尤为明显。比如在对话系统中,模型需要先理解用户输入(自编码),再生成回应(自回归);在智能写作中,需要先分析提示和文体(自编码),再进行续写(自回归);在搜索与摘要中,需要先理解问题和文档内容(自编码),然后再进行提取与改写(自回归)。
因此,一个真正强大的语言系统,必须具备结构理解的能力和语言生成的能力,并在两者之间形成完整的认知闭环。只有这样,语言模型才不只是会“说”或“听”,而是真正具备交流、思考与协作的智能。
注意力机制的核心函数Attention (Q, K, V)-1
Transformer架构的核心函数是Attention(Q, K, V)。其实这个函数非常直观,我们不妨用一种生动的方式解释它,不涉及复杂的数学推导。下面附了一张GPT画的图,虽然图不是特别精准,但完全够用来帮助我们理解。
首先,Query、Key、Value三个术语并没有想象中那么高深,字面意思即可很好理解:
- Query(Q):问询、查询
- Key(K):要素、标签
- Value(V):价值、数值
现在,我们用一个非常直观的比喻来理解这三个概念:
假设你自己就是一个token,你来到一个专属于token的大派对。你走进房间,发现里面有一大群跟你一样的token在交流。我们模拟一下你内心的活动流程:
你首先会想:“我该找谁说话呢?谁能提供我想要的信息?我应该关注谁呢?” 此时,你内心有明确的目的——你可能在找能帮你解答问题的人,或者是你的老朋友,又或者只是寻找最有趣的对象来互动。
Query(Q),就是你带着目的主动去观察、寻找的人。
是不是很像我们平时上推特找人互动的方式?每个人带着不同的需求和目的去关注不同的人。
房间里其他的token,就是 Key(K)。每个token都穿着不同的衣服,佩戴着名牌,展现出不同的个性和特征。他们向外展示的信息就是:“我是谁”、“我擅长什么”、“我值得被关注吗?”
Key(K) 提供的正是身份和标签,供你判断是否要给予关注。你可以将这些名牌想象成推特用户的Bio和蓝标认证。一旦你决定与某个token交流,他们所提供的具体信息、内容或者故事,就是 Value(V)。
Value(V) 是你在决定关注之后能够从对方那里获得的信息。我们再具体一些,假设你现在内心有一个明确的Query:“我想找人告诉我明天的天气预报。” 你环顾四周,看每个人的名牌(Key):
- 有人名牌写着“气象专家” ✅
- 有人名牌写着“电影导演” ❌
- 有人名牌写着“AI工程师” ❌
- 有人名牌写着“天气爱好者” ✅
接下来,你迅速给这些名牌(Key)做了个打分(对应数学上的点积),这些分数就指导了你该关注谁。你用这些关注权重去获取他们的信息(Value):
气象专家说了5句话,你吸收了其中70%的内容。天气爱好者说了3句话,你吸收了其中30%的内容。其他人说的话,你基本没听。
最后,你脑海里合成了一段明确的“天气”信息——这正是通过Attention机制实现的内容提取。
当然,你自己这个token也是带着自己的名牌(Key)出现的,也就是说你自己也有属性。你在进行Query的时候,是根据自身的属性和情况去关注别人的。每个token都是普通的,没有额外的加成或者特殊效果。
在Transformer架构中,每个token(词、字或者子词)最初都是一个向量(embedding),具体如何映射成Q、K、V呢?
- Query:本token去关注别人时使用的向量表示 → Q = x · W_Q
- Key:本token展示给别人的身份信息 → K = x · W_K
- Value:本token能提供给别人的具体信息 → V = x · W_V
这里W_Q是一个模型通过学习得到的参数矩阵。
至于词向量本身的具体问题,如果感兴趣,可以往前翻看以前的帖子,那里已经详细说明过了。
注意力机制的核心函数Attention (Q, K, V)-2 以及多头注意力机制
有了之前帖子的生动比喻,我们现在可以从数学的角度深入理解Attention (Q, K, V)函数。这其实是一个非常简单直观的函数,它只有三个输入变量:Q(Query,查询)、K(Key,键)和V(Value,值),并输出一个新的向量表示。具体的计算过程如下:首先是计算Q和K的点积(QKᵀ),得出每个Query向量与所有Key向量之间的“注意力打分”。然后将这个得分除以√dₖ,这一步是为了避免数值过大,帮助稳定模型训练。接下来对这些打分进行Softmax归一化处理,这样就得到了一个总和为1的概率分布,最后将这个概率分布乘以V,得到新的加权向量表示。
$$ \text{Attention}(Q, K, V) = \text{softmax} \left( \frac{QK^{\top}}{\sqrt{d_k}} \right) V $$
Softmax函数其实就是一个归一化工具,它把任意一组数值转换成一个总和为1、可以视作概率的结果,这种处理在数学上非常常见且便利。
接下来我们继续介绍多头注意力机制。那么什么是多头注意力呢?研究过语言学的人都知道,一个句子可以从多个不同层面进行分析,例如最简单的主谓宾结构分析。
假设我们有一个经典英文句子:“The quick brown fox jumps over the lazy dog.” 这个句子包含主谓宾关系、形容词修饰关系、长距离依赖关系以及时间结构关系。在Transformer模型处理这个句子时,它会把句子拆分成多个tokens,并在每一层(你先别问这个“层”是什么意思)中运行注意力机制。我们来看其中某一层的多头注意力模块具体是怎样工作的。
假设这一层有4个头(Head 1到Head 4),每个头专注于不同的语义任务:
- 第一个头(Head 1)关注主谓结构,即谁在做什么,比如主语“fox”和动词“jumps”,Head 1 会特别关注“fox”到“jumps”的关系,学习到主语和动词之间的匹配。
- 第二个头(Head 2)关注名词与形容词的搭配关系,比如“quick”和“brown”修饰“fox”,“lazy”修饰“dog”,Head 2会加强这些名词与修饰词之间的注意力联系。
- 第三个头(Head 3)关注长距离依赖关系,尤其在翻译任务中特别关键,例如句子中动词“jumps”到宾语“dog”的长距离语义连接关系,Head 3确保这些远距离词汇也能有效对齐。
- 第四个头(Head 4)关注词汇的时间或位置顺序关系,帮助模型捕捉整个句子中动作或事件的展开节奏,比如“fox jumps over the lazy dog”这一动作流程的顺序感。
熟悉语言分析的人一定能很快理解这些头分别关注的内容。
那么,这样一个简单的attention函数和多头注意力机制在一个句子中究竟要运行多少次呢?在OpenAI的GPT模型(如GPT-3和GPT-4)中,一句话会触发Attention函数运行成百上千次。具体次数取决于几个因素:每个token在每一层都会计算一次attention,而每一层中attention并不是只运行一次,而是并行运行多个头的计算。
这还只是初步解释,在下一篇帖子中,我们将引入attention层和模型层数的概念,详细探讨为什么每一句话、每一层都会重复计算attention的问题。
多头注意力机制的拼接-2
在上一段中我们初步介绍了多头注意力机制,它本质上是一种非常符合语言学分析的做法。现实中一个向量如果维度很高,比如512维,直接用一次Attention函数来处理整个向量,很容易失焦、混杂信息。多头注意力机制就是把这个高维向量拆成多个“头”,也就是多个子空间,每个子空间负责处理其中的一部分信息。
例如,如果输入的维度是512,而我们设置了8个头(head),那么每个head负责的就是64维(因为512 ÷ 8 = 64)。这样,8个head就可以并行地分别进行注意力计算,输出8个64维的向量,最后再拼接成一个新的512维向量。可以理解为,我们将一个大空间拆解成8个小空间,每个空间独立工作。
这些“子空间”也可以类比为“信息的切片维度”。以句子“The quick brown fox jumps over the lazy dog.”为例,不同的子空间可能专注于不同语言层次:
- 子空间1:关注语法结构(主谓宾)
- 子空间2:捕捉长距离依赖关系(比如“fox”和“jumps”)
- 子空间3:处理形容词与名词的搭配(比如“lazy”和“dog”)
- 子空间4:识别句法角色(主语、宾语等)
每个head都在自己的空间内执行完整的注意力函数(推特公式渲染太差了,自己查吧):
Attentioni(Qi,Ki,Vi)=softmax(QiKiTdk)Vi
注意力函数 Attentioni(Qi,Ki,Vi)等于 softmax(QiKiTdk)乘以 Vi
它们各自输出不同角度的信息,再组合成最终理解结果。你可以把这个过程比喻成多个观察者一起看一幅画:一个人用显微镜看纹理,一个人用望远镜看远景,一个人分析色彩风格,还有一个人专注人物表情。最后,只有把这些观察结果合并起来,才能真正理解整幅画面。
接下来我们要讲的是,多头注意力机制的“合并”过程。确实,所有head的输出最后会被拼接成一个整体结果,再输入到Transformer的下一层。
首先是拼接(Concatenation):假设有h个注意力头(比如8个)每个head输出一个64维向量,那么拼接起来就是一个8 × 64 = 512维的长向量
形式上就是:
- Concat(head1,head2,...,headh)
- 拼接 head1、head2、...、headh
然后是线性变换(Linear Projection):
拼接完后,还要用一个输出矩阵 WO 做一次线性变换:
MultiHead(Q,K,V)=Concat(head1,...,headh)⋅WO
多头注意力机制(Q,K,V)=拼接(head1,...,headh)⋅WO
这个 WO 是可学习的参数矩阵,它的作用是把拼接后的表示重新映射回模型原本所需的维度(例如512维),以便与残差连接等结构配合使用。
我们再换一个比喻来帮助理解:假设有8位调查记者(对应8个head),他们分别从不同角度撰写调查小结:
一位负责分析人物关系 一位负责追踪资金流动 一位观察公众舆论……
你的任务是: 把这些小结合并成一份完整的综合报告(拼接) 再使用统一的写作风格进行润色和整合(线性变换) 最终生成的就是一个统一格式的注意力理解结果,具备多角度、综合性的语义信息。这一步也正是多头注意力机制的最大价值所在。
Transformer 再往下讲,就进入到真正深水区了。
在搞懂了 Attention(Q, K, V) 这个核心函数之后,我们的视角不再局限于“某一层做了什么”,而是慢慢抬升,进入一个全局语义建构的观察点:
一个超级大语言模型,究竟是如何通过上百层的堆叠、每秒数十亿次的计算,从最原始的 token 开始,一步步“理解人类语言”,最终流畅地“说出类人语言”?
这个演化过程,我称之为——层层递进,日益精化。
不是粗暴的“特征堆叠”,而是每一层都精细处理、选择性增强、递归地抽象语义结构。每一层的输出,都会成为下一层更深一步的语言构建基底。经过几十层、甚至近百层的精化之后,模型已经不再仅仅看见“词汇”,而是看见结构、意图、风格、任务目标。
我们接下来的任务,就是拆解这个“层层递进”的过程。
这并不是一个抽象的、黑箱的神秘过程。相反,它是完全可以被理解、被拆解、被可视化的。每一层,都要经历一套标准的处理流程:
多头注意力机制:从上下文中感知相关性; 前馈神经网络:对每个 token 独立地非线性重构; ReLU 激活:选择性保留有意义的信号; 残差连接:确保信息稳定传递、避免遗忘; LayerNorm 归一化:维持数值稳定与表达张力。
理解了这些构建块在每一层是如何被重复调度的,我们才真正能从“结构观察者”的角度,走入模型的深处。
只有在这个基础上,我们才能真正讲好下一步:生成机制。
因为语言模型并不是死记硬背的复读机,它的生成,是基于“递进演化之后的语言状态向量”所做出的行为决策。要理解生成,必须理解“生成之前的准备”。
Attention Layer 中的残差连接与 LayerNorm
2025年7月1日 06:50
当今的大模型往往是超深神经网络,层数轻松超过百层。要理解如此庞大的结构带来的挑战,可以用一个不完全严谨但形象的比喻:就像“传话游戏”一样,如果让一条信息依次传递给 20 个人,很可能最后听到的版本早已面目全非。同样的,在深度网络中,如果没有设计良好的信息通路,原始语义在层层变换中也极易被扭曲、遗失。
在 2015 年之前,神经网络的深度普遍停留在 20 到 30 层之间。随着层数的加深,模型表现反而下降,这被称为“退化现象”。其根本原因包括梯度消失、特征偏移和表示不稳定等训练问题。正是在这种背景下,一篇划时代的论文应运而生——《Deep Residual Learning for Image Recognition》。这项由微软研究院的何恺明(Kaiming He)、张祥雨(Xiangyu Zhang)、任少卿(Shaoqing Ren)和孙剑(Jian Sun)等人提出的研究,首次提出了“残差连接”(Residual Connection)机制,从根本上解决了深层网络难以训练的问题。
这项创新的直接成果就是 ResNet 系列模型(如 ResNet-50、ResNet-101、ResNet-152),它们在 ImageNet 图像识别任务中取得了突破性成绩,使得“百层网络”从概念走向现实。更重要的是,这种结构范式迅速影响了整个深度学习领域,成为后续许多关键模型的结构基础,包括 Transformer 的多层堆叠编码器-解码器架构,以及基于它演化出的 BERT、GPT 等大型语言模型,乃至视觉领域的 Vision Transformer(ViT)。
残差连接的核心思想很简单:不是让每一层都重新构造全部表达,而是在前一层的基础上进行“增量式”改进,即 y = x + F(x)。这种结构允许信息贯通整个网络,不被中间层彻底覆盖或干扰。而在 Transformer 中,这一结构通常与 LayerNorm(层归一化)结合使用,形成经典的 “Add & Norm” 模式。这种设计不仅保证了信息的连续性,也通过归一化机制维持了每一层的稳定分布,使得深度语言模型得以安全地堆叠数十至上百层。
从这个角度来看,残差连接与 LayerNorm 的搭配,不仅仅是一种技术细节,而是支撑整个现代 AI 模型深度化的基础设施。正是这项创新,让深度学习从“浅层表达”真正走向了“结构认知”,从“性能探索”进入了“工业落地”的新阶段。
残差连接(Residual Connection)。我对它的总结是这样的:
“在层层递进的过程中,不让一层完全推翻上一层。”
就像“传话游戏”,你不能在传话的过程中擅自篡改上一位所说的内容,只能在其基础上尽量讲得更清楚、更准确。深度网络中的每一层信息处理,其实也面临类似的挑战——如果没有良好的机制约束,信息在多层变换中很容易被扭曲,导致语义丢失。
残差连接的核心作用,就是一种信息保护机制。如果没有它,每一层都必须从零开始重新构建表达,既容易丢失已有语义结构(比如词义、句法、语境),又让每一层都背负“完整表达”的沉重负担。而引入残差连接后,每一层的任务就轻松多了,它只需要在前一层的基础上做一些“小修小补”,相当于打个“补丁”,而不是从头重写整段逻辑。就像写论文时,你不会每次重写全部内容,而是基于已有版本不断微调、精炼。
我们可以通过一个简单的例子来直观理解残差计算。设一个三维输入向量:
$$ x = [1.0, 2.0, 3.0] $$
我们设计一个残差函数 F(x),例如通过线性变换 + 偏置 + ReLU 非线性激活构建:
$$ W = [[0.5, 0.0, 0.0],[0.0, 0.5, 0.0],[0.0, 0.0, 0.5]] $$
$$ b = [0.1, -0.1, 0.2] $$
计算过程如下:
$$ Wx + b = [0.6, 0.9, 1.7] $$
$$ F(x) = ReLU([0.6, 0.9, 1.7]) = [0.6, 0.9, 1.7] $$
最终通过残差相加得到:
$$ x + F(x) = [1.6, 2.9, 4.7] $$
这一步最重要的理念是:原始输入 x 没有被丢掉,而是与新计算的增量 F(x) 结合在一起,作为下一层的输入。这不仅保留了前面层的结构,还允许网络在已有表达基础上逐步增强,避免信息被误处理或彻底重写。
你可能会说:这不就是简单的数值相加吗?是的,数学上很简单,但背后的思想却深刻。为了让这样的加法不会导致数值不稳定或分布偏移,Transformer 中在残差相加后会紧跟一个 LayerNorm 操作。你可以把它类比为“归一化”,就像学过概率统计的人熟悉的 normalization 过程:将输出重新压缩到一个合理的分布范围内,保持数值稳定,利于训练。
所以,残差连接 + LayerNorm,就是深度网络中“传话不走样”的保障机制——既保留原意,又允许优化;既递进增强,又不过度扰动。这一结构几乎是所有现代深层模型(包括 GPT、BERT、ViT 等)的基础之一。
我以前就说过,大语言模型其实是个“类比大师”。你现在让它解释一些复杂的概念,它张口就来,而且往往举的例子特别贴切——是不是很自然地就会想:它是不是天生擅长类比?
但问题是:它为什么能做到这一点?这不是魔法,而是数学在背后运作的结果。接下来我们就要深入到它的结构机制里:
比如——FeedForward 网络中,为什么要把一个低维向量映射到一个更高维的空间?这叫做仿射升维; 再比如——为什么要加一个看似简单的偏置项 b?它不仅调整激活区间,还给了模型泛化的能力。 这些操作,每一个看似微小的数学动作,其实都在悄悄塑造一个关键能力:在未见之处,仍能做出结构相似的判断——这就是类比的本质,也是模型能“懂你”的根基。
Transformer中的FeedForward Network
在我们已经深入解析了 Attention 的机制之后,Transformer 中另一个同样核心的结构也应被严肃对待——那就是 FNN(前馈网络)。
它是除 Attention 之外,Transformer 架构中最关键的表达机制之一:它承担的不是信息交换,而是语义抽象、非线性转换与个体认知的建构。
- Attention 是:“我听别人说了什么”
- FNN 是:“我自己怎么理解这件事”
如果你真正理解了 Attention 和 FNN,那么从单层视角来看,你已经基本掌握了 Transformer 在局部是如何工作的。这是构造一切语言理解的微结构单元。
我接下来的写作计划,是尽可能深入到数学层面去讲透 FNN。因为我的读者大多已经是大模型的高阶用户,对 Prompt 工程非常熟悉。
这个时候,如果你愿意回到线性代数的语言,你很可能会经历一个 AHA Moment——顿悟瞬间: 你会突然意识到:你在用提示词构造路径、引导模型理解的所有技巧,其实都有精确的数学解释。为什么大模型具备超越类比的泛化能力?为什么它能从人类没想到的角度“重构”一个概念?
答案就藏在那些你可能早就学过但从未重看的概念里:仿射升维、非线性映射、高维空间的激活结构。你不需要 PhD,只需要真正理解线性代数,就足以窥见大型模型背后的几何心智。
Affine Transformations仿射:预热启动
在正式进入高维空间与神经网络中的仿射结构之前,我们先来一次“直觉预热”。
我想最好的方式,就是借助电脑图形学(Computer Graphics)中的经典场景,用最可视化、最直观的方式带你理解什么是仿射升维(Affine Transformation with Dimensional Expansion)。
为什么这样做?
因为图形变换,就是向量变换的“具象版本”。我们可以直接把向量、空间、矩阵、旋转、平移这些抽象的代数操作,和你每天看到的图像画面联系起来。
接下来,请你先看下面这个小视频
里面演示了二维向量(也可以理解为像素点)在经历平移 + 旋转等变换时,是如何在屏幕上发生运动的,同时也会看到它背后所使用的矩阵与坐标变化。
看完之后,你会发现:
所谓仿射升维,其实就是在构建一个空间,让线性变换 + 平移变得统一、可操作、可组合。
这正是大模型背后的数学骨架之一。
大模型的神经元——FNN的第一步仿射升维
$$ h=W₁x+b1, W₁∈\mathbb{R}^{2048 \times 512}
$$
为什么我们这里要引入 W₁ 和 b1 呢?因为这只是 FNN 的第一跳,后面还有 W2 和 b2,所以这一跳必须先做。
来拆一下:
- x 是输入向量,来自前面经过了多头 Attention 处理后的结果;
- W1 是我们这一步的权重矩阵;
- b1 是偏置项;
- h=W₁x+b1 是我们要得到的升维结果。
上一条推我已经让你去看图形学的升维视频了,你应该能直观感受到——升维就是把一个低维向量“抬进”高维空间。这里虽然是 512 维升到 2048 维,但原理完全一样。
如果你学过线性代数,不管你是数学系还是经管/理工背景,你一定知道矩阵乘法的“合法性规则”:前一个矩阵的列数 = 后一个向量的行数,乘法才成立。
所以这里:
$$ x \in \mathbb{R}_{512}
$$
$$ W_{1}x \in \mathbb{R}_{2048 \times 512}
$$
- x 属于实数集 R 中的 512 维空间
- W₁属于实数域 R 中的 2048×512 维矩阵
自然就可以相乘,输出一个 2048 维的向量 h。
这一步的本质,就是把输入向量展开到一个更宽阔的语义空间里,为后面的非线性激活和降维做准备。
W₁是什么
我们先来讲讲 W₁ 到底是什么。它的作用可以用一句话概括:升维是为了扩大空间,将原始的语义向量投射到一个更丰富、更有表达力的高维空间中。这个“升维”其实非常好理解,不是什么神秘操作,而是为了让信息在网络中更好地传输和流动。维度一旦上升,模型就能在这个更大的空间中对语义结构做出更细致的区分,比如不同词义、上下文语境、语法角色等。
那 W₁ 一般是多少维的矩阵呢?经验上,它的维度通常是输入维度的 4 倍,比如输入是 512 维,W₁ 就是一个 R2048×512 的矩阵。为什么是 4 倍?这其实是通过大量实验总结出来的经验法则。维度太小没意义,模型表达能力受限;维度太大不仅计算成本高,还容易引发过拟合。所以 4 倍这个比例,往往被认为是在表达能力与计算效率之间的一个相对均衡点。
此外,Transformer 是一个典型的堆叠结构,每一层都有自己独立的 Multi-Head Attention 和 FeedForward 模块,因此每一层的 W₁ 都是不一样的。这是神经网络设计中的基本原则:每一层负责不同的“思维阶段”,自然需要不同的表达基底。例如,底层网络更偏向捕捉词法、句法和局部搭配结构,使用的是小尺度的投影方向;中层则开始处理句内语义与依存关系,需要中等尺度的特征组合;而高层关注的是跨句的语义抽象、意图识别与上下文构建,使用的是宏观语义空间的展开方式。
那么 W₁ 是怎么来的?它不是固定设定的,而是在训练过程中通过反向传播(Backpropagation)一步步“学”出来的。模型根据损失函数对每一层的输出表现打分,然后通过链式法则更新 W₁ 的每个参数,最终形成了一个专属于该层的高维变换器,它反映了模型对输入语言结构的“个性化理解方式”。
那么,b₁ 又是什么?
如果你看了我上一期推荐的那个讲解图形学中向量变换的视频,你现在应该更容易理解这个公式:
$$ h = W_{1}x + b_{1}
$$
$$ y = \mathbf{w} \cdot \mathbf{x} + b
$$
把它简单点想,就是最基本的一元一次函数形式:
$$ y = w \cdot x + b
$$
y 等于 w 乘以 x 加上 b
你学过初中数学就知道,这里的 b 是干嘛的——它就是把函数整体上下平移的。想象一个二维坐标系,原本一条线通过原点,加入偏置 b 后,它可以上移、下移,从而决定函数从哪个高度开始激活。用图形学的语言来说,这就是一个仿射变换(affine transformation)中的“平移项”。
为什么这个操作重要?你想象一下神经网络在处理一堆数据点时,如果没有偏置,
每个神经元的激活阈值都“卡”在原点附近,
这样网络就缺乏灵活性,无法适配不同类型的输入。有了偏置 b1,模型就可以在不同的空间位置上开始处理、激活、变化。它打破了“所有输入都从 0 开始”的限制,允许模型在更丰富的位置感知信息、响应输入。
也正因为如此,偏置项 b1直接影响模型的泛化能力。它不是随机给的,而是通过数据训练出来的。可以说,在 Transformer 这样的模型中,b1 是一笔神来之笔:它虽然看起来微小,但起到了结构调节器的作用。
如果你用语义的方式去理解它——偏置不只是一个参数,它就像是“神经元的性格倾向”。
有的神经元天生外向,b 值较大,稍有输入就会激活,像个反应敏捷、情绪丰富的人;
有的神经元天生内向,b 值较小或为负,输入必须很强烈才会触发,像个谨慎、沉稳的人。
所以说,偏置不是功能,它是性格,是神经元对世界的反应起点。
偏置也像“默认语境”:就像一句“真不错啊”,在不同语境下可能是赞美,也可能是讽刺。同样的输入 x,在不同的偏置背景下,模型的理解是完全不同的。偏置决定了你在什么心情、什么立场下接受一个输入。
它还像语言句式中的语气助词。
权重 W₁决定句子的主干结构,而偏置 b 就像“哦”“呢”“啊”“终于”这样的词,它不改变信息本体,但完全能改变表达的语感、态度和重心。
再比如音乐中的“定音锤”:乐句可以自由变化,但每段音乐都有一个调性起点,而这个调性,就是由偏置设定的。换句话说,在神经网络中,W 是旋律,b 是调性。模型每一层的偏置,就是在设定“我准备从这里开始感知世界”。
最后,也是最重要的,从迁移学习的角度来看,偏置更像是一种泛化的预备状态。一个优秀的大模型不是每次都要重新学习全部结构,而是保留一套强大的神经基座,然后在不同任务中只需要微调一些“启动姿态”就能适配新任务。这组“启动姿态”很多时候就是偏置。它帮你从“通用结构”过渡到“特定场景”,帮助模型找到新的共鸣点。
完整的 FFN 函数流程
现在你已经可以完整理解 FFN(前馈神经网络)的整个结构公式了:
$$ \text{FFN}(x) = \text{ReLU}(xW_1 + b_1)W_2 + b_2
$$
这个公式描述了 Transformer 中每一层最关键的结构之一。我们可以一步步来拆解其中的逻辑与意义。
1️⃣ 输入向量 x 的语义状态
输入向量 x
是前面一系列处理步骤的结果,也就是经过多头注意力机制、残差连接和层归一化之后的输出。
在我们的语境中,x
是一个 512维的语义向量,代表当前 token 在这一层的语义状态。
2️⃣ 第一步:升维操作 xW₁ + b₁
其中:
W₁
是一个维度为 512 × 2048 的权重矩阵(即
$$ W₁ ∈ \mathbb{R}^{512 \times 2048} $$
b₁
是一个 2048维的偏置向量
这个步骤的目的,是将 512 维的语义向量展开到更大的特征空间 —— 2048 维。
这一步是“语义展开”,让模型有更多的参数自由度,能表达更复杂、精妙的语义特征。相当于做了一个语义的 “扩容器”。
3️⃣ 第二步:非线性激活函数 ReLU
ReLU,全称为 Rectified Linear Unit,是当前神经网络中最常用的激活函数。它的定义非常简单:
-
对于输入向量中的每个值
z
:
- 若
z > 0
,保留原值 - 若
z ≤ 0
,输出 0
- 若
你可以把它理解为一种“语义滤波器”,只保留正能量、抑制无效/负激活。
示例:
$$ 输入:[-2.0, 0.0, 1.5, 3.2, -0.8] $$
$$ ReLU 输出:[0.0, 0.0, 1.5, 3.2, 0.0]
$$
这一步是线性之后的稀疏激活,有助于模型专注于最重要的语义特征。
4️⃣ 第三步:降维操作 · W₂ + b₂
W₂
是一个 2048 × 512 的降维矩阵b₂
是一个 512维的偏置向量
这一阶段是“语义浓缩”,将展开后的语义向量重新投影回 512 维的原始表示空间,准备给下一层使用。
✴️ 总结成图结构:
$$ \text{FFN} = \underbrace{\text{升维} + \text{ReLU}}{\text{语义展开}} \rightarrow \underbrace{\text{降维} + \text{偏置}}{\text{语义浓缩}}
$$
💡 用线性代数角度再看一次:
我们可以从矩阵维度的角度理解这个过程:
- 输入
x
是一个 1×512 的向量 - 乘以
$$ W₁ ∈ \mathbb{R}^{512 \times 2048} $$
(升维矩阵),得到 1×2048
- ReLU 激活后仍为 1×2048
- 乘以降维矩阵「下公式」最终得到 1×512
$$ W₂ ∈ \mathbb{R}^{2048 \times 512}, $$
- 加上偏置
b₂
得到输出
整个过程就是:
x → 升维 → 激活 → 降维 → 加偏置 → 输出
🔁 想复现 FFN 的升降维过程?
你可以自己拿:
1×3
向量3×12
升维矩阵12×3
降维矩阵
来手动推演 FFN 的升维 + ReLU + 降维全过程。
❓为什么降维后还要再加一个偏置 b₂?
从功能上来说与 b₁ 类似,是经验与表现之间的权衡,有助于语言变换更稳定、表达更细腻。
如果你想用一两句话记住这个过程:
FFN = 升维 + ReLU → 降维 + 偏置
人工智能的认知皮层
至此,我们已经从整体结构上解构了大语言模型 Transformer 的单层模块,它也常被类比为“人工智能的认知皮层”。在 Transformer 架构中,每一层 Layer 并不只是一个简单的神经网络运算单位,而是一个结构化的信息处理模块,仿照人类大脑皮层的处理方式,将输入的语言信息逐步抽象、压缩、选择,并生成更高层次、更符合语义逻辑的表达。
一个标准的 Transformer 层通常包含三个核心组成部分。第一是多头自注意力机制(Multi-Head Self-Attention),它允许每个 token 不只是理解自己,还能同时“看到”句子中其他所有 token,并以不同的角度去判断哪些信息在当前语境中最为重要。注意力机制的“多头”结构则让模型在多个语义空间中并行提取关联特征。第二部分是前馈神经网络(Feed-Forward Network, FFN),它对每个 token 的表示向量单独进行处理:先升维以拓展语义表示空间,再通过非线性激活函数选择有意义的特征,最后再降维回原始维度,以完成一次局部语义的加工。第三部分是残差连接与层归一化(Residual Connection + LayerNorm),它们共同保证信息的稳定传递:残差连接允许模型保留原始信息而不被新一层完全覆盖,而归一化机制则避免激活值在层间传递中失衡,有助于稳定训练过程。
注意力机制的核心函数Attention (Q, K, V)-2 以及多头注意力机制
Attention Layer 中的残差连接与 LayerNorm
这个结构可以被简化成一个逻辑流程图:输入向量首先进入多头注意力模块,然后加上残差并做一次归一化处理;接着传入前馈神经网络,再次残差连接并归一化。最终输出的新向量则会成为下一层的输入。这样的模块并不是独立存在的,而是作为整个模型的基础单元被一层层堆叠起来。以 GPT 模型为例,GPT-2 包含 12 至 24 层,GPT-3 增至 96 层,而 GPT-4 被推测可能超过 100 层;BERT-base 有 12 层,BERT-large 有 24 层。每一层都拥有相同的结构,但参数独立、语义功能递进。就像人脑皮层中不同区域处理不同层级的信息,每一层 Transformer 都负责更进一步的语义抽象。
从认知结构的角度来看,Transformer 的每一层可以类比为一个“人工皮层单元”,具备类神经系统的三个核心功能:感知、加工、整合。感知机制由多头注意力实现,相当于模型的“感官”;加工机制由 FFN 执行,完成特征提取与语义变化;整合机制则通过残差连接与归一化,把旧的信息结构与新提取的语义进行融合,形成更稳定的表达方式。这使得每一层都具备了局部理解、结构压缩和语义统一的能力,是大模型内部的认知最小单位。
一句话总结:Transformer Layer 就是大型语言模型的大脑皮层。每一层都在进行一次“看懂 → 加工 → 整合”的语义演化过程,最终通过数十乃至上百层的堆叠,构建出类人语言智能的神经系统。
原文地址:https://rainiermoss.notion.site/Attention-is-ALL-you-need-221320d5081a80ff8df8e6cdc826ddb0