前言:推开那扇通往“上帝视角”的门
🌪️ 一场静悄悄的革命
把时针拨回 2017 年。
那时候的 AI 还在费劲地像小学生一样,一个字一个字地读课文(RNN/LSTM 时代)。它读到句子末尾时,往往已经忘了开头讲了什么。
就在那一年,Google 的几位工程师丢出了一篇论文——《Attention Is All You Need》。
这篇论文就像一块巨石砸进了平静的湖面,激起的涟漪最终演变成了今天的海啸:BERT、GPT-3、ChatGPT、Sora…… 这些震撼世界的模型,剥开外衣后,里面躺着的都是同一个架构——Transformer。
它是 AI 时代的蒸汽机,是通往通用人工智能(AGI)的入场券。
🤯 为什么要写这篇博客?
如果你尝试过去读原论文,或者搜过网上的教程,你可能经历过以下心态崩溃的瞬间:
softmax
(
Q
K
T
d
k
)
V
\\text{softmax}(\\frac{QK^T}{\\sqrt{d_k}})V
softmax(dkQKT)V 直接关网页。
这篇博客不打算这么干。
我们不追求把每个数学推导都写得天衣无缝,我们追求的是直觉(Intuition)。 我会用搭乐高、查字典、开相亲大会、做阅读理解等各种生动的比喻,带你钻进 Transformer 的黑盒子里,看着数据是如何在里面流动的。
我们将把这个复杂的巨兽拆解成一个个简单的零件,最后你会发现:原来所谓的“神级架构”,也不过就是精妙的工程学积木罢了。
🗺️ 我们的探险路线图
为了不让你在迷宫里晕头转向,这是我们接下来的旅程规划:
#mermaid-svg-IXDGPm1GZoXtXwek{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-IXDGPm1GZoXtXwek .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-IXDGPm1GZoXtXwek .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-IXDGPm1GZoXtXwek .error-icon{fill:#552222;}#mermaid-svg-IXDGPm1GZoXtXwek .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-IXDGPm1GZoXtXwek .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-IXDGPm1GZoXtXwek .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-IXDGPm1GZoXtXwek .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-IXDGPm1GZoXtXwek .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-IXDGPm1GZoXtXwek .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-IXDGPm1GZoXtXwek .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-IXDGPm1GZoXtXwek .marker{fill:#333333;stroke:#333333;}#mermaid-svg-IXDGPm1GZoXtXwek .marker.cross{stroke:#333333;}#mermaid-svg-IXDGPm1GZoXtXwek svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-IXDGPm1GZoXtXwek p{margin:0;}#mermaid-svg-IXDGPm1GZoXtXwek .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-IXDGPm1GZoXtXwek .cluster-label text{fill:#333;}#mermaid-svg-IXDGPm1GZoXtXwek .cluster-label span{color:#333;}#mermaid-svg-IXDGPm1GZoXtXwek .cluster-label span p{background-color:transparent;}#mermaid-svg-IXDGPm1GZoXtXwek .label text,#mermaid-svg-IXDGPm1GZoXtXwek span{fill:#333;color:#333;}#mermaid-svg-IXDGPm1GZoXtXwek .node rect,#mermaid-svg-IXDGPm1GZoXtXwek .node circle,#mermaid-svg-IXDGPm1GZoXtXwek .node ellipse,#mermaid-svg-IXDGPm1GZoXtXwek .node polygon,#mermaid-svg-IXDGPm1GZoXtXwek .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-IXDGPm1GZoXtXwek .rough-node .label text,#mermaid-svg-IXDGPm1GZoXtXwek .node .label text,#mermaid-svg-IXDGPm1GZoXtXwek .image-shape .label,#mermaid-svg-IXDGPm1GZoXtXwek .icon-shape .label{text-anchor:middle;}#mermaid-svg-IXDGPm1GZoXtXwek .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-IXDGPm1GZoXtXwek .rough-node .label,#mermaid-svg-IXDGPm1GZoXtXwek .node .label,#mermaid-svg-IXDGPm1GZoXtXwek .image-shape .label,#mermaid-svg-IXDGPm1GZoXtXwek .icon-shape .label{text-align:center;}#mermaid-svg-IXDGPm1GZoXtXwek .node.clickable{cursor:pointer;}#mermaid-svg-IXDGPm1GZoXtXwek .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-IXDGPm1GZoXtXwek .arrowheadPath{fill:#333333;}#mermaid-svg-IXDGPm1GZoXtXwek .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-IXDGPm1GZoXtXwek .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-IXDGPm1GZoXtXwek .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-IXDGPm1GZoXtXwek .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-IXDGPm1GZoXtXwek .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-IXDGPm1GZoXtXwek .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-IXDGPm1GZoXtXwek .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-IXDGPm1GZoXtXwek .cluster text{fill:#333;}#mermaid-svg-IXDGPm1GZoXtXwek .cluster span{color:#333;}#mermaid-svg-IXDGPm1GZoXtXwek div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-IXDGPm1GZoXtXwek .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-IXDGPm1GZoXtXwek rect.text{fill:none;stroke-width:0;}#mermaid-svg-IXDGPm1GZoXtXwek .icon-shape,#mermaid-svg-IXDGPm1GZoXtXwek .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-IXDGPm1GZoXtXwek .icon-shape p,#mermaid-svg-IXDGPm1GZoXtXwek .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-IXDGPm1GZoXtXwek .icon-shape rect,#mermaid-svg-IXDGPm1GZoXtXwek .image-shape rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-IXDGPm1GZoXtXwek .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-IXDGPm1GZoXtXwek .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-IXDGPm1GZoXtXwek :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}
生成与输出
核心组件拆解
起点
第1章: 为什么要抛弃RNN?
第2章: 宏观俯瞰 Transformer
第3章: Embedding & 位置编码
第4-5章: 自注意力 & 多头机制
第6-7章: 残差连接 & FFN
第8章: 解码器的 Mask 秘密
第9章: 输出与未来
终点: 觉醒
📚 目录:Transformer 拆解之旅
-
[第一章:告别“接力跑”——为什么要抛弃 RNN?]
- 看旧时代的霸主是如何因“记性不好”和“腿脚太慢”被历史淘汰的。
-
[第二章:黑盒与乐高——宏观俯瞰 Transformer]
- 不谈细节,先看骨架。认识 Encoder 和 Decoder 这对孪生兄弟。
-
[第三章:单词的 GPS——Embedding 与位置编码]
- 机器不识字也不识数,怎么让它知道“我爱你”和“你爱我”的区别?
-
[第四章:灵魂核心——自注意力机制 (Self-Attention)]
- 全篇最硬核!看 AI 如何通过“相亲大会”找出一句话里的隐藏关系。
-
[第五章:多头注意力 (Multi-Head Attention)——三个臭皮匠,顶个诸葛亮]
- 为什么要搞 8 个脑袋?论“多维度思考”的重要性。
-
[第六章:连接与归一化——残差连接 (Residual) 与 LayerNorm]
- 防止楼盖塌的工程学奇迹,给信息开通“VIP 直通车”。
-
[第七章:前馈神经网络 (Feed-Forward Networks)——记忆的精炼]
- Attention 负责社交,FFN 负责思考。揭秘参数量最大的“记忆区”。
-
[第八章:解码器的独角戏——Masked Multi-Head Attention]
- 考试不能作弊!看 Decoder 如何戴着“眼罩”预测未来。
-
[第九章:终章——输出与未来]
- 从一堆数字变回人类语言。BERT 和 GPT 家族是如何分道扬镳的?
-
[附录 1:代码实战] (PyTorch 逐行手撕 Transformer)
-
[后记] (走出黑盒,看见星辰大海)
第一章:告别“接力跑”——为什么要抛弃 RNN?
在 2017 年那篇著名的论文《Attention Is All You Need》横空出世之前,自然语言处理(NLP)的世界是由 RNN(循环神经网络) 和它的升级版 LSTM(长短期记忆网络) 统治的。
虽然它们在当时也是划时代的发明,但它们身上有一个致命的基因缺陷——时序依赖(Sequential Dependency)。
1. 以前的 AI 是怎么“读书”的?
想象一下,你让一个旧时代的 AI 翻译这句话:
“The cat didn’t cross the street because it was too tired.” (这只猫没有过马路,因为它太累了。)
RNN 处理这句话的方式,就像是一个只能看见眼前一个单词的阅读者,或者像是在玩**“传话游戏”**(接力跑)。
h
1
h_1
h1)。
h
1
h_1
h1 的记忆,它读入 cat,生成新的记忆
h
2
h_2
h2。
h
2
h_2
h2 的记忆,它读入 didn't……
❌ 痛点一:距离产生的不是美,是遗忘
在这个“接力跑”的过程中,随着句子越来越长,开头的信息就像传话游戏一样,越传越模糊。这就是著名的长距离依赖问题(Long-term Dependency Problem)。虽然 LSTM 通过“遗忘门”强行续命,但面对几百个词的长文,它依然会“老年痴呆”。
❌ 痛点二:显卡有劲儿使不上
这是最让工程师抓狂的。因为第 100 个词的计算必须等第 99 个词算完。这意味着你买了最贵的 NVIDIA 显卡,有几千个计算核心,结果它们只能排队一个接一个地干活,无法并行。
我们来看一张图,感受一下这种“憋屈”:
#mermaid-svg-aVKJOF1sPUtKQxdL{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-aVKJOF1sPUtKQxdL .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-aVKJOF1sPUtKQxdL .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-aVKJOF1sPUtKQxdL .error-icon{fill:#552222;}#mermaid-svg-aVKJOF1sPUtKQxdL .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-aVKJOF1sPUtKQxdL .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-aVKJOF1sPUtKQxdL .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-aVKJOF1sPUtKQxdL .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-aVKJOF1sPUtKQxdL .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-aVKJOF1sPUtKQxdL .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-aVKJOF1sPUtKQxdL .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-aVKJOF1sPUtKQxdL .marker{fill:#333333;stroke:#333333;}#mermaid-svg-aVKJOF1sPUtKQxdL .marker.cross{stroke:#333333;}#mermaid-svg-aVKJOF1sPUtKQxdL svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-aVKJOF1sPUtKQxdL p{margin:0;}#mermaid-svg-aVKJOF1sPUtKQxdL .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-aVKJOF1sPUtKQxdL .cluster-label text{fill:#333;}#mermaid-svg-aVKJOF1sPUtKQxdL .cluster-label span{color:#333;}#mermaid-svg-aVKJOF1sPUtKQxdL .cluster-label span p{background-color:transparent;}#mermaid-svg-aVKJOF1sPUtKQxdL .label text,#mermaid-svg-aVKJOF1sPUtKQxdL span{fill:#333;color:#333;}#mermaid-svg-aVKJOF1sPUtKQxdL .node rect,#mermaid-svg-aVKJOF1sPUtKQxdL .node circle,#mermaid-svg-aVKJOF1sPUtKQxdL .node ellipse,#mermaid-svg-aVKJOF1sPUtKQxdL .node polygon,#mermaid-svg-aVKJOF1sPUtKQxdL .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-aVKJOF1sPUtKQxdL .rough-node .label text,#mermaid-svg-aVKJOF1sPUtKQxdL .node .label text,#mermaid-svg-aVKJOF1sPUtKQxdL .image-shape .label,#mermaid-svg-aVKJOF1sPUtKQxdL .icon-shape .label{text-anchor:middle;}#mermaid-svg-aVKJOF1sPUtKQxdL .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-aVKJOF1sPUtKQxdL .rough-node .label,#mermaid-svg-aVKJOF1sPUtKQxdL .node .label,#mermaid-svg-aVKJOF1sPUtKQxdL .image-shape .label,#mermaid-svg-aVKJOF1sPUtKQxdL .icon-shape .label{text-align:center;}#mermaid-svg-aVKJOF1sPUtKQxdL .node.clickable{cursor:pointer;}#mermaid-svg-aVKJOF1sPUtKQxdL .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-aVKJOF1sPUtKQxdL .arrowheadPath{fill:#333333;}#mermaid-svg-aVKJOF1sPUtKQxdL .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-aVKJOF1sPUtKQxdL .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-aVKJOF1sPUtKQxdL .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-aVKJOF1sPUtKQxdL .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-aVKJOF1sPUtKQxdL .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-aVKJOF1sPUtKQxdL .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-aVKJOF1sPUtKQxdL .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-aVKJOF1sPUtKQxdL .cluster text{fill:#333;}#mermaid-svg-aVKJOF1sPUtKQxdL .cluster span{color:#333;}#mermaid-svg-aVKJOF1sPUtKQxdL div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-aVKJOF1sPUtKQxdL .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-aVKJOF1sPUtKQxdL rect.text{fill:none;stroke-width:0;}#mermaid-svg-aVKJOF1sPUtKQxdL .icon-shape,#mermaid-svg-aVKJOF1sPUtKQxdL .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-aVKJOF1sPUtKQxdL .icon-shape p,#mermaid-svg-aVKJOF1sPUtKQxdL .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-aVKJOF1sPUtKQxdL .icon-shape rect,#mermaid-svg-aVKJOF1sPUtKQxdL .image-shape rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-aVKJOF1sPUtKQxdL .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-aVKJOF1sPUtKQxdL .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-aVKJOF1sPUtKQxdL :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}
RNN 的接力跑模式 (串行)
路途遥远,信息衰减
Input: The
h1
h2
Input: cat
h3
Input: …
h99
h100
Input: it
图解说明:注意那个从
h
1
h_1
h1 到
h
100
h_{100}
h100 的虚线。在 RNN 中,it 想要理解自己是指代 cat,需要跨越漫长的时间步,信号早已微弱不堪。
2. Transformer 的“上帝视角”
Transformer 的出现,就像是把这个逐字阅读的 AI,变成了一个过目不忘的速读天才。
它抛弃了循环(Recurrence),它不再一个词一个词地读,而是一巴掌把整句话拍在桌子上,同时处理所有的词!
- 没有时间先后:它不需要等 The 读完才读 cat。
- 并行计算:显卡里的几千个核心终于可以同时开工了,速度起飞。
- 无视距离:在 Transformer 眼里,第 1 个词和第 100 个词之间的距离是 0。它们之间可以直接“眉来眼去”(计算注意力),不需要中间商传话。
这就好比大家在一个吵闹的鸡尾酒会上:
- RNN 是一个人拿着麦克风挨个采访,问完这个才能问下一个。
- Transformer 是所有人同时在房间里,谁想和谁说话都可以直接喊,大家都能瞬间听到彼此。
我们来看 Transformer 是如何工作的:
#mermaid-svg-rkejNaFNd8LBkDye{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-rkejNaFNd8LBkDye .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-rkejNaFNd8LBkDye .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-rkejNaFNd8LBkDye .error-icon{fill:#552222;}#mermaid-svg-rkejNaFNd8LBkDye .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-rkejNaFNd8LBkDye .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-rkejNaFNd8LBkDye .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-rkejNaFNd8LBkDye .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-rkejNaFNd8LBkDye .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-rkejNaFNd8LBkDye .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-rkejNaFNd8LBkDye .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-rkejNaFNd8LBkDye .marker{fill:#333333;stroke:#333333;}#mermaid-svg-rkejNaFNd8LBkDye .marker.cross{stroke:#333333;}#mermaid-svg-rkejNaFNd8LBkDye svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-rkejNaFNd8LBkDye p{margin:0;}#mermaid-svg-rkejNaFNd8LBkDye .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-rkejNaFNd8LBkDye .cluster-label text{fill:#333;}#mermaid-svg-rkejNaFNd8LBkDye .cluster-label span{color:#333;}#mermaid-svg-rkejNaFNd8LBkDye .cluster-label span p{background-color:transparent;}#mermaid-svg-rkejNaFNd8LBkDye .label text,#mermaid-svg-rkejNaFNd8LBkDye span{fill:#333;color:#333;}#mermaid-svg-rkejNaFNd8LBkDye .node rect,#mermaid-svg-rkejNaFNd8LBkDye .node circle,#mermaid-svg-rkejNaFNd8LBkDye .node ellipse,#mermaid-svg-rkejNaFNd8LBkDye .node polygon,#mermaid-svg-rkejNaFNd8LBkDye .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-rkejNaFNd8LBkDye .rough-node .label text,#mermaid-svg-rkejNaFNd8LBkDye .node .label text,#mermaid-svg-rkejNaFNd8LBkDye .image-shape .label,#mermaid-svg-rkejNaFNd8LBkDye .icon-shape .label{text-anchor:middle;}#mermaid-svg-rkejNaFNd8LBkDye .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-rkejNaFNd8LBkDye .rough-node .label,#mermaid-svg-rkejNaFNd8LBkDye .node .label,#mermaid-svg-rkejNaFNd8LBkDye .image-shape .label,#mermaid-svg-rkejNaFNd8LBkDye .icon-shape .label{text-align:center;}#mermaid-svg-rkejNaFNd8LBkDye .node.clickable{cursor:pointer;}#mermaid-svg-rkejNaFNd8LBkDye .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-rkejNaFNd8LBkDye .arrowheadPath{fill:#333333;}#mermaid-svg-rkejNaFNd8LBkDye .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-rkejNaFNd8LBkDye .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-rkejNaFNd8LBkDye .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-rkejNaFNd8LBkDye .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-rkejNaFNd8LBkDye .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-rkejNaFNd8LBkDye .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-rkejNaFNd8LBkDye .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-rkejNaFNd8LBkDye .cluster text{fill:#333;}#mermaid-svg-rkejNaFNd8LBkDye .cluster span{color:#333;}#mermaid-svg-rkejNaFNd8LBkDye div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-rkejNaFNd8LBkDye .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-rkejNaFNd8LBkDye rect.text{fill:none;stroke-width:0;}#mermaid-svg-rkejNaFNd8LBkDye .icon-shape,#mermaid-svg-rkejNaFNd8LBkDye .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-rkejNaFNd8LBkDye .icon-shape p,#mermaid-svg-rkejNaFNd8LBkDye .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-rkejNaFNd8LBkDye .icon-shape rect,#mermaid-svg-rkejNaFNd8LBkDye .image-shape rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-rkejNaFNd8LBkDye .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-rkejNaFNd8LBkDye .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-rkejNaFNd8LBkDye :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}
Transformer 的上帝视角
所有词同时输入
直接连接
直接连接
Input: The cat … it
Transformer 核心处理区
The
it
cat
Output: 翻译结果
图解说明:在 Transformer 中,cat 和 it 之间有一条直接的连线(通过 Self-Attention 机制,后面章节会细讲)。无论句子多长,它们永远是“邻居”。
3. 本章小结:时代的转折点
如果把 NLP 模型的进化史看作交通工具的演变:
- RNN 是一列老式火车,车厢必须一节扣一节,第一节动了,最后一节才能跟着动。
- Transformer 是一支星际舰队,所有飞船(单词)在太空中展开,彼此之间通过无线电瞬时联络,既能独立机动,又能整体协同。
这一章你需要记住的核心概念:
这就引出了一个巨大的悬念:既然没有了先后顺序,Transformer 怎么知道“我爱你”和“你爱我”的区别呢?毕竟这两个句子的单词完全一样啊!这就是我们第二章和第三章要解决的问题。
在第一章,我们已经把 RNN 扔进了历史的垃圾桶。现在,我们要把 Transformer 搬上解剖台。
在深入那些复杂的矩阵乘法之前,我们先得退后一步,用宏观的视角看看它的整体骨架。如果你一上来就钻进“自注意力”的细节,很容易只见树木不见森林。
第二章:黑盒与乐高——宏观俯瞰 Transformer
很多技术博客上来就给你扔出一张密密麻麻的内部结构图,看着就头晕。我们不这么干。我们先假设 Transformer 就是一个完全密封的黑盒子。
1. 最简单的视角:神奇的翻译机
想象 Transformer 是一个放在桌子上的黑色方块。
- 左边入口:塞进去一句中文:“我爱学习”。
- 右边出口:吐出来一句英文:“I love study”。
此时,我们不需要知道里面发生了什么,只需要知道它是一个Sequence-to-Sequence(序列到序列)的模型。
#mermaid-svg-iQG7zzNYbwMPjLE9{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-iQG7zzNYbwMPjLE9 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-iQG7zzNYbwMPjLE9 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-iQG7zzNYbwMPjLE9 .error-icon{fill:#552222;}#mermaid-svg-iQG7zzNYbwMPjLE9 .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-iQG7zzNYbwMPjLE9 .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-iQG7zzNYbwMPjLE9 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-iQG7zzNYbwMPjLE9 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-iQG7zzNYbwMPjLE9 .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-iQG7zzNYbwMPjLE9 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-iQG7zzNYbwMPjLE9 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-iQG7zzNYbwMPjLE9 .marker{fill:#333333;stroke:#333333;}#mermaid-svg-iQG7zzNYbwMPjLE9 .marker.cross{stroke:#333333;}#mermaid-svg-iQG7zzNYbwMPjLE9 svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-iQG7zzNYbwMPjLE9 p{margin:0;}#mermaid-svg-iQG7zzNYbwMPjLE9 .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-iQG7zzNYbwMPjLE9 .cluster-label text{fill:#333;}#mermaid-svg-iQG7zzNYbwMPjLE9 .cluster-label span{color:#333;}#mermaid-svg-iQG7zzNYbwMPjLE9 .cluster-label span p{background-color:transparent;}#mermaid-svg-iQG7zzNYbwMPjLE9 .label text,#mermaid-svg-iQG7zzNYbwMPjLE9 span{fill:#333;color:#333;}#mermaid-svg-iQG7zzNYbwMPjLE9 .node rect,#mermaid-svg-iQG7zzNYbwMPjLE9 .node circle,#mermaid-svg-iQG7zzNYbwMPjLE9 .node ellipse,#mermaid-svg-iQG7zzNYbwMPjLE9 .node polygon,#mermaid-svg-iQG7zzNYbwMPjLE9 .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-iQG7zzNYbwMPjLE9 .rough-node .label text,#mermaid-svg-iQG7zzNYbwMPjLE9 .node .label text,#mermaid-svg-iQG7zzNYbwMPjLE9 .image-shape .label,#mermaid-svg-iQG7zzNYbwMPjLE9 .icon-shape .label{text-anchor:middle;}#mermaid-svg-iQG7zzNYbwMPjLE9 .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-iQG7zzNYbwMPjLE9 .rough-node .label,#mermaid-svg-iQG7zzNYbwMPjLE9 .node .label,#mermaid-svg-iQG7zzNYbwMPjLE9 .image-shape .label,#mermaid-svg-iQG7zzNYbwMPjLE9 .icon-shape .label{text-align:center;}#mermaid-svg-iQG7zzNYbwMPjLE9 .node.clickable{cursor:pointer;}#mermaid-svg-iQG7zzNYbwMPjLE9 .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-iQG7zzNYbwMPjLE9 .arrowheadPath{fill:#333333;}#mermaid-svg-iQG7zzNYbwMPjLE9 .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-iQG7zzNYbwMPjLE9 .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-iQG7zzNYbwMPjLE9 .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-iQG7zzNYbwMPjLE9 .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-iQG7zzNYbwMPjLE9 .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-iQG7zzNYbwMPjLE9 .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-iQG7zzNYbwMPjLE9 .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-iQG7zzNYbwMPjLE9 .cluster text{fill:#333;}#mermaid-svg-iQG7zzNYbwMPjLE9 .cluster span{color:#333;}#mermaid-svg-iQG7zzNYbwMPjLE9 div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-iQG7zzNYbwMPjLE9 .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-iQG7zzNYbwMPjLE9 rect.text{fill:none;stroke-width:0;}#mermaid-svg-iQG7zzNYbwMPjLE9 .icon-shape,#mermaid-svg-iQG7zzNYbwMPjLE9 .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-iQG7zzNYbwMPjLE9 .icon-shape p,#mermaid-svg-iQG7zzNYbwMPjLE9 .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-iQG7zzNYbwMPjLE9 .icon-shape rect,#mermaid-svg-iQG7zzNYbwMPjLE9 .image-shape rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-iQG7zzNYbwMPjLE9 .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-iQG7zzNYbwMPjLE9 .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-iQG7zzNYbwMPjLE9 :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}
输入: 我爱学习
Transformer 黑盒
输出: I love study
2. 掀开盖子:左右互搏的“乐高塔”
现在,我们把黑盒子的盖子掀开。你会发现里面并不是浑然一体的,而是分成了左右两大阵营,就像两座乐高积木塔。
这就是大名鼎鼎的 Encoder-Decoder(编码器-解码器) 架构。
- 左边的塔(Encoder 编码器):负责“输入”。它的工作是“理解”。它要把你那句中文嚼碎了、吃透了,转化成一团机器能看懂的“语义向量”。
- 右边的塔(Decoder 解码器):负责“输出”。它的工作是“生成”。它拿着左边给它的“语义”,根据上文,一个字一个字地蹦出英文。
🎓 生动比喻:老学究与畅销书作家
为了彻底理解这两兄弟的关系,我们可以这样比喻:
- Encoder(老学究):他博古通今,阅读理解能力满分。你给他一篇文章,他看完后不说话,而是默默地画出一张“思维导图”(Context Vector)。这张图里包含了文章里所有的知识点、逻辑关系和情感色彩。
- Decoder(畅销书作家):他文笔极好,负责根据那张“思维导图”来写文章。但他有个习惯,写字必须一个一个写。他一边看着老学究给的导图(Cross Attention),一边看着自己刚刚写下的字(Masked Self-Attention),以此来决定下一个字写什么。
注意:这两座塔不仅是分开的,而且是可以堆叠的。 在 Google 最初的论文中,Encoder 和 Decoder 各自堆了 6 层。为什么是 6 层?没啥特别原因,可能是 Google 工程师觉得 6 这个数字吉利(其实是实验出来的超参数)。这就好比老学究不是一个人,而是 6 个老学究组成的的专家组,一层层地传递信息,理解得越来越深。
3. 宏观架构图解
我们用 Mermaid 来画一下这个“乐高塔”结构。请注意中间那条横跨左右的连线,那就是**“老学究”把“思维导图”递给“作家”的关键时刻**。
#mermaid-svg-vbvADCBfv6pIHHzF{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-vbvADCBfv6pIHHzF .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-vbvADCBfv6pIHHzF .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-vbvADCBfv6pIHHzF .error-icon{fill:#552222;}#mermaid-svg-vbvADCBfv6pIHHzF .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-vbvADCBfv6pIHHzF .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-vbvADCBfv6pIHHzF .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-vbvADCBfv6pIHHzF .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-vbvADCBfv6pIHHzF .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-vbvADCBfv6pIHHzF .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-vbvADCBfv6pIHHzF .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-vbvADCBfv6pIHHzF .marker{fill:#333333;stroke:#333333;}#mermaid-svg-vbvADCBfv6pIHHzF .marker.cross{stroke:#333333;}#mermaid-svg-vbvADCBfv6pIHHzF svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-vbvADCBfv6pIHHzF p{margin:0;}#mermaid-svg-vbvADCBfv6pIHHzF .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-vbvADCBfv6pIHHzF .cluster-label text{fill:#333;}#mermaid-svg-vbvADCBfv6pIHHzF .cluster-label span{color:#333;}#mermaid-svg-vbvADCBfv6pIHHzF .cluster-label span p{background-color:transparent;}#mermaid-svg-vbvADCBfv6pIHHzF .label text,#mermaid-svg-vbvADCBfv6pIHHzF span{fill:#333;color:#333;}#mermaid-svg-vbvADCBfv6pIHHzF .node rect,#mermaid-svg-vbvADCBfv6pIHHzF .node circle,#mermaid-svg-vbvADCBfv6pIHHzF .node ellipse,#mermaid-svg-vbvADCBfv6pIHHzF .node polygon,#mermaid-svg-vbvADCBfv6pIHHzF .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-vbvADCBfv6pIHHzF .rough-node .label text,#mermaid-svg-vbvADCBfv6pIHHzF .node .label text,#mermaid-svg-vbvADCBfv6pIHHzF .image-shape .label,#mermaid-svg-vbvADCBfv6pIHHzF .icon-shape .label{text-anchor:middle;}#mermaid-svg-vbvADCBfv6pIHHzF .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-vbvADCBfv6pIHHzF .rough-node .label,#mermaid-svg-vbvADCBfv6pIHHzF .node .label,#mermaid-svg-vbvADCBfv6pIHHzF .image-shape .label,#mermaid-svg-vbvADCBfv6pIHHzF .icon-shape .label{text-align:center;}#mermaid-svg-vbvADCBfv6pIHHzF .node.clickable{cursor:pointer;}#mermaid-svg-vbvADCBfv6pIHHzF .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-vbvADCBfv6pIHHzF .arrowheadPath{fill:#333333;}#mermaid-svg-vbvADCBfv6pIHHzF .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-vbvADCBfv6pIHHzF .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-vbvADCBfv6pIHHzF .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-vbvADCBfv6pIHHzF .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-vbvADCBfv6pIHHzF .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-vbvADCBfv6pIHHzF .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-vbvADCBfv6pIHHzF .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-vbvADCBfv6pIHHzF .cluster text{fill:#333;}#mermaid-svg-vbvADCBfv6pIHHzF .cluster span{color:#333;}#mermaid-svg-vbvADCBfv6pIHHzF div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-vbvADCBfv6pIHHzF .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-vbvADCBfv6pIHHzF rect.text{fill:none;stroke-width:0;}#mermaid-svg-vbvADCBfv6pIHHzF .icon-shape,#mermaid-svg-vbvADCBfv6pIHHzF .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-vbvADCBfv6pIHHzF .icon-shape p,#mermaid-svg-vbvADCBfv6pIHHzF .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-vbvADCBfv6pIHHzF .icon-shape rect,#mermaid-svg-vbvADCBfv6pIHHzF .image-shape rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-vbvADCBfv6pIHHzF .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-vbvADCBfv6pIHHzF .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-vbvADCBfv6pIHHzF :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}
Decoder Stack (解码器堆叠)
Encoder Stack (编码器堆叠)
传递语义记忆 (K, V)
传递语义记忆 (K, V)
传递语义记忆 (K, V)
传递语义记忆 (K, V)
输入: 我 爱 学 习
Encoder Layer 1
Encoder Layer 2
…
Encoder Layer 6 (老学究的最终理解)
输入: Start I love …
Decoder Layer 1
Decoder Layer 2
…
Decoder Layer 6
Linear + Softmax
输出概率: study
4. 这里的“坑”和“彩蛋”
在继续深入之前,有两个概念你需要先有个印象,防止后面迷路:
并行与串行的分裂:
- Encoder 是完全并行的。它是一眼看完整个句子(我爱学习),这 4 个字同时进入模型处理。
- Decoder 在推理(翻译)时,依然是串行的。它只能先生成 I,再生成 love,再生成 study。因为它不知道后面会写啥。
家族分家(预告): 现在的 AI 届,原始的 Encoder-Decoder 结构其实用得变少了,大家开始分家产:
- BERT 家族:只拿走了左边的 Encoder。因为它不需要说话,只需要“理解”语言(做填空题、阅读理解)。
- GPT 家族:只拿走了右边的 Decoder。因为它不需要理解特定的输入文本,它只管在那儿“瞎编”下一句,一路生成下去。
本章小结
这一章我们不需要搞懂内部计算,只需要记住:
现在,我们要把镜头推进,走进 Encoder 的第一层。但在计算之前,机器面临一个巨大的问题:机器不认识汉字,也不认识英文,它只认识数字。
而且,我们在第一章说过,Transformer 并行处理导致它没有“时间概念”。如果不做特殊处理,机器会认为“读书”和“书读”是一回事。
在前两章我们吹了半天 Transformer 的“并行计算”有多牛,但这其实带来了一个巨大的副作用:它是个不折不扣的“路痴”。
因为它是把所有词一口气吃进去的,所以在它眼里,“我打你”和“你打我”是一模一样的——不就是“我、你、打”这三个词的组合嘛!
为了治好这个 Bug,我们需要给每个词装上身份证(Embedding)和GPS(位置编码)。
第三章:单词的 GPS——Embedding 与位置编码
1. 机器的字典:Embedding(词嵌入)
首先,不管是 Transformer 还是以前的 RNN,机器其实根本不认识“Apple”这个词。在它看来,这只是一串 ASCII 码。
我们需要把文字变成机器能计算的数字。但不能简单地把 Apple 变成 1,Banana 变成 2。因为 1 和 2 在数学上挨得很近,但苹果和香蕉在语义上可能差很远(或者很近)。
我们使用的是 Embedding(词嵌入)。
🎓 生动比喻:单词的“DNA 图谱”
想象一下,我们把字典里的每一个词,都对应到一个长长的数字列表(向量)。这个列表通常有 512 维(或者 768、1024 维)。
每一维数字都代表这个词的一种“潜在特征”。虽然机器不会明说,但我们可以这样脑补:
- 第 1 维代表“是不是名词”
- 第 2 维代表“是不是活物”
- 第 3 维代表“王室程度”
- …
比如:
- King (国王) -> [0.9, 0.9, 0.99, …] (名词,活人,极其王室)
- Queen (女王) -> [0.9, 0.9, 0.99, …] (跟国王很像,只有代表性别的某一维不同)
- Apple (苹果) -> [0.9, 0.1, 0.00, …] (名词,植物,跟王室没半毛钱关系)
这就是 Embedding:把冰冷的单词,变成了有丰富语义内涵的数学向量。
2. 治愈路痴:Positional Encoding(位置编码)
Embedding 搞定后,真正的麻烦来了。
RNN 是按顺序读的,读完第一个才能读第二个,所以它天然知道位置信息。但 Transformer 是并行的(还记得第一章鸡尾酒会的比喻吗?)。
如果我们直接把 Embedding("我"),Embedding("爱"),Embedding("你") 扔进去,模型只知道这三个词出现了,完全不知道谁在谁前面。
为了解决这个问题,聪明的工程师想了一招:给 Embedding 向量“加”点料。
🎓 生动比喻:给座位编号
想象一群人(单词)乱哄哄地挤进一个房间(Transformer)。 为了不乱套,我们在每个人进门时,强行给他的衣服上贴一个号码牌,或者发一个带有位置信息的 GPS 信号。
- 对于第一个词“我”,我们给它加上
P
1
P_1
P1 的位置信号。 - 对于第二个词“爱”,我们给它加上
P
2
P_2
P2 的位置信号。
这样,即使大家混在一起,模型只要看一眼信号,就知道:“哦,虽然你们是一起进来的,但‘我’是排在第一号座位的。”
⚠️ 这里的核心骚操作:是相加(Add),不是拼接(Concat)
初学者很容易觉得,位置信息应该像挂拖车一样跟在词向量后面(拼接)。但 Transformer 居然是直接把位置向量“加”到了词向量上面!
I
n
p
u
t
=
E
m
b
e
d
d
i
n
g
+
P
o
s
i
t
i
o
n
a
l
E
n
c
o
d
i
n
g
Input = Embedding + PositionalEncoding
Input=Embedding+PositionalEncoding
这就像是:
- 词义是红色颜料。
- 位置是蓝色颜料。
- Transformer 实际上把它们混成了紫色颜料输进去。
这难道不会破坏原来的词义吗? 答案是:会有一点点干扰,但没关系。因为词向量的维度很高(512维),而位置编码的数值很独特。在高维空间里,模型能够学会把“词义”和“位置”重新分离开来。
3. 正弦波的魔法:为什么用 Sin/Cos?
Transformer 的位置编码并不是简单的 1, 2, 3, 4 这种整数。因为如果句子太长,数值会变得无限大,把词义完全盖过去。
它使用的是正弦和余弦函数(Sin/Cos)。
#mermaid-svg-TYRwknC3AY4yCjnV{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-TYRwknC3AY4yCjnV .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-TYRwknC3AY4yCjnV .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-TYRwknC3AY4yCjnV .error-icon{fill:#552222;}#mermaid-svg-TYRwknC3AY4yCjnV .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-TYRwknC3AY4yCjnV .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-TYRwknC3AY4yCjnV .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-TYRwknC3AY4yCjnV .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-TYRwknC3AY4yCjnV .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-TYRwknC3AY4yCjnV .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-TYRwknC3AY4yCjnV .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-TYRwknC3AY4yCjnV .marker{fill:#333333;stroke:#333333;}#mermaid-svg-TYRwknC3AY4yCjnV .marker.cross{stroke:#333333;}#mermaid-svg-TYRwknC3AY4yCjnV svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-TYRwknC3AY4yCjnV p{margin:0;}#mermaid-svg-TYRwknC3AY4yCjnV .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-TYRwknC3AY4yCjnV .cluster-label text{fill:#333;}#mermaid-svg-TYRwknC3AY4yCjnV .cluster-label span{color:#333;}#mermaid-svg-TYRwknC3AY4yCjnV .cluster-label span p{background-color:transparent;}#mermaid-svg-TYRwknC3AY4yCjnV .label text,#mermaid-svg-TYRwknC3AY4yCjnV span{fill:#333;color:#333;}#mermaid-svg-TYRwknC3AY4yCjnV .node rect,#mermaid-svg-TYRwknC3AY4yCjnV .node circle,#mermaid-svg-TYRwknC3AY4yCjnV .node ellipse,#mermaid-svg-TYRwknC3AY4yCjnV .node polygon,#mermaid-svg-TYRwknC3AY4yCjnV .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-TYRwknC3AY4yCjnV .rough-node .label text,#mermaid-svg-TYRwknC3AY4yCjnV .node .label text,#mermaid-svg-TYRwknC3AY4yCjnV .image-shape .label,#mermaid-svg-TYRwknC3AY4yCjnV .icon-shape .label{text-anchor:middle;}#mermaid-svg-TYRwknC3AY4yCjnV .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-TYRwknC3AY4yCjnV .rough-node .label,#mermaid-svg-TYRwknC3AY4yCjnV .node .label,#mermaid-svg-TYRwknC3AY4yCjnV .image-shape .label,#mermaid-svg-TYRwknC3AY4yCjnV .icon-shape .label{text-align:center;}#mermaid-svg-TYRwknC3AY4yCjnV .node.clickable{cursor:pointer;}#mermaid-svg-TYRwknC3AY4yCjnV .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-TYRwknC3AY4yCjnV .arrowheadPath{fill:#333333;}#mermaid-svg-TYRwknC3AY4yCjnV .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-TYRwknC3AY4yCjnV .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-TYRwknC3AY4yCjnV .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-TYRwknC3AY4yCjnV .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-TYRwknC3AY4yCjnV .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-TYRwknC3AY4yCjnV .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-TYRwknC3AY4yCjnV .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-TYRwknC3AY4yCjnV .cluster text{fill:#333;}#mermaid-svg-TYRwknC3AY4yCjnV .cluster span{color:#333;}#mermaid-svg-TYRwknC3AY4yCjnV div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-TYRwknC3AY4yCjnV .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-TYRwknC3AY4yCjnV rect.text{fill:none;stroke-width:0;}#mermaid-svg-TYRwknC3AY4yCjnV .icon-shape,#mermaid-svg-TYRwknC3AY4yCjnV .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-TYRwknC3AY4yCjnV .icon-shape p,#mermaid-svg-TYRwknC3AY4yCjnV .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-TYRwknC3AY4yCjnV .icon-shape rect,#mermaid-svg-TYRwknC3AY4yCjnV .image-shape rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-TYRwknC3AY4yCjnV .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-TYRwknC3AY4yCjnV .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-TYRwknC3AY4yCjnV :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}
位置编码的波纹
Sin/Cos
Sin/Cos
Sin/Cos
位置 1
波纹向量 1
位置 2
波纹向量 2
位置 100
波纹向量 100
你可以把它理解为**“多重时钟”**:
- 向量的第 1 维像秒针,走得快(频率高)。
- 向量的第 2 维像分针,走得慢。
- 向量的第 3 维像时针,走得更慢。
每个位置(Time Step),都对应着这些指针的一个唯一组合。 这样,无论句子多长,位置编码的数值永远在 -1 到 1 之间震荡,既稳定又独特。
4. 流程图解
让我们用 Mermaid 把这两个步骤合二为一,看看数据进入 Transformer 内部的第一步到底长啥样。
#mermaid-svg-to7xurLLWY4CfU44{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-to7xurLLWY4CfU44 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-to7xurLLWY4CfU44 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-to7xurLLWY4CfU44 .error-icon{fill:#552222;}#mermaid-svg-to7xurLLWY4CfU44 .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-to7xurLLWY4CfU44 .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-to7xurLLWY4CfU44 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-to7xurLLWY4CfU44 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-to7xurLLWY4CfU44 .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-to7xurLLWY4CfU44 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-to7xurLLWY4CfU44 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-to7xurLLWY4CfU44 .marker{fill:#333333;stroke:#333333;}#mermaid-svg-to7xurLLWY4CfU44 .marker.cross{stroke:#333333;}#mermaid-svg-to7xurLLWY4CfU44 svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-to7xurLLWY4CfU44 p{margin:0;}#mermaid-svg-to7xurLLWY4CfU44 .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-to7xurLLWY4CfU44 .cluster-label text{fill:#333;}#mermaid-svg-to7xurLLWY4CfU44 .cluster-label span{color:#333;}#mermaid-svg-to7xurLLWY4CfU44 .cluster-label span p{background-color:transparent;}#mermaid-svg-to7xurLLWY4CfU44 .label text,#mermaid-svg-to7xurLLWY4CfU44 span{fill:#333;color:#333;}#mermaid-svg-to7xurLLWY4CfU44 .node rect,#mermaid-svg-to7xurLLWY4CfU44 .node circle,#mermaid-svg-to7xurLLWY4CfU44 .node ellipse,#mermaid-svg-to7xurLLWY4CfU44 .node polygon,#mermaid-svg-to7xurLLWY4CfU44 .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-to7xurLLWY4CfU44 .rough-node .label text,#mermaid-svg-to7xurLLWY4CfU44 .node .label text,#mermaid-svg-to7xurLLWY4CfU44 .image-shape .label,#mermaid-svg-to7xurLLWY4CfU44 .icon-shape .label{text-anchor:middle;}#mermaid-svg-to7xurLLWY4CfU44 .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-to7xurLLWY4CfU44 .rough-node .label,#mermaid-svg-to7xurLLWY4CfU44 .node .label,#mermaid-svg-to7xurLLWY4CfU44 .image-shape .label,#mermaid-svg-to7xurLLWY4CfU44 .icon-shape .label{text-align:center;}#mermaid-svg-to7xurLLWY4CfU44 .node.clickable{cursor:pointer;}#mermaid-svg-to7xurLLWY4CfU44 .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-to7xurLLWY4CfU44 .arrowheadPath{fill:#333333;}#mermaid-svg-to7xurLLWY4CfU44 .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-to7xurLLWY4CfU44 .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-to7xurLLWY4CfU44 .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-to7xurLLWY4CfU44 .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-to7xurLLWY4CfU44 .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-to7xurLLWY4CfU44 .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-to7xurLLWY4CfU44 .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-to7xurLLWY4CfU44 .cluster text{fill:#333;}#mermaid-svg-to7xurLLWY4CfU44 .cluster span{color:#333;}#mermaid-svg-to7xurLLWY4CfU44 div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-to7xurLLWY4CfU44 .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-to7xurLLWY4CfU44 rect.text{fill:none;stroke-width:0;}#mermaid-svg-to7xurLLWY4CfU44 .icon-shape,#mermaid-svg-to7xurLLWY4CfU44 .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-to7xurLLWY4CfU44 .icon-shape p,#mermaid-svg-to7xurLLWY4CfU44 .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-to7xurLLWY4CfU44 .icon-shape rect,#mermaid-svg-to7xurLLWY4CfU44 .image-shape rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-to7xurLLWY4CfU44 .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-to7xurLLWY4CfU44 .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-to7xurLLWY4CfU44 :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}
输入处理流程
原始文本: I love AI
分词 (Tokenization)
Token IDs: [24, 56, 99]
Embedding 查表
词向量 (Word Embeddings) [Batch, Seq_Len, 512]
+
位置编码生成 (Positional Encoding) (Sin/Cos Waves)
最终输入向量 (带着位置信息的词向量)
本章小结
现在,数据已经准备好了!它既包含了“是什么意思”,也包含了“在什么位置”。
如果说 Embedding 是给 Transformer 供血的血管,那 Self-Attention(自注意力机制) 就是它的心脏。这也是这篇论文标题《Attention Is All You Need》里那个价值千金的词。
很多教程在这里会甩出一堆
Q
×
K
T
Q \\times K^T
Q×KT 的公式把你劝退。别怕,我们还是用故事来讲。
第四章:灵魂核心——自注意力机制 (Self-Attention)
1. 到底什么是“自注意力”?
我们在第一章说过,RNN 的毛病是“读到后面忘前面”。而 Self-Attention 的核心思想就是:在读每一个词的时候,都把整个句子的其他词再看一遍,看看谁跟自己最亲。
还是那句经典的例子:
“The animal didn’t cross the street because it was too tired.”
当机器读到 “it” 这个词时,它的注意力应该放在哪里?
- 它应该去关注 “street” 吗?不对,马路不会觉得累。
- 它应该去关注 “animal” 吗?对!动物才会觉得累。
Self-Attention 就像一盏聚光灯。当处理 “it” 时,它会把灯光最强烈地打在 “animal” 身上,把 “street” 放在阴影里。这样,“it” 就吸收了 “animal” 的含义。
2. 核心铁三角:Q、K、V 的身世之谜
为了实现这种“找关系”的能力,Transformer 把输入的每一个词向量(Vector),都分裂成了三个分身。
这三个分身是通过分别乘以三个不同的权重矩阵(
W
Q
,
W
K
,
W
V
W^Q, W^K, W^V
WQ,WK,WV)变出来的。它们分别是:
Query (查询向量):这是**“我手中的牌”**。
- 代表当前这个词去“寻找”其他词时的诉求。
- 比如 “it” 的 Query 在喊:“谁是能让我‘觉得累’的名词?”
Key (键向量):这是**“你头上的标签”**。
- 代表这个词被用来“匹配”时的特征。
- 比如 “animal” 的 Key 写着:“我是名词,我是活物”。
Value (值向量):这是**“你的内涵”**。
- 代表这个词真正的语义内容。
- 如果匹配成功,就要把这个 Value 拿走,融合到 Query 身上。
🎓 生动比喻:图书馆检索系统
为了彻底搞懂 Q、K、V,我们可以把这看作一次图书馆查书的过程:
- Query (
Q
Q
Q):是你手里的借书条(上面写着:我要找关于“很多毛的活物”的书)。 - Key (
K
K
K):是书架上每一本书脊上的分类编号(比如:生物类-哺乳动物)。 - Value (
V
V
V):是书里面真正的内容。
过程是这样的:
Q
Q
Q),去和每一本书的分类号 (
K
K
K) 进行比对。
V
V
V) 取出来,读进脑子里。
3. 计算四步走:从相亲到牵手
机器内部是如何通过数学运算来模拟这个过程的呢?其实就是向量点积(Dot Product)。
第一步:计算匹配度 (Score)
拿当前词的
Q
Q
Q,去乘以所有词的
K
K
K。
S
c
o
r
e
=
Q
⋅
K
T
Score = Q \\cdot K^T
Score=Q⋅KT
- 点积越大,代表两个向量越相似,也就是关系越紧密。
- “it” 的
Q
Q
Q 和 “animal” 的K
K
K 点积,得分 0.9(很高)。 - “it” 的
Q
Q
Q 和 “street” 的K
K
K 点积,得分 0.1(很低)。
第二步:归一化与打分 (Softmax)
为了让分数变成概率(加起来等于 1),我们需要过一个 Softmax 函数。 在此之前,为了防止分数太大导致梯度消失,通常会除以一个系数(
d
k
\\sqrt{d_k}
dk
,比如 8)。
- 处理后:“animal” 的权重变成 88%,“street” 的权重变成 2%,其他的词分剩下的 10%。
第三步:加权求和 (Weighted Sum)
这是最后一步,也是最神奇的一步。 用刚才算出来的权重,去乘以所有词的
V
V
V,然后加在一起。
O
u
t
p
u
t
=
0.88
×
V
a
n
i
m
a
l
+
0.02
×
V
s
t
r
e
e
t
+
.
.
.
Output = 0.88 \\times V_{animal} + 0.02 \\times V_{street} + …
Output=0.88×Vanimal+0.02×Vstreet+…
结果: 此时,“it” 这个词经过这一层处理后,它的向量里虽然还保留着 “it” 的影子,但大部分成分已经变成了 “animal” 的特征。它不再是一个单纯的代词,它“吸星大法”吸取了上下文的精华!
4. 流程图解:QKV 的内部工厂
这个过程是所有词同时进行的(矩阵运算)。让我们看下 Meramid 图解:
#mermaid-svg-Ndar7XvFdmue8SMl{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-Ndar7XvFdmue8SMl .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-Ndar7XvFdmue8SMl .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-Ndar7XvFdmue8SMl .error-icon{fill:#552222;}#mermaid-svg-Ndar7XvFdmue8SMl .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-Ndar7XvFdmue8SMl .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-Ndar7XvFdmue8SMl .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-Ndar7XvFdmue8SMl .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-Ndar7XvFdmue8SMl .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-Ndar7XvFdmue8SMl .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-Ndar7XvFdmue8SMl .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-Ndar7XvFdmue8SMl .marker{fill:#333333;stroke:#333333;}#mermaid-svg-Ndar7XvFdmue8SMl .marker.cross{stroke:#333333;}#mermaid-svg-Ndar7XvFdmue8SMl svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-Ndar7XvFdmue8SMl p{margin:0;}#mermaid-svg-Ndar7XvFdmue8SMl .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-Ndar7XvFdmue8SMl .cluster-label text{fill:#333;}#mermaid-svg-Ndar7XvFdmue8SMl .cluster-label span{color:#333;}#mermaid-svg-Ndar7XvFdmue8SMl .cluster-label span p{background-color:transparent;}#mermaid-svg-Ndar7XvFdmue8SMl .label text,#mermaid-svg-Ndar7XvFdmue8SMl span{fill:#333;color:#333;}#mermaid-svg-Ndar7XvFdmue8SMl .node rect,#mermaid-svg-Ndar7XvFdmue8SMl .node circle,#mermaid-svg-Ndar7XvFdmue8SMl .node ellipse,#mermaid-svg-Ndar7XvFdmue8SMl .node polygon,#mermaid-svg-Ndar7XvFdmue8SMl .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-Ndar7XvFdmue8SMl .rough-node .label text,#mermaid-svg-Ndar7XvFdmue8SMl .node .label text,#mermaid-svg-Ndar7XvFdmue8SMl .image-shape .label,#mermaid-svg-Ndar7XvFdmue8SMl .icon-shape .label{text-anchor:middle;}#mermaid-svg-Ndar7XvFdmue8SMl .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-Ndar7XvFdmue8SMl .rough-node .label,#mermaid-svg-Ndar7XvFdmue8SMl .node .label,#mermaid-svg-Ndar7XvFdmue8SMl .image-shape .label,#mermaid-svg-Ndar7XvFdmue8SMl .icon-shape .label{text-align:center;}#mermaid-svg-Ndar7XvFdmue8SMl .node.clickable{cursor:pointer;}#mermaid-svg-Ndar7XvFdmue8SMl .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-Ndar7XvFdmue8SMl .arrowheadPath{fill:#333333;}#mermaid-svg-Ndar7XvFdmue8SMl .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-Ndar7XvFdmue8SMl .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-Ndar7XvFdmue8SMl .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-Ndar7XvFdmue8SMl .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-Ndar7XvFdmue8SMl .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-Ndar7XvFdmue8SMl .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-Ndar7XvFdmue8SMl .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-Ndar7XvFdmue8SMl .cluster text{fill:#333;}#mermaid-svg-Ndar7XvFdmue8SMl .cluster span{color:#333;}#mermaid-svg-Ndar7XvFdmue8SMl div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-Ndar7XvFdmue8SMl .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-Ndar7XvFdmue8SMl rect.text{fill:none;stroke-width:0;}#mermaid-svg-Ndar7XvFdmue8SMl .icon-shape,#mermaid-svg-Ndar7XvFdmue8SMl .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-Ndar7XvFdmue8SMl .icon-shape p,#mermaid-svg-Ndar7XvFdmue8SMl .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-Ndar7XvFdmue8SMl .icon-shape rect,#mermaid-svg-Ndar7XvFdmue8SMl .image-shape rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-Ndar7XvFdmue8SMl .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-Ndar7XvFdmue8SMl .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-Ndar7XvFdmue8SMl :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}
Self-Attention 内部处理机制
分数 (Scores)
注意力权重 (Weights)
输入向量 X (Embedding + Pos)
W_Q 矩阵
Query (Q) 拿着借书条
W_K 矩阵
Key (K) 书分类号
W_V 矩阵
Value (V) 书的内容
点积运算 (MatMul) Score = Q × K
Softmax (归一化为概率 %)
加权求和 (MatMul) Output = % × V
最终输出 Z (吸收了上下文信息的向量)
5. 为什么要除以
d
k
\\sqrt{d_k}
dk?
如果
Q
Q
Q 和
K
K
K 的维度很大,点积的结果会变得非常大。这就好比你在 Softmax 里输入了一个几千的数字,Softmax 就会变得极端——只认最大的那个,其他的全变成 0,导致梯度几乎消失,模型学不动了。除以一个数是为了把数值拉回“舒适区”。
本章小结
Q
Q
Q 查
K
K
K,算出权重,然后加权汇总
V
V
V。
但是!人看文章不能只用一种视角。有的要看语法,有的要看指代,有的要看情绪。 现在的 Attention 只有一组 QKV,这就像只有一只眼睛。
如果 Transformer 只有这一个脑袋,它可能会比较“死板”。为了让它变成真正的六边形战士,Google 的工程师赋予了它“三头六臂”。
第五章:多头注意力 (Multi-Head Attention)——三个臭皮匠,顶个诸葛亮
1. 为什么要搞这么多脑袋?
想象一下,你正在读这句影评:
“The movie was long but good.”
如果你只有一种思维方式(一个 Head),你可能只关注到了 movie 和 long 的关系(描述时长)。 但是,这句话里明显还有另一层更重要的逻辑:尽管 long(通常是贬义),但是 good(褒义),这里有一个转折关系。
单头注意力的缺陷在于:它可能在同一时间,只能专注于一种类型的语义关联。如果它忙着看语法结构,可能就忽略了情感色彩。
Multi-Head Attention(多头注意力) 的核心思想就是: 既然一个脑袋不够用,那我就搞 8 个!
- Head 1:专门负责看语法结构(谁是主语,谁是宾语)。
- Head 2:专门负责看指代关系(it 指的是谁)。
- Head 3:专门负责看时态信息(是过去发生还是将来发生)。
- Head 4:专门负责看情感色彩(是夸还是骂)。
- …
大家各司其职,最后把结果汇总起来,这就构成了一个对句子全方位、多角度的理解。
2. 怎么“砍”成多头?(Split & Concat)
你可能会担心:“搞 8 个头,计算量岂不是变成了原来的 8 倍?我的显卡还要不要了?”
这就是 Transformer 设计精妙的地方。它并没有把计算量翻倍,而是把原来的向量“切”碎了。
假设原本的词向量维度(
d
m
o
d
e
l
d_{model}
dmodel)是 512。 我们要搞 8 个头 (
h
=
8
h=8
h=8)。
Transformer 是这样做的:
d
k
=
512
/
8
=
64
d_k = 512 / 8 = 64
dk=512/8=64)。
Q
,
K
,
V
Q, K, V
Q,K,V 的自注意力计算。
W
Q
,
W
K
,
W
V
W^Q, W^K, W^V
WQ,WK,WV 权重矩阵。这意味着 Head 1 学到的东西,Head 2 根本不知道,互不干扰。
这就好比: 本来是一个大神(512维)在读一本书。 现在变成了 8 个普通人(64维),每个人只读一章。 虽然单人的能力弱了,但大家同时读,最后开会把读后感拼在一起,效率极高且视角丰富。
3. 最后的融合:线性变换 (Linear)
把 8 个头的输出拼起来之后,虽然维度变回了 512,但它们之间还是“生分”的(前面 64 位是 Head 1 的看法,后面 64 位是 Head 2 的看法…)。
所以,最后必须加一个线性变换层(Linear Layer,
W
O
W^O
WO)。
这个层的作用就像是会议主持人或者鸡尾酒调酒师。它把这一条拼接好的长向量混合一下,让不同头的信息进行交互和融合,最终生成一个统一的输出向量。
4. 流程图解:多头工厂
这一部分最适合用图来看。你会发现它像极了工厂里的分流—加工—汇流流水线。
#mermaid-svg-8uJnM5X3JTCyX47j{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-8uJnM5X3JTCyX47j .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-8uJnM5X3JTCyX47j .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-8uJnM5X3JTCyX47j .error-icon{fill:#552222;}#mermaid-svg-8uJnM5X3JTCyX47j .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-8uJnM5X3JTCyX47j .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-8uJnM5X3JTCyX47j .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-8uJnM5X3JTCyX47j .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-8uJnM5X3JTCyX47j .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-8uJnM5X3JTCyX47j .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-8uJnM5X3JTCyX47j .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-8uJnM5X3JTCyX47j .marker{fill:#333333;stroke:#333333;}#mermaid-svg-8uJnM5X3JTCyX47j .marker.cross{stroke:#333333;}#mermaid-svg-8uJnM5X3JTCyX47j svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-8uJnM5X3JTCyX47j p{margin:0;}#mermaid-svg-8uJnM5X3JTCyX47j .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-8uJnM5X3JTCyX47j .cluster-label text{fill:#333;}#mermaid-svg-8uJnM5X3JTCyX47j .cluster-label span{color:#333;}#mermaid-svg-8uJnM5X3JTCyX47j .cluster-label span p{background-color:transparent;}#mermaid-svg-8uJnM5X3JTCyX47j .label text,#mermaid-svg-8uJnM5X3JTCyX47j span{fill:#333;color:#333;}#mermaid-svg-8uJnM5X3JTCyX47j .node rect,#mermaid-svg-8uJnM5X3JTCyX47j .node circle,#mermaid-svg-8uJnM5X3JTCyX47j .node ellipse,#mermaid-svg-8uJnM5X3JTCyX47j .node polygon,#mermaid-svg-8uJnM5X3JTCyX47j .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-8uJnM5X3JTCyX47j .rough-node .label text,#mermaid-svg-8uJnM5X3JTCyX47j .node .label text,#mermaid-svg-8uJnM5X3JTCyX47j .image-shape .label,#mermaid-svg-8uJnM5X3JTCyX47j .icon-shape .label{text-anchor:middle;}#mermaid-svg-8uJnM5X3JTCyX47j .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-8uJnM5X3JTCyX47j .rough-node .label,#mermaid-svg-8uJnM5X3JTCyX47j .node .label,#mermaid-svg-8uJnM5X3JTCyX47j .image-shape .label,#mermaid-svg-8uJnM5X3JTCyX47j .icon-shape .label{text-align:center;}#mermaid-svg-8uJnM5X3JTCyX47j .node.clickable{cursor:pointer;}#mermaid-svg-8uJnM5X3JTCyX47j .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-8uJnM5X3JTCyX47j .arrowheadPath{fill:#333333;}#mermaid-svg-8uJnM5X3JTCyX47j .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-8uJnM5X3JTCyX47j .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-8uJnM5X3JTCyX47j .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-8uJnM5X3JTCyX47j .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-8uJnM5X3JTCyX47j .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-8uJnM5X3JTCyX47j .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-8uJnM5X3JTCyX47j .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-8uJnM5X3JTCyX47j .cluster text{fill:#333;}#mermaid-svg-8uJnM5X3JTCyX47j .cluster span{color:#333;}#mermaid-svg-8uJnM5X3JTCyX47j div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-8uJnM5X3JTCyX47j .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-8uJnM5X3JTCyX47j rect.text{fill:none;stroke-width:0;}#mermaid-svg-8uJnM5X3JTCyX47j .icon-shape,#mermaid-svg-8uJnM5X3JTCyX47j .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-8uJnM5X3JTCyX47j .icon-shape p,#mermaid-svg-8uJnM5X3JTCyX47j .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-8uJnM5X3JTCyX47j .icon-shape rect,#mermaid-svg-8uJnM5X3JTCyX47j .image-shape rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-8uJnM5X3JTCyX47j .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-8uJnM5X3JTCyX47j .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-8uJnM5X3JTCyX47j :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}
Multi-Head Attention 机制
并行处理 (8个平行宇宙)
Q,K,V 计算
Q,K,V 计算
Q,K,V 计算
Head 1 (关注语法) 64维
输入向量 Z (512维)
切分
Head 2 (关注指代) 64维
…
Head 8 (关注情感) 64维
输出 1
输出 2
输出 8
拼接 (Concat) 64 x 8 = 512维
线性变换 (Linear/WO) 信息大融合
最终输出 (Multi-Head Output)
5. 这里的“彩蛋”
虽然我们在图里说是“关注语法”、“关注情感”,但其实这是我们人类的事后诸葛亮。 在训练开始前,机器并不知道 Head 1 应该学什么。 这些功能是 AI 在训练过程中自己学会的。
- 有时候你会发现 Head 3 和 Head 4 学重了,这被称为“多头冗余”,但为了保险起见,冗余一点也没关系。
本章小结
到这里,Attention 部分的核心就讲完了!但是,如果你把现在的模型叠个 100 层,它可能会根本训练不起来,因为数据传着传着就“死”了(梯度消失/爆炸)。
为了让这栋大楼能盖得更高更稳,我们需要引入两个建筑学神器:残差连接 (Residual Connection) 和 层归一化 (Layer Normalization)。
如果把 Transformer 比作盖楼,前几章我们已经造好了最核心的砖块(Attention)。但是,只要稍微有些工程经验的人都知道:楼盖得太高,是会塌的。
在深度学习里,这个“塌”表现为梯度消失(Gradient Vanishing)或者网络退化——越深的网络反而越笨。
为了让 Transformer 能够毫无顾虑地叠上几十层甚至上百层,Google 工程师引入了两根“定海神针”:残差连接(Residual Connection) 和 层归一化(Layer Normalization)。
这一章,我们看看这两个听起来很高大上、实际上却非常朴素的机制。
第六章:连接与归一化——防止“楼倒塌”的工程学
在 Transformer 的每一层(Layer)里,无论是 Attention 还是后面要讲的 FFN,都被包裹在一个固定的结构里:Add & Norm。
1. 残差连接 (Residual Connection/Add):给信息留条退路
还记得我们前几章讲的 Multi-Head Attention 吗?虽然它很厉害,但万一这一层“脑抽”了,把原本好的信息给算坏了怎么办?
残差连接(源自 ResNet)的核心思想就是:不要只相信你的运算结果,还要保留原始的输入。
O
u
t
p
u
t
=
L
a
y
e
r
(
x
)
+
x
Output = Layer(x) + x
Output=Layer(x)+x
🎓 生动比喻:抄作业的艺术
想象你在做数学题(这一层网络)。
-
x
x
x:是你上一次考试的成绩(或者参考答案)。 -
L
a
y
e
r
(
x
)
Layer(x)
Layer(x):是你现在的计算过程。
残差连接的意思是:你可以去计算新的结果,但最后交卷的时候,要把你算出来的东西加上原来的
x
x
x。
这样设计有两个巨大的好处:
L
a
y
e
r
(
x
)
Layer(x)
Layer(x) 接近 0 或乱码),只要加上
x
x
x,至少结果不会比原来更差。这相当于给信息开了一条VIP 直通车,让它能无损通过。
2. 层归一化 (Layer Normalization/Norm):让大家都在起跑线上
神经网络最怕“大起大落”。 如果第一层的输出是 0.5,第二层变成了 500,第三层变成了 50000……这数值一爆炸,后面的数学公式就没法算了(激活函数会饱和)。
我们需要把每一层的输出,都强行拉回到一个标准的范围(比如均值为 0,方差为 1)。
在图像处理(CV)里,大家常用 Batch Norm(按批次归一化)。但在 NLP 里,因为句子长短不一,Batch Norm 很难用。所以 Transformer 用的是 Layer Norm。
🎓 生动比喻:标准化考试分数
想象班里有学霸和学渣。
- 这次考试太难,大家平均分只有 30 分。
- 下次考试太简单,大家平均分 90 分。
如果不处理,这两次分数的含义完全不同。Layer Norm 做的事情就是: 不管卷子难易,我把你这一行的所有分数进行“缩放”。
- 把平均分强行拉回 0。
- 把分散程度强行拉回 1。
这样,无论数据在里面怎么折腾,下一层网络接收到的,永远是分布稳定、清爽干净的数据。
3. Add & Norm 的组合拳
在 Transformer 的论文图里,你会看到每个模块周围都有一圈线。这就是 Add & Norm 的工作流程。
4. 流程图解:VIP 通道与安检门
让我们用 Mermaid 看看这个结构是如何包裹 Attention 的。
#mermaid-svg-v2LbDUFgISpGP2mm{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-v2LbDUFgISpGP2mm .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-v2LbDUFgISpGP2mm .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-v2LbDUFgISpGP2mm .error-icon{fill:#552222;}#mermaid-svg-v2LbDUFgISpGP2mm .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-v2LbDUFgISpGP2mm .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-v2LbDUFgISpGP2mm .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-v2LbDUFgISpGP2mm .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-v2LbDUFgISpGP2mm .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-v2LbDUFgISpGP2mm .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-v2LbDUFgISpGP2mm .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-v2LbDUFgISpGP2mm .marker{fill:#333333;stroke:#333333;}#mermaid-svg-v2LbDUFgISpGP2mm .marker.cross{stroke:#333333;}#mermaid-svg-v2LbDUFgISpGP2mm svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-v2LbDUFgISpGP2mm p{margin:0;}#mermaid-svg-v2LbDUFgISpGP2mm .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-v2LbDUFgISpGP2mm .cluster-label text{fill:#333;}#mermaid-svg-v2LbDUFgISpGP2mm .cluster-label span{color:#333;}#mermaid-svg-v2LbDUFgISpGP2mm .cluster-label span p{background-color:transparent;}#mermaid-svg-v2LbDUFgISpGP2mm .label text,#mermaid-svg-v2LbDUFgISpGP2mm span{fill:#333;color:#333;}#mermaid-svg-v2LbDUFgISpGP2mm .node rect,#mermaid-svg-v2LbDUFgISpGP2mm .node circle,#mermaid-svg-v2LbDUFgISpGP2mm .node ellipse,#mermaid-svg-v2LbDUFgISpGP2mm .node polygon,#mermaid-svg-v2LbDUFgISpGP2mm .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-v2LbDUFgISpGP2mm .rough-node .label text,#mermaid-svg-v2LbDUFgISpGP2mm .node .label text,#mermaid-svg-v2LbDUFgISpGP2mm .image-shape .label,#mermaid-svg-v2LbDUFgISpGP2mm .icon-shape .label{text-anchor:middle;}#mermaid-svg-v2LbDUFgISpGP2mm .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-v2LbDUFgISpGP2mm .rough-node .label,#mermaid-svg-v2LbDUFgISpGP2mm .node .label,#mermaid-svg-v2LbDUFgISpGP2mm .image-shape .label,#mermaid-svg-v2LbDUFgISpGP2mm .icon-shape .label{text-align:center;}#mermaid-svg-v2LbDUFgISpGP2mm .node.clickable{cursor:pointer;}#mermaid-svg-v2LbDUFgISpGP2mm .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-v2LbDUFgISpGP2mm .arrowheadPath{fill:#333333;}#mermaid-svg-v2LbDUFgISpGP2mm .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-v2LbDUFgISpGP2mm .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-v2LbDUFgISpGP2mm .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-v2LbDUFgISpGP2mm .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-v2LbDUFgISpGP2mm .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-v2LbDUFgISpGP2mm .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-v2LbDUFgISpGP2mm .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-v2LbDUFgISpGP2mm .cluster text{fill:#333;}#mermaid-svg-v2LbDUFgISpGP2mm .cluster span{color:#333;}#mermaid-svg-v2LbDUFgISpGP2mm div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-v2LbDUFgISpGP2mm .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-v2LbDUFgISpGP2mm rect.text{fill:none;stroke-width:0;}#mermaid-svg-v2LbDUFgISpGP2mm .icon-shape,#mermaid-svg-v2LbDUFgISpGP2mm .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-v2LbDUFgISpGP2mm .icon-shape p,#mermaid-svg-v2LbDUFgISpGP2mm .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-v2LbDUFgISpGP2mm .icon-shape rect,#mermaid-svg-v2LbDUFgISpGP2mm .image-shape rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-v2LbDUFgISpGP2mm .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-v2LbDUFgISpGP2mm .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-v2LbDUFgISpGP2mm :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}
Add & Norm 模块详解
努力干活区
去计算 F(x)
VIP 直通车 (原样保留 x)
计算结果
Multi-Head Attention (或者 FFN)
输入向量 x
分流点
+
Layer Norm (归一化处理)
输出 = Norm(x + F(x))
图解说明:注意那条虚线,它就是残差连接。它绕过了复杂的 Attention 计算,直接连到了加号上。这就是深层网络不退化的秘密武器。
本章小结
现在,我们的输入经过了 Attention(提取特征),又经过了 Add & Norm(稳固结构)。
接下来,数据将进入 Encoder 这一层的最后一个组件——前馈神经网络 (Feed-Forward Networks)。 如果说 Attention 是“观察”,那 FFN 就是“思考”和“消化”。
这一章我们来讲讲 Transformer 里最容易被忽视,但参数量其实最大的部分。
在前面的章节里,Attention 就像是一个社交达人,它忙着在不同的单词之间牵线搭桥,搞清楚“谁和谁是亲戚”。
但光有社交是不够的。收集了一堆信息之后,每个单词都需要回到自己的工位上,冷静下来,把这些信息消化、吸收、内化成自己的东西。
这就是 前馈神经网络 (Feed-Forward Networks, FFN) 的工作。
第七章:前馈神经网络 (Feed-Forward Networks)——记忆的精炼
1. 社交后的独处:Position-wise
首先,我们要纠正一个概念。虽然它叫“神经网络”,但在 Transformer 的这一层里,它其实是非常孤僻的。
- Attention 层:是全局的。它看遍了整个句子,把别人的信息拿过来。
- FFN 层:是独立的(Position-wise)。它单独处理每一个词向量,不看周围的人。
比喻时刻:
- Attention 是开会讨论。大家交换意见,我听听你的想法,你听听我的想法。
- FFN 是会后总结。每个人回到自己的脑子里(或者笔记本上),单独整理刚才听到的内容,提炼出重点。
注意:虽然大家是各回各家单独处理,但大家用的“处理逻辑”(权重矩阵
W
W
W)是一模一样的。这就像全班同学都用同一套模版写总结。
2. 三明治结构:宽进窄出
FFN 的内部结构非常简单,就像一个三明治,或者说是一个膨胀—收缩的过程。
它由两个线性变换(Linear)夹着一个非线性激活函数(ReLU)组成。
第一层 Linear(膨胀): 把输入的维度(比如 512)强行变大(通常变大 4 倍,变成 2048)。
- 为什么要变大? 就像把一个折叠的纸团展开。在低维空间挤在一起分不清的特征,投射到高维空间后,更容易把它们分离开来。
激活函数(ReLU): 这是注入“灵魂”的一步。如果没有它,两层 Linear 叠在一起其实还是等于一层 Linear。ReLU 负责把那些负能量(负数)砍掉,只保留正能量。
- 公式:
R
e
L
U
(
x
)
=
max
(
0
,
x
)
ReLU(x) = \\max(0, x)
ReLU(x)=max(0,x)
第二层 Linear(收缩): 把 2048 维的向量再压缩回 512 维。
- 为什么要变回来? 为了和下一层网络对接(还记得残差连接吗?维度必须一致才能相加)。
🎓 生动比喻:做面团
- 输入:一团刚揉好的面(包含了 Attention 收集的信息)。
- 第一步(变宽):把面团用力擀开,铺满整个桌子。这样你能看清面粉里的每一个细节。
- 第二步(ReLU):在面饼上撒点料,或者切掉边缘不整齐的部分。
- 第三步(变窄):把面饼重新揉回一个小面团。
此时,这个面团虽然外观没变(还是 512 维),但内部的筋道(特征)已经完全不同了。
3. 数学公式(看一眼就行)
F
F
N
(
x
)
=
max
(
0
,
x
W
1
+
b
1
)
W
2
+
b
2
FFN(x) = \\max(0, xW_1 + b_1)W_2 + b_2
FFN(x)=max(0,xW1+b1)W2+b2
-
x
x
x:输入(512维) -
W
1
W_1
W1:把 512 变成 2048 -
W
2
W_2
W2:把 2048 变成 512
4. 流程图解:数据的“呼吸”运动
让我们看看数据在这个环节是如何“吸气膨胀”再“呼气收缩”的。
#mermaid-svg-OncFgLMfEeOkAQz1{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-OncFgLMfEeOkAQz1 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-OncFgLMfEeOkAQz1 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-OncFgLMfEeOkAQz1 .error-icon{fill:#552222;}#mermaid-svg-OncFgLMfEeOkAQz1 .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-OncFgLMfEeOkAQz1 .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-OncFgLMfEeOkAQz1 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-OncFgLMfEeOkAQz1 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-OncFgLMfEeOkAQz1 .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-OncFgLMfEeOkAQz1 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-OncFgLMfEeOkAQz1 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-OncFgLMfEeOkAQz1 .marker{fill:#333333;stroke:#333333;}#mermaid-svg-OncFgLMfEeOkAQz1 .marker.cross{stroke:#333333;}#mermaid-svg-OncFgLMfEeOkAQz1 svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-OncFgLMfEeOkAQz1 p{margin:0;}#mermaid-svg-OncFgLMfEeOkAQz1 .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-OncFgLMfEeOkAQz1 .cluster-label text{fill:#333;}#mermaid-svg-OncFgLMfEeOkAQz1 .cluster-label span{color:#333;}#mermaid-svg-OncFgLMfEeOkAQz1 .cluster-label span p{background-color:transparent;}#mermaid-svg-OncFgLMfEeOkAQz1 .label text,#mermaid-svg-OncFgLMfEeOkAQz1 span{fill:#333;color:#333;}#mermaid-svg-OncFgLMfEeOkAQz1 .node rect,#mermaid-svg-OncFgLMfEeOkAQz1 .node circle,#mermaid-svg-OncFgLMfEeOkAQz1 .node ellipse,#mermaid-svg-OncFgLMfEeOkAQz1 .node polygon,#mermaid-svg-OncFgLMfEeOkAQz1 .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-OncFgLMfEeOkAQz1 .rough-node .label text,#mermaid-svg-OncFgLMfEeOkAQz1 .node .label text,#mermaid-svg-OncFgLMfEeOkAQz1 .image-shape .label,#mermaid-svg-OncFgLMfEeOkAQz1 .icon-shape .label{text-anchor:middle;}#mermaid-svg-OncFgLMfEeOkAQz1 .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-OncFgLMfEeOkAQz1 .rough-node .label,#mermaid-svg-OncFgLMfEeOkAQz1 .node .label,#mermaid-svg-OncFgLMfEeOkAQz1 .image-shape .label,#mermaid-svg-OncFgLMfEeOkAQz1 .icon-shape .label{text-align:center;}#mermaid-svg-OncFgLMfEeOkAQz1 .node.clickable{cursor:pointer;}#mermaid-svg-OncFgLMfEeOkAQz1 .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-OncFgLMfEeOkAQz1 .arrowheadPath{fill:#333333;}#mermaid-svg-OncFgLMfEeOkAQz1 .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-OncFgLMfEeOkAQz1 .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-OncFgLMfEeOkAQz1 .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-OncFgLMfEeOkAQz1 .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-OncFgLMfEeOkAQz1 .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-OncFgLMfEeOkAQz1 .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-OncFgLMfEeOkAQz1 .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-OncFgLMfEeOkAQz1 .cluster text{fill:#333;}#mermaid-svg-OncFgLMfEeOkAQz1 .cluster span{color:#333;}#mermaid-svg-OncFgLMfEeOkAQz1 div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-OncFgLMfEeOkAQz1 .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-OncFgLMfEeOkAQz1 rect.text{fill:none;stroke-width:0;}#mermaid-svg-OncFgLMfEeOkAQz1 .icon-shape,#mermaid-svg-OncFgLMfEeOkAQz1 .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-OncFgLMfEeOkAQz1 .icon-shape p,#mermaid-svg-OncFgLMfEeOkAQz1 .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-OncFgLMfEeOkAQz1 .icon-shape rect,#mermaid-svg-OncFgLMfEeOkAQz1 .image-shape rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-OncFgLMfEeOkAQz1 .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-OncFgLMfEeOkAQz1 .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-OncFgLMfEeOkAQz1 :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}
FFN 内部运作机理
特征展开
特征提炼完成
输入向量 x (维度: 512)
Linear Layer 1 (升维: 512 -> 2048)
中间层向量 (维度: 2048)
ReLU 激活函数 (过滤/非线性变换)
激活后的向量 (维度: 2048)
Linear Layer 2 (降维: 2048 -> 512)
输出向量 (维度: 512)
5. 一个有趣的发现
你可能听说过 GPT 的参数量很大(比如 1750 亿参数)。其实,这其中有 2/3 的参数都集中在 FFN 里!
- Attention 的参数只占很少一部分(
W
Q
,
W
K
,
W
V
W^Q, W^K, W^V
WQ,WK,WV 都不大)。 - FFN 的那个“中间层”(2048 甚至更大)消耗了大量的矩阵空间。
有研究认为,Attention 负责逻辑和关系,而 FFN 真的就像是“大脑的记忆区”,里面存储了大量的具体知识(比如“法国的首都是巴黎”这种事实,可能就存在 FFN 的权重里)。
本章小结
至此,Encoder(编码器)的所有秘密都被我们解开了!
Input -> Embedding -> Pos -> [ Attention -> Add&Norm -> FFN -> Add&Norm ] x N -> Output
现在,我们要跨过那道界线,进入右边的 Decoder(解码器)。 虽然 Decoder 看起来和 Encoder 很像,但它有一个非常“心机”的改动——它在考试时不能偷看答案。
在 Encoder(左边的塔)里,我们要理解一句话,当然是一眼看完全文最好(上帝视角)。 但在 Decoder(右边的塔)里,任务变了。Decoder 的任务是生成。
而在生成的时候,最忌讳的就是——剧透。
第八章:解码器的独角戏——Masked Multi-Head Attention
1. 为什么 Decoder 不能有“上帝视角”?
想象你在参加英语考试,题目是中译英:
中文:我爱学习 答案:I love study
在训练的时候,我们是把正确答案 I love study 喂给 Decoder 的(这叫 Teacher Forcing)。
但是,如果 Decoder 在预测 I 的时候,已经偷看到了后面的 love 和 study,那它还学个屁啊?它直接照抄不就行了? 这就好比老师让你填空,结果把答案写在了横线后面,你根本不用动脑子,直接抄就行。
到了真正考试(推理/应用)的时候,是没有人给你看后面的词的。如果训练时习惯了作弊,考试时绝对抓瞎。
所以,我们需要给 Decoder 戴上一副特制的眼镜: 当它读到第
t
t
t 个词的时候,强行让它看不见
t
t
t 之后的词。
这就是 Mask (掩码)。
2. Mask 的魔法:下三角矩阵
具体怎么做呢?我们回想一下 Attention 的计算公式:
S
o
f
t
m
a
x
(
Q
⋅
K
T
)
Softmax(Q \\cdot K^T)
Softmax(Q⋅KT)
Q
⋅
K
T
Q \\cdot K^T
Q⋅KT 算出来的是一个
N
×
N
N \\times N
N×N 的方阵,代表每个词对其他词的关注度。
为了实施“防作弊”策略,我们在把这个矩阵扔进 Softmax 之前,要做个**“大手术”**:
我们把矩阵的右上角全部涂黑(或者是贴上胶带)。 在数学上,就是把右上角的位置全部赋值为 负无穷大 (
−
∞
-\\infty
−∞)。
🎓 生动比喻:阶梯教室的挡板
想象 Decoder 是一个阶梯教室:
- 坐在第 1 排的人(第 1 个词),只能看见他自己。
- 坐在第 2 排的人(第 2 个词),能看见第 1 排和自己。
- 坐在第 3 排的人,能看见 1、2 和自己。
- …
- 任何人都绝对看不见坐在他后面的人!
这样,I 只能关注 I;love 只能关注 I 和 love。未来的词 study 对它们来说就是一片黑暗。
❌ 为什么是负无穷大?
因为 Softmax 函数会将输入转化为概率。
e
−
∞
≈
0
e^{-\\infty} \\approx 0
e−∞≈0。 这样一来,所有右上角的权重在经过 Softmax 后都会变成 0。这就在数学上彻底切断了“偷看未来”的可能性。
3. 图解:被遮挡的视线
看这个图之前,请记住:下三角是光明的,上三角是黑暗的。
#mermaid-svg-AfOj2YVTeoMhLdG2{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-AfOj2YVTeoMhLdG2 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-AfOj2YVTeoMhLdG2 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-AfOj2YVTeoMhLdG2 .error-icon{fill:#552222;}#mermaid-svg-AfOj2YVTeoMhLdG2 .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-AfOj2YVTeoMhLdG2 .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-AfOj2YVTeoMhLdG2 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-AfOj2YVTeoMhLdG2 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-AfOj2YVTeoMhLdG2 .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-AfOj2YVTeoMhLdG2 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-AfOj2YVTeoMhLdG2 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-AfOj2YVTeoMhLdG2 .marker{fill:#333333;stroke:#333333;}#mermaid-svg-AfOj2YVTeoMhLdG2 .marker.cross{stroke:#333333;}#mermaid-svg-AfOj2YVTeoMhLdG2 svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-AfOj2YVTeoMhLdG2 p{margin:0;}#mermaid-svg-AfOj2YVTeoMhLdG2 .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-AfOj2YVTeoMhLdG2 .cluster-label text{fill:#333;}#mermaid-svg-AfOj2YVTeoMhLdG2 .cluster-label span{color:#333;}#mermaid-svg-AfOj2YVTeoMhLdG2 .cluster-label span p{background-color:transparent;}#mermaid-svg-AfOj2YVTeoMhLdG2 .label text,#mermaid-svg-AfOj2YVTeoMhLdG2 span{fill:#333;color:#333;}#mermaid-svg-AfOj2YVTeoMhLdG2 .node rect,#mermaid-svg-AfOj2YVTeoMhLdG2 .node circle,#mermaid-svg-AfOj2YVTeoMhLdG2 .node ellipse,#mermaid-svg-AfOj2YVTeoMhLdG2 .node polygon,#mermaid-svg-AfOj2YVTeoMhLdG2 .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-AfOj2YVTeoMhLdG2 .rough-node .label text,#mermaid-svg-AfOj2YVTeoMhLdG2 .node .label text,#mermaid-svg-AfOj2YVTeoMhLdG2 .image-shape .label,#mermaid-svg-AfOj2YVTeoMhLdG2 .icon-shape .label{text-anchor:middle;}#mermaid-svg-AfOj2YVTeoMhLdG2 .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-AfOj2YVTeoMhLdG2 .rough-node .label,#mermaid-svg-AfOj2YVTeoMhLdG2 .node .label,#mermaid-svg-AfOj2YVTeoMhLdG2 .image-shape .label,#mermaid-svg-AfOj2YVTeoMhLdG2 .icon-shape .label{text-align:center;}#mermaid-svg-AfOj2YVTeoMhLdG2 .node.clickable{cursor:pointer;}#mermaid-svg-AfOj2YVTeoMhLdG2 .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-AfOj2YVTeoMhLdG2 .arrowheadPath{fill:#333333;}#mermaid-svg-AfOj2YVTeoMhLdG2 .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-AfOj2YVTeoMhLdG2 .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-AfOj2YVTeoMhLdG2 .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-AfOj2YVTeoMhLdG2 .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-AfOj2YVTeoMhLdG2 .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-AfOj2YVTeoMhLdG2 .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-AfOj2YVTeoMhLdG2 .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-AfOj2YVTeoMhLdG2 .cluster text{fill:#333;}#mermaid-svg-AfOj2YVTeoMhLdG2 .cluster span{color:#333;}#mermaid-svg-AfOj2YVTeoMhLdG2 div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-AfOj2YVTeoMhLdG2 .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-AfOj2YVTeoMhLdG2 rect.text{fill:none;stroke-width:0;}#mermaid-svg-AfOj2YVTeoMhLdG2 .icon-shape,#mermaid-svg-AfOj2YVTeoMhLdG2 .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-AfOj2YVTeoMhLdG2 .icon-shape p,#mermaid-svg-AfOj2YVTeoMhLdG2 .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-AfOj2YVTeoMhLdG2 .icon-shape rect,#mermaid-svg-AfOj2YVTeoMhLdG2 .image-shape rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-AfOj2YVTeoMhLdG2 .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-AfOj2YVTeoMhLdG2 .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-AfOj2YVTeoMhLdG2 :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}
Masked Attention 矩阵可视化
√ 看得见
X 被挡住 (-inf)
X 被挡住 (-inf)
√ 看得见
√ 看得见
X 被挡住 (-inf)
√ 看得见
√ 看得见
√ 看得见
Word 1 (I)
Col 1 (I)
Col 2 (love)
Col 3 (study)
Word 2 (love)
Word 3 (study)
4. Decoder 的第二层 Attention:跨界之恋 (Cross Attention)
Decoder 比 Encoder 多了一个组件。 在搞完上面那个“防作弊 Self-Attention”之后,Decoder 还需要做一件最重要的事:看 Encoder 的脸色。
这一层叫 Encoder-Decoder Attention(或者叫 Cross Attention)。
这里的
Q
,
K
,
V
Q, K, V
Q,K,V 来源发生了变化,这是全篇唯一的**“混血”**环节:
- Query (
Q
Q
Q):来自 Decoder 自己(刚算完的那个带着 Mask 的输出)。- 潜台词:“我想写下一个字了,请问老学究,根据我现在写的内容,原文里哪里最重要?”
- Key (
K
K
K) & Value (V
V
V):来自 Encoder 的输出(老学究画的那张思维导图)。- 潜台词:“原文的信息都在这儿了,你自己查吧。”
🎓 生动比喻:作家查资料
5. Decoder 完整结构图
Decoder 的每一层其实是 3 个子层 组成的(比 Encoder 多一层)。
#mermaid-svg-Q8lmVcdngY3GLS2F{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-Q8lmVcdngY3GLS2F .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-Q8lmVcdngY3GLS2F .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-Q8lmVcdngY3GLS2F .error-icon{fill:#552222;}#mermaid-svg-Q8lmVcdngY3GLS2F .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-Q8lmVcdngY3GLS2F .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-Q8lmVcdngY3GLS2F .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-Q8lmVcdngY3GLS2F .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-Q8lmVcdngY3GLS2F .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-Q8lmVcdngY3GLS2F .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-Q8lmVcdngY3GLS2F .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-Q8lmVcdngY3GLS2F .marker{fill:#333333;stroke:#333333;}#mermaid-svg-Q8lmVcdngY3GLS2F .marker.cross{stroke:#333333;}#mermaid-svg-Q8lmVcdngY3GLS2F svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-Q8lmVcdngY3GLS2F p{margin:0;}#mermaid-svg-Q8lmVcdngY3GLS2F .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-Q8lmVcdngY3GLS2F .cluster-label text{fill:#333;}#mermaid-svg-Q8lmVcdngY3GLS2F .cluster-label span{color:#333;}#mermaid-svg-Q8lmVcdngY3GLS2F .cluster-label span p{background-color:transparent;}#mermaid-svg-Q8lmVcdngY3GLS2F .label text,#mermaid-svg-Q8lmVcdngY3GLS2F span{fill:#333;color:#333;}#mermaid-svg-Q8lmVcdngY3GLS2F .node rect,#mermaid-svg-Q8lmVcdngY3GLS2F .node circle,#mermaid-svg-Q8lmVcdngY3GLS2F .node ellipse,#mermaid-svg-Q8lmVcdngY3GLS2F .node polygon,#mermaid-svg-Q8lmVcdngY3GLS2F .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-Q8lmVcdngY3GLS2F .rough-node .label text,#mermaid-svg-Q8lmVcdngY3GLS2F .node .label text,#mermaid-svg-Q8lmVcdngY3GLS2F .image-shape .label,#mermaid-svg-Q8lmVcdngY3GLS2F .icon-shape .label{text-anchor:middle;}#mermaid-svg-Q8lmVcdngY3GLS2F .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-Q8lmVcdngY3GLS2F .rough-node .label,#mermaid-svg-Q8lmVcdngY3GLS2F .node .label,#mermaid-svg-Q8lmVcdngY3GLS2F .image-shape .label,#mermaid-svg-Q8lmVcdngY3GLS2F .icon-shape .label{text-align:center;}#mermaid-svg-Q8lmVcdngY3GLS2F .node.clickable{cursor:pointer;}#mermaid-svg-Q8lmVcdngY3GLS2F .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-Q8lmVcdngY3GLS2F .arrowheadPath{fill:#333333;}#mermaid-svg-Q8lmVcdngY3GLS2F .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-Q8lmVcdngY3GLS2F .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-Q8lmVcdngY3GLS2F .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-Q8lmVcdngY3GLS2F .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-Q8lmVcdngY3GLS2F .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-Q8lmVcdngY3GLS2F .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-Q8lmVcdngY3GLS2F .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-Q8lmVcdngY3GLS2F .cluster text{fill:#333;}#mermaid-svg-Q8lmVcdngY3GLS2F .cluster span{color:#333;}#mermaid-svg-Q8lmVcdngY3GLS2F div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-Q8lmVcdngY3GLS2F .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-Q8lmVcdngY3GLS2F rect.text{fill:none;stroke-width:0;}#mermaid-svg-Q8lmVcdngY3GLS2F .icon-shape,#mermaid-svg-Q8lmVcdngY3GLS2F .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-Q8lmVcdngY3GLS2F .icon-shape p,#mermaid-svg-Q8lmVcdngY3GLS2F .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-Q8lmVcdngY3GLS2F .icon-shape rect,#mermaid-svg-Q8lmVcdngY3GLS2F .image-shape rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-Q8lmVcdngY3GLS2F .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-Q8lmVcdngY3GLS2F .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-Q8lmVcdngY3GLS2F :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}
Decoder Layer 内部构造
提供 Q
提供 K, V
Decoder 输入 (Shifted Output)
1. Masked Self-Attention (只能看前面,不能看后面)
Add & Norm
2. Encoder-Decoder Attention (Q来自下方, K/V来自Encoder)
Encoder 的输出 (K, V)
Add & Norm
3. Feed-Forward Network (消化思考)
Add & Norm
输出到下一层
本章小结
Q
Q
Q 去查 Encoder 的
K
K
K 和
V
V
V。
现在,Decoder 经过层层堆叠,终于输出了一个向量。 但这个向量只是一串数字,怎么把它变回我们人类能看懂的单词(比如 study)呢?
第九章:终章——输出与未来
1. 最后一公里:Linear & Softmax
在 Decoder 的最顶层,输出的依然是一个 512 维(或 1024 维)的向量。 为了把它变成字,我们需要经过最后两个关卡。
第一关:Linear Layer(巨大的单词投影仪)
机器的词汇表(Vocabulary)通常很大,比如有 30,000 个单词。 Linear 层就是一个超级巨大的全连接网络。它的作用是把那个 512 维 的向量,瞬间投影放大到 30,000 维。
- 逻辑:这个 30,000 维的向量里,每一个维度都对应字典里的一个词。
- 结果:我们会得到 30,000 个数值(Logits)。数值越大,代表机器觉得下个词是这个词的可能性越高。
第二关:Softmax(概率裁判)
这 30,000 个数值有正有负,甚至还有无穷大,没法直接看。 Softmax 把它们转换成概率。
- 所有概率加起来等于 1。
- 比如:
- apple: 0.001%
- book: 0.002%
- study: 95%
- …
最终,我们选概率最大的那个词(study),作为当前的输出。
2. 流程图解:从数字到单词
这是 Transformer 生产线上的最后一道工序:
#mermaid-svg-a58D8EoJlrftNuXd{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-a58D8EoJlrftNuXd .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-a58D8EoJlrftNuXd .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-a58D8EoJlrftNuXd .error-icon{fill:#552222;}#mermaid-svg-a58D8EoJlrftNuXd .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-a58D8EoJlrftNuXd .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-a58D8EoJlrftNuXd .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-a58D8EoJlrftNuXd .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-a58D8EoJlrftNuXd .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-a58D8EoJlrftNuXd .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-a58D8EoJlrftNuXd .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-a58D8EoJlrftNuXd .marker{fill:#333333;stroke:#333333;}#mermaid-svg-a58D8EoJlrftNuXd .marker.cross{stroke:#333333;}#mermaid-svg-a58D8EoJlrftNuXd svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-a58D8EoJlrftNuXd p{margin:0;}#mermaid-svg-a58D8EoJlrftNuXd .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-a58D8EoJlrftNuXd .cluster-label text{fill:#333;}#mermaid-svg-a58D8EoJlrftNuXd .cluster-label span{color:#333;}#mermaid-svg-a58D8EoJlrftNuXd .cluster-label span p{background-color:transparent;}#mermaid-svg-a58D8EoJlrftNuXd .label text,#mermaid-svg-a58D8EoJlrftNuXd span{fill:#333;color:#333;}#mermaid-svg-a58D8EoJlrftNuXd .node rect,#mermaid-svg-a58D8EoJlrftNuXd .node circle,#mermaid-svg-a58D8EoJlrftNuXd .node ellipse,#mermaid-svg-a58D8EoJlrftNuXd .node polygon,#mermaid-svg-a58D8EoJlrftNuXd .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-a58D8EoJlrftNuXd .rough-node .label text,#mermaid-svg-a58D8EoJlrftNuXd .node .label text,#mermaid-svg-a58D8EoJlrftNuXd .image-shape .label,#mermaid-svg-a58D8EoJlrftNuXd .icon-shape .label{text-anchor:middle;}#mermaid-svg-a58D8EoJlrftNuXd .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-a58D8EoJlrftNuXd .rough-node .label,#mermaid-svg-a58D8EoJlrftNuXd .node .label,#mermaid-svg-a58D8EoJlrftNuXd .image-shape .label,#mermaid-svg-a58D8EoJlrftNuXd .icon-shape .label{text-align:center;}#mermaid-svg-a58D8EoJlrftNuXd .node.clickable{cursor:pointer;}#mermaid-svg-a58D8EoJlrftNuXd .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-a58D8EoJlrftNuXd .arrowheadPath{fill:#333333;}#mermaid-svg-a58D8EoJlrftNuXd .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-a58D8EoJlrftNuXd .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-a58D8EoJlrftNuXd .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-a58D8EoJlrftNuXd .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-a58D8EoJlrftNuXd .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-a58D8EoJlrftNuXd .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-a58D8EoJlrftNuXd .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-a58D8EoJlrftNuXd .cluster text{fill:#333;}#mermaid-svg-a58D8EoJlrftNuXd .cluster span{color:#333;}#mermaid-svg-a58D8EoJlrftNuXd div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-a58D8EoJlrftNuXd .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-a58D8EoJlrftNuXd rect.text{fill:none;stroke-width:0;}#mermaid-svg-a58D8EoJlrftNuXd .icon-shape,#mermaid-svg-a58D8EoJlrftNuXd .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-a58D8EoJlrftNuXd .icon-shape p,#mermaid-svg-a58D8EoJlrftNuXd .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-a58D8EoJlrftNuXd .icon-shape rect,#mermaid-svg-a58D8EoJlrftNuXd .image-shape rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-a58D8EoJlrftNuXd .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-a58D8EoJlrftNuXd .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-a58D8EoJlrftNuXd :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}
Output Generation
Decoder 最终输出向量 (512维)
Linear Layer (全连接层: 512 -> 30,000)
Logits (30,000 个维度的打分)
Softmax (归一化为概率)
概率分布 (Study: 0.9, Love: 0.05, …)
Argmax 选最大的
最终单词: 'study'
3. 后日谈:Transformer 的家族分家
Transformer 论文发表后,AI 界发生了天翻地覆的变化。但有趣的是,后来的大佬们很少直接用原版的 Transformer(Encoder-Decoder 架构),而是把这个架构拆开来用了。
这就形成了现在大语言模型(LLM)界的两大门派:
🔵 编码器派 (Encoder-only):BERT 家族
- 代表人物:BERT, RoBERTa
- 做法:只用了 Transformer 的 左半边 (Encoder)。
- 特长:“懂你”。因为 Encoder 可以同时看到上下文,它是搞阅读理解、情感分析、文本分类的神。它不擅长说话,但擅长听懂人话。
🟢 解码器派 (Decoder-only):GPT 家族
- 代表人物:GPT-3, ChatGPT, Llama, Claude
- 做法:只用了 Transformer 的 右半边 (Decoder)(当然,去掉了中间那个 Cross Attention,变成了纯粹的 Autoregressive)。
- 特长:“忽悠”(哦不,是生成)。它就像一个话痨,你看不到未来,只能根据上文不停地蹦出下一个字。虽然它一开始不如 BERT 懂语法,但大家后来发现,只要大力出奇迹(堆数据、堆算力),Decoder 居然也能涌现出惊人的理解能力!
冷知识:现在的 ChatGPT 其实本质上就是一个巨大的 Decoder。它一直在做我们在第八章讲的事情:预测下一个词。
4. 结语:Attention Is All You Need
回顾我们的旅程,从第一章抛弃 RNN,到中间的 Attention 矩阵运算,再到最后的概率输出。
Transformer 的成功在于它做对了三件事:
那个 2017 年 Google 团队想出来的“黑盒子”,如今已经变成了人工智能时代的蒸汽机。
太棒了!有了理论基础,再看代码就像看说明书一样简单。
为了保持风格一致,这份代码讲解依然不走“枯燥教科书”路线。我会把 PyTorch 代码 和之前的 生动比喻 对应起来,并且特别标注出**“形状变换”**(Tensor Shapes),因为做 NLP 最头疼的就是不知道矩阵变成啥样了。
这是一份**《Transformer 核心组件·实战手术刀》。你可以把它作为博客的附录或者单独的技术实战篇**。
附录:PyTorch 代码逐行拆解
下面我们用 PyTorch 把 Transformer 最核心的零件拆下来给你看。 (注:为了代码清晰,省去了部分 Dropout 和初始化细节,专注核心逻辑。)
0. 准备工作
import torch
import torch.nn as nn
import math
import torch.nn.functional as F
# 假设我们有一个简单的配置
d_model = 512 # 词向量维度 (Embedding Size)
n_heads = 8 # 多头注意力的头数
d_ff = 2048 # FFN 中间层维度 (4倍 d_model)
1. 对应第三章:Embedding + 位置编码 (GPS)
这是数据的入口。最关键的是 PositionalEncoding,它是不需要训练的(requires_grad=False),它只是一个固定的数学波纹。
class PositionalEncoding(nn.Module):
def __init__(self, d_model, max_len=5000):
super(PositionalEncoding, self).__init__()
# 1. 创建一个足够长的矩阵 (max_len x d_model)
pe = torch.zeros(max_len, d_model)
position = torch.arange(0, max_len, dtype=torch.float).unsqueeze(1)
# 2. 计算分母 div_term (那个 10000^(2i/d) 的倒数)
# 这里的数学技巧是为了数值稳定性
div_term = torch.exp(torch.arange(0, d_model, 2).float() * (–math.log(10000.0) / d_model))
# 3. 填充 Sin 和 Cos
# 偶数位用 Sin,奇数位用 Cos
pe[:, 0::2] = torch.sin(position * div_term)
pe[:, 1::2] = torch.cos(position * div_term)
# 4. 增加一个维度,变成 [1, max_len, d_model],方便后续直接和 batch 相加
pe = pe.unsqueeze(0)
# 5. 注册为 buffer (意味着它不是参数,不需要梯度更新,但在保存模型时会跟着走)
self.register_buffer('pe', pe)
def forward(self, x):
# x 的形状: [Batch, Seq_Len, d_model]
# 直接把位置编码加到 x 上 (切片切出当前序列长度)
x = x + self.pe[:, :x.size(1)]
return x
👨💻 讲解: 这一步就是把**“蓝色颜料”(位置信息)倒进“红色颜料”**(词向量)里。 register_buffer 是 PyTorch 的一个小技巧,告诉模型:“这是个常量,别在这个变量上浪费梯度计算资源。”
2. 对应第四、五章:多头注意力 (Multi-Head Attention)
这是全篇最难写的部分。核心难点在于维度的变换。我们需要把 512 切成 8 个 64,算完后再拼回去。
class MultiHeadAttention(nn.Module):
def __init__(self, d_model, n_heads):
super(MultiHeadAttention, self).__init__()
self.d_model = d_model
self.n_heads = n_heads
self.head_dim = d_model // n_heads # 每个头的维度: 512 / 8 = 64
assert self.head_dim * n_heads == d_model, "维度必须能被头数整除!"
# 定义 W_q, W_k, W_v 矩阵
# 这里有个骚操作:与其定义 8 个小矩阵,不如定义 1 个大矩阵,后面再切分
self.w_q = nn.Linear(d_model, d_model)
self.w_k = nn.Linear(d_model, d_model)
self.w_v = nn.Linear(d_model, d_model)
# 定义最后的融合层 W_o
self.fc_out = nn.Linear(d_model, d_model)
def forward(self, query, key, value, mask=None):
batch_size = query.shape[0]
# 1. 线性变换 (Linear Projection)
# Q, K, V 形状: [Batch, Seq_Len, d_model]
Q = self.w_q(query)
K = self.w_k(key)
V = self.w_v(value)
# 2. 切分多头 (Split Heads)
# 这一步把 d_model 拆成了 n_heads * head_dim
# 变换后形状: [Batch, Seq_Len, n_heads, head_dim]
Q = Q.view(batch_size, –1, self.n_heads, self.head_dim)
K = K.view(batch_size, –1, self.n_heads, self.head_dim)
V = V.view(batch_size, –1, self.n_heads, self.head_dim)
# 3. 调整维度顺序 (Transpose)
# 为了做矩阵乘法,我们需要把 seq_len 和 head_dim 放在最后两维
# 变换后形状: [Batch, n_heads, Seq_Len, head_dim]
Q = Q.permute(0, 2, 1, 3)
K = K.permute(0, 2, 1, 3)
V = V.permute(0, 2, 1, 3)
# 4. 计算注意力分数 (Scaled Dot-Product Attention)
# energy 形状: [Batch, n_heads, Seq_Len, Seq_Len]
# 这里的 matmul 是针对最后两个维度的
energy = torch.matmul(Q, K.transpose(–2, –1)) / math.sqrt(self.head_dim)
# 如果有 Mask (比如 Decoder 不能看后面,或者 Padding Mask)
if mask is not None:
# 把 mask 为 0 的地方填成负无穷 (-1e20)
energy = energy.masked_fill(mask == 0, –1e20)
# 5. Softmax 归一化
attention = torch.softmax(energy, dim=–1)
# 6. 加权求和
# x 形状: [Batch, n_heads, Seq_Len, head_dim]
x = torch.matmul(attention, V)
# 7. 拼接多头 (Concat)
# 先变回 [Batch, Seq_Len, n_heads, head_dim]
x = x.permute(0, 2, 1, 3).contiguous()
# 再压扁成 [Batch, Seq_Len, d_model]
x = x.view(batch_size, –1, self.d_model)
# 8. 最后的线性混合
x = self.fc_out(x)
return x
👨💻 讲解:
- view 和 permute 是这里的灵魂。这就像是你在玩魔方,为了让同颜色的面转到一起,你需要先把魔方转几个角度。
- contiguous() 是个 PyTorch 的内存管理细节,如果不加,在 view 的时候可能会报错(因为内存不连续了)。
- masked_fill 就是那个“阶梯教室挡板”,把不需要看的地方强行设为负无穷。
3. 对应第七章:前馈神经网络 (FFN)
这是那个“宽进窄出”的三明治结构。简单粗暴,但参数量巨大。
class FeedForward(nn.Module):
def __init__(self, d_model, d_ff, dropout=0.1):
super(FeedForward, self).__init__()
# nn.Sequential 就像是一个把层串起来的容器
self.net = nn.Sequential(
# 第一层:膨胀 (512 -> 2048)
nn.Linear(d_model, d_ff),
# 激活函数:ReLU (过滤负能量)
nn.ReLU(),
# Dropout:防止过拟合
nn.Dropout(dropout),
# 第二层:收缩 (2048 -> 512)
nn.Linear(d_ff, d_model)
)
def forward(self, x):
return self.net(x)
4. 对应第六章:Encoder Layer (组装乐高)
把上面所有的零件,用 Add & Norm 封装起来,就成了 Encoder 的一层。
class EncoderLayer(nn.Module):
def __init__(self, d_model, n_heads, d_ff, dropout=0.1):
super(EncoderLayer, self).__init__()
# 两个主要的子层
self.self_attn = MultiHeadAttention(d_model, n_heads)
self.feed_forward = FeedForward(d_model, d_ff, dropout)
# 两个归一化层 (Layer Norm)
self.norm1 = nn.LayerNorm(d_model)
self.norm2 = nn.LayerNorm(d_model)
# Dropout
self.dropout = nn.Dropout(dropout)
def forward(self, x, mask):
# — 子层 1: Self-Attention —
# 1. 保留残差 (原始输入)
residual = x
# 2. 计算 Attention
x = self.self_attn(x, x, x, mask)
# 3. Dropout + Add + Norm
# 注意:这里展示的是 Post-Norm (论文原版),现在的 LLM 多用 Pre-Norm
x = self.norm1(residual + self.dropout(x))
# — 子层 2: Feed Forward —
# 1. 保留残差
residual = x
# 2. 计算 FFN
x = self.feed_forward(x)
# 3. Dropout + Add + Norm
x = self.norm2(residual + self.dropout(x))
return x
👨💻 讲解: 这里的代码结构非常清晰地展示了 “Add & Norm”: x = norm(residual + sub_layer(x))。 这就是让 Transformer 能叠 100 层的秘诀。
5. 拼装成 Transformer Encoder
最后,我们用 nn.ModuleList 把 6 个(或 N 个)EncoderLayer 叠在一起。
class TransformerEncoder(nn.Module):
def __init__(self, d_model, n_layers, n_heads, d_ff, vocab_size, max_len):
super(TransformerEncoder, self).__init__()
# 词嵌入 + 位置编码
self.embedding = nn.Embedding(vocab_size, d_model)
self.pos_encoding = PositionalEncoding(d_model, max_len)
# 堆叠 N 层 EncoderLayer
self.layers = nn.ModuleList([
EncoderLayer(d_model, n_heads, d_ff)
for _ in range(n_layers)
])
self.dropout = nn.Dropout(0.1)
def forward(self, x, mask):
# 1. 输入处理
x = self.embedding(x)
x = self.pos_encoding(x)
x = self.dropout(x)
# 2. 一层一层往下传
for layer in self.layers:
x = layer(x, mask)
return x
总结
看完了代码,是不是觉得 Transformer 也没那么可怕? 它本质上就是一堆 Linear 层(矩阵乘法),加上形状变换(view/permute),最后套上归一化(LayerNorm)。
虽然现在的 GPT-4 等模型在此基础上做了很多微小的修改(比如用 RMSNorm 替代 LayerNorm,用 SwiGLU 替代 ReLU,用 RoPE 替代 Sin/Cos),但骨架依然是你今天亲手拆解的这一副。
现在,打开你的 IDE,试着把这些代码跑起来吧!
后记:走出黑盒,看见星辰大海
当你读到这行字的时候,恭喜你!你已经成功拆解了当今 AI 时代最硬核的引擎——Transformer。
回过头看,你可能不敢相信,那个现在能写诗、能写代码、能陪你聊天的 ChatGPT,那个号称拥有“人类智慧”的庞然大物,其底层逻辑竟然就是我们刚刚聊完的这几样东西:
- 几个矩阵乘法(让词与词之间发生化学反应)。
- 几个残差连接(防止楼盖塌了)。
- 一个 Softmax(把结果变成概率)。
- 再加上无数的数据和算力。
1. 并不神秘的“魔法”
写这篇博客最大的初衷,就是想打破对 AI 的“迷信”。
以前我们总觉得,要让机器学会语言,必须教它主谓宾、定状补,教它复杂的语法树。但 Transformer 告诉我们:No,你只需要让它自己去“看”(Attention),看足够多的书,它自己就能涌现出理解力。
它没有任何一条硬性规则告诉它“it 指代 animal”,它只是通过亿万次的训练,算出这两个词在一起出现的概率最高。
这是一种暴力美学,也是一种统计学的胜利。
2. 为什么是 Transformer?
你可能会问,未来会有模型取代 Transformer 吗? 答案是肯定的。比如最近很火的 Mamba (SSM) 架构就在挑战它的地位。
但 Transformer 在 AI 历史上的地位就像是蒸汽机。 它之所以伟大,不仅是因为效果好,更是因为它即使粗暴地堆叠,也能并行地运转(记得第一章的抛弃 RNN 吗?)。正是这种架构上的突破,才让后来 GPT-4 这种万亿参数的“怪兽”成为可能。
它开启了 “Scale is all you need”(规模即一切)的时代。
3. 你的下一站
看懂了原理图,只是万里长征第一步。如果你想真正掌握它,我给你三个建议:
写在最后
2017 年,8 位 Google 工程师发表《Attention Is All You Need》时,他们可能也没想到,这个本来用于翻译的积木块,会在几年后点燃通用人工智能(AGI)的火种。
我们正处在一个新时代的黎明。现在,你已经懂得了这台“引擎”的图纸。 接下来,请带上这个工具,去创造你自己的东西吧。
因为在 AI 的世界里,Attention is all you need,但 Curiosity(好奇心)才是你唯一的边界。
网硕互联帮助中心






评论前必须登录!
注册