def main(dataset_name, net_name, xp_path, data_path, load_model, objective, nu,
         device, seed, batch_size, n_jobs_dataloader, normal_class, isize,
         rep_dim):

    # Set seed
    if seed != -1:
        random.seed(seed)
        np.random.seed(seed)
        torch.manual_seed(seed)

    # Default device to 'cpu' if cuda is not available
    if not torch.cuda.is_available():
        device = 'cpu'

    # Load data
    dataset = load_dataset(dataset_name, data_path, normal_class, isize)

    # Initialize DeepSVDD model and set neural network \phi
    deep_SVDD = DeepSVDD(objective, nu)
    deep_SVDD.set_network(net_name, rep_dim)
    # If specified, load Deep SVDD model (radius R, center c, network weights, and possibly autoencoder weights)
    deep_SVDD.load_model(model_path=load_model)
    # Test model
    deep_SVDD.test(dataset,
                   device=device,
                   n_jobs_dataloader=n_jobs_dataloader,
                   batch_size=batch_size)
    print(deep_SVDD.results['test_auc'])

    # Save results, model, and configuration
    deep_SVDD.save_results(export_json=xp_path + '/results_test.json')
Ejemplo n.º 2
0
def main(dataset_name, net_name, xp_path, data_path, load_config, load_model, objective, nu, device, seed,
         optimizer_name, lr, n_epochs, lr_milestone, batch_size, weight_decay, pretrain, ae_optimizer_name, ae_lr,
         ae_n_epochs, ae_lr_milestone, ae_batch_size, ae_weight_decay, n_jobs_dataloader, normal_class):
    """
    Deep SVDD, a fully deep method for anomaly detection.

    :arg DATASET_NAME: Name of the dataset to load.
    :arg NET_NAME: Name of the neural network to use.
    :arg XP_PATH: Export path for logging the experiment.
    :arg DATA_PATH: Root path of data.
    """

    # Get configuration
    cfg = Config(locals().copy())

    # Set up logging
    logging.basicConfig(level=logging.INFO)
    logger = logging.getLogger()
    logger.setLevel(logging.INFO)
    formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
    log_file = xp_path + '/log.txt'
    file_handler = logging.FileHandler(log_file)
    file_handler.setLevel(logging.INFO)
    file_handler.setFormatter(formatter)
    logger.addHandler(file_handler)

    # Print arguments
    logger.info('Log file is %s.' % log_file)
    logger.info('Data path is %s.' % data_path)
    logger.info('Export path is %s.' % xp_path)

    logger.info('Dataset: %s' % dataset_name)
    logger.info('Normal class: %d' % normal_class)
    logger.info('Network: %s' % net_name)

    # If specified, load experiment config from JSON-file
    if load_config:
        cfg.load_config(import_json=load_config)
        logger.info('Loaded configuration from %s.' % load_config)

    # Print configuration
    logger.info('Deep SVDD objective: %s' % cfg.settings['objective'])
    logger.info('Nu-paramerter: %.2f' % cfg.settings['nu'])

    # Set seed
    if cfg.settings['seed'] != -1:
        random.seed(cfg.settings['seed'])
        np.random.seed(cfg.settings['seed'])
        torch.manual_seed(cfg.settings['seed'])
        logger.info('Set seed to %d.' % cfg.settings['seed'])

    # Default device to 'cpu' if cuda is not available
    if not torch.cuda.is_available():
        device = 'cpu'
    logger.info('Computation device: %s' % device)
    logger.info('Number of dataloader workers: %d' % n_jobs_dataloader)

    # Load data
    dataset = load_dataset(dataset_name, data_path, normal_class)

    # Initialize DeepSVDD model and set neural network \phi
    deep_SVDD = DeepSVDD(cfg.settings['objective'], cfg.settings['nu'])
    deep_SVDD.set_network(net_name)
    # If specified, load Deep SVDD model (radius R, center c, network weights, and possibly autoencoder weights)
    if load_model:
        deep_SVDD.load_model(model_path=load_model, load_ae=True)
        logger.info('Loading model from %s.' % load_model)

    logger.info('Pretraining: %s' % pretrain)
    if pretrain:
        # Log pretraining details
        logger.info('Pretraining optimizer: %s' % cfg.settings['ae_optimizer_name'])
        logger.info('Pretraining learning rate: %g' % cfg.settings['ae_lr'])
        logger.info('Pretraining epochs: %d' % cfg.settings['ae_n_epochs'])
        logger.info('Pretraining learning rate scheduler milestones: %s' % (cfg.settings['ae_lr_milestone'],))
        logger.info('Pretraining batch size: %d' % cfg.settings['ae_batch_size'])
        logger.info('Pretraining weight decay: %g' % cfg.settings['ae_weight_decay'])

        # Pretrain model on dataset (via autoencoder)
        deep_SVDD.pretrain(dataset,
                           optimizer_name=cfg.settings['ae_optimizer_name'],
                           lr=cfg.settings['ae_lr'],
                           n_epochs=cfg.settings['ae_n_epochs'],
                           lr_milestones=cfg.settings['ae_lr_milestone'],
                           batch_size=cfg.settings['ae_batch_size'],
                           weight_decay=cfg.settings['ae_weight_decay'],
                           device=device,
                           n_jobs_dataloader=n_jobs_dataloader)

    # Log training details
    logger.info('Training optimizer: %s' % cfg.settings['optimizer_name'])
    logger.info('Training learning rate: %g' % cfg.settings['lr'])
    logger.info('Training epochs: %d' % cfg.settings['n_epochs'])
    logger.info('Training learning rate scheduler milestones: %s' % (cfg.settings['lr_milestone'],))
    logger.info('Training batch size: %d' % cfg.settings['batch_size'])
    logger.info('Training weight decay: %g' % cfg.settings['weight_decay'])

    # Train model on dataset
    deep_SVDD.train(dataset,
                    optimizer_name=cfg.settings['optimizer_name'],
                    lr=cfg.settings['lr'],
                    n_epochs=cfg.settings['n_epochs'],
                    lr_milestones=cfg.settings['lr_milestone'],
                    batch_size=cfg.settings['batch_size'],
                    weight_decay=cfg.settings['weight_decay'],
                    device=device,
                    n_jobs_dataloader=n_jobs_dataloader)

    # Test model
    deep_SVDD.test(dataset, device=device, n_jobs_dataloader=n_jobs_dataloader)

    # Plot most anomalous and most normal (within-class) test samples
    indices, labels, scores = zip(*deep_SVDD.results['test_scores'])
    indices, labels, scores = np.array(indices), np.array(labels), np.array(scores)
    idx_sorted = indices[labels == 0][np.argsort(scores[labels == 0])]  # sorted from lowest to highest anomaly score

    if dataset_name in ('mnist', 'cifar10'):

        if dataset_name == 'mnist':
            X_normals = dataset.test_set.test_data[idx_sorted[:32], ...].unsqueeze(1)
            X_outliers = dataset.test_set.test_data[idx_sorted[-32:], ...].unsqueeze(1)

        if dataset_name == 'cifar10':
            X_normals = torch.tensor(np.transpose(dataset.test_set.test_data[idx_sorted[:32], ...], (0, 3, 1, 2)))
            X_outliers = torch.tensor(np.transpose(dataset.test_set.test_data[idx_sorted[-32:], ...], (0, 3, 1, 2)))

        plot_images_grid(X_normals, export_img=xp_path + '/normals', title='Most normal examples', padding=2)
        plot_images_grid(X_outliers, export_img=xp_path + '/outliers', title='Most anomalous examples', padding=2)

    # Save results, model, and configuration
    deep_SVDD.save_results(export_json=xp_path + '/results.json')
    deep_SVDD.save_model(export_model=xp_path + '/model.tar')
    cfg.save_config(export_json=xp_path + '/config.json')
