Skip to content

Commit 1edd5b2

Browse files
Irina NicolaeIrina Nicolae
authored andcommitted
Merge branch 'dev'
Changes: - Add logging - Add PGD evasion attack - Add model theft attack and sigmoid defence - Add thermometer encoding in defences - Correct adversarial trainer to match Madry setup - Update examples and notebooks - Add visualization module Conflicts: notebooks/adversarial-training-mnist.ipynb
2 parents a031768 + 1b4a8fe commit 1edd5b2

File tree

78 files changed

+2654
-676
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

78 files changed

+2654
-676
lines changed

art/__init__.py

Lines changed: 41 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,42 @@
1+
import json
2+
import logging
3+
import logging.config
14
import os
25

3-
import json
6+
from numpy import float32
7+
8+
LOGGING = {
9+
'version': 1,
10+
'disable_existing_loggers': False,
11+
'formatters': {
12+
'std': {
13+
'format': '%(asctime)s [%(levelname)s] %(name)s: %(message)s',
14+
'datefmt': '%Y-%m-%d %H:%M'
15+
}
16+
},
17+
'handlers': {
18+
'default': {
19+
'class': 'logging.NullHandler',
20+
},
21+
'test': {
22+
'class': 'logging.StreamHandler',
23+
'formatter': 'std',
24+
'level': logging.DEBUG
25+
}
26+
},
27+
'loggers': {
28+
'': {
29+
'handlers': ['default']
30+
},
31+
'testLogger': {
32+
'handlers': ['test'],
33+
'level': 'INFO',
34+
'propagate': True
35+
}
36+
}
37+
}
38+
logging.config.dictConfig(LOGGING)
39+
logger = logging.getLogger(__name__)
440

541
_folder = os.path.expanduser('~')
642
if not os.access(_folder, os.W_OK):
@@ -19,8 +55,7 @@
1955
try:
2056
os.makedirs(_folder)
2157
except OSError:
22-
# Log warning here
23-
pass
58+
logger.warning('Unable to create folder for configuration file.', exc_info=True)
2459

2560
if not os.path.exists(_config_path):
2661
# Generate default config
@@ -30,8 +65,9 @@
3065
with open(_config_path, 'w') as f:
3166
f.write(json.dumps(_config, indent=4))
3267
except IOError:
33-
# Log warning here
34-
pass
68+
logger.warning('Unable to create configuration file', exc_info=True)
3569

3670
if 'DATA_PATH' in _config:
3771
DATA_PATH = _config['DATA_PATH']
72+
73+
NUMPY_DTYPE = float32

art/attacks/__init__.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,9 @@
77
from art.attacks.fast_gradient import FastGradientMethod
88
from art.attacks.iterative_method import BasicIterativeMethod
99
from art.attacks.newtonfool import NewtonFool
10+
from art.attacks.projected_gradient_descent import ProjectedGradientDescent
1011
from art.attacks.saliency_map import SaliencyMapMethod
1112
from art.attacks.universal_perturbation import UniversalPerturbation
1213
from art.attacks.virtual_adversarial import VirtualAdversarialMethod
14+
from art.attacks.model_theft import ModelTheft
15+
from art.attacks.sampling_model_theft import SamplingModelTheft

art/attacks/carlini.py

Lines changed: 184 additions & 68 deletions
Large diffs are not rendered by default.

art/attacks/carlini_unittest.py

Lines changed: 38 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,23 @@
11
from __future__ import absolute_import, division, print_function, unicode_literals
22

3-
import tensorflow as tf
4-
import numpy as np
3+
import logging
54
import unittest
5+
66
import keras
77
import keras.backend as k
8-
from keras.models import Sequential
9-
from keras.layers import Dense, Flatten, Conv2D, MaxPooling2D
8+
import numpy as np
9+
import tensorflow as tf
1010
import torch.nn as nn
1111
import torch.optim as optim
12+
from keras.layers import Dense, Flatten, Conv2D, MaxPooling2D
13+
from keras.models import Sequential
1214

13-
from art.attacks.carlini import CarliniL2Method
14-
from art.classifiers.tensorflow import TFClassifier
15-
from art.classifiers.keras import KerasClassifier
16-
from art.classifiers.pytorch import PyTorchClassifier
15+
from art.attacks import CarliniL2Method
16+
from art.classifiers import KerasClassifier, PyTorchClassifier, TFClassifier
1717
from art.utils import load_mnist, random_targets
1818

19+
logger = logging.getLogger('testLogger')
20+
1921
BATCH_SIZE, NB_TRAIN, NB_TEST = 100, 5000, 10
2022

2123

@@ -84,7 +86,7 @@ def test_failure_attack(self):
8486

