# Summary
问题:模型在训练集上表现很好,但在测试集上表现差(过拟合)
解决:正则化 = 限制模型复杂度,防止过拟合
正则化(Regularization):是一种让模型“别太过度的”的方法,
- 英文 regular 本义是 “有规律的、规则的、平滑的、不过度的”。
- regularize = “让它变得 regular”,即“让模型参数别太极端、太乱”。
- 所以 regularization 应该直译成:规则化 / 规整化 / 平滑化。
1. [[Weight Decay 权重衰减]] 是一种正则化方法,它惩罚过大的权重值。
2. [[dropout]]也是一种正则化方法
pre Norm 而不是 post Norm是现代模型主流做法:未经世事的时候有个泛化不极端的三观更好一些
现在大模型训练很少使用dropout,所有的大模型都采用了 weight decay
# Notes
## 一、不是所有参数都需要正则化的
|策略|训练 Loss|验证 Loss|说明|
|---|---|---|---|
|所有参数都 decay|2.5|3.2|过度正则化,欠拟合|
|选择性 decay|2.1|2.3|✅ 最佳平衡|
|没有任何 decay|1.8|3.5|过拟合|
---
## 二、Post-Norm vs Pre-Norm
### 2.1 Post-Norm (原始 Transformer)
```Java
输入 → Multi-Head Attention → Add & Norm → FFN → Add & Norm → 输出
```
- 先做子层运算(Attention/FFN)
- 再加残差连接
- 最后做归一化
这是 2017 年原始 Transformer 论文("Attention is All You Need")的设计。
### 2.2 Pre-Norm (现代主流)
```Java
输入 → Norm → Multi-Head Attention → Add → Norm → FFN → Add → 输出
```
- 先做归一化
- 再做子层运算
- 最后加残差连接
### 2.3 为什么 LLM 用 Pre-Norm?
训练稳定性更好:
- Post-Norm 在深层网络(几十层)容易梯度爆炸/消失
- Pre-Norm 的梯度传播更平滑,不需要太精细的学习率调整
- 可以不用 warmup 或用更少的 warmup 步数
更容易扩展:
- 堆叠到 100+ 层时,Pre-Norm 依然稳定
- GPT、LLaMA、Llama 等主流 LLM 都用 Pre-Norm
代价:
- 理论上 Post-Norm 的表达能力可能稍强一点
- 但在大规模训练中,稳定性比这点性能差异更重要
实际应用
现在几乎所有大语言模型都默认用 Pre-Norm,比如:
- GPT 系列
- LLaMA/Llama 系列
- PaLM
- BLOOM
不仅在训练数据上表现好,而且能在新输入上泛化好的算法。在机器学习中,许多策略被显式地设计来减少测试误差(可能会以增大训练误差为代价)。这些策略被统称为正则化。我们将在后文看到,深度学习工作者可以使用许多不同形式的正则化策略。事实上,开发更有效的正则化策略已成为本领域的主要研究工作之一。
在深度学习的背景下,大多数正则化策略都会对估计进行正则化。估计的正则化以偏差的增加换取方差的减少。一个有效的正则化是有利的“交易”,也就是能显著减少方差而不过度增加偏差。我们在第5章中讨论泛化和过拟合时,主要侧重模型族训练的3种情况:(1)不包括真实的数据生成
(Normalization)和正则化(Regularization)是两个不同的概念,虽然名字相似,但目的和作用完全不同。
不是归一化
我用最通俗的方式来解释这两个概念:
# 用考试来打比方
## 正则化 = 防止"死记硬背"
想象一个学生准备考试:
过拟合的学生:
- 把所有练习题的答案都背下来了
- 练习题100分,但真实考试只有60分
- 因为他只是死记硬背,没真正理解
正则化就像老师的对策:
- L1/L2正则化:"不许写太复杂的解题步骤,越简单越好"
- Dropout:"考试时随机遮住你一半的笔记,逼你真正理解"
- 早停:"只给你3天复习时间,防止你背答案"
- 数据增强:"我把题目换个问法,看你是不是真懂了"
## 归一化 = 统一"计量单位"
想象你在算一道数学题:
没归一化的情况:
```Java
小明的零花钱:5元
小明家到学校距离:3000米
小明的考试成绩:98分
问:哪个数字最重要?
```
计算机看到3000最大,以为距离最重要!
归一化后:
```Java
零花钱:0.05 (在0-100元范围内)
距离:0.3 (在0-10000米范围内)
成绩:0.98 (在0-100分范围内)
```
现在计算机知道成绩(0.98)才是最重要的!
# 更生活化的例子
## 正则化 = 健身时的"适可而止"
- 不用正则化:疯狂练某块肌肉→肌肉拉伤,其他部位薄弱
- 用正则化:均衡训练→整体协调,真正强壮
具体方法:
- L2正则化:每块肌肉都练,但都不要练过头
- L1正则化:只练最重要的几块肌肉,其他的放弃
- Dropout:今天不练腿,明天不练胸,强迫其他部位代偿
## 归一化 = 做菜时的"统一切法"
做菜时如果:
- 土豆切成大块(10分钟能熟)
- 胡萝卜切成丝(2分钟就熟)
- 肉切成厚片(15分钟才熟)
结果:要么土豆没熟,要么胡萝卜糊了
归一化就是:把所有食材切成差不多大小,这样能同时熟!
# 用神经网络训练打比方
## 为什么模型会"过拟合"?
就像一个AI在学认猫:
- 训练集:看了100张你家橘猫的照片
- 学歪了:以为"猫=橘色+胖+你家沙发"
- 测试时:看到黑猫就不认识了
正则化:强迫AI不要记住"你家沙发"这种无关细节
## 为什么需要"归一化"?
想象AI同时学习:
- 特征1:猫的体重(5-10公斤)= 数值范围5-10
- 特征2:猫的胡须数量(40-50根)= 数值范围40-50
- 特征3:猫叫声频率(700-1000赫兹)= 数值范围700-1000
没归一化:AI以为频率最重要(因为数字最大)归一化后:所有特征都变成0-1之间,AI能公平对待每个特征
# 一句话总结
- 正则化:防止模型"死记硬背"训练数据
- 像老师防止学生背答案
- 像健身防止练偏
- 目的:让模型真正"理解"而不是"记住"
- 归一化:把不同尺度的数据调整到同一标准
- 像把不同货币换算成人民币
- 像把食材切成同样大小
- 目的:让模型能公平对待所有特征
# 实际效果
```python
# 不用正则化
训练集准确率:99% # 背得很熟!
测试集准确率:70% # 一到考试就露馅
# 用了正则化
训练集准确率:92% # 没背答案
测试集准确率:88% # 真正理解了
# 不用归一化
训练100轮才收敛 # 像开车没放手刹
# 用了归一化
训练10轮就收敛 # 轻松多了
```
# 记忆口诀
正则化:
> "别学太死,灵活一点"(防止过拟合)
归一化:
> "大家站同一起跑线"(统一尺度)
这样理解是不是清楚多了?
# 1. 归一化 (Normalization)
目的:加速训练、稳定梯度、改善收敛
## 常见类型
- Batch Normalization (BN):对每个批次的特征进行标准化
- Layer Normalization (LN):对每个样本的特征进行标准化(Transformer 常用)
- RMSNorm:Layer Norm 的简化版(你测试中用到的)
- Group Normalization:介于 BN 和 LN 之间
## 作用原理
```python
# Layer Normalization 示例
def layer_norm(x, gamma, beta, eps=1e-5):
mean = x.mean(dim=-1, keepdim=True)
var = x.var(dim=-1, keepdim=True)
x_normalized = (x - mean) / torch.sqrt(var + eps)
return gamma x_normalized + beta
```
# 2. 正则化 (Regularization)
目的:防止过拟合、提高泛化能力
## 常见类型
- L1/L2 正则化:在损失函数中添加权重惩罚项
- Dropout:训练时随机丢弃部分神经元
- 权重衰减 (Weight Decay):AdamW 中的 weight decay
- 数据增强:也是一种正则化手段
## 作用原理
```python
# L2 正则化示例
loss = cross_entropy_loss + lambda sum(p2 for p in parameters)
# Dropout 示例
def dropout(x, p=0.5, training=True):
if training:
mask = torch.rand_like(x) > p
return x mask / (1 - p)
return x
```
# 3. 关键区别
|方面|归一化 (Normalization)|正则化 (Regularization)|
|---|---|---|
|主要目的|加速训练、稳定梯度|防止过拟合|
|作用对象|激活值/特征|模型参数/结构|
|使用时机|前向传播中|训练时(测试时通常关闭)|
|对性能影响|提升训练速度和稳定性|提升泛化能力|
# 4. 在 Transformer 中的应用
```python
class TransformerBlock:
def __init__(self):
self.norm1 = RMSNorm() # 归一化
self.norm2 = RMSNorm() # 归一化
self.dropout = Dropout(p=0.1) # 正则化
def forward(self, x, training=True):
# 归一化稳定训练
x = x + self.dropout(self.attention(self.norm1(x)), training)
x = x + self.dropout(self.ffn(self.norm2(x)), training)
return x
```
所以在你的测试中:
- `test_rmsnorm` 测试的是归一化功能
- `test_gradient_clipping` 也可以看作一种训练稳定技术
- 而 AdamW 中的 weight decay 则是正则化技术
两者经常一起使用,共同提升模型的训练效果和最终性能!