main/core.py
def train_model(model, data, nb_epoch=0, batch_size=1, lr_func=None, patience=10, verbose=False):
    '''Trains the model.

    inputs:
        model - a Keras model
        data - three dictionaries for training,
                validation, and testing separately
        nb_epoch - number of epochs to train for
        batch_size - batch_size to use on the data. This must agree with what was
                specified for data (i.e., if tensors are padded or not)
        lr_func - string which is evaluated with 'epoch' to produce the learning 
                rate at each epoch 
        patience - number of epochs to wait when no progress is being made in 
                the validation loss. a patience of -1 means that the model will
                use weights from the best-performing model during training

    outputs:
        model - a trained Keras model
        loss - list of training losses corresponding to each epoch 
        val_loss - list of validation losses corresponding to each epoch'''

    # Unpack data 
    (train, val, _) = data
    mols_train = train['mols']; y_train = train['y']
    mols_val   = val['mols'];   y_val   = val['y']
    print('{} to train on'.format(len(mols_train)))
    print('{} to validate on'.format(len(mols_val)))

    # Create learning rate function
    if lr_func:
        lr_func_string = 'def lr(epoch):\n    return {}\n'.format(lr_func)
        exec(lr_func_string)

    print(f"The initial learning rate: {K.eval(model.optimizer.lr)}")

    # Fit (allows keyboard interrupts in the middle)
    # Because molecular graph tensors are different sizes based on N_atoms, can only do one at a time
    # (alternative is to pad with zeros and try to add some masking feature to GraphFP)
    # -> this is why batch_size == 1 is treated distinctly
    try:
        loss = []
        val_loss = []

        if batch_size == 1: # DO NOT NEED TO PAD
            wait = 0
            prev_best_val_loss = 99999999
            for i in range(nb_epoch):
                this_loss = []
                this_val_loss = []
                if lr_func:
                    model.optimizer.lr.set_value(lr(i))
                    print('Epoch {}/{}, lr = {}'.format(i + 1, nb_epoch, K.eval(model.optimizer.lr)))
                else:
                    # if we use Adam or sth and don't use lr_func, we cannot get the current learning rate
                    print('Epoch {}/{}'.format(i + 1, nb_epoch))


                # Run through training set
                if verbose: print('Training...')
                training_order = list(range(len(mols_train)))
                np.random.shuffle(training_order)
                for j in training_order:
                    single_mol = mols_train[j]
                    single_y_as_array = np.reshape(y_train[j], (1, -1))
                    sloss = model.train_on_batch(
                        [np.array([single_mol[0]]), np.array([single_mol[1]]), np.array([single_mol[2]])],
                        single_y_as_array
                    )
                    this_loss.append(sloss)

                # Run through testing set
                if verbose: print('Validating..')
                for j in range(len(mols_val)):
                    single_mol = mols_val[j]
                    single_y_as_array = np.reshape(y_val[j], (1, -1))
                    sloss = model.test_on_batch(
                        [np.array([single_mol[0]]), np.array([single_mol[1]]), np.array([single_mol[2]])],
                        single_y_as_array
                    )
                    this_val_loss.append(sloss)
                
                loss.append(np.mean(this_loss))
                val_loss.append(np.mean(this_val_loss))
                print('loss: {}\tval_loss: {}'.format(loss[i], val_loss[i]))

                # Check progress
                if np.mean(this_val_loss) < prev_best_val_loss:
                    wait = 0
                    prev_best_val_loss = np.mean(this_val_loss)
                    if patience == -1:
                        model.save_weights('best.h5', overwrite=True)
                else:
                    wait = wait + 1
                    print('{} epochs without val_loss progress'.format(wait))
                    if wait == patience:
                        print('stopping early!')
                        break
            if patience == -1:
                model.load_weights('best.h5')

        else: 
            # When the batch_size is larger than one, we have padded mol tensors
            # which  means we need to concatenate them but can use Keras' built-in
            # training functions with callbacks, validation_split, etc.
            if lr_func:
                callbacks = [LearningRateScheduler(lr)]
            else:
                callbacks = []
            if patience != -1:
                callbacks.append(EarlyStopping(patience = patience, verbose = 1))

            if mols_val:
                mols = np.vstack((mols_train, mols_val))
                y = np.concatenate((y_train, y_val))
                hist = model.fit(mols, y, 
                    nb_epoch = nb_epoch, 
                    batch_size = batch_size, 
                    validation_split = (1 - float(len(mols_train))/(len(mols_val) + len(mols_train))),
                    verbose = verbose,
                    callbacks = callbacks)    
            else:
                hist = model.fit(np.array(mols_train), np.array(y_train), 
                    nb_epoch = nb_epoch, 
                    batch_size = batch_size, 
                    verbose = verbose,
                    callbacks = callbacks)    
            
            loss = []; val_loss = []
            if 'loss' in hist.history: loss = hist.history['loss']
            if 'val_loss' in hist.history: val_loss = hist.history['val_loss']

    except KeyboardInterrupt:
        print('User terminated training early (intentionally)')

    return (model, loss, val_loss)
