Skip to content

Commit bf52c6b

Browse files
committed
2 parents 276e9ff + 4dfdb04 commit bf52c6b

File tree

5 files changed

+232
-9
lines changed

5 files changed

+232
-9
lines changed

examples/hyper_learn.py

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
from __future__ import print_function
2+
3+
import numpy as np
4+
from hyperopt import Trials, tpe
5+
6+
from plasma.conf import conf
7+
from pprint import pprint
8+
pprint(conf)
9+
#from plasma.primitives.shots import Shot, ShotList
10+
from plasma.preprocessor.normalize import Normalizer
11+
from plasma.models.loader import Loader
12+
#from plasma.models.runner import train, make_predictions,make_predictions_gpu
13+
14+
if conf['data']['normalizer'] == 'minmax':
15+
from plasma.preprocessor.normalize import MinMaxNormalizer as Normalizer
16+
elif conf['data']['normalizer'] == 'meanvar':
17+
from plasma.preprocessor.normalize import MeanVarNormalizer as Normalizer
18+
elif conf['data']['normalizer'] == 'var':
19+
from plasma.preprocessor.normalize import VarNormalizer as Normalizer #performs !much better than minmaxnormalizer
20+
elif conf['data']['normalizer'] == 'averagevar':
21+
from plasma.preprocessor.normalize import AveragingVarNormalizer as Normalizer #performs !much better than minmaxnormalizer
22+
else:
23+
print('unkown normalizer. exiting')
24+
exit(1)
25+
26+
np.random.seed(1)
27+
28+
print("normalization",end='')
29+
nn = Normalizer(conf)
30+
nn.train()
31+
loader = Loader(conf,nn)
32+
shot_list_train,shot_list_validate,shot_list_test = loader.load_shotlists(conf)
33+
print("...done")
34+
35+
print('Training on {} shots, testing on {} shots'.format(len(shot_list_train),len(shot_list_test)))
36+
from plasma.models import runner
37+
38+
specific_runner = runner.HyperRunner(conf,loader,shot_list_train)
39+
40+
best_run, best_model = specific_runner.frnn_minimize(algo=tpe.suggest,max_evals=2,trials=Trials())
41+
print (best_run)
42+
print (best_model)

plasma/conf.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,5 +8,7 @@
88
conf = parameters('./conf.yaml')
99
elif os.path.exists('./examples/conf.yaml'):
1010
conf = parameters('./examples/conf.yaml')
11+
elif os.path.exists('../examples/conf.yaml'):
12+
conf = parameters('../examples/conf.yaml')
1113
else:
1214
raise FileNotFoundError(errno.ENOENT, os.strerror(errno.ENOENT), 'conf.yaml')

plasma/models/builder.py

Lines changed: 79 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ def on_batch_end(self, batch, logs=None):
2020
self.losses.append(logs.get('loss'))
2121

2222

23-
class ModelBuilder():
23+
class ModelBuilder(object):
2424
def __init__(self,conf):
2525
self.conf = conf
2626

@@ -32,7 +32,6 @@ def get_unique_id(self):
3232
unique_id = hash(dill.dumps(this_conf))
3333
return unique_id
3434

