【机器学习】机器学习基础_过拟合与正则化_L1_L2_Dropout详解

发布时间:2026/8/25 7:01:03
【机器学习】机器学习基础_过拟合与正则化_L1_L2_Dropout详解 文章目录一、过拟合训练集优秀真实场景翻车二、欠拟合模型连训练集都没学好三、偏差-方差为什么太简单或太复杂都不好四、用一个小实验看过拟合五、验证集发现过拟合的基本工具六、L2 正则化不要让权重太大七、L1 正则化鼓励稀疏八、Dropout训练时随机关闭一部分神经元九、Early Stopping在验证集变差前停下十、数据增强和数据清洗也是正则化十一、大模型微调中的过拟合风险十二、训练曲线怎么读十三、常见误区十四、你应该记住的最小心智模型总结大模型视角下一篇摘要模型在训练集上表现很好不代表上线后也好。过拟合指模型把训练数据里的偶然噪声、样本偏差甚至标注错误也学进去导致验证集和真实场景表现变差。正则化的目标不是让模型“少学习”而是让模型学到更稳定、更可泛化的规律。本文从训练/验证曲线讲起解释过拟合、欠拟合、偏差-方差、L1、L2、Weight Decay、Dropout、Early Stopping、数据增强和大模型微调中的过拟合风险并用小实验演示复杂模型如何把噪声也拟合进去。前置知识第 5 篇梯度下降第 7 篇损失函数阅读时间约 65 分钟代码环境Python 3.10numpy 1.24torch 2.0入门导读先抓住主线机器学习真正关心的是泛化模型在没见过的数据上表现如何。训练时我们能看到训练集 loss但产品面对的是新用户、新文档、新问题、新分布。如果模型只记住训练样本训练 loss 会很低但真实效果会很差。过拟合的典型现象训练 loss 持续下降 验证 loss 先下降后上升 训练指标很好 验证/线上指标变差正则化就是一组降低过拟合风险的方法。读完先达到这个程度就够了能区分过拟合和欠拟合能看懂训练集/验证集曲线能解释 L1、L2、Weight Decay 的直觉差异能理解 Dropout 训练和推理行为不同能知道 Early Stopping 和验证集为什么重要能理解大模型微调时为什么也会过拟合。带着这 3 个问题读为什么训练 loss 越低有时验证效果反而越差L1、L2、Dropout 分别在约束什么大模型已经很强为什么小数据微调仍然容易过拟合一、过拟合训练集优秀真实场景翻车过拟合指模型对训练数据拟合得太细学到了训练集中特有的噪声和偶然模式。例如你训练一个垃圾邮件分类器训练集中很多垃圾邮件都包含某个推广词。模型可能学到只要出现这个词就判垃圾邮件如果真实场景里正常邮件也会出现这个词模型就会误判。过拟合不是模型“学太多知识”而是学到了不该泛化的细节。常见信号训练 loss 很低验证 loss 高训练 accuracy 很高验证 accuracy 低模型对训练样本回答很准对新样本不稳小数据集上训练很多 epoch 后效果变差。二、欠拟合模型连训练集都没学好欠拟合是另一端模型能力不足或训练不充分连训练集规律都学不好。常见原因模型太简单特征不足训练时间太短学习率太小或优化失败正则化太强数据标签噪声太大loss 或输入处理有问题。判断训练 loss 高 验证 loss 也高 训练和验证都不好过拟合和欠拟合的处理方向不同。现象可能措施欠拟合增大模型、训练更久、减弱正则、改特征过拟合增加数据、加强正则、早停、降低模型容量不要一看到验证差就加正则。先看训练集有没有学好。三、偏差-方差为什么太简单或太复杂都不好偏差和方差是理解泛化的经典框架。高偏差模型太简单学不到真实规律训练和验证都差。高方差模型太灵活对训练数据变化很敏感训练好但验证差。直觉欠拟合偏差高 过拟合方差高正则化通常是在降低方差但可能增加偏差。也就是说正则化太弱会过拟合正则化太强会欠拟合。调参就是在表达能力和泛化能力之间找平衡。四、用一个小实验看过拟合我们用多项式拟合带噪声的数据。低阶多项式可能欠拟合高阶多项式可能过拟合。importnumpyasnp np.random.seed(0)xnp.linspace(-3,3,20)ynp.sin(x)0.2*np.random.randn(len(x))fordegreein[1,3,12]:coeffnp.polyfit(x,y,degdegree)prednp.polyval(coeff,x)msenp.mean((pred-y)**2)print(fdegree{degree}, train_mse{mse:.4f})你会看到高阶多项式训练误差可能更低但它可能是在拟合噪声。如果你在更密集的新点上观察曲线高阶模型可能剧烈抖动。这就是过拟合直觉训练集上看起来很好但学到的是不稳定模式。五、验证集发现过拟合的基本工具为了判断模型是否泛化需要把数据拆成训练集 train用于更新参数 验证集 validation用于调参和早停 测试集 test最终报告效果训练集 loss 只能说明模型对训练数据越来越熟。验证集 loss 才能更接近“没见过的数据”表现。典型曲线欠拟合train loss 高val loss 高 正常训练train loss 降val loss 也降 过拟合train loss 继续降val loss 开始升如果没有验证集你很难发现模型什么时候开始记噪声。注意数据泄漏如果验证集内容出现在训练集中验证指标会虚高。六、L2 正则化不要让权重太大L2 正则在 loss 里加入权重平方和L o s s t o t a l L o s s t a s k λ ∑ i w i 2 Loss_{total} Loss_{task} \lambda \sum_i w_i^2Losstotal​Losstask​λi∑​wi2​它鼓励权重不要过大。直觉如果模型需要非常大的权重才能拟合训练集可能是在追逐噪声。L2 会让模型偏向更平滑、更稳定的解。NumPy 示例importnumpyasnp wnp.array([0.5,-2.0,3.0])lambda_0.01l2_penaltylambda_*np.sum(w**2)print(l2_penalty)L2 正则和 Weight Decay 是同一件事吗不完全是。严格地说L2 正则是在 loss 里显式加一项λ ∑ i w i 2 \lambda\sum_i w_i^2λ∑i​wi2​让梯度下降顺便把权重推小Weight Decay是优化器每步更新时直接把参数乘以( 1 − λ ⋅ l r ) (1-\lambda\cdot lr)(1−λ⋅lr)与 loss 的梯度解耦。在普通 SGD中这两种写法数学上等价所以历史上常被混用。但在Adam/AdamW这类自适应优化器中L2 正则项也会被 Adam 的一阶/二阶动量估计缩放导致大权重反而衰减不动AdamW 把 weight decay 从梯度里拆出来直接作用在参数上这样才有稳定的衰减效果。因此大模型训练里推荐用AdamW 的 decoupled weight decay。PyTorchoptimizertorch.optim.AdamW(model.parameters(),lr3e-4,weight_decay0.01,)七、L1 正则化鼓励稀疏L1 正则加入权重绝对值和L o s s t o t a l L o s s t a s k λ ∑ i ∣ w i ∣ Loss_{total} Loss_{task} \lambda \sum_i |w_i|Losstotal​Losstask​λi∑​∣wi​∣L1 的特点是鼓励一部分权重变成 0从而得到稀疏模型。稀疏的好处特征选择模型更简单某些场景更可解释。但 L1 在深度学习大模型训练中不如 L2/weight decay 常见。它更常见于线性模型、特征选择或希望显式稀疏的场景。代码l1_penaltylambda_*np.sum(np.abs(w))print(l1_penalty)L1 和 L2 都是在 loss 中加入额外约束但它们偏好的参数形态不同L1 偏稀疏L2 偏小而平滑。八、Dropout训练时随机关闭一部分神经元Dropout 在训练时随机把一部分神经元输出置 0。直觉不要让模型过度依赖某几条路径。PyTorchimporttorchimporttorch.nnasnn xtorch.ones(8)dropoutnn.Dropout(p0.5)dropout.train()print(train:,dropout(x))dropout.eval()print(eval:,dropout(x))训练时输出会随机有 0推理时不会随机关闭。PyTorch 使用inverted dropout训练时会把保留下来的值除以保留概率( 1 − p ) (1-p)(1−p)使期望不变。这样推理时就不需要额外缩放。可以用下面的代码直观感受这个 scalingimporttorchimporttorch.nnasnn torch.manual_seed(0)xtorch.ones(10)dropoutnn.Dropout(p0.5)# 训练时约一半置 0保留下来的乘 1/(1-0.5)2dropout.train()outdropout(x)print(train 输出:,out)# 未被丢弃的位置值是 2.0不是 1.0print(train 均值:,out.mean().item())# 均值仍然接近 1.0期望不变dropout.eval()print(eval 输出:,dropout(x))# 全 1不做缩放关键点inverted dropout 把补偿缩放提前放在训练时因此推理阶段.eval()后 forward 完全等价于没有 Dropout也就无需在部署时改动模型结构。Dropout 常用于小数据或过拟合明显的场景。但大模型预训练中Dropout 不一定很大有些模型甚至使用很小的 dropout。因为大规模数据本身已经提供了强正则效果。九、Early Stopping在验证集变差前停下Early Stopping 是非常实用的正则化方法。做法每隔一段时间评估验证集保存验证指标最好的 checkpoint如果验证指标长时间不提升就停止训练。伪代码best_val_lossfloat(inf)patience3bad_epochs0forepochinrange(100):train_one_epoch()val_lossevaluate()ifval_lossbest_val_loss:best_val_lossval_loss save_checkpoint()bad_epochs0else:bad_epochs1ifbad_epochspatience:breakEarly Stopping 的关键是验证集可靠。如果验证集太小、噪声太大或和真实场景不一致早停判断也会不可靠。十、数据增强和数据清洗也是正则化正则化不只在公式里。增加数据、多样化数据、清洗噪声本质上也能改善泛化。常见方法图像裁剪、翻转、颜色扰动文本回译、同义改写、模板扩充语音加噪、变速代码不同实现方式、单测增强大模型 SFT增加任务多样性、去除低质量样本。如果训练集和真实场景差异很大单靠 L2 或 Dropout 很难解决问题。数据分布匹配往往比调正则更重要。十一、大模型微调中的过拟合风险大模型参数很多即使只做 LoRA 微调也可能在小数据集上过拟合。常见表现训练集回答越来越像标注格式但泛化差模型开始机械复述训练样本对训练集中常见模板依赖过强验证集 loss 不再下降原模型通用能力下降出现灾难性遗忘。常见缓解使用高质量、多样化数据控制 epoch不要反复刷小数据降低学习率使用 weight decay使用 dropout 或 LoRA dropout做 early stopping保留通用指令数据混合训练用独立验证集评估。对于大模型微调数据质量通常比数据量更关键。少量高质量数据可能比大量低质量模板数据更好。十二、训练曲线怎么读可以用这张表快速判断训练 loss验证 loss可能问题方向高高欠拟合增大模型、训练更久、减弱正则低高过拟合加强正则、更多数据、早停不降不降学习率/数据/loss 问题先排查训练流程震荡震荡学习率过大或数据噪声降学习率、增 batch、检查数据训练降验证先降后升典型过拟合保存最佳 checkpoint不要只看最终一个数。曲线形状能告诉你模型经历了什么。十三、常见误区误区 1训练集效果越好模型越好。真正关心的是泛化。训练集太好但验证差往往是过拟合。误区 2正则化就是让模型学得少。正则化是让模型学更稳定的规律而不是记住噪声。误区 3L1、L2、Weight Decay 都一样。L1 鼓励稀疏L2 鼓励小权重AdamW 的 weight decay 是解耦衰减工程行为不同。误区 4Dropout 推理时也随机关闭。推理时应model.eval()Dropout 关闭随机行为。误区 5大模型不会过拟合。大模型在小数据微调、低质量数据、重复模板数据上非常容易过拟合。误区 6验证集可以反复调到最好后当测试集。验证集被反复用于调参后也会被间接过拟合。最终评估应保留独立测试集。十四、你应该记住的最小心智模型过拟合和正则化可以这样记欠拟合训练集都学不好 过拟合训练集很好新数据不好 正则化限制模型记噪声提升泛化常见正则手段L2/Weight Decay限制权重过大 L1鼓励稀疏 Dropout减少路径依赖 Early Stopping在验证集变差前停止 数据增强/清洗让训练分布更接近真实场景判断优先看train loss 和 val loss 的相对走势总结过拟合是模型在训练集上表现很好但在验证集或真实场景中表现变差。欠拟合则是模型连训练集都没学好。正则化通过限制模型复杂度、约束权重、随机扰动训练路径、早停和改善数据分布帮助模型学到更可泛化的规律。L2/Weight Decay 鼓励权重不要过大L1 鼓励稀疏Dropout 减少神经元之间的过度依赖Early Stopping 用验证集防止训练过头。大模型微调同样会过拟合尤其是在小数据、重复模板和低质量标注上。第一遍记住一句话训练集表现证明模型记住了数据验证集表现才更接近模型是否学到了规律。大模型视角后续你看 SFT、LoRA、DPO、RAG 评估时过拟合都会出现。大模型不是越训越好尤其是微调阶段训练太久或数据太窄会损害泛化和通用能力。高质量验证集和早停是大模型工程里非常现实的安全线。下一篇批归一化与层归一化为什么大模型选 LayerNorm—— 正则化关注泛化归一化关注训练稳定。下一篇看 BatchNorm、LayerNorm、RMSNorm 如何稳定深层网络。