-
Notifications
You must be signed in to change notification settings - Fork 5
Expand file tree
/
Copy pathoptimizer.py
More file actions
126 lines (113 loc) · 4.64 KB
/
Copy pathoptimizer.py
File metadata and controls
126 lines (113 loc) · 4.64 KB
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
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
import scipy.optimize
import numpy as np
import tensorflow as tf
class L_BFGS_B:
"""
Optimize the keras network model using L-BFGS-B algorithm.
Attributes:
model: optimization target model.
samples: training samples.
factr: function convergence condition. typical values for factr are: 1e12 for low accuracy;
1e7 for moderate accuracy; 10.0 for extremely high accuracy.
pgtol: gradient convergence condition.
m: maximum number of variable metric corrections used to define the limited memory matrix.
maxls: maximum number of line search steps (per iteration).
maxiter: maximum number of iterations.
metris: log metrics
progbar: progress bar
"""
def __init__(self, model, x_train, y_train, factr=1e5, m=50, maxls=50, maxiter=30000):
"""
Args:
model: optimization target model.
samples: training samples.
factr: convergence condition. typical values for factr are: 1e12 for low accuracy;
1e7 for moderate accuracy; 10.0 for extremely high accuracy.
pgtol: gradient convergence condition.
m: maximum number of variable metric corrections used to define the limited memory matrix.
maxls: maximum number of line search steps (per iteration).
maxiter: maximum number of iterations.
"""
# set attributes
self.model = model
self.x_train = [ tf.constant(x, dtype=tf.float32) for x in x_train ]
self.y_train = [ tf.constant(y, dtype=tf.float32) for y in y_train ]
self.factr = factr
self.m = m
self.maxls = maxls
self.maxiter = maxiter
self.metrics = ['loss']
# initialize the progress bar
self.progbar = tf.keras.callbacks.ProgbarLogger(
count_mode='steps', stateful_metrics=self.metrics)
self.progbar.set_params( {
'verbose':1, 'epochs':1, 'steps':self.maxiter, 'metrics':self.metrics})
def set_weights(self, flat_weights):
"""
Set weights to the model.
Args:
flat_weights: flatten weights.
"""
# get model weights
shapes = [ w.shape for w in self.model.get_weights() ]
# compute splitting indices
split_ids = np.cumsum([ np.prod(shape) for shape in [0] + shapes ])
# reshape weights
weights = [ flat_weights[from_id:to_id].reshape(shape)
for from_id, to_id, shape in zip(split_ids[:-1], split_ids[1:], shapes) ]
# set weights to the model
self.model.set_weights(weights)
@tf.function
def tf_evaluate(self, x, y):
"""
Evaluate loss and gradients for weights as tf.Tensor.
Args:
x: input data.
Returns:
loss and gradients for weights as tf.Tensor.
"""
with tf.GradientTape() as g:
loss = tf.reduce_mean(tf.keras.losses.logcosh(self.model(x), y))
grads = g.gradient(loss, self.model.trainable_variables)
return loss, grads
def evaluate(self, weights):
"""
Evaluate loss and gradients for weights as ndarray.
Args:
weights: flatten weights.
Returns:
loss and gradients for weights as ndarray.
"""
# update weights
self.set_weights(weights)
# compute loss and gradients for weights
loss, grads = self.tf_evaluate(self.x_train, self.y_train)
# convert tf.Tensor to flatten ndarray
loss = loss.numpy().astype('float64')
grads = np.concatenate([ g.numpy().flatten() for g in grads ]).astype('float64')
return loss, grads
def callback(self, weights):
"""
Callback that prints the progress to stdout.
Args:
weights: flatten weights.
"""
self.progbar.on_batch_begin(0)
loss, _ = self.evaluate(weights)
self.progbar.on_batch_end(0, logs=dict(zip(self.metrics, [loss])))
def fit(self):
"""
Train the model using L-BFGS-B algorithm.
"""
# get initial weights as a flat vector
initial_weights = np.concatenate(
[ w.flatten() for w in self.model.get_weights() ])
# optimize the weight vector
print('Optimizer: L-BFGS-B (maxiter={})'.format(self.maxiter))
self.progbar.on_train_begin()
self.progbar.on_epoch_begin(1)
scipy.optimize.fmin_l_bfgs_b(func=self.evaluate, x0=initial_weights,
factr=self.factr, m=self.m,
maxls=self.maxls, maxiter=self.maxiter, callback=self.callback)
self.progbar.on_epoch_end(1)
self.progbar.on_train_end()