960个参数跑通Transformer:从零理解大模型

如果有人问你"大模型有几千亿参数,参数到底是什么",大多数回答要么是"就是权重矩阵"(等于没说),要么丢一堆公式把你吓跑。

这篇从零开始,用一个 960 个参数的迷你 Transformer 把这件事讲透。能跑,有真实输出,不灌水。

参数是什么:不是旋钮,是"话语权"

想象模型在回答一个问题:猫喜欢吃____?

模型内部有几百亿个"小评委",每个评委只管一件具体的事:

  • 评委 A:这个词是不是食物?
  • 评委 B:这个词是不是动物?
  • 评委 C:上下文有没有提到猫?

每个评委给出一个 0 到 1 之间的分数。但每个评委的"话语权"不一样——有的说话算数(权重高),有的说了等于没说(权重低)。

这个"话语权"的数值,就是参数。

python
# 评委A检测出"鱼"的食物属性是0.9
# 但评委A的话语权(参数)是0.8
# 最终贡献:0.9 × 0.8 = 0.72

# 评委B检测出"鱼"的动物属性是0.5
# 但评委B的话语权只有0.1
# 最终贡献:0.5 × 0.1 = 0.05

几百亿个这种数字合在一起,构成了模型的全部"经验"。

训练前,这些数字全是随机数,模型乱说("猫喜欢吃桌子")。训练就是给模型喂海量文本,每次答错就微调这些数值。几万亿字读下来,几百亿个数值慢慢稳定。训练结束,数值固定——这就是你下载的模型文件。

从3个参数开始

python
def predict(word):
    judge_food   = check_food(word)     # 0.9
    judge_animal = check_animal(word)   # 0.5
    judge_context = check_context(word) # 0.8

    score = (judge_food   * weight_A)   # 0.9 × 0.8 = 0.72
          + (judge_animal * weight_B)   # 0.5 × 0.3 = 0.15
          + (judge_context * weight_C)  # 0.8 × 0.7 = 0.56
    return score
    # → 1.43

3 个权重 = 3 个参数。weight_Aweight_Bweight_C 就是参数。训练调的就是这三个数字。

正确答案哪来的?不需要人工标注。从互联网文本里挖掉一个词让模型猜:

原文:我家的小猫特别喜欢吃鱼,每天都吃一罐
挖空:我家的小猫特别喜欢吃____,每天都吃一罐
答案:鱼

模型对每个候选词都算一遍分数,选最高的。猜错了就调参数。循环几万亿遍。这叫自监督学习。

参数量怎么爆炸的:乘法不是指数

一个容易踩的坑:100 万参数/层 × 100 层,为什么是 1 亿而不是 100 的 100 次方?

每层的参数是独立的,不累乘,只累加。

第1层→第2层:100万个权重(自己的)
第2层→第3层:100万个权重(全新的,跟上一层没关系)
第3层→第4层:100万个权重(又是全新的)
...
100万 × 99层连接 ≈ 1亿

打比方:100 层楼,每层 1000 个房间,每间放 1 张床。总床数 = 100 × 1000 = 10 万,不是 1000 的 100 次方。

那万亿参数怎么来的?把每层做宽 + 层数做多:

我的例子:  3个检测器, 1层     → 3个参数
小模型:    几百个检测器, 12层  → ~1亿
GPT-3:    上万个检测器, 96层  → 1750亿

结构一样,维度和层数大了几个数量级,参数自然到几千亿。不需要指数增长,乘法就够了。

三个关键零件

光有加权求和不够,还有三个固定规则让模型能工作。

ReLU:非线性开关

python
def ReLU(x):
    return max(0, x)

负的归零,正的留着。没有任何参数,不需要训练,就这一条折线。

为什么必须有它? 如果每层只做乘法加法(线性变换),不管叠多少层,最后还是一个乘法加一个加法:

第1层:y = 2x + 1
第2层:z = 3y - 2 = 3(2x+1) - 2 = 6x + 1

不管叠 100 层还是 1000 层,最后还是一条直线。但语言不是直线的——"猫喜欢吃鱼"合理,"猫喜欢吃桌子"不合理,这是有门槛、有条件的。

ReLU 在每一层做了一个"开关":信号够大才放行,不够大就切断。几十亿个开关叠起来,组合出极其复杂的条件判断逻辑。

一句话:ReLU 让层数有意义。没有它,100 层等于 1 层。

LayerNorm:数值调音器

经过一层的乘法加法,数值可能飘到离谱的范围:

第1层输出:[0.1, 0.5, 2.3]   ← 正常
第2层输出:[0.01, 15.7, 842]  ← 飘了
第3层输出:[0.0001, 99000, 8.3e15]  ← 爆了

LayerNorm 就是每层算完后强制把数值压回标准范围——减均值、除标准差。太大就调小,太小就调大。