Ejemplo n.º 3
0
def main(dataset_name, net_name, xp_path, data_path, load_config, load_model,
         objective, nu, device, seed, optimizer_name, lr, n_epochs,
         lr_milestone, batch_size, weight_decay, pretrain, ae_optimizer_name,
         ae_lr, ae_n_epochs, ae_lr_milestone, ae_batch_size, ae_weight_decay,
         n_jobs_dataloader, ae_loss_type, ae_only, normal_class, ae_test_only):
    """
    Deep SVDD, a fully deep method for anomaly detection.

    :arg DATASET_NAME: Name of the dataset to load.
    :arg NET_NAME: Name of the neural network to use.
    :arg XP_PATH: Export path for logging the experiment.
    :arg DATA_PATH: Root path of data.
    """

    # Get configuration
    mean = [
        (0.36607818518032215, 0.3528722483374472, 0.3585191239764038),  # 0
        (0.4487305946663354, 0.4487305946663354, 0.4487305946663354),  # 1
        (0.3923340318128373, 0.26295472525674995, 0.22025334692657814),  # 2
        (0.4536255693657713, 0.4682865838881645, 0.4452575836280415),  # 3
        (0.672454086143443, 0.4779993567370712, 0.35007702036667776),  # 4
        (0.5352967021800805, 0.5314880132137422, 0.547828897157147),  # 5
        (0.3267409463643222, 0.41484389522093523, 0.46695618025405883),  # 6
        (0.6926364358307354, 0.662149771557822, 0.6490556404776292),  # 7
        (0.24011281595607017, 0.1769201147939173, 0.17123964257174726),  # 8
        (0.21251877631977975, 0.23440739849813622, 0.2363959074824541),  # 9
        (0.3025230547246622, 0.30300693821061303, 0.32466943588225744),  # 10
        (0.7214971293922232, 0.7214971293922232, 0.7214971293922232),  # 11
        (0.20453672401964704, 0.19061953742573437, 0.1973630989492544),  # 12
        (0.38709726938081024, 0.27680750921869235, 0.24161576675737736),  # 13
        (0.39719792798156195, 0.39719792798156195, 0.39719792798156195),  # 14
    ]
    std = [
        (0.1334089197933497, 0.13091438558839882, 0.11854704285817017),  # 0
        (0.16192189716258867, 0.16192189716258867, 0.16192189716258867),  # 1
        (0.0527090063203568, 0.035927180158353854, 0.026535684323885065),  # 2
        (0.11774565267141425, 0.13039328961987165, 0.12533147519872007),  # 3
        (0.07714836895006975, 0.06278302787607731, 0.04349760909698915),  # 4
        (0.36582285759516936, 0.3661720233895615, 0.34943018535446296),  # 5
        (0.14995070226373788, 0.2117666336616603, 0.23554648659289779),  # 6
        (0.23612927993223184, 0.25644744015075704, 0.25718179933681784),  # 7
        (0.168789697373752, 0.07563237349131141, 0.043146545992581754),  # 8
        (0.15779873915363898, 0.18099161937329614, 0.15159372072430388),  # 9
        (0.15720102988319967, 0.1803989691876269, 0.15113407058442763),  # 10
        (0.13265686578689692, 0.13265686578689692, 0.13265686578689692),  # 11
        (0.2316392849251032, 0.21810285502082638, 0.19743939091294657),  # 12
        (0.20497542590257026, 0.14190994609091834, 0.11531548927488476),  # 13
        (0.3185215984033291, 0.3185215984033291, 0.3185215984033291),  # 14
    ]

    cfg = Config(locals().copy())

    # Set up logging
    logging.basicConfig(level=logging.INFO)
    logger = logging.getLogger()
    logger.setLevel(logging.INFO)
    formatter = logging.Formatter(
        '%(asctime)s - %(name)s - %(levelname)s - %(message)s')

    xp_path = xp_path + '/'

    xp_path = xp_path + str(normal_class)
    log_file = xp_path + '/log.txt'
    file_handler = logging.FileHandler(log_file)
    file_handler.setLevel(logging.INFO)
    file_handler.setFormatter(formatter)
    logger.addHandler(file_handler)

    # Print arguments
    logger.info('Log file is %s.' % log_file)
    logger.info('Data path is %s.' % data_path)
    logger.info('Export path is %s.' % xp_path)
    logger.info('Dataset: %s' % dataset_name)
    logger.info('Normal class: %s' % normal_class)
    logger.info('Network: %s' % net_name)

    # If specified, load experiment config from JSON-file
    if load_config:
        cfg.load_config(import_json=load_config)
        logger.info('Loaded configuration from %s.' % load_config)

    # Print configuration
    logger.info('Deep SVDD objective: %s' % cfg.settings['objective'])
    logger.info('Nu-paramerter: %.2f' % cfg.settings['nu'])

    # Set seed
    if cfg.settings['seed'] != -1:
        random.seed(cfg.settings['seed'])
        np.random.seed(cfg.settings['seed'])
        torch.manual_seed(cfg.settings['seed'])
        logger.info('Set seed to %d.' % cfg.settings['seed'])

    # Default device to 'cpu' if cuda is not available
    if not torch.cuda.is_available():
        device = 'cpu'
    logger.info('Computation device: %s' % device)
    logger.info('Number of dataloader workers: %d' % n_jobs_dataloader)

    # Load data
    dataset = load_dataset(dataset_name, data_path, normal_class)

    # Initialize DeepSVDD model and set neural network \phi
    deep_SVDD = DeepSVDD(cfg.settings['objective'], cfg.settings['nu'])
    deep_SVDD.set_network(net_name)
    # If specified, load Deep SVDD model (radius R, center c, network weights, and possibly autoencoder weights)
    if load_model:
        deep_SVDD.load_model(model_path=load_model, load_ae=True)
        logger.info('Loading model from %s.' % load_model)

    logger.info('Pretraining: %s' % pretrain)
    if pretrain:
        # Log pretraining details
        logger.info('Pretraining optimizer: %s' %
                    cfg.settings['ae_optimizer_name'])
        logger.info('Pretraining learning rate: %g' % cfg.settings['ae_lr'])
        logger.info('Pretraining epochs: %d' % cfg.settings['ae_n_epochs'])
        logger.info('Pretraining learning rate scheduler milestones: %s' %
                    (cfg.settings['ae_lr_milestone'], ))
        logger.info('Pretraining batch size: %d' %
                    cfg.settings['ae_batch_size'])
        logger.info('Pretraining weight decay: %g' %
                    cfg.settings['ae_weight_decay'])

        # Pretrain model on dataset (via autoencoder)
        model_save_path = './models/' + dataset_name + '/' + str(
            normal_class) + '_' + str(
                ae_n_epochs) + '_' + ae_loss_type + '.pth'

        if ae_test_only == False:
            deep_SVDD.pretrain(
                dataset,
                optimizer_name=cfg.settings['ae_optimizer_name'],
                lr=cfg.settings['ae_lr'],
                n_epochs=cfg.settings['ae_n_epochs'],
                lr_milestones=cfg.settings['ae_lr_milestone'],
                batch_size=cfg.settings['ae_batch_size'],
                weight_decay=cfg.settings['ae_weight_decay'],
                device=device,
                n_jobs_dataloader=n_jobs_dataloader,
                dataset_name=dataset_name,
                ae_loss_type=ae_loss_type,
                ae_only=ae_only,
                model_save_path=model_save_path)
        else:
            deep_SVDD.load_test(
                dataset,
                optimizer_name=cfg.settings['ae_optimizer_name'],
                lr=cfg.settings['ae_lr'],
                n_epochs=cfg.settings['ae_n_epochs'],
                lr_milestones=cfg.settings['ae_lr_milestone'],
                batch_size=cfg.settings['ae_batch_size'],
                weight_decay=cfg.settings['ae_weight_decay'],
                device=device,
                n_jobs_dataloader=n_jobs_dataloader,
                dataset_name=dataset_name,
                ae_loss_type=ae_loss_type,
                ae_only=ae_only,
                model_save_path=model_save_path)

        # Plot most anomalous and most normal (within-class) test samples
        exit(0)
        indices, labels, scores = zip(*deep_SVDD.results['ae_test_scores'])
        indices, labels, scores = np.array(indices), np.array(
            labels), np.array(scores)
        idx_sorted = indices[labels == 0][np.argsort(scores[
            labels == 0])]  # sorted from lowest to highest anomaly score

        if dataset_name in ('mnist', 'cifar10', 'object', 'texture'):

            if dataset_name == 'mnist':
                X_normals = dataset.test_set.test_data[idx_sorted[:32],
                                                       ...].unsqueeze(1)
                X_outliers = dataset.test_set.test_data[idx_sorted[-32:],
                                                        ...].unsqueeze(1)

            if dataset_name == 'cifar10':
                X_normals = torch.tensor(
                    np.transpose(
                        dataset.test_set.test_data[idx_sorted[:32], ...],
                        (0, 3, 1, 2)))
                X_outliers = torch.tensor(
                    np.transpose(
                        dataset.test_set.test_data[idx_sorted[-32:], ...],
                        (0, 3, 1, 2)))

            if dataset_name == 'object':
                # 22 3 256 256
                X_normals = torch.tensor(dataset.test_data[idx_sorted[:32],
                                                           ...])
                X_outliers = torch.tensor(dataset.test_data[idx_sorted[-32:],
                                                            ...])

                for i in range(3):
                    X_normals[:, i, :, :] *= std[normal_class][i]
                    X_normals[:, i, :, :] += mean[normal_class][i]
                    X_outliers[:, i, :, :] *= std[normal_class][i]
                    X_outliers[:, i, :, :] += mean[normal_class][i]

            #plot_images_grid(X_normals, export_img=xp_path + '/AE_normals', title='Most normal examples', padding=2)
            #plot_images_grid(X_outliers, export_img=xp_path + '/AE_outliers', title='Most anomalous examples', padding=2)
            if ae_only:
                exit(0)
    # Log training details
    logger.info('Training optimizer: %s' % cfg.settings['optimizer_name'])
    logger.info('Training learning rate: %g' % cfg.settings['lr'])
    logger.info('Training epochs: %d' % cfg.settings['n_epochs'])
    logger.info('Training learning rate scheduler milestones: %s' %
                (cfg.settings['lr_milestone'], ))
    logger.info('Training batch size: %d' % cfg.settings['batch_size'])
    logger.info('Training weight decay: %g' % cfg.settings['weight_decay'])

    # Train model on dataset
    deep_SVDD.train(dataset,
                    optimizer_name=cfg.settings['optimizer_name'],
                    lr=cfg.settings['lr'],
                    n_epochs=cfg.settings['n_epochs'],
                    lr_milestones=cfg.settings['lr_milestone'],
                    batch_size=cfg.settings['batch_size'],
                    weight_decay=cfg.settings['weight_decay'],
                    device=device,
                    n_jobs_dataloader=n_jobs_dataloader,
                    dataset_name=dataset_name)

    # Test model
    deep_SVDD.test(dataset, device=device, n_jobs_dataloader=n_jobs_dataloader)

    # Plot most anomalous and most normal (within-class) test samples
    indices, labels, scores, _, _ = zip(*deep_SVDD.results['test_scores'])
    indices, labels, scores = np.array(indices), np.array(labels), np.array(
        scores)
    idx_sorted = indices[labels == 0][np.argsort(
        scores[labels == 0])]  # sorted from lowest to highest anomaly score

    if dataset_name in ('mnist', 'cifar10', 'object', 'texture'):

        if dataset_name == 'mnist':
            X_normals = dataset.test_set.test_data[idx_sorted[:32],
                                                   ...].unsqueeze(1)
            X_outliers = dataset.test_set.test_data[idx_sorted[-32:],
                                                    ...].unsqueeze(1)

        if dataset_name == 'cifar10':
            X_normals = torch.tensor(
                np.transpose(dataset.test_set.test_data[idx_sorted[:32], ...],
                             (0, 3, 1, 2)))
            X_outliers = torch.tensor(
                np.transpose(dataset.test_set.test_data[idx_sorted[-32:], ...],
                             (0, 3, 1, 2)))

        if dataset_name == 'object':
            # 22 3 256 256
            X_normals = torch.tensor(dataset.test_data[idx_sorted[:32], ...])
            X_outliers = torch.tensor(dataset.test_data[idx_sorted[-32:], ...])
            for i in range(3):
                X_normals[:, i, :, :] *= std[normal_class][i]
                X_normals[:, i, :, :] += mean[normal_class][i]
                X_outliers[:, i, :, :] *= std[normal_class][i]
                X_outliers[:, i, :, :] += mean[normal_class][i]

        plot_images_grid(X_normals,
                         export_img=xp_path + '/normals',
                         title='Most normal examples',
                         padding=2)
        plot_images_grid(X_outliers,
                         export_img=xp_path + '/outliers',
                         title='Most anomalous examples',
                         padding=2)
Ejemplo n.º 4
0
def main(dataset_name, net_name, xp_path, data_path, load_config, load_model, load_ae_model, objective, nu, number_clusters, device, seed,
         optimizer_name, lr, n_epochs, lr_milestone, batch_size, weight_decay, pretrain, ae_optimizer_name, ae_lr,
         ae_n_epochs, ae_lr_milestone, ae_batch_size, ae_weight_decay, n_jobs_dataloader, normal_class):
    """
    Deep SVDD, a fully deep method for anomaly detection.

    :arg DATASET_NAME: Name of the dataset to load.
    :arg NET_NAME: Name of the neural network to use.
    :arg XP_PATH: Export path for logging the experiment.
    :arg DATA_PATH: Root path of data.
    """

    # Get configuration
    cfg = Config(locals().copy())

    # Set up logging
    logging.basicConfig(level=logging.INFO)
    logger = logging.getLogger()
    logger.setLevel(logging.INFO)
    formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
    log_file = xp_path + '/log.txt'
    file_handler = logging.FileHandler(log_file)
    file_handler.setLevel(logging.INFO)
    file_handler.setFormatter(formatter)
    logger.addHandler(file_handler)

    # If specified, load experiment config from JSON-file
    if load_config:
        cfg.load_config(import_json=load_config)
        logger.info('Loaded configuration from %s.' % load_config)
    
    # Print configuration
    logger.info('Deep SVDD objective: %s' % cfg.settings['objective'])
    logger.info('Nu-paramerter: %.2f' % cfg.settings['nu'])
    logger.info('Number of hyperphere centers: %d' % cfg.settings['number_clusters'])
    
    # Default device to 'cpu' if cuda is not available
    if not torch.cuda.is_available():
        device = 'cpu'
    logger.info('Computation device: %s' % device)
    logger.info('Number of dataloader workers: %d' % n_jobs_dataloader)

    # Load data
    dataset = load_dataset(dataset_name, data_path, normal_class)

    # Initialize DeepSVDD model and set neural network \phi
    deep_SVDD = DeepSVDD(xp_path, cfg.settings['objective'], cfg.settings['nu'], cfg.settings['number_clusters'])
    deep_SVDD.set_network(net_name)
    # If specified, load Deep SVDD model (radius R, center c, network weights, and possibly autoencoder weights)
    if load_model:
        deep_SVDD.load_model(model_path=load_model, load_ae=False)
        logger.info('Loading model from %s.' % load_model)

    # import pdb; pdb.set_trace()
    # Test model
    deep_SVDD.test(dataset, device=device, n_jobs_dataloader=n_jobs_dataloader)

    # import pdb; pdb.set_trace()

    # Plot most anomalous and most normal (within-class) test samples
    indices, labels, scores = zip(*deep_SVDD.results['test_scores'])
    indices, labels, scores = np.array(indices), np.array(labels), np.array(scores)
    idx_sorted = indices[labels == 0][np.argsort(scores[labels == 0])]  # sorted from lowest to highest anomaly score

    ### NEW ### 
    # idx_sorted_normal = indices[labels == 0][np.argsort(scores[labels == 0])]  # normal images sorted from lowest to highest anomaly score
    # idx_sorted_outlier = indices[labels == 1][np.argsort(scores[labels == 1])]  # anomaly images sorted from lowest to highest anomaly score

    # Lowest to highest uncertainty scores
    idx_sorted_all = indices[np.argsort(scores)]
    labels_sorted_all = labels[np.argsort(scores)]
    scores_sorted_all = np.sort(scores)
    for i in range(128):
        idx = idx_sorted_all[i]   
        X = dataset.test_set[idx][0].unsqueeze(1)
        plot_images_labels(X, label = labels_sorted_all[i], export_img=xp_path + '/images/img_'+str(i), title='Score = {:4.2f}'.format(scores_sorted_all[i]), padding=2)
    # Assemble Gallery
    folder = xp_path + '/images'
    image_paths = [os.path.join(folder, f) 
                for f in os.listdir(folder) if f.endswith('.png')]

    # Random selection of images
    image_array = random.sample(image_paths, k=128)

    # Create and save image grid
    image = concat_images(image_array, (100, 100), (16, 8))
    image.save(os.path.join(folder,'gallery_128.png'), 'PNG')

    # for i in range(32):
    #     idx = idx_sorted_all[i]   
    #     X = dataset.test_set[idx][0].unsqueeze(1)
    #     plot_images_labels(X, label = labels_sorted_all[i], export_img=xp_path + '/simple_img_'+str(i), title='Simplest Example: Score = {:4.2f}'.format(scores_sorted_all[i]), padding=2)

    # # Highest to lowest uncertainty scores
    # idx_sorted_all = np.flip(idx_sorted_all)
    # labels_sorted_all = np.flip(labels_sorted_all)
    # scores_sorted_all = np.flip(scores_sorted_all)

    # for i in range(32):
    #     idx = idx_sorted_all[i]
    #     X = dataset.test_set[idx][0].unsqueeze(1)
    #     plot_images_labels(X, label = labels_sorted_all[i], export_img=xp_path + '/difficult_img_'+str(i), title='Difficult Example: Score = {:4.2f}'.format(scores_sorted_all[i]), padding=2)

    import pdb; pdb.set_trace()

    # X_n = [dataset.test_set[i][0] for i in idx_sorted_normal[-8:]]
    # X_n = torch.cat(X_n).unsqueeze(1)
    # X_o = [dataset.test_set[i][0] for i in idx_sorted_outlier[-8:]]
    # X_o = torch.cat(X_o).unsqueeze(1)

    # # import pdb; pdb.set_trace()
    # plot_images_labels(X_n, label = 0, export_img=xp_path + '/normals', title='Hardest normal examples', padding=2)
    # # import pdb; pdb.set_trace()
    # plot_images_labels(X_o, label = 1, export_img=xp_path + '/outliers', title='Hardest outlier examples', padding=2)
    ### - ###

    # From clean images, extract the ones model predicts as normal with highest confidence
    X_normals = [dataset.test_set[i][0] for i in idx_sorted[:64]]
    X_normals = torch.cat(X_normals).unsqueeze(1)

    # From clean images, extract the ones model predicts as normal with lowest confidence
    X_outliers = [dataset.test_set[i][0] for i in idx_sorted[-64:]]
    X_outliers = torch.cat(X_outliers).unsqueeze(1)

    plot_images_grid(X_normals, export_img=xp_path + '/normals_64', title='Most normal examples', padding=2)
    plot_images_grid(X_outliers, export_img=xp_path + '/outliers_64', title='Most anomalous examples', padding=2)
