예제 #1
0
def train_CNN_bad_data_split(params):

    # Initialize the model
    print('Do transfer learning with existed model trained on ImageNet!\n')
    print('The chosen network is %s !' % params.network)

    model = create_model(params.network, params.gpu)
    trg_size = (224, 224
                )  # most of the imagenet pretrained model has this input size

    # All pre-trained models expect input images normalized in the same way,
    # i.e. mini-batches of 3-channel RGB images of shape (3 x H x W), where H
    # and W are expected to be at least 224. The images have to be loaded in to
    # a range of [0, 1] and then normalized using mean = [0.485, 0.456, 0.406]
    # and std = [0.229, 0.224, 0.225].
    transformations = transforms.Compose([
        MinMaxNormalization(),
        transforms.ToPILImage(),
        transforms.Resize(trg_size),
        transforms.ToTensor()
    ])

    total_time = time()
    init_state = copy.deepcopy(model.state_dict())

    if params.split is None:
        fold_iterator = range(params.n_splits)
    else:
        fold_iterator = [params.split]

    for fi in fold_iterator:
        print("Running for the %d-th fold" % fi)

        training_sub_df, valid_sub_df = load_data(params.tsv_path,
                                                  params.diagnoses,
                                                  fi,
                                                  n_splits=params.n_splits,
                                                  baseline=params.baseline)

        # split the training + validation by slice
        training_df, valid_df = mix_slices(training_sub_df,
                                           valid_sub_df,
                                           mri_plane=params.mri_plane)

        data_train = MRIDataset_slice_mixed(params.caps_directory,
                                            training_df,
                                            transformations=transformations,
                                            mri_plane=params.mri_plane,
                                            prepare_dl=params.prepare_dl)

        data_valid = MRIDataset_slice_mixed(params.caps_directory,
                                            valid_df,
                                            transformations=transformations,
                                            mri_plane=params.mri_plane,
                                            prepare_dl=params.prepare_dl)

        # Use argument load to distinguish training and testing
        train_loader = DataLoader(data_train,
                                  batch_size=params.batch_size,
                                  shuffle=True,
                                  num_workers=params.num_workers,
                                  pin_memory=True)

        valid_loader = DataLoader(data_valid,
                                  batch_size=params.batch_size,
                                  shuffle=False,
                                  num_workers=params.num_workers,
                                  pin_memory=True)

        # chosen optimizer for back-propagation
        optimizer = eval("torch.optim." + params.optimizer)(
            filter(lambda x: x.requires_grad, model.parameters()),
            params.learning_rate,
            weight_decay=params.weight_decay)

        model.load_state_dict(init_state)

        # Binary cross-entropy loss
        loss = torch.nn.CrossEntropyLoss()

        # parameters used in training
        best_accuracy = 0.0
        best_loss_valid = np.inf

        writer_train_batch = SummaryWriter(
            log_dir=(os.path.join(params.output_dir, "log_dir", "fold_" +
                                  str(fi), "train_batch")))
        writer_train_all_data = SummaryWriter(
            log_dir=(os.path.join(params.output_dir, "log_dir", "fold_" +
                                  str(fi), "train_all_data")))

        writer_valid = SummaryWriter(
            log_dir=(os.path.join(params.output_dir, "log_dir", "fold_" +
                                  str(fi), "valid")))

        # initialize the early stopping instance
        early_stopping = EarlyStopping('min',
                                       min_delta=params.tolerance,
                                       patience=params.patience)

        for epoch in range(params.epochs):
            print("At %i-th epoch." % epoch)

            # train the model
            train_df, acc_mean_train, loss_batch_mean_train, global_step \
                = train(
                        model,
                        train_loader,
                        params,
                        loss,
                        optimizer,
                        writer_train_batch,
                        epoch,
                        model_mode='train',
                        selection_threshold=params.selection_threshold
                        )

            # calculate the accuracy with the whole training data to monitor overfitting
            train_all_df, acc_mean_train_all, loss_batch_mean_train_all, _\
                = train(
                        model,
                        train_loader,
                        params.gpu,
                        loss,
                        optimizer,
                        writer_train_all_data,
                        epoch,
                        model_mode='valid',
                        selection_threshold=params.selection_threshold
                        )

            print(
                "For training, subject level balanced accuracy is %f at the end of epoch %d"
                % (acc_mean_train_all, epoch))

            # at then end of each epoch, we validate one time for the model with the validation data
            valid_df, acc_mean_valid, loss_batch_mean_valid, _ \
                = train(
                        model,
                        valid_loader,
                        params.gpu,
                        loss,
                        optimizer,
                        writer_valid,
                        epoch,
                        model_mode='valid',
                        selection_threshold=params.selection_threshold
                        )

            print(
                "For validation, subject level balanced accuracy is %f at the end of epoch %d"
                % (acc_mean_valid, epoch))

            # save the best model based on the best loss and accuracy
            acc_is_best = acc_mean_valid > best_accuracy
            best_accuracy = max(best_accuracy, acc_mean_valid)
            loss_is_best = loss_batch_mean_valid < best_loss_valid
            best_loss_valid = min(loss_batch_mean_valid, best_loss_valid)

            save_checkpoint(
                {
                    'epoch': epoch + 1,
                    'model': model.state_dict(),
                    'loss': loss_batch_mean_valid,
                    'accuracy': acc_mean_valid,
                    'optimizer': optimizer.state_dict(),
                    'global_step': global_step
                }, acc_is_best, loss_is_best,
                os.path.join(params.output_dir, "best_model_dir",
                             "fold_" + str(fi), "CNN"))

            # try early stopping criterion
            if early_stopping.step(
                    loss_batch_mean_valid) or epoch == params.epochs - 1:
                print(
                    "By applying early stopping or at the last epoch defined by user, "
                    "the training is stopped at %d-th epoch" % epoch)

                break

        # Final evaluation for all criteria
        for selection in ['best_loss', 'best_acc']:
            model, best_epoch = load_model(
                model,
                os.path.join(params.output_dir, 'best_model_dir',
                             'fold_%i' % fi, 'CNN', str(selection)),
                gpu=params.gpu,
                filename='model_best.pth.tar')

            train_df, metrics_train = test(model, train_loader, params.gpu,
                                           loss)
            valid_df, metrics_valid = test(model, valid_loader, params.gpu,
                                           loss)

            # write the information of subjects and performances into tsv files.
            slice_level_to_tsvs(params.output_dir,
                                train_df,
                                metrics_train,
                                fi,
                                dataset='train',
                                selection=selection)
            slice_level_to_tsvs(params.output_dir,
                                valid_df,
                                metrics_valid,
                                fi,
                                dataset='validation',
                                selection=selection)

            soft_voting_to_tsvs(params.output_dir,
                                fi,
                                dataset='train',
                                selection=selection,
                                selection_threshold=params.selection_threshold)
            soft_voting_to_tsvs(params.output_dir,
                                fi,
                                dataset='validation',
                                selection=selection,
                                selection_threshold=params.selection_threshold)
            torch.cuda.empty_cache()

    total_time = time() - total_time
    print("Total time of computation: %d s" % total_time)
