除了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) 那么激活函数的期望输出也不会改变 所以不用在测试过程中加入额外的缩放参数 这与训练过程不同 这就是随机失活正则化算法 你会在这周的编程作业中练习它的操作 并获得更多的一手体验 但是为什么它真的有效呢? 下一个视频中我将更直接地解释 随机失活的原理 我们下一节再见