跟 ReLU 的区别:ReLU 让模型聪明(能学复杂模式),LayerNorm 让模型不崩(数值不爆炸)。

注意力:词与词互看

这是 Transformer 的核心创新。每个词不再只看自己,而是去看上下文里所有其他词,判断谁跟自己相关,相关的信号加强。

实现上,每个词通过三组参数生成三个向量:查询(Q)、键(K)、值(V)。

  • Q(查询):我想找什么样的信息?
  • K(键):我能提供什么样的信息?
  • V(值):我实际携带的信息内容。

当前词的 Q 跟所有词的 K 做点积算相关度,转成权重后,按权重混合所有词的 V。这就是"注意力"。

完整 Transformer:8维迷你版

把前面所有概念串起来,写一个能跑的迷你 Transformer。

配置:8 维向量,前馈网络 16 宽,2 层,词表 4 个词(鱼、猫粮、桌子、汽车)。

每层内部做 5 件事:

python
def Transformer层(向量组, 层参数):
    # ① 注意力:词与词互看,按相关度混合信息
    attn = 注意力(向量组, 层参数)  # 用 Q/K/V 三个矩阵

    # ② 残差连接 + LayerNorm(防止信号消失 + 压数值)
    残差 = 向量组 + attn
    归一化 = LayerNorm(残差)

    # ③ 前馈网络:升维→ReLU→降维
    ffn = 前馈网络(归一化, 层参数)  # W1: 8→16, ReLU, W2: 16→8

    # ④ 残差 + LayerNorm
    输出 = LayerNorm(归一化 + ffn)
    return 输出

完整的 predict 流程:

python
def predict(输入词):
    # ① 查词向量表:词 → 8维向量
    向量组 = [词向量表[词] for 词 in 输入词]

    # ② 过2层 Transformer
    for 层参数 in 模型参数:
        向量组 = Transformer层(向量组, 层参数)

    # ③ 取最后一个位置的输出向量
    最终 = 向量组[-1]

    # ④ 跟词表里每个词算分数
    分数 = [点乘(最终, 输出矩阵[i]) for i in range(词表大小)]

    # ⑤ softmax 转概率,选分最高的
    概率 = softmax(分数)
    return 概率

跑出来的真实输出

这个迷你模型有 960 个参数(参数是随机的,未训练):

迷你Transformer运行输出

每层参数明细:

注意力 Q/K/V:8×8 × 3 = 192
前馈 W1/W2:8×16 + 16×8 = 256
每层小计:448
2层合计:896

词向量表:4词 × 8维 = 32
输出层:8维 × 4词 = 32
────────────────────
总计:960

输入 ["鱼", "猫粮"] 作为上下文,模型对"猫粮"给出了最高概率(45%)。当然这个结果没有意义——参数是随机的。训练就是把这 960 个数字从随机调到正确的过程。

注意力权重也长这样:

「鱼」看其他词:
  → 「鱼」: 56.2%(看自己最多)
  → 「猫粮」: 43.8%

训练之后,如果输入是"猫喜欢吃",模型会学到"猫"和"鱼"的注意力权重很高,"猫"和"桌子"很低。注意力让模型知道哪些词之间有关系。

放大到真实模型

同样一套结构,把维度和层数调大:

迷你版:    8维, 16前馈, 2层, 4词      → 960参数
GPT-3:    12288维, 49152前馈, 96层, 10万词 → 1750亿

维度从 8 → 12288(放大 1536 倍),前馈从 16 → 49152(放大 3072 倍),乘一下就到几千亿了。原理一模一样,没有魔法。

为什么要分层

一层只能做一次简单判断(一条折线)。不管一层做得多宽,还是一次线性变换——100 万个检测器堆在一层里,也只是"初级检查",没有组长汇总做二次判断。

两层就不一样了:第二层拿第一层的判断结果当输入,在简单判断的基础上做组合判断。浅层看字面,中层看语法,深层看语义,最深层看意图。每多一层,抽象程度上一个台阶。

实际加层遵循收益递减规律:效果先涨后平。模型"学不会"训练数据时加层有用;加到一定程度后 loss 不再下降,再加层只让推理变慢,就该停了。

GPT-3 选 96 层而不是 192 层,就是因为试下来 192 层只多涨了 2% 性能,但推理慢了一倍——不值。

整个逻辑链串起来:

互联网文本 → 挖空 → 模型猜 → 对答案 → 调参数 → 循环万亿遍 → 参数定型 → 成品模型

参数本身不神奇,就是一堆数字乘来乘去。神奇的是训练把它们调到了刚好能"理解语言"的程度。


附:本文迷你 Transformer 完整可运行代码已开源,960 个参数,Python 标准库即可运行,无需安装任何框架。封面图来自 karpathy/nanoGPT,最简单的 GPT 训练库。

推荐阅读