过拟合与正则化

last modify

过拟合与欠拟合

过拟合

现象

  • 训练集效果很好,但是验证集很差,这种现象称为过拟合,表现为高方差

常见解决方法

  • 训练数据不足

    • 数据增强

      • NLP-EDA

      • CV-切割、裁剪、旋转

      • Mixup

    • 对抗训练

  • 训练数据中存在噪声:

    • 交叉验证

    • 集成学习(Bagging)

  • 模型复杂度较高:

    • 正则化项

    • Dropout

    • Early Stoping

    • 降低模型复杂度

      • 减少模型参数

      • 使用简单模型

欠拟合

现象

  • 训练集验证集的效果都很差,这种现象称为欠拟合,表现为高偏差

常见解决方法

  • 特征工程

    • FM、FFM

  • 集成学习(Boosting)

  • 提高模型复杂度

    • 增加模型参数

    • 使用复杂模型

参考

常见正则化方法

数据增强

  • 简单数据增强

    • NLP(EDA:增删改、替换)

    • 图像(切割、裁剪、旋转等)

  • 数据融合

    • Mixup

为损失函数添加正则化项

  • 常见的正则化项有 L1、L2 正则项;

参考

L1 正则化

L2 正则化

提前结束训练(Early Stopping)

  • 当模型在验证集上的性能开始下降时,提前结束训练;

  • 一般会配合交叉验证来使用;

参考

Dropout

作用

  • 提升泛化能力,减少过拟合;

原理

  • Dropout 提供了一种廉价的 Bagging 集成近似(模型平均);

思想

  • 遗传算法,通过随机变异(随机删除神经元),来促使整个种群的进化;

常见问题

Dropout 在训练和测试时有什么区别?为什么?

  • 训练时,经过 Dropout 的输出值会乘以 $\frac{1}{1-p}$;测试时不会。

  • 经过 Dropout 后,输入 x 的期望输出将变为 p*0 + (1-p)*x = (1-p)xp 的可能变为 0,1-p 的可能保持不变);

  • 为了还原未经过 Dropout 的期望值,故需要乘以 $\frac{1}{1-p}$

为什么 Dropout 能防止过拟合?

  • 直观上,Dropout 会使部分神经元失活,减小了模型容量,从而降低了模型的拟合能力;

  • 宏观上,Dropout 提供了一种廉价的 Bagging 集成方法(共享权重);

  • 隐藏单元经过 Dropout 后,必须学习与不同采样的神经元合作,使得神经元具有更强的健壮性(减少神经元之间复杂的共适应关系);

PyTorch 实现

  • 【训练阶段】前向传播时,对每个神经元以概率 p 失活(即乘以 0.),而其他未失活的单元则乘以 1/(1-p)(放大)

  • 【测试阶段】使 dropout 失效,即正常使用所有神经元;

class Dropout(nn.Module):

    def __init__(self, p):
        super().__init__()
        self.p = p  # 以 p 的概率丢弃

    def forward(self, x):
        if not self.training:
            return x
        
        mask = (torch.rand(x.shape) > self.p).float()
        return x * mask / (1.0 - self.p)

R-Drop

[2106.14448] R-Drop: Regularized Dropout for Neural Networks

动机 & 作法

  • 尝试解决 Dropout 在训练与预测时使用不一致的问题;

  • Dropout 本身不是已经尝试解决了这个不一致问题吗?它的解决方案有什么问题?

    • Dropout 通过缩放神经元的输出值来缓解训练与预测时不一致的影响。Dropout 的本意是为了得到一个“模型平均”的结果,而这种通过缩放来还原实际上是一种“权重平均”(见 Dropout 的推导),这两者未必等价;

    • 具体来说,Dropout 的正确使用方式应该是预测时打开 Dropout,然后计算多次预测的平均值作为结果;但实际并不是这样使用的。

  • R-Drop 是怎么解决这个问题的?

    • 通过对同一样本 Dropout 两次,然后加入 KL 散度来保持不同 Dropout 下预测结果的一致性;

  • KL 散度损失是怎么保证预测一致性的?

    • 交叉熵损失只关注目标类的得分,非目标类的得分不影响最终 loss;相当于训练目标是 “不同 Dropout 下目标类的得分都大于非目标类的得分”。

    • 举例来说 [0.5, 0.2, 0.3][0.5, 0.3, 0.2][1, 0, 0] 的交叉熵损失是一样的,都是 -log(0.5),非目标类的 0.20.3 都没有起作用;

    • KL 散度则会关注每一个类别的得分,相当于训练目标是“不同 Dropout 下每个类别的得分一致

    • 就上例来说,计算 [0.5, 0.2, 0.3][0.5, 0.3, 0.2][1, 0, 0] 的 KL 散度都会产生非零损失;

PyTorch 实现

class RDrop(nn.Module):

    def __init__(self, encoder, kl_alpha=1.0):
        super().__init__()

        self.encoder = encoder
        self.kl_alpha = kl_alpha
        self.ce = nn.CrossEntropyLoss()
        self.kl = nn.KLDivLoss()

    def forward(self, x, labels):
        logits1 = self.encoder(x)
        logits2 = self.encoder(x)
        ce_loss = (self.ce(logits1, labels) + self.ce(logits2, labels)) / 2
        kl_loss1 = self.kl(F.log_softmax(logits1, dim=-1), F.softmax(logits2, dim=-1))
        kl_loss2 = self.kl(F.log_softmax(logits2, dim=-1), F.softmax(logits1, dim=-1))
        return ce_loss + self.kl_alpha * (kl_loss1 + kl_loss2) / 2

参考

各种 Normalization

参考

Batch Normalization

per channel per batch

使用场景:CV

前向过程

μ=1mi=1mxi//batch meanσ2=1mi=1m(xiμ)2//batch variancex^i=xiμσ2+ϵ//normalizationyi=γx^i+β//scale and shift\begin{aligned} \mu &= \frac{1}{m} \sum_{i=1}^m x_i &//&\text{batch mean} \\ \sigma^2 &= \frac{1}{m} \sum_{i=1}^m (x_i-\mu)^2 &//&\text{batch variance} \\ \hat{x}_i &= \frac{x_i - \mu}{\sqrt{\sigma^2 + \epsilon}} &//&\text{normalization} \\ y_i &= \gamma \hat{x}_i + \beta &//&\text{scale and shift} \end{aligned}

PyTorch实现

def batch_norm(x, eps=1e-5):
    """x: [batch_size, time_step, channel]"""
    C = x.shape[-1]
    mean = torch.mean(x, dim=(0, 1), keepdim=True)  # [1, 1, C]
    std = torch.std(x, dim=(0, 1), unbiased=False, keepdim=True)  # [1, 1, C]
    gamma = torch.nn.Parameter(torch.empty(C))
    beta = torch.nn.Parameter(torch.empty(C))
    output = gamma * (x - mean) / (std + eps) + beta
    return output

参考

Layer Normalization

per sample per layer

使用场景:NLP

前向过程

Instance Normalization

per sample per channel

作用

使用场景:CV 风格迁移

Group Normalization

per sample per group

Weight Normalization

常见问题

BN 与 LN 的区别

  • BN 在 batch 维度为归一;

  • LN 在 feature 维度做归一;

为什么 BN 一般不用于 NLP ?

对抗训练

Last updated