本文是吴恩达《机器学习》视频笔记第55篇,对应第5周第5个视频。
“Implementation note:——Gradient checking”
01
—
笔记
前面的小节中提过在前向网络、后向网络中计算导数的算法,但是反向传播算法因为实现起来比较复杂,所以会出现一些意想不到的bugs。
具体表现是,我们的代码看上去运行的很正常,而且代价函数也在不断的减小,但是因为不知道的bug的存在,使得我们得到的神经网络并不是最优解。
那有什么办法帮我们把这些不易觉察的bug给揪出来呢?一种思想就是本小节要讲的梯度检验。
说来也简单,就是我们使用一种和反向网络不同的方法来计算(估算)梯度,然后通过这个梯度值用来验证我们神经网络计算值的代码是否正确。具体怎么做呢?
先看一维的情况:这样的一个函数,我们怎么计算\theta点上的导数呢?
我们知道,这个点上的导数就是J(\Theta)曲线在这个点上的切线的斜率,如下图蓝色线。而我们可以用一个较小的值\epsilon在\theta点处的曲线点连接线的斜率值,用这个值来近似计算这个点的导数,如下图所示,下图下半部分的右边蓝色的被画了叉叉的公式是单侧差分,而我们用来近似导数的是双侧差分。
我们在Octave中用代码实现这个事的时候呢,就可以定义一个EPSILON的常量(比较小的),然后用下面这样一行代码:
就可以算出这一点的导数。
如果不是一维实数,而是一个向量用来计算偏导数呢?
其实在每一个分量上把其它量看出常数项就可以计算这个分量上的偏导数了,而且这样的计算和单一维度的实数的导数计算是类似的。如下图:
实现的代码看上去也不复杂,如下:
上图中是一个for循环,循环的次数n就是\theta向量的维度,循环体中就是实现了\theta向量中\theta_i分量的偏导数计算。即:
最后计算的结果放到gradApprox数组中。
接下来我们要做的事情是什么呢?我们就用上面的方法计算出来的梯度gradApprox和我们从反向传播中计算出来的梯度DVec进行比较,看它们是不是很接近。
把DVec计算、gradApprox计算、DVec和gradApprox这三件事串起来,具体的实现方法就是:
注意:在正式训练你的神经网络分类器的时候一定一定要关闭你的梯度检验函数,否则的话你的训练会非常非常的慢。
因为梯度检验仅仅是用来检验我们反向传播代码是不是正确,一旦确定了方向传播代码的正确性,梯度检验在神经网络训练中出来消耗更多的计算资源就毫无用处了。就像一座大桥我们在验收的时候会检测它的安全性,但不会每次有汽车经过之前都检测它的安全性。
02
—
视频
关注公众号:
加作者好友,进入学习群: