Skip to content

Commit ba993e1

Browse files
committed
added horovod functions and run scripts
1 parent 3560450 commit ba993e1

File tree

3 files changed

+523
-0
lines changed

3 files changed

+523
-0
lines changed

Pilot1/ST1/clr_callback.py

Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
from tensorflow.keras.callbacks import *
2+
from tensorflow.keras import backend as K
3+
import numpy as np
4+
5+
class CyclicLR(Callback):
6+
"""This callback implements a cyclical learning rate policy (CLR).
7+
The method cycles the learning rate between two boundaries with
8+
some constant frequency, as detailed in this paper (https://arxiv.org/abs/1506.01186).
9+
The amplitude of the cycle can be scaled on a per-iteration or
10+
per-cycle basis.
11+
This class has three built-in policies, as put forth in the paper.
12+
"triangular":
13+
A basic triangular cycle w/ no amplitude scaling.
14+
"triangular2":
15+
A basic triangular cycle that scales initial amplitude by half each cycle.
16+
"exp_range":
17+
A cycle that scales initial amplitude by gamma**(cycle iterations) at each
18+
cycle iteration.
19+
For more detail, please see paper.
20+
21+
# Example
22+
```python
23+
clr = CyclicLR(base_lr=0.001, max_lr=0.006,
24+
step_size=2000., mode='triangular')
25+
model.fit(X_train, Y_train, callbacks=[clr])
26+
```
27+
28+
Class also supports custom scaling functions:
29+
```python
30+
clr_fn = lambda x: 0.5*(1+np.sin(x*np.pi/2.))
31+
clr = CyclicLR(base_lr=0.001, max_lr=0.006,
32+
step_size=2000., scale_fn=clr_fn,
33+
scale_mode='cycle')
34+
model.fit(X_train, Y_train, callbacks=[clr])
35+
```
36+
# Arguments
37+
base_lr: initial learning rate which is the
38+
lower boundary in the cycle.
39+
max_lr: upper boundary in the cycle. Functionally,
40+
it defines the cycle amplitude (max_lr - base_lr).
41+
The lr at any cycle is the sum of base_lr
42+
and some scaling of the amplitude; therefore
43+
max_lr may not actually be reached depending on
44+
scaling function.
45+
step_size: number of training iterations per
46+
half cycle. Authors suggest setting step_size
47+
2-8 x training iterations in epoch.
48+
mode: one of {triangular, triangular2, exp_range}.
49+
Default 'triangular'.
50+
Values correspond to policies detailed above.
51+
If scale_fn is not None, this argument is ignored.
52+
gamma: constant in 'exp_range' scaling function:
53+
gamma**(cycle iterations)
54+
scale_fn: Custom scaling policy defined by a single
55+
argument lambda function, where
56+
0 <= scale_fn(x) <= 1 for all x >= 0.
57+
mode paramater is ignored
58+
scale_mode: {'cycle', 'iterations'}.
59+
Defines whether scale_fn is evaluated on
60+
cycle number or cycle iterations (training
61+
iterations since start of cycle). Default is 'cycle'.
62+
"""
63+
64+
def __init__(self, base_lr=0.001, max_lr=0.006, step_size=2000., mode='triangular',
65+
gamma=1., scale_fn=None, scale_mode='cycle'):
66+
super(CyclicLR, self).__init__()
67+
68+
self.base_lr = base_lr
69+
self.max_lr = max_lr
70+
self.step_size = step_size
71+
self.mode = mode
72+
self.gamma = gamma
73+
if scale_fn == None:
74+
if self.mode == 'triangular':
75+
self.scale_fn = lambda x: 1.
76+
self.scale_mode = 'cycle'
77+
elif self.mode == 'triangular2':
78+
self.scale_fn = lambda x: 1/(2.**(x-1))
79+
self.scale_mode = 'cycle'
80+
elif self.mode == 'exp_range':
81+
self.scale_fn = lambda x: gamma**(x)
82+
self.scale_mode = 'iterations'
83+
else:
84+
self.scale_fn = scale_fn
85+
self.scale_mode = scale_mode
86+
self.clr_iterations = 0.
87+
self.trn_iterations = 0.
88+
self.history = {}
89+
90+
self._reset()
91+
92+
def _reset(self, new_base_lr=None, new_max_lr=None,
93+
new_step_size=None):
94+
"""Resets cycle iterations.
95+
Optional boundary/step size adjustment.
96+
"""
97+
if new_base_lr != None:
98+
self.base_lr = new_base_lr
99+
if new_max_lr != None:
100+
self.max_lr = new_max_lr
101+
if new_step_size != None:
102+
self.step_size = new_step_size
103+
self.clr_iterations = 0.
104+
105+
def clr(self):
106+
cycle = np.floor(1+self.clr_iterations/(2*self.step_size))
107+
x = np.abs(self.clr_iterations/self.step_size - 2*cycle + 1)
108+
if self.scale_mode == 'cycle':
109+
return self.base_lr + (self.max_lr-self.base_lr)*np.maximum(0, (1-x))*self.scale_fn(cycle)
110+
else:
111+
return self.base_lr + (self.max_lr-self.base_lr)*np.maximum(0, (1-x))*self.scale_fn(self.clr_iterations)
112+
113+
def on_train_begin(self, logs={}):
114+
logs = logs or {}
115+
116+
if self.clr_iterations == 0:
117+
K.set_value(self.model.optimizer.lr, self.base_lr)
118+
else:
119+
K.set_value(self.model.optimizer.lr, self.clr())
120+
121+
def on_batch_end(self, epoch, logs=None):
122+
123+
logs = logs or {}
124+
self.trn_iterations += 1
125+
self.clr_iterations += 1
126+
127+
self.history.setdefault('lr', []).append(K.get_value(self.model.optimizer.lr))
128+
self.history.setdefault('iterations', []).append(self.trn_iterations)
129+
130+
for k, v in logs.items():
131+
self.history.setdefault(k, []).append(v)
132+
133+
K.set_value(self.model.optimizer.lr, self.clr())
Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
############# Module Loading ##############
2+
import argparse
3+
import os
4+
import numpy as np
5+
import matplotlib
6+
import pandas as pd
7+
8+
matplotlib.use("Agg")
9+
10+
import tensorflow as tf
11+
from tensorflow import keras
12+
from tensorflow.keras import backend as K
13+
from tensorflow.keras import layers
14+
from tensorflow.keras.callbacks import (
15+
CSVLogger,
16+
EarlyStopping,
17+
ModelCheckpoint,
18+
ReduceLROnPlateau,
19+
)
20+
21+
from tensorflow.keras.optimizers import Adam
22+
from tensorflow.keras.preprocessing import sequence, text
23+
import horovod.keras as hvd ### importing horovod to use data parallelization in another step
24+
import keras_tuner
25+
26+
from clr_callback import *
27+
from smiles_regress_transformer_funcs_hvd import *
28+
29+
#######Argument parsing#############
30+
31+
file_path = os.path.dirname(os.path.realpath(__file__))
32+
33+
# psr and args take input outside of the script and assign:
34+
# (1) file paths for data_path_train and data_path_vali
35+
# (2) number of training epochs
36+
37+
psr = argparse.ArgumentParser(description="input csv file")
38+
psr.add_argument("--in_train", default="in_train")
39+
psr.add_argument("--in_vali", default="in_vali")
40+
psr.add_argument("--ep", type=int, default=400)
41+
psr.add_argument("--num_heads", type=int, default=16)
42+
psr.add_argument("--DR_TB", type=float, default=0.1)
43+
psr.add_argument("--DR_ff", type=float, default=0.1)
44+
psr.add_argument("--activation", default="activation")
45+
psr.add_argument("--drop_post_MHA", type=bool, default=True)
46+
psr.add_argument("--lr", type=float, default=1e-5)
47+
psr.add_argument("--loss_fn", default="mean_squared_error")
48+
psr.add_argument("--hvd_switch", type=bool, default=True)
49+
50+
args = vars(psr.parse_args()) # returns dictionary mapping of an object
51+
52+
######## Set hyperparameters ########
53+
54+
EPOCH = args["ep"]
55+
num_heads = args["num_heads"]
56+
DR_TB = args["DR_TB"]
57+
DR_ff = args["DR_ff"]
58+
activation = args["activation"]
59+
dropout1 = args["drop_post_MHA"]
60+
lr = args["lr"]
61+
loss_fn = args["loss_fn"]
62+
BATCH = 32 # batch size used for training
63+
vocab_size = 40000
64+
maxlen = 250
65+
#act_fn='elu'
66+
#embed_dim = 128 # Embedding size for each token
67+
#num_heads = 16 # Number of attention heads
68+
#ff_dim = 128 # Hidden layer size in feed forward network inside transformer
69+
checkpt_file = "smile_regress.autosave.model.h5"
70+
csv_file = "smile_regress.training.log"
71+
patience_red_lr = 20
72+
patience_early_stop = 100
73+
hvd_switch = args["hvd_switch"]
74+
75+
########Create training and validation data#####
76+
77+
#x: tokenized sequence data, y: single value dock score
78+
data_path_train = args["in_train"]
79+
data_path_vali = args["in_vali"]
80+
81+
data_train = pd.read_csv(data_path_train)
82+
data_vali = pd.read_csv(data_path_vali)
83+
84+
data_train.head()
85+
# Dataset has type and smiles as the two fields
86+
# reshaping: y formatted as [[y_1],[y_2],...] with floats
87+
y_train = data_train["type"].values.reshape(-1, 1) * 1.0
88+
y_val = data_vali["type"].values.reshape(-1, 1) * 1.0
89+
90+
tokenizer = text.Tokenizer(num_words=vocab_size)
91+
tokenizer.fit_on_texts(data_train["smiles"])
92+
93+
x_train = prep_text(data_train["smiles"], tokenizer, maxlen)
94+
x_val = prep_text(data_vali["smiles"], tokenizer, maxlen)
95+
96+
######## Implement horovod if necessary ########
97+
if hvd_switch:
98+
lr, x_train, y_train = initialize_hvd(lr, x_train, y_train)
99+
x_train, y_train = implement_hvd(x_train, y_train)
100+
101+
102+
######## Build model #############
103+
104+
model = build_model(num_heads, DR_TB, DR_ff, activation, dropout1, lr, loss_fn, hvd_switch)
105+
106+
####### Set callbacks ##############
107+
callbacks = callback_setting (
108+
hvd_switch,
109+
checkpt_file,
110+
lr,
111+
csv_file,
112+
patience_red_lr,
113+
patience_early_stop
114+
)
115+
116+
####### Train model! #########
117+
118+
history = model.fit(
119+
x_train,
120+
y_train,
121+
batch_size=BATCH,
122+
epochs=EPOCH,
123+
verbose=1,
124+
validation_data=(x_val, y_val),
125+
callbacks=callbacks,
126+
)
127+

0 commit comments

Comments
 (0)