dropout策略及python实现

1 原理

《Dropout: A Simple Way to Prevent Neural Networks from Overfitting》

在神经网络的训练过程中,对于一次迭代中的某一层神经网络,先随机选中一些神经元并将其临时隐藏(丢弃),然后再进行本次训练和优化。在下一次迭代中,继续随机隐藏一些神经元,如此直至训练结束。由于是随机丢弃,故而每一个mini-batch都在训练不同的网络。

在训练时,每个神经单元以概率 p p p被保留(Dropout丢弃率为 1 − p 1-p 1p);在预测阶段(测试阶段),每个神经单元都是存在的,权重参数 w w w要乘以 p p p,输出是 p w pw pw,示意图如

预测阶段为什么乘 p p p

前一层隐藏层的一个神经元在dropout之前的输出是 x x x,训练时dropout之后的期望值是 E = p x + ( 1 − p ) 0 E=px+(1-p)0 E=px+(1p)0; 在预测阶段该层神经元总是激活,为了保持同样的输出期望值并使下一层也得到同样的结果,需要调整 x − > p x x->px x>px. 其中 p p p是Bernoulli分布(0-1分布)中值为1的概率。

2 dropout实现

训练时随机扔掉部分神经元节点,在预测的时候,结果需要乘以 p p 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 1/p。所以我们换一个思路,在训练时候对数据进行 1 / p 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

4 为什么可以防止过拟合

(1)取平均的作用

先回到标准的模型即没有dropout,我们用相同的训练数据去训练5个不同的神经网络,一般会得到5个不同的结果,此时我们可以采用 “5个结果取均值”或者“多数取胜的投票策略”去决定最终结果。例如3个网络判断结果为数字9,那么很有可能真正的结果就是数字9,其它两个网络给出了错误结果。这种“综合起来取平均”的策略通常可以有效防止过拟合问题。因为不同的网络可能产生不同的过拟合,取平均则有可能让一些“相反的”拟合互相抵消。dropout掉不同的隐藏神经元就类似在训练不同的网络,随机删掉一半隐藏神经元导致网络结构已经不同,整个dropout过程就相当于对很多个不同的神经网络取平均。而不同的网络产生不同的过拟合,一些互为“反向”的拟合相互抵消就可以达到整体上减少过拟合。

(2)减少神经元之间复杂的共适应关系

用作者原话是“在标准神经网络中,每个参数接收的导数表明其应该如何变化才能使最终损失函数降低,并给定所有其它神经网络单元的状态。因此神经单元可能以一种可以修正其它神经网络单元的错误的方式进行改变。而这就可能导致复杂的共适应(co-adaptations)。由于这些共适应现象没有推广到未见的数据,将导致过拟合。我们假设对每个隐藏层的神经网络单元,Dropout通过使其它隐藏层神经网络单元不可靠从而阻止了共适应的发生。因此,一个隐藏层神经元不能依赖其它特定神经元去纠正其错误。”

因为dropout程序导致两个神经元不一定每次都在一个dropout网络中出现。这样权值的更新不再依赖于有固定关系的隐含节点的共同作用,阻止了某些特征仅仅在其它特定特征下才有效果的情况 。迫使网络去学习更加鲁棒的特征,这些特征在其它的神经元的随机子集中也存在。换句话说假如我们的神经网络是在做出某种预测,它不应该对一些特定的线索片段太过敏感,即使丢失特定的线索,它也应该可以从众多其它线索中学习一些共同的特征。从这个角度看dropout就有点像L1,L2正则,减少权重使得网络对丢失特定神经元连接的鲁棒性提高。

(3)Dropout类似于性别在生物进化中的角色

物种为了生存往往会倾向于适应这种环境,环境突变则会导致物种难以做出及时反应,性别的出现可以繁衍出适应新环境的变种,有效的阻止过拟合,即避免环境改变时物种可能面临的灭绝。

欢迎关注微信公众号(算法工程师面试那些事儿),建号初期,期待和大家一起刷leecode,刷机器学习、深度学习面试题等,共勉~

算法工程师面试那些事儿

参考:

(1)https://cs231n.github.io/neural-networks-2/#reg
(2)https://jmlr.org/papers/volume15/srivastava14a.old/srivastava14a.pdf
(3)https://www.cnblogs.com/zingp/p/11631913.html

Guess you like

Origin blog.csdn.net/qq_40006058/article/details/121070560
Recommended