实施梯度检查
记住我们写的J是θ的函数,即
完成此操作后,让我们针对任何某个θ(可能为θ₅)进行处理。因此,我们现在要做的是精确地计算θ的近似导数,即函数J的偏导数。还要注意,我们将为此使用前面讨论过的两侧导数。为了以数学方式表示这一点,
现在,通过前面关于双向导数的讨论,我们也可以说这大约是J相对于θ₅的偏导数,或者
这清楚地告诉我们,我们现在不仅可以对θ₅,而且可以对所有i重复相同的过程,其中i∈(1,n)。因此,用于此目的的伪Python代码看起来像这样
逼近
现在我们有两个向量dθ和dθ。这些似乎应该彼此相等。但是现在,我们将面临另一个问题,即“如何确定两个向量是否近似相等?”
我现在要做的是计算两个向量之间的欧几里得距离。我们要做的是求出差异元素的平方和,然后计算其平方根以获得欧几里得距离。上面的句子似乎令人困惑,相信我,这是事实!仔细阅读两次或三次,然后再继续阅读。我们将进一步对此向量应用另一种方法,我们将这些向量的长度归一化。为此,我们只需将它们的各个长度相加,并以此除以差的欧几里得距离。如果您现在感到困惑,那么再研究一下将对您有帮助。
注意:在这里,我对矢量的L 2范数使用了常规符号。之所以我们对这个距离进行归一化,是以防万一这些向量真的很大或很小。
在实践中实施梯度检查
在许多项目中实施梯度检查时,我观察到value =10⁻⁶或10⁻⁷的值在大多数情况下都起作用。因此,使用上述相似性公式,您发现该公式产生的值小于10⁻⁷或10⁻⁸,这太好了。这意味着您的导数近似很可能是正确的。如果是10⁻⁵,我会说没关系。但是我会仔细检查向量的分量,并检查是否一个分量太大,如果某些分量很大,则可能是您有一个错误。如果为10³³,那我会非常担心,也许某个地方有一个错误。如果您获得的value大于此,那肯定是错误的!您可能应该看看θ的各个分量。这样做可能会发现dθ[i]的值与dθ[approx.]非常不同,并使用该值向下跟踪以找出哪个导数不正确。
在制作ML应用程序时,我做了一张很棒的表格供您参考
在理想的情况下,实现神经网络时将要执行的操作通常是实现正向传播,再实现反向传播。然后,您可能会发现此梯度具有相对较大的值。然后怀疑一定存在一个错误,然后进行调试。经过一段时间的调试后,如果您发现它出现了一个较小的梯度,那么您就可以更加放心它是正确的(并且会感到轻松:))。这种特殊的方法通常也帮助我在神经网络中发现错误,我建议您在调试网络时也要使用此方法。
其他小技巧
- 不用于训练,仅用于调试
每个epoch的梯度检测将使速度非常缓慢 - 如果算法无法通过梯度检查,请查看组件
如果您的算法无法通过Grad检查,那么查看组件将大有帮助。有时,它可能还会提示您该错误可能在哪里。
- 正则化
如果您的J有一个附加的正则化项,那么您还将计算正则化项的导数并将其相加
- dropout
dropout要做的是,他们随机地去除一些神经元,这使得难以获得执行梯度下降的成本函数。可以将删除视为优化某些成本函数J的方法,但它的成本函数J是对所有可以在任何迭代中消除的节点的所有指数大子集求和而定义的。因此,成本函数J很难计算,并且您每次在我们使用dropout对象中消除不同的随机子集时,都只是对成本函数进行采样。因此,很难使用梯度检测来仔细检查是否有dropout情况。因此,我通常要做的是实现无dropout的Grad检查。因此,如果需要,可以将keep-prob和dropout设置为1.0。然后进行dropout,并希望我的dropout实现是正确的。
您也可以使用一些泰勒展开式来完成此操作,但在此不做介绍。
总结
就是这样,您刚刚看到了如何轻松调试神经网络并非常轻松地发现其中的问题。我希望梯度检查可以像帮助我一样帮助您发现问题并调试网络。