35-
3635
def build_model(self,predict,custom_batch_size=None):
3736
conf = self.conf
3837
model_conf = conf['model']
@@ -158,3 +157,81 @@ def get_all_saved_files(self):
158157
if curr_id == unique_id:
159158
epochs.append(epoch)
160159
return epochs
160+
161+
162+
#FIXME this is essentially the ModelBuilder.build_model
163+
#in the long run we want to replace the space dictionary with the
164+
#regular conf file - I am sure there is a way to accomodate
165+
def hyper_build_model(self,space,predict,custom_batch_size=None):
166+
conf = self.conf
167+
model_conf = conf['model']
168+
rnn_size = model_conf['rnn_size']
169+
rnn_type = model_conf['rnn_type']
170+
optimizer = model_conf['optimizer']
171+
lr = model_conf['lr']
172+
clipnorm = model_conf['clipnorm']
173+
regularization = model_conf['regularization']
174+
175+
if optimizer == 'sgd':
176+
optimizer_class = SGD
177+
elif optimizer == 'adam':
178+
optimizer_class = Adam
179+
elif optimizer == 'rmsprop':
180+
optimizer_class = RMSprop
181+
elif optimizer == 'nadam':
182+
optimizer_class = Nadam
183+
else:
184+
optimizer = optimizer
185+
186+
if lr is not None or clipnorm is not None:
187+
optimizer = optimizer_class(lr = lr,clipnorm=clipnorm)
188+
189+
loss_fn = conf['data']['target'].loss#model_conf['loss']
190+
dropout_prob = model_conf['dropout_prob']
191+
length = model_conf['length']
192+
pred_length = model_conf['pred_length']
193+
skip = model_conf['skip']
194+
stateful = model_conf['stateful']
195+
return_sequences = model_conf['return_sequences']
196+
output_activation = conf['data']['target'].activation#model_conf['output_activation']
197+
num_signals = conf['data']['num_signals']
198+
199+
200+
batch_size = self.conf['training']['batch_size']
201+
if predict:
202+
batch_size = self.conf['model']['pred_batch_size']
203+
#so we can predict with one time point at a time!
204+
if return_sequences:
205+
length =pred_length
206+
else:
207+
length = 1
208+
209+
if custom_batch_size is not None:
210+
batch_size = custom_batch_size
211+
212+
if rnn_type == 'LSTM':
213+
rnn_model = LSTM
214+
elif rnn_type == 'SimpleRNN':
215+
rnn_model =SimpleRNN
216+
else:
217+
print('Unkown Model Type, exiting.')
218+
exit(1)
219+
220+
batch_input_shape=(batch_size,length, num_signals)
221+
model = Sequential()
222+
223+
for _ in range(model_conf['rnn_layers']):
224+
model.add(rnn_model(rnn_size, return_sequences=return_sequences,batch_input_shape=batch_input_shape,
225+
stateful=stateful,W_regularizer=l2(regularization),U_regularizer=l2(regularization),
226+
b_regularizer=l2(regularization),dropout_W=dropout_prob,dropout_U=dropout_prob))
227+
model.add(Dropout(space['Dropout']))
228+
if return_sequences:
229+
model.add(TimeDistributed(Dense(1,activation=output_activation)))
230+
else:
231+
model.add(Dense(1,activation=output_activation))
232+
model.compile(loss=loss_fn, optimizer=optimizer)
233+
model.reset_states()
234+
#model.compile(loss='mean_squared_error', optimizer='sgd') #for numerical output
235+
236+
return model
237+

plasma/models/mpi_runner.py

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -139,7 +139,7 @@ def get_val(self):
139139

140140

