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)
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)
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')
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)
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)
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)
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')
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])
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)
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)
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
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
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)
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)
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')