Ejemplo n.º 5
0
def main(dataset_name, net_name, xp_path, data_path, load_config, load_model,
         load_ae_model, objective, nu, number_clusters, device, seed,
         optimizer_name, lr, n_epochs, lr_milestone, batch_size, weight_decay,
         pretrain, ae_optimizer_name, ae_lr, ae_n_epochs, ae_lr_milestone,
         ae_batch_size, ae_weight_decay, n_jobs_dataloader, normal_class):
    """
    Deep SVDD, a fully deep method for anomaly detection.

    :arg DATASET_NAME: Name of the dataset to load.
    :arg NET_NAME: Name of the neural network to use.
    :arg XP_PATH: Export path for logging the experiment.
    :arg DATA_PATH: Root path of data.
    """

    # Get configuration
    cfg = Config(locals().copy())

    # Set up logging
    logging.basicConfig(level=logging.INFO)
    logger = logging.getLogger()
    logger.setLevel(logging.INFO)
    formatter = logging.Formatter(
        '%(asctime)s - %(name)s - %(levelname)s - %(message)s')
    log_file = xp_path + '/log.txt'
    file_handler = logging.FileHandler(log_file)
    file_handler.setLevel(logging.INFO)
    file_handler.setFormatter(formatter)
    logger.addHandler(file_handler)

    # Print arguments
    logger.info('Log file is %s.' % log_file)
    logger.info('Data path is %s.' % data_path)
    logger.info('Export path is %s.' % xp_path)

    logger.info('Dataset: %s' % dataset_name)
    logger.info('Normal class: %d' % normal_class)
    logger.info('Network: %s' % net_name)

    # If specified, load experiment config from JSON-file
    if load_config:
        cfg.load_config(import_json=load_config)
        logger.info('Loaded configuration from %s.' % load_config)

    # Print configuration
    logger.info('Deep SVDD objective: %s' % cfg.settings['objective'])
    logger.info('Nu-paramerter: %.2f' % cfg.settings['nu'])
    logger.info('Number of hyperphere centers: %d' %
                cfg.settings['number_clusters'])

    # Set seed
    if cfg.settings['seed'] != -1:
        random.seed(cfg.settings['seed'])
        np.random.seed(cfg.settings['seed'])
        torch.manual_seed(cfg.settings['seed'])
        logger.info('Set seed to %d.' % cfg.settings['seed'])

    # Default device to 'cpu' if cuda is not available
    if not torch.cuda.is_available():
        device = 'cpu'
    logger.info('Computation device: %s' % device)
    logger.info('Number of dataloader workers: %d' % n_jobs_dataloader)

    # Load data
    dataset = load_dataset(dataset_name, data_path, normal_class)

    # Initialize DeepSVDD model and set neural network \phi
    deep_SVDD = DeepSVDD(xp_path, cfg.settings['objective'],
                         cfg.settings['nu'], cfg.settings['number_clusters'])
    deep_SVDD.set_network(net_name)
    # If specified, load Deep SVDD model (radius R, center c, network weights, and possibly autoencoder weights)
    if load_model:
        deep_SVDD.load_model(model_path=load_model, load_ae=True)
        logger.info('Loading model from %s.' % load_model)
    # If specified, load pretrained AE model (autoencoder weights)
    if load_ae_model:
        deep_SVDD.load_pretrained_AE_model(model_path=load_ae_model)
        logger.info('Loading pretrained AE model from %s.' % load_ae_model)

    logger.info('Pretraining: %s' % pretrain)
    if pretrain:
        # Log pretraining details
        logger.info('Pretraining optimizer: %s' %
                    cfg.settings['ae_optimizer_name'])
        logger.info('Pretraining learning rate: %g' % cfg.settings['ae_lr'])
        logger.info('Pretraining epochs: %d' % cfg.settings['ae_n_epochs'])
        logger.info('Pretraining learning rate scheduler milestones: %s' %
                    (cfg.settings['ae_lr_milestone'], ))
        logger.info('Pretraining batch size: %d' %
                    cfg.settings['ae_batch_size'])
        logger.info('Pretraining weight decay: %g' %
                    cfg.settings['ae_weight_decay'])

        # Pretrain model on dataset (via autoencoder)
        deep_SVDD.pretrain(dataset,
                           optimizer_name=cfg.settings['ae_optimizer_name'],
                           lr=cfg.settings['ae_lr'],
                           n_epochs=cfg.settings['ae_n_epochs'],
                           lr_milestones=cfg.settings['ae_lr_milestone'],
                           batch_size=cfg.settings['ae_batch_size'],
                           weight_decay=cfg.settings['ae_weight_decay'],
                           device=device,
                           n_jobs_dataloader=n_jobs_dataloader)

    # Log training details
    logger.info('Training optimizer: %s' % cfg.settings['optimizer_name'])
    logger.info('Training learning rate: %g' % cfg.settings['lr'])
    logger.info('Training epochs: %d' % cfg.settings['n_epochs'])
    logger.info('Training learning rate scheduler milestones: %s' %
                (cfg.settings['lr_milestone'], ))
    logger.info('Training batch size: %d' % cfg.settings['batch_size'])
    logger.info('Training weight decay: %g' % cfg.settings['weight_decay'])

    # Train model on dataset
    deep_SVDD.train(dataset,
                    optimizer_name=cfg.settings['optimizer_name'],
                    lr=cfg.settings['lr'],
                    n_epochs=cfg.settings['n_epochs'],
                    lr_milestones=cfg.settings['lr_milestone'],
                    batch_size=cfg.settings['batch_size'],
                    weight_decay=cfg.settings['weight_decay'],
                    device=device,
                    n_jobs_dataloader=n_jobs_dataloader)

    # Test model
    deep_SVDD.test(dataset, device=device, n_jobs_dataloader=n_jobs_dataloader)

    # Save results, model, and configuration
    deep_SVDD.save_results(export_json=xp_path + '/results.json')
    if pretrain:
        deep_SVDD.save_model(export_model=xp_path + '/model.tar')
    else:
        deep_SVDD.save_model(export_model=xp_path + '/model.tar',
                             save_ae=False)
    cfg.save_config(export_json=xp_path + '/config.json')
    # Save cluster centers
    np.save(os.path.join(xp_path, 'centers.npy'), np.asarray(deep_SVDD.c))

    # Plot most anomalous and most normal (within-class) test samples
    indices, labels, scores = zip(*deep_SVDD.results['test_scores'])
    indices, labels, scores = np.array(indices), np.array(labels), np.array(
        scores)
    idx_sorted = indices[labels == 0][np.argsort(
        scores[labels == 0])]  # sorted from lowest to highest anomaly score

    if dataset_name in ('mnist', 'cifar10', 'cycif'):

        if dataset_name == 'mnist':
            X_normals = dataset.test_set.test_data[idx_sorted[:32],
                                                   ...].unsqueeze(1)
            X_outliers = dataset.test_set.test_data[idx_sorted[-32:],
                                                    ...].unsqueeze(1)

            plot_images_grid(X_normals,
                             export_img=xp_path + '/normals',
                             title='Most normal examples',
                             padding=2)
            plot_images_grid(X_outliers,
                             export_img=xp_path + '/outliers',
                             title='Most anomalous examples',
                             padding=2)

        if dataset_name == 'cifar10':
            X_normals = torch.tensor(
                np.transpose(dataset.test_set.test_data[idx_sorted[:32], ...],
                             (0, 3, 1, 2)))
            X_outliers = torch.tensor(
                np.transpose(dataset.test_set.test_data[idx_sorted[-32:], ...],
                             (0, 3, 1, 2)))

            plot_images_grid(X_normals,
                             export_img=xp_path + '/normals',
                             title='Most normal examples',
                             padding=2)
            plot_images_grid(X_outliers,
                             export_img=xp_path + '/outliers',
                             title='Most anomalous examples',
                             padding=2)

        if dataset_name == 'cycif':
            # # Lowest to highest uncertainty scores
            # idx_sorted_all = indices[np.argsort(scores)]
            # labels_sorted_all = labels[np.argsort(scores)]
            # scores_sorted_all = np.sort(scores)

            # for i in range(32):
            #     idx = idx_sorted_all[i]
            #     X = dataset.test_set[idx][0].unsqueeze(1)
            #     # From test images, extract the ones model predicts as normal with highest confidence (better)
            #     plot_images_labels(X, label = labels_sorted_all[i], export_img=xp_path + '/images/simple_img_'+str(i), title='Simplest Example: Score = {:4.2f}'.format(scores_sorted_all[i]), padding=2)

            # # Highest to lowest uncertainty scores
            # idx_sorted_all = np.flip(idx_sorted_all)
            # labels_sorted_all = np.flip(labels_sorted_all)
            # scores_sorted_all = np.flip(scores_sorted_all)

            # for i in range(32):
            #     idx = idx_sorted_all[i]
            #     X = dataset.test_set[idx][0].unsqueeze(1)
            #     # From test images, extract the ones model predicts as normal with lowest confidence (worse)
            #     plot_images_labels(X, label = labels_sorted_all[i], export_img=xp_path + '/images/difficult_img_'+str(i), title='Difficult Example: Score = {:4.2f}'.format(scores_sorted_all[i]), padding=2)

            # Lowest to highest uncertainty scores
            idx_sorted_all = indices[np.argsort(scores)]
            labels_sorted_all = labels[np.argsort(scores)]
            scores_sorted_all = np.sort(scores)
            for i in range(128):
                idx = idx_sorted_all[i]
                X = dataset.test_set[idx][0].unsqueeze(1)
                plot_images_labels(
                    X,
                    label=labels_sorted_all[i],
                    export_img=xp_path + '/images/img_' + str(i),
                    title='Score = {:4.2f}'.format(scores_sorted_all[i]),
                    padding=2)
            # Assemble Gallery
            folder = xp_path + '/images'
            image_paths = [
                os.path.join(folder, f) for f in os.listdir(folder)
                if f.endswith('.png')
            ]

            # Random selection of images
            image_array = random.sample(image_paths, k=128)

            # Create and save image grid
            image = concat_images(image_array, (100, 100), (16, 8))
            image.save(os.path.join(folder, 'gallery_128.png'), 'PNG')
Ejemplo n.º 6
0
def main(dataset_name, net_name, xp_path, data_path, load_config, load_model,
         objective, nu, device, seed, optimizer_name, lr, n_epochs,
         lr_milestone, batch_size, weight_decay, pretrain, ae_optimizer_name,
         ae_lr, ae_n_epochs, ae_lr_milestone, ae_batch_size, ae_weight_decay,
         n_jobs_dataloader, normal_class, save_points_outside_r):
    """
    Deep SVDD, a fully deep method for anomaly detection.

    :arg DATASET_NAME: Name of the dataset to load.
    :arg NET_NAME: Name of the neural network to use.
    :arg XP_PATH: Export path for logging the experiment.
    :arg DATA_PATH: Root path of data.
    """

    # Get configuration
    cfg = Config(locals().copy())

    # Set up logging
    logging.basicConfig(level=logging.INFO)
    logger = logging.getLogger()
    logger.setLevel(logging.INFO)
    formatter = logging.Formatter(
        '%(asctime)s - %(name)s - %(levelname)s - %(message)s')
    log_file = xp_path + '/log.txt'
    file_handler = logging.FileHandler(log_file)
    file_handler.setLevel(logging.INFO)
    file_handler.setFormatter(formatter)
    logger.addHandler(file_handler)

    # Print arguments
    logger.info('Log file is %s.' % log_file)
    logger.info('Data path is %s.' % data_path)
    logger.info('Export path is %s.' % xp_path)

    logger.info('Dataset: %s' % dataset_name)
    logger.info('Normal class: %d' % normal_class)
    logger.info('Network: %s' % net_name)

    # If specified, load experiment config from JSON-file
    if load_config:
        cfg.load_config(import_json=load_config)
        logger.info('Loaded configuration from %s.' % load_config)

    # Print configuration
    logger.info('Deep SVDD objective: %s' % cfg.settings['objective'])
    logger.info('Nu-paramerter: %.2f' % cfg.settings['nu'])

    # Set seed
    if cfg.settings['seed'] != -1:
        random.seed(cfg.settings['seed'])
        np.random.seed(cfg.settings['seed'])
        torch.manual_seed(cfg.settings['seed'])
        logger.info('Set seed to %d.' % cfg.settings['seed'])

    # Default device to 'cpu' if cuda is not available
    if not torch.cuda.is_available():
        device = 'cpu'
    logger.info('Computation device: %s' % device)
    logger.info('Number of dataloader workers: %d' % n_jobs_dataloader)

    # Load data
    dataset = load_dataset(dataset_name, data_path, normal_class)

    # Initialize DeepSVDD model and set neural network \phi
    deep_SVDD = DeepSVDD(cfg.settings['objective'], cfg.settings['nu'])
    deep_SVDD.set_network(net_name)
    # If specified, load Deep SVDD model (radius R, center c, network weights, and possibly autoencoder weights)
    if load_model:
        deep_SVDD.load_model(model_path=load_model, load_ae=False)
        logger.info('Loading model from %s.' % load_model)

    logger.info('Pretraining: %s' % pretrain)
    if pretrain:
        # Log pretraining details
        logger.info('Pretraining optimizer: %s' %
                    cfg.settings['ae_optimizer_name'])
        logger.info('Pretraining learning rate: %g' % cfg.settings['ae_lr'])
        logger.info('Pretraining epochs: %d' % cfg.settings['ae_n_epochs'])
        logger.info('Pretraining learning rate scheduler milestones: %s' %
                    (cfg.settings['ae_lr_milestone'], ))
        logger.info('Pretraining batch size: %d' %
                    cfg.settings['ae_batch_size'])
        logger.info('Pretraining weight decay: %g' %
                    cfg.settings['ae_weight_decay'])

        # Pretrain model on dataset (via autoencoder)
        deep_SVDD.pretrain(dataset,
                           optimizer_name=cfg.settings['ae_optimizer_name'],
                           lr=cfg.settings['ae_lr'],
                           n_epochs=cfg.settings['ae_n_epochs'],
                           lr_milestones=cfg.settings['ae_lr_milestone'],
                           batch_size=cfg.settings['ae_batch_size'],
                           weight_decay=cfg.settings['ae_weight_decay'],
                           device=device,
                           n_jobs_dataloader=n_jobs_dataloader)

    # Log training details
    logger.info('Training optimizer: %s' % cfg.settings['optimizer_name'])
    logger.info('Training learning rate: %g' % cfg.settings['lr'])
    logger.info('Training epochs: %d' % cfg.settings['n_epochs'])
    logger.info('Training learning rate scheduler milestones: %s' %
                (cfg.settings['lr_milestone'], ))
    logger.info('Training batch size: %d' % cfg.settings['batch_size'])
    logger.info('Training weight decay: %g' % cfg.settings['weight_decay'])

    # Train model on dataset
    deep_SVDD.train(dataset,
                    optimizer_name=cfg.settings['optimizer_name'],
                    lr=cfg.settings['lr'],
                    n_epochs=cfg.settings['n_epochs'],
                    lr_milestones=cfg.settings['lr_milestone'],
                    batch_size=cfg.settings['batch_size'],
                    weight_decay=cfg.settings['weight_decay'],
                    device=device,
                    n_jobs_dataloader=n_jobs_dataloader)

    if save_points_outside_r:
        logger.info('Saving points outside of r')
        deep_SVDD.savePointsOutsideR(dataset,
                                     device=device,
                                     n_jobs_dataloader=n_jobs_dataloader)

    # Test model
    deep_SVDD.test(dataset, device=device, n_jobs_dataloader=n_jobs_dataloader)

    deep_SVDD.save_results(export_json=xp_path + '/results.json')
    deep_SVDD.save_model(export_model=xp_path + '/model.tar')
    cfg.save_config(export_json=xp_path + '/config.json')
