Esempio n. 1
0
def main(args):
    # Used for memory error in RTX2070
    physical_devices = tf.config.experimental.list_physical_devices('GPU')
    config = tf.config.experimental.set_memory_growth(physical_devices[0],
                                                      True)

    input_size = (None, None)
    # Load model from JSON file if file path was provided...
    if os.path.exists(args.model):
        try:
            with open(args.model, 'r') as f:
                json = f.read()
            model = model_from_json(json)
            args.model = os.path.splitext(os.path.split(args.model)[-1])[0]
        except JSONDecodeError:
            raise ValueError(
                "JSON decode error found. File path %s exists but could not be decoded; verify if JSON encoding was "
                "performed properly." % args.model)
    # ...Otherwise, create model from this project by using a proper key name
    else:
        model = models_dict[args.model]((input_size[0], input_size[1], 1))
    try:
        # Model name should match with the name of a model from
        # https://www.tensorflow.org/api_docs/python/tf/keras/applications/
        # This assumes you used a model with RGB inputs as the first part of your model,
        # therefore your input data should be preprocessed with the corresponding
        # 'preprocess_input' function
        m = importlib.import_module('tensorflow.keras.applications.%s' %
                                    model.name)
        rgb_preprocessor = getattr(m, "preprocess_input")
    except ModuleNotFoundError:
        rgb_preprocessor = None

    # Load trained weights
    model.load_weights(args.pretrained_weights)

    # Model is compiled to provide the desired metrics
    model.compile(optimizer=Adam(lr=1e-4),
                  loss=custom_losses.bce_dsc_loss(3.0),
                  metrics=[
                      custom_losses.dice_coef,
                      keras_metrics.Precision(),
                      keras_metrics.Recall()
                  ])

    # Here we find to paths to all images from the selected datasets
    paths = data.create_image_paths(args.dataset_names, args.dataset_paths)

    for path in paths[0, :]:

        [im, gt, pred] = data.test_image_from_path(model, path, None,
                                                   rgb_preprocessor)

        name = os.path.split(path)[-1]
        name, extension = os.path.splitext(name)
        extension = ".png"
        if not os.path.exists(args.save_to) and path != '':
            os.makedirs(args.save_to)
        cv2.imwrite(os.path.join(args.save_to, name + extension),
                    255 * np.where(pred > 0.5, 1.0, 0.0))
Esempio n. 2
0
def main(args):
    input_size = (None, None)
    # Load model from JSON file if file path was provided...
    if os.path.exists(args.model):
        try:
            with open(args.model, 'r') as f:
                json = f.read()
            model = model_from_json(json)
            args.model = os.path.splitext(os.path.split(args.model)[-1])[0]
        except JSONDecodeError:
            raise ValueError(
                "JSON decode error found. File path %s exists but could not be decoded; verify if JSON encoding was "
                "performed properly." % args.model)
    # ...Otherwise, create model from this project by using a proper key name
    else:
        model = models_dict[args.model]((input_size[0], input_size[1], 1))
    try:
        # Model name should match with the name of a model from
        # https://www.tensorflow.org/api_docs/python/tf/keras/applications/
        # This assumes you used a model with RGB inputs as the first part of your model,
        # therefore your input data should be preprocessed with the corresponding
        # 'preprocess_input' function
        m = importlib.import_module('tensorflow.keras.applications.%s' % model.name)
        rgb_preprocessor = getattr(m, "preprocess_input")
    except ModuleNotFoundError:
        rgb_preprocessor = None

    # Load trained weights
    model.load_weights(args.pretrained_weights)

    # Model is compiled to provide the desired metrics
    model.compile(optimizer=Adam(lr=1e-4), loss=custom_losses.bce_dsc_loss(3.0),
                  metrics=[custom_losses.dice_coef, keras_metrics.Precision(), keras_metrics.Recall()])

    # Here we find to paths to all images from the selected datasets
    paths = data.create_image_paths(args.dataset_names, args.dataset_paths)

    print("Evaluating the model...")
    data.save_results_on_paths(model, paths, args.save_to)
    metrics = model.evaluate(x=data.validation_image_generator(paths, batch_size=1, rgb_preprocessor=rgb_preprocessor),
                             steps=paths.shape[1])
    result_string = "Dataset: %s\nModel: %s\n" % ("/".join(args.dataset_names), args.model)
    for idx, metric in enumerate(model.metrics_names):
        result_string += "{}: {:.4f}\n".format(metric, metrics[idx])
    for attribute in args.__dict__.keys():
        result_string += "\n--%s: %s" % (attribute, str(args.__getattribute__(attribute)))
    with open(os.path.join(args.save_to, "results.txt"), "w") as f:
        f.write(result_string.strip())
