Ejemplo n.º 1
0
def train_model(model: Model, base_model: Model,
                train_gen: classifier_sequence.ClassifierSequence,
                val_gen: classifier_sequence.ClassifierSequence) -> None:
    """Trains the model on the given data sets."""
    for layer in base_model.layers:
        layer.trainable = False

    opt = optimizers.SGD(learning_rate=0.00001, momentum=0.8, clipnorm=1)
    # opt = optimizers.Adam(learning_rate=0.000001)

    model.compile(optimizer=opt,
                  loss='binary_crossentropy',
                  metrics=[
                      'accuracy',
                      metrics.Recall(),
                      metrics.Precision(),
                      metrics.FalsePositives(),
                      metrics.FalseNegatives()
                  ])

    log_dir = "logs/fit/" + datetime.datetime.now().strftime("%Y%m%d-%H%M%S")
    tensorboard_callback = callbacks.TensorBoard(log_dir=log_dir,
                                                 histogram_freq=1)

    model.fit(train_gen,
              validation_data=val_gen,
              epochs=60,
              callbacks=[tensorboard_callback])

    for layer in base_model.layers:
        layer.trainable = True

    opt = optimizers.SGD(learning_rate=0.00001, momentum=0.8, clipnorm=1)

    model.compile(optimizer=opt,
                  loss='binary_crossentropy',
                  metrics=[
                      'accuracy',
                      metrics.Recall(),
                      metrics.Precision(),
                      metrics.FalsePositives(),
                      metrics.FalseNegatives()
                  ])

    model.fit(train_gen,
              validation_data=val_gen,
              epochs=120,
              initial_epoch=60,
              callbacks=[tensorboard_callback])
Ejemplo n.º 2
0
    def build(self):
        model = tf.keras.Sequential()
        model.add(layers.Flatten(input_shape=(42, 4)))

        for i in range(self.layers):
            if self.reg:
                model.add(
                    layers.Dense(self.sizes[i],
                                 activation='elu',
                                 kernel_regularizer=regularizers.l2(
                                     self.reg[i])))
            else:
                model.add(layers.Dense(self.sizes[i], activation='elu'))

            if self.dropout:
                model.add(layers.Dropout(self.dropout[i]))

        model.add(layers.Dense(1, activation='sigmoid'))

        model.compile(optimizer=optimizers.Adam(learning_rate=self.lr),
                      loss=losses.BinaryCrossentropy(),
                      metrics=[
                          'binary_accuracy',
                          metrics.TruePositives(name='tp'),
                          metrics.FalseNegatives(name='fn'),
                          metrics.TrueNegatives(name='tn'),
                          metrics.FalsePositives(name='fp'),
                          metrics.Recall(name='recall'),
                          metrics.Precision(name='precision')
                      ])

        return model
Ejemplo n.º 3
0
def eval_use_model(model_name, path_model_file, test_file, class_num):
    """
    evaluating model by using entire model (weights, architecture, optimizers, etc.)

    Arguments:\n
    model_name --> String, Resnet50/Resnet18/VGG16/VGG19
    path_model_file --> String, path which store .hdf5 of model's weight\n
    test_file --> String, path to which store .h5 file of test dataset
    class_num --> Int, number of class/label\n

    Returns:\n
    none
    """
    # Load model weights
    new_model = Model()
    new_model = load_model(path_model_file)
    new_model.compile(optimizer='adam',
                      loss='categorical_crossentropy',
                      metrics=[
                          metrics.AUC(),
                          metrics.CategoricalAccuracy(),
                          metrics.TruePositives(),
                          metrics.TrueNegatives(),
                          metrics.FalsePositives(),
                          metrics.FalseNegatives()
                      ])

    # retrieve X_test, Y_test
    X_test, Y_test = retrieve_test_dataset(test_file, int(class_num))

    for i in range(4):
        hasil = new_model.evaluate(X_test, Y_test)
        print(new_model.metrics_names)
        print(hasil)
Ejemplo n.º 4
0
 def call(self,
          y_true_local,
          y_pred_local,
          fp=metrics.FalsePositives(),
          fn=metrics.FalseNegatives(),
          tp=metrics.TruePositives(),
          tn=metrics.TrueNegatives()):
     return 0.5 * tn / (tn + fn) + (tp / (tp + fp))
Ejemplo n.º 5
0
def get_metrics():
    acc = 'accuracy'
    auc = metrics.AUC(num_thresholds=200,
                      curve='ROC',
                      name='auc',
                      thresholds=None,
                      multi_label=False)
    fp = metrics.FalsePositives(thresholds=[0.001, 0.01, 0.1, 1.0], name='FP')
    tp = metrics.TruePositives(thresholds=[0.001, 0.01, 0.1, 1.0], name='TP')

    return [acc]  #, auc, fp, tp]
Ejemplo n.º 6
0
def test_metric_direction_inference():
    # Test min metrics.
    assert metrics_tracking.infer_metric_direction("MAE") == "min"
    assert (
        metrics_tracking.infer_metric_direction(metrics.binary_crossentropy) == "min"
    )
    assert metrics_tracking.infer_metric_direction(metrics.FalsePositives()) == "min"

    # All losses in keras.losses are considered as 'min'.
    assert metrics_tracking.infer_metric_direction("squared_hinge") == "min"
    assert metrics_tracking.infer_metric_direction(losses.hinge) == "min"
    assert (
        metrics_tracking.infer_metric_direction(losses.CategoricalCrossentropy())
        == "min"
    )

    # Test max metrics.
    assert metrics_tracking.infer_metric_direction("binary_accuracy") == "max"
    assert (
        metrics_tracking.infer_metric_direction(metrics.categorical_accuracy)
        == "max"
    )
    assert metrics_tracking.infer_metric_direction(metrics.Precision()) == "max"

    # Test unknown metrics.
    assert metrics_tracking.infer_metric_direction("my_metric") is None

    def my_metric_fn(x, y):
        return x

    assert metrics_tracking.infer_metric_direction(my_metric_fn) is None

    class MyMetric(metrics.Metric):
        def update_state(self, x, y):
            return 1

        def result(self):
            return 1

    assert metrics_tracking.infer_metric_direction(MyMetric()) is None

    # Test special cases.
    assert metrics_tracking.infer_metric_direction("loss") == "min"
    assert metrics_tracking.infer_metric_direction("acc") == "max"
    assert metrics_tracking.infer_metric_direction("val_acc") == "max"
    assert metrics_tracking.infer_metric_direction("crossentropy") == "min"
    assert metrics_tracking.infer_metric_direction("ce") == "min"
    assert metrics_tracking.infer_metric_direction("weighted_acc") == "max"
    assert metrics_tracking.infer_metric_direction("val_weighted_ce") == "min"
    assert (
        metrics_tracking.infer_metric_direction("weighted_binary_accuracy") == "max"
    )
 def confusion_matrix(self, y_label, y_class):
     tn = metrics.TrueNegatives()
     tn.update_state(y_label, y_class) 
     print('TrueNegatives result: ', tn.result().numpy())
     tp =metrics.TruePositives()
     tp.update_state(y_label, y_class) 
     print('TruePositives result: ', tp.result().numpy())
     fn = metrics.FalseNegatives()
     fn.update_state(y_label, y_class) 
     print('FalseNegatives result: ', fn.result().numpy())
     fp = metrics.FalsePositives()
     fp.update_state(y_label, y_class) 
     print('FalsePositives result: ', fp.result().numpy())
Ejemplo n.º 8
0
def test_metric_direction_inference():
    # Test min metrics.
    assert metrics_tracking.infer_metric_direction('MAE') == 'min'
    assert metrics_tracking.infer_metric_direction(
        metrics.binary_crossentropy) == 'min'
    assert metrics_tracking.infer_metric_direction(
        metrics.FalsePositives()) == 'min'

    # All losses in keras.losses are considered as 'min'.
    assert metrics_tracking.infer_metric_direction('squared_hinge') == 'min'
    assert metrics_tracking.infer_metric_direction(losses.hinge) == 'min'
    assert metrics_tracking.infer_metric_direction(
        losses.CategoricalCrossentropy()) == 'min'

    # Test max metrics.
    assert metrics_tracking.infer_metric_direction('binary_accuracy') == 'max'
    assert metrics_tracking.infer_metric_direction(
        metrics.categorical_accuracy) == 'max'
    assert metrics_tracking.infer_metric_direction(
        metrics.Precision()) == 'max'

    # Test unknown metrics.
    assert metrics_tracking.infer_metric_direction('my_metric') is None

    def my_metric_fn(x, y):
        return x

    assert metrics_tracking.infer_metric_direction(my_metric_fn) is None

    class MyMetric(metrics.Metric):
        def update_state(self, x, y):
            return 1

        def result(self):
            return 1

    assert metrics_tracking.infer_metric_direction(MyMetric()) is None

    # Test special cases.
    assert metrics_tracking.infer_metric_direction('loss') == 'min'
    assert metrics_tracking.infer_metric_direction('acc') == 'max'
    assert metrics_tracking.infer_metric_direction('val_acc') == 'max'
    assert metrics_tracking.infer_metric_direction('crossentropy') == 'min'
    assert metrics_tracking.infer_metric_direction('ce') == 'min'
    assert metrics_tracking.infer_metric_direction('weighted_acc') == 'max'
    assert metrics_tracking.infer_metric_direction('val_weighted_ce') == 'min'
    assert metrics_tracking.infer_metric_direction(
        'weighted_binary_accuracy') == 'max'
Ejemplo n.º 9
0
 def __get_metric(self, metric):
     if metric == "auc":
         return m.AUC()
     elif metric == "accuracy":
         return m.Accuracy()
     elif metric == "binary_accuracy":
         return m.BinaryAccuracy()
     elif metric == "categorical_accuracy":
         return m.CategoricalAccuracy()
     elif metric == "binary_crossentropy":
         return m.BinaryCrossentropy()
     elif metric == "categorical_crossentropy":
         return m.CategoricalCrossentropy()
     elif metric == "sparse_categorical_crossentropy":
         return m.SparseCategoricalCrossentropy()
     elif metric == "kl_divergence":
         return m.KLDivergence()
     elif metric == "poisson":
         return m.Poission()
     elif metric == "mse":
         return m.MeanSquaredError()
     elif metric == "rmse":
         return m.RootMeanSquaredError()
     elif metric == "mae":
         return m.MeanAbsoluteError()
     elif metric == "mean_absolute_percentage_error":
         return m.MeanAbsolutePercentageError()
     elif metric == "mean_squared_logarithm_error":
         return m.MeanSquaredLogarithmError()
     elif metric == "cosine_similarity":
         return m.CosineSimilarity()
     elif metric == "log_cosh_error":
         return m.LogCoshError()
     elif metric == "precision":
         return m.Precision()
     elif metric == "recall":
         return m.Recall()
     elif metric == "true_positive":
         return m.TruePositives()
     elif metric == "true_negative":
         return m.TrueNegatives()
     elif metric == "false_positive":
         return m.FalsePositives()
     elif metric == "false_negative":
         return m.FalseNegatives()
     else:
         raise Exception("specified metric not defined")
Ejemplo n.º 10
0
def create_model_v2(data):
    name_len = len(data['training_data'][0][0])
    gender_len = len(data['training_data'][0][2])
    dob_len = len(data['training_data'][0][3])

    i_name_1 = keras.Input(name="name_1", shape=(name_len, 1))
    i_name_2 = keras.Input(name="name_2", shape=(name_len, 1))
    i_last_name_1 = keras.Input(name="last_name_1", shape=(name_len, 1))
    i_last_name_2 = keras.Input(name="last_name_2", shape=(name_len, 1))
    i_gender_1 = keras.Input(name="gender_1", shape=(gender_len, ))
    i_gender_2 = keras.Input(name="gender_2", shape=(gender_len, ))
    i_dob_1 = keras.Input(name="dob_1", shape=(dob_len, 1))
    i_dob_2 = keras.Input(name="dob_2", shape=(dob_len, 1))
    i_ratio_n = keras.Input(name="fuzz_n", shape=(1, ))
    i_ratio_ln = keras.Input(name="fuzz_ln", shape=(1, ))
    i_ratio_d = keras.Input(name="fuzz_d", shape=(1, ))

    l4_combined = layers.Concatenate()([
        create_name_branch(i_name_1, i_name_2),
        create_name_branch(i_last_name_1, i_last_name_2),
        create_gender_branch(i_gender_1, i_gender_2),
        create_dob_branch(i_dob_1, i_dob_2),
        create_ratio_branch(i_ratio_n, 10),
        create_ratio_branch(i_ratio_ln, 10),
        create_ratio_branch(i_ratio_d, 5)
    ])
    l5_brain = layers.Dense(20, activation='tanh')(l4_combined)

    model = keras.Model(inputs=[
        i_name_1, i_last_name_1, i_gender_1, i_dob_1, i_name_2, i_last_name_2,
        i_gender_2, i_dob_2, i_ratio_n, i_ratio_ln, i_ratio_d
    ],
                        outputs=[
                            layers.Dense(1, activation='sigmoid')(l5_brain)
                        ])

    model.compile(loss='binary_crossentropy',
                  optimizer='adam',
                  metrics=[
                      'accuracy',
                      metrics.FalsePositives(),
                      metrics.FalseNegatives()
                  ])

    return model