Trains the model.

    inputs:
        model - a Keras model
        data - three dictionaries for training,
                validation, and testing separately
        nb_epoch - number of epochs to train for
        batch_size - batch_size to use on the data. This must agree with what was
                specified for data (i.e., if tensors are padded or not)
        lr_func - string which is evaluated with 'epoch' to produce the learning 
                rate at each epoch 
        patience - number of epochs to wait when no progress is being made in 
                the validation loss. a patience of -1 means that the model will
                use weights from the best-performing model during training

    outputs:
        model - a trained Keras model
        loss - list of training losses corresponding to each epoch 
        val_loss - list of validation losses corresponding to each epoch
Trains the model.
inputs:
model - a Keras model
data - three dictionaries for training,
validation, and testing separately
nb_epoch - number of epochs to train for
batch_size - batch_size to use on the data. This must agree with what was
specified for data
lr_func - string which is evaluated with 'epoch' to produce the learning
rate at each epoch
patience - number of epochs to wait when no progress is being made in
the validation loss. a patience of -1 means that the model will
use weights from the best-performing model during training

a trained Keras model
loss - list of training losses corresponding to each epoch
val_loss - list of validation losses corresponding to each epoch
Trains the model . inputs : model - a Keras model data - three dictionaries for training validation and testing separately nb_epoch - number of epochs to train for batch_size - batch_size to use on the data . This must agree with what was specified for data lr_func - string which is evaluated with ' epoch ' to produce the learning rate at each epoch patience - number of epochs to wait when no progress is being made in the validation loss . a patience of - 1 means that the model will use weights from the best - performing model during training a trained Keras model loss - list of training losses corresponding to each epoch val_loss - list of validation losses corresponding to each epoch
def train_model(model, data, nb_epoch=0, batch_size=1, lr_func=None, patience=10, verbose=False):
    (train, val, _) = data
    mols_train = train['mols']; y_train = train['y']
    mols_val   = val['mols'];   y_val   = val['y']
    print('{} to train on'.format(len(mols_train)))
    print('{} to validate on'.format(len(mols_val)))
    if lr_func:
        lr_func_string = 'def lr(epoch):\n    return {}\n'.format(lr_func)
        exec(lr_func_string)
    print(f"The initial learning rate: {K.eval(model.optimizer.lr)}")
    try:
        loss = []
        val_loss = []
        if batch_size == 1: 
            wait = 0
            prev_best_val_loss = 99999999
            for i in range(nb_epoch):
                this_loss = []
                this_val_loss = []
                if lr_func:
                    model.optimizer.lr.set_value(lr(i))
                    print('Epoch {}/{}, lr = {}'.format(i + 1, nb_epoch, K.eval(model.optimizer.lr)))
                else:
                    print('Epoch {}/{}'.format(i + 1, nb_epoch))
                if verbose: print('Training...')
                training_order = list(range(len(mols_train)))
                np.random.shuffle(training_order)
                for j in training_order:
                    single_mol = mols_train[j]
                    single_y_as_array = np.reshape(y_train[j], (1, -1))
                    sloss = model.train_on_batch(
                        [np.array([single_mol[0]]), np.array([single_mol[1]]), np.array([single_mol[2]])],
                        single_y_as_array
                    )
                    this_loss.append(sloss)
                if verbose: print('Validating..')
                for j in range(len(mols_val)):
                    single_mol = mols_val[j]
                    single_y_as_array = np.reshape(y_val[j], (1, -1))
                    sloss = model.test_on_batch(
                        [np.array([single_mol[0]]), np.array([single_mol[1]]), np.array([single_mol[2]])],
                        single_y_as_array
                    )
                    this_val_loss.append(sloss)
                loss.append(np.mean(this_loss))
                val_loss.append(np.mean(this_val_loss))
                print('loss: {}\tval_loss: {}'.format(loss[i], val_loss[i]))
                if np.mean(this_val_loss) < prev_best_val_loss:
                    wait = 0
                    prev_best_val_loss = np.mean(this_val_loss)
                    if patience == -1:
                        model.save_weights('best.h5', overwrite=True)
                else:
                    wait = wait + 1
                    print('{} epochs without val_loss progress'.format(wait))
                    if wait == patience:
                        print('stopping early!')
                        break
            if patience == -1:
                model.load_weights('best.h5')
        else: 
            if lr_func:
                callbacks = [LearningRateScheduler(lr)]
            else:
                callbacks = []
            if patience != -1:
                callbacks.append(EarlyStopping(patience = patience, verbose = 1))
            if mols_val:
                mols = np.vstack((mols_train, mols_val))
                y = np.concatenate((y_train, y_val))
                hist = model.fit(mols, y, 
                    nb_epoch = nb_epoch, 
                    batch_size = batch_size, 
                    validation_split = (1 - float(len(mols_train))/(len(mols_val) + len(mols_train))),
                    verbose = verbose,
                    callbacks = callbacks)    
            else:
                hist = model.fit(np.array(mols_train), np.array(y_train), 
                    nb_epoch = nb_epoch, 
                    batch_size = batch_size, 
                    verbose = verbose,
                    callbacks = callbacks)    
            loss = []; val_loss = []
            if 'loss' in hist.history: loss = hist.history['loss']
            if 'val_loss' in hist.history: val_loss = hist.history['val_loss']
    except KeyboardInterrupt:
        print('User terminated training early (intentionally)')
    return (model, loss, val_loss)