141141
class MPIModel():
142-
def __init__(self,model,optimizer,comm,batch_iterator,batch_size,num_replicas=None,warmup_steps=1000,lr=0.01):
142+
def __init__(self,model,optimizer,comm,batch_iterator,batch_size,num_replicas=None,warmup_steps=1000,lr=0.01,custom_num_workers=0):
143143
# random.seed(task_index)
144144
self.epoch = 0
145145
self.model = model
@@ -151,11 +151,16 @@ def __init__(self,model,optimizer,comm,batch_iterator,batch_size,num_replicas=No
151151
self.batch_size = batch_size
152152
self.batch_iterator = batch_iterator
153153
self.warmup_steps=warmup_steps
154-
self.num_workers = comm.Get_size()
154+
if custom_num_workers:
155+
if custom_num_workers < comm.Get_size():
156+
self.num_workers = custom_num_workers
157+
else: self.num_workers = comm.Get_size()
158+
else:
159+
self.num_workers = comm.Get_size()
155160
self.task_index = comm.Get_rank()
156161
self.history = cbks.History()
157162
if num_replicas is None or num_replicas < 1 or num_replicas > self.num_workers:
158-
self.num_replicas = num_workers
163+
self.num_replicas = self.num_workers
159164
else:
160165
self.num_replicas = num_replicas
161166

plasma/models/runner.py

Lines changed: 101 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,9 @@
66
import numpy as np
77
from itertools import imap
88

9+
from hyperopt import hp, STATUS_OK
10+
from hyperas.distributions import conditional
11+
912
import time
1013
import sys
1114
import os
@@ -17,7 +20,6 @@
1720
from plasma.utils.performance import PerformanceAnalyzer
1821
from plasma.utils.evaluation import *
1922

20-
2123
def train(conf,shot_list_train,loader):
2224

2325
np.random.seed(1)
@@ -99,8 +101,102 @@ def train(conf,shot_list_train,loader):
99101
plot_losses(conf,[training_losses,validation_losses,validation_roc],specific_builder,name='training_validation_roc')
100102
print('...done')
101103

102-
103-
104+
class HyperRunner(object):
105+
def __init__(self,conf,loader,shot_list):
106+
self.loader = loader
107+
self.shot_list = shot_list
108+
self.conf = conf
109+
110+
#FIXME setup for hyperas search
111+
def keras_fmin_fnct(self,space):
112+
from plasma.models import builder
113+
114+
specific_builder = builder.ModelBuilder(self.conf)
115+
116+
train_model, test_model = specific_builder.hyper_build_model(space,False), specific_builder.hyper_build_model(space,True)
117+
118+
np.random.seed(1)
119+
validation_losses = []
120+
validation_roc = []
121+
training_losses = []
122+
shot_list_train,shot_list_validate = self.shot_list.split_direct(1.0-conf['training']['validation_frac'],do_shuffle=True)
123+
os.environ['THEANO_FLAGS'] = 'device=gpu,floatX=float32'
124+
import theano
125+
from keras.utils.generic_utils import Progbar
126+
from keras import backend as K
127+
128+
129+
num_epochs = self.conf['training']['num_epochs']
130+
num_at_once = self.conf['training']['num_shots_at_once']
131+
lr_decay = self.conf['model']['lr_decay']
132+
lr = self.conf['model']['lr']
133+
134+
resulting_dict = {'loss':None,'status':STATUS_OK,'model':None}
135+
136+
e = -1
137+
#print("Current num_epochs {}".format(e))
138+
while e < num_epochs-1:
139+
e += 1
140+
pbar = Progbar(len(shot_list_train))
141+
142+
shot_list_train.shuffle()
143+
shot_sublists = shot_list_train.sublists(num_at_once)[:1]
144+
training_losses_tmp = []
145+
146+
K.set_value(train_model.optimizer.lr, lr*lr_decay**(e))
147+
for (i,shot_sublist) in enumerate(shot_sublists):
148+
X_list,y_list = self.loader.load_as_X_y_list(shot_sublist)
149+
for j,(X,y) in enumerate(zip(X_list,y_list)):
150+
history = builder.LossHistory()
151+
train_model.fit(X,y,
152+
batch_size=Loader.get_batch_size(self.conf['training']['batch_size'],prediction_mode=False),
153+
nb_epoch=1,shuffle=False,verbose=0,
154+
validation_split=0.0,callbacks=[history])
155+
train_model.reset_states()
156+
train_loss = np.mean(history.losses)
157+
training_losses_tmp.append(train_loss)
158+
159+
pbar.add(1.0*len(shot_sublist)/len(X_list), values=[("train loss", train_loss)])
160+
self.loader.verbose=False
161+
sys.stdout.flush()
162+
training_losses.append(np.mean(training_losses_tmp))
163+
specific_builder.save_model_weights(train_model,e)
164+
165+
roc_area,loss = make_predictions_and_evaluate_gpu(self.conf,shot_list_validate,self.loader)
166+
print("Epoch: {}, loss: {}, validation_losses_size: {}".format(e,loss,len(validation_losses)))
167+
validation_losses.append(loss)
168+
validation_roc.append(roc_area)
169+
resulting_dict['loss'] = loss
170+
resulting_dict['model'] = train_model
171+
#print("Results {}, before {}".format(resulting_dict,id(resulting_dict)))
172+
173+
#print("Results {}, after {}".format(resulting_dict,id(resulting_dict)))
174+
return resulting_dict
175+
176+
def get_space(self):
177+
return {
178+
'Dropout': hp.uniform('Dropout', 0, 1),
179+
}
180+
181+
def frnn_minimize(self, algo, max_evals, trials, rseed=1337):
182+
from hyperopt import fmin
183+
184+
best_run = fmin(self.keras_fmin_fnct,
185+
space=self.get_space(),
186+
algo=algo,
187+
max_evals=max_evals,
188+
trials=trials,
189+
rstate=np.random.RandomState(rseed))
190+
191+
best_model = None
192+
for trial in trials:
193+
vals = trial.get('misc').get('vals')
194+
for key in vals.keys():
195+
vals[key] = vals[key][0]
196+
if trial.get('misc').get('vals') == best_run and 'model' in trial.get('result').keys():
197+
best_model = trial.get('result').get('model')
198+
199+
return best_run, best_model
104200

105201
def plot_losses(conf,losses_list,specific_builder,name=''):
106202
unique_id = specific_builder.get_unique_id()
@@ -140,7 +236,8 @@ def make_predictions(conf,shot_list,loader):
140236
model_save_path = specific_builder.get_latest_save_path()
141237

142238
start_time = time.time()
143-
pool = mp.Pool()
239+
use_cores = max(1,mp.cpu_count()-2)
240+
pool = mp.Pool(use_cores)
144241
fn = partial(make_single_prediction,builder=specific_builder,loader=loader,model_save_path=model_save_path)
145242

146243
print('running in parallel on {} processes'.format(pool._processes))

0 commit comments

Comments
 (0)