Ejemplo n.º 11
0
    def __init__(self, n_features, n_classes):
        print("##################### Init NN #####################")
        self.N_FEATURES = n_features
        self.N_CLASSES = n_classes
        self.METRICS = [
            'accuracy',
            tkm.TruePositives(),
            tkm.FalsePositives(name='fp'),
            tkm.TrueNegatives(name='tn'),
            tkm.FalseNegatives(name='fn'),
            #tkm.BinaryAccuracy(name='accuracy'),
            tkm.Precision(name='precision'),
            tkm.Recall(name='recall'),
            tkm.AUC(name='auc')
        ]

        self.DATE = datetime.now().strftime("%d-%m_%H%M%S")
        create_dir(self.DATE)
Ejemplo n.º 12
0
    def experiment(self, under=False, ratio=3, plot=False):
        METRICS = [
            metrics.TruePositives(name='tp'),
            metrics.FalsePositives(name='fp'),
            metrics.TrueNegatives(name='tn'),
            metrics.FalseNegatives(name='fn'),
            metrics.BinaryAccuracy(name='accuracy'),
            metrics.Precision(name='precision'),
            metrics.Recall(name='recall'),
            metrics.AUC(name='auc')
        ]

        data = DataLoader()
        model = LeNet(data.X, METRICS)
        augmenter = Augmenter(data.X, data.Y)

        if under:
            data.X, data.Y = augmenter.undersample(ratio=ratio)

        if self.augmentation.type == 1 or self.augmentation.type == 2:
            data.X, data.Y = augmenter.duplicate(noise=self.augmentation.noise,
                                                 sigma=self.augmentation.sigma)
        elif self.augmentation.type == 3:
            data.X, data.Y = augmenter.SMOTE()

        #data.normalize()
        #print(len(data.X))
        #print(len(data.valX))

        data.summarize(test=False)
        his = model.fit(data.X, data.Y, data.valX, data.valY)
        RES, fpr, tpr = model.predict(data.testX, data.testY)
        #self.model_summary(RES)
        if plot:
            self.plot(his)
            self.ROC(fpr, tpr)
        return RES
Ejemplo n.º 13
0
    def compile(self, model, train_generator, valid_generator):
        """:arg
        This function contain model compile and model fit process, input a model and output history and trained model

        """
        start_time = time()
        print("*" * 40, "Start {} Processing".format(model._name), "*" * 40)

        # we use a lot of metric to evalute our binary classification result
        METRICS = [
              metrics.TruePositives(name='tp'),
              metrics.FalsePositives(name='fp'),
              metrics.TrueNegatives(name='tn'),
              metrics.FalseNegatives(name='fn'),
              metrics.BinaryAccuracy(name='binary_accuracy'),
              #metrics.CategoricalAccuracy(name='accuracy'),
              metrics.Precision(name='precision'),
              metrics.Recall(name='recall'),
              metrics.AUC(name='auc'),
              # F1Score(num_classes = int(y_train.shape[1]), name='F1')
        ]

        # define a optimizer
        opt_rms = optimizers.RMSprop(lr = 1e-4, decay = 1e-5)
        # define compile parameters
        model.compile(loss = 'binary_crossentropy', optimizer = opt_rms, metrics = ['accuracy'])
        # start to fit
        history = model.fit(
            train_generator,
            steps_per_epoch=20,
            epochs=5,
            validation_data=valid_generator,
            validation_steps=20
        )

        return history
Ejemplo n.º 14
0
        elif data_subset_mode == 'val':
            data = data.batch(batch_size, drop_remainder=True) \
                       .map(VAL_image_augmentor)
        elif data_subset_mode == 'test':
            data = data.batch(batch_size, drop_remainder=True) \
                       .map(TEST_image_augmentor)

        if infinite:
            data = data.repeat()

        return data.prefetch(AUTOTUNE)

    METRICS = [
    #     per_class_accuracy,
        metrics.TruePositives(name='tp'),
        metrics.FalsePositives(name='fp'),
        metrics.TrueNegatives(name='tn'),
        metrics.FalseNegatives(name='fn'),
        metrics.CategoricalAccuracy(name='accuracy'),
        metrics.Precision(name='precision'),
        metrics.Recall(name='recall'),
        metrics.TopKCategoricalAccuracy(name='top_3_categorical_accuracy', k=3),
        metrics.TopKCategoricalAccuracy(name='top_5_categorical_accuracy', k=5)
    ]
    ###########################################################################
    ###########################################################################


    encoder = base_dataset.LabelEncoder(data.data.family)
    split_data = base_dataset.preprocess_data(data, encoder, data_config)
    for subset, subset_data in split_data.items():
Ejemplo n.º 15
0
import numpy as np
from tensorflow.keras import metrics as keras_metrics
from tensorflow.keras.callbacks import EarlyStopping
from tensorflow.keras.layers import Dense
from tensorflow.keras.models import Sequential

from ProteinDataset import ProteinDataset, mask_generator

EPOCHS_DEFAULT = 100
PATIENCE_DEFAULT = 10
METRICS = [
    keras_metrics.TruePositives(name="tp"),
    keras_metrics.FalsePositives(name="fp"),
    keras_metrics.TrueNegatives(name="tn"),
    keras_metrics.FalseNegatives(name="fn"),
    keras_metrics.BinaryAccuracy(name="accuracy"),
    keras_metrics.Precision(name="precision"),
    keras_metrics.Recall(name="recall"),
    keras_metrics.AUC(name="auc"),
]

parser = argparse.ArgumentParser(
    description="Run a Logistic Regression pipeline.")
