从零开始理解大模型(五):Transformer 全景——积木怎么搭成大厦

举报
AGENT魔方 发表于 2026/04/16 10:41:01 2026/04/16
【摘要】 本文是「从零开始理解大模型」系列第五篇,本系列共十篇,从 “下一个词预测” 逐步搭建完整的大模型心智模型,每篇均附带可运行代码。本篇以全景视角讲解 Transformer 架构,带你看懂基础组件如何一步步搭建出大模型的核心架构

专栏1.png

欢迎阅读「从零开始理解大模型」系列 —— 十篇文章,从"下一个词预测"到完整的大模型心智模型。每篇配可运行代码。

作者:十一

前四篇,我们一块一块地认识了积木:

  • Token(第二篇)—— 把文字切成模型认识的碎片
  • Embedding(第三篇)—— 把碎片变成带语义的向量
  • Attention(第四篇)—— 让每个词"看见"上下文

但光有积木还不够。Attention 只是 Transformer 一层的一半,另一半是什么?GPT-2 有 12 层,LLaMA 有 32 层,为什么要叠这么多?

这篇把积木搭成完整的大厦。读完之后,大模型从输入到输出的每一步,你都明白了。


一、先说结论

1.png

句话版本:Transformer = (Attention + FFN) × N 层,再加点"胶水"。就这么简单的结构,重复 N 次,就是所有大模型的骨架。


二、先打个比方,建立全局感觉

想象一家公司,一份报告要经过 12 个部门审阅。

每个部门固定做两件事:

  1. 开会(Attention)—— 大家坐在一起,互相交流信息。每个人听完别人的发言,更新自己的理解。"你们都说说,我综合一下。"

  2. 回工位写总结(FFN)—— 开完会,每个人回去独自思考,把讨论内容消化成自己的判断。"我自己想想,这事到底意味着什么。"

另外有两个保障机制:

  • 保留原件(残差连接)—— 每次修改,都在原件上叠加,不会覆盖原件。"改归改,原来的东西不能丢。"

  • 统一格式(LayerNorm)—— 每次流转前,把报告里的数字拉到统一范围。"大家别一个写米、一个写公里,先统一度量衡。"

12 个部门审完,报告里既有所有部门的意见,又没丢失原始信息。

这就是 Transformer 干的全部事情。 下面一个一个展开。


三、一层 Transformer 长什么样

画成流程图:

输入向量
    │
    ▼
┌─────────────────────────────────────┐
│  ① LayerNorm(统一格式)              │
│  ② Multi-Head Attention(开会)       │
│  ③ 残差连接:输出 = 输入 + 开会结果    │
├─────────────────────────────────────┤
│  ④ LayerNorm(统一格式)              │
│  ⑤ FFN(独立思考)                    │
│  ⑥ 残差连接:输出 = 输入 + 思考结果    │
└─────────────────────────────────────┘
    │
    ▼
输出向量(送去下一层继续处理)

上半部分是 Attention——让词和词之间互相交流。下半部分是 FFN——让每个词自己消化信息。中间的 LayerNorm 和残差连接做稳定保障。

写成代码,核心就四行:

residual = hidden
hidden = residual + attention(layernorm_1(hidden))   # 开会 + 保留原件
residual = hidden
hidden = residual + ffn(layernorm_2(hidden))         # 独立思考 + 保留原件

看着是不是特别朴素?别小看它——GPT-4、Claude、LLaMA、DeepSeek,内部全是这四行在不断重复。

下面逐个讲解三个你还没见过的新组件。


四、FFN——"开完会了,自己坐下来想一想"

4.1 光开会还不够

第四篇讲的 Attention,让每个词都"听到了"其他词的信息。处理 "Thank you very" 的时候,"very" 知道了前面有 "Thank" 和 "you"。

但"听到"不等于"想明白"。

就像你参加了一场会,听了一大堆发言,脑子里全是信息碎片。你还得回到工位上坐下来,自己理一理:**"这些信息综合起来,到底说明什么?"**

这个"坐下来理一理"的步骤,就是 FFN(Feed-Forward Network,前馈网络)。

为什么叫"前馈"?因为数据只往前走,不回头——当前 token 的信息处理完后,直接"喂"给下一层,不会把自己的输出再喂回自己。没有循环、没有反复,一路向前。

4.2 它到底怎么做的

公式长这样:

FFN(x) = W₂ · GELU(W₁ · x + b₁) + b₂

这里的 W₁、W₂ 是训练时学出来的权重矩阵,训练完就固定不变了。同一层里所有 token 共用同一组 W₁、W₂——不是每个 token 各有一份。

