正则化(机器学习、深度学习)

介绍

正则化(Regularization)是 为防止模型过拟合、提升泛化能力,而设计的一系列策略/手段

核心逻辑

在模型训练过程中引入“额外约束”,平衡模型的“拟合能力”和“泛化能力”——既让模型能学到训练数据的规律,又不让它过度记住训练数据的噪声/特例。

类比

可以用一个简单的比喻理解:

  • 未正则化的模型:一个死记硬背的学生,能背下所有练习题,但换个题型就不会;
  • 正则化后的模型:一个理解知识点的学生,掌握核心规律,能应对新题型。

过拟合的根源 & 正则化的解决思路

先明确过拟合的核心原因,才能理解正则化的作用逻辑:

过拟合根源 正则化的解决思路
模型复杂度太高(参数过多) 降低模型复杂度(如Dropout丢弃神经元、L1稀疏化权重)
训练数据少/有噪声 扩充有效数据(数据增强)、惩罚噪声拟合(权重衰减)
训练迭代过多 提前终止训练(早停)

正则化的分类

按约束方式,正则化手段可分为三大类:

(1)参数约束类

直接对模型的可训练参数(权重/偏置)施加约束,避免参数取值极端:

  • L2正则化(权重衰减):

    • 原理:损失函数 += λ * ||W||²(权重的L2范数),惩罚过大的权重,让权重分布更平滑;
    • 特点:最常用、最基础,几乎所有模型都适用;
    • PyTorch实现:优化器中weight_decay参数。
  • L1正则化:

    • 原理:损失函数 += λ * ||W||₁(权重的L1范数),让部分权重趋近于0,实现特征稀疏化;
    • 特点:适合高维特征、小样本场景,使用频率低于L2。

(2)结构约束类

通过改变模型的训练结构,降低模型对局部特征的依赖:

  • Dropout(随机丢弃):

    • 原理:训练时随机丢弃部分神经元,迫使模型不依赖单一神经元,学习更鲁棒的特征;
    • 特点:深度学习专属,尤其适合全连接层、Transformer的FFN层。
  • 归一化(BN/LN):

    • 原理:对层输出做均值0、方差1的归一化,稳定训练过程,间接降低过拟合风险;
    • 特点:既是训练加速工具,也是轻量正则化手段,Transformer中必用LayerNorm。

(3)训练过程约束类

从训练流程上限制模型的过度拟合:

  • 早停(Early Stopping):

    • 原理:监控验证集性能,当性能不再提升时停止训练,避免模型“死记”训练数据;
    • 特点:所有模型必备,无额外计算成本。
  • 数据增强:

    • 原理:对训练数据做随机变换(如图像翻转、文本同义词替换),扩充有效训练样本;
    • 特点:从源头解决“数据少”的问题,泛化效果最好的正则化手段之一。

正则化原则

(1)强度调优

正则化强度(如Dropout的p、权重衰减的λ)需适中:

  • 过强:模型欠拟合(训练集/验证集效果都差);
  • 过弱:模型仍过拟合(训练集效果好,验证集效果差);
  • 常用经验值:
    • 权重衰减:1e-5 ~ 1e-3;
    • Dropout:0.1 ~ 0.5(大模型用0.1~0.3,小模型用0.3~0.5)。

(2)组合使用

单一正则化效果有限,实际项目中通常组合使用:

  • 基础组合:权重衰减(L2) + 早停;
  • 深度学习组合:权重衰减 + Dropout + LayerNorm + 数据增强;
  • 小样本组合:权重衰减 + L1 + 早停 + 数据增强。

(3)推理阶段注意事项

部分正则化工具在推理时需关闭:

  • Dropout、BatchNorm:通过model.eval()切换到评估模式;
  • 权重衰减、L1、早停、数据增强:仅作用于训练阶段,推理无影响。

简单示例

正则化训练流程

import torch
import torch.nn as nn
import torch.optim as optim

# 1. 定义带正则化的模型
class SimpleModel(nn.Module):
    def __init__(self):
        super().__init__()
        self.fc1 = nn.Linear(10, 20)
        self.ln = nn.LayerNorm(20)  # 归一化(轻量正则化)
        self.dropout = nn.Dropout(p=0.2)  # Dropout正则化
        self.fc2 = nn.Linear(20, 2)

    def forward(self, x):
        x = self.ln(torch.relu(self.fc1(x)))
        x = self.dropout(x)  # 训练时生效
        return self.fc2(x)

# 2. 初始化模型、优化器(权重衰减=L2正则化)
model = SimpleModel()
optimizer = optim.Adam(model.parameters(), lr=1e-3, weight_decay=1e-4)  # L2正则化
loss_fn = nn.CrossEntropyLoss()

# 3. 训练流程(含早停)
best_val_loss = float('inf')
patience = 5
counter = 0

for epoch in range(100):
    # 训练模式(启用Dropout/LN训练模式)
    model.train()
    # 模拟训练数据(实际需替换为真实数据加载)
    x_train = torch.randn(32, 10)
    y_train = torch.randint(0, 2, (32,))
    output = model(x_train)
    loss = loss_fn(output, y_train)

    # 反向传播
    optimizer.zero_grad()
    loss.backward()
    optimizer.step()

    # 验证阶段(早停逻辑)
    model.eval()
    with torch.no_grad():
        x_val = torch.randn(16, 10)
        y_val = torch.randint(0, 2, (16,))
        val_output = model(x_val)
        val_loss = loss_fn(val_output, y_val)

    # 早停判断
    if val_loss < best_val_loss:
        best_val_loss = val_loss
        torch.save(model.state_dict(), 'best_model.pth')
        counter = 0
    else:
        counter += 1
        if counter >= patience:
            print("早停触发,停止训练")
            break

# 4. 推理阶段(关闭正则化)
model.eval()
with torch.no_grad():
    x_test = torch.randn(1, 10)
    pred = model(x_test)
    print("推理结果:", pred.argmax(dim=1).item())

总结

  1. 正则化的核心是平衡拟合与泛化,通过添加约束防止模型过拟合;
  2. 正则化分为参数约束(L1/L2)、结构约束(Dropout/LN)、训练约束(早停/数据增强)三类;
  3. 实践中需组合使用正则化工具,并调优强度,推理时关闭Dropout等训练专属正则化。

原文出处:/show_1GW2cw5fNl9t.html