wolffd@0
|
1 function [gradient, delta] = gradchek(w, func, grad, varargin)
|
wolffd@0
|
2 %GRADCHEK Checks a user-defined gradient function using finite differences.
|
wolffd@0
|
3 %
|
wolffd@0
|
4 % Description
|
wolffd@0
|
5 % This function is intended as a utility for other netlab functions
|
wolffd@0
|
6 % (particularly optimisation functions) to use. It enables the user to
|
wolffd@0
|
7 % check whether a gradient calculation has been correctly implmented
|
wolffd@0
|
8 % for a given function. GRADCHEK(W, FUNC, GRAD) checks how accurate the
|
wolffd@0
|
9 % gradient GRAD of a function FUNC is at a parameter vector X. A
|
wolffd@0
|
10 % central difference formula with step size 1.0e-6 is used, and the
|
wolffd@0
|
11 % results for both gradient function and finite difference
|
wolffd@0
|
12 % approximation are printed. The optional return value GRADIENT is the
|
wolffd@0
|
13 % gradient calculated using the function GRAD and the return value
|
wolffd@0
|
14 % DELTA is the difference between the functional and finite difference
|
wolffd@0
|
15 % methods of calculating the graident.
|
wolffd@0
|
16 %
|
wolffd@0
|
17 % GRADCHEK(X, FUNC, GRAD, P1, P2, ...) allows additional arguments to
|
wolffd@0
|
18 % be passed to FUNC and GRAD.
|
wolffd@0
|
19 %
|
wolffd@0
|
20 % See also
|
wolffd@0
|
21 % CONJGRAD, GRADDESC, HMC, OLGD, QUASINEW, SCG
|
wolffd@0
|
22 %
|
wolffd@0
|
23
|
wolffd@0
|
24 % Copyright (c) Ian T Nabney (1996-2001)
|
wolffd@0
|
25
|
wolffd@0
|
26 % Reasonable value for step size
|
wolffd@0
|
27 epsilon = 1.0e-6;
|
wolffd@0
|
28
|
wolffd@0
|
29 func = fcnchk(func, length(varargin));
|
wolffd@0
|
30 grad = fcnchk(grad, length(varargin));
|
wolffd@0
|
31
|
wolffd@0
|
32 % Treat
|
wolffd@0
|
33 nparams = length(w);
|
wolffd@0
|
34 deltaf = zeros(1, nparams);
|
wolffd@0
|
35 step = zeros(1, nparams);
|
wolffd@0
|
36 for i = 1:nparams
|
wolffd@0
|
37 % Move a small way in the ith coordinate of w
|
wolffd@0
|
38 step(i) = 1.0;
|
wolffd@0
|
39 fplus = feval('linef', epsilon, func, w, step, varargin{:});
|
wolffd@0
|
40 fminus = feval('linef', -epsilon, func, w, step, varargin{:});
|
wolffd@0
|
41 % Use central difference formula for approximation
|
wolffd@0
|
42 deltaf(i) = 0.5*(fplus - fminus)/epsilon;
|
wolffd@0
|
43 step(i) = 0.0;
|
wolffd@0
|
44 end
|
wolffd@0
|
45 gradient = feval(grad, w, varargin{:});
|
wolffd@0
|
46 fprintf(1, 'Checking gradient ...\n\n');
|
wolffd@0
|
47 delta = gradient - deltaf;
|
wolffd@0
|
48 fprintf(1, ' analytic diffs delta\n\n');
|
wolffd@0
|
49 disp([gradient', deltaf', delta'])
|