Exemple #1
0
def plot_pics():
    with torch.no_grad():

        data_native_6 = np.load('../.././log/object/6/Images.npy')
        data_native_7 = np.load('../.././log/object/7/Images.npy')
        data_native_8 = np.load('../.././log/object/8/Images.npy')
        data_native_9 = np.load('../.././log/object/9/Images.npy')
        data_native_10 = np.load('../.././log/object/10/Images.npy')

        good = []
        for i in range(5):
            temp = np.array(data_native_6[i])
            good.append(temp)
        for i in range(5):
            temp = np.array(data_native_7[i])
            good.append(temp)
        for i in range(5):
            temp = np.array(data_native_8[i])
            good.append(temp)
        for i in range(5):
            temp = np.array(data_native_9[i])
            good.append(temp)
        for i in range(5):
            temp = np.array(data_native_10[i])
            good.append(temp)
        good = np.array(good)
        good = torch.from_numpy(good)
        plot_images_grid(good,
                         export_img='./pictures/good.eps',
                         title='Normal',
                         nrow=5,
                         padding=5)

        abnormal = []
        for i in range(60, 65):
            temp = np.array(data_native_6[i])
            abnormal.append(temp)
        for i in range(23, 28):
            temp = np.array(data_native_7[i])
            abnormal.append(temp)
        for i in range(50, 55):
            temp = np.array(data_native_8[i])
            abnormal.append(temp)
        for i in range(60, 65):
            temp = np.array(data_native_9[i])
            abnormal.append(temp)
        for i in range(135, 140):
            temp = np.array(data_native_10[i])
            abnormal.append(temp)
        abnormal = np.array(abnormal)
        abnormal = torch.from_numpy(abnormal)
        plot_images_grid(abnormal,
                         export_img='./pictures/abnormal.eps',
                         title='Abnormal',
                         nrow=5,
                         padding=5)
Exemple #2
0
def test(dataset: BaseADDataset, ae_net: BaseNet):
    # Set device for network
    ae_net = ae_net.to(device)

    # Get test data loader

    letter, labels = dataset.loaders(batch_size=batch_size,
                                     num_workers=0,
                                     shuffle_test=False,
                                     shuffle_train=False)

    loss_epoch = 0.0
    n_batches = 0
    start_time = time.time()

    with torch.no_grad():
        i = 0
        for data, label in zip(letter, labels):
            i += 1
            inputs, _ = data
            lab, _ = label
            inputs = inputs.to(device)
            lab = lab.to(device)
            # Zero the network parameter gradients
            outputs = ae_net(inputs)
            plot_images_grid(inputs[0:16],
                             export_img='./log/test/input' + str(i),
                             title='Input ',
                             nrow=4,
                             padding=4)
            plot_images_grid(lab[0:16],
                             export_img='./log/test/label' + str(i),
                             title='Label ',
                             nrow=4,
                             padding=4)
            plot_images_grid(outputs[0:16],
                             export_img='./log/test/output' + str(i),
                             title='Output ',
                             nrow=4,
                             padding=4)
Exemple #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, 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')
Exemple #4
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)
Exemple #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)

    # 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)
