def read_datasets(dataset_dir, output_dir, log_dir): for domain in ['mnist', 'cifar10']: for architecture in ['a', 'b', 'c']: for test_type in ['standard', 'adversarial', 'relu']: final_dataset_path = Path( output_dir) / f'{domain}-{architecture}-{test_type}.zip' if not final_dataset_path.exists(): results_dir = Path( dataset_dir) / test_type / f'{domain}-{architecture}' print('Checking', results_dir) final_dataset = MergedComparisonDataset() for dataset_path in results_dir.iterdir(): dataset_path = dataset_path.with_suffix('.zip') dataset = utils.load_zip(dataset_path) stem = dataset_path.stem log_path = Path( log_dir ) / test_type / f'{domain}-{architecture}' / stem / 'compare.log' if log_path.exists(): with open(log_path, 'r') as f: log = f.readlines() else: log = None add_dataset(final_dataset, dataset, log) final_dataset_path.parent.mkdir(parents=True, exist_ok=True) utils.save_zip(final_dataset, final_dataset_path)
def attack(**kwargs): parsing.set_log_level(kwargs['log_level']) if kwargs['deterministic']: if kwargs['seed'] is None: logger.warning('Determinism is enabled, but no seed has been provided.') utils.enable_determinism() logger.debug('Running attack command with kwargs %s.', kwargs) if kwargs['cpu_threads'] is not None: torch.set_num_threads(kwargs['cpu_threads']) if kwargs['seed'] is not None: utils.set_seed(kwargs['seed']) model = parsing.parse_model(kwargs['domain'], kwargs['architecture'], kwargs['state_dict_path'], False, kwargs['masked_relu'], False, load_weights=True) model.eval() model.to(kwargs['device']) dataset = parsing.parse_dataset(kwargs['domain'], kwargs['dataset'], dataset_edges=(kwargs['start'], kwargs['stop'])) dataloader = torch.utils.data.DataLoader( dataset, kwargs['batch_size'], shuffle=False) attack_config = utils.read_attack_config_file(kwargs['attack_config_file']) attack_pool = parsing.parse_attack_pool( kwargs['attacks'], kwargs['domain'], kwargs['p'], kwargs['attack_type'], model, attack_config, kwargs['device'], seed=kwargs['seed']) p = kwargs['p'] if kwargs['blind_trust']: logger.warning( 'Blind trust is activated. This means that the success of the attack will NOT be checked.') adversarial_dataset = tests.attack_test(model, attack_pool, dataloader, p, kwargs['misclassification_policy'], kwargs['device'], attack_config, kwargs, dataset.start, dataset.stop, None, blind_trust=kwargs['blind_trust']) adversarial_dataset.print_stats() if kwargs['save_to'] is not None: utils.save_zip(adversarial_dataset, kwargs['save_to']) if kwargs['show'] is not None: utils.show_images(adversarial_dataset.genuines, adversarial_dataset.adversarials, limit=kwargs['show'], model=model)
def read_datasets(): for domain in ['mnist', 'cifar10']: for architecture in ['a', 'b', 'c']: for test_type in ['standard', 'adversarial', 'relu']: final_dataset_path = Path( 'final') / f'{domain}-{architecture}-{test_type}.zip' if not final_dataset_path.exists(): results_dir = Path( 'mip_results') / test_type / f'{domain}-{architecture}' print('Checking', results_dir) final_dataset = MergedDataset() for dataset_path in results_dir.iterdir(): dataset_path = dataset_path.with_suffix('.zip') dataset = utils.load_zip(dataset_path) stem = dataset_path.stem memory_log_path = Path( 'logs' ) / test_type / f'{domain}-{architecture}' / stem / 'mip_memory.dat' if memory_log_path.exists(): with open(memory_log_path, 'r') as f: memory_log = f.readlines() memory_log = parse_memory_log(memory_log) else: memory_log = None add_dataset(final_dataset, dataset, memory_log) final_dataset_path.parent.mkdir(parents=True, exist_ok=True) utils.save_zip(final_dataset, final_dataset_path)
def evasion(**kwargs): parsing.set_log_level(kwargs['log_level']) if kwargs['deterministic']: if kwargs['seed'] is None: logger.warning( 'Determinism is enabled, but no seed has been provided.') utils.enable_determinism() if kwargs['cpu_threads'] is not None: torch.set_num_threads(kwargs['cpu_threads']) if kwargs['seed'] is not None: utils.set_seed(kwargs['seed']) model = parsing.parse_model(kwargs['domain'], kwargs['architecture'], kwargs['state_dict_path'], False, kwargs['masked_relu'], False, load_weights=True) model.eval() model.to(kwargs['device']) dataset = parsing.parse_dataset(kwargs['domain'], kwargs['dataset'], dataset_edges=(kwargs['start'], kwargs['stop'])) dataloader = torch.utils.data.DataLoader(dataset, kwargs['batch_size'], shuffle=False) attack_config = utils.read_attack_config_file(kwargs['attack_config_file']) p = kwargs['p'] counter_attack_names = kwargs['counter_attacks'] substitute_state_dict_paths = kwargs['substitute_state_dict_paths'] if kwargs['rejection_threshold'] >= 0: logger.warning( 'Received a positive rejection threshold. Since Counter-Attack only outputs nonpositive values, ' 'the detector will never reject an example.') if len(substitute_state_dict_paths) != len(counter_attack_names): raise click.BadArgumentUsage( 'substitute_state_dict_paths must be as many values as the number of counter attacks.' ) detector = parsing.parse_detector_pool( counter_attack_names, kwargs['domain'], kwargs['p'], 'defense', model, attack_config, kwargs['device'], use_substitute=True, substitute_state_dict_paths=substitute_state_dict_paths) defended_model = detectors.NormalisedDetectorModel( model, detector, kwargs['rejection_threshold']) # TODO: I parametri sono sbagliati evasion_pool = parsing.parse_attack_pool(kwargs['evasion_attacks'], kwargs['domain'], kwargs['p'], 'evasion', model, attack_config, kwargs['device'], defended_model=defended_model, seed=kwargs['seed']) adversarial_dataset = tests.attack_test(model, evasion_pool, dataloader, p, kwargs['misclassification_policy'], kwargs['device'], attack_config, dataset.start, dataset.stop, kwargs, defended_model) adversarial_dataset.print_stats() if kwargs['save_to'] is not None: utils.save_zip(adversarial_dataset, kwargs['save_to']) if kwargs['show'] is not None: utils.show_images(adversarial_dataset.genuines, adversarial_dataset.adversarials, limit=kwargs['show'], model=model)
def compare(**kwargs): parsing.set_log_level(kwargs['log_level']) if kwargs['deterministic']: if kwargs['seed'] is None: logger.warning( 'Determinism is enabled, but no seed has been provided.') utils.enable_determinism() if kwargs['cpu_threads'] is not None: torch.set_num_threads(kwargs['cpu_threads']) if kwargs['seed'] is not None: utils.set_seed(kwargs['seed']) model = parsing.parse_model(kwargs['domain'], kwargs['architecture'], kwargs['state_dict_path'], False, kwargs['masked_relu'], False, load_weights=True) model.eval() if kwargs['indices_path'] is None: indices_override = None else: with open(kwargs['indices_path']) as f: indices_override = json.load(f) dataset = parsing.parse_dataset(kwargs['domain'], kwargs['dataset'], dataset_edges=(kwargs['start'], kwargs['stop']), indices_override=indices_override) dataloader = torch.utils.data.DataLoader(dataset, kwargs['batch_size'], shuffle=False) attack_config = utils.read_attack_config_file(kwargs['attack_config_file']) p = kwargs['p'] device = kwargs['device'] attack_names = kwargs['attacks'] attacks = [] for attack_name in attack_names: attack = parsing.parse_attack(attack_name, kwargs['domain'], p, 'standard', model, attack_config, device, seed=kwargs['seed']) attacks.append(attack) if kwargs['indices_path'] is None: start = kwargs['start'] stop = kwargs['stop'] else: start = None stop = None result_dataset = tests.multiple_attack_test( model, attack_names, attacks, dataloader, p, kwargs['misclassification_policy'], device, attack_config, start, stop, kwargs, indices_override=indices_override) if not kwargs['no_stats']: result_dataset.print_stats() if kwargs['show'] is not None: print() print('Showing top results.') best_results = result_dataset.simulate_pooling(attack_names) utils.show_images(best_results.genuines, best_results.adversarials, limit=kwargs['show'], model=model) for attack_name in attack_names: print(f'Showing results for {attack_name}.') attack_results = result_dataset.simulate_pooling([attack_name]) utils.show_images(attack_results.genuines, attack_results.adversarials, limit=kwargs['show'], model=model) if kwargs['save_to'] is not None: utils.save_zip(result_dataset, kwargs['save_to'])
def mip(**kwargs): command_start_timestamp = time.time() parsing.set_log_level(kwargs['log_level']) if kwargs['deterministic']: logger.warning('Determinism is not guaranteed for Gurobi.') if kwargs['seed'] is None: logger.warning( 'Determinism is enabled, but no seed has been provided.') utils.enable_determinism() if kwargs['cpu_threads'] is not None: torch.set_num_threads(kwargs['cpu_threads']) seed = kwargs['seed'] if seed is not None: utils.set_seed(kwargs['seed']) torch_model_retrieval_start_timestamp = time.time() model = parsing.parse_model(kwargs['domain'], kwargs['architecture'], kwargs['state_dict_path'], False, kwargs['masked_relu'], False, load_weights=True) model.eval() dataset_retrieval_start_timestamp = torch_model_retrieval_end_timestamp = time.time( ) dataset = parsing.parse_dataset(kwargs['domain'], kwargs['dataset'], dataset_edges=(kwargs['start'], kwargs['stop'])) dataset_retrieval_end_timestamp = time.time() dataloader = torch.utils.data.DataLoader(dataset, kwargs['batch_size'], shuffle=False) if kwargs['pre_adversarial_dataset'] is None: pre_adversarial_dataset = None else: pre_adversarial_dataset = utils.load_zip( kwargs['pre_adversarial_dataset']) if isinstance(pre_adversarial_dataset, adversarial_dataset.AttackComparisonDataset): # Use the best results to compute an adversarial dataset pre_adversarial_dataset = pre_adversarial_dataset.to_adversarial_dataset( pre_adversarial_dataset.attack_names) p = kwargs['p'] if p == 2: metric = 'l2' elif np.isposinf(p): metric = 'linf' else: raise NotImplementedError(f'Unsupported metric "l{p}"') attack_config = utils.read_attack_config_file(kwargs['attack_config_file']) attack_kwargs = attack_config.get_arguments('mip', kwargs['domain'], metric, 'standard') attack_creation_start_timestamp = time.time() attack = attacks.MIPAttack(model, p, False, seed=seed, **attack_kwargs) attack_creation_end_timestamp = time.time() mip_dataset = tests.mip_test( model, attack, dataloader, p, kwargs['misclassification_policy'], kwargs['device'], attack_config, kwargs, start=dataset.start, stop=dataset.stop, pre_adversarial_dataset=pre_adversarial_dataset, gurobi_log_dir=kwargs['gurobi_log_dir']) mip_dataset.print_stats() command_end_timestamp = time.time() mip_dataset.global_extra_info['times']['command'] = { 'start_timestamp': command_start_timestamp, 'end_timestamp': command_end_timestamp } mip_dataset.global_extra_info['times']['torch_model_retrieval'] = { 'start_timestamp': torch_model_retrieval_start_timestamp, 'end_timestamp': torch_model_retrieval_end_timestamp } mip_dataset.global_extra_info['times']['dataset_retrieval'] = { 'start_timestamp': dataset_retrieval_start_timestamp, 'end_timestamp': dataset_retrieval_end_timestamp } mip_dataset.global_extra_info['times']['attack_creation'] = { 'start_timestamp': attack_creation_start_timestamp, 'end_timestamp': attack_creation_end_timestamp } if kwargs['save_to'] is not None: utils.save_zip(mip_dataset, kwargs['save_to']) if kwargs['show'] is not None: utils.show_images(mip_dataset.genuines, mip_dataset.adversarials, limit=kwargs['show'], model=model)
def cross_validation(**kwargs): parsing.set_log_level(kwargs['log_level']) if kwargs['deterministic']: if kwargs['seed'] is None: logger.warning( 'Determinism is enabled, but no seed has been provided.') utils.enable_determinism() if kwargs['cpu_threads'] is not None: torch.set_num_threads(kwargs['cpu_threads']) if kwargs['seed'] is not None: utils.set_seed(kwargs['seed']) model = parsing.parse_model(kwargs['domain'], kwargs['architecture'], kwargs['state_dict_path'], False, kwargs['masked_relu'], False, load_weights=True) model.eval() model.to(kwargs['device']) dataset = parsing.parse_dataset(kwargs['domain'], kwargs['dataset'], dataset_edges=(kwargs['start'], kwargs['stop'])) dataloader = torch.utils.data.DataLoader(dataset, kwargs['batch_size'], shuffle=False) attack_config = utils.read_attack_config_file(kwargs['attack_config_file']) p = kwargs['p'] attack_names = kwargs['attacks'] rejection_thresholds = kwargs['rejection_thresholds'] substitute_state_dict_paths = kwargs['substitute_state_dict_paths'] if len(attack_names) < 2: raise click.BadArgumentUsage('attacks must be at least two.') if len(rejection_thresholds) == 1: rejection_thresholds = len(attack_names) * [rejection_thresholds[0]] if len(rejection_thresholds) != len(attack_names): raise click.BadArgumentUsage( 'rejection_thresholds must be either one value or as many values as the number of attacks.' ) if len(substitute_state_dict_paths) != len(attack_names): raise click.BadArgumentUsage( 'substitute_state_dict_paths must be as many values as the number of attacks.' ) if any(rejection_threshold > 0 for rejection_threshold in rejection_thresholds): logger.warning( 'Received a positive rejection threshold. Since Counter-Attack only outputs nonpositive values, ' 'the detector will never reject an example.') test_names = [] evasion_attacks = [] defended_models = [] for i in range(len(attack_names)): # Remove one attack from the pool. This attack will act as the evasion attack evasion_attack_name = attack_names[i] counter_attack_names = [ x for j, x in enumerate(attack_names) if j != i ] ca_substitute_state_dict_paths = [ x for j, x in enumerate(substitute_state_dict_paths) if j != i ] rejection_threshold = rejection_thresholds[i] detector = parsing.parse_detector_pool( counter_attack_names, kwargs['domain'], kwargs['p'], 'standard', model, attack_config, kwargs['device'], use_substitute=True, substitute_state_dict_paths=ca_substitute_state_dict_paths) defended_model = detectors.NormalisedDetectorModel( model, detector, rejection_threshold) evasion_attack = parsing.parse_attack(evasion_attack_name, kwargs['domain'], kwargs['p'], 'evasion', model, attack_config, kwargs['device'], defended_model=defended_model, seed=kwargs['seed']) test_name = f'{evasion_attack_name} vs {counter_attack_names}' test_names.append(test_name) evasion_attacks.append(evasion_attack) defended_models.append(defended_model) logger.info('Tests:\n{}'.format('\n'.join(test_names))) evasion_dataset = tests.multiple_evasion_test( model, test_names, evasion_attacks, defended_models, dataloader, p, kwargs['misclassification_policy'], kwargs['device'], attack_config, dataset.start, dataset.stop, kwargs) if kwargs['save_to'] is not None: utils.save_zip(evasion_dataset, kwargs['save_to']) for test_name in test_names: print(f'Test "{test_name}":') adversarial_dataset = evasion_dataset.to_adversarial_dataset(test_name) adversarial_dataset.print_stats() if kwargs['show'] is not None: utils.show_images(adversarial_dataset.genuines, adversarial_dataset.adversarials, limit=kwargs['show'], model=model)
def distance_dataset(**kwargs): parsing.set_log_level(kwargs['log_level']) if kwargs['deterministic']: if kwargs['seed'] is None: logger.warning( 'Determinism is enabled, but no seed has been provided.') utils.enable_determinism() if kwargs['cpu_threads'] is not None: torch.set_num_threads(kwargs['cpu_threads']) if kwargs['seed'] is not None: utils.set_seed(kwargs['seed']) model = parsing.parse_model(kwargs['domain'], kwargs['architecture'], kwargs['state_dict_path'], False, kwargs['masked_relu'], False, load_weights=True) model.eval() model.to(kwargs['device']) attack_config = utils.read_attack_config_file(kwargs['attack_config_file']) attack_pool = parsing.parse_attack_pool(kwargs['attacks'], kwargs['domain'], kwargs['p'], 'standard', model, attack_config, kwargs['device'], seed=kwargs['seed']) p = kwargs['p'] if kwargs['from_genuine'] is None and kwargs['from_adversarial'] is None: raise RuntimeError( 'At least one among --from-genuine and --from-adversarial must be provided.' ) images = [] distances = [] if kwargs['from_genuine'] is not None: genuine_dataset = parsing.parse_dataset(kwargs['domain'], kwargs['from_genuine'], dataset_edges=(kwargs['start'], kwargs['stop'])) genuine_loader = torch.utils.data.DataLoader(genuine_dataset, kwargs['batch_size'], shuffle=False) # TODO: I parametri sono tutti sbagliati genuine_result_dataset = tests.attack_test( model, attack_pool, genuine_loader, p, kwargs['misclassification_policy'], kwargs['device'], attack_config, genuine_dataset.start, genuine_dataset.stop, kwargs, None) images += list(genuine_result_dataset.genuines) distances += list(genuine_result_dataset.distances) if kwargs['from_adversarial'] is not None: adversarial_dataset = parsing.parse_dataset( kwargs['domain'], kwargs['from_adversarial'], allow_standard=False, dataset_edges=(kwargs['start'], kwargs['stop'])) adv_start, adv_stop = adversarial_dataset.start, adversarial_dataset.stop # Get the labels for the adversarial samples adversarial_dataset = utils.create_label_dataset( model, adversarial_dataset.adversarials, kwargs['batch_size']) adversarial_loader = torch.utils.data.DataLoader(adversarial_dataset, kwargs['batch_size'], shuffle=False) # TODO: I parametri sono sbagliati adversarial_result_dataset = tests.attack_test( model, attack_pool, adversarial_loader, p, False, kwargs['device'], attack_config, adv_start, adv_stop, kwargs, None) images += list(adversarial_result_dataset.genuines) distances += list(adversarial_result_dataset.distances) images = torch.stack(images) distances = torch.stack(distances) final_dataset = ad.AdversarialDistanceDataset(images, distances) utils.save_zip(final_dataset, kwargs['save_to'])