parser.add_argument("dataset_pkl", help="Dataset (in PKL format) to use.")
parser.add_argument(
    "--name",
    help=
    "Configuration name (e.g. 'contacts' or 'topology'). This will be tagged during the MLFlow run.",
    default=None,
)
parser.add_argument("--epochs",
Ejemplo n.º 16
0
def main(**kwargs):

    import sys

    for k, v in kwargs.items():
        sys.argv += [k, v]

    from pprint import pprint
    import argparse
    import datetime
    import json
    import os


    parser = argparse.ArgumentParser()
    parser.add_argument('--neptune_project_name', default='jacobarose/sandbox', type=str, help='Neptune.ai project name to log under')
    parser.add_argument('--experiment_name', default='pnas_minimal_example', type=str, help='Neptune.ai experiment name to log under')
    parser.add_argument('--config_path', default=r'/home/jacob/projects/pyleaves/pyleaves/configs/example_configs/pnas_resnet_config.json', type=str, help='JSON config file')
    parser.add_argument('-gpu', '--gpu_id', default='1', type=str, help='integer number of gpu to train on', dest='gpu_id')
    parser.add_argument('-tags', '--add-tags', default=[], type=str, nargs='*', help='Add arbitrary list of tags to apply to this run in neptune', dest='tags')
    parser.add_argument('-f', default=None)
    args = parser.parse_args()

    with open(args.config_path, 'r') as config_file:
        PARAMS = json.load(config_file)

    # print(gpu)
    # os.environ["CUDA_DEVICE_ORDER"]="PCI_BUS_ID"
    os.environ["CUDA_VISIBLE_DEVICES"] = str(args.gpu_id)

    pprint(PARAMS)
    import tensorflow as tf
    import neptune
    # tf.debugging.set_log_device_placement(True)
    print(tf.__version__)





    import arrow
    import numpy as np
    import pandas as pd
    import seaborn as sns
    import matplotlib.pyplot as plt
    import io
    from stuf import stuf
    from more_itertools import unzip
    from functools import partial
    # import tensorflow as tf
    # tf.compat.v1.enable_eager_execution()
    AUTOTUNE = tf.data.experimental.AUTOTUNE

    from pyleaves.leavesdb.tf_utils.tf_utils import set_random_seed, reset_keras_session
    import pyleaves
    from pyleaves.utils.img_utils import random_pad_image
    from pyleaves.utils.utils import ensure_dir_exists
    from pyleaves.datasets import leaves_dataset, fossil_dataset, pnas_dataset, base_dataset
    from pyleaves.models.vgg16 import VGG16, VGG16GrayScale
    from pyleaves.models import resnet, vgg16
    from tensorflow.compat.v1.keras.callbacks import Callback, ModelCheckpoint, TensorBoard, LearningRateScheduler, EarlyStopping
    from tensorflow.keras import metrics
    from tensorflow.keras.preprocessing.image import load_img, img_to_array
    from tensorflow.keras import layers
    from tensorflow.keras import backend as K
    import tensorflow_datasets as tfds
    import neptune_tensorboard as neptune_tb

    seed = 346
    # set_random_seed(seed)
    # reset_keras_session()
    def get_preprocessing_func(model_name):
        if model_name.startswith('resnet'):
            from tensorflow.keras.applications.resnet_v2 import preprocess_input
        elif model_name == 'vgg16':
            from tensorflow.keras.applications.vgg16 import preprocess_input
        elif model_name=='shallow':
            def preprocess_input(x):
                return x/255.0 # ((x/255.0)-0.5)*2.0

        return preprocess_input #lambda x,y: (preprocess_input(x),y)

    def _load_img(image_path):#, img_size=(224,224)):
        img = tf.io.read_file(image_path)
        img = tf.image.decode_jpeg(img, channels=3)
        img = tf.image.convert_image_dtype(img, tf.float32)
        return img
        # return tf.compat.v1.image.resize_image_with_pad(img, *img_size)

    def _encode_label(label, num_classes=19):
        label = tf.cast(label, tf.int32)
        label = tf.one_hot(label, depth=num_classes)
        return label

    def _load_example(image_path, label, num_classes=19):
        img = _load_img(image_path)
        one_hot_label = _encode_label(label, num_classes=num_classes)
        return img, one_hot_label

    def _load_uint8_example(image_path, label, num_classes=19):
        img = tf.image.convert_image_dtype(_load_img(image_path)*255.0, dtype=tf.uint8)
        one_hot_label = _encode_label(label, num_classes=num_classes)
        return img, one_hot_label

    def rgb2gray_3channel(img, label):
        '''
        Convert rgb image to grayscale, but keep num_channels=3
        '''
        img = tf.image.rgb_to_grayscale(img)
        img = tf.image.grayscale_to_rgb(img)
        return img, label

    def rgb2gray_1channel(img, label):
        '''
        Convert rgb image to grayscale, num_channels from 3 to 1
        '''
        img = tf.image.rgb_to_grayscale(img)
        return img, label

    def log_data(logs):
        for k, v in logs.items():
            neptune.log_metric(k, v)

    neptune_logger = tf.keras.callbacks.LambdaCallback(on_epoch_end=lambda epoch, logs: log_data(logs))

    def focal_loss(gamma=2.0, alpha=4.0):

        gamma = float(gamma)
        alpha = float(alpha)

        def focal_loss_fixed(y_true, y_pred):
            """Focal loss for multi-classification
            FL(p_t)=-alpha(1-p_t)^{gamma}ln(p_t)
            Notice: y_pred is probability after softmax
            gradient is d(Fl)/d(p_t) not d(Fl)/d(x) as described in paper
            d(Fl)/d(p_t) * [p_t(1-p_t)] = d(Fl)/d(x)
            Focal Loss for Dense Object Detection
            https://arxiv.org/abs/1708.02002

            Arguments:
                y_true {tensor} -- ground truth labels, shape of [batch_size, num_cls]
                y_pred {tensor} -- model's output, shape of [batch_size, num_cls]

            Keyword Arguments:
                gamma {float} -- (default: {2.0})
                alpha {float} -- (default: {4.0})

            Returns:
                [tensor] -- loss.
            """
            epsilon = 1.e-9
            y_true = tf.convert_to_tensor(y_true, tf.float32)
            y_pred = tf.convert_to_tensor(y_pred, tf.float32)

            model_out = tf.add(y_pred, epsilon)
            ce = tf.multiply(y_true, -tf.log(model_out))
            weight = tf.multiply(y_true, tf.pow(tf.subtract(1., model_out), gamma))
            fl = tf.multiply(alpha, tf.multiply(weight, ce))
            reduced_fl = tf.reduce_max(fl, axis=1)
            return tf.reduce_mean(reduced_fl)
        return focal_loss_fixed


    def per_class_accuracy(y_true, y_pred):
        return tf.metrics.mean_per_class_accuracy(y_true, y_pred, num_classes=PARAMS['num_classes'])

    def build_model(model_params,
                    optimizer,
                    loss,
                    METRICS):

        if model_params['name']=='vgg16':
            model_builder = vgg16.VGG16GrayScale(model_params)
        elif model_params['name'].startswith('resnet'):
            model_builder = resnet.ResNet(model_params)

        base = model_builder.build_base()
        model = model_builder.build_head(base)

        model.compile(optimizer=optimizer,
                      loss=loss,
                      metrics=METRICS)

        return model

    def build_shallow(input_shape=(224,224,3),
                      num_classes=10,
                      optimizer=None,
                      loss=None,
                      METRICS=None):

        model = tf.keras.models.Sequential()
        model.add(layers.Conv2D(64, (7, 7), activation='relu', input_shape=input_shape, kernel_initializer=tf.initializers.GlorotNormal()))
        model.add(layers.MaxPooling2D((2, 2)))
        model.add(layers.Conv2D(64, (7, 7), activation='relu', kernel_initializer=tf.initializers.GlorotNormal()))
        model.add(layers.MaxPooling2D((2, 2)))
        model.add(layers.Conv2D(64, (7, 7), activation='relu', kernel_initializer=tf.initializers.GlorotNormal()))
        model.add(layers.Flatten())
        model.add(layers.Dense(64*2, activation='relu', kernel_initializer=tf.initializers.GlorotNormal()))
        model.add(layers.Dense(num_classes,activation='softmax', kernel_initializer=tf.initializers.GlorotNormal()))

        model.compile(optimizer=optimizer,
                      loss=loss,
                      metrics=METRICS)

        return model


    class ImageLogger:
        '''Tensorflow 2.0 version'''
        def __init__(self, log_dir: str, max_images: int, name: str):
            self.file_writer = tf.summary.create_file_writer(log_dir)
            self.log_dir = log_dir
            self.max_images = max_images
            self.name = name
            self._counter = tf.Variable(0, dtype=tf.int64)

            self.filepaths = []

        def add_log(self, img, counter=None, name=None):
            '''
            Intention is to generalize this to an abstract class for logging to any experiment management platform (e.g. neptune, mlflow, etc)

            Currently takes a filepath pointing to an image file and logs to current neptune experiment.
            '''

            # scaled_images = (img - tf.math.reduce_min(img))/(tf.math.reduce_max(img) - tf.math.reduce_min(img))
            # keep = 0
            # scaled_images = tf.image.convert_image_dtype(tf.squeeze(scaled_images[keep,:,:,:]), dtype=tf.uint8)
            # scaled_images = tf.expand_dims(scaled_images, 0)
            # tf.summary.image(name=self.name, data=scaled_images, step=self._counter, max_outputs=self.max_images)


            scaled_img = (img - np.min(img))/(np.max(img) - np.min(img)) * 255.0
            scaled_img = scaled_img.astype(np.uint32)

            neptune.log_image(log_name= name or self.name,
                              x=counter,
                              y=scaled_img)
            return scaled_img

        def __call__(self, images, labels):

            with self.file_writer.as_default():
                scaled_images = (images - tf.math.reduce_min(images))/(tf.math.reduce_max(images) - tf.math.reduce_min(images))
                keep = 0

                scaled_images = tf.image.convert_image_dtype(tf.squeeze(scaled_images[keep,:,:,:]), dtype=tf.uint8)
                scaled_images = tf.expand_dims(scaled_images, 0)

                labels = tf.argmax(labels[[keep], :],axis=1)
                tf.summary.image(name=self.name, data=scaled_images, step=self._counter, max_outputs=self.max_images)

                filepath = os.path.join(self.log_dir,'sample_images',f'{self.name}-{self._counter}.jpg')

                scaled_images = tf.image.encode_jpeg(tf.squeeze(scaled_images))
                tf.io.write_file(filename=tf.constant(filepath),
                                 contents=scaled_images)

            # self.add_log(scaled_images)
            self._counter.assign_add(1)
            return images, labels

    def _cond_apply(x, y, func, prob):
        """Conditionally apply func to x and y with probability prob.

        Parameters
        ----------
        x : type
            Input to conditionally pass through func
        y : type
            Label
        func : type
            Function to conditionally be applied to x and y
        prob : type
            Probability of applying function, within range [0.0,1.0]

        Returns
        -------
        x, y
        """
        return tf.cond((tf.random.uniform([], 0, 1) >= (1.0 - prob)), lambda: func(x,y), lambda: (x,y))


    class ImageAugmentor:
        """Short summary.

        Parameters
        ----------
        augmentations : dict
            Maps a sequence of named augmentations to a scalar probability,
             according to which they'll be conditionally applied in order.
        resize_w_pad : tuple, default=None
            Description of parameter `resize_w_pad`.
        random_crop :  tuple, default=None
            Description of parameter `random_crop`.
        random_jitter : dict
            First applies resize_w_pad, then random_crop. If user desires only 1 of these, set this to None.
            Should be a dict with 2 keys:
                'resize':(height, width)
                'crop_size':(crop_height,crop_width, channels)

        Only 1 of these 3 kwargs should be provided to any given augmentor:
        {'resize_w_pad', 'random_crop', 'random_jitter'}
        Example values for each:
            resize_w_pad=(224,224)
            random_crop=(224,224,3)
            random_jitter={'resize':(338,338),
                           'crop_size':(224,224, 3)}



        seed : int, default=None
            Random seed to apply to all augmentations

        Examples
        -------
        Examples should be written in doctest format, and
        should illustrate how to use the function/class.
        >>>

        Attributes
        ----------
        augmentations

        """

        def __init__(self,
                     name='',
                     augmentations={'rotate':1.0,
                                    'flip':1.0,
                                    'color':1.0,
                                    'rgb2gray_3channel':1.0},
                     resize_w_pad=None,
                     random_crop=None,
                     random_jitter={'resize':(338,338),
                                    'crop_size':(224,224,3)},
                     log_dir=None,
                     seed=None):

            self.name = name
            self.augmentations = augmentations
            self.seed = seed

            if resize_w_pad:
                self.target_h = resize_w_pad[0]
                self.target_w = resize_w_pad[1]
                # self.resize = self.resize_w_pad
            elif random_crop:
                self.crop_size = random_crop
                self.target_h = self.crop_size[0]
                self.target_w = self.crop_size[1]
                # self.resize = self.random_crop
            elif random_jitter:
                # self.target_h = tf.random.uniform([], random_jitter['crop_size'][0], random_jitter['resize'][0], dtype=tf.int32, seed=self.seed)
                # self.target_w = tf.random.uniform([], random_jitter['crop_size'][1], random_jitter['resize'][1], dtype=tf.int32, seed=self.seed)
                self.crop_size = random_jitter['crop_size']
                # self.resize = self.random_jitter
                self.target_h = random_jitter['crop_size'][0]
                self.target_w = random_jitter['crop_size'][1]
            self.resize = self.resize_w_pad



            self.maps = {'rotate':self.rotate,
                          'flip':self.flip,
                          'color':self.color,
                          'rgb2gray_3channel':self.rgb2gray_3channel,
                          'rgb2gray_1channel':self.rgb2gray_1channel}

            self.log_dir = log_dir

        def rotate(self, x: tf.Tensor, label: tf.Tensor) -> tf.Tensor:
            """Rotation augmentation

            Args:
                x,     tf.Tensor: Image
                label, tf.Tensor: arbitrary tensor, passes through unchanged

            Returns:
                Augmented image, label
            """
            # Rotate 0, 90, 180, 270 degrees
            return tf.image.rot90(x, tf.random.uniform(shape=[], minval=0, maxval=4, dtype=tf.int32,seed=self.seed)), label

        def flip(self, x: tf.Tensor, label: tf.Tensor) -> tf.Tensor:
            """Flip augmentation

            Args:
                x,     tf.Tensor: Image to flip
                label, tf.Tensor: arbitrary tensor, passes through unchanged
            Returns:
                Augmented image, label
            """
            x = tf.image.random_flip_left_right(x, seed=self.seed)
            x = tf.image.random_flip_up_down(x, seed=self.seed)

            return x, label

        def color(self, x: tf.Tensor, label: tf.Tensor) -> tf.Tensor:
            """Color augmentation

            Args:
                x,     tf.Tensor: Image
                label, tf.Tensor: arbitrary tensor, passes through unchanged

            Returns:
                Augmented image, label
            """
            x = tf.image.random_hue(x, 0.08, seed=self.seed)
            x = tf.image.random_saturation(x, 0.6, 1.6, seed=self.seed)
            x = tf.image.random_brightness(x, 0.05, seed=self.seed)
            x = tf.image.random_contrast(x, 0.7, 1.3, seed=self.seed)
            return x, label

        def rgb2gray_3channel(self, x: tf.Tensor, label: tf.Tensor) -> tf.Tensor:
            """Convert RGB image -> grayscale image, maintain number of channels = 3

            Args:
                x,     tf.Tensor: Image
                label, tf.Tensor: arbitrary tensor, passes through unchanged

            Returns:
                Augmented image, label
            """
            x = tf.image.rgb_to_grayscale(x)
            x = tf.image.grayscale_to_rgb(x)
            return x, label

        def rgb2gray_1channel(self, x: tf.Tensor, label: tf.Tensor) -> tf.Tensor:
            """Convert RGB image -> grayscale image, reduce number of channels from 3 -> 1

            Args:
                x,     tf.Tensor: Image
                label, tf.Tensor: arbitrary tensor, passes through unchanged

            Returns:
                Augmented image, label
            """
            x = tf.image.rgb_to_grayscale(x)
            return x, label

        def resize_w_pad(self, x: tf.Tensor, label: tf.Tensor) -> tf.Tensor:
            # TODO Finish this
            # random_pad_image(x,min_image_size=None,max_image_size=None,pad_color=None,seed=self.seed)
            return tf.image.resize_with_pad(x, target_height=self.target_h, target_width=self.target_w), label

        def random_crop(self, x: tf.Tensor, label: tf.Tensor) -> tf.Tensor:
            return tf.image.random_crop(x, size=self.crop_size), label

        @tf.function
        def random_jitter(self, x: tf.Tensor, label: tf.Tensor) -> tf.Tensor:
            x, label = self.resize_w_pad(x, label)
            x, label = self.random_crop(x, label)
            return x, label

        def apply_augmentations(self, dataset: tf.data.Dataset):
            """
            Call this function to apply all of the augmentation in the order of specification
            provided to the constructor __init__() of ImageAugmentor.

            Args:
                dataset, tf.data.Dataset: must yield individual examples of form (x, y)
            Returns:
                Augmented dataset
            """

            dataset = dataset.map(self.resize, num_parallel_calls=AUTOTUNE)

            for aug_name, aug_p in self.augmentations.items():
                aug = self.maps[aug_name]
                dataset = dataset.map(lambda x,y: _cond_apply(x, y, aug, prob=aug_p), num_parallel_calls=AUTOTUNE)
                # dataset = dataset.map(lambda x,y: _cond_apply(x, y, func=aug, prob=aug_p), num_parallel_calls=AUTOTUNE)

            return dataset


    class ImageLoggerCallback(Callback):
        '''Tensorflow 2.0 version

        Callback that keeps track of a tf.data.Dataset and logs the correct batch to neptune based on the current batch.
        '''
        def __init__(self, data :tf.data.Dataset, freq=1, max_images=-1, name='', encoder=None):

            self.data = data
            self.freq = freq
            self.max_images = max_images
            self.name = name
            self.encoder=encoder
            self.init_iterator()

        def init_iterator(self):
            self.data_iter = iter(self.data)
            self._batch = 0
            self._count = 0
            self.finished = False

        def yield_batch(self):
            batch_data = next(self.data_iter)
            self._batch += 1
            self._count += batch_data[0].shape[0]
            return batch_data

        def add_log(self, img, counter=None, name=None):
            '''
            Intention is to generalize this to an abstract class for logging to any experiment management platform (e.g. neptune, mlflow, etc)

            Currently takes a filepath pointing to an image file and logs to current neptune experiment.
            '''
            scaled_img = (img - np.min(img))/(np.max(img) - np.min(img)) * 255.0
            scaled_img = scaled_img.astype(np.uint32)

            neptune.log_image(log_name= name or self.name,
                              x=counter,
                              y=scaled_img)
            return scaled_img

        def on_train_batch_begin(self, batch, logs=None):
            if batch % self.freq or self.finished:
                return
            while batch >= self._batch:
                x, y = self.yield_batch()

            if self.max_images==-1:
                self.max_images=x.shape[0]

            if x.ndim==3:
                np.newaxis(x, axis=0)
            if x.shape[0]>self.max_images:
                x = x[:self.max_images,...]
                y = y[:self.max_images,...]

            x = x.numpy()
            y = np.argmax(y.numpy(),axis=1)
            if self.encoder:
                y = self.encoder.decode(y)
            for i in range(x.shape[0]):
                # self.add_log(x[i,...], counter=i, name = f'{self.name}-{y[i]}-batch_{str(self._batch).zfill(3)}')
                self.add_log(x[i,...], counter=self._count+i, name = f'{self.name}-{y[i]}')
            print(f'Batch {self._batch}: Logged {np.max([x.shape[0],self.max_images])} {self.name} images to neptune')

        def on_epoch_end(self, epoch, logs={}):
            self.finished = True


    class ConfusionMatrixCallback(Callback):
        '''Tensorflow 2.0 version'''
        def __init__(self, log_dir, imgs : dict, labels : dict, classes, freq=1, include_train=False, seed=None):
            self.file_writer = tf.summary.create_file_writer(log_dir)
            self.log_dir = log_dir
            self.seed = seed
            self._counter = 0
            assert np.all(np.array(imgs.keys()) == np.array(labels.keys()))
            self.imgs = imgs

            for k,v in labels.items():
                if v.ndim==2:
                    labels[k] = tf.argmax(v,axis=-1)
            self.labels = labels
            self.num_samples = {k:l.numpy().shape[0] for k,l in labels.items()}
            self.classes = classes
            self.freq = freq
            self.include_train = include_train

        def log_confusion_matrix(self, model, imgs, labels, epoch, name='', norm_cm=False):

            pred_labels = model.predict_classes(imgs)
            # pred_labels = tf.argmax(pred_labels,axis=-1)
            pred_labels = pred_labels[:,None]

            con_mat = tf.math.confusion_matrix(labels=labels, predictions=pred_labels, num_classes=len(self.classes)).numpy()
            if norm_cm:
                con_mat = np.around(con_mat.astype('float') / con_mat.sum(axis=1)[:, np.newaxis], decimals=2)
            con_mat_df = pd.DataFrame(con_mat,
                             index = self.classes,
                             columns = self.classes)

            figure = plt.figure(figsize=(12, 12))
            sns.heatmap(con_mat_df, annot=True, cmap=plt.cm.Blues)
            plt.tight_layout()
            plt.ylabel('True label')
            plt.xlabel('Predicted label')

            buf = io.BytesIO()
            plt.savefig(buf, format='png')
            buf.seek(0)

            image = tf.image.decode_png(buf.getvalue(), channels=4)
            image = tf.expand_dims(image, 0)

            with self.file_writer.as_default():
                tf.summary.image(name=name+'_confusion_matrix', data=image, step=self._counter)

            neptune.log_image(log_name=name+'_confusion_matrix',
                              x=self._counter,
                              y=figure)
            plt.close(figure)
            self._counter += 1

            return image

        def on_epoch_end(self, epoch, logs={}):

            if (not self.freq) or (epoch%self.freq != 0):
                return

            if self.include_train:
                cm_summary_image = self.log_confusion_matrix(self.model, self.imgs['train'], self.labels['train'], epoch=epoch, name='train')
            cm_summary_image = self.log_confusion_matrix(self.model, self.imgs['val'], self.labels['val'], epoch=epoch, name='val')

####################################################################################
####################################################################################
####################################################################################



    neptune.init(project_qualified_name=args.neptune_project_name)
    # neptune_tb.integrate_with_tensorflow()


    experiment_dir = '/media/data/jacob/sandbox_logs'
    experiment_name = args.experiment_name

    experiment_start_time = arrow.utcnow().format('YYYY-MM-DD_HH-mm-ss')
    log_dir =os.path.join(experiment_dir, experiment_name, 'log_dir',PARAMS['loss'], experiment_start_time)
    ensure_dir_exists(log_dir)
    print('Tensorboard log_dir: ', log_dir)
    # os.system(f'neptune tensorboard {log_dir} --project {args.neptune_project_name}')

    weights_best = os.path.join(log_dir, 'model_ckpt.h5')
    restore_best_weights=False
    histogram_freq=0
    patience=25
    num_epochs = PARAMS['num_epochs']
    initial_epoch=0

    src_db = pyleaves.DATABASE_PATH
    datasets = {
                'PNAS': pnas_dataset.PNASDataset(src_db=src_db),
                'Leaves': leaves_dataset.LeavesDataset(src_db=src_db),
                'Fossil': fossil_dataset.FossilDataset(src_db=src_db)
                }
    # data = datasets[PARAMS['dataset_name']]
    data_config = stuf(threshold=PARAMS['data_threshold'],
                       num_classes=PARAMS['num_classes']    ,
                       data_splits_meta={
                                         'train':PARAMS['train_size'],
                                         'val':PARAMS['val_size'],
                                         'test':PARAMS['test_size']
                                        }
                       )

    preprocess_input = get_preprocessing_func(PARAMS['model_name'])
    preprocess_input(tf.zeros([4, 224, 224, 3]))
    
    load_example = partial(_load_uint8_example, num_classes=data_config.num_classes)
    # load_example = partial(_load_example, num_classes=data_config.num_classes)


    if PARAMS['num_channels']==3:
        color_aug = {'rgb2gray_3channel':1.0}
    elif PARAMS['num_channels']==1:
        color_aug = {'rgb2gray_1channel':1.0}

    resize_w_pad=None
    random_jitter=None
    if not PARAMS['random_jitter']['resize']:
        resize_w_pad = PARAMS['image_size']
    else:
        random_jitter=PARAMS['random_jitter']

    TRAIN_image_augmentor = ImageAugmentor(name='train',
                                           augmentations={**PARAMS["augmentations"],
                                                          **color_aug},#'rotate':1.0,'flip':1.0,**color_aug},
                                           resize_w_pad=resize_w_pad,
                                           random_crop=None,
                                           random_jitter=random_jitter,
                                           log_dir=log_dir,
                                           seed=None)
    VAL_image_augmentor = ImageAugmentor(name='val',
                                         augmentations={**color_aug},
                                         resize_w_pad=PARAMS['image_size'],
                                         random_crop=None,
                                         random_jitter=None,
                                         log_dir=log_dir,
                                         seed=None)
    TEST_image_augmentor = ImageAugmentor(name='test',
                                          augmentations={**color_aug},
                                          resize_w_pad=PARAMS['image_size'],
                                          random_crop=None,
                                          random_jitter=None,
                                          log_dir=log_dir,
                                          seed=None)


    def neptune_log_augmented_images(split_data, num_demo_samples=40, PARAMS=PARAMS):
        num_demo_samples = 40
        cm_data_x = {'train':[],'val':[]}
        cm_data_y = {'train':[],'val':[]}
        cm_data_x['train'], cm_data_y['train'] = next(iter(get_data_loader(data=split_data['train'], data_subset_mode='train', batch_size=num_demo_samples, infinite=True, augment=False,seed=2836)))
        cm_data_x['val'], cm_data_y['val'] = next(iter(get_data_loader(data=split_data['val'], data_subset_mode='val', batch_size=num_demo_samples, infinite=True, augment=False, seed=2836)))

        for (k_x,v_x), (k_y, v_y) in zip(cm_data_x.items(), cm_data_y.items()):
            x = tf.data.Dataset.from_tensor_slices(v_x)
            y = tf.data.Dataset.from_tensor_slices(v_y)
            xy_data = tf.data.Dataset.zip((x, y))
            v = xy_data.map(VAL_image_augmentor.resize, num_parallel_calls=AUTOTUNE)
            v_aug = TRAIN_image_augmentor.apply_augmentations(xy_data)
            v_x, v_y = [i.numpy() for i in next(iter(v.batch(10*num_demo_samples)))]
            v_x_aug, v_y_aug = [i.numpy() for i in next(iter(v_aug.batch(10*num_demo_samples)))]
            k = k_x
            for i in range(num_demo_samples):
                print(f'Neptune: logging {k}_{i}')
                print(f'{v_x[i].shape}, {v_x_aug[i].shape}')
                idx = np.random.randint(0,len(v_x))
                if True: #'train' in k:
                    TRAIN_image_augmentor.logger.add_log(v_x[idx],counter=i, name=k)
                    TRAIN_image_augmentor.logger.add_log(v_x_aug[idx],counter=i, name=k+'_aug')


    def get_data_loader(data : tuple, data_subset_mode='train', batch_size=32, num_classes=None, infinite=True, augment=True, seed=2836):

        num_samples = len(data[0])
        x = tf.data.Dataset.from_tensor_slices(data[0])
        labels = tf.data.Dataset.from_tensor_slices(data[1])
        data = tf.data.Dataset.zip((x, labels))

        data = data.cache()
        if data_subset_mode == 'train':
            data = data.shuffle(buffer_size=num_samples)

        # data = data.map(lambda x,y: (tf.image.convert_image_dtype(load_img(x)*255.0,dtype=tf.uint8),y), num_parallel_calls=-1)
        # data = data.map(load_example, num_parallel_calls=AUTOTUNE)
        data = data.map(load_example, num_parallel_calls=AUTOTUNE)


        data = data.map(lambda x,y: (preprocess_input(x), y), num_parallel_calls=AUTOTUNE)

        if infinite:
            data = data.repeat()

        if data_subset_mode == 'train':
            data = data.shuffle(buffer_size=200, seed=seed)
            augmentor = TRAIN_image_augmentor
        elif data_subset_mode == 'val':
            augmentor = VAL_image_augmentor
        elif data_subset_mode == 'test':
            augmentor = TEST_image_augmentor

        if augment:
            data = augmentor.apply_augmentations(data)

        data = data.batch(batch_size, drop_remainder=True)

        return data.prefetch(AUTOTUNE)

    def get_tfds_data_loader(data : tf.data.Dataset, data_subset_mode='train', batch_size=32, num_samples=100, num_classes=19, infinite=True, augment=True, seed=2836):


        def encode_example(x, y):
            x = tf.image.convert_image_dtype(x, tf.float32) * 255.0
            y = _encode_label(y, num_classes=num_classes)
            return x, y

        test_d = next(iter(data))
        print(test_d[0].numpy().min())
        print(test_d[0].numpy().max())

        data = data.shuffle(buffer_size=num_samples) \
                   .cache() \
                   .map(encode_example, num_parallel_calls=AUTOTUNE)

        test_d = next(iter(data))
        print(test_d[0].numpy().min())
        print(test_d[0].numpy().max())

        data = data.map(preprocess_input, num_parallel_calls=AUTOTUNE)

        test_d = next(iter(data))
        print(test_d[0].numpy().min())
        print(test_d[0].numpy().max())

        if data_subset_mode == 'train':
            data = data.shuffle(buffer_size=100, seed=seed)
            augmentor = TRAIN_image_augmentor
        elif data_subset_mode == 'val':
            augmentor = VAL_image_augmentor
        elif data_subset_mode == 'test':
            augmentor = TEST_image_augmentor

        if augment:
            data = augmentor.apply_augmentations(data)

        test_d = next(iter(data))
        print(test_d[0].numpy().min())
        print(test_d[0].numpy().max())

        data = data.batch(batch_size, drop_remainder=True)
        if infinite:
            data = data.repeat()

        return data.prefetch(AUTOTUNE)






    # y_true = [[0, 1, 0], [0, 0, 1]]
    # y_pred = [[0.05, 0.95, 0], [0.1, 0.8, 0.1]]

    def accuracy(y_true, y_pred):
        y_pred = tf.argmax(y_pred, axis=-1)
        y_true = tf.argmax(y_true, axis=-1)

        return tf.reduce_mean(tf.cast(tf.equal(y_true, y_pred), tf.float32))


    def true_pos(y_true, y_pred):
        # y_true = K.ones_like(y_true)
        return K.sum(K.round(K.clip(y_true * y_pred, 0, 1)))

    def false_pos(y_true, y_pred):
        # y_true = K.ones_like(y_true)
        true_positives = K.sum(K.round(K.clip(y_true * y_pred, 0, 1)))
        all_positives = K.sum(K.round(K.clip(y_true, 0, 1)))
        return all_positives - true_positives

    def true_neg(y_true, y_pred):
        # y_true = K.ones_like(y_true)
        return K.sum(1-K.round(K.clip(y_true * y_pred, 0, 1)))

    def recall(y_true, y_pred):
        # y_true = K.ones_like(y_true)
        true_positives = K.sum(K.round(K.clip(y_true * y_pred, 0, 1)))
        all_positives = K.sum(K.round(K.clip(y_true, 0, 1)))

        recall = true_positives / (all_positives + K.epsilon())
        return recall

    def precision(y_true, y_pred):
        y_true = K.ones_like(y_true)

        true_positives = K.sum(K.round(K.clip(y_true * y_pred, 0, 1)))

        predicted_positives = K.sum(K.round(K.clip(y_pred, 0, 1)))
        precision = true_positives / (predicted_positives + K.epsilon())
        # tf.print(y_true, y_pred)
        return precision

    def f1_score(y_true, y_pred):
        m_precision = precision(y_true, y_pred)
        m_recall = recall(y_true, y_pred)
        # pdb.set_trace()
        return 2*((m_precision*m_recall)/(m_precision+m_recall+K.epsilon()))

    # def false_neg(y_true, y_pred):
    #     y_true = K.ones_like(~y_true)
    #     true_neg = K.sum(K.round(K.clip(y_true * y_pred, 0, 1)))
    #     all_negative = K.sum(K.round(K.clip(y_true, 0, 1)))
    #     return all_negatives - true_

        # return K.mean(K.argmax(y_true,axis=1)*K.argmax(y_pred,axis=1))

        # 'accuracy',
        # metrics.TrueNegatives(name='tn'),
        # metrics.FalseNegatives(name='fn'),
    METRICS = [
        f1_score,
        metrics.TruePositives(name='tp'),
        metrics.FalsePositives(name='fp'),
        metrics.CategoricalAccuracy(name='accuracy'),
        metrics.TopKCategoricalAccuracy(name='top_3_categorical_accuracy', k=3),
        metrics.TopKCategoricalAccuracy(name='top_5_categorical_accuracy', k=5)
    ]
    PARAMS['sys.argv'] = ' '.join(sys.argv)

    with neptune.create_experiment(name=experiment_name, params=PARAMS, upload_source_files=[__file__]):


        print('Logging experiment tags:')
        for tag in args.tags:
            print(tag)
            neptune.append_tag(tag)

        neptune.append_tag(PARAMS['dataset_name'])
        neptune.append_tag(PARAMS['model_name'])
        neptune.log_artifact(args.config_path)
        cm_data_x = {'train':[],'val':[]}
        cm_data_y = {'train':[],'val':[]}

        if PARAMS['dataset_name'] in tfds.list_builders():
            num_demo_samples=40

            tfds_builder = tfds.builder(PARAMS['dataset_name'])
            tfds_builder.download_and_prepare()

            num_samples = tfds_builder.info.splits['train'].num_examples
            num_samples_dict = {'train':int(num_samples*PARAMS['train_size']),
                            'val':int(num_samples*PARAMS['val_size']),
                            'test':int(num_samples*PARAMS['test_size'])}

            classes = tfds_builder.info.features['label'].names
            num_classes = len(classes)

            train_slice = [0,int(PARAMS['train_size']*100)]
            val_slice = [int(PARAMS['train_size']*100), int((PARAMS['train_size']+PARAMS['val_size'])*100)]
            test_slice = [100 - int(PARAMS['test_size']*100), 100]

            tfds_train_data = tfds.load(PARAMS['dataset_name'], split=f"train[{train_slice[0]}%:{train_slice[1]}%]", shuffle_files=True, as_supervised=True)
            tfds_validation_data = tfds.load(PARAMS['dataset_name'], split=f"train[{val_slice[0]}%:{val_slice[1]}%]", shuffle_files=True, as_supervised=True)
            tfds_test_data = tfds.load(PARAMS['dataset_name'], split=f"train[{test_slice[0]}%:{test_slice[1]}%]", shuffle_files=True, as_supervised=True)

            # PARAMS['batch_size']=1
            train_data = get_tfds_data_loader(data = tfds_train_data, data_subset_mode='train', batch_size=PARAMS['batch_size'], num_samples=num_samples_dict['train'], num_classes=num_classes, infinite=True, augment=True, seed=2836)
            validation_data = get_tfds_data_loader(data = tfds_validation_data, data_subset_mode='val', batch_size=PARAMS['batch_size'], num_samples=num_samples_dict['val'], num_classes=num_classes, infinite=True, augment=True, seed=2837)
            test_data = get_tfds_data_loader(data = tfds_test_data, data_subset_mode='test', batch_size=PARAMS['batch_size'], num_samples=num_samples_dict['test'], num_classes=num_classes, infinite=True, augment=True, seed=2838)

            # tfds_train_data = tfds.load(PARAMS['dataset_name'], split=f"train[{train_slice[0]}%:{train_slice[1]}%]", shuffle_files=True, as_supervised=True)
            # tfds_validation_data = tfds.load(PARAMS['dataset_name'], split=f"train[{val_slice[0]}%:{val_slice[1]}%]", shuffle_files=True, as_supervised=True)
            # tfds_test_data = tfds.load(PARAMS['dataset_name'], split=f"train[{test_slice[0]}%:{test_slice[1]}%]", shuffle_files=True, as_supervised=True)

            split_data = {'train':get_tfds_data_loader(data = tfds_train_data, data_subset_mode='train', batch_size=num_demo_samples, num_samples=num_samples_dict['train'], num_classes=num_classes, infinite=True, augment=True, seed=2836),
                          'val':get_tfds_data_loader(data = tfds_validation_data, data_subset_mode='val', batch_size=num_demo_samples, num_samples=num_samples_dict['val'], num_classes=num_classes, infinite=True, augment=True, seed=2837),
                          'test':get_tfds_data_loader(data = tfds_test_data, data_subset_mode='test', batch_size=num_demo_samples, num_samples=num_samples_dict['test'], num_classes=num_classes, infinite=True, augment=True, seed=2838)
                          }

            steps_per_epoch=num_samples_dict['train']//PARAMS['batch_size']
            validation_steps=num_samples_dict['val']//PARAMS['batch_size']

            cm_data_x['train'], cm_data_y['train'] = next(iter(split_data['train']))
            cm_data_x['val'], cm_data_y['val'] = next(iter(split_data['val']))

        else:
            data = datasets[PARAMS['dataset_name']]
            neptune.set_property('num_classes',data.num_classes)
            neptune.set_property('class_distribution',data.metadata.class_distribution)

            encoder = base_dataset.LabelEncoder(data.data.family)
            split_data = base_dataset.preprocess_data(data, encoder, data_config)
            # import pdb;pdb.set_trace()
            for subset, subset_data in split_data.items():
                split_data[subset] = [list(i) for i in unzip(subset_data)]

            PARAMS['batch_size'] = 32

            steps_per_epoch=len(split_data['train'][0])//PARAMS['batch_size']#//10
            validation_steps=len(split_data['val'][0])//PARAMS['batch_size']#//10

            split_datasets = {
                              k:base_dataset.BaseDataset.from_dataframe(
                                pd.DataFrame({
                                            'path':v[0],
                                            'family':v[1]
                                            })) \
                              for k,v in split_data.items()
                             }

            for k,v in split_datasets.items():
                print(k, v.num_classes)

            classes = split_datasets['train'].classes

            train_data=get_data_loader(data=split_data['train'], data_subset_mode='train', batch_size=PARAMS['batch_size'], infinite=True, augment=True, seed=2836)
            validation_data=get_data_loader(data=split_data['val'], data_subset_mode='val', batch_size=PARAMS['batch_size'], infinite=True, augment=True, seed=2837)
            if 'test' in split_data.keys():
                test_data=get_data_loader(data=split_data['test'], data_subset_mode='test', batch_size=PARAMS['batch_size'], infinite=True, augment=True, seed=2838)

            num_demo_samples=150
            # neptune_log_augmented_images(split_data, num_demo_samples=num_demo_samples, PARAMS=PARAMS)
            cm_data_x['train'], cm_data_y['train'] = next(iter(get_data_loader(data=split_data['train'], data_subset_mode='train', batch_size=num_demo_samples, infinite=True, augment=True, seed=2836)))
            cm_data_x['val'], cm_data_y['val'] = next(iter(get_data_loader(data=split_data['val'], data_subset_mode='val', batch_size=num_demo_samples, infinite=True, augment=True,  seed=2836)))


        ########################################################################################
        train_image_logger_cb = ImageLoggerCallback(data=train_data, freq=20, max_images=-1, name='train', encoder=encoder)
        val_image_logger_cb = ImageLoggerCallback(data=validation_data, freq=20, max_images=-1, name='val', encoder=encoder)
        ########################################################################################

        cm_callback = ConfusionMatrixCallback(log_dir, cm_data_x, cm_data_y, classes=classes, seed=PARAMS['seed'], include_train=True)
        checkpoint = ModelCheckpoint(weights_best, monitor='val_loss', verbose=0, save_best_only=True, save_weights_only=False, mode='min',restore_best_weights=restore_best_weights)
        tfboard = TensorBoard(log_dir=log_dir, histogram_freq=histogram_freq, write_images=True)
        early = EarlyStopping(monitor='val_loss', patience=patience, verbose=1)
        callbacks = [checkpoint,tfboard,early, cm_callback, neptune_logger, train_image_logger_cb, val_image_logger_cb]
    ##########################
        if PARAMS['optimizer'] == 'Adam':
            optimizer = tf.keras.optimizers.Adam(
                learning_rate=PARAMS['lr']
            )
        elif PARAMS['optimizer'] == 'Nadam':
            optimizer = tf.keras.optimizers.Nadam(
                learning_rate=PARAMS['lr']
            )
        elif PARAMS['optimizer'] == 'SGD':
            optimizer = tf.keras.optimizers.SGD(
                learning_rate=PARAMS['lr']
            )
    ##########################
        if PARAMS['loss']=='focal_loss':
            loss = focal_loss(gamma=2.0, alpha=4.0)
        elif PARAMS['loss']=='categorical_crossentropy':
            loss = 'categorical_crossentropy'
    ##########################
        model_params = stuf(name=PARAMS['model_name'],
                            model_dir=os.path.join(experiment_dir, experiment_name, 'models'),
                            num_classes=PARAMS['num_classes'],
                            frozen_layers = PARAMS['frozen_layers'],
                            input_shape = (*PARAMS['image_size'],PARAMS['num_channels']),
                            base_learning_rate = PARAMS['lr'],
                            regularization = PARAMS['regularization'])
    ####
        if PARAMS['model_name']=='shallow':
            model = build_shallow(input_shape=model_params.input_shape,
                                  num_classes=PARAMS['num_classes'],
                                  optimizer=optimizer,
                                  loss=loss,
                                  METRICS=METRICS)

        else:
            model = build_model(model_params,
                                optimizer,
                                loss,
                                METRICS)
        print(f"TRAINING {PARAMS['model_name']}")

        model.summary(print_fn=lambda x: neptune.log_text('model_summary', x))

        history = model.fit(train_data,
                            epochs=num_epochs,
                            callbacks=callbacks,
                            validation_data=validation_data,
                            shuffle=True,
                            initial_epoch=initial_epoch,
                            steps_per_epoch=steps_per_epoch,
                            validation_steps=validation_steps)


        if 'test' in split_data:
            results = model.evaluate(test_data,
                                    steps=len(split_data['test'][0]))
        else:
            results = model.evaluate(validation_data,
                                    steps=validation_steps)
Ejemplo n.º 17
0
    def train_model(self, themes_weight: ThemeWeights,
                    dataset: TrainValidationDataset, voc_size: int,
                    keras_callback: LambdaCallback):

        input = keras.layers.Input(shape=(dataset.article_length))

        outputs: List[keras.layers.Layer] = []

        for i in range(0, dataset.theme_count):
            print("")
            dense = keras.layers.Embedding(
                input_dim=voc_size, output_dim=self.embedding_size)(input)
            ltsm = keras.layers.Bidirectional(
                keras.layers.LSTM(self.LTSM_output_size,
                                  recurrent_dropout=0.2,
                                  dropout=0.2))(dense)
            dropout = keras.layers.Dropout(0.2)(ltsm)
            dense2 = keras.layers.Dense(units=self.dense2_output_size,
                                        activation=tf.nn.relu)(dropout)
            output = keras.layers.Dense(
                units=1,
                activation=tf.nn.sigmoid,
                name=str(i),
                kernel_regularizer=regularizers.l2(0.01),
                activity_regularizer=regularizers.l1(0.01))(dense2)
            outputs.append(output)

        if len(outputs) > 1:
            outputs = [keras.layers.concatenate(outputs)]
        else:
            outputs = [outputs]

        model = keras.Model(inputs=[input], outputs=outputs)

        model.compile(
            optimizer=tf.keras.optimizers.Adam(clipnorm=1, clipvalue=0.5),
            #loss=tf.keras.losses.BinaryCrossentropy(from_logits=True),
            loss=WeightedBinaryCrossEntropy(
                weights=themes_weight.weight_list(), from_logits=True),
            # loss = {"0" : tf.keras.losses.BinaryCrossentropy(from_logits=True),
            #         "1" : tf.keras.losses.BinaryCrossentropy(from_logits=True)},
            metrics=[
                metrics.AUC(multi_label=True),
                metrics.BinaryAccuracy(),
                metrics.TruePositives(),
                metrics.TrueNegatives(),
                metrics.FalseNegatives(),
                metrics.FalsePositives(),
                metrics.Recall(),
                metrics.Precision()
            ],
            run_eagerly=False)

        model.summary()

        keras.utils.plot_model(model,
                               self.__model_name__ + '.png',
                               show_shapes=True)

        callbacks = [ManualInterrupter, keras_callback]

        # model.fit(self.dataset.trainData, epochs=15, steps_per_epoch=self.dataset.train_batch_count,
        #           validation_data=self.dataset.validationData, validation_steps=self.dataset.validation_batch_count,
        #           callbacks=callbacks, class_weight=self.theme_weight)

        # model.fit(self.dataset.trainData, epochs=10, steps_per_epoch=self.dataset.train_batch_count,
        #           validation_data=self.dataset.validationData, validation_steps=self.dataset.validation_batch_count,
        #           callbacks=callbacks, class_weight={ 0 : 1, 1 : 7.8, 2 : 4.3})

        model.fit(dataset.trainData,
                  epochs=40,
                  steps_per_epoch=dataset.train_batch_count,
                  validation_data=dataset.validationData,
                  validation_steps=dataset.validation_batch_count,
                  callbacks=callbacks)

        self.__model__ = model
Ejemplo n.º 18
0
def run_model(model,
              train_generator,
              validation_generator,
              min_lr,
              max_lr,
              model_path,
              tensorboard_path,
              trial_id,
              optimizer,
              hparams=None,
              step_factor=8,
              epochs=120,
              loss=tf.keras.losses.CategoricalCrossentropy(from_logits=False)):
    checkpoint_path = os.path.join(model_path, 'cp-best.cpkt')
    checkpoint = tf.keras.callbacks.ModelCheckpoint(checkpoint_path,
                                                    monitor='val_AUC',
                                                    mode='max',
                                                    verbose=1,
                                                    save_freq='epoch',
                                                    save_best_only=True,
                                                    save_weights_only=True)
    tensorboard = tf.keras.callbacks.TensorBoard(
        log_dir=tensorboard_path, profile_batch=0,
        write_graph=True)  # profile_batch='300,401',

    lrate = SGDRScheduler(min_lr=min_lr,
                          max_lr=max_lr,
                          steps_per_epoch=len(train_generator),
                          cycle_length=step_factor,
                          lr_decay=0.5,
                          mult_factor=1,
                          gentle_start_epochs=0,
                          gentle_fraction=1.0)
    add_lr = Add_Images_and_LR(log_dir=tensorboard_path, add_images=False)
    early_stop = tf.keras.callbacks.EarlyStopping(monitor='val_AUC',
                                                  patience=300,
                                                  verbose=True,
                                                  mode='max')
    callbacks = [tensorboard, lrate, add_lr]
    # if epochs < 9000:
    callbacks += [early_stop]
    if hparams is not None:
        hp_callback = Callback(tensorboard_path,
                               hparams=hparams,
                               trial_id='Trial_ID:{}'.format(trial_id))
        callbacks += [hp_callback]
    callbacks += [checkpoint]
    METRICS = [
        metrics.TruePositives(name='TruePositive'),
        metrics.FalsePositives(name='FalsePositive'),
        metrics.TrueNegatives(name='TrueNegative'),
        metrics.FalseNegatives(name='FalseNegative'),
        metrics.BinaryAccuracy(name='Accuracy'),
        metrics.Precision(name='Precision'),
        metrics.Recall(name='Recall'),
        metrics.AUC(name='AUC'),
    ]
    print('\n\n\n\nRunning {}\n\n\n\n'.format(tensorboard_path))
    model.compile(optimizer, loss=loss, metrics=METRICS)
    model.fit(train_generator.data_set,
              epochs=epochs,
              steps_per_epoch=len(train_generator),
              validation_data=validation_generator.data_set,
              validation_steps=len(validation_generator),
              validation_freq=10,
              callbacks=callbacks)
    model.save(os.path.join(model_path, 'final_model.h5'))
    tf.keras.backend.clear_session()
    return None
Ejemplo n.º 19
0
def train(
    csv_path,
    model_save_path,
    tfrecords_path,
    volume_shape=(128, 128, 128),
    image_size=(128, 128),
    dropout=0.2,
    batch_size=16,
    n_classes=2,
    n_epochs=15,
    mode="CV",
):
    """Train a model.

    Parameters
    ----------
    csv_path: str - Path
        Path to the csv file containing training volume paths, labels (X, Y).
    model_save_path: str - Path
        Path to where the save model and model weights.
    tfrecords_path: str - Path
        Path to preprocessed training tfrecords.
    volume_shape: tuple of size 3, optional, default=(128, 128, 128)
        The shape of the preprocessed volumes.
    image_size: tuple of size 2, optional, default=(128, 128)
        The shape of a 2D slice along each volume axis.
    dropout: float, optional, default=0.4
         Float between 0 and 1. Fraction of the input units to drop.
    batch_size: int, optional, default=16
        No. of training examples utilized in each iteration.
    n_classes: int, optional, default=2
        No. of unique classes to train the model on. Default assumption is a
        binary classifier.
    n_epochs: int, optional, default=15
        No. of complete passes through the training dataset.
    mode: str, optional, default=15
        One of "CV" or "full". Indicates the type of training to perform.

    Returns
    -------
    `tf.keras.callbacks.History`
        A History object that records several metrics such as training/validation loss/metrics
        at successive epochs.
    """

    train_csv_path = os.path.join(csv_path, "training.csv")
    train_paths = pd.read_csv(train_csv_path)["X"].values
    train_labels = pd.read_csv(train_csv_path)["Y"].values

    if mode == "CV":
        valid_csv_path = os.path.join(csv_path, "validation.csv")
        valid_paths = pd.read_csv(valid_csv_path)["X"].values
        # valid_labels = pd.read_csv(valid_csv_path)["Y"].values

    weights = class_weight.compute_class_weight("balanced",
                                                np.unique(train_labels),
                                                train_labels)
    weights = dict(enumerate(weights))

    planes = ["axial", "coronal", "sagittal", "combined"]

    global_batch_size = batch_size

    os.makedirs(model_save_path, exist_ok=True)
    cp_save_path = os.path.join(model_save_path, "weights")
    logdir_path = os.path.join(model_save_path, "tb_logs")
    metrics_path = os.path.join(model_save_path, "metrics")

    os.makedirs(metrics_path, exist_ok=True)

    for plane in planes:

        logdir = os.path.join(logdir_path, plane)
        os.makedirs(logdir, exist_ok=True)

        tbCallback = TensorBoard(log_dir=logdir)

        os.makedirs(os.path.join(cp_save_path, plane), exist_ok=True)

        model_checkpoint = ModelCheckpoint(
            os.path.join(cp_save_path, plane, "best-wts.h5"),
            monitor="val_loss",
            save_weights_only=True,
            mode="min",
        )

        if not plane == "combined":
            lr = 1e-3
            model = _model.Submodel(
                input_shape=image_size,
                dropout=dropout,
                name=plane,
                include_top=True,
                weights=None,
            )
        else:
            lr = 5e-4
            model = _model.CombinedClassifier(
                input_shape=image_size,
                dropout=dropout,
                trainable=True,
                wts_root=cp_save_path,
            )

        print("Submodel: ", plane)

        METRICS = [
            metrics.TruePositives(name="tp"),
            metrics.FalsePositives(name="fp"),
            metrics.TrueNegatives(name="tn"),
            metrics.FalseNegatives(name="fn"),
            metrics.BinaryAccuracy(name="accuracy"),
            metrics.Precision(name="precision"),
            metrics.Recall(name="recall"),
            metrics.AUC(name="auc"),
        ]

        model.compile(
            loss=tf.keras.losses.binary_crossentropy,
            optimizer=Adam(learning_rate=lr),
            metrics=METRICS,
        )

        dataset_train = get_dataset(
            file_pattern=os.path.join(tfrecords_path, "data-train_*"),
            n_classes=n_classes,
            batch_size=global_batch_size,
            volume_shape=volume_shape,
            plane=plane,
            shuffle_buffer_size=global_batch_size,
        )

        steps_per_epoch = math.ceil(len(train_paths) / batch_size)

        if mode == "CV":
            earlystopping = EarlyStopping(monitor="val_loss", patience=3)

            dataset_valid = get_dataset(
                file_pattern=os.path.join(tfrecords_path, "data-valid_*"),
                n_classes=n_classes,
                batch_size=global_batch_size,
                volume_shape=volume_shape,
                plane=plane,
                shuffle_buffer_size=global_batch_size,
            )

            validation_steps = math.ceil(len(valid_paths) / batch_size)

            history = model.fit(
                dataset_train,
                epochs=n_epochs,
                steps_per_epoch=steps_per_epoch,
                validation_data=dataset_valid,
                validation_steps=validation_steps,
                callbacks=[tbCallback, model_checkpoint, earlystopping],
                class_weight=weights,
            )

            hist_df = pd.DataFrame(history.history)

        else:
            earlystopping = EarlyStopping(monitor="loss", patience=3)
            print(model.summary())
            print("Steps/Epoch: ", steps_per_epoch)
            history = model.fit(
                dataset_train,
                epochs=n_epochs,
                steps_per_epoch=steps_per_epoch,
                callbacks=[tbCallback, model_checkpoint, earlystopping],
                class_weight=weights,
            )

        hist_df = pd.DataFrame(history.history)
        jsonfile = os.path.join(metrics_path, plane + ".json")

        with open(jsonfile, mode="w") as f:
            hist_df.to_json(f)

    return history
Ejemplo n.º 20
0
def dag_2_cnn(dag, gpuID, input_shape=(256,256,1), target_shape=(256,256,1), pretrained_weights = None, compile=True):
    os.environ["CUDA_VISIBLE_DEVICES"] = str(gpuID)
    nodes = list(dag.nodes())
    
    #breadth-first search starting at root
    bfs = nx.bfs_successors(dag, nodes[0])
    modules = dict()

    #root will always have this name
    assert(nodes[0] == 'input_0_0')

    with tf.device('/gpu:{}'.format(gpuID)):
        modules[nodes[0]] = Input(input_shape)
        
        for branch in bfs: #branch: tuple with (node, [list of successors to node])
            for successor in branch[1]:
                modules = traverse(dag, successor, modules)
                
        leaves = [x for x in dag.nodes() if dag.out_degree(x)==0 and dag.in_degree(x)>0]
        
        if len(leaves) == 1:
            output = modules[leaves[0]]
        else:
            raise NotImplementedError
        
        #NOTE: mean iou removed from metrics 21/07/2020
        model = Model(inputs=modules['input_0_0'], outputs=output)
        
        if compile:
            model.compile(optimizer=Adam(lr=1e-4), loss='binary_crossentropy', metrics=['accuracy', metrics.Precision(), metrics.Recall(), metrics.TruePositives(), metrics.TrueNegatives(), metrics.FalsePositives(), metrics.FalseNegatives(), metrics.AUC()])
        
        
        if pretrained_weights:
            model.load_weights(pretrained_weights)

    return model
Ejemplo n.º 21
0
from tensorflow.keras              import metrics
from tensorflow.keras.optimizers   import RMSprop, SGD

losses = {'clone': "binary_crossentropy",
        'partial': "binary_crossentropy",
        'fufi': "binary_crossentropy"
}

lossWeights = {'clone': weight_ccpf[1],
             'partial': weight_ccpf[2],
             'fufi': weight_ccpf[3]
}

metrics_use = {'clone': [metrics.TruePositives(), 
                     metrics.FalseNegatives(), 
                     metrics.FalsePositives(), 
                     metrics.TrueNegatives()],
             'partial': [metrics.TruePositives(), 
                       metrics.FalseNegatives(), 
                       metrics.FalsePositives(), 
                       metrics.TrueNegatives()],
             'fufi': [metrics.TruePositives(), 
                       metrics.FalseNegatives(), 
                       metrics.FalsePositives(), 
                       metrics.TrueNegatives()]
}

just_trnsf.compile(optimizer=RMSprop(lr=0.0001), loss = losses,
                   loss_weights = lossWeights, metrics = metrics_use)   
                   
weights_name_next = dnnfolder + "/weights/trnsf_finetune_test.hdf5"
Ejemplo n.º 22
0
    def train_model(self, themes_weight: List[float],
                    dataset: TrainValidationDataset, voc_size: int,
                    keras_callback: LambdaCallback):

        article_length = dataset.article_length
        theme_count = dataset.theme_count

        model = tf.keras.Sequential([
            # 1
            # keras.layers.Embedding(input_dim=voc_size, output_dim=firstLayoutOutputDim),
            # keras.layers.Dropout(0.2),
            # keras.layers.Conv1D(200,3,input_shape=(ARTICLE_MAX_WORD_COUNT,firstLayoutOutputDim), activation=tf.nn.relu),
            # keras.layers.GlobalAveragePooling1D(),
            # keras.layers.Dense(250, activation=tf.nn.relu),
            # keras.layers.Dense(theme_count, activation=tf.nn.softmax)

            # 2
            # keras.layers.Embedding(input_dim=voc_size, output_dim=firstLayoutOutputDim),
            # keras.layers.LSTM(ltsmOutputDim, dropout=0.2, recurrent_dropout=0.2, activation='tanh'),
            # keras.layers.Dense(theme_count, activation=tf.nn.softmax)

            # 3
            # keras.layers.Embedding(input_dim=self.voc_size, output_dim=embedding_output_dim),
            # keras.layers.Bidirectional(keras.layers.LSTM(intermediate_dim, return_sequences=True)),
            # # keras.layers.Dropout(0.1),
            # keras.layers.Bidirectional(keras.layers.LSTM(last_dim, dropout=0.05, recurrent_dropout=0.05)),
            # keras.layers.Dense(last_dim, activation=tf.nn.relu),
            # keras.layers.Dense(self.theme_count, activation=tf.nn.softmax)

            # 4
            # keras.layers.Embedding(input_dim=self.voc_size, input_length=self.article_length, output_dim=embedding_output_dim),
            # keras.layers.Bidirectional(keras.layers.LSTM(intermediate_dim, return_sequences=True, dropout=0.2, recurrent_dropout=0.2)),
            # keras.layers.Dropout(0.2),
            # keras.layers.Bidirectional(keras.layers.LSTM(last_dim * 2, recurrent_dropout=0.2)), #was last_dim * 2
            # keras.layers.Dense(last_dim, activation=tf.nn.relu),
            # keras.layers.Dense(self.theme_count, activation=tf.nn.sigmoid)

            # 5
            #keras.layers.Embedding(input_dim=self.voc_size, input_length=self.article_length, output_dim=embedding_output_dim),
            # keras.layers.Conv1D(filters=64, kernel_size=5, input_shape=(self.voc_size, embedding_output_dim), activation="relu"),
            # keras.layers.MaxPool1D(4),
            #keras.layers.Bidirectional(keras.layers.LSTM(intermediate_dim, recurrent_dropout=0.1)),
            #keras.layers.Dense(last_dim, activation=tf.nn.relu),
            #keras.layers.Dense(self.theme_count, activation=tf.nn.sigmoid)

            #6
            keras.layers.Embedding(input_dim=voc_size,
                                   input_length=article_length,
                                   output_dim=128,
                                   mask_zero=True),
            keras.layers.Bidirectional(
                keras.layers.LSTM(128, recurrent_dropout=0.2, dropout=0.2)),
            #keras.layers.Dropout(0.2),
            #keras.layers.Dense(last_dim, activation=tf.nn.relu),
            # keras.layers.Dense(self.theme_count, activation=tf.nn.sigmoid, use_bias=True,bias_initializer=tf.keras.initializers.Constant(-1.22818328))
            keras.layers.Dense(theme_count,
                               activation=tf.nn.sigmoid,
                               kernel_regularizer=regularizers.l2(0.1),
                               activity_regularizer=regularizers.l1(0.05))

            # 7
            # keras.layers.Embedding(input_dim=self.voc_size, input_length=self.article_length,
            #                        output_dim=embedding_output_dim),
            # keras.layers.GlobalAvgPool1D(),
            # keras.layers.Dense(last_dim, activation=tf.nn.relu),
            # keras.layers.Dense(self.theme_count, activation=tf.nn.sigmoid)
        ])

        model.summary()

        model.compile(
            optimizer=tf.keras.optimizers.Adam(clipnorm=1, clipvalue=0.5),
            #loss=WeightedBinaryCrossEntropy(themes_weight, from_logits=True),
            loss=keras.losses.BinaryCrossentropy(from_logits=True),
            metrics=[
                metrics.AUC(),
                metrics.BinaryAccuracy(),
                metrics.TruePositives(),
                metrics.TrueNegatives(),
                metrics.FalseNegatives(),
                metrics.FalsePositives(),
                metrics.Recall(),
                metrics.Precision()
            ],
            run_eagerly=self.run_eagerly)

        keras.utils.plot_model(model, 'Model1.png', show_shapes=True)

        cb_list = [ManualInterrupter, keras_callback]

        model.fit(dataset.trainData,
                  epochs=10,
                  steps_per_epoch=dataset.train_batch_count,
                  validation_data=dataset.validationData,
                  validation_steps=dataset.validation_batch_count,
                  callbacks=cb_list,
                  class_weight={
                      0: 1,
                      1: themes_weight[0]
                  })

        model.save("output/" + self.get_model_name() + ".h5")
        model.save_weights("output/" + self.get_model_name() + "_weight.h5")

        self.__model__ = model
Ejemplo n.º 23
0
    def compile_fit(self,
                    model_input,
                    q_train_padded,
                    a_train_padded,
                    y_q_label_df,
                    y_a_label_df,
                    y_q_classify_list,
                    y_q_classify_dict,
                    y_a_classify_list,
                    y_a_classify_dict,
                    epoch_num=3):
        """
        This function is used to switch between numrical. The switch controled by hyperparameters self.TYPE
        When self.TYPE == 'num', input will be q_train_padded and y_q_label_df (others are same)
        Meanwhile, switch to ['MSE'] as loss and ['mse', 'mae'] as metrics

        When self.TYPE == 'classify', input will be q_train_padded and y_q_classify_list[0] etc.
        Meanwhile, swith to ['categorical_crossentropy'] as loss and ['accuracy'] as metrics

        """
        start_time = time()
        print("*" * 40, "Start {} Processing".format(model_input._name),
              "*" * 40)
        # loss_fun = 'categorical_crossentropy'
        # loss_fun = 'MSE' #MeanSquaredError
        # loss_fun = '

        METRICS = [
            metrics.TruePositives(name='tp'),
            metrics.FalsePositives(name='fp'),
            metrics.TrueNegatives(name='tn'),
            metrics.FalseNegatives(name='fn'),
            metrics.CategoricalAccuracy(name='accuracy'),
            metrics.Precision(name='precision'),
            metrics.Recall(name='recall'),
            metrics.AUC(name='auc'),
            # F1Score(num_classes = int(y_train.shape[1]), name='F1')
        ]

        loss_fun = None
        metrics_fun = None
        # becase large data input, we want to process automaticaly. So set this arugs to choose
        # question process or answer process automatically
        if self.PART == 'q':
            print("Start processing question part")
            # start to decide complie parameters
            if self.TYPE == 'num':
                print("Start numerical output")
                # call split
                X_train, X_val, y_train, y_val = self.split_data(
                    q_train_padded, y_q_label_df, test_size=0.2)
                loss_fun = losses.MeanSquaredError()
                metrics_fun = ['mse', 'mae']
            elif self.TYPE == 'classify':
                print("Start classify output")
                X_train, X_val, y_train, y_val = self.split_data(
                    q_train_padded, y_q_classify_list[0], test_size=0.2)
                loss_fun = losses.CategoricalCrossentropy()
                metrics_fun = METRICS
            else:
                print("UNKNOW self.TYPE")

        elif self.PART == 'a':
            print("Start processing answer part")
            if self.TYPE == 'num':
                print("Start numerical output")
                # call split
                X_train, X_val, y_train, y_val = self.split_data(
                    a_train_padded, y_a_label_df, test_size=0.2)
                loss_fun = losses.MeanSquaredError()
                metrics_fun = ['mse', 'mae']
            elif self.TYPE == 'classify':
                print("Start classify output")
                X_train, X_val, y_train, y_val = self.split_data(
                    a_train_padded, y_a_classify_list[0], test_size=0.2)
                loss_fun = losses.CategoricalCrossentropy()
                metrics_fun = METRICS
            else:
                print("UNKNOW self.TYPE")

        learning_rate = 1e-3
        opt_adam = optimizers.Adam(lr=learning_rate, decay=1e-5)
        model_input.compile(loss=loss_fun,
                            optimizer=opt_adam,
                            metrics=metrics_fun)
        # batch_size is subjected to my GPU and GPU memory, after testing, 32 is reasonable value size.
        # If vector bigger, this value should dercrease

        history = model_input.fit(
            X_train,
            y_train,
            validation_data=(X_val, y_val),
            epochs=epoch_num,
            batch_size=16,
            verbose=1,
            callbacks=[PredictCallback(X_val, y_val, model_input)])
        # spearmanr_list = PredictCallback(X_val, y_val, model_input).spearmanr_list
        # dic = ['loss', 'accuracy', 'val_loss','val_accuracy']
        history_dict = [x for x in history.history]
        # model_input.predict(train_features[:10])

        cost_time = round((time() - start_time), 4)
        print("*" * 40,
              "End {} with {} seconds".format(model_input._name, cost_time),
              "*" * 40,
              end='\n\n')

        return history, model_input
Ejemplo n.º 24
0
            print(model_index)
            model_parameters = parameters[model_index]
            for key in model_parameters.keys():
                if type(model_parameters[key]) is np.int64:
                    model_parameters[key] = int(model_parameters[key])
                elif type(model_parameters[key]) is np.float64:
                    model_parameters[key] = float(model_parameters[key])
            out_parameters['Model_Index'].append(model_index)
            model_base_path = r'H:\Deeplearning_Recurrence_Work\Models\Model_Index_{}'.format(model_index)
            pred_path = os.path.join(model_base_path, 'Predictions.npy')
            truth_path = os.path.join(model_base_path, 'Truth.npy')
            model_path = os.path.join(model_base_path, 'cp-best.cpkt')
            # model_path = os.path.join(model_base_path, 'final_model.h5')
            METRICS = [
                metrics.TruePositives(name='TruePositive'),
                metrics.FalsePositives(name='FalsePositive'),
                metrics.TrueNegatives(name='TrueNegative'),
                metrics.FalseNegatives(name='FalseNegative'),
                metrics.BinaryAccuracy(name='Accuracy'),
                metrics.Precision(name='Precision'),
                metrics.Recall(name='Recall'),
                metrics.AUC(name='AUC', multi_label=True),
            ]

            model = mydensenet(**model_parameters)
            model.load_weights(model_path)
            model.compile(optimizer=optimizers.Adam(), loss=CosineLoss(), metrics=METRICS)
            visualizer = ModelVisualizationClass(model=model, save_images=True,
                                                 out_path=r'H:\Deeplearning_Recurrence_Work\Activation_Images_{}'.format(model_index))
            all_layers = visualizer.all_layers
            desired_layers = [i.name for i in all_layers if i.name.startswith('conv')]
Ejemplo n.º 25
0
    def train_model(self, themes_weight: List[float],
                    dataset: TrainValidationDataset, voc_size: int,
                    keras_callback: LambdaCallback):
        epochs = 60
        embedding_output_dim = 128
        last_dim = 128

        article_length = dataset.article_length
        theme_count = dataset.theme_count

        model = tf.keras.Sequential([
            keras.layers.Embedding(input_dim=voc_size,
                                   input_length=article_length,
                                   output_dim=embedding_output_dim,
                                   mask_zero=True),
            keras.layers.Conv1D(filters=64,
                                kernel_size=3,
                                input_shape=(voc_size, embedding_output_dim),
                                activation=tf.nn.relu),
            keras.layers.GlobalMaxPooling1D(),
            keras.layers.Dropout(0.2),
            keras.layers.Dense(last_dim, activation=tf.nn.relu),
            keras.layers.Dropout(0.2),
            keras.layers.Dense(theme_count,
                               activation=tf.nn.sigmoid,
                               kernel_regularizer=regularizers.l2(0.2),
                               activity_regularizer=regularizers.l1(0.1))
        ])

        model.summary()

        model.compile(optimizer=tf.keras.optimizers.Adam(clipnorm=1,
                                                         clipvalue=0.5),
                      loss=WeightedBinaryCrossEntropy(themes_weight,
                                                      from_logits=True),
                      metrics=[
                          metrics.AUC(),
                          metrics.BinaryAccuracy(),
                          metrics.TruePositives(),
                          metrics.TrueNegatives(),
                          metrics.FalseNegatives(),
                          metrics.FalsePositives(),
                          metrics.Recall(),
                          metrics.Precision()
                      ],
                      run_eagerly=self.run_eagerly)

        keras.utils.plot_model(model,
                               "output/" + self.model_name + ".png",
                               show_shapes=True)

        model.fit(dataset.trainData,
                  epochs=epochs,
                  steps_per_epoch=dataset.train_batch_count,
                  validation_data=dataset.validationData,
                  validation_steps=dataset.validation_batch_count,
                  callbacks=[ManualInterrupter(), keras_callback])

        model.save("output/" + self.model_name + ".h5")
        model.save_weights("output/" + self.model_name + "_weight.h5")

        self.__model__ = model
Ejemplo n.º 26
0
def unet_sep(param,
             input_shape=(1024, 1024, 3),
             roi_pool_size=[10, 10],
             chan_num=3,
             weight_ccpf=[1, 1, 1, 1, 1],
             projection_dim=100,
             transformer_layers=4,
             num_heads=4,
             is_comp=True,
             lr=1e-3):
    num_bbox = param["num_bbox"]

    input_img = layers.Input(shape=input_shape)
    input_bbox = layers.Input(shape=(num_bbox, 4))

    ## get unet stem model
    just_unet = strde_unet_xcept_gn_shallow()
    #    just_unet  = strde_unet_xcept_gn_deep()
    #    just_unet = strde_sepconv_unet_xcept_gn_shallow()
    #    just_unet = strde_sepconv_unet_xcept_gn_deep()
    #    just_unet = res_unet()

    ## and classifier model
    just_trnsf = classify_branch(num_bbox=num_bbox,
                                 crypt_class=param['crypt_class'])

    ## crate instances of models
    inst_cr, inst_fm = just_unet(input_img)

    if param['crypt_class']:
        inst_cl, inst_pa, inst_fu, inst_crcls = just_trnsf(
            [inst_fm, input_bbox])

        ## combine into final model
        final_model = Model(
            inputs=[input_img, input_bbox],
            outputs=[inst_cr, inst_cl, inst_pa, inst_fu, inst_crcls])

        losses = {
            'crypt': "binary_crossentropy",
            'cpf': "binary_crossentropy",
            'cpf_1': "binary_crossentropy",
            'cpf_2': "binary_crossentropy",
            'cpf_3': "binary_crossentropy"
        }
        lossWeights = {
            'crypt': weight_ccpf[0],
            'cpf': weight_ccpf[1],
            'cpf_1': weight_ccpf[2],
            'cpf_2': weight_ccpf[3],
            'cpf_3': weight_ccpf[4]
        }
        metrics_use = {
            'crypt':
            metrics.Accuracy(),
            'cpf': [
                metrics.TruePositives(),
                metrics.FalseNegatives(),
                metrics.FalsePositives(),
                metrics.TrueNegatives()
            ],
            'cpf_1': [
                metrics.TruePositives(),
                metrics.FalseNegatives(),
                metrics.FalsePositives(),
                metrics.TrueNegatives()
            ],
            'cpf_2': [
                metrics.TruePositives(),
                metrics.FalseNegatives(),
                metrics.FalsePositives(),
                metrics.TrueNegatives()
            ],
            'cpf_3': [
                metrics.TruePositives(),
                metrics.FalseNegatives(),
                metrics.FalsePositives(),
                metrics.TrueNegatives()
            ]
        }
    else:
        inst_cl, inst_pa, inst_fu = just_trnsf([inst_fm, input_bbox])

        ## combine into final model
        final_model = Model(inputs=[input_img, input_bbox],
                            outputs=[inst_cr, inst_cl, inst_pa, inst_fu])

        losses = {
            'crypt': "binary_crossentropy",
            'cpf': "binary_crossentropy",
            'cpf_1': "binary_crossentropy",
            'cpf_2': "binary_crossentropy"
        }
        lossWeights = {
            'crypt': weight_ccpf[0],
            'cpf': weight_ccpf[1],
            'cpf_1': weight_ccpf[2],
            'cpf_2': weight_ccpf[3]
        }
        metrics_use = {
            'crypt':
            metrics.Accuracy(),
            'cpf': [
                metrics.TruePositives(),
                metrics.FalseNegatives(),
                metrics.FalsePositives(),
                metrics.TrueNegatives()
            ],
            'cpf_1': [
                metrics.TruePositives(),
                metrics.FalseNegatives(),
                metrics.FalsePositives(),
                metrics.TrueNegatives()
            ],
            'cpf_2': [
                metrics.TruePositives(),
                metrics.FalseNegatives(),
                metrics.FalsePositives(),
                metrics.TrueNegatives()
            ]
        }
    if is_comp:  # compile
        final_model.compile(optimizer=Adam(lr=lr),
                            loss=losses,
                            loss_weights=lossWeights,
                            metrics=metrics_use)
    return final_model, just_trnsf, just_unet
 def confusion_matrix_metric(self):
     return [metrics.TruePositives(name='tp'),
     metrics.FalsePositives(name='fp'),
     metrics.TrueNegatives(name='tn'),
     metrics.FalseNegatives(name='fn')]
Ejemplo n.º 28
0
    RANDOM_STATE = int(args.random_state)
    TEST_SIZE = float(args.val_size)
    LEARNING_RATE = float(args.learning_rate)
    EPOCHS = int(args.epochs)
    BATCH_SIZE = int(args.batch_size)
    DROPOUT = float(args.dropout)
    IMGSIZE = (int(args.imgsize[0]), int(args.imgsize[1]))
    LOGDIR = args.logdir
    DATA = args.data
    BACKBONE = args.backbone
    NAME = args.model

    # --- define model metrics ---
    METRICS = [
        metrics.TruePositives(name="True_Positives"),
        metrics.FalsePositives(name="False_Positives"),
        metrics.TrueNegatives(name="True_Negatives"),
        metrics.FalseNegatives(name="False_Negatives"),
        metrics.BinaryAccuracy(name="Binary_Accuracy"),
        metrics.Precision(name="Precision"),
        metrics.Recall(name="Recall"),
        metrics.AUC(name="AUC")
    ]

    # --- tensorflow calbacks ---
    date = datetime.datetime.now().strftime("%Y%m%d-%H%M%S")
    if platform.system().lower() == "windows":
        LOGDIR = LOGDIR + "\\" + NAME + "\\" + date
    else:
        LOGDIR = LOGDIR + "/" + NAME + "/" + date
    if not os.path.isdir(LOGDIR):
def find_best_lr(batch_size=24):
    tf.random.set_seed(3141)
    base_path, morfeus_drive, excel_path = return_paths()

    # if base_path.startswith('H'):  # Only run this locally
    #     create_excel_values(excel_path=excel_path)
    for iteration in [0]:
        out_path = os.path.join(morfeus_drive, 'Learning_Rates')
        model_parameters, out_path = return_model_parameters(
            out_path=out_path, excel_path=excel_path, iteration=iteration)
        if model_parameters is None:
            continue
        model_key = model_parameters['Model_Type']
        optimizer = model_parameters['Optimizer']
        model_base = return_model(model_key=model_key)
        model = model_base(**model_parameters)
        if model_parameters['loss'] == 'CosineLoss':
            loss = CosineLoss()
            min_lr = 1e-6
            max_lr = 1e-1
        elif model_parameters['loss'] == 'CategoricalCrossEntropy':
            loss = tf.keras.losses.CategoricalCrossentropy()
            min_lr = 1e-10
            max_lr = 1e-3
        _, _, train_generator, validation_generator = return_generators(
            batch_size=batch_size,
            model_key=model_key,
            all_training=True,
            cache=True,
            cache_add='LR_Finder_{}'.format(model_key))
        print(out_path)
        k = TensorBoard(log_dir=out_path, profile_batch=0, write_graph=True)
        k.set_model(model)
        k.on_train_begin()
        lr_opt = tf.keras.optimizers.Adam
        if optimizer == 'SGD':
            lr_opt = tf.keras.optimizers.SGD
        elif optimizer == 'Adam':
            lr_opt = tf.keras.optimizers.Adam
        elif optimizer == 'RAdam':
            lr_opt = RectifiedAdam
        METRICS = [
            metrics.TruePositives(name='TruePositive'),
            metrics.FalsePositives(name='FalsePositive'),
            metrics.TrueNegatives(name='TrueNegative'),
            metrics.FalseNegatives(name='FalseNegative'),
            metrics.CategoricalAccuracy(name='Accuracy'),
            metrics.Precision(name='Precision'),
            metrics.Recall(name='Recall'),
            metrics.AUC(name='AUC'),
        ]
        LearningRateFinder(epochs=10,
                           model=model,
                           metrics=METRICS,
                           out_path=out_path,
                           optimizer=lr_opt,
                           loss=loss,
                           steps_per_epoch=1000,
                           train_generator=train_generator.data_set,
                           lower_lr=min_lr,
                           high_lr=max_lr)
        tf.keras.backend.clear_session()
        return False  # repeat!
    return True