def attacks(model, X_test, Y_test): from keras import backend as K K.set_learning_phase(1) run_config = tf.ConfigProto() run_config.gpu_options.allow_growth=True with tf.Session(config=run_config) as sess: # Define input TF placeholder x = tf.placeholder(tf.float32, shape=(None, *X_test.shape[1:])) y = tf.placeholder(tf.float32, shape=(None, *Y_test.shape[1:])) wrap = KerasModelWrapper(model) fgsm = FastGradientMethod(wrap, sess=sess) fgsm_params = {'eps': 0.3, 'clip_min': 0., 'clip_max': 1.} adv_x = fgsm.generate(x, **fgsm_params) # Consider the attack to be constant adv_x = tf.stop_gradient(adv_x) preds_adv = model(adv_x) eval_par = {'batch_size': 10} initialize_uninitialized_global_variables(sess) acc = model_eval(sess, x, y, preds_adv, X_test, Y_test, args=eval_par) return acc
def build_model(pathModel, pathWeights=None): from keras.models import load_model from cleverhans.utils_tf import initialize_uninitialized_global_variables print("Loading model from disk...") model = load_model(pathModel) if pathWeights: print("Loading model weights") model.load_weights(pathWeights) print("Loaded.") K.set_learning_phase(0) initialize_uninitialized_global_variables(sess) #from keras import optimizers # model.compile(optimizer = optimizers.SGD(lr=1e-3, momentum=0.9), # loss='categorical_crossentropy', metrics=['accuracy']) return model
def build_model(): from keras.models import load_model from cleverhans.utils_tf import initialize_uninitialized_global_variables cwd = os.getcwd() print('current working directory') print(type(cwd)) print(cwd) list_of_files = glob.glob(cwd + '/cnn_models/*') latest_file = max(list_of_files, key=os.path.getctime) print('latest model') print(latest_file) pathModel = latest_file model = load_model(pathModel) #K.set_learning_phase(0) initialize_uninitialized_global_variables(sess) return model
def train(sess, loss, x_train, y_train, init_all=False, evaluate=None, feed=None, args=None, rng=None, var_list=None, fprop_args=None, optimizer=None, devices=None, x_batch_preprocessor=None, use_ema=False, ema_decay=.998, run_canary=None, loss_threshold=1e5, dataset_train=None, dataset_size=None): """ Run (optionally multi-replica, synchronous) training to minimize `loss` :param sess: TF session to use when training the graph :param loss: tensor, the loss to minimize :param x_train: numpy array with training inputs or tf Dataset :param y_train: numpy array with training outputs or tf Dataset :param init_all: (boolean) If set to true, all TF variables in the session are (re)initialized, otherwise only previously uninitialized variables are initialized before training. :param evaluate: function that is run after each training iteration (typically to display the test/validation accuracy). :param feed: An optional dictionary that is appended to the feeding dictionary before the session runs. Can be used to feed the learning phase of a Keras model for instance. :param args: dict or argparse `Namespace` object. Should contain `nb_epochs`, `learning_rate`, `batch_size` :param rng: Instance of numpy.random.RandomState :param var_list: Optional list of parameters to train. :param fprop_args: dict, extra arguments to pass to fprop (loss and model). :param optimizer: Optimizer to be used for training :param devices: list of device names to use for training If None, defaults to: all GPUs, if GPUs are available all devices, if no GPUs are available :param x_batch_preprocessor: callable Takes a single tensor containing an x_train batch as input Returns a single tensor containing an x_train batch as output Called to preprocess the data before passing the data to the Loss :param use_ema: bool If true, uses an exponential moving average of the model parameters :param ema_decay: float or callable The decay parameter for EMA, if EMA is used If a callable rather than a float, this is a callable that takes the epoch and batch as arguments and returns the ema_decay for the current batch. :param loss_threshold: float Raise an exception if the loss exceeds this value. This is intended to rapidly detect numerical problems. Sometimes the loss may legitimately be higher than this value. In such cases, raise the value. If needed it can be np.inf. :param dataset_train: tf Dataset instance. Used as a replacement for x_train, y_train for faster performance. :param dataset_size: integer, the size of the dataset_train. :return: True if model trained """ # Check whether the hardware is working correctly canary.run_canary() if run_canary is not None: warnings.warn("The `run_canary` argument is deprecated. The canary " "is now much cheaper and thus runs all the time. The " "canary now uses its own loss function so it is not " "necessary to turn off the canary when training with " " a stochastic loss. Simply quit passing `run_canary`." "Passing `run_canary` may become an error on or after " "2019-10-16.") args = _ArgsWrapper(args or {}) fprop_args = fprop_args or {} # Check that necessary arguments were given (see doc above) # Be sure to support 0 epochs for debugging purposes if args.nb_epochs is None: raise ValueError("`args` must specify number of epochs") if optimizer is None: if args.learning_rate is None: raise ValueError("Learning rate was not given in args dict") assert args.batch_size, "Batch size was not given in args dict" if rng is None: rng = np.random.RandomState() if optimizer is None: optimizer = tf.train.AdamOptimizer(learning_rate=args.learning_rate) else: if not isinstance(optimizer, tf.train.Optimizer): raise ValueError("optimizer object must be from a child class of " "tf.train.Optimizer") grads = [] xs = [] preprocessed_xs = [] ys = [] if dataset_train is not None: assert x_train is None and y_train is None and x_batch_preprocessor is None if dataset_size is None: raise ValueError("You must provide a dataset size") data_iterator = dataset_train.make_one_shot_iterator().get_next() x_train, y_train = sess.run(data_iterator) devices = infer_devices(devices) for device in devices: with tf.device(device): # x = tf.placeholder(x_train.dtype, (None,) + x_train.shape[1:]) # y = tf.placeholder(y_train.dtype, (None,) + y_train.shape[1:]) x = tf.placeholder(tf.float32, (None,) + x_train.shape[1:]) y = tf.placeholder(tf.float32, (None,) + y_train.shape[1:]) xs.append(x) ys.append(y) if x_batch_preprocessor is not None: x = x_batch_preprocessor(x) # We need to keep track of these so that the canary can feed # preprocessed values. If the canary had to feed raw values, # stochastic preprocessing could make the canary fail. preprocessed_xs.append(x) loss_value = loss.fprop(x, y, **fprop_args) print("loss_value", loss_value) grads.append(optimizer.compute_gradients( loss_value, var_list=var_list)) print("grads:", grads) num_devices = len(devices) print("num_devices: ", num_devices) grad = avg_grads(grads) # Trigger update operations within the default graph (such as batch_norm). with tf.control_dependencies(tf.get_collection(tf.GraphKeys.UPDATE_OPS)): train_step = optimizer.apply_gradients(grad) epoch_tf = tf.placeholder(tf.int32, []) batch_tf = tf.placeholder(tf.int32, []) if use_ema: if callable(ema_decay): ema_decay = ema_decay(epoch_tf, batch_tf) ema = tf.train.ExponentialMovingAverage(decay=ema_decay) with tf.control_dependencies([train_step]): train_step = ema.apply(var_list) # Get pointers to the EMA's running average variables avg_params = [ema.average(param) for param in var_list] # Make temporary buffers used for swapping the live and running average # parameters tmp_params = [tf.Variable(param, trainable=False) for param in var_list] # Define the swapping operation param_to_tmp = [tf.assign(tmp, param) for tmp, param in safe_zip(tmp_params, var_list)] with tf.control_dependencies(param_to_tmp): avg_to_param = [tf.assign(param, avg) for param, avg in safe_zip(var_list, avg_params)] with tf.control_dependencies(avg_to_param): tmp_to_avg = [tf.assign(avg, tmp) for avg, tmp in safe_zip(avg_params, tmp_params)] swap = tmp_to_avg batch_size = args.batch_size assert batch_size % num_devices == 0 device_batch_size = batch_size // num_devices if init_all: sess.run(tf.global_variables_initializer()) else: initialize_uninitialized_global_variables(sess) for epoch in xrange(args.nb_epochs): if dataset_train is not None: nb_batches = int(math.ceil(float(dataset_size) / batch_size)) else: # Indices to shuffle training set index_shuf = list(range(len(x_train))) # Randomly repeat a few training examples each epoch to avoid # having a too-small batch while len(index_shuf) % batch_size != 0: index_shuf.append(rng.randint(len(x_train))) nb_batches = len(index_shuf) // batch_size rng.shuffle(index_shuf) # Shuffling here versus inside the loop doesn't seem to affect # timing very much, but shuffling here makes the code slightly # easier to read x_train_shuffled = x_train[index_shuf] y_train_shuffled = y_train[index_shuf] prev = time.time() for batch in range(nb_batches): if dataset_train is not None: x_train_shuffled, y_train_shuffled = sess.run(data_iterator) start, end = 0, batch_size else: # Compute batch start and end indices start = batch * batch_size end = (batch + 1) * batch_size # Perform one training step diff = end - start assert diff == batch_size feed_dict = {epoch_tf: epoch, batch_tf: batch} for dev_idx in xrange(num_devices): cur_start = start + dev_idx * device_batch_size cur_end = start + (dev_idx + 1) * device_batch_size feed_dict[xs[dev_idx]] = x_train_shuffled[cur_start:cur_end] feed_dict[ys[dev_idx]] = y_train_shuffled[cur_start:cur_end] if cur_end != end and dataset_train is None: msg = ("batch_size (%d) must be a multiple of num_devices " "(%d).\nCUDA_VISIBLE_DEVICES: %s" "\ndevices: %s") args = (batch_size, num_devices, os.environ['CUDA_VISIBLE_DEVICES'], str(devices)) raise ValueError(msg % args) if feed is not None: feed_dict.update(feed) _, loss_numpy = sess.run([train_step, loss_value], feed_dict=feed_dict) if np.abs(loss_numpy) > loss_threshold: raise ValueError("Extreme loss during training: ", loss_numpy) if np.isnan(loss_numpy) or np.isinf(loss_numpy): raise ValueError("NaN/Inf loss during training") assert (dataset_train is not None or end == len(index_shuf)) # Check that all examples were used cur = time.time() _logger.info("Epoch " + str(epoch) + " took " + str(cur - prev) + " seconds") print("loss:", loss_numpy) if evaluate is not None: if use_ema: # Before running evaluation, load the running average # parameters into the live slot, so we can see how well # the EMA parameters are performing sess.run(swap) evaluate() if use_ema: # Swap the parameters back, so that we continue training # on the live parameters sess.run(swap) if use_ema: # When training is done, swap the running average parameters into # the live slot, so that we use them when we deploy the model sess.run(swap) return True
def train(sess, loss, x_train, y_train, init_all=True, evaluate=None, feed=None, args=None, rng=None, var_list=None, fprop_args=None, optimizer=None, devices=None, x_batch_preprocessor=None, use_ema=False, ema_decay=.998, run_canary=True, loss_threshold=1e5): """ Run (optionally multi-replica, synchronous) training to minimize `loss` :param sess: TF session to use when training the graph :param loss: tensor, the loss to minimize :param x_train: numpy array with training inputs :param y_train: numpy array with training outputs :param init_all: (boolean) If set to true, all TF variables in the session are (re)initialized, otherwise only previously uninitialized variables are initialized before training. :param evaluate: function that is run after each training iteration (typically to display the test/validation accuracy). :param feed: An optional dictionary that is appended to the feeding dictionary before the session runs. Can be used to feed the learning phase of a Keras model for instance. :param args: dict or argparse `Namespace` object. Should contain `nb_epochs`, `learning_rate`, `batch_size` :param rng: Instance of numpy.random.RandomState :param var_list: Optional list of parameters to train. :param fprop_args: dict, extra arguments to pass to fprop (loss and model). :param optimizer: Optimizer to be used for training :param devices: list of device names to use for training If None, defaults to: all GPUs, if GPUs are available all devices, if no GPUs are available :param x_batch_preprocessor: callable Takes a single tensor containing an x_train batch as input Returns a single tensor containing an x_train batch as output Called to preprocess the data before passing the data to the Loss :param use_ema: bool If true, uses an exponential moving average of the model parameters :param ema_decay: float or callable The decay parameter for EMA, if EMA is used If a callable rather than a float, this is a callable that takes the epoch and batch as arguments and returns the ema_decay for the current batch. :param run_canary: bool If True and using 3 or more GPUs, runs some canary code that should fail if there is a multi-GPU driver problem. Turn this off if your gradients are inherently stochastic (e.g. if you use dropout). The canary code checks that all GPUs give approximately the same gradient. :param loss_threshold: float Raise an exception if the loss exceeds this value. This is intended to rapidly detect numerical problems. Sometimes the loss may legitimately be higher than this value. In such cases, raise the value. If needed it can be np.inf. :return: True if model trained """ args = _ArgsWrapper(args or {}) fprop_args = fprop_args or {} # Check that necessary arguments were given (see doc above) assert args.nb_epochs, "Number of epochs was not given in args dict" if optimizer is None: if args.learning_rate is None: raise ValueError("Learning rate was not given in args dict") assert args.batch_size, "Batch size was not given in args dict" if rng is None: rng = np.random.RandomState() if optimizer is None: optimizer = tf.train.AdamOptimizer(learning_rate=args.learning_rate) else: if not isinstance(optimizer, tf.train.Optimizer): raise ValueError("optimizer object must be from a child class of " "tf.train.Optimizer") grads = [] xs = [] preprocessed_xs = [] ys = [] devices = infer_devices(devices) for idx, device in enumerate(devices): with tf.device(device): x = tf.placeholder(x_train.dtype, (None, ) + x_train.shape[1:]) y = tf.placeholder(x_train.dtype, (None, ) + y_train.shape[1:]) xs.append(x) ys.append(y) if x_batch_preprocessor is not None: x = x_batch_preprocessor(x) # We need to keep track of these so that the canary can feed # preprocessed values. If the canary had to feed raw values, # stochastic preprocessing could make the canary fail. preprocessed_xs.append(x) loss_value = loss.fprop(x, y, **fprop_args) grads.append( optimizer.compute_gradients(loss_value, var_list=var_list)) num_devices = len(devices) print("num_devices: ", num_devices) grad = avg_grads(grads) # Trigger update operations within the default graph (such as batch_norm). with tf.control_dependencies(tf.get_collection(tf.GraphKeys.UPDATE_OPS)): train_step = optimizer.apply_gradients(grad) epoch_tf = tf.placeholder(tf.int32, []) batch_tf = tf.placeholder(tf.int32, []) if use_ema: if callable(ema_decay): ema_decay = ema_decay(epoch_tf, batch_tf) ema = tf.train.ExponentialMovingAverage(decay=ema_decay) with tf.control_dependencies([train_step]): train_step = ema.apply(var_list) # Get pointers to the EMA's running average variables avg_params = [ema.average(param) for param in var_list] # Make temporary buffers used for swapping the live and running average # parameters tmp_params = [ tf.Variable(param, trainable=False) for param in var_list ] # Define the swapping operation param_to_tmp = [ tf.assign(tmp, param) for tmp, param in safe_zip(tmp_params, var_list) ] with tf.control_dependencies(param_to_tmp): avg_to_param = [ tf.assign(param, avg) for param, avg in safe_zip(var_list, avg_params) ] with tf.control_dependencies(avg_to_param): tmp_to_avg = [ tf.assign(avg, tmp) for avg, tmp in safe_zip(avg_params, tmp_params) ] swap = tmp_to_avg batch_size = args.batch_size assert batch_size % num_devices == 0 device_batch_size = batch_size // num_devices if init_all: sess.run(tf.global_variables_initializer()) else: initialize_uninitialized_global_variables(sess) # Check whether the hardware is working correctly # So far the failure has only been observed with 3 or more GPUs run_canary = run_canary and num_devices > 2 if run_canary: canary_feed_dict = {} for x, y in safe_zip(preprocessed_xs, ys): canary_feed_dict[x] = x_train[:device_batch_size].copy() canary_feed_dict[y] = y_train[:device_batch_size].copy() # To reduce the runtime and memory cost of this canary, # we test the gradient of only one parameter. # For now this is just set to the first parameter in the list, # because it is an index that is always guaranteed to work. # If we think that this is causing false negatives and we should # test other parameters, we could test a random parameter from # the list or we could rewrite the canary to examine more than # one parameter. param_to_test = 0 grad_vars = [] for i in xrange(num_devices): dev_grads = grads[i] grad_vars.append(dev_grads[param_to_test][0]) grad_values = sess.run(grad_vars, feed_dict=canary_feed_dict) failed = False for i in xrange(1, num_devices): if grad_values[0].shape != grad_values[i].shape: print("shape 0 does not match shape %d:" % i, grad_values[0].shape, grad_values[i].shape) failed = True continue if not np.allclose(grad_values[0], grad_values[i], atol=1e-6): print("grad_values[0]: ", grad_values[0].mean(), grad_values[0].max()) print("grad_values[%d]: " % i, grad_values[i].mean(), grad_values[i].max()) print("max diff: ", np.abs(grad_values[0] - grad_values[1]).max()) failed = True if failed: print("Canary failed.") quit() for epoch in xrange(args.nb_epochs): # Indices to shuffle training set index_shuf = list(range(len(x_train))) # Randomly repeat a few training examples each epoch to avoid # having a too-small batch while len(index_shuf) % batch_size != 0: index_shuf.append(rng.randint(len(x_train))) nb_batches = len(index_shuf) // batch_size rng.shuffle(index_shuf) # Shuffling here versus inside the loop doesn't seem to affect # timing very much, but shuffling here makes the code slightly # easier to read x_train_shuffled = x_train[index_shuf] y_train_shuffled = y_train[index_shuf] prev = time.time() for batch in range(nb_batches): # Compute batch start and end indices start = batch * batch_size end = (batch + 1) * batch_size # Perform one training step feed_dict = {epoch_tf: epoch, batch_tf: batch} diff = end - start assert diff == batch_size for dev_idx in xrange(num_devices): cur_start = start + dev_idx * device_batch_size cur_end = start + (dev_idx + 1) * device_batch_size feed_dict[xs[dev_idx]] = x_train_shuffled[cur_start:cur_end] feed_dict[ys[dev_idx]] = y_train_shuffled[cur_start:cur_end] if cur_end != end: msg = ("batch_size (%d) must be a multiple of num_devices " "(%d).\nCUDA_VISIBLE_DEVICES: %s" "\ndevices: %s") args = (batch_size, num_devices, os.environ['CUDA_VISIBLE_DEVICES'], str(devices)) raise ValueError(msg % args) if feed is not None: feed_dict.update(feed) _, loss_numpy = sess.run([train_step, loss_value], feed_dict=feed_dict) if np.abs(loss_numpy) > loss_threshold: raise ValueError("Extreme loss during training: ", loss_numpy) if np.isnan(loss_numpy) or np.isinf(loss_numpy): raise ValueError("NaN/Inf loss during training") assert end == len(index_shuf) # Check that all examples were used cur = time.time() _logger.info("Epoch " + str(epoch) + " took " + str(cur - prev) + " seconds") if evaluate is not None: if use_ema: # Before running evaluation, load the running average # parameters into the live slot, so we can see how well # the EMA parameters are performing sess.run(swap) evaluate() if use_ema: # Swap the parameters back, so that we continue training # on the live parameters sess.run(swap) if use_ema: # When training is done, swap the running average parameters into # the live slot, so that we use them when we deploy the model sess.run(swap) return True
def cifar_tutorial(train_start=0, train_end=49000, test_start=0, test_end=10000, nb_epochs=6, batch_size=128, learning_rate=0.001, clean_train=True, testing=False, backprop_through_attack=False, nb_filters=64, num_threads=None): """ MNIST cleverhans tutorial :param train_start: index of first training set example :param train_end: index of last training set example :param test_start: index of first test set example :param test_end: index of last test set example :param nb_epochs: number of epochs to train model :param batch_size: size of training batches :param learning_rate: learning rate for training :param clean_train: perform normal training on clean examples only before performing adversarial training. :param testing: if true, complete an AccuracyReport for unit tests to verify that performance is adequate :param backprop_through_attack: If True, backprop through adversarial example construction process during adversarial training. :param clean_train: if true, train on clean examples :return: an AccuracyReport object """ # Object used to keep track of (and return) key accuracies report = AccuracyReport() # Set TF random seed to improve reproducibility tf.set_random_seed(1234) # Set logging level to see debug information set_log_level(logging.DEBUG) # Create TF session if num_threads: config_args = dict(intra_op_parallelism_threads=1) else: config_args = {} sess = tf.Session(config=tf.ConfigProto(**config_args)) (X_train, Y_train), (X_test, Y_test) = cifar10.load_data() Y_train = np_utils.to_categorical(Y_train, 10) Y_test = np_utils.to_categorical(Y_test, 10) X_train = X_train.astype('float32') X_test = X_test.astype('float32') X_train /= 255 X_test /= 255 label_smooth = .1 Y_train = Y_train.clip(label_smooth / 9., 1. - label_smooth) x = tf.placeholder(tf.float32, shape=(None, 32, 32, 3)) y = tf.placeholder(tf.float32, shape=([None, 10])) nb_classes = 10 source_samples = 10 img_rows = 32 img_cols = 32 channels = 3 train_params = { 'nb_epochs': nb_epochs, 'batch_size': batch_size, 'learning_rate': learning_rate } fgsm_params = {'eps': FLAGS.fgsm_eps, 'clip_min': 0., 'clip_max': 1.} rng = np.random.RandomState([2017, 8, 30]) prune_factor = FLAGS.prune_factor if clean_train: prune_percent = { 'conv1_w': 5, 'conv2_w': 5, 'conv3_w': 5, 'conv4_w': 5, 'fc1_w': prune_factor, 'fc2_w': prune_factor, 'fc3_w': prune_factor } #model = make_resnet(x,10,[None,32,32,3],reuse = True,prune_percent = prune_percent) model = make_strong_cnn(nb_filters=nb_filters, prune_percent=prune_percent) initialize_uninitialized_global_variables(sess) preds = model.get_probs(x) saver = tf.train.Saver() eval_par = {'batch_size': batch_size} def fgsm_combo(): acc = model_eval(sess, x, y, preds, X_test, Y_test, args=eval_par) print('Test accuracy on legitimate examples: %0.4f\n' % acc) fgsm = FastGradientMethod(model, sess=sess) #initialize_uninitialized_global_variables(sess) adv_x = fgsm.generate(x, **fgsm_params) preds_adv = model.get_probs(adv_x) acc = model_eval(sess, x, y, preds_adv, X_test, Y_test, args=eval_par) print( 'Test accuracy on adversarial examples generated by fgsm: %0.4f\n' % acc) bim = BasicIterativeMethod(model, sess=sess) adv_x = bim.generate(x) preds_adv = model.get_probs(adv_x) acc = model_eval(sess, x, y, preds_adv, X_test, Y_test, args=eval_par) print( 'Test accuracy on adversarial examples generated by IterativeMethod: %0.4f\n' % acc) def evaluate(): # Evaluate the accuracy of the MNIST model on legitimate test # examples acc = model_eval(sess, x, y, preds, X_test, Y_test, args=eval_par) report.clean_train_clean_eval = acc assert X_test.shape[0] == test_end - test_start, X_test.shape print('Test accuracy on legitimate examples: %0.4f' % acc) ckpt_name = './cifar_model.ckpt' if not FLAGS.resume: model_train(sess, x, y, preds, X_train, Y_train, evaluate=evaluate, args=train_params, rng=rng) saver.save(sess, ckpt_name) if FLAGS.resume: saver = tf.train.import_meta_graph(ckpt_name + '.meta') print("loading pretrain model") saver.restore(sess, ckpt_name) acc = model_eval(sess, x, y, preds, X_test, Y_test, args=eval_par) print('Test accuracy on pretrained model: %0.4f\n' % acc) if not FLAGS.resume: import sys sys.exit() def do_jsma(): print('Crafting ' + str(source_samples) + ' * ' + str(nb_classes - 1) + ' adversarial examples') # Keep track of success (adversarial example classified in target) results = np.zeros((nb_classes, source_samples), dtype='i') # Rate of perturbed features for each test set example and target class perturbations = np.zeros((nb_classes, source_samples), dtype='f') # Initialize our array for grid visualization grid_shape = (nb_classes, nb_classes, img_rows, img_cols, channels) grid_viz_data = np.zeros(grid_shape, dtype='f') # Instantiate a SaliencyMapMethod attack object jsma = SaliencyMapMethod(model, back='tf', sess=sess) jsma_params = { 'theta': 1., 'gamma': 0.1, 'clip_min': 0., 'clip_max': 1., 'y_target': None } figure = None # Loop over the samples we want to perturb into adversarial examples for sample_ind in xrange(0, source_samples): print('--------------------------------------') print('Attacking input %i/%i' % (sample_ind + 1, source_samples)) sample = X_test[sample_ind:(sample_ind + 1)] # We want to find an adversarial example for each possible target class # (i.e. all classes that differ from the label given in the dataset) current_class = int(np.argmax(Y_test[sample_ind])) target_classes = other_classes(nb_classes, current_class) # For the grid visualization, keep original images along the diagonal grid_viz_data[current_class, current_class, :, :, :] = np.reshape( sample, (img_rows, img_cols, channels)) # Loop over all target classes for target in target_classes: print('Generating adv. example for target class %i' % target) # This call runs the Jacobian-based saliency map approach one_hot_target = np.zeros((1, nb_classes), dtype=np.float32) one_hot_target[0, target] = 1 jsma_params['y_target'] = one_hot_target adv_x = jsma.generate_np(sample, **jsma_params) # Check if success was achieved res = int(model_argmax(sess, x, preds, adv_x) == target) # Computer number of modified features adv_x_reshape = adv_x.reshape(-1) test_in_reshape = X_test[sample_ind].reshape(-1) nb_changed = np.where( adv_x_reshape != test_in_reshape)[0].shape[0] percent_perturb = float(nb_changed) / adv_x.reshape( -1).shape[0] # Display the original and adversarial images side-by-side if FLAGS.viz_enabled: figure = pair_visual( np.reshape(sample, (img_rows, img_cols)), np.reshape(adv_x, (img_rows, img_cols)), figure) # Add our adversarial example to our grid data grid_viz_data[target, current_class, :, :, :] = np.reshape( adv_x, (img_rows, img_cols, channels)) # Update the arrays for later analysis results[target, sample_ind] = res perturbations[target, sample_ind] = percent_perturb print('--------------------------------------') # Compute the number of adversarial examples that were successfully found nb_targets_tried = ((nb_classes - 1) * source_samples) succ_rate = float(np.sum(results)) / nb_targets_tried print('Avg. rate of successful adv. examples {0:.4f}'.format( succ_rate)) report.clean_train_adv_eval = 1. - succ_rate # Compute the average distortion introduced by the algorithm percent_perturbed = np.mean(perturbations) print('Avg. rate of perturbed features {0:.4f}'.format( percent_perturbed)) # Compute the average distortion introduced for successful samples only percent_perturb_succ = np.mean(perturbations * (results == 1)) print('Avg. rate of perturbed features for successful ' 'adversarial examples {0:.4f}'.format(percent_perturb_succ)) if FLAGS.viz_enabled: import matplotlib.pyplot as plt plt.close(figure) _ = grid_visual(grid_viz_data) return report def do_cw(): nb_adv_per_sample = str(nb_classes - 1) if FLAGS.targeted else '1' print('Crafting ' + str(source_samples) + ' * ' + nb_adv_per_sample + ' adversarial examples') print("This could take some time ...") # Instantiate a CW attack object cw = CarliniWagnerL2(model, back='tf', sess=sess) if FLAGS.viz_enabled: assert source_samples == nb_classes idxs = [ np.where(np.argmax(Y_test, axis=1) == i)[0][0] for i in range(nb_classes) ] if FLAGS.targeted: if FLAGS.viz_enabled: # Initialize our array for grid visualization grid_shape = (nb_classes, nb_classes, img_rows, img_cols, channels) grid_viz_data = np.zeros(grid_shape, dtype='f') adv_inputs = np.array([[instance] * nb_classes for instance in X_test[idxs]], dtype=np.float32) else: adv_inputs = np.array( [[instance] * nb_classes for instance in X_test[:source_samples]], dtype=np.float32) one_hot = np.zeros((nb_classes, nb_classes)) one_hot[np.arange(nb_classes), np.arange(nb_classes)] = 1 adv_inputs = adv_inputs.reshape((source_samples * nb_classes, img_rows, img_cols, channels)) adv_ys = np.array([one_hot] * source_samples, dtype=np.float32).reshape( (source_samples * nb_classes, nb_classes)) yname = "y_target" else: if FLAGS.viz_enabled: # Initialize our array for grid visualization grid_shape = (nb_classes, 2, img_rows, img_cols, channels) grid_viz_data = np.zeros(grid_shape, dtype='f') adv_inputs = X_test[idxs] else: adv_inputs = X_test[:source_samples] adv_ys = None yname = "y" cw_params = { 'binary_search_steps': 1, yname: adv_ys, 'max_iterations': FLAGS.attack_iterations, 'learning_rate': 0.1, 'batch_size': source_samples * nb_classes if FLAGS.targeted else source_samples, 'initial_const': 10 } adv = cw.generate_np(adv_inputs, **cw_params) if FLAGS.targeted: adv_accuracy = model_eval(sess, x, y, preds, adv, adv_ys, args=eval_par) else: if FLAGS.viz_enabled: adv_accuracy = 1 - \ model_eval(sess, x, y, preds, adv, Y_test[ idxs], args=eval_par) else: adv_accuracy = 1 - \ model_eval(sess, x, y, preds, adv, Y_test[ :source_samples], args=eval_par) if FLAGS.viz_enabled: for j in range(nb_classes): if FLAGS.targeted: for i in range(nb_classes): grid_viz_data[i, j] = adv[i * nb_classes + j] else: grid_viz_data[j, 0] = adv_inputs[j] grid_viz_data[j, 1] = adv[j] print(grid_viz_data.shape) print('--------------------------------------') # Compute the number of adversarial examples that were successfully found print('Avg. rate of successful adv. examples {0:.4f}'.format( adv_accuracy)) report.clean_train_adv_eval = 1. - adv_accuracy # Compute the average distortion introduced by the algorithm percent_perturbed = np.mean( np.sum((adv - adv_inputs)**2, axis=(1, 2, 3))**.5) print('Avg. L_2 norm of perturbations {0:.4f}'.format( percent_perturbed)) # Close TF session # sess.close() # Finally, block & display a grid of all the adversarial examples if FLAGS.viz_enabled: import matplotlib.pyplot as plt _ = grid_visual(grid_viz_data) return report fgsm = FastGradientMethod(model, sess=sess) #model.test_mode() #initialize_uninitialized_global_variables(sess) fgsm_combo() do_cw() do_jsma() if not FLAGS.load_pruned_model: print("start iterative pruning") for i in range(FLAGS.prune_iterations): print("iterative %d" % (i)) dict_nzidx = model.apply_prune(sess) trainer = tf.train.AdamOptimizer(learning_rate) preds = model.get_probs(x) loss = model_loss(y, preds) grads = trainer.compute_gradients(loss) grads = model.apply_prune_on_grads(grads, dict_nzidx) prune_args = {'trainer': trainer, 'grads': grads} train_params = { 'nb_epochs': FLAGS.retrain_epoch, 'batch_size': batch_size, 'learning_rate': FLAGS.retrain_lr } model_train(sess, x, y, preds, X_train, Y_train, evaluate=evaluate, args=train_params, rng=rng, prune_args=prune_args, retrainindex=i) acc = model_eval(sess, x, y, preds_adv, X_test, Y_test, args=eval_par) print('Test accuracy on adversarial examples: %0.4f\n' % acc) saver.save(sess, './pruned_cifar_model.ckpt') else: print("load pruned model") saver = tf.train.import_meta_graph( './pruned_cifar_model.ckpt.meta') saver.restore(sess, './pruned_cifar_model.ckpt') print("before applying gradient inhibition\n") fgsm_combo() do_cw() do_jsma() if FLAGS.do_inhibition: model.inhibition(sess, original_method=FLAGS.use_inhibition_original, inhibition_eps=FLAGS.inhibition_eps) print("after applying gradient inhibition\n") fgsm_combo() do_cw() do_jsma()
def train_ae(sess, loss, x_train, x_train_target, init_all=False, evaluate=None, feed=None, args=None, rng=None, var_list=None, fprop_args=None, optimizer=None, devices=None, x_batch_preprocessor=None, use_ema=False, ema_decay=.998, run_canary=None, loss_threshold=1e5, dataset_train=None, dataset_size=None): # Check whether the hardware is working correctly start_time = time.time() canary.run_canary() if run_canary is not None: warnings.warn("The `run_canary` argument is deprecated. The canary " "is now much cheaper and thus runs all the time. The " "canary now uses its own loss function so it is not " "necessary to turn off the canary when training with " " a stochastic loss. Simply quit passing `run_canary`." "Passing `run_canary` may become an error on or after " "2019-10-16.") args = _ArgsWrapper(args or {}) fprop_args = fprop_args or {} # Check that necessary arguments were given (see doc above) # Be sure to support 0 epochs for debugging purposes if args.nb_epochs is None: raise ValueError("`args` must specify number of epochs") if optimizer is None: if args.learning_rate is None: raise ValueError("Learning rate was not given in args dict") assert args.batch_size, "Batch size was not given in args dict" if rng is None: rng = np.random.RandomState() if optimizer is None: optimizer = tf.train.AdamOptimizer(learning_rate=args.learning_rate) else: if not isinstance(optimizer, tf.train.Optimizer): raise ValueError("optimizer object must be from a child class of " "tf.train.Optimizer") grads = [] xs = [] xs_t = [] preprocessed_xs = [] preprocessed_xs_t = [] #ys = [] if dataset_train is not None: assert x_train is None and x_batch_preprocessor is None if dataset_size is None: raise ValueError("You must provide a dataset size") data_iterator = dataset_train.make_one_shot_iterator().get_next() x_train, x_train_target = sess.run(data_iterator) devices = infer_devices(devices) for device in devices: with tf.device(device): x = tf.placeholder(x_train.dtype, (None, ) + x_train.shape[1:]) x_t = tf.placeholder(x_train_target.dtype, (None, ) + x_train_target.shape[1:]) #y = tf.placeholder(y_train.dtype, (None,) + y_train.shape[1:]) xs.append(x) xs_t.append(x_t) #ys.append(y) if x_batch_preprocessor is not None: x = x_batch_preprocessor(x) x_t = x_batch_preprocessor(x_t) # We need to keep track of these so that the canary can feed # preprocessed values. If the canary had to feed raw values, # stochastic preprocessing could make the canary fail. preprocessed_xs.append(x) preprocessed_xs_t.append(x_t) loss_value = loss.fprop(x, x_t, **fprop_args) grads.append( optimizer.compute_gradients(loss_value, var_list=var_list)) num_devices = len(devices) print("num_devices: ", num_devices) grad = avg_grads(grads) # Trigger update operations within the default graph (such as batch_norm). with tf.control_dependencies(tf.get_collection(tf.GraphKeys.UPDATE_OPS)): train_step = optimizer.apply_gradients(grad) epoch_tf = tf.placeholder(tf.int32, []) batch_tf = tf.placeholder(tf.int32, []) if use_ema: if callable(ema_decay): ema_decay = ema_decay(epoch_tf, batch_tf) ema = tf.train.ExponentialMovingAverage(decay=ema_decay) with tf.control_dependencies([train_step]): train_step = ema.apply(var_list) # Get pointers to the EMA's running average variables avg_params = [ema.average(param) for param in var_list] # Make temporary buffers used for swapping the live and running average # parameters tmp_params = [ tf.Variable(param, trainable=False) for param in var_list ] # Define the swapping operation param_to_tmp = [ tf.assign(tmp, param) for tmp, param in safe_zip(tmp_params, var_list) ] with tf.control_dependencies(param_to_tmp): avg_to_param = [ tf.assign(param, avg) for param, avg in safe_zip(var_list, avg_params) ] with tf.control_dependencies(avg_to_param): tmp_to_avg = [ tf.assign(avg, tmp) for avg, tmp in safe_zip(avg_params, tmp_params) ] swap = tmp_to_avg batch_size = args.batch_size assert batch_size % num_devices == 0 device_batch_size = batch_size // num_devices if init_all: sess.run(tf.global_variables_initializer()) else: initialize_uninitialized_global_variables(sess) for epoch in xrange(args.nb_epochs): if dataset_train is not None: nb_batches = int(math.ceil(float(dataset_size) / batch_size)) else: # Indices to shuffle training set index_shuf = list(range(len(x_train))) # Randomly repeat a few training examples each epoch to avoid # having a too-small batch while len(index_shuf) % batch_size != 0: index_shuf.append(rng.randint(len(x_train))) nb_batches = len(index_shuf) // batch_size rng.shuffle(index_shuf) # Shuffling here versus inside the loop doesn't seem to affect # timing very much, but shuffling here makes the code slightly # easier to read x_train_shuffled = x_train[index_shuf] x_train_target_shuffled = x_train_target[index_shuf] #y_train_shuffled = y_train[index_shuf] prev = time.time() for batch in range(nb_batches): if dataset_train is not None: x_train_shuffled, x_train_target_shuffled = sess.run( data_iterator) start, end = 0, batch_size else: # Compute batch start and end indices start = batch * batch_size end = (batch + 1) * batch_size # Perform one training step diff = end - start assert diff == batch_size feed_dict = {epoch_tf: epoch, batch_tf: batch} for dev_idx in xrange(num_devices): cur_start = start + dev_idx * device_batch_size cur_end = start + (dev_idx + 1) * device_batch_size feed_dict[xs[dev_idx]] = x_train_shuffled[cur_start:cur_end] feed_dict[ xs_t[dev_idx]] = x_train_target_shuffled[cur_start:cur_end] #feed_dict[ys[dev_idx]] = y_train_shuffled[cur_start:cur_end] if cur_end != end and dataset_train is None: msg = ("batch_size (%d) must be a multiple of num_devices " "(%d).\nCUDA_VISIBLE_DEVICES: %s" "\ndevices: %s") args = (batch_size, num_devices, os.environ['CUDA_VISIBLE_DEVICES'], str(devices)) raise ValueError(msg % args) if feed is not None: feed_dict.update(feed) _, loss_numpy = sess.run([train_step, loss_value], feed_dict=feed_dict) if np.abs(loss_numpy) > loss_threshold: raise ValueError("Extreme loss during training: ", loss_numpy) if np.isnan(loss_numpy) or np.isinf(loss_numpy): raise ValueError("NaN/Inf loss during training") assert (dataset_train is not None or end == len(index_shuf)) # Check that all examples were used cur = time.time() _logger.info("Epoch " + str(epoch) + " took " + str(cur - prev) + " seconds") if evaluate is not None: if use_ema: # Before running evaluation, load the running average # parameters into the live slot, so we can see how well # the EMA parameters are performing sess.run(swap) evaluate() if use_ema: # Swap the parameters back, so that we continue training # on the live parameters sess.run(swap) if use_ema: # When training is done, swap the running average parameters into # the live slot, so that we use them when we deploy the model sess.run(swap) end_time = time.time() print("Time taken for training: ", end_time - start_time) return True
def cifar10_tutorial(train_start=0, train_end=60000, test_start=0, test_end=10000, nb_epochs=NB_EPOCHS, batch_size=BATCH_SIZE, architecture=ARCHITECTURE, load_model=LOAD_MODEL, ckpt_dir='None', learning_rate=LEARNING_RATE, clean_train=CLEAN_TRAIN, backprop_through_attack=BACKPROP_THROUGH_ATTACK, nb_filters=NB_FILTERS, num_threads=None, label_smoothing=0.): """ CIFAR10 cleverhans tutorial :param train_start: index of first training set example :param train_end: index of last training set example :param test_start: index of first test set example :param test_end: index of last test set example :param nb_epochs: number of epochs to train model :param batch_size: size of training batches :param learning_rate: learning rate for training :param clean_train: perform normal training on clean examples only before performing adversarial training. :param backprop_through_attack: If True, backprop through adversarial example construction process during adversarial training. :param label_smoothing: float, amount of label smoothing for cross entropy :return: an AccuracyReport object """ # Object used to keep track of (and return) key accuracies report = AccuracyReport() # Set TF random seed to improve reproducibility tf.set_random_seed(int(time.time() * 1000) % 2**31) np.random.seed(int(time.time() * 1001) % 2**31) # Set logging level to see debug information set_log_level(logging.DEBUG) # Create TF session if num_threads: config_args = dict(intra_op_parallelism_threads=1) else: config_args = {} sess = tf.Session(config=tf.ConfigProto(**config_args)) # Get CIFAR10 data data = CIFAR10(train_start=train_start, train_end=train_end, test_start=test_start, test_end=test_end) dataset_size = data.x_train.shape[0] dataset_train = data.to_tensorflow()[0] dataset_train = dataset_train.map( lambda x, y: (random_shift(random_horizontal_flip(x)), y), 4) dataset_train = dataset_train.batch(batch_size) dataset_train = dataset_train.prefetch(16) x_train, y_train = data.get_set('train') pgd_train = None if FLAGS.load_pgd_train_samples: pgd_path = os.path.expanduser('~/data/advhyp/{}/samples'.format( FLAGS.load_pgd_train_samples)) x_train = np.load(os.path.join(pgd_path, 'train_clean.npy')) y_train = np.load(os.path.join(pgd_path, 'train_y.npy')) pgd_train = np.load(os.path.join(pgd_path, 'train_pgd.npy')) if x_train.shape[1] == 3: x_train = x_train.transpose((0, 2, 3, 1)) pgd_train = pgd_train.transpose((0, 2, 3, 1)) if len(y_train.shape) == 1: y_tmp = np.zeros((len(y_train), np.max(y_train) + 1), y_train.dtype) y_tmp[np.arange(len(y_tmp)), y_train] = 1. y_train = y_tmp x_test, y_test = data.get_set('test') pgd_test = None if FLAGS.load_pgd_test_samples: pgd_path = os.path.expanduser('~/data/advhyp/{}/samples'.format( FLAGS.load_pgd_test_samples)) x_test = np.load(os.path.join(pgd_path, 'test_clean.npy')) y_test = np.load(os.path.join(pgd_path, 'test_y.npy')) pgd_test = np.load(os.path.join(pgd_path, 'test_pgd.npy')) if x_test.shape[1] == 3: x_test = x_test.transpose((0, 2, 3, 1)) pgd_test = pgd_test.transpose((0, 2, 3, 1)) if len(y_test.shape) == 1: y_tmp = np.zeros((len(y_test), np.max(y_test) + 1), y_test.dtype) y_tmp[np.arange(len(y_tmp)), y_test] = 1. y_test = y_tmp train_idcs = np.arange(len(x_train)) np.random.shuffle(train_idcs) x_train, y_train = x_train[train_idcs], y_train[train_idcs] if pgd_train is not None: pgd_train = pgd_train[train_idcs] test_idcs = np.arange(len(x_test))[:FLAGS.test_size] np.random.shuffle(test_idcs) x_test, y_test = x_test[test_idcs], y_test[test_idcs] if pgd_test is not None: pgd_test = pgd_test[test_idcs] # Use Image Parameters img_rows, img_cols, nchannels = x_test.shape[1:4] nb_classes = y_test.shape[1] # Define input TF placeholder x = tf.placeholder(tf.float32, shape=(None, img_rows, img_cols, nchannels)) y = tf.placeholder(tf.float32, shape=(None, nb_classes)) # Train an MNIST model train_params = { 'nb_epochs': nb_epochs, 'batch_size': batch_size, 'learning_rate': learning_rate } eval_params = {'batch_size': batch_size} pgd_params = { # ord: , 'eps': FLAGS.eps, 'eps_iter': (FLAGS.eps / 5), 'nb_iter': 10, 'clip_min': 0, 'clip_max': 255 } cw_params = { 'binary_search_steps': FLAGS.cw_search_steps, 'max_iterations': FLAGS.cw_steps, #1000 'abort_early': True, 'learning_rate': FLAGS.cw_lr, 'batch_size': batch_size, 'confidence': 0, 'initial_const': FLAGS.cw_c, 'clip_min': 0, 'clip_max': 255 } # Madry dosen't divide by 255 x_train *= 255 x_test *= 255 if pgd_train is not None: pgd_train *= 255 if pgd_test is not None: pgd_test *= 255 print('x_train amin={} amax={}'.format(np.amin(x_train), np.amax(x_train))) print('x_test amin={} amax={}'.format(np.amin(x_test), np.amax(x_test))) print( 'clip_min : {}, clip_max : {} >> CHECK WITH WHICH VALUES THE CLASSIFIER WAS PRETRAINED !!! <<' .format(pgd_params['clip_min'], pgd_params['clip_max'])) rng = np.random.RandomState() # [2017, 8, 30] debug_dict = dict() if FLAGS.save_debug_dict else None def do_eval(preds, x_set, y_set, report_key, is_adv=None, predictor=None, x_adv=None): if predictor is None: acc = model_eval(sess, x, y, preds, x_set, y_set, args=eval_params) else: do_eval(preds, x_set, y_set, report_key, is_adv=is_adv) if x_adv is not None: x_set_adv, = batch_eval(sess, [x], [x_adv], [x_set], batch_size=batch_size) assert x_set.shape == x_set_adv.shape x_set = x_set_adv n_batches = math.ceil(x_set.shape[0] / batch_size) p_set, p_det = np.concatenate([ predictor.send(x_set[b * batch_size:(b + 1) * batch_size]) for b in tqdm.trange(n_batches) ]).T acc = np.equal(p_set, y_set[:len(p_set)].argmax(-1)).mean() # if is_adv: # import IPython ; IPython.embed() ; exit(1) if FLAGS.save_debug_dict: debug_dict['x_set'] = x_set debug_dict['y_set'] = y_set ddfn = 'logs/debug_dict_{}.pkl'.format( 'adv' if is_adv else 'clean') if not os.path.exists(ddfn): with open(ddfn, 'wb') as f: pickle.dump(debug_dict, f) debug_dict.clear() if is_adv is None: report_text = None elif is_adv: report_text = 'adversarial' else: report_text = 'legitimate' if report_text: print('Test accuracy on %s examples %s: %0.4f' % (report_text, 'with correction' if predictor is not None else 'without correction', acc)) if is_adv is not None: label = 'test_acc_{}_{}'.format( report_text, 'corrected' if predictor else 'uncorrected') swriter.add_scalar(label, acc) if predictor is not None: detect = np.equal(p_det, is_adv).mean() label = 'test_det_{}_{}'.format( report_text, 'corrected' if predictor else 'uncorrected') print(label, detect) swriter.add_scalar(label, detect) label = 'test_dac_{}_{}'.format( report_text, 'corrected' if predictor else 'uncorrected') swriter.add_scalar( label, np.equal(p_set, y_set[:len(p_set)].argmax(-1))[np.equal( p_det, is_adv)].mean()) return acc if clean_train: if architecture == 'ConvNet': model = ModelAllConvolutional('model1', nb_classes, nb_filters, input_shape=[32, 32, 3]) elif architecture == 'ResNet': model = ResNet(scope='ResNet') else: raise Exception('Specify valid classifier architecture!') preds = model.get_logits(x) loss = CrossEntropy(model, smoothing=label_smoothing) if load_model: model_name = 'naturally_trained' if FLAGS.load_adv_trained: model_name = 'adv_trained' if ckpt_dir is not 'None': ckpt = tf.train.get_checkpoint_state( os.path.join(os.path.expanduser(ckpt_dir), model_name)) else: ckpt = tf.train.get_checkpoint_state('./models/' + model_name) ckpt_path = False if ckpt is None else ckpt.model_checkpoint_path saver = tf.train.Saver(var_list=dict( (v.name.split('/', 1)[1].split(':')[0], v) for v in tf.global_variables())) saver.restore(sess, ckpt_path) print('\nMODEL SUCCESSFULLY LOADED from : {}'.format(ckpt_path)) initialize_uninitialized_global_variables(sess) else: def evaluate(): do_eval(preds, x_test, y_test, 'clean_train_clean_eval', False) train(sess, loss, None, None, dataset_train=dataset_train, dataset_size=dataset_size, evaluate=evaluate, args=train_params, rng=rng, var_list=model.get_params()) logits_op = preds.op while logits_op.type != 'MatMul': logits_op = logits_op.inputs[0].op latent_x_tensor, weights = logits_op.inputs logits_tensor = preds nb_classes = weights.shape[-1].value if not FLAGS.save_pgd_samples: noise_eps = FLAGS.noise_eps.split(',') if FLAGS.noise_eps_detect is None: FLAGS.noise_eps_detect = FLAGS.noise_eps noise_eps_detect = FLAGS.noise_eps_detect.split(',') if pgd_train is not None: pgd_train = pgd_train[:FLAGS.n_collect] if not FLAGS.passthrough: predictor = tf_robustify.collect_statistics( x_train[:FLAGS.n_collect], y_train[:FLAGS.n_collect], x, sess, logits_tensor=logits_tensor, latent_x_tensor=latent_x_tensor, weights=weights, nb_classes=nb_classes, p_ratio_cutoff=FLAGS.p_ratio_cutoff, noise_eps=noise_eps, noise_eps_detect=noise_eps_detect, pgd_eps=pgd_params['eps'], pgd_lr=pgd_params['eps_iter'] / pgd_params['eps'], pgd_iters=pgd_params['nb_iter'], save_alignments_dir='logs/stats' if FLAGS.save_alignments else None, load_alignments_dir=os.path.expanduser( '~/data/advhyp/madry/stats') if FLAGS.load_alignments else None, clip_min=pgd_params['clip_min'], clip_max=pgd_params['clip_max'], batch_size=batch_size, num_noise_samples=FLAGS.num_noise_samples, debug_dict=debug_dict, debug=FLAGS.debug, targeted=False, pgd_train=pgd_train, fit_classifier=FLAGS.fit_classifier, clip_alignments=FLAGS.clip_alignments, just_detect=FLAGS.just_detect) else: def _predictor(): _x = yield while (_x is not None): _y = sess.run(preds, {x: _x}).argmax(-1) _x = yield np.stack((_y, np.zeros_like(_y)), -1) predictor = _predictor() next(predictor) if FLAGS.save_alignments: exit(0) # Evaluate the accuracy of the model on clean examples acc_clean = do_eval(preds, x_test, y_test, 'clean_train_clean_eval', False, predictor=predictor) # Initialize the PGD attack object and graph if FLAGS.attack == 'pgd': pgd = MadryEtAl(model, sess=sess) adv_x = pgd.generate(x, **pgd_params) elif FLAGS.attack == 'cw': cw = CarliniWagnerL2(model, sess=sess) adv_x = cw.generate(x, **cw_params) elif FLAGS.attack == 'mean': pgd = MadryEtAl(model, sess=sess) mean_eps = FLAGS.mean_eps * FLAGS.eps def _attack_mean(x): x_many = tf.tile(x[None], (FLAGS.mean_samples, 1, 1, 1)) x_noisy = x_many + tf.random_uniform(x_many.shape, -mean_eps, mean_eps) x_noisy = tf.clip_by_value(x_noisy, 0, 255) x_pgd = pgd.generate(x_noisy, **pgd_params) x_clip = tf.minimum(x_pgd, x_many + FLAGS.eps) x_clip = tf.maximum(x_clip, x_many - FLAGS.eps) x_clip = tf.clip_by_value(x_clip, 0, 255) return x_clip adv_x = tf.map_fn(_attack_mean, x) adv_x = tf.reduce_mean(adv_x, 1) preds_adv = model.get_logits(adv_x) if FLAGS.save_pgd_samples: for ds, y, name in ((x_train, y_train, 'train'), (x_test, y_test, 'test')): train_batches = math.ceil(len(ds) / FLAGS.batch_size) train_pgd = np.concatenate([ sess.run(adv_x, { x: ds[b * FLAGS.batch_size:(b + 1) * FLAGS.batch_size] }) for b in tqdm.trange(train_batches) ]) np.save('logs/{}_clean.npy'.format(name), ds / 255.) np.save('logs/{}_y.npy'.format(name), y) train_pgd /= 255. np.save('logs/{}_pgd.npy'.format(name), train_pgd) exit(0) # Evaluate the accuracy of the model on adversarial examples if not FLAGS.load_pgd_test_samples: acc_pgd = do_eval(preds_adv, x_test, y_test, 'clean_train_adv_eval', True, predictor=predictor, x_adv=adv_x) else: acc_pgd = do_eval(preds, pgd_test, y_test, 'clean_train_adv_eval', True, predictor=predictor) swriter.add_scalar('test_acc_mean', (acc_clean + acc_pgd) / 2., 0) print('Repeating the process, using adversarial training') exit(0) # Create a new model and train it to be robust to MadryEtAl if architecture == 'ConvNet': model2 = ModelAllConvolutional('model2', nb_classes, nb_filters, input_shape=[32, 32, 3]) elif architecture == 'ResNet': model = ResNet() else: raise Exception('Specify valid classifier architecture!') pgd2 = MadryEtAl(model2, sess=sess) def attack(x): return pgd2.generate(x, **pgd_params) loss2 = CrossEntropy(model2, smoothing=label_smoothing, attack=attack) preds2 = model2.get_logits(x) adv_x2 = attack(x) if not backprop_through_attack: # For some attacks, enabling this flag increases the cost of # training, but gives the defender the ability to anticipate how # the atacker will change their strategy in response to updates to # the defender's parameters. adv_x2 = tf.stop_gradient(adv_x2) preds2_adv = model2.get_logits(adv_x2) if load_model: if ckpt_dir is not 'None': ckpt = tf.train.get_checkpoint_state( os.path.join(os.path.expanduser(ckpt_dir), 'adv_trained')) else: ckpt = tf.train.get_checkpoint_state('./models/adv_trained') ckpt_path = False if ckpt is None else ckpt.model_checkpoint_path assert ckpt_path and tf_model_load( sess, file_path=ckpt_path), '\nMODEL LOADING FAILED' print('\nMODEL SUCCESSFULLY LOADED from : {}'.format(ckpt_path)) initialize_uninitialized_global_variables(sess) else: def evaluate2(): # Accuracy of adversarially trained model on legitimate test inputs do_eval(preds2, x_test, y_test, 'adv_train_clean_eval', False) # Accuracy of the adversarially trained model on adversarial # examples do_eval(preds2_adv, x_test, y_test, 'adv_train_adv_eval', True) # Perform and evaluate adversarial training train(sess, loss2, None, None, dataset_train=dataset_train, dataset_size=dataset_size, evaluate=evaluate2, args=train_params, rng=rng, var_list=model2.get_params()) # Evaluate model do_eval(preds2, x_test, y_test, 'adv_train_clean_eval', False) do_eval(preds2_adv, x_test, y_test, 'adv_train_adv_eval', True) return report