-
Notifications
You must be signed in to change notification settings - Fork 19
/
AutoGrad.m
54 lines (50 loc) · 1.29 KB
/
AutoGrad.m
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
function [f,g] = autoGrad(x,type,funObj,varargin)
% [f,g] = autoGrad(x,useComplex,funObj,varargin)
%
% Numerically compute gradient of objective function from function values
%
% type =
% 1 - forward-differencing (p+1 evaluations)
% 2 - central-differencing (more accurate, but requires 2p evaluations)
% 3 - complex-step derivative (most accurate and only requires p evaluations, but only works for certain objectives)
p = length(x);
if type == 1 % Use Finite Differencing
f = funObj(x,varargin{:});
mu = 2*sqrt(1e-12)*(1+norm(x));
diff = zeros(p,1);
for j = 1:p
e_j = zeros(p,1);
e_j(j) = 1;
diff(j,1) = funObj(x + mu*e_j,varargin{:});
end
g = (diff-f)/mu;
elseif type == 3 % Use Complex Differentials
mu = 1e-150;
diff = zeros(p,1);
for j = 1:p
e_j = zeros(p,1);
e_j(j) = 1;
diff(j,1) = funObj(x + mu*i*e_j,varargin{:});
end
f = mean(real(diff));
g = imag(diff)/mu;
else % Use Central Differencing
mu = 2*sqrt(1e-12)*(1+norm(x));
diff1 = zeros(p,1);
diff2 = zeros(p,1);
for j = 1:p
e_j = zeros(p,1);
e_j(j) = 1;
diff1(j,1) = funObj(x + mu*e_j,varargin{:});
diff2(j,1) = funObj(x - mu*e_j,varargin{:});
end
f = mean([diff1;diff2]);
g = (diff1 - diff2)/(2*mu);
end
if 0 % DEBUG CODE
[fReal gReal] = funObj(x,varargin{:});
[fReal f]
[gReal g]
diff
pause;
end