Ejemplo n.º 7
0
def main(dataset_name, net_name, xp_path, data_path, load_config, load_model,
         objective, nu, device, seed, optimizer_name, lr, n_epochs,
         lr_milestone, batch_size, weight_decay, pretrain, ae_optimizer_name,
         ae_lr, ae_n_epochs, ae_lr_milestone, ae_batch_size, ae_weight_decay,
         n_jobs_dataloader, normal_class, img_name):
    """
    Deep SVDD, a fully deep method for anomaly detection.

    :arg DATASET_NAME: Name of the dataset to load.
    :arg NET_NAME: Name of the neural network to use.
    :arg XP_PATH: Export path for logging the experiment.
    :arg DATA_PATH: Root path of data.
    """

    # Get configuration
    cfg = Config(locals().copy())

    # Set up logging
    logging.basicConfig(level=logging.INFO)
    logger = logging.getLogger()
    logger.setLevel(logging.INFO)
    formatter = logging.Formatter(
        '%(asctime)s - %(name)s - %(levelname)s - %(message)s')
    log_file = xp_path + '/log.txt'
    file_handler = logging.FileHandler(log_file)
    file_handler.setLevel(logging.INFO)
    file_handler.setFormatter(formatter)
    logger.addHandler(file_handler)

    # Current date and time
    logger.info('Current date and time is %s.' % datetime.now())

    # () arguments
    logger.info('Log file is %s.' % log_file)
    logger.info('Data path is %s.' % data_path)
    logger.info('Export path is %s.' % xp_path)

    logger.info('Dataset: %s' % dataset_name)
    logger.info('Normal class: %d' % normal_class)
    logger.info('Network: %s' % net_name)

    # If specified, load experiment config from JSON-file
    if load_config:
        cfg.load_config(import_json=load_config)
        logger.info('Loaded configuration from %s.' % load_config)

    # Print configuration
    logger.info('Deep SVDD objective: %s' % cfg.settings['objective'])
    logger.info('Nu-parameter: %.2f' % cfg.settings['nu'])

    # Set seed
    if cfg.settings['seed'] != -1:
        random.seed(cfg.settings['seed'])
        np.random.seed(cfg.settings['seed'])
        torch.manual_seed(cfg.settings['seed'])
        logger.info('Set seed to %d.' % cfg.settings['seed'])

    # Default device to 'cpu' if cuda is not available
    if not torch.cuda.is_available():
        device = 'cpu'
    logger.info('Computation device: %s' % device)
    logger.info('Number of dataloader workers: %d' % n_jobs_dataloader)

    # Load data
    dataset = load_dataset(dataset_name, data_path, normal_class)

    # Initialize DeepSVDD model and set neural network \phi
    deep_SVDD = DeepSVDD(cfg.settings['objective'], cfg.settings['nu'])
    deep_SVDD.set_network(net_name)
    # If specified, load Deep SVDD model (radius R, center c, network weights, and possibly autoencoder weights)
    if load_model:
        deep_SVDD.load_model(model_path=load_model, load_ae=True)
        logger.info('Loading model from %s.' % load_model)

    logger.info('Pretraining: %s' % pretrain)
    if pretrain:
        # Log pretraining details
        logger.info('Pretraining optimizer: %s' %
                    cfg.settings['ae_optimizer_name'])
        logger.info('Pretraining learning rate: %g' % cfg.settings['ae_lr'])
        logger.info('Pretraining epochs: %d' % cfg.settings['ae_n_epochs'])
        logger.info('Pretraining learning rate scheduler milestones: %s' %
                    (cfg.settings['ae_lr_milestone'], ))
        logger.info('Pretraining batch size: %d' %
                    cfg.settings['ae_batch_size'])
        logger.info('Pretraining weight decay: %g' %
                    cfg.settings['ae_weight_decay'])

        # Pretrain model on dataset (via autoencoder)
        deep_SVDD.pretrain(dataset,
                           optimizer_name=cfg.settings['ae_optimizer_name'],
                           lr=cfg.settings['ae_lr'],
                           n_epochs=cfg.settings['ae_n_epochs'],
                           lr_milestones=cfg.settings['ae_lr_milestone'],
                           batch_size=cfg.settings['ae_batch_size'],
                           weight_decay=cfg.settings['ae_weight_decay'],
                           device=device,
                           n_jobs_dataloader=n_jobs_dataloader)

    # Log training details
    logger.info('Training optimizer: %s' % cfg.settings['optimizer_name'])
    logger.info('Training learning rate: %g' % cfg.settings['lr'])
    logger.info('Training epochs: %d' % cfg.settings['n_epochs'])
    logger.info('Training learning rate scheduler milestones: %s' %
                (cfg.settings['lr_milestone'], ))
    logger.info('Training batch size: %d' % cfg.settings['batch_size'])
    logger.info('Training weight decay: %g' % cfg.settings['weight_decay'])

    # Train model on dataset
    deep_SVDD.train(dataset,
                    optimizer_name=cfg.settings['optimizer_name'],
                    lr=cfg.settings['lr'],
                    n_epochs=cfg.settings['n_epochs'],
                    lr_milestones=cfg.settings['lr_milestone'],
                    batch_size=cfg.settings['batch_size'],
                    weight_decay=cfg.settings['weight_decay'],
                    device=device,
                    n_jobs_dataloader=n_jobs_dataloader)

    # Test model
    deep_SVDD.test(dataset, device=device, n_jobs_dataloader=n_jobs_dataloader)

    # Plot most anomalous and most normal (within-class) test samples
    indices, labels, scores = zip(*deep_SVDD.results['test_scores'])
    indices, labels, scores = np.array(indices), np.array(labels), np.array(
        scores)

    idx_all_sorted = indices[np.argsort(scores)]
    idx_normal_sorted = indices[labels == 0][np.argsort(
        scores[labels == 0])]  # sorted from lowest to highest anomaly score
    idx_outlier_sorted = indices[labels == 1][np.argsort(scores[labels == 1])]
    idx_sorted = indices[np.argsort(scores)]

    test_auc = deep_SVDD.results['test_auc']

    if dataset_name in ('mnist', 'cifar10', 'fashion', 'crack', 'crack128'):
        if dataset_name == 'mnist':
            X_normals = dataset.test_set.test_data[idx_sorted_normal[:32],
                                                   ...].unsqueeze(1)
            X_outliers = dataset.test_set.test_data[idx_sorted_normal[-32:],
                                                    ...].unsqueeze(1)

        if dataset_name == 'cifar10':
            X_normals = torch.tensor(
                np.transpose(
                    dataset.test_set.test_data[idx_sorted_normal[:32], ...],
                    (0, 3, 1, 2)))
            X_outliers = torch.tensor(
                np.transpose(
                    dataset.test_set.test_data[idx_sorted_normal[-32:], ...],
                    (0, 3, 1, 2)))

        if dataset_name == 'fashion':
            X_normals = torch.reshape(
                torch.tensor(dataset.test_set.data[idx_sorted_normal[:32],
                                                   ...]),
                (32, 28, 28)).unsqueeze(1)
            X_outliers = torch.reshape(
                torch.tensor(dataset.test_set.data[idx_sorted_normal[-32:],
                                                   ...]),
                (32, 28, 28)).unsqueeze(1)

        plot_imgs = True
        indices, labels, scores = zip(
            *deep_SVDD.results['test_scores (corner)'])
        indices, labels, scores = np.array(indices), np.array(
            labels), np.array(scores)
        idx_all_sorted = indices[np.argsort(
            scores)]  # from lowest to highest score
        idx_normal_sorted = indices[labels == 0][np.argsort(
            scores[labels == 0])]  # from lowest to highest score
        idx_outlier_sorted = indices[labels == 1][np.argsort(
            scores[labels == 1])]  # from lowest to highest score

        if dataset_name == 'crack':
            mid = len(idx_all_sorted) / 2
            if len(idx_all_sorted) > 64 and len(
                    idx_normal_sorted) > 64 and len(idx_outlier_sorted) > 100:
                #X_middle = torch.reshape(torch.tensor(dataset.test_set.data[idx_all_sorted[int(mid-312):int(mid+313)], ...]), (625,64,64)).unsqueeze(1)
                X_all_normal = torch.reshape(
                    torch.tensor(
                        dataset.test_set_corner.data[idx_all_sorted[:64],
                                                     ...]),
                    (64, 64, 64)).unsqueeze(1)
                X_all_outlier = torch.reshape(
                    torch.tensor(
                        dataset.test_set_corner.data[idx_all_sorted[-144:],
                                                     ...]),
                    (144, 64, 64)).unsqueeze(1)
                X_normals_normal = torch.reshape(
                    torch.tensor(
                        dataset.test_set_corner.data[idx_normal_sorted[:64],
                                                     ...]),
                    (64, 64, 64)).unsqueeze(1)
                X_normals_outlier = torch.reshape(
                    torch.tensor(
                        dataset.test_set_corner.data[idx_normal_sorted[-64:],
                                                     ...]),
                    (64, 64, 64)).unsqueeze(1)
                X_outliers_normal = torch.reshape(
                    torch.tensor(
                        dataset.test_set_corner.data[idx_outlier_sorted[:100],
                                                     ...]),
                    (100, 64, 64)).unsqueeze(1)
                X_outliers_outlier = torch.reshape(
                    torch.tensor(
                        dataset.test_set_corner.data[idx_outlier_sorted[-100:],
                                                     ...]),
                    (100, 64, 64)).unsqueeze(1)
            else:
                plot_imgs = False
                X_all_normal = torch.reshape(
                    torch.tensor(
                        dataset.test_set_corner.data[idx_all_sorted[:1], ...]),
                    (1, 64, 64)).unsqueeze(1)
                X_all_outlier = torch.reshape(
                    torch.tensor(
                        dataset.test_set_corner.data[idx_all_sorted[-1:],
                                                     ...]),
                    (1, 64, 64)).unsqueeze(1)
                X_normals_normal = torch.reshape(
                    torch.tensor(
                        dataset.test_set_corner.data[idx_normal_sorted[:1],
                                                     ...]),
                    (1, 64, 64)).unsqueeze(1)
                X_normals_outlier = torch.reshape(
                    torch.tensor(
                        dataset.test_set_corner.data[idx_normal_sorted[-1:],
                                                     ...]),
                    (1, 64, 64)).unsqueeze(1)
                X_outliers_normal = torch.reshape(
                    torch.tensor(
                        dataset.test_set_corner.data[idx_outlier_sorted[:1],
                                                     ...]),
                    (1, 64, 64)).unsqueeze(1)
                X_outliers_outlier = torch.reshape(
                    torch.tensor(
                        dataset.test_set_corner.data[idx_outlier_sorted[-1:],
                                                     ...]),
                    (1, 64, 64)).unsqueeze(1)

        if dataset_name == 'crack128':
            mid = len(idx_all_sorted) / 2
            if len(idx_all_sorted) > 64 and len(
                    idx_normal_sorted) > 64 and len(idx_outlier_sorted) > 100:

                #X_middle = torch.reshape(torch.tensor(dataset.test_set.data[idx_all_sorted[int(mid-312):int(mid+313)], ...]), (625,128,128)).unsqueeze(1)
                X_all_normal = torch.reshape(
                    torch.tensor(
                        dataset.test_set_corner.data[idx_all_sorted[:64],
                                                     ...]),
                    (64, 128, 128)).unsqueeze(1)
                X_all_outlier = torch.reshape(
                    torch.tensor(
                        dataset.test_set_corner.data[idx_all_sorted[-144:],
                                                     ...]),
                    (144, 128, 128)).unsqueeze(1)
                X_normals_normal = torch.reshape(
                    torch.tensor(
                        dataset.test_set_corner.data[idx_normal_sorted[:64],
                                                     ...]),
                    (64, 128, 128)).unsqueeze(1)
                X_normals_outlier = torch.reshape(
                    torch.tensor(
                        dataset.test_set_corner.data[idx_normal_sorted[-64:],
                                                     ...]),
                    (64, 128, 128)).unsqueeze(1)
                X_outliers_normal = torch.reshape(
                    torch.tensor(
                        dataset.test_set_corner.data[idx_outlier_sorted[:100],
                                                     ...]),
                    (100, 128, 128)).unsqueeze(1)
                X_outliers_outlier = torch.reshape(
                    torch.tensor(
                        dataset.test_set_corner.data[idx_outlier_sorted[-100:],
                                                     ...]),
                    (100, 128, 128)).unsqueeze(1)
            else:
                plot_imgs = False
                X_all_normal = torch.reshape(
                    torch.tensor(
                        dataset.test_set_corner.data[idx_all_sorted[:1], ...]),
                    (1, 128, 128)).unsqueeze(1)
                X_all_outlier = torch.reshape(
                    torch.tensor(
                        dataset.test_set_corner.data[idx_all_sorted[-1:],
                                                     ...]),
                    (1, 128, 128)).unsqueeze(1)
                X_normals_normal = torch.reshape(
                    torch.tensor(
                        dataset.test_set_corner.data[idx_normal_sorted[:1],
                                                     ...]),
                    (1, 128, 128)).unsqueeze(1)
                X_normals_outlier = torch.reshape(
                    torch.tensor(
                        dataset.test_set_corner.data[idx_normal_sorted[-1:],
                                                     ...]),
                    (1, 128, 128)).unsqueeze(1)
                X_outliers_normal = torch.reshape(
                    torch.tensor(
                        dataset.test_set_corner.data[idx_outlier_sorted[:1],
                                                     ...]),
                    (1, 128, 128)).unsqueeze(1)
                X_outliers_outlier = torch.reshape(
                    torch.tensor(
                        dataset.test_set_corner.data[idx_outlier_sorted[-1:],
                                                     ...]),
                    (1, 128, 128)).unsqueeze(1)

        if plot_imgs:
            #plot_images_grid(X_middle, export_img=xp_path + '/plots/' + img_name + '_all_middle_', title='All samples', padding=2, nrow=25)
            #plot_images_grid(X_all_normal, export_img=xp_path + '/plots/' + img_name + '_all_low_', title='Least anomalous samples', padding=2, nrow=8)
            plot_images_grid(X_all_outlier,
                             export_img=xp_path + '/plots/' + img_name +
                             '_all_high_',
                             title='Most anomalous samples',
                             padding=2,
                             nrow=12)
            #plot_images_grid(X_normals_normal, export_img=xp_path + '/plots/' + img_name + '_normals_low_', title='Least anomalous normal samples', padding=2, nrow=8)
            plot_images_grid(X_normals_outlier,
                             export_img=xp_path + '/plots/' + img_name +
                             '_normals_high_',
                             title='Most anmalous normal samples',
                             padding=2,
                             nrow=8)
            plot_images_grid(X_outliers_normal,
                             export_img=xp_path + '/plots/' + img_name +
                             '_outliers_low_',
                             title='Least anomalous anomaly samples',
                             padding=2,
                             nrow=10)
            plot_images_grid(X_outliers_outlier,
                             export_img=xp_path + '/plots/' + img_name +
                             '_outliers_high_',
                             title='Most anomalous anomaly samples',
                             padding=2,
                             nrow=10)

        test_auc = deep_SVDD.results['test_auc']
        test_auc_corner = deep_SVDD.results['test_auc (corner)']
        plot_images_hist(
            scores[labels == 0],
            scores[labels == 1],
            export_img=xp_path + '/plots/' + img_name + '_hist_corner',
            title=
            'Deep SVDD Anomaly scores of normal and crack samples (with corner cracks)',
            auc=test_auc_corner)

        indices, labels, scores = zip(*deep_SVDD.results['test_scores'])
        indices, labels, scores = np.array(indices), np.array(
            labels), np.array(scores)
        plot_images_hist(
            scores[labels == 0],
            scores[labels == 1],
            export_img=xp_path + '/plots/' + img_name + '_hist',
            title='Deep SVDD anomaly scores of normal and crack samples',
            auc=test_auc)

    # Save results, model, and configuration
    deep_SVDD.save_results(export_json=xp_path + '/results.json')
    deep_SVDD.save_model(export_model=xp_path + '/model.tar')
    cfg.save_config(export_json=xp_path + '/config.json')
