除了L2正则化
另一种非常强大的正则化技术是 随机失活正则化(丢弃法 dropout)
让我们来看看是如何工作的
假设你训练左图所示的神经网络并发现过拟合现象
你可以随机失活技术来处理它
让我先拷贝这个神经网络图
使用随机失活技术 我们要遍历这个网络的每一层
并且为丢弃(drop)网络中的某个节点置一个概率值
即对于网络中的每一层
我们将对每一个结点作一次公平投币
使这个节点有50%的几率被保留
50%的的几率被丢弃
抛完这些硬币
我们会决定消除哪些节点
然后清除那些节点上所有正在进行的运算
所以你最后得到的是一个小得多的
被简化了很多的网络
然后再做反向传播训练
这是一个被简化的神经网络的例子
对于不同的训练样例(examples)
你可以为所有的节点重新进行若干轮投币
保留和消除不同的节点
对每一个训练样例
你可以选择其中任意一个网络进行训练
也许这个技术看起来有点疯狂
他们只是按照随机的编码决定这些节点的去留
但是这个技术确实是有效的
因为对于每一个训练样例你都在训练一个小得多的网络
这样或许能让你理解为什么你能正则化整个网络
因为被训练的是一些小得多的网络
让我们看看如何实现随机失活算法
有几种方法可以实现随机失活算法
我将展示最常用的一种
反向随机失活(inverted dropout)
完整起见
我们在l=3的层上演示这个技术
在我准备写的代码中 这里有一堆的3
我将演示如何实现单层的随机失活技术
设置一个矢量d
d3表示层3的失活向量
3将作为np.random.rand(a)中a的后缀
d3将获得和a3一样的形状
当d3中的某个元素小于某个值
这个值命名为keep.prob
即keep.prob是一个数值
之前我将它赋值为0.5
在这个样例中它赋值为0.8
这是给定隐藏单元将被保留的概率值
keep.prob=0.8
意味着这个隐藏单元有0.2的几率被丢弃
因此它将生成一个随机矩阵
这个方法也适用与矢量化运算
这种情况下d3将是一个矩阵
因此任意一个训练样例及隐藏单元的组合
其对应的d3中的元素都有0.8的几率取值为1
0.2的几率取值为0
这个表达式表示这个随机数有0.8的几率取值为1 或为真(True)
20%或0.2的几率取值为非(False) 或0
然后取层3的激活矩阵
用a3来表示
a3为刚才计算的激活矩阵
它是用原来的a3与d3相乘得到的矩阵
这里的相乘是逐元素相乘
也可以写成a3*=d3
这样做的作用是 对于d3中值为0的元素
每个元素有20%的几率取值为0
通过点乘将a3中0值对应位置的元素
一一清零
如果你用python实现
技术上来说d3是一个值为True或False的布尔值数组
而不是1或0
但是用1和0表示True和False
做点乘运算确实能达到效果
你可以自己用python验证一下
最后我们要放大a3
将a3除以0.8 实际上是除以keep.prob参数
我来解释以下最后一步
方便起见 假设层3有50个单元
或者说50个神经元
所以a3的维数是50x1
如果你做矢量化的运算 它的维数是50xm
所以每个神经元有80%的几率被 20%的几率被丢弃
这意味着平均起来
将有10个单元失活或者被清零
现在再看看z4的值
z4=w4*a3+b4
它的期望值
将减少20%
也就是说a3中20%的元素都被清零了
为了不减少z4的期望值
我们需要除以0.8
因为
它能提供你所需要的大约20%的校正值
这样a3的期望值就不会被改变
这就是所谓的反向随机失活技术(inverted dropout technique)
它的作用在于
你可以将keep.prob设为任意值
0.8或0.9甚至1
如果值为1那就没有丢弃 因为它保留了所有神经元
这个值也可以是0.5或随便什么
反向随机失活技术通过除以keep.prob
确保a3的期望值不变
而且你会发现在测试阶段
也就是你要评估一个神经网络时
--这个我们将在下一页幻灯片讨论
反向随机失活技术
就是这条线指向的随机失活正则化过程中这个绿色的框表示的部分
它简化了神经网络的测试部分 因为它减少了可能引入的缩放问题
到目前为止随机失活正则化最普遍的实现
据我所知就是反向随机失活
我建议你自己操作一下
但是在一些早期的随机失活法的版本中
并没有除以keep.prob这个操作
所以在测试过程中求平均值变得越来越复杂
但是人们已经不再使用那些版本了
我们使用矢量d
而且你会注意到 不同的训练样例的训练
实际上对不同的隐藏单元实施了清零
实际上 如果用同一个训练集进行迭代
在不同的训练轮次中
你应该随机地将不同的隐藏单元清零
因此这并不意味着同一个训练样例的训练
应该保证一直丢弃相同的隐藏单元
--在梯度下降法的一次迭代中
你把一些隐藏单元清零了
在第二次迭代时
也就是第二次遍历测试集的时候
你可以用不同的模式给隐藏单元清零
矢量d或者说层3对应的d3
将决定哪些被清零
--无论是在正向传播还是反向传播过程中
我们在这里只展示了正向传播
用这个算法完成训练后 我们来看看测试阶段的算法
在测试阶段 你想对一些x做预测
使用我们的标准表示法
我用a0
即层0的激活函数输出代表测试样例x
我们要做的是 不在测试阶段使用随机失活算法
具体来说
Z^1= w^1.a^0 + b^1.
a^1 = g^1(z^1 Z).
Z^2 = w^2.a^1 + b^2.
a^2 =...
直到到达了最后一层并得到一个预测y^
但请注意在测试阶段你并没有
在哪里使用随机失活算法 没有抛硬币
你不用抛硬币来决定哪些隐藏单元要被消除
这是因为在测试阶段做预测的时候
你并不想让你的输出也是随机的
在测试阶段也使用随机失活算法
只会为预测增加噪声
理论上来说 可以做的一件事是
用不同的随机失活的神经网络进行多次预测取并平均值
但是这个方法运算效率不高而且会得到几乎相同的预测结果
每次不同的预测过程将给出非常非常相似的结果
刚才提到过
反向随机失活
记得上一页我们有做除以keep.prob的运算
它的作用是保证如果测试过程
没有针对随机失活算法进行缩放(scaling)
那么激活函数的期望输出也不会改变
所以不用在测试过程中加入额外的缩放参数
这与训练过程不同
这就是随机失活正则化算法
你会在这周的编程作业中练习它的操作
并获得更多的一手体验
但是为什么它真的有效呢？
下一个视频中我将更直接地解释
随机失活的原理
我们下一节再见