def main(dataset_name, net_name, xp_path, data_path, load_model, objective, nu, device, seed, batch_size, n_jobs_dataloader, normal_class, isize, rep_dim): # Set seed if seed != -1: random.seed(seed) np.random.seed(seed) torch.manual_seed(seed) # Default device to 'cpu' if cuda is not available if not torch.cuda.is_available(): device = 'cpu' # Load data dataset = load_dataset(dataset_name, data_path, normal_class, isize) # Initialize DeepSVDD model and set neural network \phi deep_SVDD = DeepSVDD(objective, nu) deep_SVDD.set_network(net_name, rep_dim) # If specified, load Deep SVDD model (radius R, center c, network weights, and possibly autoencoder weights) deep_SVDD.load_model(model_path=load_model) # Test model deep_SVDD.test(dataset, device=device, n_jobs_dataloader=n_jobs_dataloader, batch_size=batch_size) print(deep_SVDD.results['test_auc']) # Save results, model, and configuration deep_SVDD.save_results(export_json=xp_path + '/results_test.json')
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, 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 main(dataset_name, net_name, xp_path, data_path, load_config, load_model, objective, nu, device, seed, optimizer_name, lr, n_epochs, lr_milestone, batch_size, weight_decay, pretrain, ae_optimizer_name, ae_lr, ae_n_epochs, ae_lr_milestone, ae_batch_size, ae_weight_decay, n_jobs_dataloader, normal_class, save_points_outside_r): """ Deep SVDD, a fully deep method for anomaly detection. :arg DATASET_NAME: Name of the dataset to load. :arg NET_NAME: Name of the neural network to use. :arg XP_PATH: Export path for logging the experiment. :arg DATA_PATH: Root path of data. """ # Get configuration cfg = Config(locals().copy()) # Set up logging logging.basicConfig(level=logging.INFO) logger = logging.getLogger() logger.setLevel(logging.INFO) formatter = logging.Formatter( '%(asctime)s - %(name)s - %(levelname)s - %(message)s') log_file = xp_path + '/log.txt' file_handler = logging.FileHandler(log_file) file_handler.setLevel(logging.INFO) file_handler.setFormatter(formatter) logger.addHandler(file_handler) # Print arguments logger.info('Log file is %s.' % log_file) logger.info('Data path is %s.' % data_path) logger.info('Export path is %s.' % xp_path) logger.info('Dataset: %s' % dataset_name) logger.info('Normal class: %d' % normal_class) logger.info('Network: %s' % net_name) # If specified, load experiment config from JSON-file if load_config: cfg.load_config(import_json=load_config) logger.info('Loaded configuration from %s.' % load_config) # Print configuration logger.info('Deep SVDD objective: %s' % cfg.settings['objective']) logger.info('Nu-paramerter: %.2f' % cfg.settings['nu']) # Set seed if cfg.settings['seed'] != -1: random.seed(cfg.settings['seed']) np.random.seed(cfg.settings['seed']) torch.manual_seed(cfg.settings['seed']) logger.info('Set seed to %d.' % cfg.settings['seed']) # Default device to 'cpu' if cuda is not available if not torch.cuda.is_available(): device = 'cpu' logger.info('Computation device: %s' % device) logger.info('Number of dataloader workers: %d' % n_jobs_dataloader) # Load data dataset = load_dataset(dataset_name, data_path, normal_class) # Initialize DeepSVDD model and set neural network \phi deep_SVDD = DeepSVDD(cfg.settings['objective'], cfg.settings['nu']) deep_SVDD.set_network(net_name) # If specified, load Deep SVDD model (radius R, center c, network weights, and possibly autoencoder weights) if load_model: deep_SVDD.load_model(model_path=load_model, load_ae=False) logger.info('Loading model from %s.' % load_model) logger.info('Pretraining: %s' % pretrain) if pretrain: # Log pretraining details logger.info('Pretraining optimizer: %s' % cfg.settings['ae_optimizer_name']) logger.info('Pretraining learning rate: %g' % cfg.settings['ae_lr']) logger.info('Pretraining epochs: %d' % cfg.settings['ae_n_epochs']) logger.info('Pretraining learning rate scheduler milestones: %s' % (cfg.settings['ae_lr_milestone'], )) logger.info('Pretraining batch size: %d' % cfg.settings['ae_batch_size']) logger.info('Pretraining weight decay: %g' % cfg.settings['ae_weight_decay']) # Pretrain model on dataset (via autoencoder) deep_SVDD.pretrain(dataset, optimizer_name=cfg.settings['ae_optimizer_name'], lr=cfg.settings['ae_lr'], n_epochs=cfg.settings['ae_n_epochs'], lr_milestones=cfg.settings['ae_lr_milestone'], batch_size=cfg.settings['ae_batch_size'], weight_decay=cfg.settings['ae_weight_decay'], device=device, n_jobs_dataloader=n_jobs_dataloader) # Log training details logger.info('Training optimizer: %s' % cfg.settings['optimizer_name']) logger.info('Training learning rate: %g' % cfg.settings['lr']) logger.info('Training epochs: %d' % cfg.settings['n_epochs']) logger.info('Training learning rate scheduler milestones: %s' % (cfg.settings['lr_milestone'], )) logger.info('Training batch size: %d' % cfg.settings['batch_size']) logger.info('Training weight decay: %g' % cfg.settings['weight_decay']) # Train model on dataset deep_SVDD.train(dataset, optimizer_name=cfg.settings['optimizer_name'], lr=cfg.settings['lr'], n_epochs=cfg.settings['n_epochs'], lr_milestones=cfg.settings['lr_milestone'], batch_size=cfg.settings['batch_size'], weight_decay=cfg.settings['weight_decay'], device=device, n_jobs_dataloader=n_jobs_dataloader) if save_points_outside_r: logger.info('Saving points outside of r') deep_SVDD.savePointsOutsideR(dataset, device=device, n_jobs_dataloader=n_jobs_dataloader) # Test model deep_SVDD.test(dataset, device=device, n_jobs_dataloader=n_jobs_dataloader) deep_SVDD.save_results(export_json=xp_path + '/results.json') deep_SVDD.save_model(export_model=xp_path + '/model.tar') cfg.save_config(export_json=xp_path + '/config.json')
def main(dataset_name, net_name, xp_path, data_path, load_config, load_model, objective, nu, device, seed, optimizer_name, lr, n_epochs, lr_milestone, batch_size, weight_decay, pretrain, ae_optimizer_name, ae_lr, ae_n_epochs, ae_lr_milestone, ae_batch_size, ae_weight_decay, n_jobs_dataloader, normal_class, img_name): """ Deep SVDD, a fully deep method for anomaly detection. :arg DATASET_NAME: Name of the dataset to load. :arg NET_NAME: Name of the neural network to use. :arg XP_PATH: Export path for logging the experiment. :arg DATA_PATH: Root path of data. """ # Get configuration cfg = Config(locals().copy()) # Set up logging logging.basicConfig(level=logging.INFO) logger = logging.getLogger() logger.setLevel(logging.INFO) formatter = logging.Formatter( '%(asctime)s - %(name)s - %(levelname)s - %(message)s') log_file = xp_path + '/log.txt' file_handler = logging.FileHandler(log_file) file_handler.setLevel(logging.INFO) file_handler.setFormatter(formatter) logger.addHandler(file_handler) # Current date and time logger.info('Current date and time is %s.' % datetime.now()) # () arguments logger.info('Log file is %s.' % log_file) logger.info('Data path is %s.' % data_path) logger.info('Export path is %s.' % xp_path) logger.info('Dataset: %s' % dataset_name) logger.info('Normal class: %d' % normal_class) logger.info('Network: %s' % net_name) # If specified, load experiment config from JSON-file if load_config: cfg.load_config(import_json=load_config) logger.info('Loaded configuration from %s.' % load_config) # Print configuration logger.info('Deep SVDD objective: %s' % cfg.settings['objective']) logger.info('Nu-parameter: %.2f' % cfg.settings['nu']) # Set seed if cfg.settings['seed'] != -1: random.seed(cfg.settings['seed']) np.random.seed(cfg.settings['seed']) torch.manual_seed(cfg.settings['seed']) logger.info('Set seed to %d.' % cfg.settings['seed']) # Default device to 'cpu' if cuda is not available if not torch.cuda.is_available(): device = 'cpu' logger.info('Computation device: %s' % device) logger.info('Number of dataloader workers: %d' % n_jobs_dataloader) # Load data dataset = load_dataset(dataset_name, data_path, normal_class) # Initialize DeepSVDD model and set neural network \phi deep_SVDD = DeepSVDD(cfg.settings['objective'], cfg.settings['nu']) deep_SVDD.set_network(net_name) # If specified, load Deep SVDD model (radius R, center c, network weights, and possibly autoencoder weights) if load_model: deep_SVDD.load_model(model_path=load_model, load_ae=True) logger.info('Loading model from %s.' % load_model) logger.info('Pretraining: %s' % pretrain) if pretrain: # Log pretraining details logger.info('Pretraining optimizer: %s' % cfg.settings['ae_optimizer_name']) logger.info('Pretraining learning rate: %g' % cfg.settings['ae_lr']) logger.info('Pretraining epochs: %d' % cfg.settings['ae_n_epochs']) logger.info('Pretraining learning rate scheduler milestones: %s' % (cfg.settings['ae_lr_milestone'], )) logger.info('Pretraining batch size: %d' % cfg.settings['ae_batch_size']) logger.info('Pretraining weight decay: %g' % cfg.settings['ae_weight_decay']) # Pretrain model on dataset (via autoencoder) deep_SVDD.pretrain(dataset, optimizer_name=cfg.settings['ae_optimizer_name'], lr=cfg.settings['ae_lr'], n_epochs=cfg.settings['ae_n_epochs'], lr_milestones=cfg.settings['ae_lr_milestone'], batch_size=cfg.settings['ae_batch_size'], weight_decay=cfg.settings['ae_weight_decay'], device=device, n_jobs_dataloader=n_jobs_dataloader) # Log training details logger.info('Training optimizer: %s' % cfg.settings['optimizer_name']) logger.info('Training learning rate: %g' % cfg.settings['lr']) logger.info('Training epochs: %d' % cfg.settings['n_epochs']) logger.info('Training learning rate scheduler milestones: %s' % (cfg.settings['lr_milestone'], )) logger.info('Training batch size: %d' % cfg.settings['batch_size']) logger.info('Training weight decay: %g' % cfg.settings['weight_decay']) # Train model on dataset deep_SVDD.train(dataset, optimizer_name=cfg.settings['optimizer_name'], lr=cfg.settings['lr'], n_epochs=cfg.settings['n_epochs'], lr_milestones=cfg.settings['lr_milestone'], batch_size=cfg.settings['batch_size'], weight_decay=cfg.settings['weight_decay'], device=device, n_jobs_dataloader=n_jobs_dataloader) # Test model deep_SVDD.test(dataset, device=device, n_jobs_dataloader=n_jobs_dataloader) # Plot most anomalous and most normal (within-class) test samples indices, labels, scores = zip(*deep_SVDD.results['test_scores']) indices, labels, scores = np.array(indices), np.array(labels), np.array( scores) idx_all_sorted = indices[np.argsort(scores)] idx_normal_sorted = indices[labels == 0][np.argsort( scores[labels == 0])] # sorted from lowest to highest anomaly score idx_outlier_sorted = indices[labels == 1][np.argsort(scores[labels == 1])] idx_sorted = indices[np.argsort(scores)] test_auc = deep_SVDD.results['test_auc'] if dataset_name in ('mnist', 'cifar10', 'fashion', 'crack', 'crack128'): if dataset_name == 'mnist': X_normals = dataset.test_set.test_data[idx_sorted_normal[:32], ...].unsqueeze(1) X_outliers = dataset.test_set.test_data[idx_sorted_normal[-32:], ...].unsqueeze(1) if dataset_name == 'cifar10': X_normals = torch.tensor( np.transpose( dataset.test_set.test_data[idx_sorted_normal[:32], ...], (0, 3, 1, 2))) X_outliers = torch.tensor( np.transpose( dataset.test_set.test_data[idx_sorted_normal[-32:], ...], (0, 3, 1, 2))) if dataset_name == 'fashion': X_normals = torch.reshape( torch.tensor(dataset.test_set.data[idx_sorted_normal[:32], ...]), (32, 28, 28)).unsqueeze(1) X_outliers = torch.reshape( torch.tensor(dataset.test_set.data[idx_sorted_normal[-32:], ...]), (32, 28, 28)).unsqueeze(1) plot_imgs = True indices, labels, scores = zip( *deep_SVDD.results['test_scores (corner)']) indices, labels, scores = np.array(indices), np.array( labels), np.array(scores) idx_all_sorted = indices[np.argsort( scores)] # from lowest to highest score idx_normal_sorted = indices[labels == 0][np.argsort( scores[labels == 0])] # from lowest to highest score idx_outlier_sorted = indices[labels == 1][np.argsort( scores[labels == 1])] # from lowest to highest score if dataset_name == 'crack': mid = len(idx_all_sorted) / 2 if len(idx_all_sorted) > 64 and len( idx_normal_sorted) > 64 and len(idx_outlier_sorted) > 100: #X_middle = torch.reshape(torch.tensor(dataset.test_set.data[idx_all_sorted[int(mid-312):int(mid+313)], ...]), (625,64,64)).unsqueeze(1) X_all_normal = torch.reshape( torch.tensor( dataset.test_set_corner.data[idx_all_sorted[:64], ...]), (64, 64, 64)).unsqueeze(1) X_all_outlier = torch.reshape( torch.tensor( dataset.test_set_corner.data[idx_all_sorted[-144:], ...]), (144, 64, 64)).unsqueeze(1) X_normals_normal = torch.reshape( torch.tensor( dataset.test_set_corner.data[idx_normal_sorted[:64], ...]), (64, 64, 64)).unsqueeze(1) X_normals_outlier = torch.reshape( torch.tensor( dataset.test_set_corner.data[idx_normal_sorted[-64:], ...]), (64, 64, 64)).unsqueeze(1) X_outliers_normal = torch.reshape( torch.tensor( dataset.test_set_corner.data[idx_outlier_sorted[:100], ...]), (100, 64, 64)).unsqueeze(1) X_outliers_outlier = torch.reshape( torch.tensor( dataset.test_set_corner.data[idx_outlier_sorted[-100:], ...]), (100, 64, 64)).unsqueeze(1) else: plot_imgs = False X_all_normal = torch.reshape( torch.tensor( dataset.test_set_corner.data[idx_all_sorted[:1], ...]), (1, 64, 64)).unsqueeze(1) X_all_outlier = torch.reshape( torch.tensor( dataset.test_set_corner.data[idx_all_sorted[-1:], ...]), (1, 64, 64)).unsqueeze(1) X_normals_normal = torch.reshape( torch.tensor( dataset.test_set_corner.data[idx_normal_sorted[:1], ...]), (1, 64, 64)).unsqueeze(1) X_normals_outlier = torch.reshape( torch.tensor( dataset.test_set_corner.data[idx_normal_sorted[-1:], ...]), (1, 64, 64)).unsqueeze(1) X_outliers_normal = torch.reshape( torch.tensor( dataset.test_set_corner.data[idx_outlier_sorted[:1], ...]), (1, 64, 64)).unsqueeze(1) X_outliers_outlier = torch.reshape( torch.tensor( dataset.test_set_corner.data[idx_outlier_sorted[-1:], ...]), (1, 64, 64)).unsqueeze(1) if dataset_name == 'crack128': mid = len(idx_all_sorted) / 2 if len(idx_all_sorted) > 64 and len( idx_normal_sorted) > 64 and len(idx_outlier_sorted) > 100: #X_middle = torch.reshape(torch.tensor(dataset.test_set.data[idx_all_sorted[int(mid-312):int(mid+313)], ...]), (625,128,128)).unsqueeze(1) X_all_normal = torch.reshape( torch.tensor( dataset.test_set_corner.data[idx_all_sorted[:64], ...]), (64, 128, 128)).unsqueeze(1) X_all_outlier = torch.reshape( torch.tensor( dataset.test_set_corner.data[idx_all_sorted[-144:], ...]), (144, 128, 128)).unsqueeze(1) X_normals_normal = torch.reshape( torch.tensor( dataset.test_set_corner.data[idx_normal_sorted[:64], ...]), (64, 128, 128)).unsqueeze(1) X_normals_outlier = torch.reshape( torch.tensor( dataset.test_set_corner.data[idx_normal_sorted[-64:], ...]), (64, 128, 128)).unsqueeze(1) X_outliers_normal = torch.reshape( torch.tensor( dataset.test_set_corner.data[idx_outlier_sorted[:100], ...]), (100, 128, 128)).unsqueeze(1) X_outliers_outlier = torch.reshape( torch.tensor( dataset.test_set_corner.data[idx_outlier_sorted[-100:], ...]), (100, 128, 128)).unsqueeze(1) else: plot_imgs = False X_all_normal = torch.reshape( torch.tensor( dataset.test_set_corner.data[idx_all_sorted[:1], ...]), (1, 128, 128)).unsqueeze(1) X_all_outlier = torch.reshape( torch.tensor( dataset.test_set_corner.data[idx_all_sorted[-1:], ...]), (1, 128, 128)).unsqueeze(1) X_normals_normal = torch.reshape( torch.tensor( dataset.test_set_corner.data[idx_normal_sorted[:1], ...]), (1, 128, 128)).unsqueeze(1) X_normals_outlier = torch.reshape( torch.tensor( dataset.test_set_corner.data[idx_normal_sorted[-1:], ...]), (1, 128, 128)).unsqueeze(1) X_outliers_normal = torch.reshape( torch.tensor( dataset.test_set_corner.data[idx_outlier_sorted[:1], ...]), (1, 128, 128)).unsqueeze(1) X_outliers_outlier = torch.reshape( torch.tensor( dataset.test_set_corner.data[idx_outlier_sorted[-1:], ...]), (1, 128, 128)).unsqueeze(1) if plot_imgs: #plot_images_grid(X_middle, export_img=xp_path + '/plots/' + img_name + '_all_middle_', title='All samples', padding=2, nrow=25) #plot_images_grid(X_all_normal, export_img=xp_path + '/plots/' + img_name + '_all_low_', title='Least anomalous samples', padding=2, nrow=8) plot_images_grid(X_all_outlier, export_img=xp_path + '/plots/' + img_name + '_all_high_', title='Most anomalous samples', padding=2, nrow=12) #plot_images_grid(X_normals_normal, export_img=xp_path + '/plots/' + img_name + '_normals_low_', title='Least anomalous normal samples', padding=2, nrow=8) plot_images_grid(X_normals_outlier, export_img=xp_path + '/plots/' + img_name + '_normals_high_', title='Most anmalous normal samples', padding=2, nrow=8) plot_images_grid(X_outliers_normal, export_img=xp_path + '/plots/' + img_name + '_outliers_low_', title='Least anomalous anomaly samples', padding=2, nrow=10) plot_images_grid(X_outliers_outlier, export_img=xp_path + '/plots/' + img_name + '_outliers_high_', title='Most anomalous anomaly samples', padding=2, nrow=10) test_auc = deep_SVDD.results['test_auc'] test_auc_corner = deep_SVDD.results['test_auc (corner)'] plot_images_hist( scores[labels == 0], scores[labels == 1], export_img=xp_path + '/plots/' + img_name + '_hist_corner', title= 'Deep SVDD Anomaly scores of normal and crack samples (with corner cracks)', auc=test_auc_corner) indices, labels, scores = zip(*deep_SVDD.results['test_scores']) indices, labels, scores = np.array(indices), np.array( labels), np.array(scores) plot_images_hist( scores[labels == 0], scores[labels == 1], export_img=xp_path + '/plots/' + img_name + '_hist', title='Deep SVDD anomaly scores of normal and crack samples', auc=test_auc) # Save results, model, and configuration deep_SVDD.save_results(export_json=xp_path + '/results.json') deep_SVDD.save_model(export_model=xp_path + '/model.tar') cfg.save_config(export_json=xp_path + '/config.json')
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')
def main(dataset_name, net_name, xp_path, data_path, load_config, load_model, objective, nu, focal_parameter, update_center_epochs, device, seed, optimizer_name, lr, n_epochs, lr_milestone, batch_size, weight_decay, pretrain, ae_optimizer_name, ae_lr, ae_n_epochs, ae_lr_milestone, ae_batch_size, ae_weight_decay, n_jobs_dataloader, normal_class): """ Deep SVDD, a fully deep method for anomaly detection. :arg DATASET_NAME: Name of the dataset to load. :arg NET_NAME: Name of the neural network to use. :arg XP_PATH: Export path for logging the experiment. :arg DATA_PATH: Root path of data. """ # Get configuration cfg = Config(locals().copy()) # Set up logging logging.basicConfig(level=logging.INFO) logger = logging.getLogger() logger.setLevel(logging.INFO) formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s') log_file = xp_path + '/log.txt' file_handler = logging.FileHandler(log_file) file_handler.setLevel(logging.INFO) file_handler.setFormatter(formatter) logger.addHandler(file_handler) # Print arguments logger.info('Log file is %s.' % log_file) logger.info('Data path is %s.' % data_path) logger.info('Export path is %s.' % xp_path) logger.info('Dataset: %s' % dataset_name) logger.info('Normal class: %d' % normal_class) logger.info('Network: %s' % net_name) # If specified, load experiment config from JSON-file if load_config: cfg.load_config(import_json=load_config) logger.info('Loaded configuration from %s.' % load_config) # Print configuration logger.info('Deep SVDD objective: %s' % cfg.settings['objective']) logger.info('Nu-paramerter: %.2f' % cfg.settings['nu']) logger.info('focal_parameter: %.2f' % cfg.settings['focal_parameter']) logger.info('update_center_epochs: %d' % cfg.settings['update_center_epochs']) # Set seed if cfg.settings['seed'] != -1: random.seed(cfg.settings['seed']) os.environ['PYTHONHASHSEED'] = str(seed) np.random.seed(cfg.settings['seed']) torch.manual_seed(cfg.settings['seed']) torch.cuda.manual_seed(cfg.settings['seed']) torch.cuda.manual_seed_all(cfg.settings['seed']) cudnn.benchmark = False torch.backends.cudnn.deterministic = True logger.info('Set seed to %d.' % cfg.settings['seed']) # Default device to 'cpu' if cuda is not available if not torch.cuda.is_available(): device = 'cpu' logger.info('Computation device: %s' % device) logger.info('Number of dataloader workers: %d' % n_jobs_dataloader) # Load data dataset = load_dataset(dataset_name, data_path, normal_class) # Initialize DeepSVDD model and set neural network \phi deep_SVDD = DeepSVDD(cfg.settings['objective'], cfg.settings['nu'], cfg.settings['focal_parameter'], cfg.settings['update_center_epochs']) deep_SVDD.set_network(net_name) # If specified, load Deep SVDD model (radius R, center c, network weights, and possibly autoencoder weights) if load_model: deep_SVDD.load_model(model_path=load_model, load_ae=True) logger.info('Loading model from %s.' % load_model) logger.info('Pretraining: %s' % pretrain) if pretrain: # Log pretraining details logger.info('Pretraining optimizer: %s' % cfg.settings['ae_optimizer_name']) logger.info('Pretraining learning rate: %g' % cfg.settings['ae_lr']) logger.info('Pretraining epochs: %d' % cfg.settings['ae_n_epochs']) logger.info('Pretraining learning rate scheduler milestones: %s' % (cfg.settings['ae_lr_milestone'],)) logger.info('Pretraining batch size: %d' % cfg.settings['ae_batch_size']) logger.info('Pretraining weight decay: %g' % cfg.settings['ae_weight_decay']) # Pretrain model on dataset (via autoencoder) deep_SVDD.pretrain(dataset, optimizer_name=cfg.settings['ae_optimizer_name'], lr=cfg.settings['ae_lr'], n_epochs=cfg.settings['ae_n_epochs'], lr_milestones=cfg.settings['ae_lr_milestone'], batch_size=cfg.settings['ae_batch_size'], weight_decay=cfg.settings['ae_weight_decay'], device=device, n_jobs_dataloader=n_jobs_dataloader) # Log training details logger.info('Training optimizer: %s' % cfg.settings['optimizer_name']) logger.info('Training learning rate: %g' % cfg.settings['lr']) logger.info('Training epochs: %d' % cfg.settings['n_epochs']) logger.info('Training learning rate scheduler milestones: %s' % (cfg.settings['lr_milestone'],)) logger.info('Training batch size: %d' % cfg.settings['batch_size']) logger.info('Training weight decay: %g' % cfg.settings['weight_decay']) # record test AUC after each 100 epoch # f_get_para = open('../log/mnist_test/100_AUC.txt', 'w') # f_get_para.write("\r\n \r\nrecord test AUC each 100 epoch \r\n \r\n \r\n") # f_get_para.close() # # f_get_para = open('../log/mnist_test/get_param.txt', 'w') # f_get_para.write("\r\n \r\nrecord test AUC each very epoch \r\n \r\n \r\n") # f_get_para.close() # Train model on dataset deep_SVDD.train(dataset, optimizer_name=cfg.settings['optimizer_name'], lr=cfg.settings['lr'], n_epochs=cfg.settings['n_epochs'], lr_milestones=cfg.settings['lr_milestone'], batch_size=cfg.settings['batch_size'], weight_decay=cfg.settings['weight_decay'], device=device, n_jobs_dataloader=n_jobs_dataloader) # Test model # deep_SVDD.test(dataset, device=device, n_jobs_dataloader=n_jobs_dataloader) # Plot most anomalous and most normal (within-class) test samples # indices, labels, scores = zip(*deep_SVDD.results['test_scores']) # indices, labels, scores = np.array(indices), np.array(labels), np.array(scores) # idx_sorted = indices[labels == 0][np.argsort(scores[labels == 0])] # sorted from lowest to highest anomaly score # # if dataset_name in ('mnist', 'cifar10'): # # if dataset_name == 'mnist': # X_normals = dataset.test_set.test_data[idx_sorted[:32], ...].unsqueeze(1) # X_outliers = dataset.test_set.test_data[idx_sorted[-32:], ...].unsqueeze(1) # # if dataset_name == 'cifar10': # X_normals = torch.tensor(np.transpose(dataset.test_set.test_data[idx_sorted[:32], ...], (0, 3, 1, 2))) # X_outliers = torch.tensor(np.transpose(dataset.test_set.test_data[idx_sorted[-32:], ...], (0, 3, 1, 2))) # # plot_images_grid(X_normals, export_img=xp_path + '/normals', title='Most normal examples', padding=2) # plot_images_grid(X_outliers, export_img=xp_path + '/outliers', title='Most anomalous examples', padding=2) # # # Save results, model, and configuration # deep_SVDD.save_results(export_json=xp_path + '/results.json') # deep_SVDD.save_model(export_model=xp_path + '/model.tar') # cfg.save_config(export_json=xp_path + '/config.json') # plot curves loss_plot = deep_SVDD.trainer.Loss_list accuracy_plot = deep_SVDD.trainer.Accuracy_list x1 = range(0, n_epochs) y1 = accuracy_plot x2 = range(0, n_epochs) y2 = loss_plot plt.subplot(2, 1, 1) plt.plot(x1, y1, 'o-') plt.title('Class %d vs focal %.2f' % (normal_class, focal_parameter)) plt.ylabel('Test accuracy') plt.subplot(2, 1, 2) plt.plot(x2, y2, '.-') plt.xlabel('Test loss vs. epoches') plt.ylabel('Test loss') plt.savefig("accuracy_loss focal %.2f .jpg" % focal_parameter)
def main(dataset_name, net_name, load_config, load_model, objective, nu, device, seed, optimizer_name, lr, n_epochs, lr_milestone, batch_size, weight_decay, pretrain, ae_optimizer_name, ae_lr, ae_n_epochs, ae_lr_milestone, ae_batch_size, ae_weight_decay, n_jobs_dataloader, ratio, run_times): """ Deep SVDD, a fully deep method for anomaly detection. :arg DATASET_NAME: Name of the dataset to load. :arg NET_NAME: Name of the neural network to use. :arg XP_PATH: Export path for logging the experiment. :arg DATA_PATH: Root path of data. """ class_num = 10 if dataset_name == 'cifar100': class_num = 20 for run_index in range(run_times): #for ratio in [0.05, 0.1, 0.15, 0.2, 0.25]: for i in range(class_num): normal_class = i class_name = get_class_name_from_index(normal_class, dataset_name) os.makedirs(os.path.join(RESULTS_DIR), exist_ok=True) # Get configuration cfg = Config(locals().copy()) # Set up logging logging.basicConfig(level=logging.INFO) logger = logging.getLogger() logger.setLevel(logging.INFO) formatter = logging.Formatter( '%(asctime)s - %(name)s - %(levelname)s - %(message)s') xp_path = RESULTS_DIR log_file = xp_path + '/log.txt' file_handler = logging.FileHandler(log_file) file_handler.setLevel(logging.INFO) file_handler.setFormatter(formatter) logger.addHandler(file_handler) # Print arguments logger.info('Log file is %s.' % log_file) logger.info('Export path is %s.' % xp_path) logger.info('Dataset: %s' % dataset_name) logger.info('Normal class: %d' % normal_class) logger.info('Network: %s' % net_name) # If specified, load experiment config from JSON-file if load_config: cfg.load_config(import_json=load_config) logger.info('Loaded configuration from %s.' % load_config) # Print configuration logger.info('Deep SVDD objective: %s' % cfg.settings['objective']) logger.info('Nu-paramerter: %.2f' % cfg.settings['nu']) # Set seed cfg.settings['seed'] = run_index if cfg.settings['seed'] != -1: random.seed(cfg.settings['seed']) np.random.seed(cfg.settings['seed']) torch.manual_seed(cfg.settings['seed']) logger.info('Set seed to %d.' % cfg.settings['seed']) # Default device to 'cpu' if cuda is not available if not torch.cuda.is_available(): device = 'cpu' logger.info('Computation device: %s' % device) logger.info('Number of dataloader workers: %d' % n_jobs_dataloader) # Load data dataset = load_dataset(dataset_name, normal_class, ratio) # Initialize DeepSVDD model and set neural network \phi deep_SVDD = DeepSVDD(cfg.settings['objective'], cfg.settings['nu']) deep_SVDD.set_network(net_name) # If specified, load Deep SVDD model (radius R, center c, network weights, and possibly autoencoder weights) if load_model: deep_SVDD.load_model(model_path=load_model, load_ae=True) logger.info('Loading model from %s.' % load_model) logger.info('Pretraining: %s' % pretrain) if pretrain: # Log pretraining details logger.info('Pretraining optimizer: %s' % cfg.settings['ae_optimizer_name']) logger.info('Pretraining learning rate: %g' % cfg.settings['ae_lr']) logger.info('Pretraining epochs: %d' % cfg.settings['ae_n_epochs']) logger.info( 'Pretraining learning rate scheduler milestones: %s' % (cfg.settings['ae_lr_milestone'], )) logger.info('Pretraining batch size: %d' % cfg.settings['ae_batch_size']) logger.info('Pretraining weight decay: %g' % cfg.settings['ae_weight_decay']) # Pretrain model on dataset (via autoencoder) deep_SVDD.pretrain( dataset, optimizer_name=cfg.settings['ae_optimizer_name'], lr=cfg.settings['ae_lr'], n_epochs=cfg.settings['ae_n_epochs'], lr_milestones=cfg.settings['ae_lr_milestone'], batch_size=cfg.settings['ae_batch_size'], weight_decay=cfg.settings['ae_weight_decay'], device=device, n_jobs_dataloader=n_jobs_dataloader) # Log training details logger.info('Training optimizer: %s' % cfg.settings['optimizer_name']) logger.info('Training learning rate: %g' % cfg.settings['lr']) logger.info('Training epochs: %d' % cfg.settings['n_epochs']) logger.info('Training learning rate scheduler milestones: %s' % (cfg.settings['lr_milestone'], )) logger.info('Training batch size: %d' % cfg.settings['batch_size']) logger.info('Training weight decay: %g' % cfg.settings['weight_decay']) # Train model on dataset deep_SVDD.train(dataset, optimizer_name=cfg.settings['optimizer_name'], lr=cfg.settings['lr'], n_epochs=cfg.settings['n_epochs'], lr_milestones=cfg.settings['lr_milestone'], batch_size=cfg.settings['batch_size'], weight_decay=cfg.settings['weight_decay'], device=device, n_jobs_dataloader=n_jobs_dataloader) # Test model scores, labels = deep_SVDD.test( dataset, device=device, n_jobs_dataloader=n_jobs_dataloader) res_file_name = '{}_dsvdd-{}_{}_{}.npz'.format( dataset_name, ratio, class_name, datetime.now().strftime('%Y-%m-%d-%H%M')) res_file_path = os.path.join(RESULTS_DIR, dataset_name, res_file_name) os.makedirs(os.path.join(RESULTS_DIR, dataset_name), exist_ok=True) save_roc_pr_curve_data(scores, labels, res_file_path) # Plot most anomalous and most normal (within-class) test samples # indices, labels, scores = zip(*deep_SVDD.results['test_scores']) # indices, labels, scores = np.array(indices), np.array(labels), np.array(scores) # idx_sorted = indices[labels == 0][np.argsort(scores[labels == 0])] # sorted from lowest to highest anomaly score # # if dataset_name in ('mnist', 'cifar10'): # # if dataset_name == 'mnist': # X_normals = dataset.test_set.test_data[idx_sorted[:32], ...].unsqueeze(1) # X_outliers = dataset.test_set.test_data[idx_sorted[-32:], ...].unsqueeze(1) # # if dataset_name == 'cifar10': # X_normals = torch.tensor(np.transpose(dataset.test_set.test_data[idx_sorted[:32], ...], (0, 3, 1, 2))) # X_outliers = torch.tensor(np.transpose(dataset.test_set.test_data[idx_sorted[-32:], ...], (0, 3, 1, 2))) # # plot_images_grid(X_normals, export_img=xp_path + '/normals', title='Most normal examples', padding=2) # plot_images_grid(X_outliers, export_img=xp_path + '/outliers', title='Most anomalous examples', padding=2) # Save results, model, and configuration logger.info('finish class {} training.'.format(class_name)) logger.info('send exp finish mail.') send_mailgun()