Exemple #6
0
def main(dataset_name, xp_path, data_path, load_config, load_model,
         ratio_known_normal, ratio_known_outlier, ratio_pollution, seed,
         n_estimators, max_samples, contamination, n_jobs_model, hybrid,
         load_ae, n_jobs_dataloader, normal_class, known_outlier_class,
         n_known_outlier_classes):
    """
    (Hybrid) Isolation Forest model for anomaly detection.

    :arg DATASET_NAME: Name of the dataset to load.
    :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 paths
    logger.info('Log file is %s.' % log_file)
    logger.info('Data path is %s.' % data_path)
    logger.info('Export path is %s.' % xp_path)

    # Print experimental setup
    logger.info('Dataset: %s' % dataset_name)
    logger.info('Normal class: %d' % normal_class)
    logger.info('Ratio of labeled normal train samples: %.2f' %
                ratio_known_normal)
    logger.info('Ratio of labeled anomalous samples: %.2f' %
                ratio_known_outlier)
    logger.info('Pollution ratio of unlabeled train data: %.2f' %
                ratio_pollution)
    if n_known_outlier_classes == 1:
        logger.info('Known anomaly class: %d' % known_outlier_class)
    else:
        logger.info('Number of known anomaly classes: %d' %
                    n_known_outlier_classes)

    # 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 Isolation Forest configuration
    logger.info('Number of base estimators in the ensemble: %d' %
                cfg.settings['n_estimators'])
    logger.info('Number of samples for training each base estimator: %d' %
                cfg.settings['max_samples'])
    logger.info('Contamination parameter: %.2f' %
                cfg.settings['contamination'])
    logger.info('Number of jobs for model training: %d' % n_jobs_model)
    logger.info('Hybrid model: %s' % cfg.settings['hybrid'])

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

    # Use 'cpu' as device for Isolation Forest
    device = 'cpu'
    torch.multiprocessing.set_sharing_strategy(
        'file_system')  # fix multiprocessing issue for ubuntu
    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,
                           known_outlier_class,
                           n_known_outlier_classes,
                           ratio_known_normal,
                           ratio_known_outlier,
                           ratio_pollution,
                           random_state=np.random.RandomState(
                               cfg.settings['seed']))
    # Log random sample of known anomaly classes if more than 1 class
    if n_known_outlier_classes > 1:
        logger.info('Known anomaly classes: %s' %
                    (dataset.known_outlier_classes, ))

    # Initialize Isolation Forest model
    Isoforest = IsoForest(hybrid=cfg.settings['hybrid'],
                          n_estimators=cfg.settings['n_estimators'],
                          max_samples=cfg.settings['max_samples'],
                          contamination=cfg.settings['contamination'],
                          n_jobs=n_jobs_model,
                          seed=cfg.settings['seed'])

    # If specified, load model parameters from already trained model
    if load_model:
        Isoforest.load_model(import_path=load_model, device=device)
        logger.info('Loading model from %s.' % load_model)

    # If specified, load model autoencoder weights for a hybrid approach
    if hybrid and load_ae is not None:
        Isoforest.load_ae(dataset_name, model_path=load_ae)
        logger.info('Loaded pretrained autoencoder for features from %s.' %
                    load_ae)

    # Train model on dataset
    Isoforest.train(dataset,
                    device=device,
                    n_jobs_dataloader=n_jobs_dataloader)

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

    # Save results and configuration
    Isoforest.save_results(export_json=xp_path + '/results.json')
    cfg.save_config(export_json=xp_path + '/config.json')

    # Plot most anomalous and most normal test samples
    indices, labels, scores = zip(*Isoforest.results['test_scores'])
    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

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

        if dataset_name in ('mnist', 'fmnist'):
            X_all_low = dataset.test_set.data[idx_all_sorted[:32],
                                              ...].unsqueeze(1)
            X_all_high = dataset.test_set.data[idx_all_sorted[-32:],
                                               ...].unsqueeze(1)
            X_normal_low = dataset.test_set.data[idx_normal_sorted[:32],
                                                 ...].unsqueeze(1)
            X_normal_high = dataset.test_set.data[idx_normal_sorted[-32:],
                                                  ...].unsqueeze(1)

        if dataset_name == 'cifar10':
            X_all_low = torch.tensor(
                np.transpose(dataset.test_set.data[idx_all_sorted[:32], ...],
                             (0, 3, 1, 2)))
            X_all_high = torch.tensor(
                np.transpose(dataset.test_set.data[idx_all_sorted[-32:], ...],
                             (0, 3, 1, 2)))
            X_normal_low = torch.tensor(
                np.transpose(
                    dataset.test_set.data[idx_normal_sorted[:32], ...],
                    (0, 3, 1, 2)))
            X_normal_high = torch.tensor(
                np.transpose(
                    dataset.test_set.data[idx_normal_sorted[-32:], ...],
                    (0, 3, 1, 2)))

        plot_images_grid(X_all_low, export_img=xp_path + '/all_low', padding=2)
        plot_images_grid(X_all_high,
                         export_img=xp_path + '/all_high',
                         padding=2)
        plot_images_grid(X_normal_low,
                         export_img=xp_path + '/normals_low',
                         padding=2)
        plot_images_grid(X_normal_high,
                         export_img=xp_path + '/normals_high',
                         padding=2)
Exemple #7
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')
Exemple #8
0
def plot_reconstruction(net,device,ae_loss_type, normal_classes):
    ssim_loss1 = pytorch_ssim.SSIM(window_size=11, size_average=False)
    with torch.no_grad():
        # np.save('./log/object/Reconstruction_evaluation/Images.npy', inputs.cpu().numpy()[-16:])
        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
               ]



        path = './log/object/' + str(normal_classes)

        # np.save('./log/AnboT/Reconstruction_evaluation/native.npy', inputs.cpu().numpy())
        data_native = np.load(path+'/Images.npy')
        data_native = torch.from_numpy(data_native).to(device)

        reconstructions = []

        if ae_loss_type == 'object_HAE' or ae_loss_type == 'object_HAE_ssim':
            x_reco, rep_0_reco, rep_1_reco, rep_2_reco, rep_3_reco, rep_4_reco, \
            rep_5_reco, rep_6_reco, rep_7_reco, rep_8_reco, rep_9_reco = net(data_native)
            reconstructions.append(x_reco)
            reconstructions.append(rep_0_reco)
            reconstructions.append(rep_1_reco)
            reconstructions.append(rep_2_reco)
            reconstructions.append(rep_3_reco)
            reconstructions.append(rep_4_reco)
            reconstructions.append(rep_5_reco)
            reconstructions.append(rep_6_reco)
            reconstructions.append(rep_7_reco)
            reconstructions.append(rep_8_reco)
            reconstructions.append(rep_9_reco)


        elif ae_loss_type == 'texture_HAE' or ae_loss_type == 'texture_HAE_ssim':
            pass
        elif ae_loss_type == 'mnist_HAE' or ae_loss_type == 'mnist_HAE_ssim':
            pass
        else:
            reconstruction = net(data_native)
            reconstructions.append(reconstruction)

        # for i in range(3):
        #     data_native[:, i, :, :] *= std[normal_classes][i]
        #     data_native[:, i, :, :] += mean[normal_classes][i]
        #     data_native[:, i, :, :] *= 6
        #     data_native[:, i, :, :] += 3
        #     reconstruction[:, i, :, :] *= std[normal_classes][i]
        #     reconstruction[:, i, :, :] += mean[normal_classes][i]
        #     reconstruction[:, i, :, :] *= 6
        #     reconstruction[:, i, :, :] += 3

        features = []

        if ae_loss_type == 'ssim':
            for reconstruction in reconstructions:
                feature = -ssim_loss1(data_native, reconstruction)
                features.append(feature.cpu().numpy())
        else:
            for reconstruction in reconstructions:
                feature = (data_native - reconstruction) ** 2
                features.append(feature.cpu().numpy())

        plot_images_grid(data_native[0::4], export_img=path + '/Img_native', title='Images', nrow=4, padding=4)
        with torch.no_grad():
            np.save('./log/object/' + str(normal_classes) + '/Data_Images.npy', data_native.cpu().numpy())

        print(np.shape(features))

        features = np.array(features)
        data_native = data_native.cpu().numpy()

        # [11,100,3,256,256]
        # for i in range(np.shape(features)[1]):
        #     plt.imshow(np.transpose(data_native[i],(1,2,0)))
        #     plt.savefig("./log/object/8/naive_"+str(i))
        #     # plt.show()
        #     for j in range(np.shape(features)[0]):
        #         m = features[j][i]
        #
        #         plt.imshow(np.transpose(m,(1,2,0)))
        #         plt.title(str(np.sum(m))+' & '+str(compute_local_error(m)))
        #         plt.savefig("./log/object/8/rec_" + str(i)+'_'+str(j))
        #         # plt.show()

        for i in range(len(features)):
            # plot_images_grid(torch.tensor(np.transpose(reconstruction.cpu().numpy(), (0, 3, 1, 2))), export_img=path + '/reconstruction', title='Reconstructions', padding=2)
            plot_images_grid(torch.tensor(reconstructions[i][0::4]), export_img=path + '/Img_reconstruction_'+str(i), title='Reconstructions '+str(i),
                             nrow=4, padding=4)
            plot_images_grid(torch.tensor(features[i][0::4]), export_img=path + '/Img_feature_'+str(i), title='Feature Map '+str(i), nrow=4,
                             padding=4)
            with torch.no_grad():
                np.save('./log/object/' + str(normal_classes) + '/Data_Reconstruction_'+str(i)+'.npy', reconstructions[i].cpu().numpy())
                np.save('./log/object/' + str(normal_classes) + '/Data_Feature_'+str(i)+'.npy', features[i])
Exemple #9
0
def main(dataset_name, net_name, xp_path, data_path, load_config, load_model, eta,
         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,
         num_threads, n_jobs_dataloader, normal_class):
    """
    Deep SAD, a method for deep semi-supervised 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 paths
    logger.info('Log file is %s' % log_file)
    logger.info('Data path is %s' % data_path)
    logger.info('Export path is %s' % xp_path)

    # Print experimental setup
    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 model configuration
    logger.info('Eta-parameter: %.2f' % cfg.settings['eta'])

    # Set seed
    if cfg.settings['seed'] != -1:
        random.seed(cfg.settings['seed'])
        np.random.seed(cfg.settings['seed'])
        torch.manual_seed(cfg.settings['seed'])
        torch.cuda.manual_seed(cfg.settings['seed'])
        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'
    # Set the number of threads used for parallelizing CPU operations
    if num_threads > 0:
        torch.set_num_threads(num_threads)
    logger.info('Computation device: %s' % device)
    logger.info('Number of threads: %d' % num_threads)
    logger.info('Number of dataloader workers: %d' % n_jobs_dataloader)

    # Load data
    dataset = load_dataset(dataset_name, data_path, normal_class, random_state=np.random.RandomState(cfg.settings['seed']))
    # Log random sample of known anomaly classes if more than 1 class

    # Initialize DeepSAD model and set neural network phi
    deepSAD = DeepSAD(cfg.settings['eta'])
    deepSAD.set_network(net_name)

    # If specified, load Deep SAD model (center c, network weights, and possibly autoencoder weights)
    if load_model:
        deepSAD.load_model(model_path=load_model, load_ae=True, map_location=device)
        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)
        deepSAD.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)

        # Save pretraining results
        deepSAD.save_ae_results(export_json=xp_path + '/ae_results.json')

    # 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
    deepSAD.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
    deepSAD.test(dataset, device=device, n_jobs_dataloader=n_jobs_dataloader)

    # Save results, model, and configuration
    deepSAD.save_results(export_json=xp_path + '/results.json')
    deepSAD.save_model(export_model=xp_path + '/model.tar')
    cfg.save_config(export_json=xp_path + '/config.json')

    # Plot most anomalous and most normal test samples
    indices, labels, scores = zip(*deepSAD.results['test_scores'])
    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

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

        if dataset_name in ('mnist', 'fmnist'):
            X_all_low = dataset.test_set.data[idx_all_sorted[:32], ...].unsqueeze(1)
            X_all_high = dataset.test_set.data[idx_all_sorted[-32:], ...].unsqueeze(1)
            X_normal_low = dataset.test_set.data[idx_normal_sorted[:32], ...].unsqueeze(1)
            X_normal_high = dataset.test_set.data[idx_normal_sorted[-32:], ...].unsqueeze(1)

        if dataset_name == 'cifar10':
            X_all_low = torch.tensor(np.transpose(dataset.test_set.data[idx_all_sorted[:32], ...], (0,3,1,2)))
            X_all_high = torch.tensor(np.transpose(dataset.test_set.data[idx_all_sorted[-32:], ...], (0,3,1,2)))
            X_normal_low = torch.tensor(np.transpose(dataset.test_set.data[idx_normal_sorted[:32], ...], (0,3,1,2)))
            X_normal_high = torch.tensor(np.transpose(dataset.test_set.data[idx_normal_sorted[-32:], ...], (0,3,1,2)))

        plot_images_grid(X_all_low, export_img=xp_path + '/all_low', padding=2)
        plot_images_grid(X_all_high, export_img=xp_path + '/all_high', padding=2)
        plot_images_grid(X_normal_low, export_img=xp_path + '/normals_low', padding=2)
        plot_images_grid(X_normal_high, export_img=xp_path + '/normals_high', padding=2)
