梯度检验与高级优化

From Ufldl

Jump to: navigation, search
Line 6: Line 6:
Wiki上传者:王方,email:fangkey@gmail.com,新浪微博:@GuitarFang
Wiki上传者:王方,email:fangkey@gmail.com,新浪微博:@GuitarFang
 +
:【原文】:
:【原文】:
Line 20: Line 21:
your confidence in the correctness of your code.
your confidence in the correctness of your code.
:【初译】:
:【初译】:
 +
众所周知,反向传播算法很难调试,尤其是由于它的很多有细小问题的实现。举例来说,在指标上有一位误差的实现而只训练其中一些权重层,或者一个忽略偏离项的实现,都会导致学习的材料显示地惊人一致(然而实际的表现却比正确的实现差)。因此,即使是一个有问题的实现也可能在表面上没有任何征兆。在这一章,我们将描述一个用以数学上检查由你的代码计算得出的导数从而保证实现的正确性的方法。使用这里描述的导数检验方法将很大程度地提高你对代码正确性的信心。
:【一审】:
:【一审】:
 +
众所周知,反向传播算法很难调试以使之正确,尤其是当存在很多难于发现的Bug的时候。举例来说,当矩阵下标存在一位偏差时,或者只有一部分权重得到训练时,再或者忘记计算偏置项时,你都会得到一个看上去十分合理的结果(这句的逻辑这样才是正确的)(然而实际的性能却比正确的实现差)。因此,即使是一个有问题的实现也可能在表面上没有任何征兆。在这一章,我们将描述一种数学上的方法,用它来检查由你的代码计算得出的导数,从而保证你的实现是正确的。使用这里描述的导数检验方法将很大程度地提高你对代码正确性的信心。
:【二审】:
:【二审】:
 +
众所周知,反向传播算法(我之前都译为“传导”,大家基本都译为“传播”就先传播)是很难调试成功的,特别是,代码中存在很多易于出错的细微之处――比如说,索引的缺位错误(off-by-one error,二审注:如果仅是为了翻译,只要选个合适的词翻译就可,但为了让读者理解,我觉得有必要加上具体说明),因此可能就只求解了一部分层中的权重参数;或者代码中疏略了偏置项――学习的结果很可能是即让人吃惊又觉得很可信(事实是比正确的代码差多了)。因此,即使这代码是错误的,我们也很难轻易发现有什么东西遗漏了。本节中,我们将讨论一种对导数(导数的运算由代码实现)进行数值检测的方法,以确定你的代码是否正确。使用本节所述导数检测的方法,将非常有助于提升对你所写代码正确性的信心。
 +
缺位错误(Off-by-one error)说明:指的是,比如for 循环中循环m次,则应该是for(i=1; i<=m ;i++),但有时程序员疏忽,会写成for(i=1;i<m;i++),这就是缺位错误。
:【原文】:
:【原文】:
Line 31: Line 36:
\end{align}</math>
\end{align}</math>
:【初译】:
:【初译】:
 +
假设我们想要最小化变量<math>\textstyle \theta</math>的目标函数<math>\textstyle J(\theta)</math>。假设<math>\textstyle J : \Re \mapsto \Re</math>,则<math>\textstyle \theta \in \Re</math>。在一维的情况下,一次梯度下降的迭代便是
 +
:<math>\begin{align}
 +
\theta := \theta - \alpha \frac{d}{d\theta}J(\theta).
 +
\end{align}</math>
:【一审】:
:【一审】:
 +
假设我们想要最小化以<math>\textstyle \theta</math>为自变量的目标函数<math>\textstyle J(\theta)</math>。假设<math>\textstyle J : \Re \mapsto \Re</math>,则<math>\textstyle \theta \in \Re</math>。在一维的情况下,一次梯度下降的迭代便是
 +
:<math>\begin{align}
 +
\theta := \theta - \alpha \frac{d}{d\theta}J(\theta).
 +
\end{align}</math>
:【二审】:
:【二审】:
 +
假设我们想要最小化以<math>\textstyle \theta</math>为自变量的目标函数<math>\textstyle J(\theta)</math>。这里,<math>\textstyle J : \Re \mapsto \Re</math>,则<math>\textstyle \theta \in \Re</math>。在一维的情况下,一次梯度下降的迭代便是
 +
:<math>\begin{align}
 +
\theta := \theta - \alpha \frac{d}{d\theta}J(\theta).
 +