Ejemplo n.º 8
0
def main(dataset_name, net_name, xp_path, data_path, load_data, load_config,
         load_model, objective, nu, device, seed, optimizer_name, lr, n_epochs,
         lr_milestone, batch_size, weight_decay, pretrain, ae_optimizer_name,
         ae_lr, ae_n_epochs, ae_lr_milestone, ae_batch_size, ae_weight_decay,
         n_jobs_dataloader, normal_class):
    """
    Deep SVDD, a fully deep method for anomaly detection.

    :arg DATASET_NAME: Name of the dataset to load.
    :arg NET_NAME: Name of the neural n etwork to use.
    :arg XP_PATH: Export path for loggi ng the experiment.
    :arg DATA_PATH: Root path of data.  
    """

    # Get configuration
    cfg = Config(locals().copy())

    # Set up logging
    logging.basicConfig(level=logging.INFO)
    logger = logging.getLogger()
    logger.setLevel(logging.INFO)
    formatter = logging.Formatter(
        '%(asctime)s - %(name)s - %(levelname)s - %(message)s')
    log_file = xp_path + '/log.txt'
    file_handler = logging.FileHandler(log_file)
    file_handler.setLevel(logging.INFO)
    file_handler.setFormatter(formatter)
    logger.addHandler(file_handler)

    # Print arguments
    logger.info('Log file is %s.' % log_file)
    logger.info('Data path is %s.' % data_path)
    logger.info('Export path is %s.' % xp_path)

    logger.info('Dataset: %s' % dataset_name)
    logger.info('Normal class: %d' % normal_class)
    logger.info('Network: %s' % net_name)

    # If specified, load experiment config from JSON-file
    if load_config:
        cfg.load_config(import_json=load_config)
        logger.info('Loaded configuration from %s.' % load_config)

    # Print configuration
    logger.info('Deep SVDD objective: %s' % cfg.settings['objective'])
    logger.info('Nu-paramerter: %.2f' % cfg.settings['nu'])

    # Set seed
    if cfg.settings['seed'] != -1:
        random.seed(cfg.settings['seed'])
        np.random.seed(cfg.settings['seed'])
        torch.manual_seed(cfg.settings['seed'])
        logger.info('Set seed to %d.' % cfg.settings['seed'])

    # Default device to 'cpu' if cuda is not available
    if not torch.cuda.is_available():
        device = 'cpu'
    logger.info('Computation device: %s' % device)
    logger.info('Number of dataloader workers: %d' % n_jobs_dataloader)

    # Load data
    if dataset_name == 'campus':
        train_path = 'train/OK'
        test_path = 'test'
        train_image, test_image, test_label = train_test_numpy_load(
            data_path, train_path, test_path, load_data)
        dataset = load_campus_dataset(dataset_name, data_path, train_image,
                                      test_image, test_label)
    else:
        dataset = load_dataset(dataset_name, data_path, normal_class)

    # Initialize DeepSVDD model and set neural network \phi
    deep_SVDD = DeepSVDD(cfg.settings['objective'], cfg.settings['nu'])
    deep_SVDD.set_network(net_name)
    # If specified, load Deep SVDD model (radius R, center c, network weights, and possibly autoencoder weights)
    if load_model:
        deep_SVDD.load_model(model_path=load_model, load_ae=True)
        logger.info('Loading model from %s.' % load_model)

    # logger.info('Pretraining: %s' % pretrain)
    if pretrain:
        # Log pretraining details
        logger.info('Pretraining optimizer: %s' %
                    cfg.settings['ae_optimizer_name'])
        logger.info('Pretraining learning rate: %g' % cfg.settings['ae_lr'])
        logger.info('Pretraining epochs: %d' % cfg.settings['ae_n_epochs'])
        logger.info('Pretraining learning rate scheduler milestones: %s' %
                    (cfg.settings['ae_lr_milestone'], ))
        logger.info('Pretraining batch size: %d' %
                    cfg.settings['ae_batch_size'])
        logger.info('Pretraining weight decay: %g' %
                    cfg.settings['ae_weight_decay'])

        # Pretrain model on dataset (via autoencoder)
        deep_SVDD.pretrain(dataset,
                           optimizer_name=cfg.settings['ae_optimizer_name'],
                           lr=cfg.settings['ae_lr'],
                           n_epochs=cfg.settings['ae_n_epochs'],
                           lr_milestones=cfg.settings['ae_lr_milestone'],
                           batch_size=cfg.settings['ae_batch_size'],
                           weight_decay=cfg.settings['ae_weight_decay'],
                           device=device,
                           n_jobs_dataloader=n_jobs_dataloader,
                           test_image=test_image)

    # Log training details
    logger.info('Training optimizer: %s' % cfg.settings['optimizer_name'])
    logger.info('Training learning rate: %g' % cfg.settings['lr'])
    logger.info('Training epochs: %d' % cfg.settings['n_epochs'])
    logger.info('Training learning rate scheduler milestones: %s' %
                (cfg.settings['lr_milestone'], ))
    logger.info('Training batch size: %d' % cfg.settings['batch_size'])
    logger.info('Training weight decay: %g' % cfg.settings['weight_decay'])

    # Train model on dataset
    deep_SVDD.train(dataset,
                    optimizer_name=cfg.settings['optimizer_name'],
                    lr=cfg.settings['lr'],
                    n_epochs=cfg.settings['n_epochs'],
                    lr_milestones=cfg.settings['lr_milestone'],
                    batch_size=cfg.settings['batch_size'],
                    weight_decay=cfg.settings['weight_decay'],
                    device=device,
                    n_jobs_dataloader=n_jobs_dataloader)
    # plot t_sne
    # deep_SVDD.t_sne(dataset, device=device, n_jobs_dataloader=n_jobs_dataloader, data_path=data_path, xp_path=xp_path)

    # Test model
    deep_SVDD.test(dataset, device=device, n_jobs_dataloader=n_jobs_dataloader)

    # Plot most anomalous and most normal (within-class) test samples
    indices, labels, scores = zip(*deep_SVDD.results['test_scores'])
    indices, labels, scores = np.array(indices), np.array(labels), np.array(
        scores)

    if dataset_name in ('mnist', 'cifar10', 'campus'):

        if dataset_name == 'mnist':
            X_normals = dataset.test_set.test_data[idx_sorted[:32],
                                                   ...].unsqueeze(1)
            X_outliers = dataset.test_set.test_data[idx_sorted[-32:],
                                                    ...].unsqueeze(1)

        if dataset_name == 'cifar10':
            X_normals = torch.tensor(
                np.transpose(dataset.test_set.test_data[idx_sorted[:32], ...],
                             (0, 3, 1, 2)))
            X_outliers = torch.tensor(
                np.transpose(dataset.test_set.test_data[idx_sorted[-32:], ...],
                             (0, 3, 1, 2)))

        if dataset_name == 'campus':
            test_score_path = os.path.join(xp_path, 'test_score.pickle')
            with open(test_score_path, 'wb') as f:
                pickle.dump(deep_SVDD.results['test_scores'], f,
                            pickle.HIGHEST_PROTOCOL)

        if dataset_name == 'campus':
            fpr = dict()
            tpr = dict()
            roc_auc = dict()
            fpr, tpr, threshold = roc_curve(labels, scores)
            roc_auc = auc(fpr, tpr)
            plt.figure()
            lw = 2
            plt.plot(fpr,
                     tpr,
                     color='darkorange',
                     lw=lw,
                     label='ROC curve (area= %0.2f)' % roc_auc)
            plt.plot([0, 1], [0, 1], color='navy', lw=lw, linestyle='--')
            plt.xlim([0.0, 1.0])
            plt.ylim([0.0, 1.05])
            plt.xlabel('False Positive Rate')
            plt.ylabel('True Positive Rate')
            plt.title('Receiver operating characteristic example')
            plt.legend(loc="lower right")
            plt.savefig(os.path.join(xp_path, 'auc_roc.png'))
        else:
            plot_images_grid(X_normals,
                             export_img=xp_path + '/normals',
                             title='Most normal examples',
                             padding=2)
            plot_images_grid(X_outliers,
                             export_img=xp_path + '/outliers',
                             title='Most anomalous examples',
                             padding=2)

    # Save results, model, and configuration
    deep_SVDD.save_results(export_json=xp_path + '/results.json')
    deep_SVDD.save_model(export_model=xp_path + '/model.tar')
    cfg.save_config(export_json=xp_path + '/config.json')
