dropout 正则化(Dropout Regularization)

dropout 正则化(Dropout Regularization)

除了 L 2 L2 L2正则化,还有一个非常实用的正则化方法——“Dropout(随机失活)”,我们来看看它的工作原理。

假设你在训练上图这样的神经网络,它存在过拟合,这就是dropout所要处理的,我们复制这个神经网络,dropout会遍历网络的每一层,并设置消除神经网络中节点的概率。假设网络中的每一层,每个节点都以抛硬币的方式设置概率,每个节点得以保留和消除的概率都是0.5,设置完节点概率,我们会消除一些节点,然后删除掉从该节点进出的连线,最后得到一个更少节点,规模更小的网络,然后用backprop方法进行训练。

这是网络节点精简后的一个样本,对于其它样本,我们照旧以抛硬币的方式设置概率,保留一类节点集合,删除其它类型的节点集合。对于每个训练样本,我们都将采用一个精简后神经网络来训练它,这种方法似乎有点怪,单纯遍历节点,编码也是随机的,可它真的有效。不过可想而知,我们针对每个训练样本训练规模小得多的网络,最后你可能会认识到为什么要正则化网络,因为我们在训练规模小得多的网络。

如何实施dropout呢?方法有几种,接下来我要讲的是最常用的方法,inverted dropout(反向随机失活),出于完整性考虑,我们用一个三层( l = 3 l=3 l=3)网络来举例说明。编码中会有很多涉及到3的地方。我只举例说明如何在某一层中实施dropout

首先要定义向量 d d d d [ 3 ] d^{[3]} d[3]表示网络第三层的dropout向量:

d3 = np.random.rand(a3.shape[0],a3.shape[1])

然后看它是否小于某数,我们称之为keep-probkeep-prob是一个具体数字,上个示例中它是0.5,而本例中它是0.8,它表示保留某个隐藏单元的概率,此处keep-prob等于0.8,它意味着消除任意一个隐藏单元的概率是0.2,它的作用就是生成随机矩阵,如果对 a [ 3 ] a^{[3]} a[3]进行因子分解,效果也是一样的。 d [ 3 ] d^{[3]} d[3]是一个矩阵,每个样本和每个隐藏单元,其中 d [ 3 ] d^{[3]} d[3]中的对应值为1的概率都是0.8,对应为0的概率是0.2,随机数字小于0.8。它等于1的概率是0.8,等于0的概率是0.2。

接下来要做的就是从第三层中获取激活函数,这里我们叫它 a [ 3 ] a^{[3]} a[3] a [ 3 ] a^{[3]} a[3]含有要计算的激活函数, a [ 3 ] a^{[3]} a[3]等于上面的 a [ 3 ] a^{[3]} a[3]乘以 d [ 3 ] d^{[3]} d[3]a3 =np.multiply(a3,d3),这里是元素相乘,也可写为 a 3 ∗ = d 3 a3*=d3 a3=d3,它的作用就是让 d [ 3 ] d^{[3]} d[3]中所有等于0的元素(输出),而各个元素等于0的概率只有20%,乘法运算最终把 d [ 3 ] d^{\left\lbrack3 \right]} d[3]中相应元素输出,即让 d [ 3 ] d^{[3]} d[3]中0元素与 a [ 3 ] a^{[3]} a[3]中相对元素归零。

如果用python实现该算法的话, d [ 3 ] d^{[3]} d[3]则是一个布尔型数组,值为truefalse,而不是1和0,乘法运算依然有效,python会把truefalse翻译为1和0,大家可以用python尝试一下。

最后,我们向外扩展 a [ 3 ] a^{[3]} a[3],用它除以0.8,或者除以keep-prob参数。

