理解Dropout和BatchNormalization

Dropout原理

相信对于了解机器学习的朋友们来说,dropout必定不陌生。dropout是一种在神经网络训练过程中防止过拟合的技术。简单来说,dropout就是指在每一轮模型权重的训练过程中,每一次随机剔除确定比例的神经元,然后只训练剩下的部分,更新权重参数。
在这里插入图片描述
具体一点来说,在每一轮的训练过程中,我们以最初的复杂模型为基础,以pre-given 的比例随机剔除掉一些神经元,然后形成一个新的简化版神经网络结构。然后将输入通过这个简化板的网络进行前向传播,然后对误差进行反向传播来update这个简化网络的权重参数。此轮结束。在下一轮训练开始时,我们恢复原先的网络结构,然后再以pre-given的比例随机剔除掉一部分神经元,然后生成另一个简化版的神经网络,还是重复上一轮的训练过程。此轮结束。不停地重复上述的训练过程,直到全部训练iteration结束。

为什么work?

很多人从不同的角度解释了为什么dropout可以有效地抑制过拟合,我认为最自然的一种想法就是加强了单个特征的‘单兵作战’能力,从而使得模型整体的泛化能力得到提升,也就抑制了过拟合。举个简单的例子,假设我们需要一个神经网络来判断一个输入是否代表一只狗。随着网络的加深我们会提炼出一系列的特征,比如有大眼睛,伸舌头,吃骨头等等。那么当我们使用一个深度网络去训练时,网络可能会理解说我们需要这么多特征的联合来判断是一只狗,然后模型的权重可能就会对应地做出过度的调整来拟合我们的数据。那么现在我们再拿出一张狗的图片,恰巧它在眯着眼睡觉,那么我们这个复杂的网络就很有可能可能判断说这肯定不是一只狗。这个时候我们的模型很显然过拟合了,泛化能力极差。
现在,我们使用dropout的思路,每次训练模型时丢掉一部分神经元特征,然后只用剩下的几个特征去训练,那么可以预见的是,每个简化的网络都具有比较强悍的单兵作战能力,仅仅依靠个别几个特征,我们的模型也会尽可能得做出准确的预测,当然,不可否认的是,单个模型也存在过拟合的可能,但是别忘了,dropout只在训练的过程中使用,在预测环节,我们使用的是整个神经网络,可以理解为是多个单兵作战能力很强,具有灵活性模型的average,在这种情况,模型的泛化能力将会有极大的提高。
引用某位博主的原话,我认为非常形象:

相互依赖的大部队(神经网络)不能适应各种各样的变化,应变能力不强,容易团灭,但dropout一些神经元后就像打游击战了,很灵活,可以对付各种情况。

总结来说,dropout可以有效消除神经元之间的复杂的共适应性,从而提高模型的泛化能力,抑制过拟合。

Inverted Dropout

我们先不讨论什么是Inverted Dropout,先来思考一下在引入dropout之后的训练输出与在预测时的输出有什么区别。我们知道在预测时,我们会使用完整的网络结构,也就是说在网络的每一层,每一个神经元都有输出。但是对于训练过程而言,假设每个神经元被保留的概率为p,那么意味着每一个神经元都有1-p的概率输出为0,对于某个神经元,假设正常情况输出为x,那么在训练过程的期望输出就是p*x+(1-p)*0=px, 所以可以预见的是当我们使用dropout时,神经网络在训练时的输出和使用时的输出的scale有明显不同。原始的dropout,或者叫做Vanilla Dropout,为了避免这个差异,在预测时我们根据dropout的策略对输出做相应的调整,十分麻烦。因此,我们引入inverted dropout的想法,我们让两个部分都在训练中完成,具体来说,对于一个经过dropout的网络,我们对那些未被丢弃的神经元的输出作rescale处理,比如,我们保留了p比例的神经元,那么对于这些被保留的神经元,我们将它们的输出相应地调整为原来的1/p倍,从而保证总体的输出信号强度还是与不做dropout时的网络强度的scale一致。
在这里插入图片描述
上面是一个dropout=0.5的例子,这里,我们对于dropout之后的剩余神经元的输出乘以(1/0.5)倍,也就是2倍。

Batch Normalization

在深度神经网络的训练过程中,随着网络深度的不断加深,模型的训练会越来越困难,其中最主要的一个原因就是梯度消失,尤其是对于sigmoid作为激活函数的情况下,梯度消失的情况尤为明显。因为在训练的过程中,随着网络加深或训练的加深,我们的激活输入值x=wu+b的分布会逐渐偏移,一般而言会向激活函数取值区间的上下两端移动,而对于sigmoid而言,当自变量取值较0有较大偏移时,sigmoid的导数取值无限接近于0。我们知道反向传播依赖梯度的计算,其中表达式中就包含激活函数的导数这一项,因此当这一项接近于0时,整个梯度的值就会非常小,造成梯度消失,训练无法收敛。那么BN的作用就是在于通过normalization的思想,将每一层神经网络的任意神经元的输入(激活输入值)的分布强行拉回到一个合理的区间,一般为均值为0,方差为1的标准正态分布。换句话说,也就是是将激活输入值通过变换后使其落在激活函数对于自变量变化较为敏感的区域,从而使得梯度的值变大,避免梯度消失。

下面我们通过下面这张图再来仔细看一下再mini-batch SGD下,BN具体是怎样操作的。
在这里插入图片描述
我们以上图中的t层作为例子。对于t层中的每一个神经元,我们将mini-batch中的m个样本的激活输入值{x1,x2,x3…xm},计算E(x)以及Var(x),然后计算xi_hat=(xi-E(x))/Var(x) for i in (1,2,3,…m)。也就是说,对于t层的每一个神经元而言,经过BN之后的激活输入值x_hat均满足服从标准正态分布。

OK,似乎上面已经完成了BN了,但是事实上,原作者认为如果对所有hidden layer的神经元都作BN处理,会使得神经网络的表征能力下降,无法保证非线性的获得以及发挥深度网络的优势,因此,作者再之后又增加了一步scale and shift的操作,y=scale*x+shift,这两个参数是通过训练来学习的,用来对变换的激活输入值做反变换来保证网络的表达能力足够的强。通过这一步,使得整个BN的过程能够找到一个线性和非线性的较好平衡点,既能享受非线性的较强表达能力的好处,又避免太靠非线性区两头使得网络收敛速度太慢。下面是完整的流程图
在这里插入图片描述
最后再来总结一下BN的好处:
1.抑制梯度消失,加快网络的收敛速度。
2.对于参数初始值的选取,要求不会那么高,降低调参的难度。
3.也有人认为BN的使用有正则化的效果。

参考:
1.https://www.cnblogs.com/guoyaohua/p/8724433.html
2.https://mp.weixin.qq.com/s/ubb-l3CS8we6FDLH-_0cZA
3.Deep Learning with Python --Francois Chollet

猜你喜欢

转载自blog.csdn.net/weixin_44607838/article/details/109668883
今日推荐