Ejemplo n.º 9
0
def main(dataset_name, net_name, xp_path, data_path, load_config, load_model, objective, nu, focal_parameter, update_center_epochs, device, seed,
         optimizer_name, lr, n_epochs, lr_milestone, batch_size, weight_decay, pretrain, ae_optimizer_name, ae_lr,
         ae_n_epochs, ae_lr_milestone, ae_batch_size, ae_weight_decay, n_jobs_dataloader, normal_class):
    """
    Deep SVDD, a fully deep method for anomaly detection.

    :arg DATASET_NAME: Name of the dataset to load.
    :arg NET_NAME: Name of the neural network to use.
    :arg XP_PATH: Export path for logging the experiment.
    :arg DATA_PATH: Root path of data.
    """

    # Get configuration
    cfg = Config(locals().copy())

    # Set up logging
    logging.basicConfig(level=logging.INFO)
    logger = logging.getLogger()
    logger.setLevel(logging.INFO)
    formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
    log_file = xp_path + '/log.txt'
    file_handler = logging.FileHandler(log_file)
    file_handler.setLevel(logging.INFO)
    file_handler.setFormatter(formatter)
    logger.addHandler(file_handler)

    # Print arguments
    logger.info('Log file is %s.' % log_file)
    logger.info('Data path is %s.' % data_path)
    logger.info('Export path is %s.' % xp_path)

    logger.info('Dataset: %s' % dataset_name)
    logger.info('Normal class: %d' % normal_class)
    logger.info('Network: %s' % net_name)

    # If specified, load experiment config from JSON-file
    if load_config:
        cfg.load_config(import_json=load_config)
        logger.info('Loaded configuration from %s.' % load_config)

    # Print configuration
    logger.info('Deep SVDD objective: %s' % cfg.settings['objective'])
    logger.info('Nu-paramerter: %.2f' % cfg.settings['nu'])
    logger.info('focal_parameter: %.2f' % cfg.settings['focal_parameter'])
    logger.info('update_center_epochs: %d' % cfg.settings['update_center_epochs'])

    # Set seed
    if cfg.settings['seed'] != -1:
        random.seed(cfg.settings['seed'])
        os.environ['PYTHONHASHSEED'] = str(seed)
        np.random.seed(cfg.settings['seed'])
        torch.manual_seed(cfg.settings['seed'])
        torch.cuda.manual_seed(cfg.settings['seed'])
        torch.cuda.manual_seed_all(cfg.settings['seed'])
        cudnn.benchmark = False
        torch.backends.cudnn.deterministic = True
        logger.info('Set seed to %d.' % cfg.settings['seed'])

    # Default device to 'cpu' if cuda is not available
    if not torch.cuda.is_available():
        device = 'cpu'
    logger.info('Computation device: %s' % device)
    logger.info('Number of dataloader workers: %d' % n_jobs_dataloader)

    # Load data
    dataset = load_dataset(dataset_name, data_path, normal_class)

    # Initialize DeepSVDD model and set neural network \phi
    deep_SVDD = DeepSVDD(cfg.settings['objective'], cfg.settings['nu'], cfg.settings['focal_parameter'], cfg.settings['update_center_epochs'])
    deep_SVDD.set_network(net_name)
    # If specified, load Deep SVDD model (radius R, center c, network weights, and possibly autoencoder weights)
    if load_model:
        deep_SVDD.load_model(model_path=load_model, load_ae=True)
        logger.info('Loading model from %s.' % load_model)

    logger.info('Pretraining: %s' % pretrain)
    if pretrain:
        # Log pretraining details
        logger.info('Pretraining optimizer: %s' % cfg.settings['ae_optimizer_name'])
        logger.info('Pretraining learning rate: %g' % cfg.settings['ae_lr'])
        logger.info('Pretraining epochs: %d' % cfg.settings['ae_n_epochs'])
        logger.info('Pretraining learning rate scheduler milestones: %s' % (cfg.settings['ae_lr_milestone'],))
        logger.info('Pretraining batch size: %d' % cfg.settings['ae_batch_size'])
        logger.info('Pretraining weight decay: %g' % cfg.settings['ae_weight_decay'])

        # Pretrain model on dataset (via autoencoder)
        deep_SVDD.pretrain(dataset,
                           optimizer_name=cfg.settings['ae_optimizer_name'],
                           lr=cfg.settings['ae_lr'],
                           n_epochs=cfg.settings['ae_n_epochs'],
                           lr_milestones=cfg.settings['ae_lr_milestone'],
                           batch_size=cfg.settings['ae_batch_size'],
                           weight_decay=cfg.settings['ae_weight_decay'],
                           device=device,
                           n_jobs_dataloader=n_jobs_dataloader)

    # Log training details
    logger.info('Training optimizer: %s' % cfg.settings['optimizer_name'])
    logger.info('Training learning rate: %g' % cfg.settings['lr'])
    logger.info('Training epochs: %d' % cfg.settings['n_epochs'])
    logger.info('Training learning rate scheduler milestones: %s' % (cfg.settings['lr_milestone'],))
    logger.info('Training batch size: %d' % cfg.settings['batch_size'])
    logger.info('Training weight decay: %g' % cfg.settings['weight_decay'])

    # record test AUC after each 100 epoch
    # f_get_para = open('../log/mnist_test/100_AUC.txt', 'w')
    # f_get_para.write("\r\n \r\nrecord test AUC each 100 epoch   \r\n \r\n \r\n")
    # f_get_para.close()
    #
    # f_get_para = open('../log/mnist_test/get_param.txt', 'w')
    # f_get_para.write("\r\n \r\nrecord test AUC each very epoch   \r\n \r\n \r\n")
    # f_get_para.close()

    # Train model on dataset
    deep_SVDD.train(dataset,
                    optimizer_name=cfg.settings['optimizer_name'],
                    lr=cfg.settings['lr'],
                    n_epochs=cfg.settings['n_epochs'],
                    lr_milestones=cfg.settings['lr_milestone'],
                    batch_size=cfg.settings['batch_size'],
                    weight_decay=cfg.settings['weight_decay'],
                    device=device,
                    n_jobs_dataloader=n_jobs_dataloader)

    # Test model
    # deep_SVDD.test(dataset, device=device, n_jobs_dataloader=n_jobs_dataloader)

    # Plot most anomalous and most normal (within-class) test samples
    # indices, labels, scores = zip(*deep_SVDD.results['test_scores'])
    # indices, labels, scores = np.array(indices), np.array(labels), np.array(scores)
    # idx_sorted = indices[labels == 0][np.argsort(scores[labels == 0])]  # sorted from lowest to highest anomaly score
    #
    # if dataset_name in ('mnist', 'cifar10'):
    #
    #     if dataset_name == 'mnist':
    #         X_normals = dataset.test_set.test_data[idx_sorted[:32], ...].unsqueeze(1)
    #         X_outliers = dataset.test_set.test_data[idx_sorted[-32:], ...].unsqueeze(1)
    #
    #     if dataset_name == 'cifar10':
    #         X_normals = torch.tensor(np.transpose(dataset.test_set.test_data[idx_sorted[:32], ...], (0, 3, 1, 2)))
    #         X_outliers = torch.tensor(np.transpose(dataset.test_set.test_data[idx_sorted[-32:], ...], (0, 3, 1, 2)))
    #
    #     plot_images_grid(X_normals, export_img=xp_path + '/normals', title='Most normal examples', padding=2)
    #     plot_images_grid(X_outliers, export_img=xp_path + '/outliers', title='Most anomalous examples', padding=2)
    #
    # # Save results, model, and configuration
    # deep_SVDD.save_results(export_json=xp_path + '/results.json')
    # deep_SVDD.save_model(export_model=xp_path + '/model.tar')
    # cfg.save_config(export_json=xp_path + '/config.json')

    # plot curves
    loss_plot = deep_SVDD.trainer.Loss_list
    accuracy_plot = deep_SVDD.trainer.Accuracy_list
    x1 = range(0, n_epochs)
    y1 = accuracy_plot
    x2 = range(0, n_epochs)
    y2 = loss_plot
    plt.subplot(2, 1, 1)
    plt.plot(x1, y1, 'o-')
    plt.title('Class %d vs focal %.2f' % (normal_class, focal_parameter))
    plt.ylabel('Test accuracy')
    plt.subplot(2, 1, 2)
    plt.plot(x2, y2, '.-')
    plt.xlabel('Test loss vs. epoches')
    plt.ylabel('Test loss')
    plt.savefig("accuracy_loss focal %.2f .jpg" % focal_parameter)
