21
21
# https://arxiv.org/abs/1804.02395
22
22
#
23
23
###############################################################################
24
- """
25
- first and second order blackbox optimizers
26
- """
27
24
r"""Library of blackbox optimization algorithms.
28
25
29
26
Library of stateful blackbox optimization algorithms taking as input the values
35
32
import math
36
33
import numpy as np
37
34
from sklearn import linear_model
35
+ from absl import flags
36
+ import scipy .optimize as sp_opt
38
37
39
- import gradient_ascent_optimization_algorithms
38
+ from compiler_opt . es import gradient_ascent_optimization_algorithms
40
39
41
40
42
41
def filter_top_directions (perturbations , function_values , est_type ,
43
42
num_top_directions ):
44
43
"""Select the subset of top-performing perturbations.
45
44
46
- TODO(b/139662389): In the future, we may want (either here or inside the
47
- perturbation generator) to add assertions that Antithetic perturbations are
48
- delivered in the expected order (i.e (p_1, -p_1, p_2, -p_2,...)).
49
-
50
45
Args:
51
46
perturbations: np array of perturbations
52
47
For antithetic, it is assumed that the input puts the pair of
@@ -66,16 +61,16 @@ def filter_top_directions(perturbations, function_values, est_type,
66
61
"""
67
62
if not num_top_directions > 0 :
68
63
return (perturbations , function_values )
69
- if est_type == " forward_fd" :
64
+ if est_type == ' forward_fd' :
70
65
top_index = np .argsort (- function_values )
71
- elif est_type == " antithetic" :
66
+ elif est_type == ' antithetic' :
72
67
top_index = np .argsort (- np .abs (function_values [0 ::2 ] -
73
68
function_values [1 ::2 ]))
74
69
top_index = top_index [:num_top_directions ]
75
- if est_type == " forward_fd" :
70
+ if est_type == ' forward_fd' :
76
71
perturbations = perturbations [top_index ]
77
72
function_values = function_values [top_index ]
78
- elif est_type == " antithetic" :
73
+ elif est_type == ' antithetic' :
79
74
perturbations = np .concatenate (
80
75
(perturbations [2 * top_index ], perturbations [2 * top_index + 1 ]),
81
76
axis = 0 )
@@ -109,7 +104,7 @@ def run_step(self, perturbations, function_values, current_input,
109
104
New input obtained by conducting a single step of the blackbox
110
105
optimization procedure.
111
106
"""
112
- raise NotImplementedError (" Abstract method" )
107
+ raise NotImplementedError (' Abstract method' )
113
108
114
109
@abc .abstractmethod
115
110
def get_hyperparameters (self ):
@@ -123,7 +118,7 @@ def get_hyperparameters(self):
123
118
Returns:
124
119
The set of hyperparameters for blackbox function runs.
125
120
"""
126
- raise NotImplementedError (" Abstract method" )
121
+ raise NotImplementedError (' Abstract method' )
127
122
128
123
@abc .abstractmethod
129
124
def get_state (self ):
@@ -136,7 +131,7 @@ def get_state(self):
136
131
Returns:
137
132
The state of the optimizer.
138
133
"""
139
- raise NotImplementedError (" Abstract method" )
134
+ raise NotImplementedError (' Abstract method' )
140
135
141
136
@abc .abstractmethod
142
137
def update_state (self , evaluation_stats ):
@@ -149,7 +144,7 @@ def update_state(self, evaluation_stats):
149
144
150
145
Returns:
151
146
"""
152
- raise NotImplementedError (" Abstract method" )
147
+ raise NotImplementedError (' Abstract method' )
153
148
154
149
@abc .abstractmethod
155
150
def set_state (self , state ):
@@ -162,7 +157,7 @@ def set_state(self, state):
162
157
163
158
Returns:
164
159
"""
165
- raise NotImplementedError (" Abstract method" )
160
+ raise NotImplementedError (' Abstract method' )
166
161
167
162
168
163
class MCBlackboxOptimizer (BlackboxOptimizer ):
@@ -178,9 +173,9 @@ def __init__(self,
178
173
num_top_directions = 0 ,
179
174
ga_optimizer = None ):
180
175
# Check step_size and ga_optimizer
181
- if bool (step_size ) == bool (ga_optimizer ):
176
+ if (step_size is None ) == (ga_optimizer is None ):
182
177
raise ValueError (
183
- " Exactly one of step_size and ga_optimizer should be provided" )
178
+ ' Exactly one of step_size and ga_optimizer should be provided' )
184
179
if step_size :
185
180
ga_optimizer = gradient_ascent_optimization_algorithms .MomentumOptimizer (
186
181
step_size = step_size , momentum = 0.0 )
@@ -190,7 +185,7 @@ def __init__(self,
190
185
self .normalize_fvalues = normalize_fvalues
191
186
self .hyperparameters_update_method = hyperparameters_update_method
192
187
self .num_top_directions = num_top_directions
193
- if hyperparameters_update_method == " state_normalization" :
188
+ if hyperparameters_update_method == ' state_normalization' :
194
189
self .state_dim = extra_params [0 ]
195
190
self .nb_steps = 0
196
191
self .sum_state_vector = [0.0 ] * self .state_dim
@@ -217,9 +212,9 @@ def run_step(self, perturbations, function_values, current_input,
217
212
gradient = np .zeros (dim )
218
213
for i , perturbation in enumerate (top_ps ):
219
214
function_value = top_fs [i ]
220
- if self .est_type == " forward_fd" :
215
+ if self .est_type == ' forward_fd' :
221
216
gradient_sample = (function_value - current_value ) * perturbation
222
- elif self .est_type == " antithetic" :
217
+ elif self .est_type == ' antithetic' :
223
218
gradient_sample = function_value * perturbation
224
219
gradient_sample /= self .precision_parameter ** 2
225
220
gradient += gradient_sample
@@ -228,21 +223,21 @@ def run_step(self, perturbations, function_values, current_input,
228
223
# in that code, the denominator for antithetic was num_top_directions.
229
224
# we maintain compatibility for now so that the same hyperparameters
230
225
# currently used in Toaster will have the same effect
231
- if self .est_type == " antithetic" and len (top_ps ) < len (perturbations ):
226
+ if self .est_type == ' antithetic' and len (top_ps ) < len (perturbations ):
232
227
gradient *= 2
233
228
# Use the gradient ascent optimizer to compute the next parameters with the
234
229
# gradients
235
230
return self .ga_optimizer .run_step (current_input , gradient )
236
231
237
232
def get_hyperparameters (self ):
238
- if self .hyperparameters_update_method == " state_normalization" :
233
+ if self .hyperparameters_update_method == ' state_normalization' :
239
234
return self .mean_state_vector + self .std_state_vector
240
235
else :
241
236
return []
242
237
243
238
def get_state (self ):
244
239
ga_state = self .ga_optimizer .get_state ()
245
- if self .hyperparameters_update_method == " state_normalization" :
240
+ if self .hyperparameters_update_method == ' state_normalization' :
246
241
current_state = [self .nb_steps ]
247
242
current_state += self .sum_state_vector
248
243
current_state += self .squares_state_vector
@@ -252,7 +247,7 @@ def get_state(self):
252
247
return ga_state
253
248
254
249
def update_state (self , evaluation_stats ):
255
- if self .hyperparameters_update_method == " state_normalization" :
250
+ if self .hyperparameters_update_method == ' state_normalization' :
256
251
self .nb_steps += evaluation_stats [0 ]
257
252
evaluation_stats = evaluation_stats [1 :]
258
253
first_half = evaluation_stats [:self .state_dim ]
@@ -276,7 +271,7 @@ def update_state(self, evaluation_stats):
276
271
]
277
272
278
273
def set_state (self , state ):
279
- if self .hyperparameters_update_method == " state_normalization" :
274
+ if self .hyperparameters_update_method == ' state_normalization' :
280
275
self .nb_steps = state [0 ]
281
276
state = state [1 :]
282
277
self .sum_state_vector = state [:self .state_dim ]
@@ -290,17 +285,14 @@ def set_state(self, state):
290
285
self .ga_optimizer .set_state (state )
291
286
292
287
293
- """
294
- secondorder optimizers
295
- """
296
- r""" Experimental optimizers based on blackbox ES.
288
+ # pylint: disable=pointless-string-statement
289
+ """Secondorder optimizers.
290
+
291
+ Experimental optimizers based on blackbox ES.
297
292
298
293
See class descriptions for more detailed notes on each algorithm.
299
294
"""
300
295
301
- from absl import flags
302
- import scipy .optimize as sp_opt
303
-
304
296
_GRAD_TYPE = flags .DEFINE_string ('grad_type' , 'MC' , 'Gradient estimator.' )
305
297
_TR_INIT_RADIUS = flags .DEFINE_float ('tr_init_radius' , 1 ,
306
298
'Initial radius for TR method.' )
@@ -328,8 +320,6 @@ def set_state(self, state):
328
320
'Minimum radius of trust region.' )
329
321
330
322
DEFAULT_ARMIJO = 1e-4
331
-
332
- # pylint: disable=pointless-string-statement
333
323
"""Gradient estimators.
334
324
The blackbox pipeline has two steps:
335
325
estimate gradient/Hessian --> optimizer --> next weight
@@ -461,6 +451,8 @@ class QuadraticModel(object):
461
451
f(x) = 1/2x^TAx + b^Tx + c
462
452
"""
463
453
454
+ # pylint: disable=invalid-name
455
+ # argument Av should be capitalized as such for mathematical convention
464
456
def __init__ (self , Av , b , c = 0 ):
465
457
"""Initialize quadratic function.
466
458
@@ -474,6 +466,7 @@ def __init__(self, Av, b, c=0):
474
466
self .b = b
475
467
self .c = c
476
468
469
+ # pylint: enable=invalid-name
477
470
def f (self , x ):
478
471
"""Evaluate the quadratic function.
479
472
@@ -793,8 +786,7 @@ def trust_region_test(self, current_input, current_value):
793
786
absolute_max_reward = abs (current_value )
794
787
else :
795
788
absolute_max_reward = abs (self .accepted_function_value )
796
- if absolute_max_reward < 1e-8 :
797
- absolute_max_reward = 1e-8
789
+ absolute_max_reward = max (absolute_max_reward , 1e-08 )
798
790
abs_ratio = (
799
791
abs (current_value - self .accepted_function_value ) /
800
792
absolute_max_reward )
@@ -1028,8 +1020,8 @@ def run_step(self, perturbations, function_values, current_input,
1028
1020
# This point was just returned to after rejecting a step.
1029
1021
# We update the model by averaging the previous gradient/Hessian
1030
1022
# with the current perturbations. Then we set is_returned_step to False
1031
- # in preparation for taking the next step after re-solving the trust region
1032
- # at this point again, with smaller radius. """
1023
+ # in preparation for taking the next step after re-solving the
1024
+ # trust region at this point again, with smaller radius. """
1033
1025
self .accepted_quadratic_model = mf
1034
1026
self .accepted_weights = current_input
1035
1027
# This step has been accepted, so store the most recent quadratic model
0 commit comments