下面我解释一下为什么要这么做,为方便起见,我们假设第三隐藏层上有50个单元或50个神经元,在一维上 a [ 3 ] a^{[3]} a[3]是50,我们通过因子分解将它拆分成 50 × m 50×m 50×m维的,保留和删除它们的概率分别为80%和20%,这意味着最后被删除或归零的单元平均有10(50×20%=10)个,现在我们看下 z [ 4 ] z^{\lbrack4]} z[4] z [ 4 ] = w [ 4 ] a [ 3 ] + b [ 4 ] z^{[4]} = w^{[4]} a^{[3]} + b^{[4]} z[4]=w[4]a[3]+b[4],我们的预期是, a [ 3 ] a^{[3]} a[3]减少20%,也就是说 a [ 3 ] a^{[3]} a[3]中有20%的元素被归零,为了不影响 z [ 4 ] z^{\lbrack4]} z[4]的期望值,我们需要用 w [ 4 ] a [ 3 ] / 0.8 w^{[4]} a^{[3]}/0.8 w[4]a[3]/0.8,它将会修正或弥补我们所需的那20%, a [ 3 ] a^{[3]} a[3]的期望值不会变,这就是所谓的dropout方法。

它的功能是,不论keep-prop的值是多少,0.8、0.9甚至是1,如果keep-prop设置为1,那么就不存在dropout,因为它会保留所有节点。反向随机失活(inverted dropout)方法通过除以keep-prob,确保 a [ 3 ] a^{[3]} a[3]的期望值不变。

现在你使用的是 d d d向量,你会发现,不同的训练样本,清除不同的隐藏单元也不同。实际上,如果你通过相同训练集多次传递数据,每次训练数据的梯度不同,则随机对不同隐藏单元归零,有时却并非如此。比如,需要将相同隐藏单元归零,第一次迭代梯度下降时,把一些隐藏单元归零,第二次迭代梯度下降时,也就是第二次遍历训练集时,对不同类型的隐藏层单元归零。向量 d d d d [ 3 ] d^{[3]} d[3]用来决定第三层中哪些单元归零,无论用foreprop还是backprop,这里我们只介绍了foreprob

如何在测试阶段训练算法,在测试阶段,我们已经给出了 x x x,或是想预测的变量,用的是标准计数法。我用 a [ 0 ] a^{\lbrack0]} a[0],第0层的激活函数标注为测试样本 x x x,我们在测试阶段不使用dropout函数,尤其是像下列情况:

z [ 1 ] = w [ 1 ] a [ 0 ] + b [ 1 ] z^{[1]} = w^{[1]} a^{[0]} + b^{[1]} z[1]=w[1]a[0]+b[1]

a [ 1 ] = g [ 1 ] ( z [ 1 ] ) a^{[1]} = g^{[1]}(z^{[1]}) a[1]=g[1](z[1])

z [ 2 ] =   w [ 2 ] a [ 1 ] + b [ 2 ] z^{[2]} = \ w^{[2]} a^{[1]} + b^{[2]} z[2]= w[2]a[1]+b[2]

a [ 2 ] = … a^{[2]} = \ldots a[2]=

以此类推直到最后一层,预测值为 y ^ \hat{y} y^

显然在测试阶段,我们并未使用dropout,自然也就不用抛硬币来决定失活概率,以及要消除哪些隐藏单元了,因为在测试阶段进行预测时,我们不期望输出结果是随机的,如果测试阶段应用dropout函数,预测会受到干扰。理论上,你只需要多次运行预测处理过程,每一次,不同的隐藏单元会被随机归零,预测处理遍历它们,但计算效率低,得出的结果也几乎相同,与这个不同程序产生的结果极为相似。

Inverted dropout函数在除以keep-prob时可以记住上一步的操作,目的是确保即使在测试阶段不执行dropout来调整数值范围,激活函数的预期结果也不会发生变化,所以没必要在测试阶段额外添加尺度参数,这与训练阶段不同。

l = k e e p − p r o b l=keep-prob l=keepprob

这就是dropout正则化。

理解 dropout(Understanding Dropout)

Dropout可以随机删除网络中的神经单元,他为什么可以通过正则化发挥如此大的作用呢?

直观上理解:不依赖于任何一个特征,因为该单元的输入可能随时被清除,因此该单元通过这种方式传播下去,并为单元的四个输入增加一点权重,通过传播所有权重,dropout将产生收缩权重的平方范数的效果,和 L 2 L2 L2正则化类似;实施dropout的结果实它会压缩权重,并完成一些预防过拟合的外层正则化; L 2 L2 L2对不同权重的衰减是不同的,它取决于激活函数倍增的大小。