别被公式吓着。拆开来看就是三步:

输入(768 个数字)
  │
  ▼ 第一步:"展开"—— 乘一个大矩阵,768 维变成 3072 维
  │   就好比把一页笔记铺开到四页纸上,有更多空间做标注
  │
  ▼ 第二步:"划重点"—— 用激活函数(GELU)过一遍
  │   就好比拿一支半透明荧光笔划重点:
  │   - 特别重要的内容(正数)会被高亮保留
  │   - 不太重要的内容(负数)也不会被完全涂黑,而是被轻轻压低、保留一点点痕迹
  │
  ▼ 第三步:"压缩"—— 再乘一个大矩阵,3072 维压回 768 维
  │   就好比把四页标注总结回一页精华
  │
  ▼ 输出(还是 768 个数字)

有一个特别重要的特点:FFN 只看自己,不看别人。 "very" 做 FFN 的时候,完全不管 "Thank" 和 "you" 在干嘛。这和 Attention 正好反过来——Attention 是"大家一起交流",FFN 是"每个人独自思考"。

4.3 为什么说 FFN 是"知识库"

有一个有趣的发现:大模型记住的事实(比如"法国首都是巴黎")主要存在 FFN 的权重里。

打个比方:

  • Attention 是搜索引擎——在上下文里搜到了 "Thank you" 这个线索
  • FFN 是大脑里的记忆——看到这个线索后,从记忆中调出 "much" 这个最强搭配

一个负责找线索,一个负责给答案。两者配合,才能又找对又答对。


五、残差连接——"改归改,原件必须留着"

5.1 世界上最简单的操作

输出 = 输入 + f(输入)     // f 是 Attention 或 FFN

就是把输入原封不动加到输出上。对,就这么简单。

但为什么叫"残差"? 移项一下就明白了:

f(输入) = 输出 - 输入 = 残差

Attention 和 FFN 学到的东西,不是"完整答案该长啥样",而是"跟输入多少"。这个差值就叫残差

学一个小的修正量,比从零学一个完整答案简单多了。这就是残差学习的核心思想,名字也从这来。

5.2 没有它,12 层就废了

想想"传话游戏":你悄悄告诉第一个人一句话,一个传一个,传 12 轮——最后一个人说出来的,跟原话八竿子打不着。

没有残差连接的 Transformer 就是这样。12 层一叠,原始信息早就面目全非了。而且训练的时候,调参数的信号(叫"梯度")要从第 12 层一路传回第 1 层,每过一层就弱一点。传 12 层下来,信号几乎没了——前面的层调不动参数,就等于白训练。

这个问题叫梯度消失,是深层网络最经典的老大难。

5.3 加上它之后,画风完全不同

残差连接等于给每一层装了一条直通管道

输入 ──────┬──────────────────────────────────┐
           │                                  │
           ▼                                  │ 直通管道
    Attention/FFN 处理                         │(原始信息直接穿过去)
           │                                  │
           ▼                                  │
      修正量(Δ)───────→ (+) ◄────────────────┘
                           │
                           ▼
                       输出 = 输入 + Δ

不管 Attention/FFN 处理得多好或多烂,原始输入都通过直通管道完整到达了终点。

所以每一层不需要"从零开始写一份新报告",只需要在原报告上批注几句修改意见

Layer 1 输出 = Embedding + Δ₁            ← 第一个部门批了几句
Layer 2 输出 = Embedding + Δ₁ + Δ₂        ← 第二个部门又批了几句
...
Layer 12 输出 = Embedding + Δ₁ + ... + Δ₁₂  ← 12 个部门的修改意见叠在一起

就像改文章——不是每一稿从头写,而是在上一稿基础上改红字。改 12 轮,肯定比从零写 12 遍容易得多。

 transformer_anatomy.py[1] 可以验证:即使经过 12 层变换,输出和原始 Embedding 的余弦相似度还是很高。原始信息确实通过直通管道保到了最后。


六、LayerNorm——"每次传递前,先统一度量衡"

6.1 为什么需要

你去菜市场买菜,一个摊位标价"3",另一个标价"3000"。哪个贵?不知道——因为一个单位是"元/斤",另一个是"元/吨"。数字大小没意义,除非单位统一。

Transformer 里也是这样。向量经过矩阵乘法和加法之后,有些维度的数字飙到 100,有些缩到 0.001。差了十万倍。后续的 Softmax 看到这种极端分布就懵了:它会把几乎全部注意力给最大的那个值,其他值全变成零。

