如果有人问你"大模型有几千亿参数,参数到底是什么",大多数回答要么是"就是权重矩阵"(等于没说),要么丢一堆公式把你吓跑。
这篇从零开始,用一个 960 个参数的迷你 Transformer 把这件事讲透。能跑,有真实输出,不灌水。
参数是什么:不是旋钮,是"话语权"
想象模型在回答一个问题:猫喜欢吃____?
模型内部有几百亿个"小评委",每个评委只管一件具体的事:
- 评委 A:这个词是不是食物?
- 评委 B:这个词是不是动物?
- 评委 C:上下文有没有提到猫?
每个评委给出一个 0 到 1 之间的分数。但每个评委的"话语权"不一样——有的说话算数(权重高),有的说了等于没说(权重低)。
这个"话语权"的数值,就是参数。
# 评委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个参数开始
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.433 个权重 = 3 个参数。weight_A、weight_B、weight_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:非线性开关
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。这就是"注意力"。
前馈网络:为什么先升维再降维
注意力让词与词之间通了气,但通气之后,每个词还需要独立消化收集来的信息。这就是前馈网络的工作。
def 前馈网络(向量, 层参数):
升维 = matmul(向量, W1) # 8维 → 16维
激活 = [ReLU(x) for x in 升维]
降维 = matmul(激活, W2) # 16维 → 8维
return 降维为什么不是 8→8,而是绕一圈 8→16→8?
升维 = 把原始特征做组合,生成更丰富的中间判断。
输入是 8 维向量,每个维度是一个"原子特征"。升到 16 维后,多出来的 8 个维度不是凭空变出来的——每个新维度 = 原始特征的某种组合:
新第9维 = 0.3×特征1 + 0.7×特征3 + 0.1×特征5 = 0.62
→ 可能代表"是不是食物"(把多个原子特征组合成一个复合判断)
新第10维 = 0.9×特征2 + 0.5×特征8 = -0.33
→ 可能代表"是不是活的"(另一种组合)打比方:你有身高、体重、年龄、臂展等 8 个原始数据。升维就是从这 8 个数据里搭配出 16 个复合判断——"体型偏大还是偏小""是否适合打篮球""是否开始衰老"——每个复合判断都是原始数据的不同组合。维度越多,能做的组合判断越多。
ReLU 在升维之后立刻砍一刀:16 个组合判断里,负值的("这条线索不相关")直接归零,只有有意义的判断才传给降维那一步。
降维 = 把有效的复合判断压缩总结回 8 维,传给下一层。 就像开会:16 个人各发表意见(升维),最后总结成 8 条结论(降维)。输出维度必须跟输入一样大,否则下一层接不上。
真实模型升得更狠:8192 维升到 28672 维(3.5 倍),从 8192 个原子特征里组合出 28672 个中间判断。
完整 Transformer:8维迷你版
把前面所有概念串起来,写一个能跑的迷你 Transformer。
配置:8 维向量,前馈网络 16 宽,2 层,词表 4 个词(鱼、猫粮、桌子、汽车)。
每层内部做 5 件事:
def Transformer层(向量组, 层参数):
# ① 注意力:词与词互看,按相关度混合信息
attn = 注意力(向量组, 层参数) # 用 Q/K/V 三个矩阵
# ② 残差连接 + LayerNorm(防止信号消失 + 压数值)
残差 = 向量组 + attn
归一化 = LayerNorm(残差)
# ③ 前馈网络:升维→ReLU→降维
ffn = 前馈网络(归一化, 层参数) # W1: 8→16, ReLU, W2: 16→8
# ④ 残差 + LayerNorm
输出 = LayerNorm(归一化 + ffn)
return 输出完整的 predict 流程:
def predict(输入词):
# ① 查词向量表:词 → 8维向量
向量组 = [词向量表[词] for 词 in 输入词]
# ② 过2层 Transformer
for 层参数 in 模型参数:
向量组 = Transformer层(向量组, 层参数)
# ③ 取最后一个位置的输出向量
最终 = 向量组[-1]
# ④ 跟词表里每个词算分数
分数 = [点乘(最终, 输出矩阵[i]) for i in range(词表大小)]
# ⑤ softmax 转概率,选分最高的
概率 = softmax(分数)
return 概率跑出来的真实输出
这个迷你模型有 960 个参数(参数是随机的,未训练):

每层参数明细:
注意力 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 个数字从随机调到正确的过程。
参数怎么调:梯度下降
训练的核心就一个问题:参数有几百亿个,每个该往哪个方向调、调多少?
想象你蒙着眼睛站在一座山上,要走到最低的谷底(误差最小的地方)。你看不到全貌,只能用脚感受坡度——左脚下斜就往左走,右脚下斜就往右走。每次走一小步,走到坡度变平就停。
这就是梯度下降。坡度(梯度)告诉你该往哪走,学习率决定每步迈多大。
四个步骤循环:
① 前向传播:输入文本 → 模型猜一个词
② 算误差:猜的跟正确答案差多远
③ 反向传播:从输出往回算,每个参数对这个误差负多少责任
④ 更新参数:往误差变小的方向调一小步第③步是核心,叫反向传播。用链式法则,从最后一层开始,逐层往回算:如果某个参数调大一点点,误差是变大还是变小?变大的就往反方向调,变小的就继续往这个方向调。
这个循环跑几万亿次,参数就慢慢稳定下来。
放大到真实模型
同样一套结构,把维度和层数调大:
迷你版: 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% 性能,但推理慢了一倍——不值。
KV缓存:为什么长对话吃显存
模型生成文字是一个字一个字吐的。第 1 轮输入"猫"预测"喜欢",第 2 轮输入"猫喜欢"预测"吃",第 3 轮输入"猫喜欢吃"预测"鱼"……每吐一个字,所有已有词都要重新过一遍注意力。
但注意力的计算有个特点:旧词的 K 和 V 向量每一轮都一样,纯重复计算。
缓存就是把每一层每个已处理词的 K 和 V 存起来,新词来了直接读,不重算。
没有缓存:每轮把所有词的 K、V 全部重算
有缓存:只算新词的 K、V,追加到缓存尾部Q 不缓存——因为每次只有新词需要发起新查询。K 和 V 缓存——因为旧词提供给别人的信息不会变。
缓存的代价是吃显存。以一个 80 层、8192 维的模型为例,对话 1000 个词,KV 缓存大约占 5 GB。对话越长缓存越大——这就是为什么长对话特别贵、特别慢。
整个逻辑链串起来:
互联网文本 → 挖空 → 模型猜 → 对答案 → 算误差 → 反向传播 → 调参数 → 循环万亿遍 → 参数定型 → 成品模型
参数本身不神奇,就是一堆数字乘来乘去。神奇的是训练把它们调到了刚好能"理解语言"的程度。
附:本文迷你 Transformer 完整可运行代码已开源,960 个参数,Python 标准库即可运行,无需安装任何框架。封面图来自 karpathy/nanoGPT,最简单的 GPT 训练库。