LINE Solver
MATLAB API documentation
Loading...
Searching...
No Matches
hessian.m
1function [hess,err] = hessian(fun,x0)
2% hessian: estimate elements of the Hessian matrix (array of 2nd partials)
3% usage: [hess,err] = hessian(fun,x0)
4%
5% Hessian is NOT a tool for frequent use on an expensive
6% to evaluate objective function, especially in a large
7% number of dimensions. Its computation will use roughly
8% O(6*n^2) function evaluations for n parameters.
9%
10% arguments: (input)
11% fun - SCALAR analytical function to differentiate.
12% fun must be a function of the vector or array x0.
13% fun does not need to be vectorized.
14%
15% x0 - vector location at which to compute the Hessian.
16%
17% arguments: (output)
18% hess - nxn symmetric array of second partial derivatives
19% of fun, evaluated at x0.
20%
21% err - nxn array of error estimates corresponding to
22% each second partial derivative in hess.
23%
24%
25% Example usage:
26% Rosenbrock function, minimized at [1,1]
27% rosen = @(x) (1-x(1)).^2 + 105*(x(2)-x(1).^2).^2;
28%
29% [h,err] = hessian(rosen,[1 1])
30% h =
31% 842 -420
32% -420 210
33% err =
34% 1.0662e-12 4.0061e-10
35% 4.0061e-10 2.6654e-13
36%
37%
38% Example usage:
39% cos(x-y), at (0,0)
40% Note: this hessian matrix will be positive semi-definite
41%
42% hessian(@(xy) cos(xy(1)-xy(2)),[0 0])
43% ans =
44% -1 1
45% 1 -1
46%
47%
48% See also: derivest, gradient, gradest, hessdiag
49%
50%
51% Author: John D'Errico
52% e-mail: woodchips@rochester.rr.com
53% Release: 1.0
54% Release date: 2/10/2007
55
56% parameters that we might allow to change
57params.StepRatio = 2.0000001;
58params.RombergTerms = 3;
59
60% get the size of x0 so we can reshape
61% later.
62sx = size(x0);
63
64% was a string supplied?
65if ischar(fun)
66 fun = str2func(fun);
67end
68
69% total number of derivatives we will need to take
70nx = length(x0);
71
72% get the diagonal elements of the hessian (2nd partial
73% derivatives wrt each variable.)
74[hess,err] = hessdiag(fun,x0);
75
76% form the eventual hessian matrix, stuffing only
77% the diagonals for now.
78hess = diag(hess);
79err = diag(err);
80if nx<2
81 % the hessian matrix is 1x1. all done
82 return
83end
84
85% get the gradient vector. This is done only to decide
86% on intelligent step sizes for the mixed partials
87[grad,graderr,stepsize] = gradest(fun,x0);
88
89% Get params.RombergTerms+1 estimates of the upper
90% triangle of the hessian matrix
91dfac = params.StepRatio.^(-(0:params.RombergTerms)');
92for i = 2:nx
93 for j = 1:(i-1)
94 dij = zeros(params.RombergTerms+1,1);
95 for k = 1:(params.RombergTerms+1)
96 dij(k) = fun(x0 + swap2(zeros(sx),i, ...
97 dfac(k)*stepsize(i),j,dfac(k)*stepsize(j))) + ...
98 fun(x0 + swap2(zeros(sx),i, ...
99 -dfac(k)*stepsize(i),j,-dfac(k)*stepsize(j))) - ...
100 fun(x0 + swap2(zeros(sx),i, ...
101 dfac(k)*stepsize(i),j,-dfac(k)*stepsize(j))) - ...
102 fun(x0 + swap2(zeros(sx),i, ...
103 -dfac(k)*stepsize(i),j,dfac(k)*stepsize(j)));
104
105 end
106 dij = dij/4/prod(stepsize([i,j]));
107 dij = dij./(dfac.^2);
108
109 % Romberg extrapolation step
110 [hess(i,j),err(i,j)] = rombextrap(params.StepRatio,dij,[2 4]);
111 hess(j,i) = hess(i,j);
112 err(j,i) = err(i,j);
113 end
114end
115
116
117end % mainline function end
118
119% =======================================
120% sub-functions
121% =======================================
122function vec = swap2(vec,ind1,val1,ind2,val2)
123% swaps val as element ind, into the vector vec
124vec(ind1) = val1;
125vec(ind2) = val2;
126
127end % sub-function end
128
129
130% ============================================
131% subfunction - romberg extrapolation
132% ============================================
133function [der_romb,errest] = rombextrap(StepRatio,der_init,rombexpon)
134% do romberg extrapolation for each estimate
135%
136% StepRatio - Ratio decrease in step
137% der_init - initial derivative estimates
138% rombexpon - higher order terms to cancel using the romberg step
139%
140% der_romb - derivative estimates returned
141% errest - error estimates
142% amp - noise amplification factor due to the romberg step
143
144srinv = 1/StepRatio;
145
146% do nothing if no romberg terms
147nexpon = length(rombexpon);
148rmat = ones(nexpon+2,nexpon+1);
149switch nexpon
150 case 0
151 % rmat is simple: ones(2,1)
152 case 1
153 % only one romberg term
154 rmat(2,2) = srinv^rombexpon;
155 rmat(3,2) = srinv^(2*rombexpon);
156 case 2
157 % two romberg terms
158 rmat(2,2:3) = srinv.^rombexpon;
159 rmat(3,2:3) = srinv.^(2*rombexpon);
160 rmat(4,2:3) = srinv.^(3*rombexpon);
161 case 3
162 % three romberg terms
163 rmat(2,2:4) = srinv.^rombexpon;
164 rmat(3,2:4) = srinv.^(2*rombexpon);
165 rmat(4,2:4) = srinv.^(3*rombexpon);
166 rmat(5,2:4) = srinv.^(4*rombexpon);
167end
168
169% qr factorization used for the extrapolation as well
170% as the uncertainty estimates
171[qromb,rromb] = qr(rmat,0);
172
173% the noise amplification is further amplified by the Romberg step.
174% amp = cond(rromb);
175
176% this does the extrapolation to a zero step size.
177ne = length(der_init);
178rombcoefs = rromb\(qromb'*der_init);
179der_romb = rombcoefs(1,:)';
180
181% uncertainty estimate of derivative prediction
182s = sqrt(sum((der_init - rmat*rombcoefs).^2,1));
183rinv = rromb\eye(nexpon+1);
184cov1 = sum(rinv.^2,2); % 1 spare dof
185errest = s'*12.7062047361747*sqrt(cov1(1));
186
187end % rombextrap
188
189