\end{align}</math>
:【原文】:
:【原文】:
Suppose also that we have implemented some function <math>\textstyle g(\theta)</math> that purportedly
Suppose also that we have implemented some function <math>\textstyle g(\theta)</math> that purportedly
Line 39: Line 56:
<math>\textstyle g</math> is correct?
<math>\textstyle g</math> is correct?
:【初译】:
:【初译】:
 +
再假设我们已经实现了某个计算<math>\textstyle \frac{d}{d\theta}J(\theta)</math>的函数<math>\textstyle g(\theta)</math>,于是我们使用<math>\textstyle \theta := \theta - \alpha g(\theta)</math>对<math>\textstyle \theta</math>更新而实现了梯度下降。那么我们如何检验<math>\textstyle g</math>的实现是否正确呢?
:【一审】:
:【一审】:
 +
再假设我们已经实现了某个计算<math>\textstyle \frac{d}{d\theta}J(\theta)</math>的函数<math>\textstyle g(\theta)</math>,于是我们使用<math>\textstyle \theta := \theta - \alpha g(\theta)</math>对<math>\textstyle \theta</math>更新,从而实现了梯度下降。那么我们如何检验<math>\textstyle g</math>的实现是否正确呢?
:【二审】:
:【二审】:
 +
再假设我们已经实现了某个计算<math>\textstyle \frac{d}{d\theta}J(\theta)</math>的函数<math>\textstyle g(\theta)</math>,于是我们使用<math>\textstyle \theta := \theta - \alpha g(\theta)</math>对<math>\textstyle \theta</math>进行更新,从而实现梯度下降。那么我们如何检验<math>\textstyle g</math>的实现是否正确呢?
:【原文】:
:【原文】:
Line 54: Line 74:
\end{align}</math>
\end{align}</math>
:【初译】:
:【初译】:
 +
回忆导数的数学定义:
 +
:<math>\begin{align}
 +
\frac{d}{d\theta}J(\theta) = \lim_{\epsilon \rightarrow 0}
 +
\frac{J(\theta+ \epsilon) - J(\theta-\epsilon)}{2 \epsilon}.
 +
\end{align}</math>
 +
因此对于任何<math>\textstyle \theta</math>值,我们都可以在数学上用:
 +
:<math>\begin{align}
 +
\frac{J(\theta+{\rm EPSILON}) - J(\theta-{\rm EPSILON})}{2 \times {\rm EPSILON}}
 +
\end{align}</math>
 +
近似。
:【一审】:
:【一审】:
 +
回忆导数的数学定义:
 +
:<math>\begin{align}
 +
\frac{d}{d\theta}J(\theta) = \lim_{\epsilon \rightarrow 0}
 +
\frac{J(\theta+ \epsilon) - J(\theta-\epsilon)}{2 \epsilon}.
 +
\end{align}</math>
 +
因此对于任何<math>\textstyle \theta</math>值,我们都可以在数学上用:
 +
:<math>\begin{align}
 +
\frac{J(\theta+{\rm EPSILON}) - J(\theta-{\rm EPSILON})}{2 \times {\rm EPSILON}}
 +
\end{align}</math>
 +
近似。
:【二审】:
:【二审】:
 +
回忆导数的数学定义:
 +
:<math>\begin{align}
 +
\frac{d}{d\theta}J(\theta) = \lim_{\epsilon \rightarrow 0}
 +
\frac{J(\theta+ \epsilon) - J(\theta-\epsilon)}{2 \epsilon}.
 +
\end{align}</math>
 +
因此对于任何<math>\textstyle \theta</math>值,我们都可以对此导数用:
 +
:<math>\begin{align}
 +
\frac{J(\theta+{\rm EPSILON}) - J(\theta-{\rm EPSILON})}{2 \times {\rm EPSILON}}
 +
\end{align}</math>
 +
近似。
:【原文】:
:【原文】:
In practice, we set <math>{\rm EPSILON}</math> to a small constant, say around <math>\textstyle 10^{-4}</math>.
In practice, we set <math>{\rm EPSILON}</math> to a small constant, say around <math>\textstyle 10^{-4}</math>.
Line 62: Line 112:
as that would lead to numerical roundoff errors.)
as that would lead to numerical roundoff errors.)
:【初译】:
:【初译】:
 +
