# 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 则是正则化技术 两者经常一起使用,共同提升模型的训练效果和最终性能!