Secure your code as it's written. Use Snyk Code to scan source code in minutes - no build needed - and fix issues immediately.
def generate(self, x, y=None, **kwargs):
"""
Generate adversarial samples and return them in an array.
:param x: An array with the original inputs to be attacked.
:type x: `np.ndarray`
:param y: An array with the original labels to be predicted.
:type y: `np.ndarray`
:return: An array holding the adversarial examples.
:rtype: `np.ndarray`
"""
x_adv = x.astype(NUMPY_DTYPE)
preds = self.classifier.predict(x, batch_size=self.batch_size)
# Determine the class labels for which to compute the gradients
use_grads_subset = self.nb_grads < self.classifier.nb_classes()
if use_grads_subset:
# TODO compute set of unique labels per batch
grad_labels = np.argsort(-preds, axis=1)[:, :self.nb_grads]
labels_set = np.unique(grad_labels)
else:
labels_set = np.arange(self.classifier.nb_classes())
sorter = np.arange(len(labels_set))
# Pick a small scalar to avoid division by 0
tol = 10e-8
# Compute perturbation with implicit batching
if y is None:
# Throw error if attack is targeted, but no targets are provided
if self.targeted:
raise ValueError('Target labels `y` need to be provided for a targeted attack.')
# Use model predictions as correct outputs
targets = get_labels_np_array(self.classifier.predict(x, batch_size=self.batch_size))
else:
targets = y
adv_x_best = None
rate_best = None
for _ in range(max(1, self.num_random_init)):
adv_x = x.astype(NUMPY_DTYPE)
for i_max_iter in range(self.max_iter):
adv_x = self._compute(adv_x, x, targets, self.eps, self.eps_step, self._project,
self.num_random_init > 0 and i_max_iter == 0)
if self.num_random_init > 1:
rate = 100 * compute_success(self.classifier, x, targets, adv_x,
self.targeted, batch_size=self.batch_size)
if rate_best is None or rate > rate_best or adv_x_best is None:
rate_best = rate
adv_x_best = adv_x
else:
adv_x_best = adv_x
logger.info('Success rate of attack: %.2f%%', rate_best if rate_best is not None else
100 * compute_success(self.classifier, x, y, adv_x, self.targeted, batch_size=self.batch_size))
def _loss(self, x_adv, target):
"""
Compute the objective function value.
:param x_adv: An array with the adversarial input.
:type x_adv: `np.ndarray`
:param target: An array with the target class (one-hot encoded).
:type target: `np.ndarray`
:return: A tuple holding the current predictions and overall loss.
:rtype: `(float, float)`
"""
z_predicted = self.classifier.predict(np.array(x_adv, dtype=NUMPY_DTYPE), batch_size=self.batch_size)
z_target = np.sum(z_predicted * target, axis=1)
z_other = np.max(z_predicted * (1 - target) + (np.min(z_predicted, axis=1) - 1)[:, np.newaxis] * target, axis=1)
if self.targeted:
# if targeted, optimize for making the target class most likely
loss = np.maximum(z_other - z_target + self.confidence, np.zeros(x_adv.shape[0]))
else:
# if untargeted, optimize for making any other class most likely
loss = np.maximum(z_target - z_other + self.confidence, np.zeros(x_adv.shape[0]))
return z_predicted, loss
Perform prediction for a batch of inputs.
:param x: Test set.
:type x: `np.ndarray`
:param batch_size: Size of batches.
:type batch_size: `int`
:return: Array of predictions of shape `(nb_inputs, nb_classes)`.
:rtype: `np.ndarray`
"""
from art import NUMPY_DTYPE
# Apply defences
x_preprocessed, _ = self._apply_preprocessing(x, y=None, fit=False)
# Run predictions with batching
predictions = np.zeros((x_preprocessed.shape[0], self.nb_classes()), dtype=NUMPY_DTYPE)
for batch_index in range(int(np.ceil(x_preprocessed.shape[0] / float(batch_size)))):
begin, end = batch_index * batch_size, min((batch_index + 1) * batch_size, x_preprocessed.shape[0])
predictions[begin:end] = self._predictions(x_preprocessed[begin:end])
return predictions
"""
Compute the objective function value.
:param x: An array with the original input.
:type x: `np.ndarray`
:param x_adv: An array with the adversarial input.
:type x_adv: `np.ndarray`
:param target: An array with the target class (one-hot encoded).
:type target: `np.ndarray`
:param c_weight: Weight of the loss term aiming for classification as target.
:type c_weight: `float`
:return: A tuple holding the current logits, l2 distance and overall loss.
:rtype: `(float, float, float)`
"""
l2dist = np.sum(np.square(x - x_adv).reshape(x.shape[0], -1), axis=1)
z_predicted = self.classifier.predict(np.array(x_adv, dtype=NUMPY_DTYPE), logits=True,
batch_size=self.batch_size)
z_target = np.sum(z_predicted * target, axis=1)
z_other = np.max(z_predicted * (1 - target) + (np.min(z_predicted, axis=1) - 1)[:, np.newaxis] * target, axis=1)
# The following differs from the exact definition given in Carlini and Wagner (2016). There (page 9, left
# column, last equation), the maximum is taken over Z_other - Z_target (or Z_target - Z_other respectively)
# and -confidence. However, it doesn't seem that that would have the desired effect (loss term is <= 0 if and
# only if the difference between the logit of the target and any other class differs by at least confidence).
# Hence the rearrangement here.
if self.targeted:
# if targeted, optimize for making the target class most likely
loss = np.maximum(z_other - z_target + self.confidence, np.zeros(x.shape[0]))
else:
# if untargeted, optimize for making any other class most likely
loss = np.maximum(z_target - z_other + self.confidence, np.zeros(x.shape[0]))
def _loss(self, x, x_adv):
"""
Compute the loss function values.
:param x: An array with the original input.
:type x: `np.ndarray`
:param x_adv: An array with the adversarial input.
:type x_adv: `np.ndarray`
:return: A tuple holding the current predictions, l1 distance, l2 distance and elastic net loss.
:rtype: `(np.ndarray, float, float, float)`
"""
l1dist = np.sum(np.abs(x - x_adv).reshape(x.shape[0], -1), axis=1)
l2dist = np.sum(np.square(x - x_adv).reshape(x.shape[0], -1), axis=1)
endist = self.beta * l1dist + l2dist
predictions = self.classifier.predict(np.array(x_adv, dtype=NUMPY_DTYPE), batch_size=self.batch_size)
return np.argmax(predictions, axis=1), l1dist, l2dist, endist
def _resize_image(self, x, size_x, size_y, reset=False):
if self.classifier.channel_index == 3:
dims = (x.shape[0], size_x, size_y, x.shape[-1])
elif self.classifier.channel_index == 1:
dims = (x.shape[0], x.shape[1], size_x, size_y)
nb_vars = np.prod(dims)
if reset:
# Reset variables to original size and value
if dims == x.shape:
resized_x = x
self._current_noise.fill(0)
else:
resized_x = zoom(x, (1, dims[1] / x.shape[1], dims[2] / x.shape[2], dims[3] / x.shape[3]))
self._current_noise = np.zeros(dims, dtype=NUMPY_DTYPE)
self._sample_prob = np.ones(nb_vars, dtype=NUMPY_DTYPE) / nb_vars
else:
# Rescale variables and reset values
resized_x = zoom(x, (1, dims[1] / x.shape[1], dims[2] / x.shape[2], dims[3] / x.shape[3]))
self._sample_prob = self._get_prob(self._current_noise, double=True).flatten()
self._current_noise = np.zeros(dims, dtype=NUMPY_DTYPE)
# Reset Adam
self._reset_adam(nb_vars)
return resized_x
def _compute(self, x, x_init, y, eps, eps_step, project, random_init):
if random_init:
n = x.shape[0]
m = np.prod(x.shape[1:])
x_adv = x.astype(NUMPY_DTYPE) + random_sphere(n, m, eps, self.norm).reshape(x.shape).astype(NUMPY_DTYPE)
if hasattr(self.classifier, 'clip_values') and self.classifier.clip_values is not None:
clip_min, clip_max = self.classifier.clip_values
x_adv = np.clip(x_adv, clip_min, clip_max)
else:
x_adv = x.astype(NUMPY_DTYPE)
# Compute perturbation with implicit batching
for batch_id in range(int(np.ceil(x.shape[0] / float(self.batch_size)))):
batch_index_1, batch_index_2 = batch_id * self.batch_size, (batch_id + 1) * self.batch_size
batch = x_adv[batch_index_1:batch_index_2]
batch_labels = y[batch_index_1:batch_index_2]
# Get perturbation
perturbation = self._compute_perturbation(batch, batch_labels)
Perform prediction for a batch of inputs.
:param x: Test set.
:type x: `np.ndarray`
:param batch_size: Size of batches.
:type batch_size: `int`
:return: Array of predictions of shape `(nb_inputs, nb_classes)`.
:rtype: `np.ndarray`
"""
from art import NUMPY_DTYPE
# Apply defences
x_preprocessed, _ = self._apply_preprocessing(x, y=None, fit=False)
# Run predictions with batching
predictions = np.zeros((x_preprocessed.shape[0], self.nb_classes()), dtype=NUMPY_DTYPE)
for batch_index in range(int(np.ceil(x_preprocessed.shape[0] / float(batch_size)))):
begin, end = batch_index * batch_size, min((batch_index + 1) * batch_size, x_preprocessed.shape[0])
predictions[begin:end] = self._predictions([x_preprocessed[begin:end]])[0]
return predictions