Example #1
0
def train_autoencoder(nnet):

    if Cfg.ae_diagnostics:
        nnet.initialize_ae_diagnostics(nnet.ae_n_epochs)

    print("Starting training autoencoder with %s" % nnet.sgd_solver)

    for epoch in range(nnet.ae_n_epochs):

        start_time = time.time()

        if Cfg.ae_lr_drop and (epoch == Cfg.ae_lr_drop_in_epoch):
            # Drop the learning rate in epoch specified in Cfg.ae_lr_drop_after_epoch by factor Cfg.ae_lr_drop_factor
            # Thus, a simple separation of learning into a "region search" and "finetuning" stage.
            lr_new = Cfg.floatX(
                (1.0 / Cfg.ae_lr_drop_factor) * Cfg.learning_rate.get_value())
            print("")
            print(
                "Learning rate drop in epoch {} from {:.6f} to {:.6f}".format(
                    epoch, Cfg.floatX(Cfg.learning_rate.get_value()), lr_new))
            print("")
            Cfg.learning_rate.set_value(lr_new)

        # In each epoch, we do a full pass over the training data:
        l2 = 0
        batches = 0
        train_err = 0
        train_scores = np.empty(nnet.data.n_train)

        for batch in nnet.data.get_epoch_train():
            inputs, _, batch_idx = batch
            start_idx = batch_idx * Cfg.batch_size
            stop_idx = min(nnet.data.n_train, start_idx + Cfg.batch_size)

            err, l2, b_scores = nnet.ae_backprop(inputs)

            train_err += err * inputs.shape[0]
            train_scores[start_idx:stop_idx] = b_scores.flatten()
            batches += 1

        train_err /= nnet.data.n_train

        # save train diagnostics and test performance on val and test data if specified
        if Cfg.ae_diagnostics:
            nnet.save_ae_diagnostics('train', epoch, train_err, train_scores,
                                     l2)

            # Performance on validation and test set
            if nnet.data.n_val > 0:
                val_err = ae_performance(nnet, which_set='val', epoch=epoch)
            test_err = ae_performance(nnet, which_set='test', epoch=epoch)

        # print results for epoch
        print("{:32} {:.5f}".format("Train error:", train_err))
        if Cfg.ae_diagnostics:
            if nnet.data.n_val > 0:
                print("{:32} {:.5f}".format("Val error:", val_err))
            print("{:32} {:.5f}".format("Test error:", test_err))
        print("Epoch {} of {} took {:.3f}s".format(epoch + 1, nnet.ae_n_epochs,
                                                   time.time() - start_time))
        print("")

    # Get final performance in last epoch if no running diagnostics are taken
    if not Cfg.ae_diagnostics:
        nnet.initialize_ae_diagnostics(1)

        # perform forward passes on train, val, and test set
        print("Get final performance...")

        _ = ae_performance(nnet, which_set='train', epoch=0)
        if nnet.data.n_val > 0:
            _ = ae_performance(nnet, which_set='val', epoch=0)
        _ = ae_performance(nnet, which_set='test', epoch=0)

        print("Evaluation completed.")

    # save weights
    if Cfg.pretrain:
        nnet.dump_weights("{}/ae_pretrained_weights.p".format(Cfg.xp_path),
                          pretrain=True)
    else:
        nnet.dump_weights("{}/weights_final.p".format(Cfg.xp_path))

    # if image data plot some random reconstructions
    if nnet.data._X_train.ndim == 4:
        from utils.visualization.mosaic_plot import plot_mosaic
        n_img = 32
        random_idx = np.random.choice(nnet.data.n_train, n_img, replace=False)
        _, _, _, reps = nnet.ae_forward(nnet.data._X_train[random_idx, ...])

        title = str(n_img) + " random autoencoder reconstructions"
        plot_mosaic(reps,
                    title=title,
                    export_pdf=(Cfg.xp_path + "/ae_reconstructions"))

    # plot diagnostics if specified
    if Cfg.ae_diagnostics & Cfg.pretrain:
        from utils.visualization.diagnostics_plot import plot_ae_diagnostics
        from utils.visualization.filters_plot import plot_filters

        # common suffix for plot titles
        str_lr = "lr = " + str(nnet.ae_learning_rate)
        C = int(Cfg.C.get_value())
        if not Cfg.weight_decay:
            C = None
        str_C = "C = " + str(C)
        title_suffix = "(" + nnet.ae_solver + ", " + str_C + ", " + str_lr + ")"

        # plot diagnostics
        plot_ae_diagnostics(nnet, Cfg.xp_path, title_suffix)

        # plot filters
        plot_filters(nnet,
                     Cfg.xp_path,
                     title_suffix,
                     file_prefix="ae_",
                     pretrain=True)