数字大小太离谱,后面的计算全带跑偏了。

6.2 怎么解决

LayerNorm 干的事特别朴素:把向量里所有数字"拉"回差不多大的范围

LayerNorm(x) = γ · (x - μ) / σ + β

拆开来看:

  1. 先算平均值(μ),把所有数字都减去平均值——让中心归零
  2. 再算散开程度(σ),除以它——让大小统一
  3. 最后乘以 γ 加上 β——留一点微调余地(γ 和 β 是训练时学出来的)

看个具体例子:

输入:  [100.0, 0.001, -50.0, 25.0]    ← 差距十万倍,后续计算会炸
  ↓ 减均值 18.75,除标准差 55.9
输出:  [1.45, -0.34, -1.23, 0.11]     ← 都在 -2 到 +2 之间了,好处理多了

就像考试成绩——原始分可能是 150 分满分、也可能是 10 分满分,没法比。但转成"标准分"之后,所有人的成绩都在同一个尺度上了。

LayerNorm 的参数很少——GPT-2 每层只有 3072 个——但缺了它模型就训不出来。真正的四两拨千斤。


七、拆开 GPT-2,看参数都在哪

四个组件都认识了。现在打开 GPT-2 的"引擎盖",看看 1.24 亿个参数到底怎么分配的。

先算一下每个组件有多少参数。GPT-2 的关键数字:向量维度 d=768,注意力头数 12,FFN 扩展倍数 4,词表 50257,最大位置 1024。

Embedding:

  • Token Embedding:每个 token 一个 768 维向量 → 50257 × 768 = 38,597,376
  • Position Embedding:每个位置一个 768 维向量 → 1024 × 768 = 786,432

Attention(每层):

  • Q、K、V 三个权重矩阵,每个 768×768 → 3 × 589,824 = 1,769,472
  • 输出投影矩阵 O:768×768 = 589,824
  • 四个偏置项:768 × 4 = 3,072
  • 每层合计:约 236 万

FFN(每层):

  • W₁ 扩展矩阵:768 × 3072 = 2,359,296
  • W₂ 压缩矩阵:3072 × 768 = 2,359,296
  • 两个偏置项:3072 + 768 = 3,840
  • 每层合计:约 472 万(是 Attention 的两倍,因为有 4 倍扩展)

LayerNorm(每层):

  • 每层两组(Attention 前 + FFN 前),每组有 γ 和 β 各 768 个 → 768 × 2 × 2 = 3,072

现在看运行 transformer_anatomy.py[1] 得到的实际分布:

组件                            参数量         占比
──────────────────────────────────────────────────
Token Embedding              38,597,376      31.0%  ███████████████
Position Embedding              786,432       0.6%
Attention(12层合计)        28,348,416      22.8%  ███████████
FFN(12层合计)              56,669,184      45.5%  ██████████████████████
LayerNorm + 其他                 38,400       0.0%

三个有意思的发现:

FFN 是最大头。 占 45.5%,几乎是 Attention 的两倍。为啥?因为 FFN 有 4 倍扩展(768→3072→768),两个大矩阵。FFN 是"知识库"嘛,存知识当然需要空间。

Embedding 在小模型里占比惊人。 GPT-2 的 Embedding 占了 31%。但在更大的模型(比如 LLaMA 7B)里,Embedding 只占 2% 左右——因为模型变大的时候,Transformer 层的参数增长速度远超 Embedding。

LayerNorm 小到可以忽略。 只有 38,400 个参数。但没它整个模型就训练不了。最不起眼的组件,反而最不能少。

完整拆解和数据流追踪代码见附件 transformer_anatomy.py[1]


八、为什么要叠这么多层

GPT-2 叠了 12 层,LLaMA 7B 叠了 32 层。能不能把一层做得特别大,只用一层搞定?

不行。原因有两个。

8.1 不同层看不同层次的东西

就像人理解一句话,有从浅到深的过程

1.png

第三篇的实验展示过:同一个词 "bank",在"银行"和"河岸"两个语境下,向量差异是一层一层加大的:

Layer  0: 相似度 1.000  ← 完全一样("这个 bank 啥意思我还不知道")
Layer  3: 相似度 0.887  ← 开始有点不同了("后面好像跟了 money...")
Layer  6: 相似度 0.778  ← 差距越来越大
Layer  9: 相似度 0.691
Layer 12: 相似度 0.614  ← 彻底区分了("这个是银行,那个是河岸")

浅层做粗活,深层做细活。一层搞不定的事情,叠几层就能搞定。