实际应用中,我们常将<math>{\rm EPSILON}</math>设为在<math>\textstyle 10^{-4}</math>数量级的略小常量。虽然<math>{\rm EPSILON}</math>在很大范围里都能工作得很好,但是我们并不会将它设得太小,比如 <math>\textstyle 10^{-20}</math>,因为那将导致数值舍入误差。
:【一审】:
:【一审】:
 +
实际应用中,我们常将<math>{\rm EPSILON}</math>设为一个很小的常量,比如在<math>\textstyle 10^{-4}</math>数量级。虽然<math>{\rm EPSILON}</math>在很大范围里都能工作得很好,但是我们并不会将它设得太小,比如<math>\textstyle 10^{-20}</math>,因为那将导致数值舍入误差。
:【二审】:
:【二审】:
 +
实际应用中,我们常将<math>{\rm EPSILON}</math>设为一个很小的常量,比如在<math>\textstyle 10^{-4}</math>(虽然<math>{\rm EPSILON}</math>的取值范围可以很大,但是我们并不会将它设得太小,比如<math>\textstyle 10^{-20}</math>,因为那将导致数值舍入误差。)
:【原文】:
:【原文】:
Line 73: Line 126:
\frac{J(\theta+{\rm EPSILON}) - J(\theta-{\rm EPSILON})}{2 \times {\rm EPSILON}}.
\frac{J(\theta+{\rm EPSILON}) - J(\theta-{\rm EPSILON})}{2 \times {\rm EPSILON}}.
\end{align}</math>
\end{align}</math>
 +
 +
:【初译】:
 +
因此给定一个被认为能计算<math>\textstyle \frac{d}{d\theta}J(\theta)</math>的函数<math>\textstyle g(\theta)</math>,现在我们可以通过检查
 +
:<math>\begin{align}
 +
g(\theta) \approx
 +
\frac{J(\theta+{\rm EPSILON}) - J(\theta-{\rm EPSILON})}{2 \times {\rm EPSILON}}.
 +
\end{align}</math>
 +
是否成立来验证它的正确性。
 +
:【一审】:
 +
因此给定一个被认为能计算<math>\textstyle \frac{d}{d\theta}J(\theta)</math>的函数<math>\textstyle g(\theta)</math>,现在我们可以通过检查
 +
:<math>\begin{align}
 +
g(\theta) \approx
 +
\frac{J(\theta+{\rm EPSILON}) - J(\theta-{\rm EPSILON})}{2 \times {\rm EPSILON}}.
 +
\end{align}</math>
 +
是否成立来验证它的正确性。
 +
:【二审】:
 +
因此给定一个被认为能计算<math>\textstyle \frac{d}{d\theta}J(\theta)</math>的函数<math>\textstyle g(\theta)</math>,现在我们可以通过检查
 +
:<math>\begin{align}
 +
g(\theta) \approx
 +
\frac{J(\theta+{\rm EPSILON}) - J(\theta-{\rm EPSILON})}{2 \times {\rm EPSILON}}.
 +
\end{align}</math>
 +
是否成立来验证它的正确性。
 +
:【原文】:
The degree to which these two values should approximate each other
The degree to which these two values should approximate each other
will depend on the details of <math>\textstyle J</math>.  But assuming <math>\textstyle {\rm EPSILON} = 10^{-4}</math>,
will depend on the details of <math>\textstyle J</math>.  But assuming <math>\textstyle {\rm EPSILON} = 10^{-4}</math>,
Line 78: Line 154:
to at least 4 significant digits (and often many more).
to at least 4 significant digits (and often many more).
:【初译】:
:【初译】:
 +
“≈”两者有多接近取决于<math>\textstyle J</math>。但是在假定<math>\textstyle {\rm EPSILON} = 10^{-4}</math>的情况下,你通常会发现上式“≈”两边至少有4个有效数字一致(常会更多)。
:【一审】:
:【一审】:
 +
上式两端的值的接近程度取决于<math>\textstyle J</math>的具体形式。但是在假定<math>\textstyle {\rm EPSILON} = 10^{-4}</math>的情况下,你通常会发现上式左右两边的数值至少有4个有效数字一致(常会更多)。
:【二审】:
:【二审】:
 +
上式两端值的接近程度取决于<math>\textstyle J</math>的具体形式。但是在假定<math>\textstyle {\rm EPSILON} = 10^{-4}</math>的情况下,你通常会发现上式左右两边的数值至少会精确到4位有效数字(通常会更多)。
:【原文】:
:【原文】:

Revision as of 11:10, 9 March 2013

Personal tools