机器学习算法的调试 —— 梯度检验(Gradient Checking)
2016-04-29 09:19
190 查看
反向传播算法很难调试得到正确结果,尤其是当实现程序存在很多难于发现的bug 时。举例来说,索引的缺位错误(off-by-one error)会导致只有部分层的权重得到训练(
θ:=θ−αddθJ(θ)
我们不妨以 Sigmoid 函数为例,也即 f(z)=11+exp(−z),其导数形式为 f′(z)=g(z)=f(z)(1−f(z)),我们可轻易地编程实践,接着我们便可使用 θ:=θ−αddθJ(θ)来实现梯度下降算法,那么我们如何知道 g(z)梯度的正确性呢。
回忆导数的数学定义:
ddθJ=limϵ→0J(θ+ϵ)−J(θ−ϵ)2ϵ
由此我们可得梯度校验的数值校验公式:
g(θ)≈J(θ+ϵ)−J(θ−ϵ)2ϵ
这便是梯度检验的原理。在实际应用中,我们常将 ϵ 设为一个很小的常量,比如 10−4 数量级,我们不会将它设得太小,比如 10−20,因为那将导致数值舍入误差。 事实上,上式两端值的接近程度取决于 J 的具体形式,但在假定 ϵ=10−4 的情况 下,通常会发现左右两端至少有四位有效数字是一致的(或者说精度至少在0.0001一级)。
for(i=1; i<=m; ++i)被漏写为
for(i=1; i<m; ++i)),再比如忘记计算偏置项。这些错误会使你得到一个看似十分合理的结果(但实际上比正确代码的结果要差)。因此,仅从计算结果上来看,我们很难发现代码中有什么东西遗漏了。本节中,我们将介绍一种对求导结果进行数值检验的方法,该方法可以验证求导代码是否正确。另外,使用本节所述求导检验方法,可以帮助你提升写正确代码的信心。
数学原理
考虑我们想要最小化以 θ 为自变量的目标函数 J(θ)(θ 可以为标量和可以为矢量,在 Numpy 的编程环境下,处理是一样的),迭代梯度更新公式为:θ:=θ−αddθJ(θ)
我们不妨以 Sigmoid 函数为例,也即 f(z)=11+exp(−z),其导数形式为 f′(z)=g(z)=f(z)(1−f(z)),我们可轻易地编程实践,接着我们便可使用 θ:=θ−αddθJ(θ)来实现梯度下降算法,那么我们如何知道 g(z)梯度的正确性呢。
回忆导数的数学定义:
ddθJ=limϵ→0J(θ+ϵ)−J(θ−ϵ)2ϵ
由此我们可得梯度校验的数值校验公式:
g(θ)≈J(θ+ϵ)−J(θ−ϵ)2ϵ
这便是梯度检验的原理。在实际应用中,我们常将 ϵ 设为一个很小的常量,比如 10−4 数量级,我们不会将它设得太小,比如 10−20,因为那将导致数值舍入误差。 事实上,上式两端值的接近程度取决于 J 的具体形式,但在假定 ϵ=10−4 的情况 下,通常会发现左右两端至少有四位有效数字是一致的(或者说精度至少在0.0001一级)。
编程实现
import numpy as np def sigmoid(z): return 1./(1+np.exp(-z)) def sigmoid_prime(z): return sigmoid(z)*(1-sigmoid(z)) def check_gradient(f, x0, epsilon): return (f(x0+epsilon) - f(x0-epsilon))/2/epsilon if __name__ == '__main__': x0 = np.array([1, 2, 3]) epsilon = 1e-4 print(sigmoid_prime(x0)) # [ 0.19661193 0.10499359 0.04517666] print(check_gradient(sigmoid, x0, epsilon)) # [ 0.19661193 0.10499359 0.04517666]
References
[1] 梯度检验与高级优化相关文章推荐
- HDU2098 分拆素数和
- iOS-Android Android自定义日历,可以点击、标注日期、节气、旧历等
- Winform文件下载之WinINet
- 排序链表去重
- 各种编码UNICODE、UTF-8、ANSI、ASCII、GB2312、GBK详解
- 一份关于jvm内存调优及原理的学习笔记
- js跳转
- cordova 插件
- 如何在Windows下搭建Android开发环境
- Problem P
- Problem P
- 为非官方WordPress主题添加在线升级更新功能
- 订单流程独立一些特别处理
- Xshell怎样登陆本地虚拟机
- 实验6 201306114104彭得源
- window绝对路径与相对路径
- iOS中使用URL Scheme进行App跳转的教程
- leetcode 283. Move Zeroes
- 使用批处理文件(*.bat)同时打多个cmd窗口
- 给驱动加入ioctl控制