dropout层的实现

dropout的思想和目的这里就不赘述了。

dropout的原理是根据一定概率,丢掉一些输入,代码如下:

def dropout(x, level):
    if level < 0. or level >= 1:  # level是概率值,必须在0~1之间
        raise Exception('Dropout level must be in interval [0, 1[.')
    retain_prob = 1. - level
    # 我们通过binomial函数,生成与x一样的维数向量。binomial函数就像抛硬币一样,我们可以把每个神经元当做抛硬币一样
    # 硬币 正面的概率为p,n表示每个神经元试验的次数
    # 因为我们每个神经元只需要抛一次就可以了所以n=1,size参数是我们有多少个硬币。
    sample = np.random.binomial(n=1, p=retain_prob, size=x.shape)  # 即将生成一个0、1分布的向量,0表示这个神经元被屏蔽,不工作了,也就是dropout了
    # print(sample)
    print('before dropout:', x, x.sum())
    x *= sample  # 0、1与x相乘,我们就可以屏蔽某些神经元,让它们的值变为0
    x /= retain_prob
    print('after dropout', x, x.sum())
    return x

x = np.asarray([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], dtype=np.float32)
x/= x.max()
dropout(x, 0.4)

dropout最后是需要rescale一下的,是因为在inference的时候dropout是不work的,为了得到一个确定的输出,那么在训练的阶段,就要对每个神经元的输出结果rescale一下。因为dropout层的输入有p的概率是被丢弃的,所以期望肯定是小于不dropout的输出的,因此需要乘以1/(1-p)。

上面的代码的输出是

before dropout: [0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1. ] 5.5
after dropout [0.16666666 0.         0.         0.6666666  0.8333333  0.
 1.1666666  1.3333333  1.4999999  0.        ] 5.6666665

可以看出dropout的输出和输入是接近的,在具体的神经网络训练任务中,参数往往都是很接近于0的,所以rescale之后dropout就实现了期望不变,同时又实现了随机丢弃神经元的功能。

 

参考:https://www.zhihu.com/question/61751133

你可能感兴趣的:(深度学习)