8587
# Failure attack
8688
cl2m = CarliniL2Method(classifier=tfc, targeted=True, max_iter=0, binary_search_steps=0,
87-
learning_rate=0, initial_const=1, decay=0)
89+
learning_rate=0, initial_const=1)
8890
params = {'y': random_targets(y_test, tfc.nb_classes)}
8991
x_test_adv = cl2m.generate(x_test, **params)
9092
self.assertTrue((x_test_adv <= 1.0001).all())
@@ -126,48 +128,44 @@ def test_tfclassifier(self):
126128
tfc.fit(x_train, y_train, batch_size=BATCH_SIZE, nb_epochs=10)
127129

128130
# First attack
129-
cl2m = CarliniL2Method(classifier=tfc, targeted=True, max_iter=100, binary_search_steps=1,
130-
learning_rate=1, initial_const=10, decay=0)
131+
cl2m = CarliniL2Method(classifier=tfc, targeted=True, max_iter=10)
131132
params = {'y': random_targets(y_test, tfc.nb_classes)}
132133
x_test_adv = cl2m.generate(x_test, **params)
133134
self.assertFalse((x_test == x_test_adv).all())
134135
self.assertTrue((x_test_adv <= 1.0001).all())
135136
self.assertTrue((x_test_adv >= -0.0001).all())
136137
target = np.argmax(params['y'], axis=1)
137138
y_pred_adv = np.argmax(tfc.predict(x_test_adv), axis=1)
138-
print("CW2 Target: %s" % target)
139-
print("CW2 Actual: %s" % y_pred_adv)
140-
print("CW2 Success Rate: %f" % (sum(target == y_pred_adv)/float(len(target))))
139+
logger.debug('CW2 Target: %s', target)
140+
logger.debug('CW2 Actual: %s', y_pred_adv)
141+
logger.info('CW2 Success Rate: %.2f', (sum(target == y_pred_adv) / float(len(target))))
141142
self.assertTrue((target == y_pred_adv).any())
142143

143144
# Second attack
144-
cl2m = CarliniL2Method(classifier=tfc, targeted=False, max_iter=100, binary_search_steps=1,
145-
learning_rate=1, initial_const=10, decay=0)
145+
cl2m = CarliniL2Method(classifier=tfc, targeted=False, max_iter=10)
146146
params = {'y': random_targets(y_test, tfc.nb_classes)}
147147
x_test_adv = cl2m.generate(x_test, **params)
148-
self.assertFalse((x_test == x_test_adv).all())
149148
self.assertTrue((x_test_adv <= 1.0001).all())
150149
self.assertTrue((x_test_adv >= -0.0001).all())
151150
target = np.argmax(params['y'], axis=1)
152151
y_pred_adv = np.argmax(tfc.predict(x_test_adv), axis=1)
153-
print("CW2 Target: %s" % target)
154-
print("CW2 Actual: %s" % y_pred_adv)
155-
print("CW2 Success Rate: %f" % (sum(target != y_pred_adv)/float(len(target))))
152+
logger.debug('CW2 Target: %s', target)
153+
logger.debug('CW2 Actual: %s', y_pred_adv)
154+
logger.info('CW2 Success Rate: %.2f', (sum(target == y_pred_adv) / float(len(target))))
156155
self.assertTrue((target != y_pred_adv).any())
157156

158157
# Third attack
159-
cl2m = CarliniL2Method(classifier=tfc, targeted=False, max_iter=100, binary_search_steps=1,
160-
learning_rate=1, initial_const=10, decay=0)
158+
cl2m = CarliniL2Method(classifier=tfc, targeted=False, max_iter=10)
161159
params = {}
162160
x_test_adv = cl2m.generate(x_test, **params)
163161
self.assertFalse((x_test == x_test_adv).all())
164162
self.assertTrue((x_test_adv <= 1.0001).all())
165163
self.assertTrue((x_test_adv >= -0.0001).all())
166164
y_pred = np.argmax(tfc.predict(x_test), axis=1)
167165
y_pred_adv = np.argmax(tfc.predict(x_test_adv), axis=1)
168-
print("CW2 Target: %s" % y_pred)
169-
print("CW2 Actual: %s" % y_pred_adv)
170-
print("CW2 Success Rate: %f" % (sum(y_pred != y_pred_adv)/float(len(y_pred))))
166+
logger.debug('CW2 Target: %s', y_pred)
167+
logger.debug('CW2 Actual: %s', y_pred_adv)
168+
logger.info('CW2 Success Rate: %.2f', (sum(y_pred != y_pred_adv) / float(len(y_pred))))
171169
self.assertTrue((y_pred != y_pred_adv).any())
172170

173171
def test_krclassifier(self):
@@ -197,48 +195,44 @@ def test_krclassifier(self):
197195
krc.fit(x_train, y_train, batch_size=BATCH_SIZE, nb_epochs=10)
198196

