Dropout和BN(Batch Normalization)分析

Dropout和BN(Batch Normalization)分析


简介:无论是机器学习,还是深度学习,模型过拟合是很常见的问题,解决手段无非是两个层面,一个是算法层面,一个是数据层面。数据层面一般是使用 数据增强手段,算法层面不外乎是: 正则化、模型集成、earlystopping、 dropoutBN等,本文重点详细讲解一下dropout和BN。

Dropout

参考:[深度学习中Dropout原理解析 - 知乎 (zhihu.com)](https://blog.csdn.net/qq_40176087/article/details/105904379)

1.背景

在2012年,Hinton在其论文《Improving neural networks by preventing co-adaptation of feature detectors》中提出Dropout。当一个复杂的前馈神经网络被训练在小的数据集时,容易造成过拟合。Dropout可以作为训练深度神经网络的一种trick供选择,在每次训练批次中,通过忽略一部分的特征检测器(让一部分隐藏节点值为0),可以明显减少过拟合现象。

简单来说:在(训练阶段)前向传播过程中,让某些神经元的激活值以一定的概率p停止工作,这样可以使模型泛化能力增强,并且减少训练时间。

2.具体工作流程

假设我们需要训练以下神经网络:

img

输入是x,输出是y,正常的流程是:首先把x通过网络前向传播,然后把误差反向传播以更新参数。

在使用Dropout之后,过程变成如下:

(1) 首先随机(临时)删掉网络中一半的隐藏神经元,输入输出神经元保持不变

img

(2) 然后把输入x通过修改后的网络前向传播,然后把得到的损失结果通过修改的网络反向传播,当前批训练样本执行完这个过程后,在没有被删除的神经元上按照随机梯度下降法更新对应参数 ( w , b ) (w,b) (w,b)

(3) 重复下述过程

  • 恢复被删除的神经元
  • 从隐藏层神经元中随机选择一个一般大小的子集临时删除掉(备份被删除的神经元参数)
  • 对下一批训练样本进行训练(先前向传播后后向传播损失并根据随机梯度下降法更新参数 ( w , b ) (w,b) (w,b)

不断重复上述过程。

3.Dropout在神经网络中的使用

本部分将从代码层面的公式推导进行讲解

(1) 训练阶段

img

对应的公式变化如下:

  • Standard network

z i l + 1 = w i l + 1 y l + b i l + 1 , y i l + 1 = f ( z i l + 1 ) z_i^{l+1}=w_i^{l+1}y^l+b_i^{l+1}, \\ y_i^{l+1}=f(z_i^{l+1}) zil+1=wil+1yl+bil+1,yil+1=f(zil+1)

  • Dropout network

r j ( l ) ∼ B e r n o u l l i ( p ) y ^ l = r ( l ) ∗ y ( l ) z i l + 1 = w i l + 1 y ^ l + b i l + 1 , y i l + 1 = f ( z i l + 1 ) r^{(l)}_j \sim Bernoulli(p) \\ \hat{y}^l=r^{(l)}*y^{(l)} \\ z_i^{l+1}=w_i^{l+1}\hat{y}^l+b_i^{l+1}, \\ y_i^{l+1}=f(z_i^{l+1}) rj(l)Bernoulli(p)y^l=r(l)y(l)zil+1=wil+1y^l+bil+1,yil+1=f(zil+1)

上面公式中Bernoulli函数是为了生成概率r向量,也就是随机生成一个0、1的向量。

代码层面实现让某个神经元以概率p停止工作,其实就是让它的激活函数值以概率p变为0。比如我们某一层网络神经元的个数为1000个,其激活函数输出值为 y 1 、 y 2 、 y 3 、 . . . . . . 、 y 1 000 y_1、y_2、y_3、......、y_1000 y1y2y3......y1000,我们dropout比率选择0.4,那么这一层神经元经过dropout后,1000个神经元中会有大约400个的值被置为0。

**注意:**屏蔽神经元后,还需要对向量 y 1 、 y 2 、 y 3 、 . . . . . . 、 y 1 000 y_1、y_2、y_3、......、y_1000 y1y2y3......y1000进行缩放,乘以 1 1 − p \frac{1}{1-p} 1p1,如果在训练的时候,经过置0后,没有对向量进行缩放,那么在测试时就需要对权重进行缩放,如下:

(2) 测试阶段

预测模型的时候,每一个神经单元的权重参数要乘以概率p。

img

测试阶段
w t e s t ( l ) = p W ( l ) w_{test}^{(l)}=pW^{(l)} wtest(l)=pW(l)

4.dropout防止过拟合的原因

  • 随机删掉一半隐藏神经元导致网络结构已经不同,整个dropout过程就相当于对很多个不同的神经网络取平均。而不同的网络产生不同的过拟合,在某种程度上相当于模型融合。
  • 随机删掉一半隐藏神经元使得需要更新的参数减少,有利于减小过拟合

归一化处理(BN、LN、IN、GN)

参考:Batch Normalization(BN层)详解 - 简书 (jianshu.com)(28条消息) Dropout和BN(层归一化)详解_谈笑风生…的博客-CSDN博客_层归一化

1.背景

Batch Normalization 出自《Batch Normalization: Accelerating Deep Network Training by Reducing Internal Covariate Shift》。

神经网络训练前都需要对输入数据进行归一化处理,原因在于神经网络学习过程本质是为了学习数据分布,一旦训练数据与测试数据的分布不同,那么网络的泛化能力也大大降低;另外一方面,一旦每批训练数据的分布各不相同(batch 梯度下降),那么网络就要在每次迭代都去学习适应不同的分布,这样将会大大降低网络的训练速度。

2.四种归一化

在深度学习中,有多种归一化,接下来,我们先用一个示意图来形象的表现BN、LN、IN和GN的区别,在输入图片的维度为(NCHW)中,HW是被合成一个维度,这个是方便画出示意图,C和N各占一个维度。

在这里插入图片描述

Batch Normalization
1.BN的计算就是把每个通道的NHW单独拿出来归一化处理
2.针对每个channel我们都有一组γ,β,所以可学习的参数为2*C
3.当batch size越小,BN的表现效果也越不好,因为计算过程中所得到的均值和方差不能代表全局

Layer Normalizaiton
1.LN的计算就是把每个CHW单独拿出来归一化处理,不受batchsize 的影响
2.常用在RNN网络,但如果输入的特征区别很大,那么就不建议使用它做归一化处理

Instance Normalization
1.IN的计算就是把每个HW单独拿出来归一化处理,不受通道和batchsize 的影响
2.常用在风格化迁移,但如果特征图可以用到通道之间的相关性,那么就不建议使用它做归一化处理

Group Normalizatio
1.GN的计算就是把先把通道C分成G组,然后把每个gHW单独拿出来归一化处理,最后把G组归一化之后的数据合并成CHW
2.GN介于LN和IN之间,当然可以说LN和IN就是GN的特列,比如G的大小为1或者为C

BN、LN、IN和GN这四个归一化的计算流程几乎是一样的,可以分为四步:
1.计算出均值
2.计算出方差
3.归一化处理到均值为0,方差为1
4.变化重构,恢复出这一层网络所要学到的分布
μ B ← 1 m ∑ i = 1 m x i σ B 2 ← 1 m ∑ i = 1 m ( x i − μ B ) 2 x ^ i ← x i − μ B σ B 2 + ϵ y i ← γ x ^ i + β ≡ B N γ , β ( x i ) \begin{aligned} \mu_{\mathcal{B}} & \leftarrow \frac{1}{m} \sum_{i=1}^{m} x_{i} \\ \sigma_{\mathcal{B}}^{2} & \leftarrow \frac{1}{m} \sum_{i=1}^{m}\left(x_{i}-\mu_{\mathcal{B}}\right)^{2} \\ \widehat{x}_{i} & \leftarrow \frac{x_{i}-\mu_{\mathcal{B}}}{\sqrt{\sigma_{\mathcal{B}}^{2}+\epsilon}} \\ y_{i} & \leftarrow \gamma \widehat{x}_{i}+\beta \equiv \mathrm{BN}_{\gamma, \beta}\left(x_{i}\right) \end{aligned} μBσB2x iyim1i=1mxim1i=1m(xiμB)2σB2+ϵ xiμBγx i+βBNγ,β(xi)
源码实现

m = K.mean(X, axis=-1, keepdims=True)#计算均值  
std = K.std(X, axis=-1, keepdims=True)#计算标准差  
X_normed = (X - m) / (std + self.epsilon)#归一化  
out = self.gamma * X_normed + self.beta#重构变换  

3.训练时BN

训练的时候,是根据输入的每一批数据来计算均值和方差

那么测试的时候,其实网络一旦训练完毕,参数都是固定的。对于均值来说直接计算所有训练时batch均值的平均值;然后对于标准偏差采用每个batch方差的无偏估计。
E [ x ] ← E B [ μ B ] V a r [ x ] ← m m − 1 E B [ σ B 2 ] E[x] \leftarrow E_{\mathcal{B}}[\mu_{\mathcal{B}}] \\ Var[x] \leftarrow \frac{m}{m-1}E_{\mathcal{B}}[\sigma_{\mathcal{B}}^{2}] E[x]EB[μB]Var[x]m1mEB[σB2]
最终测试阶段,BN的使用公式是
y = γ Var ⁡ [ x ] + ϵ ⋅ x + ( β − γ E [ x ] Var ⁡ [ x ] + ϵ ) y=\frac{\gamma}{\sqrt{\operatorname{Var}[x]+\epsilon}} \cdot x+\left(\beta-\frac{\gamma \mathrm{E}[x]}{\sqrt{\operatorname{Var}[x]+\epsilon}}\right) y=Var[x]+ϵ γx+(βVar[x]+ϵ γE[x])

4.BN在CNN中的使用

卷积神经网络经过卷积后得到的是一系列的特征图,如果min-batch sizes为m,那么网络某一层输入数据可以表示为四维矩阵(m,f,p,q),m为min-batch sizes,f为特征图个数,p、q分别为特征图的宽高。在CNN中,可以把每个特征图看成是一个特征处理(一个神经元),因此在使用Batch Normalization,mini-batch size的大小就是 m × p × q m \times p \times q m×p×q,于是对于每个特征图都只有一对可学习参数:γ、β.

相当于求取所有样本所对应的一个特征图的所有神经元的平均值、方差,将每个特征图神经元做归一化。

以下是keras卷积层的BN实现一部分源码

input_shape = self.input_shape  
 reduction_axes = list(range(len(input_shape)))  
 del reduction_axes[self.axis]  
 broadcast_shape = [1] * len(input_shape)  
 broadcast_shape[self.axis] = input_shape[self.axis]  
 if train:  
     m = K.mean(X, axis=reduction_axes)  
     brodcast_m = K.reshape(m, broadcast_shape)  
     std = K.mean(K.square(X - brodcast_m) + self.epsilon, axis=reduction_axes)  
     std = K.sqrt(std)  
     brodcast_std = K.reshape(std, broadcast_shape)  
     mean_update = self.momentum * self.running_mean + (1-self.momentum) * m  
     std_update = self.momentum * self.running_std + (1-self.momentum) * std  
     self.updates = [(self.running_mean, mean_update),  
                     (self.running_std, std_update)]  
     X_normed = (X - brodcast_m) / (brodcast_std + self.epsilon)  
 else:  
     brodcast_m = K.reshape(self.running_mean, broadcast_shape)  
     brodcast_std = K.reshape(self.running_std, broadcast_shape)  
     X_normed = ((X - brodcast_m) /  
                 (brodcast_std + self.epsilon))  
 out = K.reshape(self.gamma, broadcast_shape) * X_normed + K.reshape(self.beta, broadcast_shape)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值