Dropout (nn.Dropout()) (为什么神经网络中的dropout可以作为正则化)(model.eval())(为什么Dropout可看作是一种集成学习)

      Dropout字面意思就是“丢掉”,是为了防止神经网络出现过拟合,让隐藏层的节点在每次迭代时(包括正向和反向传播)有一定几率(keep-prob)失效。以提高模型的泛化能力,减少过拟合。

        Dropout属于一种正则化技术。Dropout的probability,实践中最常用的是0.5(或0.1,0.05)

        Dropout不能用于测试集,只能用于训练集!!!

Dropout (nn.Dropout()) (为什么神经网络中的dropout可以作为正则化)(model.eval())(为什么Dropout可看作是一种集成学习)_第1张图片

就比如

Dropout (nn.Dropout()) (为什么神经网络中的dropout可以作为正则化)(model.eval())(为什么Dropout可看作是一种集成学习)_第2张图片这样可以认出来

这样依然可以

Dropout (nn.Dropout()) (为什么神经网络中的dropout可以作为正则化)(model.eval())(为什么Dropout可看作是一种集成学习)_第3张图片

一般情况,dropout rate 设为0.3-0.5即可

训练和测试时的dropout

注意,dropout只在训练时采用,是为了减少神经元对部分上层神经元的依赖,类似将多个不同网络结构的模型集成起来,减少过拟合的风险。

dropout一般放在fc层后防止过拟合,提高模型泛化能力,由于卷积层参数较少,很少有放在卷积层后面的情况

而在测试时,应该用整个训练好的模型,因此不需要dropout。用model.eval()即可关闭dropout.

当使用Dropout时,通常训练所需的时间会变长。但是当模型收敛后,他将会有更好的泛化能力

Dropout 如何平衡训练和测试时的差异呢?(dropout训练时的rescale)

Dropout ,在训练时以一定的概率使神经元失活,实际上就是让对应神经元的输出为0

假设失活概率为 p ,就是这一层中的每个神经元都有p的概率失活,如下图的三层网络结构中,如果失活概率为0.5,则平均每一次训练有3个神经元失活,所以输出层每个神经元只有3个输入,而实际测试时是不会有dropout的,输出层每个神经元都有6个输入,这样在训练和测试时,输出层每个神经元的输入和的期望会有量级上的差异。

因此在训练时还要对第二层的输出数据除以(1-p)之后再传给输出层神经元,使其扩大,作为神经元失活的补偿,以使得在训练时和测试时每一层输入有大致相同的期望。

即这一层有一部分数据置零了,没置零的哪些相应扩大,使得后面的层在算wx+b的时候,求和得到的值还是相同量级的

为什么神经网络中的dropout可以作为正则化

关于dropout的工作原理有几种解释。我们可以将其视为模型平均的一种形式:我们可以在每一步中“去掉”模型的一部分并取平均值。另外,它还会增加噪音,自然会产生调节的效果。最后,它还可以稀释权重,从根本上阻止神经网络中神经元的共适应。

为什么Dropout可以看作是一种集成学习

因为对于采用了dropout的网络,一个mini-batch中的每个样本所走的网络结构是不同的,于是可以理解为我们在同时训练多个网络,所以可以视作集成学习。

Dropout的使用

nn.Dropout()

import torch
from torch import nn
 
my_dropout = nn.Dropout(p=0.2)
input = torch.randn(20, 16)
output = my_dropout(input)

Dropout (nn.Dropout()) (为什么神经网络中的dropout可以作为正则化)(model.eval())(为什么Dropout可看作是一种集成学习)_第4张图片

 可以看到,output中有些值已经被随机置0了

而没有置零的也是除以了0.8,0.1949/0.8=0.2437

Dropout的位置

Dropout一般放在全连接层防止过拟合,提高模型返回能力,由于卷积层参数较少,很少有放在卷积层后面的情况,卷积层一般使用batch norm。

dropout 应当置于 activation layer 之后

CONV/FC -> BatchNorm -> ReLu(or other activation) -> Dropout -> CONV/FC

手动实现

用numpy写的

import torch
from torch import nn
import numpy as np

#模拟两层网络
def train(p, x, w1, b1, w2, b2):
    layer1 = np.maximum(0, np.dot(w1, x) + b1)
    mask1 = np.random.binomial(1, 1-p, layer1.shape)
    layer1 = layer1 * mask1
    layer1 = layer1 / (1-p)
    
    layer2 = np.maximum(0, np.dot(w2, layer1) + b2)
    mask2 = np.random.binomial(1, 1-p, layer2.shape)
    layer2 = layer2 * mask2
    layer2 = layer2 / (1-p)
    
    return layer2

def test(x, w1, b1, w2, b2):
    layer1 = np.maximum(0, np.dot(w1, x)+b1)
    layer2 = np.maximum(0, np.dot(w2, layer1) + b2)
    
    return layer2
    

input = np.random.randn(5, 4)
w1 = np.random.rand(30,20)
b1 = np.random.rand(30)
w2 = np.random.rand(40,30)
b2 = np.random.rand(40)
output1 = train(p=0.5, x=input.reshape(-1), w1=w1, b1=b1, w2=w2, b2=b2)
print(output1)
output2 = test(x=input.reshape(-1), w1=w1, b1=b1, w2=w2, b2=b2)
print(output2)


 

你可能感兴趣的:(dropout)