Exemple #10
0
def plot_pics():
    dataset = 'texture'

    with torch.no_grad():

        detected_s = [[],[],[],[],[],[],[],[],[],[]]
        ground_truth_s = [[],[],[],[],[],[],[],[],[],[]]
        reconstruction_s = [[],[],[],[],[],[],[],[],[],[]]

        detected_c = [[], [], [], [], [], [], [], [], [], []]
        ground_truth_c = [[], [], [], [], [], [], [], [], [], []]
        reconstruction_c = [[], [], [], [], [], [], [], [], [], []]

        undetected = [[],[],[],[],[],[],[],[],[],[]]
        undetected_KNN_collection = []
        detected_KNN_collection = []
        for i in range(5,6):
            if i <5:
                dataset = 'texture'
            else:
                dataset = 'object'
            cat = str(i)

            image_train = np.load('../.././log/' + dataset + '/' + cat + '/Images_train.npy')
            image_test = np.load('../.././log/' + dataset + '/' + cat + '/Images.npy')
            image_ground_truth = np.load('../.././log/' + dataset + '/' + cat + '/Ground_truth.npy')


            if i!=5 and i!=7:
                image_train = 1-image_train
                image_test = 1-image_test

            for j in range(10):
                reconstruction_train = np.load('../.././log/' + dataset + '/' + cat + '/Data_Reconstruction_'+str(j)+'_train.npy')
                reconstruction_test = np.load('../.././log/' + dataset + '/' + cat + '/Data_Reconstruction_'+str(j)+'.npy')

                Single_Scores = np.load('../.././log/' + dataset+'/'+cat  + '/Single_Scores_' + str(j) + '.npy')
                Cal_Scores = np.load('../.././log/' + dataset+'/'+cat +   '/Cal_Scores_' + str(j) + '.npy')

                max_s = np.argmax(Single_Scores)
                max_c = np.argmax(Cal_Scores)

                detected_s[j].append(image_test[max_s])
                ground_truth_s[j].append(image_ground_truth[max_s])

                reconstruction_s[j].append(reconstruction_test[max_s])

                detected_c[j].append(image_test[max_c])
                ground_truth_c[j].append(image_ground_truth[max_c])
                reconstruction_c[j].append(reconstruction_test[max_c])
                exit()




                if i != 5 and i != 7:
                    reconstruction_train = 1 - reconstruction_train
                    reconstruction_test = 1 - reconstruction_test

                image_single = np.sum((reconstruction_train[0:19] - image_train[0:19])**2, axis=(1))
                scores_train = compute_local_error_martrix(image_single)
                max_post = np.argmax(scores_train)
                min_post = np.argmin(scores_train)
                good[j].append(image_train[min_post])
                detected[j].append(image_train[max_post])

        good = np.array(good)
        detected = np.array(detected)

        image_samples = good[7]
        for index in range(1):
            image_samples = np.concatenate([image_samples, detected[index]], 0)
        # image_samples = np.transpose(image_samples, [0,2,3,1])

        image_samples = torch.from_numpy(image_samples)

        plot_images_grid(image_samples, export_img='./pictures/Mvtec_normal_abnormal_outlier.eps', nrow=1, padding=2)
