def __init__(self, args=None): """ Initialize. :param args: optional arguments if not to use sys.argv :type args: [str] """ super(TrainDecoderClassifierAugmented, self).__init__(args) self.train_statistics = numpy.zeros((0, 8)) self.test_statistics = numpy.zeros((0, 7))
def attack(self): """ Test the model. """ assert self.model is not None assert self.model.classifier.training is False #assert self.model.decoder.training is False batch_size = 1 objective = self.objective_class() num_batches = int(math.ceil(self.args.max_samples / batch_size)) self.data = numpy.zeros((self.args.max_samples, 200, 2)) for i in range(num_batches): i_start = i * batch_size i_end = min((i + 1) * batch_size, self.args.max_samples) batch_classes = common.torch.as_variable( self.test_codes[i_start:i_end], self.args.use_gpu) batch_theta = common.torch.as_variable( numpy.zeros((batch_size, self.args.latent_space_size), dtype=numpy.float32), self.args.use_gpu) objective = self.objective_class() self.model.decoder.set_code(batch_classes) reference_logits = self.model.forward(batch_theta) attack = self.setup_attack(batch_theta, batch_classes) success, perturbations, _, _, _ = attack.run(objective) steps = numpy.linspace(-1, 5, 200) log('[Visualization] %d class=%d, predicted=%d' % (i, batch_classes[0], torch.max(reference_logits, dim=1)[1])) log('[Visualization] %d success=%d' % (i, success[0])) for s in range(len(steps)): step = steps[s] batch_theta = common.torch.as_variable( numpy.expand_dims(step * perturbations[0].astype(numpy.float32), axis=0), self.args.use_gpu) output_images = self.model.decoder(batch_theta) output_logits = self.model.classifier(output_images) f = objective.f(output_logits, reference_logits, batch_classes) #from matplotlib import pyplot #pyplot.imshow(output_images[0, 0].cpu().detach().numpy()) #pyplot.show() self.data[i, s, 0] = batch_theta[:, 5] self.data[i, s, 1] = f.item() log('[Visualization] %d step=%g, f=%g' % (i, step, f))
def __init__(self, args=None): """ Initialize. :param args: optional arguments if not to use sys.argv :type args: [str] """ super(TrainLearnedDecoderClassifierAdversarially2, self).__init__(args) self.train_statistics = numpy.zeros((0, 16)) self.test_statistics = numpy.zeros((0, 15))
def attack(self): """ Test the model. """ assert self.model is not None assert self.model.classifier.training is False #assert self.model.decoder.training is False batch_size = 1 objective = self.objective_class() num_batches = int(math.ceil(self.args.max_samples / batch_size)) self.data = numpy.zeros((self.args.max_samples, 200, 2)) for i in range(num_batches): i_start = i * batch_size i_end = min((i + 1) * batch_size, self.args.max_samples) batch_classes = common.torch.as_variable( self.test_codes[i_start:i_end], self.args.use_gpu) batch_images = common.torch.as_variable( numpy.expand_dims(self.test_images[i_start:i_end], axis=0), self.args.use_gpu) batch_theta = common.torch.as_variable( numpy.zeros( (batch_size, self.args.N_theta)).astype(numpy.float32), self.args.use_gpu) objective = self.objective_class() self.model.decoder.set_image(batch_images) reference_logits = self.model.forward(batch_theta) log('[Visualization] %d class=%d, predicted=%d' % (i, batch_classes[0], torch.max(reference_logits, dim=1)[1])) rotations = numpy.linspace(self.min_bound[5], self.max_bound[5], 200) for r in range(len(rotations)): rotation = rotations[r] batch_theta[:, 5] = rotation output_images = self.model.decoder(batch_theta) output_logits = self.model.classifier(output_images) f = objective.f(output_logits, reference_logits, batch_classes) #from matplotlib import pyplot #pyplot.imshow(output_images[0, 0].cpu().numpy()) #pyplot.show() self.data[i, r, 0] = batch_theta[:, 5] self.data[i, r, 1] = f.item() log('[Visualization] %d rotation=%g, f=%g' % (i, rotation, f))
def __init__(self, args=None): """ Initialize. :param args: optional arguments if not to use sys.argv :type args: [str] """ super(TrainClassifierAdversarially, self).__init__(args) self.train_statistics = numpy.zeros((0, 11)) self.test_statistics = numpy.zeros((0, 10)) self.attack_class = None """ (attacks.UntargetedAttack) Attack to use (as class). """ self.objective_class = None """ (attacks.UntargetedObjective) Objective to use (as class). """ self.norm = None """ (float) Attack norm for data augmentation. """
def __init__(self, args=None): """ Initialize. :param args: optional arguments if not to use sys.argv :type args: [str] """ super(TrainLearnedDecoderClassifierAdversarially, self).__init__(args) self.train_statistics = numpy.zeros((0, 11)) self.test_statistics = numpy.zeros((0, 10)) self.train_theta = None """ (numpy.ndarray) Training transformation parameters. """ self.test_theta = None """ (numpy.ndarray) Testing transformation parameters. """ self.decoder = None """ (Decoder) Decoder. """ self.decoder_classifier = None """ (DecoderClassifier) Model to attack. """
def test(self): """ Test classifier to identify valid samples to attack. """ num_batches = int( math.ceil(self.test_images.shape[0] / self.args.batch_size)) for b in range(num_batches): b_start = b * self.args.batch_size b_end = min((b + 1) * self.args.batch_size, self.test_images.shape[0]) batch_classes = common.torch.as_variable( self.test_codes[b_start:b_end], self.args.use_gpu) batch_images = common.torch.as_variable( self.test_images[b_start:b_end], self.args.use_gpu) batch_images = batch_images.permute(0, 3, 1, 2) batch_theta = common.torch.as_variable( numpy.zeros((b_end - b_start, self.args.N_theta), dtype=numpy.float32), self.args.use_gpu) if self.args.N_theta > 4: batch_theta[:, 4] = 1 self.model.decoder.set_image(batch_images) output_classes = self.model(batch_theta) values, indices = torch.max(torch.nn.functional.softmax( output_classes, dim=1), dim=1) errors = torch.abs(indices - batch_classes) self.accuracy = common.numpy.concatenate(self.accuracy, errors.data.cpu().numpy()) if b % 100 == 0: log('[Attack] computing accuracy %d' % b) self.accuracy = self.accuracy == 0 utils.write_hdf5(self.args.accuracy_file, self.accuracy) log('[Attack] wrote %s' % self.args.accuracy_file) accuracy = numpy.sum(self.accuracy) / float(self.accuracy.shape[0]) log('[Attack] accuracy %g' % accuracy) accuracy = numpy.sum(self.accuracy[:self.args.max_samples]) / float( self.args.max_samples) log('[Attack] accuracy on %d samples %g' % (self.args.max_samples, accuracy))
def compute_local_pca(self): """ Compute PCA. """ success = numpy.logical_and(self.success >= 0, self.accuracy) log('[Detection] %d valid attacked samples' % numpy.sum(success)) nearest_neighbor_images = self.nearest_neighbor_images.reshape(self.nearest_neighbor_images.shape[0], -1) nearest_neighbor_images = nearest_neighbor_images[:self.args.n_fit] perturbations = self.perturbations.reshape(self.perturbations.shape[0], -1) test_images = self.test_images.reshape(self.test_images.shape[0], -1) pure_perturbations = perturbations - test_images nearest_neighbors_indices = self.compute_nearest_neighbors(perturbations) self.distances['true'] = numpy.zeros((success.shape[0])) self.distances['test'] = numpy.zeros((success.shape[0])) self.distances['perturbation'] = numpy.zeros((success.shape[0])) self.angles['true'] = numpy.zeros((success.shape[0])) self.angles['test'] = numpy.zeros((success.shape[0])) self.angles['perturbation'] = numpy.zeros((success.shape[0])) for n in range(pure_perturbations.shape[0]): if success[n]: nearest_neighbors = nearest_neighbor_images[nearest_neighbors_indices[n, :]] nearest_neighbors = numpy.concatenate((nearest_neighbors, test_images[n].reshape(1, -1)), axis=0) pca = sklearn.decomposition.IncrementalPCA(n_components=self.args.n_pca) pca.fit(nearest_neighbors) reconstructed_test_images = pca.inverse_transform(pca.transform(test_images[n].reshape(1, -1))) reconstructed_perturbations = pca.inverse_transform(pca.transform(perturbations[n].reshape(1, -1))) reconstructed_pure_perturbations = pca.inverse_transform(pca.transform(pure_perturbations[n].reshape(1, -1))) self.distances['test'][n] = numpy.average(numpy.multiply(reconstructed_test_images - test_images[n], reconstructed_test_images - test_images[n]), axis=1) self.distances['perturbation'][n] = numpy.average(numpy.multiply(reconstructed_perturbations - perturbations[n], reconstructed_perturbations - perturbations[n]), axis=1) self.distances['true'][n] = numpy.average(numpy.multiply(reconstructed_pure_perturbations - pure_perturbations[n], reconstructed_pure_perturbations - pure_perturbations[n]), axis=1) self.angles['test'][n] = numpy.rad2deg(common.numpy.angles(reconstructed_test_images.T, test_images[n].T)) self.angles['perturbation'][n] = numpy.rad2deg(common.numpy.angles(reconstructed_perturbations.T, perturbations[n].T)) self.angles['true'][n] = numpy.rad2deg(common.numpy.angles(reconstructed_pure_perturbations.T, pure_perturbations[n].T)) log('[Detection] %d: true distance=%g angle=%g' % (n, self.distances['true'][n], self.angles['true'][n])) log('[Detection] %d: perturbation distance=%g angle=%g' % (n, self.distances['perturbation'][n], self.angles['perturbation'][n])) log('[Detection] %d: test distance=%g angle=%g' % (n, self.distances['test'][n], self.angles['test'][n])) self.distances['test'] = self.distances['test'][success] self.distances['perturbation'] = self.distances['perturbation'][success] self.distances['true'] = self.distances['true'][success]
def compute_statistics(self): """ Compute statistics based on distances. """ num_attempts = self.perturbations.shape[0] perturbations = numpy.swapaxes(self.perturbations, 0, 1) perturbations = perturbations.reshape( (perturbations.shape[0] * perturbations.shape[1], perturbations.shape[2])) success = numpy.swapaxes(self.success, 0, 1) success = success.reshape((success.shape[0] * success.shape[1])) probabilities = numpy.swapaxes(self.probabilities, 0, 1) probabilities = probabilities.reshape( (probabilities.shape[0] * probabilities.shape[1], -1)) confidences = numpy.max(probabilities, 1) perturbation_probabilities = self.test_probabilities[:self.success. shape[1]] perturbation_probabilities = numpy.repeat(perturbation_probabilities, num_attempts, axis=0) perturbation_confidences = numpy.max(perturbation_probabilities, 1) probability_ratios = confidences / perturbation_confidences raw_overall_success = success >= 0 log('[Testing] %d valid attacks' % numpy.sum(raw_overall_success)) # For off-manifold attacks this should not happen, but save is save. if not numpy.any(raw_overall_success): for type in [ 'raw_success', 'raw_iteration', 'raw_roc', 'raw_confidence_weighted_success', 'raw_confidence', 'raw_ratios' ]: self.results[type] = 0 if self.args.results_file: utils.write_pickle(self.args.results_file, self.results) log('[Testing] wrote %s' % self.args.results_file) log('[Testing] no successful attacks found, no plots') return # # We compute some simple statistics: # - raw success rate: fraction of successful attack without considering epsilon # - corrected success rate: fraction of successful attacks within epsilon-ball # - raw average perturbation: average distance to original samples (for successful attacks) # - corrected average perturbation: average distance to original samples for perturbations # within epsilon-ball (for successful attacks). # These statistics can also be computed per class. # And these statistics are computed with respect to three norms. if self.args.plot_directory and utils.display(): iterations = success[raw_overall_success] x = numpy.arange(numpy.max(iterations) + 1) y = numpy.bincount(iterations) plot_file = os.path.join(self.args.plot_directory, 'iterations') plot.bar(plot_file, x, y, title='Distribution of Iterations of Successful Attacks', xlabel='Number of Iterations', ylabel='Count') log('[Testing] wrote %s' % plot_file) plot_file = os.path.join(self.args.plot_directory, 'probabilities') plot.histogram(plot_file, confidences[raw_overall_success], 50) log('[Testing] wrote %s' % plot_file) plot_file = os.path.join(self.args.plot_directory, 'probability_ratios') plot.histogram(plot_file, probability_ratios, 50) log('[Testing] wrote %s' % plot_file) plot_file = os.path.join(self.args.plot_directory, 'test_probabilities') plot.histogram( plot_file, self.test_probabilities[ numpy.arange(self.test_probabilities.shape[0]), self.test_codes], 50) log('[Testing] wrote %s' % plot_file) y_true = numpy.concatenate( (numpy.zeros(confidences.shape[0]), numpy.ones(perturbation_confidences.shape[0]))) y_score = numpy.concatenate((confidences, perturbation_confidences)) roc_auc_score = sklearn.metrics.roc_auc_score(y_true, y_score) self.results['raw_roc'] = roc_auc_score self.results['raw_confidence_weighted_success'] = numpy.sum( confidences[raw_overall_success]) / numpy.sum( perturbation_confidences) self.results['raw_confidence'] = numpy.mean( probabilities[raw_overall_success]) self.results['raw_ratios'] = numpy.mean( probability_ratios[raw_overall_success]) self.results['raw_success'] = numpy.sum( raw_overall_success) / success.shape[0] self.results['raw_iteration'] = numpy.average( success[raw_overall_success]) if self.args.results_file: utils.write_pickle(self.args.results_file, self.results) log('[Testing] wrote %s' % self.args.results_file)
def compute_statistics(self): """ Compute statistics based on distances. """ # That's the basis for all computation as we only want to consider successful attacks # on test samples that were correctly classified. raw_overall_success = numpy.logical_and(self.success >= 0, self.accuracy) # Important check, for on-manifold attack this will happen if the manifold is small and the model very accurate! if not numpy.any(raw_overall_success): for n in range(len(self.norms)): for type in ['raw_success', 'raw_iteration', 'raw_average', 'raw_image']: self.results[n][type] = 0 for type in ['raw_class_success', 'raw_class_average', 'raw_class_image']: self.results[n][type] = numpy.zeros((self.N_class)) if self.args.results_file: utils.write_pickle(self.args.results_file, self.results) log('[Testing] wrote %s' % self.args.results_file) return # # Compute nearest neighbor statistics in image space. # if self.args.plot_directory and self.args.plot_manifolds and utils.display(): log('[Testing] computing nearest neighbor ...') nearest_neighbors_indices = self.compute_nearest_neighbors(self.perturbation_images[raw_overall_success]) pure_perturbations = self.test_images[raw_overall_success] - self.perturbation_images[raw_overall_success] pure_perturbations_norm = numpy.linalg.norm(pure_perturbations, ord=2, axis=1) for k in range(10): direction = self.perturbation_images[raw_overall_success] - self.train_images[nearest_neighbors_indices[:, k]] direction_norm = numpy.linalg.norm(direction, ord=2, axis=1) dot_products = numpy.einsum('ij,ij->i', direction, pure_perturbations) dot_product_norms = numpy.multiply(pure_perturbations_norm, direction_norm) dot_products, dot_product_norms = dot_products[dot_product_norms > 10**-8], dot_product_norms[dot_product_norms > 10**-8] dot_products /= dot_product_norms dot_products = numpy.degrees(numpy.arccos(dot_products)) # matplotlib's hsitogram plots give weird error if there are NaN values, so simple check: if dot_products.shape[0] > 0 and not numpy.any(dot_products != dot_products): plot_file = os.path.join(self.args.plot_directory, 'dot_products_nn%d' % k) plot.histogram(plot_file, dot_products, 100, xmin=numpy.min(dot_products), xmax=numpy.max(dot_products), title='Dot Products Between Adversarial Perturbations and Direction to Nearest Neighbor %d' % k, xlabel='Dot Product', ylabel='Count') log('[Testing] wrote %s' % plot_file) # # We compute some simple statistics: # - raw success rate: fraction of successful attack without considering epsilon # - corrected success rate: fraction of successful attacks within epsilon-ball # - raw average perturbation: average distance to original samples (for successful attacks) # - corrected average perturbation: average distance to original samples for perturbations # within epsilon-ball (for successful attacks). # These statistics can also be computed per class. # And these statistics are computed with respect to three norms. if self.args.plot_directory and utils.display(): iterations = self.success[raw_overall_success] x = numpy.arange(numpy.max(iterations) + 1) y = numpy.bincount(iterations) plot_file = os.path.join(self.args.plot_directory, 'iterations') plot.bar(plot_file, x, y, title='Distribution of Iterations of Successful Attacks', xlabel='Number of Iterations', ylabel='Count') log('[Testing] wrote %s' % plot_file) reference_perturbations = numpy.zeros(self.perturbations.shape) if self.args.N_theta > 4: reference_perturbations[:, 4] = 1 for n in range(len(self.norms)): norm = self.norms[n] delta = numpy.linalg.norm(self.perturbations - reference_perturbations, norm, axis=1) image_delta = numpy.linalg.norm(self.test_images - self.perturbation_images, norm, axis=1) if self.args.plot_directory and utils.display(): plot_file = os.path.join(self.args.plot_directory, 'distances_l%g' % norm) plot.histogram(plot_file, delta[raw_overall_success], 50, title='Distribution of $L_{%g}$ Distances of Successful Attacks' % norm, xlabel='Distance', ylabel='Count') log('[Testing] wrote %s' % plot_file) debug_accuracy = numpy.sum(self.accuracy) / self.accuracy.shape[0] debug_attack_fraction = numpy.sum(raw_overall_success) / numpy.sum(self.success >= 0) debug_test_fraction = numpy.sum(raw_overall_success) / numpy.sum(self.accuracy) log('[Testing] attacked mode accuracy: %g' % debug_accuracy) log('[Testing] only %g of successful attacks are valid' % debug_attack_fraction) log('[Testing] only %g of correct samples are successfully attacked' % debug_test_fraction) N_accuracy = numpy.sum(self.accuracy) self.results[n]['raw_success'] = numpy.sum(raw_overall_success) / N_accuracy self.results[n]['raw_iteration'] = numpy.average(self.success[raw_overall_success]) self.results[n]['raw_average'] = numpy.average(delta[raw_overall_success]) if numpy.any(raw_overall_success) else 0 self.results[n]['raw_image'] = numpy.average(image_delta[raw_overall_success]) if numpy.any(raw_overall_success) else 0 raw_class_success = numpy.zeros((self.N_class, self.perturbation_codes.shape[0]), bool) corrected_class_success = numpy.zeros((self.N_class, self.perturbation_codes.shape[0]), bool) self.results[n]['raw_class_success'] = numpy.zeros((self.N_class)) self.results[n]['raw_class_average'] = numpy.zeros((self.N_class)) self.results[n]['raw_class_image'] = numpy.zeros((self.N_class)) for c in range(self.N_class): N_samples = numpy.sum(self.accuracy[self.perturbation_codes == c].astype(int)) if N_samples <= 0: continue; raw_class_success[c] = numpy.logical_and(raw_overall_success, self.perturbation_codes == c) self.results[n]['raw_class_success'][c] = numpy.sum(raw_class_success[c]) / N_samples if numpy.any(raw_class_success[c]): self.results[n]['raw_class_average'][c] = numpy.average(delta[raw_class_success[c].astype(bool)]) if numpy.any(corrected_class_success[c]): self.results[n]['raw_class_image'][c] = numpy.average(image_delta[raw_class_success[c].astype(bool)]) if self.args.results_file: utils.write_pickle(self.args.results_file, self.results) log('[Testing] wrote %s' % self.args.results_file)
for step_name in step_names: for instance_name in instance_names: permanent_deformation, node_labels, _ = read_field_from_odb( 'U', results_odb_filename, step_name='gravity', instance_name=instance_name, set_name='BALLAST', get_position_numbers=True, position=NODAL) permanent_deformation *= 0 results_odb = odbAccess.openOdb(results_odb_filename, readOnly=True) instance = results_odb.rootAssembly.instances[instance_name] up = np.zeros(len(instance.nodes) * 3) bc_dofs = [] for bc in boundary_conditions: set_nodes = [] if bc.type == 'surface': base = results_odb.rootAssembly.surfaces[bc.set_name] elif bc.type == 'node_set': base = results_odb.rootAssembly.nodeSets[bc.set_name] idx = base.instances.index(instance) nodes = base.nodes[idx] print(len(nodes), "in set", bc.set_name) for n in nodes: set_nodes.append(3 * (n.label - 1) + bc.component - 1) bc_dofs.append(3 * (n.label - 1) + bc.component - 1) bc_dofs = np.unique(np.array(bc_dofs))
def __init__(self, args=None): """ Initialize. :param args: optional arguments if not to use sys.argv :type args: [str] """ self.args = None """ Arguments of program. """ parser = self.get_parser() if args is not None: self.args = parser.parse_args(args) else: self.args = parser.parse_args() self.train_images = None """ (numpy.ndarray) Images to train on. """ self.test_images = None """ (numpy.ndarray) Images to test on. """ self.train_codes = None """ (numpy.ndarray) Labels to train on. """ self.test_codes = None """ (numpy.ndarray) Labels to test on. """ if self.args.log_file: utils.makedir(os.path.dirname(self.args.log_file)) Log.get_instance().attach(open(self.args.log_file, 'w')) log('-- ' + self.__class__.__name__) for key in vars(self.args): log('[Training] %s=%s' % (key, str(getattr(self.args, key)))) utils.makedir(os.path.dirname(self.args.encoder_file)) utils.makedir(os.path.dirname(self.args.decoder_file)) utils.makedir(os.path.dirname(self.args.log_file)) self.resolution = None """ (int) Resolution. """ self.encoder = None """ (models.LearnedVariationalEncoder) Encoder. """ self.decoder = None """ (models.LearnedDecoder) Decoder. """ self.classifier = None """ (models.Classifier) Classifier. """ self.encoder_scheduler = None """ (scheduler.Scheduler) Encoder schduler. """ self.decoder_scheduler = None """ (scheduler.Scheduler) Decoder schduler. """ self.classifier_scheduler = None """ (scheduler.Scheduler) Classifier schduler. """ self.random_codes = None """ (numyp.ndarray) Random codes. """ self.train_statistics = numpy.zeros((0, 15)) """ (numpy.ndarray) Will hold training statistics. """ self.test_statistics = numpy.zeros((0, 12)) """ (numpy.ndarray) Will hold testing statistics. """ self.results = dict() """ (dict) Results. """ self.logvar = -2.5 """ (float) Log-variance hyper parameter. """
def attack(self): """ Test the model. """ assert self.model is not None assert self.model.classifier.training is False concatenate_axis = -1 if os.path.exists(self.args.perturbations_file) and os.path.exists(self.args.success_file): self.original_perturbations = utils.read_hdf5(self.args.perturbations_file) assert len(self.original_perturbations.shape) == 3, self.original_perturbations.shape log('[Attack] read %s' % self.args.perturbations_file) self.original_success = utils.read_hdf5(self.args.success_file) log('[Attack] read %s' % self.args.success_file) assert self.original_perturbations.shape[0] == self.original_success.shape[0] assert self.original_perturbations.shape[1] == self.original_success.shape[1] assert self.original_perturbations.shape[2] == self.test_theta.shape[1] if self.original_perturbations.shape[1] <= self.args.max_samples and self.original_perturbations.shape[0] <= self.args.max_attempts: log('[Attack] found %d attempts, %d samples, requested no more' % (self.original_perturbations.shape[0], self.original_perturbations.shape[1])) return elif self.original_perturbations.shape[0] == self.args.max_attempts or self.original_perturbations.shape[1] == self.args.max_samples: if self.original_perturbations.shape[0] == self.args.max_attempts: self.test_theta = self.test_theta[self.original_perturbations.shape[1]:] self.test_fonts = self.test_fonts[self.original_perturbations.shape[1]:] self.test_classes = self.test_classes[self.original_perturbations.shape[1]:] self.args.max_samples = self.args.max_samples - self.original_perturbations.shape[1] concatenate_axis = 1 log('[Attack] found %d attempts with %d perturbations, computing %d more perturbations' % ( self.original_perturbations.shape[0], self.original_perturbations.shape[1], self.args.max_samples)) elif self.original_perturbations.shape[1] == self.args.max_samples: self.args.max_attempts = self.args.max_attempts - self.original_perturbations.shape[0] concatenate_axis = 0 log('[Attack] found %d attempts with %d perturbations, computing %d more attempts' % ( self.original_perturbations.shape[0], self.original_perturbations.shape[1], self.args.max_attempts)) self.perturbations = numpy.zeros((self.args.max_attempts, self.args.max_samples, self.test_theta.shape[1])) self.success = numpy.ones((self.args.max_attempts, self.args.max_samples), dtype=int) * -1 if self.args.attack.find('Batch') >= 0: batch_size = min(self.args.batch_size, self.args.max_samples) else: batch_size = 1 objective = self.objective_class() num_batches = int(math.ceil(self.args.max_samples/batch_size)) for i in range(num_batches): if i*batch_size == self.args.max_samples: break i_start = i * batch_size i_end = min((i + 1) * batch_size, self.args.max_samples) batch_fonts = self.test_fonts[i_start: i_end] batch_classes = self.test_classes[i_start: i_end] batch_code = numpy.concatenate((common.numpy.one_hot(batch_fonts, self.N_font), common.numpy.one_hot(batch_classes, self.N_class)), axis=1).astype(numpy.float32) batch_classes = common.torch.as_variable(batch_classes, self.args.use_gpu) batch_inputs = common.torch.as_variable(self.test_theta[i_start: i_end], self.args.use_gpu) batch_code = common.torch.as_variable(batch_code, self.args.use_gpu) t = 0 # This basically allows to only optimize over theta, keeping the font/class code fixed. self.model.decoder.set_code(batch_code) while True and t < self.args.max_attempts: attack = self.setup_attack(batch_inputs, batch_classes) success, perturbations, probabilities, norm, _ = attack.run(objective) assert not numpy.any(perturbations != perturbations), perturbations # Note that we save the perturbed image, not only the perturbation! perturbations = perturbations.reshape(batch_inputs.size()) # hack for when only one dimensional latent space is used! self.perturbations[t][i_start: i_end] = perturbations + batch_inputs.cpu().numpy() self.success[t][i_start: i_end] = success t += 1 log('[Attack] %d: completed' % i) if concatenate_axis >= 0: if self.perturbations.shape[0] == self.args.max_attempts: self.perturbations = numpy.concatenate((self.original_perturbations, self.perturbations), axis=concatenate_axis) self.success = numpy.concatenate((self.original_success, self.success), axis=concatenate_axis) log('[Attack] concatenated') utils.write_hdf5(self.args.perturbations_file, self.perturbations) log('[Attack] wrote %s' % self.args.perturbations_file) utils.write_hdf5(self.args.success_file, self.success) log('[Attack] wrote %s' % self.args.success_file)
def attack(self): """ Test the model. """ assert self.model is not None assert self.model.training is False assert self.test_images.shape[0] == self.test_codes.shape[0], 'number of samples has to match' concatenate_axis = -1 if os.path.exists(self.args.perturbations_file) and os.path.exists(self.args.success_file): self.original_perturbations = utils.read_hdf5(self.args.perturbations_file) if self.test_images.shape[3] > 1: assert len(self.original_perturbations.shape) == 5 else: assert len(self.original_perturbations.shape) == 4 log('[Attack] read %s' % self.args.perturbations_file) self.original_success = utils.read_hdf5(self.args.success_file) log('[Attack] read %s' % self.args.success_file) assert self.original_perturbations.shape[0] == self.original_success.shape[0] assert self.original_perturbations.shape[1] == self.original_success.shape[1] assert self.original_perturbations.shape[2] == self.test_images.shape[1] assert self.original_perturbations.shape[3] == self.test_images.shape[2]# if self.original_perturbations.shape[1] >= self.args.max_samples and self.original_perturbations.shape[0] >= self.args.max_attempts: log('[Attack] found %d attempts, %d samples, requested no more' % (self.original_perturbations.shape[0], self.original_perturbations.shape[1])) return elif self.original_perturbations.shape[0] == self.args.max_attempts or self.original_perturbations.shape[1] == self.args.max_samples: if self.original_perturbations.shape[0] == self.args.max_attempts: self.test_images = self.test_images[self.original_perturbations.shape[1]:] self.test_codes = self.test_codes[self.original_perturbations.shape[1]:] self.args.max_samples = self.args.max_samples - self.original_perturbations.shape[1] concatenate_axis = 1 log('[Attack] found %d attempts with %d perturbations, computing %d more perturbations' % (self.original_perturbations.shape[0], self.original_perturbations.shape[1], self.args.max_samples)) elif self.original_perturbations.shape[1] == self.args.max_samples: self.args.max_attempts = self.args.max_attempts - self.original_perturbations.shape[0] concatenate_axis = 0 log('[Attack] found %d attempts with %d perturbations, computing %d more attempts' % (self.original_perturbations.shape[0], self.original_perturbations.shape[1], self.args.max_attempts)) # can't squeeze here! if self.test_images.shape[3] > 1: self.perturbations = numpy.zeros((self.args.max_attempts, self.args.max_samples, self.test_images.shape[1], self.test_images.shape[2], self.test_images.shape[3])) else: self.perturbations = numpy.zeros((self.args.max_attempts, self.args.max_samples, self.test_images.shape[1], self.test_images.shape[2])) self.success = numpy.ones((self.args.max_attempts, self.args.max_samples), dtype=int) * -1 if self.args.attack.find('Batch') >= 0: batch_size = min(self.args.batch_size, self.args.max_samples) else: batch_size = 1 objective = self.objective_class() num_batches = int(math.ceil(self.args.max_samples/batch_size)) for i in range(num_batches): # self.test_images.shape[0] if i*batch_size == self.args.max_samples: break i_start = i*batch_size i_end = min((i+1)*batch_size, self.args.max_samples) batch_images = common.torch.as_variable(self.test_images[i_start: i_end], self.args.use_gpu) batch_classes = common.torch.as_variable(numpy.array(self.test_codes[i_start: i_end]), self.args.use_gpu) batch_images = batch_images.permute(0, 3, 1, 2) t = 0 while t < self.args.max_attempts: attack = self.setup_attack(batch_images, batch_classes) success, perturbations, probabilities, norm, _ = attack.run(objective) assert not numpy.any(perturbations != perturbations), perturbations # Note that we save the perturbed image, not only the perturbation! self.perturbations[t][i_start: i_end] = numpy.squeeze(numpy.transpose(perturbations + batch_images.cpu().numpy(), (0, 2, 3, 1))) self.success[t][i_start: i_end] = success # IMPORTANT: The adversarial examples are not considering whether the classifier is # actually correct to start with. t += 1 log('[Attack] %d: completed' % i) if concatenate_axis >= 0: if self.perturbations.shape[0] == self.args.max_attempts: self.perturbations = numpy.concatenate((self.original_perturbations, self.perturbations), axis=concatenate_axis) self.success = numpy.concatenate((self.original_success, self.success), axis=concatenate_axis) log('[Attack] concatenated') utils.write_hdf5(self.args.perturbations_file, self.perturbations) log('[Attack] wrote %s' % self.args.perturbations_file) utils.write_hdf5(self.args.success_file, self.success) log('[Attack] wrote %s' % self.args.success_file)
def attack(self): """ Test the model. """ assert self.model is not None assert self.model.training is False if self.args.attack.find('Batch') >= 0: batch_size = min(self.args.batch_size, self.args.max_samples) else: batch_size = 1 objective = self.objective_class() num_batches = int(math.ceil(self.args.max_samples / batch_size)) # can't squeeze here! if self.test_images.shape[3] > 1: self.perturbations = numpy.zeros( (self.args.max_attempts, self.args.max_samples, self.test_images.shape[1], self.test_images.shape[2], self.test_images.shape[3])) else: self.perturbations = numpy.zeros( (self.args.max_attempts, self.args.max_samples, self.test_images.shape[1], self.test_images.shape[2])) self.success = numpy.ones( (self.args.max_attempts, self.args.max_samples), dtype=int) * -1 self.probabilities = numpy.zeros( (self.args.max_attempts, self.args.max_samples, self.N_class)) for i in range(num_batches): # self.test_images.shape[0] if i * batch_size == self.args.max_samples: break i_start = i * batch_size i_end = min((i + 1) * batch_size, self.args.max_samples) batch_images = numpy.random.randint(0, 255, size=[batch_size] + self.test_images.shape[1:]) batch_images = common.torch.as_variable(batch_images, self.args.use_gpu) batch_images = batch_images.permute(0, 3, 1, 2) batch_classes = common.torch.as_variable( numpy.random.randint(0, self.N_class - 1, size=(batch_images.size(0))), self.args.use_gpu) t = 0 while t < self.args.max_attempts: attack = self.setup_attack(batch_images, batch_classes) success, perturbations, probabilities, norm, _ = attack.run( objective) assert not numpy.any( perturbations != perturbations), perturbations # Note that we save the perturbed image, not only the perturbation! self.perturbations[t][i_start:i_end] = numpy.squeeze( numpy.transpose(perturbations + batch_images.cpu().numpy(), (0, 2, 3, 1))) self.success[t][i_start:i_end] = success self.probabilities[t][i_start:i_end] = probabilities # IMPORTANT: The adversarial examples are not considering whether the classifier is # actually correct to start with. t += 1 log('[Attack] %d: completed' % i) utils.write_hdf5(self.args.perturbations_file, self.perturbations) log('[Attack] wrote %s' % self.args.perturbations_file) utils.write_hdf5(self.args.success_file, self.success) log('[Attack] wrote %s' % self.args.success_file) utils.write_hdf5(self.args.probabilities_file, self.probabilities) log('[Attack] wrote %s' % self.args.probabilities_file)
def compute_nn(self, inclusive=False): """ Test detector. """ success = numpy.logical_and(self.success >= 0, self.accuracy) log('[Detection] %d valid attacked samples' % numpy.sum(success)) nearest_neighbor_images = self.nearest_neighbor_images.reshape(self.nearest_neighbor_images.shape[0], -1) perturbations = self.perturbations.reshape(self.perturbations.shape[0], -1) test_images = self.test_images.reshape(self.test_images.shape[0], -1) nearest_neighbors_indices = self.compute_nearest_neighbors(perturbations) pure_perturbations = perturbations - test_images log('[Detection] computed nearest neighbors for perturbations') self.distances['true'] = numpy.zeros((success.shape[0])) self.distances['test'] = numpy.zeros((success.shape[0])) self.distances['perturbation'] = numpy.zeros((success.shape[0])) self.angles['true'] = numpy.zeros((success.shape[0])) self.angles['test'] = numpy.zeros((success.shape[0])) self.angles['perturbation'] = numpy.zeros((success.shape[0])) for n in range(pure_perturbations.shape[0]): if success[n]: nearest_neighbors = nearest_neighbor_images[nearest_neighbors_indices[n, :]] if inclusive: nearest_neighbors = numpy.concatenate((nearest_neighbors, test_images[n].reshape(1, -1)), axis=0) nearest_neighbor_mean = test_images[n] else: nearest_neighbor_mean = numpy.average(nearest_neighbors, axis=0) nearest_neighbor_basis = nearest_neighbors - nearest_neighbor_mean relative_perturbation = perturbations[n] - nearest_neighbor_mean relative_test_image = test_images[n] - nearest_neighbor_mean if inclusive: assert numpy.allclose(relative_test_image, nearest_neighbor_basis[-1]) nearest_neighbor_vectors = numpy.stack(( pure_perturbations[n], relative_perturbation, relative_test_image ), axis=1) nearest_neighbor_projections = common.numpy.project_orthogonal(nearest_neighbor_basis.T, nearest_neighbor_vectors) assert nearest_neighbor_vectors.shape[0] == nearest_neighbor_projections.shape[0] assert nearest_neighbor_vectors.shape[1] == nearest_neighbor_projections.shape[1] angles = numpy.rad2deg(common.numpy.angles(nearest_neighbor_vectors, nearest_neighbor_projections)) distances = numpy.linalg.norm(nearest_neighbor_vectors - nearest_neighbor_projections, ord=2, axis=0) assert distances.shape[0] == 3 assert angles.shape[0] == 3 self.distances['true'][n] = distances[0] self.distances['perturbation'][n] = distances[1] self.distances['test'][n] = distances[2] self.angles['true'][n] = angles[0] self.angles['perturbation'][n] = angles[1] self.angles['test'][n] = angles[2] log('[Detection] %d: true distance=%g angle=%g' % (n, self.distances['true'][n], self.angles['true'][n])) log('[Detection] %d: perturbation distance=%g angle=%g' % (n, self.distances['perturbation'][n], self.angles['perturbation'][n])) log('[Detection] %d: test distance=%g angle=%g' % (n, self.distances['test'][n], self.angles['test'][n])) self.distances['true'] = self.distances['true'][success] self.distances['test'] = self.distances['test'][success] self.distances['perturbation'] = self.distances['perturbation'][success] self.angles['true'] = self.angles['true'][success] self.angles['test'] = self.angles['test'][success] self.angles['perturbation'] = self.angles['perturbation'][success] if inclusive: self.distances['test'][:] = 0 self.angles['test'][:] = 0
def compute_true(self): """ Compute true. """ assert self.test_codes is not None num_batches = int(math.ceil(self.perturbations.shape[0] / self.args.batch_size)) params = { 'lr': 0.09, 'lr_decay': 0.95, 'lr_min': 0.0000001, 'weight_decay': 0, } for b in range(num_batches): b_start = b * self.args.batch_size b_end = min((b + 1) * self.args.batch_size, self.perturbations.shape[0]) batch_fonts = self.test_codes[b_start: b_end, 1] batch_classes = self.test_codes[b_start: b_end, 2] batch_code = numpy.concatenate((common.numpy.one_hot(batch_fonts, self.N_font), common.numpy.one_hot(batch_classes, self.N_class)), axis=1).astype( numpy.float32) batch_code = common.torch.as_variable(batch_code, self.args.use_gpu) batch_images = common.torch.as_variable(self.test_images[b_start: b_end], self.args.use_gpu) batch_images = batch_images.permute(0, 3, 1, 2) batch_theta = common.torch.as_variable(self.test_theta[b_start: b_end].astype(numpy.float32), self.args.use_gpu, True) batch_perturbation = common.torch.as_variable(self.perturbations[b_start: b_end].astype(numpy.float32), self.args.use_gpu) self.model.set_code(batch_code) #output_images = self.model.forward(batch_theta) #test_error = torch.mean(torch.mul(output_images - batch_images, output_images - batch_images)) #print(test_error.item()) #vis.mosaic('true.png', batch_images.cpu().detach().numpy()[:, 0, :, :]) #vis.mosaic('output.png', output_images.cpu().detach().numpy()[:, 0, :, :]) # print(batch_images.cpu().detach().numpy()[0]) # print(output_images.cpu().detach().numpy()[0, 0]) #_batch_images = batch_images.cpu().detach().numpy() #_output_images = output_images.cpu().detach().numpy()[:, 0, :, :] #test_error = numpy.max(numpy.abs(_batch_images.reshape(_batch_images.shape[0], -1) - _output_images.reshape(_output_images.shape[0], -1)), axis=1) #print(test_error) #test_error = numpy.mean(numpy.multiply(_batch_images - _output_images, _batch_images - _output_images), axis=1) #print(test_error) batch_theta = torch.nn.Parameter(batch_theta) scheduler = ADAMScheduler([batch_theta], **params) log('[Detection] %d: start' % b) for t in range(100): scheduler.update(t//10, float(t)/10) scheduler.optimizer.zero_grad() output_perturbation = self.model.forward(batch_theta) error = torch.mean(torch.mul(output_perturbation - batch_perturbation, output_perturbation - batch_perturbation)) test_error = torch.mean(torch.mul(output_perturbation - batch_images, output_perturbation - batch_images)) #error.backward() #scheduler.optimizer.step() log('[Detection] %d: %d = %g, %g' % (b, t, error.item(), test_error.item())) output_perturbation = numpy.squeeze(numpy.transpose(output_perturbation.cpu().detach().numpy(), (0, 2, 3, 1))) self.projected_perturbations = common.numpy.concatenate(self.projected_perturbations, output_perturbation) projected_perturbations = self.projected_perturbations.reshape((self.projected_perturbations.shape[0], -1)) perturbations = self.perturbations.reshape((self.perturbations.shape[0], -1)) success = numpy.logical_and(self.success >= 0, self.accuracy) log('[Detection] %d valid attacked samples' % numpy.sum(success)) self.distances['true'] = numpy.linalg.norm(perturbations - projected_perturbations, ord=2, axis=1) self.angles['true'] = numpy.rad2deg(common.numpy.angles(perturbations.T, projected_perturbations.T)) self.distances['true'] = self.distances['true'][success] self.angles['true'] = self.angles['true'][success] self.distances['test'] = numpy.zeros((numpy.sum(success))) self.angles['test'] = numpy.zeros((numpy.sum(success)))
def attack(self): """ Test the model. """ assert self.model is not None assert self.model.classifier.training is False concatenate_axis = -1 if os.path.exists(self.args.perturbations_file) and os.path.exists( self.args.success_file): self.original_perturbations = utils.read_hdf5( self.args.perturbations_file) assert len(self.original_perturbations.shape) == 3 log('[Attack] read %s' % self.args.perturbations_file) self.original_success = utils.read_hdf5(self.args.success_file) log('[Attack] read %s' % self.args.success_file) assert self.original_perturbations.shape[ 0] == self.original_success.shape[0] assert self.original_perturbations.shape[ 1] == self.original_success.shape[1] if self.original_perturbations.shape[ 1] <= self.args.max_samples and self.original_perturbations.shape[ 0] <= self.args.max_attempts: log('[Attack] found %d attempts, %d samples, requested no more' % (self.original_perturbations.shape[0], self.original_perturbations.shape[1])) return elif self.original_perturbations.shape[ 0] == self.args.max_attempts or self.original_perturbations.shape[ 1] == self.args.max_samples: if self.original_perturbations.shape[ 0] == self.args.max_attempts: self.test_images = self.test_images[ self.original_perturbations.shape[1]:] self.test_codes = self.test_codes[ self.original_perturbations.shape[1]:] self.args.max_samples = self.args.max_samples - self.original_perturbations.shape[ 1] concatenate_axis = 1 log('[Attack] found %d attempts with %d perturbations, computing %d more perturbations' % (self.original_perturbations.shape[0], self.original_perturbations.shape[1], self.args.max_samples)) elif self.original_perturbations.shape[ 1] == self.args.max_samples: self.args.max_attempts = self.args.max_attempts - self.original_perturbations.shape[ 0] concatenate_axis = 0 log('[Attack] found %d attempts with %d perturbations, computing %d more attempts' % (self.original_perturbations.shape[0], self.original_perturbations.shape[1], self.args.max_attempts)) self.perturbations = numpy.zeros( (self.args.max_attempts, self.args.max_samples, self.args.N_theta)) self.success = numpy.ones( (self.args.max_attempts, self.args.max_samples), dtype=int) * -1 if self.args.attack.find('Batch') >= 0: batch_size = min(self.args.batch_size, self.args.max_samples) else: batch_size = 1 objective = self.objective_class() num_batches = int(math.ceil(self.args.max_samples / batch_size)) for i in range(num_batches): if i * batch_size == self.args.max_samples: break i_start = i * batch_size i_end = min((i + 1) * batch_size, self.args.max_samples) batch_classes = common.torch.as_variable( self.test_codes[i_start:i_end], self.args.use_gpu) batch_theta = common.torch.as_variable( numpy.zeros((i_end - i_start, self.args.N_theta), dtype=numpy.float32), self.args.use_gpu) if self.args.N_theta > 4: batch_theta[:, 4] = 1 batch_images = common.torch.as_variable( self.test_images[i_start:i_end], self.args.use_gpu) batch_images = batch_images.permute(0, 3, 1, 2) self.model.decoder.set_image(batch_images) #output_images = self.model.decoder.forward(batch_theta) #error = torch.sum(torch.abs(output_images - batch_images)) #error = error.item() #print(error) #from matplotlib import pyplot #output_images = numpy.squeeze(numpy.transpose(output_images.cpu().detach().numpy(), (0, 2, 3, 1))) #pyplot.imshow(output_images[0]) #pyplot.show() t = 0 while True and t < self.args.max_attempts: attack = self.setup_attack(batch_theta, batch_classes) success, perturbations, probabilities, norm, _ = attack.run( objective) assert not numpy.any( perturbations != perturbations), perturbations # Note that we save the perturbed image, not only the perturbation! perturbations = perturbations.reshape(batch_theta.size( )) # hack for when only one dimensional latent space is used! self.perturbations[t][ i_start:i_end] = perturbations + batch_theta.cpu().detach( ).numpy() self.success[t][i_start:i_end] = success t += 1 log('[Attack] %d: completed' % i) if concatenate_axis >= 0: if self.perturbations.shape[0] == self.args.max_attempts: self.perturbations = numpy.concatenate( (self.original_perturbations, self.perturbations), axis=concatenate_axis) self.success = numpy.concatenate( (self.original_success, self.success), axis=concatenate_axis) log('[Attack] concatenated') utils.write_hdf5(self.args.perturbations_file, self.perturbations) log('[Attack] wrote %s' % self.args.perturbations_file) utils.write_hdf5(self.args.success_file, self.success) log('[Attack] wrote %s' % self.args.success_file)