199197
# First attack
200-
cl2m = CarliniL2Method(classifier=krc, targeted=True, max_iter=100, binary_search_steps=1,
201-
learning_rate=1, initial_const=10, decay=0)
198+
cl2m = CarliniL2Method(classifier=krc, targeted=True, max_iter=10)
202199
params = {'y': random_targets(y_test, krc.nb_classes)}
203200
x_test_adv = cl2m.generate(x_test, **params)
204201
self.assertFalse((x_test == x_test_adv).all())
205202
self.assertTrue((x_test_adv <= 1.0001).all())
206203
self.assertTrue((x_test_adv >= -0.0001).all())
207204
target = np.argmax(params['y'], axis=1)
208205
y_pred_adv = np.argmax(krc.predict(x_test_adv), axis=1)
209-
print("CW2 Target: %s" % target)
210-
print("CW2 Actual: %s" % y_pred_adv)
211-
print("CW2 Success Rate: %f" % (sum(target == y_pred_adv)/float(len(target))))
206+
logger.debug('CW2 Target: %s', target)
207+
logger.debug('CW2 Actual: %s', y_pred_adv)
208+
logger.info('CW2 Success Rate: %.2f', (sum(target == y_pred_adv) / float(len(target))))
212209
self.assertTrue((target == y_pred_adv).any())
213210

214211
# Second attack
215-
cl2m = CarliniL2Method(classifier=krc, targeted=False, max_iter=100, binary_search_steps=1,
216-
learning_rate=1, initial_const=10, decay=0)
212+
cl2m = CarliniL2Method(classifier=krc, targeted=False, max_iter=10)
217213
params = {'y': random_targets(y_test, krc.nb_classes)}
218214
x_test_adv = cl2m.generate(x_test, **params)
219-
self.assertFalse((x_test == x_test_adv).all())
220215
self.assertTrue((x_test_adv <= 1.0001).all())
221216
self.assertTrue((x_test_adv >= -0.0001).all())
222217
target = np.argmax(params['y'], axis=1)
223218
y_pred_adv = np.argmax(krc.predict(x_test_adv), axis=1)
224-
print("CW2 Target: %s" % target)
225-
print("CW2 Actual: %s" % y_pred_adv)
226-
print("CW2 Success Rate: %f" % (sum(target != y_pred_adv)/float(len(target))))
219+
logger.debug('CW2 Target: %s', target)
220+
logger.debug('CW2 Actual: %s', y_pred_adv)
221+
logger.info('CW2 Success Rate: %.2f', (sum(target != y_pred_adv) / float(len(target))))
227222
self.assertTrue((target != y_pred_adv).any())
228223

229224
# Third attack
230-
cl2m = CarliniL2Method(classifier=krc, targeted=False, max_iter=100, binary_search_steps=1,
231-
learning_rate=1, initial_const=10, decay=0)
225+
cl2m = CarliniL2Method(classifier=krc, targeted=False, max_iter=10)
232226
params = {}
233227
x_test_adv = cl2m.generate(x_test, **params)
234228
self.assertFalse((x_test == x_test_adv).all())
235229
self.assertTrue((x_test_adv <= 1.0001).all())
236230
self.assertTrue((x_test_adv >= -0.0001).all())
237231
y_pred = np.argmax(krc.predict(x_test), axis=1)
238232
y_pred_adv = np.argmax(krc.predict(x_test_adv), axis=1)
239-
print("CW2 Target: %s" % y_pred)
240-
print("CW2 Actual: %s" % y_pred_adv)
241-
print("CW2 Success Rate: %f" % (sum(y_pred != y_pred_adv)/float(len(y_pred))))
233+
logger.debug('CW2 Target: %s', y_pred)
234+
logger.debug('CW2 Actual: %s', y_pred_adv)
235+
logger.info('CW2 Success Rate: %.2f', (sum(y_pred != y_pred_adv) / float(len(y_pred))))
242236
self.assertTrue((y_pred != y_pred_adv).any())
243237

244238
def test_ptclassifier(self):
@@ -263,8 +257,7 @@ def test_ptclassifier(self):
263257
ptc.fit(x_train, y_train, batch_size=BATCH_SIZE, nb_epochs=10)
264258

265259
# First attack
266-
cl2m = CarliniL2Method(classifier=ptc, targeted=True, max_iter=100, binary_search_steps=1,
267-
learning_rate=1, initial_const=10, decay=0)
260+
cl2m = CarliniL2Method(classifier=ptc, targeted=True, max_iter=10)
268261
params = {'y': random_targets(y_test, ptc.nb_classes)}
269262
x_test_adv = cl2m.generate(x_test, **params)
270263
self.assertFalse((x_test == x_test_adv).all())
@@ -275,20 +268,17 @@ def test_ptclassifier(self):
275268
self.assertTrue((target == y_pred_adv).any())
276269