Ejemplo n.º 10
0
def main(dataset_name, net_name, load_config, load_model, objective, nu,
         device, seed, optimizer_name, lr, n_epochs, lr_milestone, batch_size,
         weight_decay, pretrain, ae_optimizer_name, ae_lr, ae_n_epochs,
         ae_lr_milestone, ae_batch_size, ae_weight_decay, n_jobs_dataloader,
         ratio, run_times):
    """
    Deep SVDD, a fully deep method for anomaly detection.

    :arg DATASET_NAME: Name of the dataset to load.
    :arg NET_NAME: Name of the neural network to use.
    :arg XP_PATH: Export path for logging the experiment.
    :arg DATA_PATH: Root path of data.
    """
    class_num = 10
    if dataset_name == 'cifar100':
        class_num = 20
    for run_index in range(run_times):
        #for ratio in [0.05, 0.1, 0.15, 0.2, 0.25]:
        for i in range(class_num):
            normal_class = i
            class_name = get_class_name_from_index(normal_class, dataset_name)
            os.makedirs(os.path.join(RESULTS_DIR), exist_ok=True)
            # Get configuration
            cfg = Config(locals().copy())

            # Set up logging
            logging.basicConfig(level=logging.INFO)
            logger = logging.getLogger()
            logger.setLevel(logging.INFO)
            formatter = logging.Formatter(
                '%(asctime)s - %(name)s - %(levelname)s - %(message)s')

            xp_path = RESULTS_DIR

            log_file = xp_path + '/log.txt'
            file_handler = logging.FileHandler(log_file)
            file_handler.setLevel(logging.INFO)
            file_handler.setFormatter(formatter)
            logger.addHandler(file_handler)

            # Print arguments
            logger.info('Log file is %s.' % log_file)
            logger.info('Export path is %s.' % xp_path)

            logger.info('Dataset: %s' % dataset_name)
            logger.info('Normal class: %d' % normal_class)
            logger.info('Network: %s' % net_name)

            # If specified, load experiment config from JSON-file
            if load_config:
                cfg.load_config(import_json=load_config)
                logger.info('Loaded configuration from %s.' % load_config)

            # Print configuration
            logger.info('Deep SVDD objective: %s' % cfg.settings['objective'])
            logger.info('Nu-paramerter: %.2f' % cfg.settings['nu'])

            # Set seed
            cfg.settings['seed'] = run_index
            if cfg.settings['seed'] != -1:
                random.seed(cfg.settings['seed'])
                np.random.seed(cfg.settings['seed'])
                torch.manual_seed(cfg.settings['seed'])
                logger.info('Set seed to %d.' % cfg.settings['seed'])

            # Default device to 'cpu' if cuda is not available
            if not torch.cuda.is_available():
                device = 'cpu'
            logger.info('Computation device: %s' % device)
            logger.info('Number of dataloader workers: %d' % n_jobs_dataloader)

            # Load data
            dataset = load_dataset(dataset_name, normal_class, ratio)

            # Initialize DeepSVDD model and set neural network \phi
            deep_SVDD = DeepSVDD(cfg.settings['objective'], cfg.settings['nu'])
            deep_SVDD.set_network(net_name)
            # If specified, load Deep SVDD model (radius R, center c, network weights, and possibly autoencoder weights)
            if load_model:
                deep_SVDD.load_model(model_path=load_model, load_ae=True)
                logger.info('Loading model from %s.' % load_model)

            logger.info('Pretraining: %s' % pretrain)
            if pretrain:
                # Log pretraining details
                logger.info('Pretraining optimizer: %s' %
                            cfg.settings['ae_optimizer_name'])
                logger.info('Pretraining learning rate: %g' %
                            cfg.settings['ae_lr'])
                logger.info('Pretraining epochs: %d' %
                            cfg.settings['ae_n_epochs'])
                logger.info(
                    'Pretraining learning rate scheduler milestones: %s' %
                    (cfg.settings['ae_lr_milestone'], ))
                logger.info('Pretraining batch size: %d' %
                            cfg.settings['ae_batch_size'])
                logger.info('Pretraining weight decay: %g' %
                            cfg.settings['ae_weight_decay'])

                # Pretrain model on dataset (via autoencoder)
                deep_SVDD.pretrain(
                    dataset,
                    optimizer_name=cfg.settings['ae_optimizer_name'],
                    lr=cfg.settings['ae_lr'],
                    n_epochs=cfg.settings['ae_n_epochs'],
                    lr_milestones=cfg.settings['ae_lr_milestone'],
                    batch_size=cfg.settings['ae_batch_size'],
                    weight_decay=cfg.settings['ae_weight_decay'],
                    device=device,
                    n_jobs_dataloader=n_jobs_dataloader)

            # Log training details
            logger.info('Training optimizer: %s' %
                        cfg.settings['optimizer_name'])
            logger.info('Training learning rate: %g' % cfg.settings['lr'])
            logger.info('Training epochs: %d' % cfg.settings['n_epochs'])
            logger.info('Training learning rate scheduler milestones: %s' %
                        (cfg.settings['lr_milestone'], ))
            logger.info('Training batch size: %d' % cfg.settings['batch_size'])
            logger.info('Training weight decay: %g' %
                        cfg.settings['weight_decay'])

            # Train model on dataset
            deep_SVDD.train(dataset,
                            optimizer_name=cfg.settings['optimizer_name'],
                            lr=cfg.settings['lr'],
                            n_epochs=cfg.settings['n_epochs'],
                            lr_milestones=cfg.settings['lr_milestone'],
                            batch_size=cfg.settings['batch_size'],
                            weight_decay=cfg.settings['weight_decay'],
                            device=device,
                            n_jobs_dataloader=n_jobs_dataloader)

            # Test model
            scores, labels = deep_SVDD.test(
                dataset, device=device, n_jobs_dataloader=n_jobs_dataloader)

            res_file_name = '{}_dsvdd-{}_{}_{}.npz'.format(
                dataset_name, ratio, class_name,
                datetime.now().strftime('%Y-%m-%d-%H%M'))
            res_file_path = os.path.join(RESULTS_DIR, dataset_name,
                                         res_file_name)
            os.makedirs(os.path.join(RESULTS_DIR, dataset_name), exist_ok=True)
            save_roc_pr_curve_data(scores, labels, res_file_path)

            # Plot most anomalous and most normal (within-class) test samples
            # indices, labels, scores = zip(*deep_SVDD.results['test_scores'])
            # indices, labels, scores = np.array(indices), np.array(labels), np.array(scores)
            # idx_sorted = indices[labels == 0][np.argsort(scores[labels == 0])]  # sorted from lowest to highest anomaly score
            #
            # if dataset_name in ('mnist', 'cifar10'):
            #
            #     if dataset_name == 'mnist':
            #         X_normals = dataset.test_set.test_data[idx_sorted[:32], ...].unsqueeze(1)
            #         X_outliers = dataset.test_set.test_data[idx_sorted[-32:], ...].unsqueeze(1)
            #
            #     if dataset_name == 'cifar10':
            #         X_normals = torch.tensor(np.transpose(dataset.test_set.test_data[idx_sorted[:32], ...], (0, 3, 1, 2)))
            #         X_outliers = torch.tensor(np.transpose(dataset.test_set.test_data[idx_sorted[-32:], ...], (0, 3, 1, 2)))
            #
            #     plot_images_grid(X_normals, export_img=xp_path + '/normals', title='Most normal examples', padding=2)
            #     plot_images_grid(X_outliers, export_img=xp_path + '/outliers', title='Most anomalous examples', padding=2)

            # Save results, model, and configuration
            logger.info('finish class {} training.'.format(class_name))
    logger.info('send exp finish mail.')
    send_mailgun()