第二个直观认识是,我们从单个神经元入手,如图,这个单元的工作就是输入并生成一些有意义的输出。通过dropout,该单元的输入几乎被消除,有时这两个单元会被删除,有时会删除其它单元,就是说,紫色圈起来的这个单元,它不能依靠任何特征,因为特征都有可能被随机清除,或者说该单元的输入也都可能被随机清除。我不愿意把所有赌注都放在一个节点上,不愿意给任何一个输入加上太多权重,因为它可能会被删除,因此该单元将通过这种方式积极地传播开,并为单元的四个输入增加一点权重,通过传播所有权重,dropout将产生收缩权重的平方范数的效果,和 L 2 L2 L2正则化类似,实施dropout的结果是它会压缩权重,并完成一些预防过拟合的外层正则化。

事实证明,dropout被正式地作为一种正则化的替代形式, L 2 L2 L2对不同权重的衰减是不同的,它取决于倍增的激活函数的大小。

总结一下,dropout的功能类似于 L 2 L2 L2正则化,与 L 2 L2 L2正则化不同的是,被应用的方式不同,dropout也会有所不同,甚至更适用于不同的输入范围。

实施dropout的另一个细节是,这是一个拥有三个输入特征的网络,其中一个要选择的参数是keep-prob,它代表每一层上保留单元的概率。所以不同层的keep-prob也可以变化。第一层,矩阵 W [ 1 ] W^{[1]} W[1]是7×3,第二个权重矩阵 W [ 2 ] W^{[2]} W[2]是7×7,第三个权重矩阵 W [ 3 ] W^{[3]} W[3]是3×7,以此类推, W [ 2 ] W^{[2]} W[2]是最大的权重矩阵,因为 W [ 2 ] W^{[2]} W[2]拥有最大参数集,即7×7,为了预防矩阵的过拟合,对于这一层,我认为这是第二层,它的keep-prob值应该相对较低,假设是0.5。对于其它层,过拟合的程度可能没那么严重,它们的keep-prob值可能高一些,可能是0.7,这里是0.7。如果在某一层,我们不必担心其过拟合的问题,那么keep-prob可以为1,为了表达清除,我用紫色线笔把它们圈出来,每层keep-prob的值可能不同。

注意keep-prob的值是1,意味着保留所有单元,并且不在这一层使用dropout,对于有可能出现过拟合,且含有诸多参数的层,我们可以把keep-prob设置成比较小的值,以便应用更强大的dropout,有点像在处理 L 2 L2 L2正则化的正则化参数 λ \lambda λ,我们尝试对某些层施行更多正则化,从技术上讲,我们也可以对输入层应用dropout,我们有机会删除一个或多个输入特征,虽然现实中我们通常不这么做,keep-prob的值为1,是非常常用的输入值,也可以用更大的值,或许是0.9。但是消除一半的输入特征是不太可能的,如果我们遵守这个准则,keep-prob会接近于1,即使你对输入层应用dropout

总结一下,如果你担心某些层比其它层更容易发生过拟合,可以把某些层的keep-prob值设置得比其它层更低,缺点是为了使用交叉验证,你要搜索更多的超级参数,另一种方案是在一些层上应用dropout,而有些层不用dropout,应用dropout的层只含有一个超级参数,就是keep-prob

dropout一大缺点就是代价函数 J J J不再被明确定义,每次迭代,都会随机移除一些节点,如果再三检查梯度下降的性能,实际上是很难进行复查的。定义明确的代价函数 J J J每次迭代后都会下降,因为我们所优化的代价函数 J J J实际上并没有明确定义,或者说在某种程度上很难计算,所以我们失去了调试工具来绘制这样的图片。我通常会关闭dropout函数,将keep-prob的值设为1,运行代码,确保J函数单调递减。然后打开dropout函数,希望在dropout过程中,代码并未引入bug。我觉得你也可以尝试其它方法,虽然我们并没有关于这些方法性能的数据统计,但你可以把它们与dropout方法一起使用。

  • 2
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值