1 import numpy as np
2
3
5 """
6 A simple line search, takes a point, adds a step and returns it
7 Scales step according to given scales of the parameters and ignores
8 *magnitude* of gradient.
9
10 (in early development and experimental only at this point)
11 """
12 - def __init__(self, max_step=1, step_mod=3, **kwargs):
13 """
14 Needs to have :
15 - nothing
16 Can have :
17 - max_step: a maximum step control, a scalar or vector to restrict step size
18 in each direction (default 1)
19 - step_mod: a factor to divide the step when back-tracking (default 3)
20 - max_reduce_fac: max_step divided by this is the smallest step that will be tried (default 2000),
21 """
22 self.maxStepSize = max_step
23 self.stepMod = step_mod
24 if np.isscalar(max_step):
25 self.basis = None
26 self.dim = None
27 else:
28 self.dim = len(max_step)
29 self.basis = np.identity(self.dim)
30 try:
31 self.filter = kwargs['filter']
32 except KeyError:
33 self.filter = False
34 try:
35 self.maxReduceFac = kwargs['max_reduce_fac']
36 except KeyError:
37 self.maxReduceFac = 7
38
39
40
41
42
43
44 - def __call__(self, origin, state, **kwargs):
45 """
46 Returns a good candidate
47 Parameters :
48 - origin is the origin of the search
49 - state is the state of the optimizer
50 """
51 fun = kwargs['function']
52 d = state['direction']/np.linalg.norm(state['direction'])
53
54 if self.filter:
55 ndabs_log = -np.log10(np.abs(d))
56 mean_log = np.mean(ndabs_log)
57
58 direction = (ndabs_log > mean_log-1.5).astype(int)*d
59 else:
60 direction = d
61 state['direction'] = direction
62
63
64
65
66
67 maxStepSize = self.maxStepSize
68 if np.isscalar(maxStepSize):
69 stepSize = maxStepSize
70 else:
71 stepfacs = np.zeros(self.dim)
72 for d in range(self.dim):
73
74 try:
75 stepfacs[d] = abs(maxStepSize[d] / direction[d])
76 except ZeroDivisionError:
77
78
79 stepfacs[d] = Inf
80
81
82 stepSize = min(stepfacs)
83
84
85 i = 1
86 old_value = state['old_value']
87 not_done = True
88
89
90 init_step = stepSize
91 while not_done:
92 print "\nLinestep: i =", i, "step size =", stepSize, "direction =\n", direction
93 p = origin + i * stepSize * direction
94 print "Testing p = ", p
95 new_value = fun(p)
96 if new_value < old_value:
97 i += 1
98 old_value = new_value
99 else:
100 if i == 1:
101
102 if stepSize*self.maxReduceFac < init_step:
103 not_done = False
104 p = origin + (i-1) * stepSize * direction
105 else:
106 stepSize /= self.stepMod
107 else:
108
109 not_done = False
110 p = origin + (i-1) * stepSize * direction
111 state['alpha_step'] = stepSize
112 return p
113