1
2
3
4
5 """
6 Computes a Marquardt step for a specific function at a specific point
7 """
8
9 import numpy
10 import numpy.linalg
11
13 """
14 The simple gradient step
15 """
17 """
18 Computes the Marquardt step
19 - gamma is the initial Marquardt correction factor (gamma = 1e4)
20 - c1 is the decreasing factor (c1 = 0.5)
21 - c2 is the increasing factor (c2 = 2.)
22 """
23 self.gamma = kwargs.get('gamma', 1.e4)
24 self.c1 = kwargs.get('c1', 0.5)
25 self.c2 = kwargs.get('c2', 2.)
26
27 - def __call__(self, function, point, state):
28 """
29 Computes a gradient step based on a function and a point
30 """
31 if 'gamma' in state:
32 gamma = state['gamma']
33 else:
34 gamma = self.gamma
35
36 hessian = function.hessian(point)
37 gradient = function.gradient(point)
38 approx_hessian = hessian + numpy.diag([gamma] * len(gradient))
39 step = (-numpy.linalg.solve(approx_hessian, gradient)).reshape(point.shape)
40
41 f0 = function(point)
42 f1 = function(point + step)
43 if f1 < f0:
44 gamma = self.c1 * gamma
45 else:
46 gamma = self.c2 * gamma
47
48 state['hessian'] = hessian
49 state['approx_hessian'] = approx_hessian
50 state['gradient'] = gradient
51 state['direction'] = step
52 state['gamma'] = gamma
53 return step
54