-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathsci_trainer.py
129 lines (115 loc) · 4.93 KB
/
sci_trainer.py
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
127
128
129
# suppress tensorflow warnings (must be called before importing tensorflow)
import os
os.environ['TF_CPP_MIN_LOG_LEVEL'] = '3'
import tensorflow as tf
tf.compat.v1.logging.set_verbosity(tf.compat.v1.logging.ERROR)
import scipy.optimize
import numpy as np
class sci_Trainer:
"""
Optimize the keras network model using L-BFGS-B algorithm.
Attributes:
model: optimization target model.
samples: training samples.
factr: convergence condition. typical values for factr are: 1e12 for low accuracy;
1e7 for moderate accuracy; 10 for extremely high accuracy.
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: logging metrics.
progbar: progress bar.
"""
def __init__(self, model, x_train, y_train, first_order_trainer='rmsprop', batch_size=128, first_order_epochs=10,
factr=10, m=50, maxls=50, maxiter=15000):
# 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.iter = tf.Variable(0)
self.metrics = ['loss']
self.first_order_trainer = first_order_trainer
self.batch_size = batch_size
self.first_order_epochs = first_order_epochs
# 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.mse(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')
self.iter.assign_add(1)
tf.print("Iterations:", self.iter, "Loss Value:", loss)
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 train(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() ])
self.model.compile(optimizer=self.first_order_trainer, loss='mse')
print('Running First order optimizer: \n')
self.model.fit(x=self.x_train, y=self.y_train, batch_size=self.batch_size, epochs=self.first_order_epochs)
# optimize the weight vector
print('\nOptimizer: 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()