277270
# Second attack
278-
cl2m = CarliniL2Method(classifier=ptc, targeted=False, max_iter=100, binary_search_steps=1,
279-
learning_rate=1, initial_const=10, decay=0)
271+
cl2m = CarliniL2Method(classifier=ptc, targeted=False, max_iter=10)
280272
params = {'y': random_targets(y_test, ptc.nb_classes)}
281273
x_test_adv = cl2m.generate(x_test, **params)
282-
self.assertFalse((x_test == x_test_adv).all())
283274
self.assertTrue((x_test_adv <= 1.0001).all())
284275
self.assertTrue((x_test_adv >= -0.0001).all())
285276
target = np.argmax(params['y'], axis=1)
286277
y_pred_adv = np.argmax(ptc.predict(x_test_adv), axis=1)
287278
self.assertTrue((target != y_pred_adv).any())
288279

289280
# Third attack
290-
cl2m = CarliniL2Method(classifier=ptc, targeted=False, max_iter=100, binary_search_steps=1,
291-
learning_rate=1, initial_const=10, decay=0)
281+
cl2m = CarliniL2Method(classifier=ptc, targeted=False, max_iter=10)
292282
params = {}
293283
x_test_adv = cl2m.generate(x_test, **params)
294284
self.assertFalse((x_test == x_test_adv).all())

art/attacks/deepfool.py

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,34 @@
11
from __future__ import absolute_import, division, print_function, unicode_literals
22

3+
import logging
4+
35
import numpy as np
46

57
from art.attacks.attack import Attack
68

9+
logger = logging.getLogger(__name__)
10+
711

812
class DeepFool(Attack):
913
"""
1014
Implementation of the attack from Moosavi-Dezfooli et al. (2015).
1115
Paper link: https://arxiv.org/abs/1511.04599
1216
"""
13-
attack_params = Attack.attack_params + ['max_iter']
17+
attack_params = Attack.attack_params + ['max_iter', 'epsilon']
1418

15-
def __init__(self, classifier, max_iter=100):
19+
def __init__(self, classifier, max_iter=100, epsilon=1e-6):
1620
"""
1721
Create a DeepFool attack instance.
1822
1923
:param classifier: A trained model.
2024
:type classifier: :class:`Classifier`
2125
:param max_iter: The maximum number of iterations.
2226
:type max_iter: `int`
27+
:param epsilon: Overshoot parameter.
28+
:type epsilon: `float`
2329
"""
2430
super(DeepFool, self).__init__(classifier)
25-
params = {'max_iter': max_iter}
31+
params = {'max_iter': max_iter, 'epsilon': epsilon}
2632
self.set_params(**params)
2733

2834
def generate(self, x, **kwargs):
@@ -33,6 +39,8 @@ def generate(self, x, **kwargs):
3339
:type x: `np.ndarray`
3440
:param max_iter: The maximum number of iterations.
3541
:type max_iter: `int`
42+
:param epsilon: Overshoot parameter.
43+
:type epsilon: `float`
3644
:return: An array holding the adversarial examples.
3745
:rtype: `np.ndarray`
3846
"""
@@ -64,7 +72,7 @@ def generate(self, x, **kwargs):
6472
value = np.ma.array(np.abs(f_diff) / norm, mask=mask)
6573

6674
l = value.argmin(fill_value=np.inf)
67-
r = (abs(f_diff[l]) / pow(np.linalg.norm(grad_diff[l]), 2)) * grad_diff[l]
75+
r = (abs(f_diff[l]) / (pow(np.linalg.norm(grad_diff[l]), 2) + tol)) * grad_diff[l]
6876

6977
# Add perturbation and clip result
7078
xj = np.clip(xj + r, clip_min, clip_max)
@@ -76,7 +84,11 @@ def generate(self, x, **kwargs):
7684

7785
nb_iter += 1
7886

79-
x_adv[j] = xj[0]
87+
x_adv[j] = np.clip(x[j] + (1 + self.epsilon) * (xj[0] - x[j]), clip_min, clip_max)
88+
89+
preds = np.argmax(self.classifier.predict(x), axis=1)
90+
preds_adv = np.argmax(self.classifier.predict(x_adv), axis=1)
91+
logger.info('Success rate of DeepFool attack: %.2f%%', (np.sum(preds != preds_adv) / x.shape[0]))
8092

8193
return x_adv
8294

@@ -92,4 +104,8 @@ def set_params(self, **kwargs):
92104
if type(self.max_iter) is not int or self.max_iter <= 0:
93105
raise ValueError("The number of iterations must be a positive integer.")
94106

107+
if self.epsilon < 0:
108+
raise ValueError("The overshoot parameter must not be negative.")
109+
95110
return True
111+

0 commit comments

Comments
 (0)