Skip to content

Commit d164140

Browse files
Irina NicolaeIrina Nicolae
authored andcommitted
Optimize FGSM minimal perturbation
1 parent 150b389 commit d164140

File tree

2 files changed

+15
-15
lines changed

2 files changed

+15
-15
lines changed

src/attacks/fast_gradient.py

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -31,10 +31,10 @@ def __init__(self, classifier, sess=None, ord=np.inf, y=None, targeted=False, cl
3131
kwargs = {'ord': ord, 'targeted': targeted, 'clip_min': clip_min, 'clip_max': clip_max, 'y': y}
3232
self.set_params(**kwargs)
3333

34-
def generate_graph(self, x, eps=0.3, **kwargs):
34+
def generate_graph(self, x, eps, **kwargs):
3535
"""Generate symbolic graph for adversarial examples and return.
3636
:param x: The model's symbolic inputs.
37-
:param eps: (optional float) attack step size (input variation)
37+
:param eps: (optional tf.placeholder) The placeholder for input variation (noise amplitude)
3838
:param ord: (optional) Order of the norm (mimics Numpy). Possible values: np.inf, 1 or 2.
3939
:param y: (optional) A placeholder for the model labels. Only provide this parameter if you'd like to use true
4040
labels when crafting adversarial samples. Otherwise, model predictions are used as labels to avoid the
@@ -93,21 +93,20 @@ def minimal_perturbations(self, x, x_val, eps_step=0.1, eps_max=1., **kwargs):
9393
y = np.argmax(self.model.predict(x_val), 1)
9494
adv_x = x_val.copy()
9595

96-
curr_indexes = np.arange(len(x_val))
97-
eps = eps_step
96+
curr_indexes = np.arange(len(adv_x))
97+
eps = tf.placeholder(tf.float32, None)
98+
adv_x_op = self.generate_graph(x, eps, **kwargs)
99+
adv_y = tf.argmax(self.model(adv_x_op), 1)
100+
eps_val = eps_step
98101

99-
while len(curr_indexes) != 0 and eps <= eps_max:
102+
while len(curr_indexes) != 0 and eps_val <= eps_max:
100103
# Adversarial crafting
101-
adv_x_op = self.generate_graph(x, eps=eps, **kwargs)
102-
adv_y = tf.argmax(self.model(adv_x_op), 1)
103-
104-
new_adv_x, new_y = self.sess.run([adv_x_op, adv_y], {x: x_val[curr_indexes]})
104+
new_adv_x, new_y = self.sess.run([adv_x_op, adv_y], {x: x_val[curr_indexes], eps: eps_val})
105105

106106
# Update
107107
adv_x[curr_indexes] = new_adv_x
108108
curr_indexes = np.where(y[curr_indexes] == new_y)[0]
109-
110-
eps += eps_step
109+
eps_val += eps_step
111110

112111
return adv_x
113112

@@ -125,14 +124,15 @@ def generate(self, x_val, **kwargs):
125124
:return: A Numpy array holding the adversarial examples.
126125
"""
127126

128-
input_shape = list(x_val.shape)
129-
input_shape[0] = None
127+
input_shape = [None] + list(x_val.shape[1:])
130128
self._x = tf.placeholder(tf.float32, shape=input_shape)
131129
k.set_learning_phase(0)
132130

131+
# Return adversarial examples computed with minimal perturbation if option is active
133132
if "minimal" in kwargs and kwargs["minimal"]:
134133
return self.minimal_perturbations(self._x, x_val, **kwargs)
135134

135+
# Generate computation graph
136136
self._x_adv = self.generate_graph(self._x, **kwargs)
137137

138138
# Run symbolic graph without or with true labels

src/attacks/fast_gradient_unittest.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -83,10 +83,10 @@ def test_mnist(self):
8383
self.assertFalse((Y_test == test_y_pred).all())
8484

8585
scores = classifier.evaluate(X_train_adv_min, Y_train)
86-
print('\naccuracy on adversarial train examples: %.2f%%' % (scores[1] * 100))
86+
print('\naccuracy on adversarial train examples with minimal perturbation: %.2f%%' % (scores[1] * 100))
8787

8888
scores = classifier.evaluate(X_test_adv_min, Y_test)
89-
print('\naccuracy on adversarial test examples: %.2f%%' % (scores[1] * 100))
89+
print('\naccuracy on adversarial test examples with minimal perturbation: %.2f%%' % (scores[1] * 100))
9090

9191
def test_with_preprocessing(self):
9292

0 commit comments

Comments
 (0)