Esempio n. 1
0
def threshold_search(cls_model='b2', shape=(320, 320)):
    max_fold = 3
    model = get_model(cls_model, shape=shape)
    kfold = StratifiedKFold(n_splits=4, random_state=133, shuffle=True)
    train_df, img_2_vector = preprocess()
    oof_true = []
    oof_pred = []

    for n_fold, (train_indices, val_indices) in enumerate(
            kfold.split(
                train_df['Image'].values,
                train_df['Class'].map(lambda x: str(sorted(list(x)))))):
        val_imgs = train_df['Image'].values[val_indices]

        if n_fold <= max_fold:
            data_generator_val = DataGenenerator(val_imgs,
                                                 shuffle=False,
                                                 resized_height=shape[0],
                                                 resized_width=shape[1],
                                                 img_2_ohe_vector=img_2_vector)

            model.load_weights('classifier/checkpoints/' + cls_model + '_' +
                               str(n_fold) + '.h5')

            y_pred = model.predict_generator(data_generator_val,
                                             workers=12,
                                             verbose=1)
            y_true = data_generator_val.get_labels()

            oof_true.extend(y_true)
            oof_pred.extend(y_pred)

    oof_true = np.asarray(oof_true)
    oof_pred = np.asarray(oof_pred)
    print(oof_true.shape)
    print(oof_pred.shape)
    recall_thresholds = dict()
    precision_thresholds = dict()
    threshold_values = np.arange(0, 1, 0.01)
    for i, class_name in tqdm(enumerate(class_names)):
        recall_thresholds[class_name], precision_thresholds[
            class_name], auc = get_threshold_for_recall(oof_true, oof_pred, i)
        # best_auc = 0
        # for t in threshold_values:
        #      r , p , auc = get_threshold_for_recall(oof_true, oof_pred, i, recall_threshold=t)
        #      if auc >= best_auc:
        #         recall_thresholds[class_name], precision_thresholds[class_name] = r,p
        #         best_auc = auc

        print('Best auc {} for class {}'.format(auc, class_name))

    return recall_thresholds
Esempio n. 2
0
def postprocess_submission(cls_model='b2',
                           shape=(320, 320),
                           submission_file=None):
    recall_thresholds = threshold_search(cls_model, shape)
    print(recall_thresholds)
    model = get_model(cls_model, shape=shape)
    data_generator_test = DataGenenerator(
        folder_imgs='../../dados/test_images',
        shuffle=False,
        batch_size=1,
        resized_height=shape[0],
        resized_width=shape[1])

    for i in range(4):
        model.load_weights('classifier/checkpoints/' + cls_model + '_' +
                           str(i) + '.h5')
        if i == 0:
            y_pred_test = model.predict_generator(data_generator_test,
                                                  workers=12,
                                                  verbose=1)
        else:
            y_pred_test += model.predict_generator(data_generator_test,
                                                   workers=12,
                                                   verbose=1)

    y_pred_test /= 4

    image_labels_empty = set()
    for i, (img, predictions) in enumerate(
            zip(os.listdir('../../dados/test_images'), y_pred_test)):
        for class_i, class_name in enumerate(class_names):
            if predictions[class_i] < recall_thresholds[class_name]:
                image_labels_empty.add(f'{img}_{class_name}')

    submission = pd.read_csv(submission_file)

    predictions_nonempty = set(
        submission.loc[~submission['EncodedPixels'].isnull(),
                       'Image_Label'].values)
    print(
        f'{len(image_labels_empty.intersection(predictions_nonempty))} masks would be removed'
    )
    submission.loc[submission['Image_Label'].isin(image_labels_empty),
                   'EncodedPixels'] = np.nan
    submission.to_csv(
        '../submissions/submission_segmentation_and_classifier.csv',
        index=None)
