梯度检验 (Gradient Checking)
梯度检验帮我们节省了很多时间,也多次帮我发现backprop实施过程中的bug,接下来,我们看看如何利用它来调试或检验backprop的实施是否正确。
假设你的网络中含有下列参数,
w[1] 和
b[1] ……
w[l] 和
b[l] ,为了执行梯度检验,首先要做的就是,把所有参数转换成一个巨大的向量数据,你要做的就是把矩阵
w 转换成一个向量,把所有
w 矩阵转换成向量之后,做连接运算,得到一个巨型向量
θ ,该向量表示为参数
θ ,代价函数
J 是所有
w 和
b 的函数,现在你得到了一个
θ 的代价函数
J (即
J(θ) )。接着,你得到与
w 和
b 顺序相同的数据,你同样可以把
dw[1] 和
db[1] ……
dw[l] 和
db[l] 转换成一个新的向量,用它们来初始化大向量
dθ,它与
θ 具有相同维度。
同样的,把
dw[1] 转换成矩阵,
db[1] 已经是一个向量了,直到把
dw[l] 转换成矩阵,这样所有的
dw 都已经是矩阵,注意
dw[1] 与
w[1] 具有相同维度,
db[1] 与
b[1] 具有相同维度。经过相同的转换和连接运算操作之后,你可以把所有导数转换成一个大向量
dθ ,它与
θ 具有相同维度,现在的问题是
dθ 和代价函数
J 的梯度或坡度有什么关系?
这就是实施梯度检验的过程,英语里通常简称为“grad check”,首先,我们要清楚
J 是超参数
θ 的一个函数,你也可以将
J 函数展开为
J(θ1,θ2,θ3,⋯) ,不论超级参数向量
θ 的维度是多少,为了实施梯度检验,你要做的就是循环执行,从而对每个
i 也就是对每个
θ 组成元素计算
dθapprox[i] 的值,我使用双边误差,也就是
dθapprox[i]=2ϵJ(θ1,θ2,θ3,⋯,θi+ϵ,⋯)−J(θ1,θ2,θ3,⋯,θi−ϵ,⋯)
只对
θi 增加
ϵ ,其它项保持不变,因为我们使用的是双边误差,对另一边做同样的操作,只不过是减去
ϵ ,
θ 其它项全都保持不变。
从上节课中我们了解到这个值(
dθapprox[i] )应该逼近
dθ[i]=∂θi∂J ,
dθ[i] 是代价函数的偏导数,然后你需要对
i 的每个值都执行这个运算,最后得到两个向量,得到
dθ 的逼近值
dθapprox ,它与
dθ 具有相同维度,它们两个与
θ 具有相同维度,你要做的就是验证这些向量是否彼此接近。
具体来说,如何定义两个向量是否真的接近彼此?我一般做下列运算,计算这两个向量的距离,
dθappprox[i]−dθ[i] 的欧几里得范数,注意这里(
∣∣dθapprox−dθ∣∣2 )没有平方,它是误差平方之和,然后求平方根,得到欧式距离,然后用向量长度归一化,使用向量长度的欧几里得范数。分母只是用于预防这些向量太小或太大,分母使得这个方程式变成比率,我们实际执行这个方程式,
ϵ 可能为
10−7 ,使用这个取值范围内的
ϵ ,如果你发现计算方程式得到的值为
10−7 或更小,这就很好,这就意味着导数逼近很有可能是正确的,它的值非常小。
扫描二维码关注公众号,回复:
10608947 查看本文章
如果它的值在
10−5 范围内,我就要小心了,也许这个值没问题,但我会再次检查这个向量的所有项,确保没有一项误差过大,可能这里有bug。
如果左边这个方程式结果是
10−3 ,我就会担心是否存在bug,计算结果应该比小
10−3 很多,如果比
10−3 大很多,我就会很担心,担心是否存在bug。这时应该仔细检查所有
θ 项,看是否有一个具体的
i 值,使得
dθappprox[i] 与
dθ[i] 大不相同,并用它来追踪一些求导计算是否正确,经过一些调试,最终结果会是这种非常小的值(
10−7),那么,你的实施可能是正确的。
在实施神经网络时,我经常需要执行foreprop和backprop,然后我可能发现这个梯度检验有一个相对较大的值,我会怀疑存在bug,然后开始调试,调试,调试,调试一段时间后,我得到一个很小的梯度检验值,现在我可以很自信的说,神经网络实施是正确的。
现在你已经了解了梯度检验的工作原理,它帮助我在神经网络实施中发现了很多bug,希望它对你也有所帮助。
课程PPT