DL——为什么Dropout能防止过拟合


关于Dropout

定义

  • dropout是指在深度学习网络的训练过程中,对于神经网络单元,按照一定的概率将其暂时从网络中丢弃。注意是暂时 ,对于随机梯度下降来说,由于是随机丢弃,故而每一个mini-batch都在训练不同的网络。(因为每一轮被丢弃的神经元不同)

应用

  • 在CNN中防止过拟合的效果明显
  • 一般选择0.5比较好,因为0.5的时候Dropout随机生成的网络结果最多,但是实际使用中一般需要调节甚至变化
    • 亲测: 在使用VGG16模型迁移学习来分类Dogs2Cats数据集时,先使用0.5,然后再使用0.2略优于一直使用0.5的情况

Why能防止过拟合?

  • 虽然Dropout在实际应用中的确能防止过拟合,但是关于Dropout防止过拟合的原理,大家众说纷纭
  • 下面介绍两个主流的观点

组合派观点

集成学习方法论
  • 传统神经网络的缺点: 费时容易过拟合
  • 过拟合是很多机器学习的通病
  • 一种修改模型的过拟合解决思路是: 采用Ensemble方法的Bagging方法(平均多个模型的结果,从而能够减少模型的方差,同时减轻过拟合)或者Boosting方法(减小模型的偏差,同时能减轻过拟合?[待更新]),即训练多个模型做组合
  • 但是解决了过拟合后, 费时就成为一个大问题,不仅训练起来费时,测试起来多个模型也很费时
  • Dropout能同时解决以上问题:
    • Dropout的示意图如下: 左图是原图结构,右图是加入Dropout层的
    • 从图上可以看出,有了Dropout,训练的模型就可以看成是多个模型的组合,最终预测时丢弃Dropout即可的到所有模型的组合,从而实现类似于Ensemble方法的Bagging方法,实现了多个模型的组合
动机论
  • 虽然直观上看dropout是ensemble在分类性能上的一个近似,然而实际中,dropout毕竟还是在一个神经网络上进行的,只训练出了一套模型参数。那么他到底是因何而有效呢?

  • 首先分析一个小故事

在自然界中,在中大型动物中,一般是有性繁殖,有性繁殖是指后代的基因从父母两方各继承一半。但是从直观上看,似乎无性繁殖更加合理,因为无性繁殖可以保留大段大段的优秀基因。而有性繁殖则将基因随机拆了又拆,破坏了大段基因的联合适应性。但是自然选择中毕竟没有选择无性繁殖,而选择了有性繁殖,须知物竞天择,适者生存。我们先做一个假设,那就是基因的力量在于混合的能力而非单个基因的能力。不管是有性繁殖还是无性繁殖都得遵循这个假设。为了证明有性繁殖的强大,我们先看一个概率学小知识

  • 基本思想: 有性繁殖的方式不仅仅可以将优秀的基因传下来,还可以降低基因之间的联合适应性,使得复杂的大段大段基因联合适应性变成比较小的一个一个小段基因的联合适应性

  • dropout也能达到同样的效果,它强迫一个神经单元,和随机挑选出来的其他神经单元共同工作,达到好的效果。消除减弱了神经元节点间的联合适应性,增强了泛化能力

噪声派观点

  • 对于每一个dropout后的网络,进行训练时,相当于做了Data Augmentation ,因为,总可以找到一个样本,使得在原始的网络上也能达到dropout单元后的效果。 比如,对于某一层,dropout一些单元后,形成的结果是(1.5,0,2.5,0,1,2,0),其中0是被drop的单元,那么总能找到一个样本(新样本),使得结果也是如此。这样,每一次dropout其实都相当于增加了样本
噪声派观点总结
  • 将dropout映射回得样本训练一个完整的网络,可以达到dropout的效果
  • dropout由固定值变为一个区间,可以提高效果
  • 将dropout后的表示映射回输入空间时,并不能找到一个样本 x 使得所有层都能满足dropout的结果,但可以为每一层都找到一个样本,这样,对于每一个dropout,都可以找到一组样本可以模拟结果

Dropout其他需要注意的点

  • 数据量小的时候,dropout效果不好,数据量大了,dropout效果好
  • dropout的缺点就在于训练时间是没有dropout网络的2-3倍

Dropout训练和预测阶段输出分布一致性保证

  • 保持分布一致的必要性 :Dropout操作会改变神经元输出分布,在 Dropout 的训练和预测阶段保证输出均值一致,能使得模型在训练和预测时具有相同的统计特性,从而提高模型的泛化能力
  • 方式 :通过调整训练和预测阶段的神经元输出比例,可以保证确保两者输出分布的一致性实现方式
  • 方法一:训练阶段缩放(Inverted Dropout)
    • 训练阶段:以概率 \(p\) 失活部分神经元,同时对被激活的所有神经元,对输出均乘以 \(\frac{1}{1-p}\)
    • 预测阶段:在预测阶段,不进行神经元的随机丢弃,而是直接使用训练好的模型进行推理。此时,由于在训练阶段已经对神经元的输出进行了缩放,所以在预测阶段不需要额外的操作,模型的输出均值就会与训练阶段保持一致
  • 方法二:预测阶段缩放(Vanilla Dropout)
    • 训练阶段:以概率 \(p\) 失活部分神经元,不调整输出
    • 预测阶段:激活所有神经元,且对被激活的所有神经元,对输出均乘以 \(1-p\)
  • 注:常规的Dropout实现均保证了训练和推理阶段分布一致,测试代码如下:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    import torch
    import torch.nn as nn

    x = torch.randn(8)
    dropout = nn.Dropout(p=0.5)

    dropout.train()
    train_output = dropout(x)
    print("训练阶段输出:", train_output)

    dropout.eval()
    test_output = dropout(x)
    print("预测阶段输出:", test_output)

    # 训练阶段输出: tensor([ 0.0000, -1.0198, -1.4742, -0.0408, 1.8699, 0.0000, -0.0000, -0.0000])
    # 预测阶段输出: tensor([ 0.1318, -0.5099, -0.7371, -0.0204, 0.9350, 0.9006, -0.2567, -0.7391])