Gemma 的 (1+w) 缩放:一个 +1 为何能稳住训练
🎯 先猜一猜(下注解锁)
Gemma 把 RMSNorm 的缩放从 x·w 改成 x·(1+w),而且 weight 还是初始化成 0。看着只是个 +1。
先判断:这个 +1 最主要解决什么问题?
先补的知识
- 回忆 RMSNorm:先把向量按它自己的均方根归一化到稳定尺度,再乘一个可学习的缩放向量 weight,让模型微调每一维的强弱。
- PyTorch 里 weight 常初始化成 0(或极小值)。标准写法 y = x_norm · w,此时 w=0 → 输出被乘成 0,等于把这一层“掐断”了。
- Gemma 改成 y = x_norm · (1 + w)。w=0 时 (1+0)=1,相当于“先什么都不缩放、原样通过”。
- 工程细节:统计量要在 FP32 下算,最后 type_as(x) 转回原精度,避免半精度数值不稳。
图解原理
把缩放因子的“默认值”从 0 挪到 1。标准写法里参数学的是“我要把这维放大到多少”(从 0 起步很尴尬);Gemma 写法里参数学的是“我要在默认 1 的基础上,多一点还是少一点”。训练刚开始 w≈0,整层就是一个老老实实的纯归一化,梯度平滑、不会一上来就把信号清零。
weight 不再表示“绝对缩放值”,而表示“相对默认 1 的偏移”。初始化为 0 时就是健康默认。
notebook 里前面的归一化已经帮你铺好;TODO 只需要把缩放写对,并转回输入精度。
写成 1+w 后,参数仍能从 0 开始学习偏移,weight decay 拉向 0 时也代表“回到默认 scale=1”,不会把层拉向清零。
当 self.weight=0,输出应该等于纯 RMSNorm 结果;如果输出接近 0,说明你写成了 x_norm * weight。
Gemma 的 1+w、LLaMA 的 Pre-Norm、各种初始化技巧,目标都一样:让训练早期别突然发散。一个小小的 +1,背后是大模型训练不要崩在前几千步的工程要求。
语法热身:把基准 1 写进公式
gain = nn.Parameter(torch.zeros(4))
scale = 1.0 + gain
y = x_norm * scale
y = y.type_as(x)举一反三:搬回 TODO 1
迁移口诀:Gemma 不是乘 weight,而是乘 1 + weight;最后把 dtype 还给输入。
巩固一下
判断:Gemma RMSNorm 中 weight 初始化为 0 时,实际作用在归一化结果上的缩放是多少?
回到 notebook 的作业
这里不直接写答案。你已经拿到足够输入,最后用 notebook 的 TODO 做举一反三。