Dropout 是深度学习中的一种防止过拟合手段, 在面试中也经常会被问到, 因此有必要搞懂其原理.
1 Dropout 的运作方式
在神经网络的训练过程中, 对于一次迭代中的某一层神经网络, 先随机选择中的一些神经元并将其临时隐藏(丢弃), 然后再进行本次训练和优化. 在下一次迭代中, 继续随机隐藏一些神经元, 如此直至训练结束. 由于是随机丢弃, 故而每一个 mini-batch 都在训练不同的网络.
在训练时, 每个神经单元以概率 $p$ 被保留(Dropout 丢弃率为 $1-p$); 在预测阶段(测试阶段), 每个神经单元都是存在的, 权重参数 $w$ 要乘以 $p$, 输出是:$pw$. 示意图如下:
预测阶段需要乘上 $p$ 的原因:
前一层隐藏层的一个神经元在 $dropout$ 之前的输出是 $x$, 训练时 $dropout$ 之后的期望值是 $E=px+(1−p) \dot 0$; 在预测阶段该层神经元总是激活, 为了保持同样的输出期望值并使下一层也得到同样的结果, 需要调整 $x->px$. 其中 $p$ 是 Bernoulli 分布 (0-1 分布) 中值为 1 的概率.
2 Dropout 实现
如前文所述, 在训练时随机隐藏部分神经元, 在预测时必须要乘上 p. 代码如下:
- import numpy as np
- p = 0.5 # 神经元激活概率
- def train_step(X):
- """X contains the data"""
- # 三层神经网络前向传播为例
- H1 = np.maximum(0, np.dot(W1, X) + b1)
- U1 = np.random.rand(*H1.shape) < p # first dropout mask
- H1 *= U1 # drop!
- H2 = np.maximum(0, np.dot(W2, H1) + b2)
- U2 = np.random.rand(*H2.shape) < p # second dropout mask
- H2 *= U2 # drop!
- out = np.dot(W3, H2) + b3
- def predict(X):
- # ensembled forward pass
- H1 = np.maximum(0, np.dot(W1, X) + b1) * p # NOTE: scale the activations
- H2 = np.maximum(0, np.dot(W2, H1) + b2) * p # NOTE: scale the activations
- out = np.dot(W3, H2) + b3
3 反向 Dropout
一个略有不同的方法是使用反向 Dropout(Inverted Dropout). 该方法包括在训练阶段缩放激活函数, 从而使得其测试阶段保持不变. 比例因子是保持概率的倒数即 $1/p$. 所以我们换一个思路, 在训练时候对数据进行 1/p 缩放, 在训练时, 就不需要做什么了.
反向 Dropout 只定义一次模型并且只改变了一个参数 (保持 / 丢弃概率) 以使用同一模型进行训练和测试. 相反, 直接 Dropout, 必须要在测试阶段修改网络. 因为如果你不乘以比例因子 p, 神经网络的输出将产生更高的相对于连续神经元所期望的值(因此神经元可能饱和): 因此反向 Dropout 是更加常见的实现方式. 代码如下:
- p = 0.5 # probability of keeping a unit active. higher = Less dropout
- def train_step(X):
- # forward pass for example 3-layer neural network
- H1 = np.maximum(0, np.dot(W1, X) + b1)
- U1 = (np.random.rand(*H1.shape) < p) / p # first dropout mask. Notice /p!
- H1 *= U1 # drop!
- H2 = np.maximum(0, np.dot(W2, H1) + b2)
- U2 = (np.random.rand(*H2.shape) < p) / p # second dropout mask. Notice /p!
- H2 *= U2 # drop!
- out = np.dot(W3, H2) + b3
- # backward pass: compute gradients... (not shown)
- # perform parameter update... (not shown)
- def predict(X):
- # ensembled forward pass
- H1 = np.maximum(0, np.dot(W1, X) + b1) # no scaling necessary
- H2 = np.maximum(0, np.dot(W2, H1) + b2)
- out = np.dot(W3, H2) + b3
3. Dropout 为什么可以防止过拟合?
(1)取平均的作用
先回到标准的模型即没有 dropout, 我们用相同的训练数据去训练 5 个不同的神经网络, 一般会得到 5 个不同的结果, 此时我们可以采用 "5 个结果取均值" 或者 "多数取胜的投票策略" 去决定最终结果. 例如 3 个网络判断结果为数字 9, 那么很有可能真正的结果就是数字 9, 其它两个网络给出了错误结果. 这种 "综合起来取平均" 的策略通常可以有效防止过拟合问题. 因为不同的网络可能产生不同的过拟合, 取平均则有可能让一些 "相反的" 拟合互相抵消. dropout 掉不同的隐藏神经元就类似在训练不同的网络, 随机删掉一半隐藏神经元导致网络结构已经不同, 整个 dropout 过程就相当于对很多个不同的神经网络取平均. 而不同的网络产生不同的过拟合, 一些互为 "反向" 的拟合相互抵消就可以达到整体上减少过拟合.
(2)减少神经元之间复杂的共适应关系
用作者原话是 "在标准神经网络中, 每个参数接收的导数表明其应该如何变化才能使最终损失函数降低, 并给定所有其它神经网络单元的状态. 因此神经单元可能以一种可以修正其它神经网络单元的错误的方式进行改变. 而这就可能导致复杂的共适应(co-adaptations). 由于这些共适应现象没有推广到未见的数据, 将导致过拟合. 我们假设对每个隐藏层的神经网络单元, Dropout 通过使其它隐藏层神经网络单元不可靠从而阻止了共适应的发生. 因此, 一个隐藏层神经元不能依赖其它特定神经元去纠正其错误."
因为 dropout 程序导致两个神经元不一定每次都在一个 dropout 网络中出现. 这样权值的更新不再依赖于有固定关系的隐含节点的共同作用, 阻止了某些特征仅仅在其它特定特征下才有效果的情况 . 迫使网络去学习更加鲁棒的特征 , 这些特征在其它的神经元的随机子集中也存在. 换句话说假如我们的神经网络是在做出某种预测, 它不应该对一些特定的线索片段太过敏感, 即使丢失特定的线索, 它也应该可以从众多其它线索中学习一些共同的特征. 从这个角度看 dropout 就有点像 L1,L2 正则, 减少权重使得网络对丢失特定神经元连接的鲁棒性提高.
(3)Dropout 类似于性别在生物进化中的角色
物种为了生存往往会倾向于适应这种环境, 环境突变则会导致物种难以做出及时反应, 性别的出现可以繁衍出适应新环境的变种, 有效的阻止过拟合, 即避免环境改变时物种可能面临的灭绝.
4 参考
- http://cs231n.github.io/neural-networks-2/#reg
来源: https://www.cnblogs.com/zingp/p/11631913.html