Example #2
0
def main():

    args = parser.parse_args()
    if Cfg.print_options:
        print('Options:')
        for (key, value) in vars(args).iteritems():
            print("{:16}: {}".format(key, value))

    assert os.path.exists(args.xp_dir)

    # default value for basefile: string basis for all exported file names
    if args.out_name:
        base_file = "{}/{}".format(args.xp_dir, args.out_name)
    else:
        base_file = "{}/{}_{}_{}".format(args.xp_dir, args.dataset,
                                         args.solver, args.loss)

    # if pickle file already there, consider run already done
    if not Cfg.only_test and (os.path.exists("{}_weights.p".format(base_file))
                              and os.path.exists(
                                  "{}_results.p".format(base_file))):
        sys.exit()

    # computation device
#    if 'gpu' in args.device:
#        theano.sandbox.cuda.use(args.device)

# set save_at to n_epochs if not provided
    save_at = args.n_epochs if not args.save_at else args.save_at

    save_to = "{}_weights.p".format(base_file)
    weights = "{}/{}.p".format(args.xp_dir,
                               args.in_name) if args.in_name else None
    print(weights)

    # update config data

    # plot parameters
    Cfg.xp_path = args.xp_dir

    # dataset
    Cfg.seed = args.seed
    Cfg.out_frac = args.out_frac
    Cfg.ad_experiment = bool(args.ad_experiment)
    Cfg.weight_dict_init = bool(args.weight_dict_init)
    Cfg.pca = bool(args.pca)
    Cfg.unit_norm_used = args.unit_norm_used
    Cfg.gcn = bool(args.gcn)
    Cfg.zca_whitening = bool(args.zca_whitening)
    Cfg.mnist_val_frac = args.mnist_val_frac
    Cfg.mnist_bias = bool(args.mnist_bias)
    Cfg.mnist_rep_dim = args.mnist_rep_dim
    Cfg.mnist_architecture = args.mnist_architecture
    Cfg.mnist_normal = args.mnist_normal
    Cfg.mnist_outlier = args.mnist_outlier
    Cfg.cifar10_bias = bool(args.cifar10_bias)
    Cfg.cifar10_rep_dim = args.cifar10_rep_dim
    Cfg.cifar10_architecture = args.cifar10_architecture
    Cfg.cifar10_normal = args.cifar10_normal
    Cfg.cifar10_outlier = args.cifar10_outlier
    Cfg.gtsrb_rep_dim = args.gtsrb_rep_dim
    #    Cfg.bdd100k_rep_dim = args.bdd100k_rep_dim
    #    Cfg.bdd100k_architecture = args.bdd100k_architecture
    #    Cfg.bdd100k_val_frac = args.bdd100k_val_frac
    #    Cfg.bdd100k_bias = args.bdd100k_bias
    #    Cfg.bdd100k_n_train = args.bdd100k_n_train
    #    Cfg.bdd100k_n_test = args.bdd100k_n_test

    # neural network
    Cfg.softmax_loss = (args.loss == 'ce')
    Cfg.svdd_loss = (args.loss == 'svdd')
    Cfg.reconstruction_loss = (args.loss == 'autoencoder')
    Cfg.use_batch_norm = bool(args.use_batch_norm)
    Cfg.learning_rate.set_value(args.lr)
    Cfg.lr_decay = bool(args.lr_decay)
    Cfg.lr_decay_after_epoch = args.lr_decay_after_epoch
    Cfg.lr_drop = bool(args.lr_drop)
    Cfg.lr_drop_in_epoch = args.lr_drop_in_epoch
    Cfg.lr_drop_factor = args.lr_drop_factor
    Cfg.momentum.set_value(args.momentum)
    if args.solver == "rmsprop":
        Cfg.rho.set_value(0.9)
    if args.solver == "adadelta":
        Cfg.rho.set_value(0.95)
    Cfg.block_coordinate = bool(args.block_coordinate)
    Cfg.k_update_epochs = args.k_update_epochs
    Cfg.center_fixed = bool(args.center_fixed)
    Cfg.R_update_solver = args.R_update_solver
    Cfg.R_update_scalar_method = args.R_update_scalar_method
    Cfg.R_update_lp_obj = args.R_update_lp_obj
    Cfg.warm_up_n_epochs = args.warm_up_n_epochs
    Cfg.batch_size = args.batch_size
    Cfg.leaky_relu = bool(args.leaky_relu)

    # Pre-training and autoencoder configuration
    Cfg.pretrain = bool(args.pretrain)
    Cfg.ae_loss = args.ae_loss
    Cfg.ae_lr_drop = bool(args.ae_lr_drop)
    Cfg.ae_lr_drop_in_epoch = args.ae_lr_drop_in_epoch
    Cfg.ae_lr_drop_factor = args.ae_lr_drop_factor
    Cfg.ae_weight_decay = bool(args.ae_weight_decay)
    Cfg.ae_C.set_value(args.ae_C)

    # SVDD parameters
    Cfg.nu.set_value(args.nu)
    Cfg.c_mean_init = bool(args.c_mean_init)
    if args.c_mean_init_n_batches == -1:
        Cfg.c_mean_init_n_batches = "all"
    else:
        Cfg.c_mean_init_n_batches = args.c_mean_init_n_batches
    Cfg.hard_margin = bool(args.hard_margin)

    # regularization
    Cfg.weight_decay = bool(args.weight_decay)
    Cfg.C.set_value(args.C)
    Cfg.reconstruction_penalty = bool(args.reconstruction_penalty)
    Cfg.C_rec.set_value(args.C_rec)
    Cfg.dropout = bool(args.dropout)
    Cfg.dropout_architecture = bool(args.dropout_arch)

    # diagnostics
    Cfg.nnet_diagnostics = bool(args.nnet_diagnostics)
    Cfg.e1_diagnostics = bool(args.e1_diagnostics)
    Cfg.ae_diagnostics = bool(args.ae_diagnostics)

    # Check for previous copy of configuration and compare, abort if not equal
    logged_config = args.xp_dir + "/configuration.py"
    current_config = "./config.py"
    if os.path.exists(logged_config):
        print("Comparing logged and current config")


