UFLDL新版教程与编程练习(四):Debugging: Gradient Checking(梯度检查)

UFLDL是吴恩达团队编写的较早的一门深度学习入门,里面理论加上练习的节奏非常好,每次都想快点看完理论去动手编写练习,因为他帮你打好了整个代码框架,也有详细的注释,所以我们只要实现一点核心的代码编写工作就行了,上手快!

我这里找不到新版对应这块的中文翻译了,-_-

第四节是:Debugging: Gradient Checking(梯度检查)

因为我们很多地方(包括接下来的几节教程)会用到梯度下降法,所以很多时候会计算到梯度,但是不能保证没有BUG,有时候就是因为梯度计算出错这种不明显的错,而导致整个代码运行不通,所以就引入了数值法的梯度检查。

基本思路就是:根据导数的定义:
\frac{d}{d \theta} J(\theta)=\lim _{\epsilon \rightarrow 0} \frac{J(\theta+\epsilon)-J(\theta-\epsilon)}{2 \epsilon} 这是极限的说法,用数值计算代替的话,就是找一个很小的EPSILON来作为那个趋近于0的数,用式子表示就是:
\frac{J(\theta+\mathrm{EPSILON})-J(\theta-\mathrm{EPSILON})}{2 \times \text { EPSILON }}

g(\theta) \approx \frac{J(\theta+\mathrm{EPSILON})-J(\theta-\mathrm{EPSILON})}{2 \times \text { EPSILON }}
$$
然后,与我们之前无论是线性回归里面或者是逻辑回归里面用的公式计算的梯度进行做差比较,以此来校验我们之前按公式编写的计算的梯度是否正确,下面是自带的grad_check.m代码,不难看出,就是根据以上的原理来检查的,只不过要选一个适当的:

function average_error = grad_check(fun, theta0, num_checks, varargin)

  delta=1e-3; 
  sum_error=0;

  fprintf(' Iter       i             err');
  fprintf('           g_est               g               f\n')

  for i=1:num_checks
    T = theta0;
    % y = randsample(n,k) returns k values sampled uniformly at random, without replacement, from the integers 1 to n.
    j = randsample(numel(T),1);
    T0=T; T0(j) = T0(j)-delta;
    T1=T; T1(j) = T1(j)+delta;

    [f,g] = fun(T, varargin{:});
    f0 = fun(T0, varargin{:});
    f1 = fun(T1, varargin{:});

    g_est = (f1-f0) / (2*delta);
    error = abs(g(j) - g_est);

    fprintf('% 5d  % 6d % 15g % 15f % 15f % 15f\n', ...
            i,j,error,g(j),g_est,f);

    sum_error = sum_error + error;
  end

  average_error=sum_error/num_checks;
  fprintf('average error:%.3f\n',average_error);

g_est:数值计算出来的梯度 g:调用之前梯度下降公式计算出来的梯度 error:两者之差

细心的话,不难发现,我在之前的线性回归(包括向量化与非向量化)和逻辑回归(包括向量化与非向量化)都已经用上了Gradient Checking(梯度检查),在相应的主函数里面是这样调用的:

average_error = grad_check(@linear_regression, theta, 10,train.X, train.y);
average_error = grad_check(@linear_regression_vec, theta, 10,train.X, train.y);

average_error = grad_check(@logistic_regression, theta, 10,train.X, train.y);
average_error = grad_check(@logistic_regression_vec, theta, 10,train.X, train.y);

不相信的看一下之前的几篇博客哦~~

有理解不到位之处,还请指出,有更好的想法,可以在下方评论交流!

你可能感兴趣的:(UFLDL新版教程与编程练习(四):Debugging: Gradient Checking(梯度检查))