8.2 多层 = 多步推理

有些理解需要想好几步。

比如这句话:"The trophy doesn't fit in the suitcase because it is too big"——这里的 "it" 指 trophy 还是 suitcase?

  • 浅层:先认出 "it" 是代词,要找它指的是谁
  • 中间层:注意到 "too big" 说的是尺寸
  • 深层:推理——"太大"所以放不下。放不下的应该是 trophy(要是 suitcase 太大,反而装得下啊)。所以 "it" = trophy

一步到位做不出这种推理。每多一层,模型就多一次"想一想、改一改"的机会。

层数不是越多越好,但深度确实带来推理能力。


九、完整架构图:把所有积木拼起来

到这里,所有零件你都认识了。拼在一起:

输入文本: "Thank you very"
    │
    ▼ ─── 分词(第二篇)
[10449, 345, 845]                             ← 3 个 token ID
    │
    ├─▶ Token Embedding(查表)               ← 3 个 768 维向量
    ├─▶ Position Embedding(查表)            ← 3 个位置向量
    ▼ ─── 加在一起(第三篇)
[向量₁, 向量₂, 向量₃]                         ← 初始表示
    │
    │   ┌────────────────────────────────────────┐
    │   │        Transformer Layer × 12          │
    │   │                                        │
    │   │   LayerNorm → Attention(12头)→ 残差   │ ← 开会
    │   │   LayerNorm → FFN(768→3072→768)→ 残差 │ ← 独立思考
    │   │                                        │
    │   └────────────────────────────────────────┘
    │         ↑ 重复 12 次(GPT-2)/ 32 次(LLaMA 7B)
    │
    ▼ ─── 最终 LayerNorm
    ▼ ─── LM Head(768 → 50257)
    ▼ ─── Softmax
[..., P("much")=0.992, ...]                    ← 50257 个概率
    │
    ▼ ─── 选 token(第一篇)
" much"

就这些了。没有更多隐藏模块。

GPT-4、Claude、LLaMA、DeepSeek——底层全是这个结构。区别只在三个数字

1.png

同样的架构,放大规模而已。所以用 GPT-2 理解原理,跟用 GPT-4 完全等价。


十、LM Head 与权重共享

架构图最后的 "LM Head(768→50257)" 把向量变回 50257 个概率——模型内部一直在操作向量,这一步翻译回"每个词有多大可能性"。

很多模型(包括 GPT-2)中,LM Head 和 Token Embedding 共享同一个权重矩阵——同一张 50257×768 的表,进去的时候按行查向量,出来的时候做矩阵乘法算概率。12 层 Transformer 的任务,就是把最后一个位置的向量推向 "much" 对应的方向。推得越准,概率越高——第一篇看到的 99.2% 就是这么来的。


十一、五篇回顾

到这里,前五篇构成了一条完整的链路。大模型从输入到输出的每一步,你都看过了

1.png

前五篇回答了"大模型是什么"。 后五篇回答"怎么变得更好":训练(第六篇)、推理优化(第七篇)、上下文窗口(第八篇)、Scaling Law(第九篇)、和 Agent 结合(第十篇)。


十二、结语

回头看,Transformer 简单到令人吃惊。

总共就两种核心运算——Attention(开会讨论)、FFN(独立思考)。加上 LayerNorm 统一格式、残差连接保留原件,然后重复 N 次。

同一个结构,拿去翻译、写代码、做数学、聊天——通通能用。你不需要给每种任务设计不同的模型,只需要把这个简单结构做得足够大。

"The unreasonable effectiveness of simple architectures."

架构够通用,规模就是最好的武器。

下一篇,我们讲这些参数怎么从一堆随机数变成能对话的"大脑"——70 亿个数字,是怎么"学"出来的。


本文配套代码:transformer_anatomy.py[1](模型拆解、参数统计、数据流追踪、残差连接验证)。需要 Python 3.8+、transformers、torch。


容器模仿.png

扫码回复“大模型

获取本系列文章完整配套代码

「从零开始理解大模型」是「从零开始理解 Agent」的姊妹系列。Agent 系列讲"四肢",本系列讲"大脑"。建议对照阅读 专栏入口

相关链接

[1] transformer_anatomy.py: https://github.com/GitHubxsy/nanoAgent/blob/claude/organize-teaching-materials-4hnRP/llm-from-scratch/transformer_anatomy.py

   今日推荐

关注AGENT魔方公众号,回复大模型

领取从零开始理解大模型」实操配套代码

加速入门和掌握Agent:

0大模型配图.jpg


【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。