#        assert(files_equal(logged_config,current_config, "dataset ="))
    else:
        copyfile(current_config, logged_config)

    if not Cfg.only_test:  # Run original DSVDD code, both training and testing in one
        # train
        # load from checkpoint if available

        start_new_nnet = False
        if os.path.exists(args.xp_dir + "/ae_pretrained_weights.p"):
            print("Pretrained AE found")
            Cfg.pretrain = False
            nnet = NeuralNet(dataset=args.dataset,
                             use_weights=args.xp_dir +
                             "/ae_pretrained_weights.p",
                             pretrain=False)
        elif Cfg.pretrain:
            if os.path.exists(args.xp_dir + "/ae_checkpoint.p"):
                print("AE checkpoint found, resuming training")
                nnet = NeuralNet(dataset=args.dataset,
                                 use_weights=args.xp_dir + "/ae_checkpoint.p",
                                 pretrain=True)
            else:
                start_new_nnet = True

        elif os.path.exists(args.xp_dir + "/checkpoint.p"):
            print("DSVDD checkpoint found, resuming training")
            nnet = NeuralNet(dataset=args.dataset,
                             use_weights=args.xp_dir + "/checkpoint.p",
                             pretrain=False)
        else:
            start_new_nnet = True

        if start_new_nnet:
            nnet = NeuralNet(dataset=args.dataset,
                             use_weights=weights,
                             pretrain=Cfg.pretrain)

        # pre-train weights via autoencoder, if specified
        if Cfg.pretrain:
            nnet.pretrain(solver="adam",
                          lr=Cfg.pretrain_learning_rate,
                          n_epochs=Cfg.n_pretrain_epochs)

        nnet.train(solver=args.solver,
                   n_epochs=args.n_epochs,
                   save_at=save_at,
                   save_to=save_to)

        # pickle/serialize AD results
        if Cfg.ad_experiment:
            nnet.log_results(filename=Cfg.xp_path + "/AD_results.p")

        # text log
        nnet.log.save_to_file("{}_results.p".format(base_file))  # save log
        log_exp_config(Cfg.xp_path, args.dataset)
        log_NeuralNet(Cfg.xp_path, args.loss, args.solver, args.lr,
                      args.momentum, None, args.n_epochs, args.C, args.C_rec,
                      args.nu, args.dataset)
        if Cfg.ad_experiment:
            log_AD_results(Cfg.xp_path, nnet)

        # plot diagnostics
        if Cfg.nnet_diagnostics:
            # common suffix for plot titles
            str_lr = "lr = " + str(args.lr)
            C = int(args.C)
            if not Cfg.weight_decay:
                C = None
            str_C = "C = " + str(C)
            Cfg.title_suffix = "(" + args.solver + ", " + str_C + ", " + str_lr + ")"

            if args.loss == 'autoencoder':
                plot_ae_diagnostics(nnet, Cfg.xp_path, Cfg.title_suffix)
            else:
                plot_diagnostics(nnet, Cfg.xp_path, Cfg.title_suffix)

        if Cfg.plot_filters:
            print("Plotting filters")
            plot_filters(nnet, Cfg.xp_path, Cfg.title_suffix)

        # If AD experiment, plot most anomalous and most normal
        if Cfg.ad_experiment and Cfg.plot_most_out_and_norm:
            n_img = 32
            plot_outliers_and_most_normal(nnet, n_img, Cfg.xp_path)

    else:  # Load previous network and run only test

        # Load parameters from previous training
        ae_net = NeuralNet(dataset=args.dataset,
                           use_weights=args.xp_dir +
                           "/ae_pretrained_weights.p",
                           pretrain=True)
        ae_net.ae_solver = args.solver.lower()
        #ae_net.ae_learning_rate = args.lr
        #ae_net.ae_n_epochs = args.n_epochs

        # set learning rate
        #lr_tmp = Cfg.learning_rate.get_value()
        #Cfg.learning_rate.set_value(Cfg.floatX(lr))
        ae_net.compile_autoencoder()
        _, recon_errors = ae_performance(ae_net, 'test')
        print("Computed reconstruction errors")

        nnet = NeuralNet(dataset=args.dataset,
                         use_weights="{}/weights_best_ep.p".format(
                             args.xp_dir))
        nnet.solver = args.solver.lower()
        nnet.compile_updates()
        # nnet.evaluate(solver = args.solver)
        # nnet.test_time = time.time() - nnet.clock
        # # pickle/serialize AD results
        # if Cfg.ad_experiment:
        #     nnet.log_results(filename=Cfg.xp_path + "/AD_results.p")

        # TODO retrieve labels and scores from evaluation
        _, _, dsvdd_scores = performance(nnet, 'test')

        labels = nnet.data._y_test

        # # text log
        # nnet.log.save_to_file("{}_results.p".format(base_file))  # save log
        # log_exp_config(Cfg.xp_path, args.dataset)
        # log_NeuralNet(Cfg.xp_path, args.loss, args.solver, args.lr, args.momentum, None, args.n_epochs, args.C, args.C_rec,
        #             args.nu, args.dataset)
        # if Cfg.ad_experiment:
        #     log_AD_results(Cfg.xp_path, nnet)

        # Save scores and labels for comparison with other experiments

        if Cfg.export_results:
            for name in ("", "_recon_err"):
                results_filepath = '/home/exjobb_resultat/data/%s_DSVDD%s.pkl' % (
                    args.dataset, name)
                with open(results_filepath, 'wb') as f:
                    if name is "_recon_err":
                        pickle.dump([recon_errors, labels], f)
                    else:
                        pickle.dump([dsvdd_scores, labels], f)
                print("Saved results to %s" % results_filepath)

                # Update data source dict with experiment name
                common_results_dict = pickle.load(
                    open('/home/exjobb_resultat/data/name_dict.pkl', 'rb'))
                exp_name = args.xp_dir.strip('../log/%s/' % args.dataset)
                common_results_dict[args.dataset]["DSVDD%s" % name] = exp_name
                pickle.dump(
                    common_results_dict,
                    open('/home/exjobb_resultat/data/name_dict.pkl', 'wb'))

        # print test results to console
        print("\nOutliers from %s" % Cfg.test_out_folder)
        print("%d inliers, %d outliers" %
              (Cfg.n_test_in, Cfg.n_test - Cfg.n_test_in))
        print("Test results:\n")
        print("\t\tAUROC\tAUPRC\n")

        # Compute test metrics before printing
        auroc_recon = roc_auc_score(labels, recon_errors)
        auroc_dsvdd = roc_auc_score(labels, dsvdd_scores)
        pr, rc, _ = precision_recall_curve(labels, recon_errors)
        auprc_recon = auc(rc, pr)
        pr, rc, _ = precision_recall_curve(labels, dsvdd_scores)
        auprc_dsvdd = auc(rc, pr)

        print("Recon.err:\t%.4f\t%.4f" % (auroc_recon, auprc_recon))
        print("DSVDD:\t\t%.4f\t%.4f" % (auroc_dsvdd, auprc_dsvdd))