예제 #2
0
def main(options):
    # Initialize the model
    model = create_model(options.network, options.gpu)
    transformations = transforms.Compose([MinMaxNormalization()])

    # Define loss and optimizer
    loss = torch.nn.CrossEntropyLoss()

    if options.split is None:
        fold_iterator = range(options.n_splits)
    else:
        fold_iterator = [options.split]

    # Loop on folds
    for fi in fold_iterator:
        print("Fold %i" % fi)

        if options.dataset == 'validation':
            _, test_df = load_data(options.diagnosis_tsv_path,
                                   options.diagnoses,
                                   fi,
                                   n_splits=options.n_splits,
                                   baseline=True)
        else:
            test_df = load_data_test(options.diagnosis_tsv_path,
                                     options.diagnoses)

        for n in range(options.num_cnn):

            dataset = MRIDataset_patch(options.caps_directory,
                                       test_df,
                                       options.patch_size,
                                       options.patch_stride,
                                       transformations=transformations,
                                       patch_index=n,
                                       prepare_dl=options.prepare_dl)

            test_loader = DataLoader(dataset,
                                     batch_size=options.batch_size,
                                     shuffle=False,
                                     num_workers=options.num_workers,
                                     pin_memory=True)

            # load the best trained model during the training
            model, best_epoch = load_model(
                model,
                os.path.join(options.output_dir, 'best_model_dir',
                             "fold_%i" % fi, 'cnn-%i' % n, options.selection),
                options.gpu,
                filename='model_best.pth.tar')

            results_df, metrics = test(model, test_loader, options.gpu, loss)
            print("Patch level balanced accuracy is %f" %
                  metrics['balanced_accuracy'])

            # write the test results into the tsv files
            patch_level_to_tsvs(options.output_dir,
                                results_df,
                                metrics,
                                fi,
                                options.selection,
                                dataset=options.dataset,
                                cnn_index=n)

        print("Selection threshold: ", options.selection_threshold)
        soft_voting_to_tsvs(options.output_dir,
                            fi,
                            options.selection,
                            dataset=options.dataset,
                            num_cnn=options.num_cnn,
                            selection_threshold=options.selection_threshold)