Add attack for virtual adversarial training
@@ -413,6 +413,79 @@ class SaliencyMapMethod(Attack):
return True
+class VirtualAdversarialMethod(Attack):
+ """
+ This attack was originally proposed by Miyato et al. (2016) and was used
+ for virtual adversarial training.
+ Paper link: https://arxiv.org/abs/1507.00677
+
+ """
+ def __init__(self, model, back='tf', sess=None):
+ super(VirtualAdversarialMethod, self).__init__(model, back, sess)
+
+ def generate(self, x, **kwargs):
+ """
+ Generate symbolic graph for adversarial examples and return.
+ :param x: The model's symbolic inputs.
+ :param eps: (optional float ) the epsilon (input variation parameter)
+ :param num_iterations: (optional) the number of iterations
+ :param xi: (optional float) the finite difference parameter
+ :param clip_min: (optional float) Minimum input component value
+ :param clip_max: (optional float) Maximum input component value
+ """
+ # Parse and save attack-specific parameters
+ assert self.parse_params(**kwargs)
+
+ return vatm(self.model, x, self.model(x), eps=self.eps,
+ num_iterations=self.num_iterations, xi=self.xi,
+ clip_min=self.clip_min, clip_max=self.clip_max)
+
+ def generate_np(self, x_val, **kwargs):
+ """
+ Generate adversarial samples and return them in a Numpy array.
+ :param x_val: (required) A Numpy array with the original inputs.
+ :param eps: (optional float )the epsilon (input variation parameter)
+ :param num_iterations: (optional) the number of iterations
+ :param xi: (optional float) the finite difference parameter
+ :param clip_min: (optional float) Minimum input component value
+ :param clip_max: (optional float) Maximum input component value
+ """
+ if self.back == 'th':
+ raise NotImplementedError('Theano version not implemented.')
+
+ import tensorflow as tf
+
+ # Generate this attack's graph if it hasn't been done previously
+ if not hasattr(self, "_x"):
+ input_shape = list(x_val.shape)
+ input_shape[0] = None
+ self._x = tf.placeholder(tf.float32, shape=input_shape)
+ self._x_adv = self.generate(self._x, **kwargs)
+
+ return self.sess.run(self._x_adv, feed_dict={self._x: x_val})
+
+ def parse_params(self, eps=2.0, num_iterations=1, xi=1e-6, clip_min=None,
+ clip_max=None, **kwargs):
+ """
+ Take in a dictionary of parameters and applies attack-specific checks
+ before saving them as attributes.
+
+ Attack-specific parameters:
+ :param eps: (optional float )the epsilon (input variation parameter)
+ :param num_iterations: (optional) the number of iterations
+ :param xi: (optional float) the finite difference parameter
+ :param clip_min: (optional float) Minimum input component value
+ :param clip_max: (optional float) Maximum input component value
+ """
+ # Save attack-specific parameters
+ self.eps = eps
+ self.num_iterations = num_iterations
+ self.xi = xi
+ self.clip_min = clip_min
+ self.clip_max = clip_max
+ return True
+
+
def fgsm(x, predictions, eps, back='tf', clip_min=None, clip_max=None):
"""
A wrapper for the Fast Gradient Sign Method.