Esempio n. 3
0
def main(args):
    start = datetime.now().strftime("%d-%m-%Y_%H.%M")
    results_dir = "results_%s" % start
    results_train_dir = os.path.join(results_dir, "results_training")
    results_train_min_loss_dir = results_train_dir + "_min_val_loss"
    results_validation_dir = os.path.join(results_dir, "results_validation")
    results_validation_min_loss_dir = results_validation_dir + "_min_val_loss"
    input_size = (None, None)
    # Load model from JSON file if file path was provided...
    if os.path.exists(args.model):
        try:
            with open(args.model, 'r') as f:
                json = f.read()
            model = model_from_json(json)
            args.model = os.path.splitext(os.path.split(args.model)[-1])[0]
        except JSONDecodeError:
            raise ValueError(
                "JSON decode error found. File path %s exists but could not be decoded; verify if JSON encoding was "
                "performed properly." % args.model)
    # ...Otherwise, create model from this project by using a proper key name
    else:
        model = models_dict[args.model]((input_size[0], input_size[1], 1))
    try:
        # Model name should match with the name of a model from
        # https://www.tensorflow.org/api_docs/python/tf/keras/applications/
        # This assumes you used a model with RGB inputs as the first part of your model,
        # therefore your input data should be preprocessed with the corresponding
        # 'preprocess_input' function
        m = importlib.import_module('tensorflow.keras.applications.%s' %
                                    model.name)
        rgb_preprocessor = getattr(m, "preprocess_input")
    except ModuleNotFoundError:
        rgb_preprocessor = None

    # We don't resize images for training, but provide image patches of reduced size for memory saving
    # An image is turned into this size patches in a chess-board-like approach
    input_size = args.training_crop_size

    # For fine tuning, one can provide previous weights
    if args.pretrained_weights:
        model.load_weights(args.pretrained_weights)

    # Model is compiled so it can be trained
    model.compile(optimizer=Adam(lr=args.learning_rate),
                  loss=custom_losses.bce_dsc_loss(args.alpha),
                  metrics=[
                      custom_losses.dice_coef, 'binary_crossentropy',
                      keras_metrics.Precision(),
                      keras_metrics.Recall()
                  ])

    # Here we find to paths to all images from the selected datasets
    paths = data.create_image_paths(args.dataset_names, args.dataset_paths)
    # Data is split into 80% for training data and 20% for validation data. A custom seed is used for reproducibility.
    n_training_images = int(0.8 * paths.shape[1])
    np.random.seed(0)
    np.random.shuffle(paths.transpose())
    training_paths = paths[:, :n_training_images]
    validation_paths = paths[:, n_training_images:]

    # If asked by the user, save the paths of the validation split (useful to validate later)
    if args.save_validation_paths:
        with open("validation_paths.txt", "w+") as file:
            print("Validation paths saved to 'validation_paths.txt'")
            file.write("\n".join(
                [";".join(paths) for paths in validation_paths.transpose()]))

    # As input images can be of different sizes, here we calculate the total number of patches used for training.
    print(
        "Calculating the total number of samples after cropping and data augmentatiton. "
        "This may take a while, don't worry.")
    n_train_samples = next(
        data.train_image_generator(training_paths,
                                   input_size,
                                   args.batch_size,
                                   count_samples_mode=True,
                                   rgb_preprocessor=None,
                                   data_augmentation=args.use_da))
    print("\nProceeding to train.")

    # A customized early stopping callback. At each epoch end, the callback will test the current weights on the
    # validation set (using whole images instead of patches) and stop the training if the minimum validation loss hasn't
    # improved over the last 'patience' epochs.
    es = EarlyStoppingAtMinValLoss(validation_paths,
                                   file_path='%s_best.hdf5' % args.model,
                                   patience=args.patience,
                                   rgb_preprocessor=rgb_preprocessor)
    reduce_lr = ReduceLROnPlateau(monitor='val_loss', factor=0.5, patience=5)
    tensorboard = tf.keras.callbacks.TensorBoard(log_dir="logs")

    # Training begins. Note that the train image generator can use or not data augmentation through the parsed argument
    # 'use_da'
    print("Start!")
    try:
        history = model.fit(x=data.train_image_generator(
            training_paths,
            input_size,
            args.batch_size,
            rgb_preprocessor=rgb_preprocessor,
            data_augmentation=args.use_da),
                            epochs=args.epochs,
                            verbose=1,
                            callbacks=[es, reduce_lr, tensorboard],
                            steps_per_epoch=n_train_samples // args.batch_size)
        print("Finished!")
    except KeyboardInterrupt:
        # This assumes a user keyboard interruption, as a hard early stop
        print("Training interrupted. Only the best model will be saved.")
        # Load the weights from the epoch with the minimum validation loss
        model.load_weights('%s_best.hdf5' % args.model)
        args.epochs = 0

    # Save the weights of the last training epoch. If trained on a single epoch, these weights are equal to the
    # best weights (to avoid redundancy, no new weights file is saved)
    if args.epochs > 0:
        model.save_weights("%s.hdf5" % args.model)
        print("Last epoch's weights saved.")

    print("Evaluating the model...")
    print("On training paths:")
    data.save_results_on_paths(model, training_paths, results_train_dir)
    if args.epochs > 0:
        os.replace("%s.hdf5" % args.model,
                   os.path.join(results_train_dir, "%s.hdf5" % args.model))
    else:
        model.save_weights(
            os.path.join(results_train_dir, "%s.hdf5" % args.model))
    print("\nOn validation paths:")
    data.save_results_on_paths(model, validation_paths, results_validation_dir)

    # Evaluate the model quantitatively by using the tensorflow model's metrics
    metrics = model.evaluate(x=data.validation_image_generator(
        validation_paths, batch_size=1, rgb_preprocessor=rgb_preprocessor),
                             steps=validation_paths.shape[1])
    result_string = "Dataset: %s\nModel: %s\n" % ("/".join(
        args.dataset_names), args.model)
    for idx, metric in enumerate(model.metrics_names):
        result_string += "{}: {:.4f}\n".format(metric, metrics[idx])
    for attribute in args.__dict__.keys():
        result_string += "\n--%s: %s" % (attribute,
                                         str(args.__getattribute__(attribute)))
    with open(os.path.join(results_validation_dir, "results.txt"), "w") as f:
        f.write(result_string.strip())

    # If the model was trained more than one epoch, evaluate the best validation weights in the same validation data.
    # Otherwise, the best validation weights are the weights at the end of the only training epoch
    if args.epochs > 1:
        # Load results using the min val loss epoch's weights
        model.load_weights('%s_best.hdf5' % args.model)
        print("Evaluating the model with minimum validation loss...")
        print("On training paths:")
        data.save_results_on_paths(model, training_paths,
                                   results_train_min_loss_dir)
        print("\nOn validation paths:")
        data.save_results_on_paths(model, validation_paths,
                                   results_validation_min_loss_dir)
        os.replace(
            '%s_best.hdf5' % args.model,
            os.path.join(results_train_min_loss_dir,
                         '%s_best.hdf5' % args.model))
        metrics = model.evaluate(x=data.validation_image_generator(
            validation_paths, batch_size=1, rgb_preprocessor=rgb_preprocessor),
                                 steps=validation_paths.shape[1])
        result_string = "Dataset: %s\nModel: %s\n" % ("/".join(
            args.dataset_names), args.model)
        for idx, metric in enumerate(model.metrics_names):
            result_string += "{}: {:.4f}\n".format(metric, metrics[idx])
        for attribute in args.__dict__.keys():
            result_string += "\n--%s: %s" % (
                attribute, str(args.__getattribute__(attribute)))
        with open(os.path.join(results_validation_min_loss_dir, "results.txt"),
                  "w") as f:
            f.write(result_string.strip())

        # If trained more than one epoch, save the training history as csv and plot it
        print("\nPlotting training history...")
        import pandas as pd
        pd.DataFrame.from_dict(history.history).to_csv(os.path.join(
            results_dir, "training_history.csv"),
                                                       index=False)
        # summarize history for loss
        for key in history.history.keys():
            plt.plot(history.history[key])
        plt.ylim((0.0, 1.0 + args.alpha))
        plt.title('model losses')
        plt.ylabel('value')
        plt.xlabel('epoch')
        plt.legend(history.history.keys(), loc='upper left')
        plt.savefig(os.path.join(results_dir, "training_losses.png"))
Esempio n. 4
0
def main(args):
    input_size = (256, 256)

    paths = data.create_image_paths(args.dataset_names, args.dataset_paths)
    n_training_images = int(0.8 * paths.shape[1])
    np.random.seed(0)
    np.random.shuffle(paths.transpose())
    training_paths = paths[:, :n_training_images]
    test_paths = paths[:, n_training_images:]

    n_train_samples = next(
        data.train_image_generator(training_paths,
                                   input_size,
                                   1,
                                   resize=False,
                                   count_samples_mode=True,
                                   rgb_preprocessor=None))

    from itertools import chain, combinations

    def powerset(iterable):
        "powerset([1,2,3]) --> () (1,) (2,) (3,) (1,2) (1,3) (2,3) (1,2,3)"
        s = list(iterable)
        return chain.from_iterable(
            combinations(s, r) for r in range(len(s) + 1))

    space = {
        'alpha':
        hp.choice('alpha', [0.3, 3.0, 5.0]),
        'learning_rate':
        hp.choice('learning_rate', [0.001, 0.0005, 0.0001, 0.00005, 0.00001]),
        'train_vgg':
        hp.choice('train_vgg', [True, False])
    }
    metric_score = "dice_coef"

    def f_nn(params):

        vgg19 = VGG19(include_top=False,
                      weights='imagenet',
                      input_tensor=None,
                      input_shape=(None, None, 3),
                      pooling=None)
        encoder = Model(vgg19.input,
                        vgg19.get_layer("block5_conv4").output,
                        name="encoder")

        # encoder.trainable = params["train_vgg"]
        for layer in encoder.layers:
            if layer.name.startswith("block5_conv"):
                layer.trainable = params["train_vgg"]

        d_i = Input(shape=(encoder.output.shape[1:]), name='decoder_input')
        block5_up = UpSampling2D(size=(2, 2), name="block5_up")(d_i)

        block4_1_conv0 = Conv2D(filters=512,
                                kernel_size=3,
                                padding='same',
                                activation='relu',
                                name="block4_1_conv0")(block5_up)
        block4_merge = Concatenate(axis=-1, name="block4_merge")(
            [vgg19.get_layer("block4_conv4").output, block4_1_conv0])
        block4_1_conv1 = Conv2D(filters=512,
                                kernel_size=3,
                                padding='same',
                                activation='relu',
                                name="block4_1_conv1")(block4_merge)
        block4_1_conv2 = Conv2D(filters=512,
                                kernel_size=3,
                                padding='same',
                                activation='relu',
                                name="block4_1_conv2")(block4_1_conv1)
        block4_1_conv3 = Conv2D(filters=512,
                                kernel_size=3,
                                padding='same',
                                activation='relu',
                                name="block4_1_conv3")(block4_1_conv2)
        block4_1_conv4 = Conv2D(filters=512,
                                kernel_size=3,
                                padding='same',
                                activation='relu',
                                name="block4_1_conv4")(block4_1_conv3)
        block4_up = UpSampling2D(size=(2, 2), name="block4_up")(block4_1_conv4)

        block3_1_conv0 = Conv2D(filters=256,
                                kernel_size=3,
                                padding='same',
                                activation='relu',
                                name="block3_1_conv0")(block4_up)
        block3_merge = Concatenate(axis=-1, name="block3_merge")(
            [vgg19.get_layer("block3_conv4").output, block3_1_conv0])
        block3_1_conv1 = Conv2D(filters=256,
                                kernel_size=3,
                                padding='same',
                                activation='relu',
                                name="block3_1_conv1")(block3_merge)
        block3_1_conv2 = Conv2D(filters=256,
                                kernel_size=3,
                                padding='same',
                                activation='relu',
                                name="block3_1_conv2")(block3_1_conv1)
        block3_1_conv3 = Conv2D(filters=256,
                                kernel_size=3,
                                padding='same',
                                activation='relu',
                                name="block3_1_conv3")(block3_1_conv2)
        block3_1_conv4 = Conv2D(filters=256,
                                kernel_size=3,
                                padding='same',
                                activation='relu',
                                name="block3_1_conv4")(block3_1_conv3)
        block3_up = UpSampling2D(size=(2, 2), name="block3_up")(block3_1_conv4)

        block2_1_conv0 = Conv2D(filters=128,
                                kernel_size=3,
                                padding='same',
                                activation='relu',
                                name="block2_1_conv0")(block3_up)
        block2_merge = Concatenate(axis=-1, name="block2_merge")(
            [vgg19.get_layer("block2_conv2").output, block2_1_conv0])
        block2_1_conv1 = Conv2D(filters=128,
                                kernel_size=3,
                                padding='same',
                                activation='relu',
                                name="block2_1_conv1")(block2_merge)
        block2_1_conv2 = Conv2D(filters=128,
                                kernel_size=3,
                                padding='same',
                                activation='relu',
                                name="block2_1_conv2")(block2_1_conv1)
        block2_up = UpSampling2D(size=(2, 2), name="block2_up")(block2_1_conv2)

        block1_1_conv0 = Conv2D(filters=64,
                                kernel_size=3,
                                padding='same',
                                activation='relu',
                                name="block1_1_conv0")(block2_up)
        block1_merge = Concatenate(axis=-1, name="block1_merge")(
            [vgg19.get_layer("block1_conv2").output, block1_1_conv0])
        block1_1_conv1 = Conv2D(filters=64,
                                kernel_size=3,
                                padding='same',
                                activation='relu',
                                name="block1_1_conv1")(block1_merge)
        block1_1_conv2 = Conv2D(filters=64,
                                kernel_size=3,
                                padding='same',
                                activation='relu',
                                name="block1_1_conv2")(block1_1_conv1)
        block1_1_conv3 = Conv2D(filters=2,
                                kernel_size=3,
                                padding='same',
                                activation='relu',
                                name="block1_1_conv3")(block1_1_conv2)
        output = Conv2D(filters=1,
                        kernel_size=1,
                        activation='sigmoid',
                        name="output")(block1_1_conv3)

        decoder = Model([vgg19.input, d_i], output, name="decoder")

        decoder_output = decoder([vgg19.input, encoder(encoder.input)])
        model = Model(encoder.input, decoder_output, name=vgg19.name)

        try:
            # Model name should match with the name of a model from
            # https://www.tensorflow.org/api_docs/python/tf/keras/applications/
            # This assumes you used a model with RGB inputs as the first part of your model,
            # therefore your input data should be preprocessed with the corresponding
            # 'preprocess_input' function
            m = importlib.import_module('tensorflow.keras.applications.%s' %
                                        model.name)
            rgb_preprocessor = getattr(m, "preprocess_input")
        except ModuleNotFoundError:
            rgb_preprocessor = None

        my_loss = custom_losses.bce_dsc_loss(params["alpha"])

        metrics_list = [
            custom_losses.dice_coef,
            keras_metrics.Precision(),
            keras_metrics.Recall()
        ]
        model.compile(optimizer=Adam(lr=params["learning_rate"]),
                      loss=my_loss,
                      metrics=metrics_list,
                      experimental_run_tf_function=False)

        es = EarlyStoppingAtMinValLoss(test_paths,
                                       file_path="best_test_weights.hdf5",
                                       patience=20,
                                       rgb_preprocessor=rgb_preprocessor)
        history = model.fit(x=data.train_image_generator(
            training_paths,
            input_size,
            args.batch_size,
            resize=False,
            rgb_preprocessor=rgb_preprocessor),
                            epochs=args.epochs,
                            verbose=0,
                            callbacks=[es],
                            steps_per_epoch=n_train_samples // 4)

        metrics = model.evaluate(x=data.test_image_generator(
            test_paths,
            input_size=None,
            batch_size=1,
            rgb_preprocessor=rgb_preprocessor),
                                 steps=test_paths.shape[1],
                                 verbose=0)

        for idx, metric in enumerate(model.metrics_names):
            if metric == metric_score:
                loss = metrics[idx]
                break

        try:
            with open("best_%s.txt" % metric_score, "r") as f:
                best_metric_score = float(f.read())
        except FileNotFoundError:
            best_metric_score = 0

        if loss > best_metric_score:
            with open("best_%s.txt" % metric_score, "w") as f:
                f.write(str(loss))
            model_json = model.to_json()
            with open("best_metric_score_model.json", "w") as json_file:
                json_file.write(model_json)
            model.load_weights("best_test_weights.hdf5")
            model.save_weights("best_%s_weights.hdf5" % metric_score)
            data.save_results_on_paths(model,
                                       training_paths,
                                       "results_training",
                                       rgb_preprocessor=rgb_preprocessor)
            data.save_results_on_paths(model,
                                       test_paths,
                                       "results_test",
                                       rgb_preprocessor=rgb_preprocessor)

        os.remove("best_test_weights.hdf5")
        with open("hyperparameter_search_result.txt", "a+") as f:
            f.write("{} {:.4f}, {}\n".format(metric_score, loss, params))

        plt.clf()
        for key in history.history.keys():
            if key in ["val_%s" % metric_score, metric_score]:
                plt.plot(history.history[key])
        plt.ylim((0.0, 1.0))
        plt.title('model losses')
        plt.ylabel('value')
        plt.xlabel('epoch')
        plt.legend([
            key for key in history.history.keys()
            if key in ["val_%s" % metric_score, metric_score]
        ],
                   loc='upper left')
        global iteration
        iteration += 1
        if not os.path.exists("training_histories"):
            os.makedirs("training_histories")
        plt.savefig(
            os.path.join("training_histories",
                         "history_iteration_%s.png" % iteration))

        tf.keras.backend.clear_session()
        print('Test %s:' % metric_score, loss)
        print('Params: %s' % str(params))
        return {'loss': -loss, 'status': STATUS_OK}

    try:  # try to load an already saved trials object, and increase the max
        trials = pickle.load(open("my_model.hyperopt", "rb"))
        print("Found saved Trials! Loading...")
        print("Rerunning from {} trials to {} (+{}) trials".format(
            len(trials.trials), len(trials.trials), args.fmin_max_evals))
        global iteration
        iteration += len(trials.trials)
        args.fmin_max_evals = len(trials.trials) + args.fmin_max_evals
    except:  # create a new trials object and start searching
        trials = Trials()

    best = fmin(f_nn,
                space,
                algo=tpe.suggest,
                max_evals=args.fmin_max_evals,
                trials=trials)
    print('best: ')
    print(space_eval(space, best))

    # save the trials object
    with open("my_model.hyperopt", "wb") as f:
        pickle.dump(trials, f)

    result = "Best {}: {:.4f}\nParameters: {}\n\nDSC, Parameters\n".format(
        metric_score, -trials.best_trial["result"]["loss"],
        space_eval(space, best))
    for trial in range(len(trials)):
        trial_result = trials.results[trial]['loss']
        trial_dict = {}
        for key in trials.vals.keys():
            trial_dict[key] = trials.vals[key][trial]
        result += "{:.4f}, {}\n".format(-trial_result,
                                        space_eval(space, trial_dict))
    with open("hyperparameter_search_result.txt", "w") as f:
        f.write(result.strip())

    if os.path.exists("best_%s.txt" % metric_score):
        os.remove("best_%s.txt" % metric_score)
Esempio n. 5
0
def main(args):
    # Used for memory error in RTX2070
    physical_devices = tf.config.experimental.list_physical_devices('GPU')
    config = tf.config.experimental.set_memory_growth(physical_devices[0],
                                                      True)

    input_size = (None, None)
    # Load model from JSON file if file path was provided...
    if os.path.exists(args.model):
        try:
            with open(args.model, 'r') as f:
                json = f.read()
            model = model_from_json(json)
            args.model = os.path.splitext(os.path.split(args.model)[-1])[0]
        except JSONDecodeError:
            raise ValueError(
                "JSON decode error found. File path %s exists but could not be decoded; verify if JSON encoding was "
                "performed properly." % args.model)
    # ...Otherwise, create model from this project by using a proper key name
    else:
        model = models_dict[args.model]((input_size[0], input_size[1], 1))
    try:
        # Model name should match with the name of a model from
        # https://www.tensorflow.org/api_docs/python/tf/keras/applications/
        # This assumes you used a model with RGB inputs as the first part of your model,
        # therefore your input data should be preprocessed with the corresponding
        # 'preprocess_input' function
        m = importlib.import_module('tensorflow.keras.applications.%s' %
                                    model.name)
        rgb_preprocessor = getattr(m, "preprocess_input")
    except ModuleNotFoundError:
        rgb_preprocessor = None

    # Load trained weights
    model.load_weights(args.pretrained_weights)

    # Model is compiled to provide the desired metrics
    model.compile(optimizer=Adam(lr=1e-4),
                  loss=custom_losses.bce_dsc_loss(3.0),
                  metrics=[
                      custom_losses.dice_coef,
                      keras_metrics.Precision(),
                      keras_metrics.Recall()
                  ])

    # Here we find to paths to all images from the selected datasets
    paths = data.create_image_paths(args.dataset_names, args.dataset_paths)

    header = np.array([["Image", "GT avg", "GT std", "Pred avg", "Pred std"]])
    statistics = []

    for im_path, gt_path in paths.transpose():

        [im, gt, pred] = data.test_image_from_path(model, im_path, gt_path,
                                                   rgb_preprocessor)

        gt_masked = im[np.where(gt >= 0.5)]
        pred_masked = im[np.where(pred[..., 0] >= 0.5)]

        gt_mean = round(np.mean(gt_masked), 4)
        gt_std = round(np.std(gt_masked), 4)
        pred_mean = round(np.mean(pred_masked), 4)
        pred_std = round(np.std(pred_masked), 4)

        statistics.append([
            im_path,
            str(gt_mean),
            str(gt_std),
            str(pred_mean),
            str(pred_std)
        ])

    statistics = np.array(statistics)
    footer = np.array([[
        "Average",
        str(round(np.mean(statistics[:, 1].astype(np.float)), 4)),
        str(round(np.mean(statistics[:, 2].astype(np.float)), 4)),
        str(round(np.mean(statistics[:, 3].astype(np.float)), 4)),
        str(round(np.mean(statistics[:, 4].astype(np.float)), 4))
    ]])

    result_folder, file_name = os.path.split(args.save_to)
    if not os.path.exists(result_folder) and result_folder != "":
        os.makedirs(result_folder)
    pandas.DataFrame(np.concatenate((header, statistics, footer),
                                    axis=0)).to_csv(args.save_to,
                                                    header=None,
                                                    index=None)
Esempio n. 6
0
def main(args):
    if args.resize_inputs_to == [-1, -1]:
       args.resize_inputs_to = [None, None]
    input_size = tuple(args.resize_inputs_to)
    model, loss = models_dict[args.model]((input_size[0], input_size[1], 1),
                                          latent_dim=args.latent_space_dim,
                                          self_supervised=args.self_supervised)

    def rescale(image):
        return image / 255.0
    rgb_preprocessor = rescale

    if input_size == (None, None):
        input_size = (256, 256)

    if args.pretrained_weights:
        model.load_weights(args.pretrained_weights)
    metrics_list = ['mse'] if args.self_supervised else \
        [custom_losses.dice_coef, keras_metrics.Precision(), keras_metrics.Recall()]
    model.compile(optimizer=Adam(lr=args.learning_rate), loss=loss, metrics=metrics_list,
                    experimental_run_tf_function=False
                  )

    paths = data.create_image_paths(args.dataset_names, args.dataset_paths)
    # if args.self_supervised:
    #     paths[1, :] = paths[0, :]
    n_training_images = int(0.8 * paths.shape[1])
    np.random.seed(0)
    np.random.shuffle(paths.transpose())
    training_paths = paths[:, :n_training_images]
    test_paths = paths[:, n_training_images:]

    # n_train_samples = next(data.train_image_generator(training_paths, input_size, args.batch_size,
    #                                                   resize=(model.input.shape.as_list()[1:-1] != [None, None]),
    #                                                   normalize_x=args.normalize_input,
    #                                                   rgb_preprocessor=rgb_preprocessor,
    #                                                   count_samples_mode=True, data_augmentation=args.use_da))
    # es = EarlyStoppingAtMinValLoss(test_paths, file_path='%s_best.hdf5' % args.model, patience=20,
    #                                rgb_preprocessor=rgb_preprocessor)
    #
    # history = model.fit(x=data.train_image_generator(training_paths, input_size, args.batch_size,
    #                                                  resize=(model.input.shape.as_list()[1:-1] != [None, None]),
    #                                                  normalize_x=args.normalize_input,
    #                                                  rgb_preprocessor=rgb_preprocessor,
    #                                                  data_augmentation=args.use_da),
    #                     epochs=args.epochs,
    #                     verbose=1,
    #                     callbacks=[es],
    #                     steps_per_epoch=n_train_samples // args.batch_size)

    n_train_samples = next(data.train_image_generator_clean(training_paths, input_size, args.batch_size,
                                                      resize=False,
                                                      normalize_x=args.normalize_input,
                                                      rgb_preprocessor=rgb_preprocessor,
                                                      count_samples_mode=True, data_augmentation=args.use_da))
    es = EarlyStoppingAtMinValLoss_Clean(test_paths, file_path='%s_best.hdf5' % args.model, patience=20,
                                   rgb_preprocessor=rgb_preprocessor, resize_nocrop=False, size=input_size,
                                         normalize_input=args.normalize_input)
    history = model.fit(x=data.train_image_generator_clean(training_paths, input_size, args.batch_size,
                                                     resize=False,
                                                     normalize_x=args.normalize_input,
                                                     rgb_preprocessor=rgb_preprocessor,
                                                     data_augmentation=args.use_da),
                        epochs=args.epochs,
                        verbose=1,
                        callbacks=[es],
                        steps_per_epoch=n_train_samples // args.batch_size)


    if args.epochs > 0:
        model.save_weights("%s.hdf5" % args.model)

    evaluation_input_shape = tuple(model.input.shape[1:-1])
    if evaluation_input_shape == (None, None):
        evaluation_input_shape = None

    # Save results using the last epoch's weights
    data.save_results_on_paths(model, training_paths, "results_training", rgb_preprocessor=rgb_preprocessor)
    data.save_results_on_paths(model, test_paths, "results_test", rgb_preprocessor=rgb_preprocessor)
    # metrics = model.evaluate(x=data.test_image_generator(test_paths, evaluation_input_shape, batch_size=1,
    #                                                      rgb_preprocessor=rgb_preprocessor,
    #                                                      normalize_x=args.normalize_input),
    #                          steps=test_paths.shape[1])
    metrics = model.evaluate(x=data.train_image_generator_clean(training_paths, input_size, batch_size=1,
                                                     resize=False,
                                                     normalize_x=args.normalize_input,
                                                     rgb_preprocessor=rgb_preprocessor,
                                                     data_augmentation=False),
                             steps=test_paths.shape[1])
    result_string = "Dataset: %s\nModel: %s\n" % ("/".join(args.dataset_names), args.model)
    for idx, metric in enumerate(model.metrics_names):
        result_string += "{}: {:.4f}\n".format(metric, metrics[idx])
    for attribute in args.__dict__.keys():
        result_string += "\n--%s: %s" % (attribute, str(args.__getattribute__(attribute)))
    with open(os.path.join("results_test", "results.txt"), "w") as f:
        f.write(result_string.strip())

    if args.epochs > 1:
        # Save results using the min val loss epoch's weights
        model.load_weights('%s_best.hdf5' % args.model)
        data.save_results_on_paths(model, training_paths, "results_training_min_val_loss", rgb_preprocessor=rgb_preprocessor)
        data.save_results_on_paths(model, test_paths, "results_test_min_val_loss", rgb_preprocessor=rgb_preprocessor)
        # metrics = model.evaluate(x=data.test_image_generator(test_paths, evaluation_input_shape, batch_size=1,
        #                                                      rgb_preprocessor=rgb_preprocessor,
        #                                                      normalize_x=args.normalize_input),
        #                          steps=test_paths.shape[1])
        metrics = model.evaluate(x=data.train_image_generator_clean(training_paths, input_size, batch_size=1,
                                                     resize=False,
                                                     normalize_x=args.normalize_input,
                                                     rgb_preprocessor=rgb_preprocessor,
                                                     data_augmentation=False),
                                 steps=test_paths.shape[1])
        result_string = "Dataset: %s\nModel: %s\n" % ("/".join(args.dataset_names), args.model)
        for idx, metric in enumerate(model.metrics_names):
            result_string += "{}: {:.4f}\n".format(metric, metrics[idx])
        for attribute in args.__dict__.keys():
            result_string += "\n--%s: %s" % (attribute, str(args.__getattribute__(attribute)))
        with open(os.path.join("results_test_min_val_loss", "results.txt"), "w") as f:
            f.write(result_string.strip())

    # summarize history for loss
    for key in history.history.keys():
        plt.plot(history.history[key])
    # plt.ylim((0.0, 1.0 + args.alpha))
    plt.title('model losses')
    plt.ylabel('value')
    plt.xlabel('epoch')
    plt.legend(history.history.keys(), loc='upper left')
    plt.savefig("training_losses.png")