def train(cls_model='b2', shape=(320,320)):


    kfold = StratifiedKFold(n_splits=4, random_state=133, shuffle=True)
    train_df, img_2_vector = preprocess()

    albumentations_train = Compose([
        VerticalFlip(), HorizontalFlip(), Rotate(limit=20), GridDistortion()
    ], p=1)

    for n_fold, (train_indices, val_indices) in enumerate(kfold.split(train_df['Image'].values, train_df['Class'].map(lambda x: str(sorted(list(x)))))):
        train_imgs = train_df['Image'].values[train_indices]
        val_imgs = train_df['Image'].values[val_indices]
        data_generator_train = DataGenenerator(train_imgs, augmentation=albumentations_train,
                                               resized_height=shape[0], resized_width=shape[1],
                                               img_2_ohe_vector=img_2_vector)

        data_generator_train_eval = DataGenenerator(train_imgs, shuffle=False,
                                                    resized_height=shape[0], resized_width=shape[1],
                                                    img_2_ohe_vector=img_2_vector)

        data_generator_val = DataGenenerator(val_imgs, shuffle=False,
                                             resized_height=shape[0], resized_width=shape[1],
                                             img_2_ohe_vector=img_2_vector)

        model = get_model(cls_model, shape=shape)

        model.compile(optimizer=RAdam(), loss='binary_crossentropy',
                      metrics=['accuracy'])

        train_metric_callback = PrAucCallback(data_generator_train_eval)
        checkpoint_name = cls_model + '_' + str(n_fold)
        val_callback = PrAucCallback(data_generator_val, stage='val', checkpoint_name=checkpoint_name)

        history_0 = model.fit_generator(generator=data_generator_train,
                                        validation_data=data_generator_val,
                                        epochs=20,
                                        callbacks=[train_metric_callback, val_callback],
                                        workers=42,
                                        verbose=1
                                        )
        plt.xlabel('Recall')
        plt.ylabel('Precision')
        plt.ylim([0.0, 1.05])
        plt.xlim([0.0, 1.0])
        plt.legend([
            'PR curve',
            f'Precision {precision[i + 1]: .2f} corresponding to selected recall threshold',
            f'Recall {recall_for_prec_thres: .2f} corresponding to selected precision threshold'
        ])
        plt.title(f'Precision-Recall curve for Class {class_names[class_i]}')
    return best_recall_threshold, best_precision_threshold