def train_model ( model , data , nb_epoch = 0 , batch_size = 1 , lr_func = None , patience = 10 , verbose = False ) : ( train , val , _ ) = data mols_train = train [ 'mols' ] ; y_train = train [ 'y' ] mols_val = val [ 'mols' ] ; y_val = val [ 'y' ] print ( '{} to train on' . format ( len ( mols_train ) ) ) print ( '{} to validate on' . format ( len ( mols_val ) ) ) if lr_func : lr_func_string = 'def lr(epoch):\n    return {}\n' . format ( lr_func ) exec ( lr_func_string ) print ( f"The initial learning rate: {K.eval(model.optimizer.lr)}" ) try : loss = [ ] val_loss = [ ] if batch_size == 1 : wait = 0 prev_best_val_loss = 99999999 for i in range ( nb_epoch ) : this_loss = [ ] this_val_loss = [ ] if lr_func : model . optimizer . lr . set_value ( lr ( i ) ) print ( 'Epoch {}/{}, lr = {}' . format ( i + 1 , nb_epoch , K . eval ( model . optimizer . lr ) ) ) else : print ( 'Epoch {}/{}' . format ( i + 1 , nb_epoch ) ) if verbose : print ( 'Training...' ) training_order = list ( range ( len ( mols_train ) ) ) np . random . shuffle ( training_order ) for j in training_order : single_mol = mols_train [ j ] single_y_as_array = np . reshape ( y_train [ j ] , ( 1 , - 1 ) ) sloss = model . train_on_batch ( [ np . array ( [ single_mol [ 0 ] ] ) , np . array ( [ single_mol [ 1 ] ] ) , np . array ( [ single_mol [ 2 ] ] ) ] , single_y_as_array ) this_loss . append ( sloss ) if verbose : print ( 'Validating..' ) for j in range ( len ( mols_val ) ) : single_mol = mols_val [ j ] single_y_as_array = np . reshape ( y_val [ j ] , ( 1 , - 1 ) ) sloss = model . test_on_batch ( [ np . array ( [ single_mol [ 0 ] ] ) , np . array ( [ single_mol [ 1 ] ] ) , np . array ( [ single_mol [ 2 ] ] ) ] , single_y_as_array ) this_val_loss . append ( sloss ) loss . append ( np . mean ( this_loss ) ) val_loss . append ( np . mean ( this_val_loss ) ) print ( 'loss: {}\tval_loss: {}' . format ( loss [ i ] , val_loss [ i ] ) ) if np . mean ( this_val_loss ) < prev_best_val_loss : wait = 0 prev_best_val_loss = np . mean ( this_val_loss ) if patience == - 1 : model . save_weights ( 'best.h5' , overwrite = True ) else : wait = wait + 1 print ( '{} epochs without val_loss progress' . format ( wait ) ) if wait == patience : print ( 'stopping early!' ) break if patience == - 1 : model . load_weights ( 'best.h5' ) else : if lr_func : callbacks = [ LearningRateScheduler ( lr ) ] else : callbacks = [ ] if patience != - 1 : callbacks . append ( EarlyStopping ( patience = patience , verbose = 1 ) ) if mols_val : mols = np . vstack ( ( mols_train , mols_val ) ) y = np . concatenate ( ( y_train , y_val ) ) hist = model . fit ( mols , y , nb_epoch = nb_epoch , batch_size = batch_size , validation_split = ( 1 - float ( len ( mols_train ) ) / ( len ( mols_val ) + len ( mols_train ) ) ) , verbose = verbose , callbacks = callbacks ) else : hist = model . fit ( np . array ( mols_train ) , np . array ( y_train ) , nb_epoch = nb_epoch , batch_size = batch_size , verbose = verbose , callbacks = callbacks ) loss = [ ] ; val_loss = [ ] if 'loss' in hist . history : loss = hist . history [ 'loss' ] if 'val_loss' in hist . history : val_loss = hist . history [ 'val_loss' ] except KeyboardInterrupt : print ( 'User terminated training early (intentionally)' ) return ( model , loss , val_loss )
Trains the model.
Trains the model .
'''Trains the model.

    inputs:
        model - a Keras model
        data - three dictionaries for training,
                validation, and testing separately
        nb_epoch - number of epochs to train for
        batch_size - batch_size to use on the data. This must agree with what was
                specified for data (i.e., if tensors are padded or not)
        lr_func - string which is evaluated with 'epoch' to produce the learning 
                rate at each epoch 
        patience - number of epochs to wait when no progress is being made in 
                the validation loss. a patience of -1 means that the model will
                use weights from the best-performing model during training

    outputs:
        model - a trained Keras model
        loss - list of training losses corresponding to each epoch 
        val_loss - list of validation losses corresponding to each epoch''' # Unpack data  # Create learning rate function # Fit (allows keyboard interrupts in the middle) # Because molecular graph tensors are different sizes based on N_atoms, can only do one at a time # (alternative is to pad with zeros and try to add some masking feature to GraphFP) # -> this is why batch_size == 1 is treated distinctly # DO NOT NEED TO PAD # if we use Adam or sth and don't use lr_func, we cannot get the current learning rate # Run through training set # Run through testing set # Check progress # When the batch_size is larger than one, we have padded mol tensors # which  means we need to concatenate them but can use Keras' built-in # training functions with callbacks, validation_split, etc.
model
data
nb_epoch
batch_size
lr_func
patience
verbose