0


理论结合实际:如何调试神经网络并检查梯度

当我们实现神经网络时,反向传播的过程中更容易出错。因此,如果我们能够实现一些使我们能够轻松调试神经网络的工具,那将是多么酷。在这里,我们将看到“梯度检查”的方法。简而言之,该方法使用数值方法近似梯度。如果实际的梯度接近计算得出的梯度,则可以正确实施反向传播。还有很多其他方法,让我们一起看看。有时,可以看到网络在几个epoch内陷入僵局,然后继续快速收敛。我们还将看到如何解决这个问题。让我们开始吧!

梯度的数值近似法

为了使我们能够构建“梯度检查”函数,我们首先需要了解如何在数值上近似梯度。我发现用一个例子很容易解释此方法,所以让我们采用一个函数f(θ)=θ³。让我们看一下这个函数的图像。

您可能已经猜到了。让我们像往常一样从θ的某个值开始,现在我们说θ=1。我们要做的是不仅将θ推到右边以获得(θ+ ϵ),还将θ推到左边而得到(θ-ϵ)。出于示例的目的,我们仅表示ϵ = 0.01。现在我们将其可视化。忽略该图中的比例。

现在我们说(θ-ϵ)的点称为B,而(θ+ ϵ)的点称为C。在此图中,我们之前使用的是三角形DEF,并计算出其梯度。在这种情况下是EF / DE。事实证明,如果您使用(θ+ ϵ)和(θ-ϵ)中的一个较大的三角形,则可以得到更好的梯度估计,我的意思是用下图中的红色表示此处的三角形。

有一些论文介绍了为什么使用这个更大的三角形可以使我们更好地近似θ处的梯度,但是在本文中我将不做详细介绍。简单说明一下,您现在有两个较小的三角形,在这里您可以通过使用更大的三角形来加以考虑。

我们刚刚看到了为什么您应该改用较大的三角形,完成后让我们开始研究该三角形的数学方法。我们可以简单地表示。

H = f(θ-ϵ) and,
F = f(θ+ϵ)

根据这两个结果,您可以说较大三角形的高度(h)为

h = f(θ+ϵ)-f(θ-ϵ)

使用类似的方法,您还可以轻松地计算出此三角形的宽度(w)为

w = 2 ⋅ ϵ

双向导数

因此,如果您了解一些相关知识,则可以轻松推断出

其中

g(θ)

指梯度。

现在,通过插入刚刚讨论的示例的值,来检查上面编写的方程式的正确性。所以,我会得到以下的东西。

现在让我们计算它的实际导数。据我所知,f(θ)=θ³,通过简单的导数g(θ)= 3⋅θ²,而我们得到g(θ)=3。我们做了一个很好的近似,近似误差仅为0.0001。现在让我们看看如果使用传统方法会得到什么。如果用单边来计算,最终将得到3.0301,其近似误差为0.0301。因此,我们在这里做了出色的工作,大大降低了误差!

您刚刚看到双面导数的性能要比传统方法好得多。这给了您更大的信心,θ的g可能是f(θ)的导数的正确实现。这听起来真是太好了!这种方法也有一个缺点。事实证明,这种方法的运行时间是使用单侧方法的两倍。但是我认为在实践中使用此方法是值得的,因为它更加准确。

再深入一点

让我们回顾一下导数的形式定义。

这里要注意的重要一点是ϵ。对于non的非零值,您可以证明近似值的误差约为ϵ²。ϵ是一个很小的数字,趋向于0。因此,总而言之

error = O(ϵ²)

在此,O是指的顺序。

您可以通过简单的数学证明,如果使用单向导数,则误差将为ϵ或

error = O(ϵ)

ϵ当然是少于1的极小数,所以ϵ >> ϵ²。因此,现在您可能已经了解了为什么应该使用双面导数而不是单面导数,并且我们将看到这如何帮助我们进行梯度检查。

梯度检查

梯度检查是一种非常有用的技术,已帮助我轻松地进行调试并发现神经网络中的错误。现在,我们将演示如何使用这种出色的技术来调试或验证您的网络实现以及反向传播是否正确。这并不是什么新鲜事物,但让我们将单个神经元作为演示。

请记住,

[x₁, x₂ ... x_n]

是输入,对于每个参数,我们都参数(w¹, b¹) (w², b²) … (wⁿ, bⁿ)。因此,要实现梯度检查,您应该做的第一件事就是获取所有参数并将它们调整为巨大的矢量数据。因此,您要做的就是将所有这些w和b都进行调整,使其成为矢量。然后将所有这些向量连接成一个称为θ的巨型向量。所以现在我们可以像这样用θ来写成本函数J

因此,现在我们的J将只是θ的函数。

现在,用相同的方式对w和b进行排序,您还可以将

dw¹

,

db¹

dwⁿ

,

dbⁿ

连接起来,并将它们连接成一个大向量,我们将其称为与θ尺寸相同的dθ。我们将以类似的步骤进行操作,即将所有dw变为矢量,因为它们是矩阵,而b则已经是矢量,因此只需将它们串联即可。我觉得可能有帮助的一点是,w 1的尺寸与dw 1的尺寸相同,而b 1的尺寸与db 1的尺寸相同,依此类推。这也意味着您可以使用相同的大小和串联操作。因此,现在您可能会有一个问题,“dθ在这里是θ的斜率还是梯度?” 我们将在稍后讨论。

实施梯度检查

记住我们写的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实现是正确的。

您也可以使用一些泰勒展开式来完成此操作,但在此不做介绍。

总结

就是这样,您刚刚看到了如何轻松调试神经网络并非常轻松地发现其中的问题。我希望梯度检查可以像帮助我一样帮助您发现问题并调试网络。

作者:Rishit Dagli

本文代码:https://github.com/Rishit-dagli/Debugging-Neural-Nets

翻译:孟翔杰

DeepHub

微信号 : deephub-imba

每日大数据和人工智能的重磅干货

大厂职位内推信息

长按识别二维码关注 ->

好看就点在看!********** **********

标签:

“理论结合实际:如何调试神经网络并检查梯度”的评论:

还没有评论