Exemple #11
0
    def train(self, deepSVDD, cfg, dataset: BaseADDataset, net: BaseNet):
        logger = logging.getLogger()

        # Set device for network
        net = net.to(self.device)

        # Get train data loader
        train_loader, _ = dataset.loaders(batch_size=self.batch_size,
                                          num_workers=self.n_jobs_dataloader)

        # Set optimizer (Adam optimizer for now)
        optimizer = optim.Adam(net.parameters(),
                               lr=self.lr,
                               weight_decay=self.weight_decay,
                               amsgrad=self.optimizer_name == 'amsgrad')

        # Set learning rate scheduler
        scheduler = optim.lr_scheduler.MultiStepLR(
            optimizer, milestones=self.lr_milestones, gamma=0.1)

        # Training
        logger.info('Starting training...')
        start_time = time.time()
        net.train()
        best_score = 0

        if self.c is None:
            self.c = self.init_center_c(train_loader, net)

        for epoch in range(self.n_epochs):

            scheduler.step()
            if epoch in self.lr_milestones:
                logger.info('  LR scheduler: new learning rate is %g' %
                            float(scheduler.get_lr()[0]))

            loss_epoch = 0.0
            n_batches = 0
            epoch_start_time = time.time()

            for data in tqdm(train_loader):
                inputs, _, _ = data
                inputs = inputs.to(self.device)

                # Zero the network parameter gradients
                optimizer.zero_grad()
                # Update network parameters via backpropagation: forward + backward + optimize
                features, rec_images = net(inputs)
                dist = torch.sum((features - self.c)**2, dim=1)
                rec_loss = torch.mean(
                    torch.sum(torch.abs(rec_images - inputs),
                              dim=tuple(range(1, rec_images.dim()))))
                if self.objective == 'soft-boundary':
                    scores = dist - self.R**2
                    loss = cfg.settings['w_svdd'] * (
                        self.R**2 + (1 / self.nu) *
                        torch.mean(torch.max(torch.zeros_like(scores), scores))
                    ) + cfg.settings['w_rec'] * rec_loss
                else:
                    loss = cfg.settings['w_svdd'] * torch.mean(
                        dist) + cfg.settings['w_rec'] * rec_loss
                loss.backward()
                optimizer.step()

                # Update hypersphere radius R on mini-batch distances
                if (self.objective == 'soft-boundary') and (
                        epoch >= self.warm_up_n_epochs):
                    self.R.data = torch.tensor(get_radius(dist, self.nu),
                                               device=self.device)

                loss_epoch += loss.item()
                n_batches += 1

            # log epoch statistics
            epoch_train_time = time.time() - epoch_start_time
            logger.info('  Epoch {}/{}\t Time: {:.3f}\t Loss: {:.8f}'.format(
                epoch + 1, self.n_epochs, epoch_train_time,
                loss_epoch / n_batches))

            # Test model
            deepSVDD.test(dataset,
                          device=self.device,
                          n_jobs_dataloader=self.n_jobs_dataloader)
            if self.test_auc > best_score:
                # Save results, model, and configuration
                best_score = self.test_auc
                deepSVDD.R = float(self.R.cpu().data.numpy())  # get float
                deepSVDD.c = self.c.cpu().data.numpy().tolist()  # get list
                deepSVDD.save_results(export_json=cfg.settings['xp_path'] +
                                      '/results.json')
                deepSVDD.save_model(export_model=cfg.settings['xp_path'] +
                                    '/model.tar')
                cfg.save_config(export_json=cfg.settings['xp_path'] +
                                '/config.json')

                if cfg.settings['dataset_name'] in ('mnist', 'cifar10'):

                    # Plot most anomalous and most normal (within-class) test samples
                    indices, labels, scores = zip(
                        *deepSVDD.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 cfg.settings['dataset_name'] == 'mnist':
                        X_normals = dataset.test_set.data[idx_sorted[:32],
                                                          ...].unsqueeze(1)
                        X_outliers = dataset.test_set.data[idx_sorted[-32:],
                                                           ...].unsqueeze(1)

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

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

        self.train_time = time.time() - start_time
        logger.info('Training time: %.3f' % self.train_time)

        logger.info('Finished training.')

        return net
Exemple #12
0
def train(dataset: BaseADDataset, ae_net: BaseNet):
    # Set device for network
    ae_net = ae_net.to(device)

    # Get train data loader
    letter, labels = dataset.loaders(batch_size=batch_size,
                                     num_workers=0,
                                     shuffle_test=False,
                                     shuffle_train=False)

    # Set optimizer (Adam optimizer for now)
    optimizer = optim.Adam(ae_net.parameters(),
                           lr=lr,
                           weight_decay=weight_decay)

    # Training
    start_time = time.time()
    ae_net.train()
    for epoch in range(n_epochs):
        loss_epoch = 0.0
        n_batches = 0
        epoch_start_time = time.time()
        for data, label in zip(letter, labels):
            inputs, _ = data
            lab, _ = label
            inputs = inputs.to(device)
            lab = lab.to(device)
            # Zero the network parameter gradients
            optimizer.zero_grad()
            outputs = ae_net(inputs)
            scores = torch.sum((outputs - lab)**2,
                               dim=tuple(range(1, outputs.dim())))
            loss = torch.mean(scores)
            loss.backward()
            optimizer.step()

            loss_epoch += loss.item()
            n_batches += 1
        epoch_end_time = time.time()
        print('Epoch: ' + str(epoch + 1) + '/' + str(n_epochs) + ' time: ' +
              str(epoch_end_time - epoch_start_time) + ' loss: ' +
              str(loss_epoch / n_batches))

    with torch.no_grad():
        plot_images_grid(inputs,
                         export_img='./log/train/input',
                         title='Input ',
                         nrow=4,
                         padding=4)
        plot_images_grid(lab,
                         export_img='./log/train/labbel',
                         title='Label ',
                         nrow=4,
                         padding=4)
        plot_images_grid(outputs,
                         export_img='./log/train/output',
                         title='Output ',
                         nrow=4,
                         padding=4)

    return ae_net
Exemple #13
0
def plot_pics():
    dataset = 'mnist'

    with torch.no_grad():
        detected = [[], [], [], [], []]
        undetected = [[], [], [], [], []]
        undetected_KNN_collection = []
        detected_KNN_collection = []
        for i in range(15):
            cat = str(i)

            image_test = np.load('../.././log/' + dataset + '/' + cat +
                                 '/Images.npy')
            image_ground_truth = np.load('../.././log/' + dataset + '/' + cat +
                                         '/Ground_truth.npy')
            if i != 5 and i != 7:
                image_train = 1 - image_train
                image_test = 1 - image_test

            for j in range(10):
                reconstruction_train = np.load('../.././log/' + dataset + '/' +
                                               cat + '/Data_Reconstruction_' +
                                               str(j) + '_train.npy')
                reconstruction_test = np.load('../.././log/' + dataset + '/' +
                                              cat + '/Data_Reconstruction_' +
                                              str(j) + '.npy')

                if i != 5 and i != 7:
                    reconstruction_train = 1 - reconstruction_train
                    reconstruction_test = 1 - reconstruction_test

                scores_train = np.sum((reconstruction_train - image_train)**2,
                                      axis=(1, 2, 3))
                max_post = np.argmax(scores_train)
                min_post = np.argmin(scores_train)
                good[j].append(image_train[min_post])
                detected[j].append(image_train[max_post])

                labelNormal = Labels * np.sum(
                    (reconstruction_test - image_test)**2, axis=(1, 2, 3))
                labelNormal[labelNormal == 0.0] = max(labelNormal) + 10
                min_post = np.argmin(labelNormal)
                undetected[j].append(image_test[min_post])

            exit(0)
            labelNormal = Labels * scores
            labelNormal[labelNormal == 0.0] = max(labelNormal) + 10
            min_post = np.argmin(labelNormal)
            undetected_KNN_collection.append(image_test[min_post])

            labelNormal = abs(Labels - 1) * scores
            max_post = np.argmax(labelNormal)
            detected_KNN_collection.append(image_test[max_post])

        good = np.array(good)
        detected = np.array(detected)
        undetected = np.array(undetected)
        undetected_KNN_collection = np.array(undetected_KNN_collection)
        detected_KNN_collection = np.array(detected_KNN_collection)

        image_samples = good[4]
        for index in range(5):
            image_samples = np.concatenate([image_samples, detected[index]], 0)
        image_samples = np.concatenate(
            [image_samples, detected_KNN_collection], 0)
        # image_samples = np.transpose(image_samples, [0,2,3,1])

        image_samples = torch.from_numpy(image_samples)

        plot_images_grid(
            image_samples,
            export_img='./pictures/Mnist_normal_abnormal_outlier.eps',
            nrow=10,
            padding=2)
Exemple #14
0
def main(dataset_name, xp_path, data_path, load_config, load_model, seed,
         kernel, kappa, hybrid, load_ae, n_jobs_dataloader, normal_class):
    """
    (Hybrid) SSAD for anomaly detection as in Goernitz et al., Towards Supervised Anomaly Detection, JAIR, 2013.

    :arg DATASET_NAME: Name of the dataset to load.
    :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 paths
    logger.info('Log file is %s.' % log_file)
    logger.info('Data path is %s.' % data_path)
    logger.info('Export path is %s.' % xp_path)

    # Print experimental setup
    logger.info('Dataset: %s' % dataset_name)
    logger.info('Normal class: %d' % normal_class)
    # 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 SSAD configuration
    logger.info('SSAD kernel: %s' % cfg.settings['kernel'])
    logger.info('Kappa-paramerter: %.2f' % cfg.settings['kappa'])
    logger.info('Hybrid model: %s' % cfg.settings['hybrid'])

    # Set seed
    if cfg.settings['seed'] != -1:
        random.seed(cfg.settings['seed'])
        np.random.seed(cfg.settings['seed'])
        co.setseed(cfg.settings['seed'])
        torch.manual_seed(cfg.settings['seed'])
        torch.cuda.manual_seed(cfg.settings['seed'])
        torch.backends.cudnn.deterministic = True
        logger.info('Set seed to %d.' % cfg.settings['seed'])

    # Use 'cpu' as device for SSAD
    device = 'cpu'
    torch.multiprocessing.set_sharing_strategy(
        'file_system')  # fix multiprocessing issue for ubuntu
    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,
                           random_state=np.random.RandomState(
                               cfg.settings['seed']))

    # Initialize SSAD model
    ssad = SSAD(kernel=cfg.settings['kernel'],
                kappa=cfg.settings['kappa'],
                hybrid=cfg.settings['hybrid'])

    # If specified, load model parameters from already trained model
    if load_model:
        ssad.load_model(import_path=load_model, device=device)
        logger.info('Loading model from %s.' % load_model)

    # If specified, load model autoencoder weights for a hybrid approach
    if hybrid and load_ae is not None:
        ssad.load_ae(dataset_name, model_path=load_ae)
        logger.info('Loaded pretrained autoencoder for features from %s.' %
                    load_ae)

    # Train model on dataset
    ssad.train(dataset, device=device, n_jobs_dataloader=n_jobs_dataloader)

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

    # Save results and configuration
    ssad.save_results(export_json=xp_path + '/results.json')
    cfg.save_config(export_json=xp_path + '/config.json')

    # Plot most anomalous and most normal test samples
    indices, labels, scores = zip(*ssad.results['test_scores'])
    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

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

        if dataset_name in ('mnist', 'fmnist'):
            X_all_low = dataset.test_set.data[idx_all_sorted[:32],
                                              ...].unsqueeze(1)
            X_all_high = dataset.test_set.data[idx_all_sorted[-32:],
                                               ...].unsqueeze(1)
            X_normal_low = dataset.test_set.data[idx_normal_sorted[:32],
                                                 ...].unsqueeze(1)
            X_normal_high = dataset.test_set.data[idx_normal_sorted[-32:],
                                                  ...].unsqueeze(1)

        if dataset_name == 'cifar10':
            X_all_low = torch.tensor(
                np.transpose(dataset.test_set.data[idx_all_sorted[:32], ...],
                             (0, 3, 1, 2)))
            X_all_high = torch.tensor(
                np.transpose(dataset.test_set.data[idx_all_sorted[-32:], ...],
                             (0, 3, 1, 2)))
            X_normal_low = torch.tensor(
                np.transpose(
                    dataset.test_set.data[idx_normal_sorted[:32], ...],
                    (0, 3, 1, 2)))
            X_normal_high = torch.tensor(
                np.transpose(
                    dataset.test_set.data[idx_normal_sorted[-32:], ...],
                    (0, 3, 1, 2)))

        plot_images_grid(X_all_low, export_img=xp_path + '/all_low', padding=2)
        plot_images_grid(X_all_high,
                         export_img=xp_path + '/all_high',
                         padding=2)
        plot_images_grid(X_normal_low,
                         export_img=xp_path + '/normals_low',
                         padding=2)
        plot_images_grid(X_normal_high,
                         export_img=xp_path + '/normals_high',
                         padding=2)
Exemple #15
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')