y_pred_test = np.zeros((len(os.listdir(test_imgs_folder)), 4))
for test in ['EfficientNetB2', 'EfficientNetB4']:
    model = get_model(test)

    from keras_radam import RAdam

    for base_layer in model.layers[:-3]:
        base_layer.trainable = False

    model.compile(optimizer=RAdam(warmup_proportion=0.1, min_lr=1e-5),
                  loss='categorical_crossentropy',
                  metrics=['accuracy'])
    history_0 = model.fit_generator(
        generator=data_generator_train,
        validation_data=data_generator_val,
        epochs=20,
        callbacks=[train_metric_callback, val_callback],
        workers=num_cores,
def main(args):
    log_dir = 'logs/000'

    # get class info
    if args.classes_path:
        class_names = get_classes(args.classes_path)
    else:
        class_names = None

    # callbacks for training process
    logging = TensorBoard(log_dir=log_dir,
                          histogram_freq=0,
                          write_graph=False,
                          write_grads=False,
                          write_images=False,
                          update_freq='batch')
    checkpoint = ModelCheckpoint(os.path.join(
        log_dir,
        'ep{epoch:03d}-loss{loss:.3f}-acc{acc:.3f}-val_loss{val_loss:.3f}-val_acc{val_acc:.3f}.h5'
    ),
                                 monitor='val_acc',
                                 mode='max',
                                 verbose=1,
                                 save_weights_only=False,
                                 save_best_only=True,
                                 period=1)
    reduce_lr = ReduceLROnPlateau(monitor='val_acc',
                                  mode='max',
                                  factor=0.5,
                                  patience=10,
                                  verbose=1,
                                  cooldown=0,
                                  min_lr=1e-10)
    early_stopping = EarlyStopping(monitor='val_acc',
                                   mode='max',
                                   min_delta=0,
                                   patience=50,
                                   verbose=1)
    terminate_on_nan = TerminateOnNaN()
    checkpoint_clean = CheckpointCleanCallBack(log_dir, max_keep=5)
    #learn_rates = [0.05, 0.01, 0.005, 0.001, 0.0005]
    #lr_scheduler = LearningRateScheduler(lambda epoch: learn_rates[epoch // 30])

    callbacks = [
        logging, checkpoint, reduce_lr, early_stopping, terminate_on_nan,
        checkpoint_clean
    ]

    # prepare train&val data generator
    train_generator = get_data_generator(args.train_data_path,
                                         args.model_input_shape,
                                         args.batch_size,
                                         class_names,
                                         mode='train')
    val_generator = get_data_generator(args.val_data_path,
                                       args.model_input_shape,
                                       args.batch_size,
                                       class_names,
                                       mode='val')

    # check if classes match on train & val dataset
    assert train_generator.class_indices == val_generator.class_indices, 'class mismatch between train & val dataset'
    if not class_names:
        class_names = list(train_generator.class_indices.keys())
    print('Classes:', class_names)

    # prepare optimizer
    optimizer = get_optimizer(args.optimizer,
                              args.learning_rate,
                              average_type=None,
                              decay_type=None)

    # get train model
    model, backbone_len = get_model(args.model_type, len(class_names),
                                    args.model_input_shape,
                                    args.head_conv_channel, args.weights_path)
    model.summary()

    # Freeze backbone part for transfer learning
    for i in range(backbone_len):
        model.layers[i].trainable = False
    print('Freeze the first {} layers of total {} layers.'.format(
        backbone_len, len(model.layers)))
    model.compile(optimizer=optimizer,
                  loss='categorical_crossentropy',
                  metrics=['accuracy'])

    # Transfer training some epochs with frozen layers first if needed, to get a stable loss.
    initial_epoch = args.init_epoch
    epochs = initial_epoch + args.transfer_epoch
    print("Transfer training stage")
    print(
        'Train on {} samples, val on {} samples, with batch size {}, input_shape {}.'
        .format(train_generator.samples, val_generator.samples,
                args.batch_size, args.model_input_shape))
    model.fit_generator(
        train_generator,
        steps_per_epoch=train_generator.samples // args.batch_size,
        validation_data=val_generator,
        validation_steps=val_generator.samples // args.batch_size,
        epochs=epochs,
        initial_epoch=initial_epoch,
        #verbose=1,
        workers=1,
        use_multiprocessing=False,
        max_queue_size=10,
        callbacks=callbacks)

    # Wait 2 seconds for next stage
    time.sleep(2)

    if args.decay_type:
        # rebuild optimizer to apply learning rate decay, only after
        # unfreeze all layers
        callbacks.remove(reduce_lr)
        steps_per_epoch = max(1, train_generator.samples // args.batch_size)
        decay_steps = steps_per_epoch * (args.total_epoch - args.init_epoch -
                                         args.transfer_epoch)
        optimizer = get_optimizer(args.optimizer,
                                  args.learning_rate,
                                  average_type=None,
                                  decay_type=args.decay_type,
                                  decay_steps=decay_steps)

    # Unfreeze the whole network for further tuning
    # NOTE: more GPU memory is required after unfreezing the body
    for i in range(len(model.layers)):
        model.layers[i].trainable = True
    print("Unfreeze and continue training, to fine-tune.")
    model.compile(optimizer=optimizer,
                  loss='categorical_crossentropy',
                  metrics=['accuracy'])

    model.fit_generator(
        train_generator,
        steps_per_epoch=train_generator.samples // args.batch_size,
        validation_data=val_generator,
        validation_steps=val_generator.samples // args.batch_size,
        epochs=args.total_epoch,
        initial_epoch=epochs,
        #verbose=1,
        workers=1,
        use_multiprocessing=False,
        max_queue_size=10,
        callbacks=callbacks)

    # Finally store model
    model.save(os.path.join(log_dir, 'trained_final.h5'))