Skip to content

Commit dee4797

Browse files
mikebrowSvetlana Karslioglu
and
Svetlana Karslioglu
authored
add vectorization options as a goal target (#2483)
* add vectorization options as a goal target Signed-off-by: Mike Brown <[email protected]> Co-authored-by: Svetlana Karslioglu <[email protected]>
1 parent dcb527d commit dee4797

File tree

1 file changed

+38
-34
lines changed

1 file changed

+38
-34
lines changed

beginner_source/fgsm_tutorial.py

+38-34
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@
2727
######################################################################
2828
# Threat Model
2929
# ------------
30-
#
30+
#
3131
# For context, there are many categories of adversarial attacks, each with
3232
# a different goal and assumption of the attacker’s knowledge. However, in
3333
# general the overarching goal is to add the least amount of perturbation
@@ -45,14 +45,14 @@
4545
# misclassification* means the adversary wants to alter an image that is
4646
# originally of a specific source class so that it is classified as a
4747
# specific target class.
48-
#
48+
#
4949
# In this case, the FGSM attack is a *white-box* attack with the goal of
5050
# *misclassification*. With this background information, we can now
5151
# discuss the attack in detail.
52-
#
52+
#
5353
# Fast Gradient Sign Attack
5454
# -------------------------
55-
#
55+
#
5656
# One of the first and most popular adversarial attacks to date is
5757
# referred to as the *Fast Gradient Sign Attack (FGSM)* and is described
5858
# by Goodfellow et. al. in `Explaining and Harnessing Adversarial
@@ -64,7 +64,7 @@
6464
# the loss* based on the same backpropagated gradients. In other words,
6565
# the attack uses the gradient of the loss w.r.t the input data, then
6666
# adjusts the input data to maximize the loss.
67-
#
67+
#
6868
# Before we jump into the code, let’s look at the famous
6969
# `FGSM <https://arxiv.org/abs/1412.6572>`__ panda example and extract
7070
# some notation.
@@ -85,10 +85,10 @@
8585
# maximize the loss. The resulting perturbed image, :math:`x'`, is then
8686
# *misclassified* by the target network as a “gibbon” when it is still
8787
# clearly a “panda”.
88-
#
88+
#
8989
# Hopefully now the motivation for this tutorial is clear, so lets jump
9090
# into the implementation.
91-
#
91+
#
9292

9393
import torch
9494
import torch.nn as nn
@@ -102,33 +102,33 @@
102102
######################################################################
103103
# Implementation
104104
# --------------
105-
#
105+
#
106106
# In this section, we will discuss the input parameters for the tutorial,
107107
# define the model under attack, then code the attack and run some tests.
108-
#
108+
#
109109
# Inputs
110110
# ~~~~~~
111-
#
111+
#
112112
# There are only three inputs for this tutorial, and are defined as
113113
# follows:
114-
#
114+
#
115115
# - ``epsilons`` - List of epsilon values to use for the run. It is
116116
# important to keep 0 in the list because it represents the model
117117
# performance on the original test set. Also, intuitively we would
118118
# expect the larger the epsilon, the more noticeable the perturbations
119119
# but the more effective the attack in terms of degrading model
120120
# accuracy. Since the data range here is :math:`[0,1]`, no epsilon
121121
# value should exceed 1.
122-
#
122+
#
123123
# - ``pretrained_model`` - path to the pretrained MNIST model which was
124124
# trained with
125125
# `pytorch/examples/mnist <https://github.com/pytorch/examples/tree/master/mnist>`__.
126126
# For simplicity, download the pretrained model `here <https://drive.google.com/file/d/1HJV2nUHJqclXQ8flKvcWmjZ-OU5DGatl/view?usp=drive_link>`__.
127-
#
127+
#
128128
# - ``use_cuda`` - boolean flag to use CUDA if desired and available.
129129
# Note, a GPU with CUDA is not critical for this tutorial as a CPU will
130130
# not take much time.
131-
#
131+
#
132132

133133
epsilons = [0, .05, .1, .15, .2, .25, .3]
134134
pretrained_model = "data/lenet_mnist_model.pth"
@@ -140,15 +140,15 @@
140140
######################################################################
141141
# Model Under Attack
142142
# ~~~~~~~~~~~~~~~~~~
143-
#
143+
#
144144
# As mentioned, the model under attack is the same MNIST model from
145145
# `pytorch/examples/mnist <https://github.com/pytorch/examples/tree/master/mnist>`__.
146146
# You may train and save your own MNIST model or you can download and use
147147
# the provided model. The *Net* definition and test dataloader here have
148148
# been copied from the MNIST example. The purpose of this section is to
149149
# define the model and dataloader, then initialize the model and load the
150150
# pretrained weights.
151-
#
151+
#
152152

153153
# LeNet Model definition
154154
class Net(nn.Module):
@@ -181,7 +181,7 @@ def forward(self, x):
181181
datasets.MNIST('../data', train=False, download=True, transform=transforms.Compose([
182182
transforms.ToTensor(),
183183
transforms.Normalize((0.1307,), (0.3081,)),
184-
])),
184+
])),
185185
batch_size=1, shuffle=True)
186186

187187
# Define what device we are using
@@ -201,20 +201,20 @@ def forward(self, x):
201201
######################################################################
202202
# FGSM Attack
203203
# ~~~~~~~~~~~
204-
#
204+
#
205205
# Now, we can define the function that creates the adversarial examples by
206206
# perturbing the original inputs. The ``fgsm_attack`` function takes three
207207
# inputs, *image* is the original clean image (:math:`x`), *epsilon* is
208208
# the pixel-wise perturbation amount (:math:`\epsilon`), and *data_grad*
209209
# is gradient of the loss w.r.t the input image
210210
# (:math:`\nabla_{x} J(\mathbf{\theta}, \mathbf{x}, y)`). The function
211211
# then creates perturbed image as
212-
#
212+
#
213213
# .. math:: perturbed\_image = image + epsilon*sign(data\_grad) = x + \epsilon * sign(\nabla_{x} J(\mathbf{\theta}, \mathbf{x}, y))
214-
#
214+
#
215215
# Finally, in order to maintain the original range of the data, the
216216
# perturbed image is clipped to range :math:`[0,1]`.
217-
#
217+
#
218218

219219
# FGSM attack code
220220
def fgsm_attack(image, epsilon, data_grad):
@@ -244,14 +244,14 @@ def denorm(batch, mean=[0.1307], std=[0.3081]):
244244
mean = torch.tensor(mean).to(device)
245245
if isinstance(std, list):
246246
std = torch.tensor(std).to(device)
247-
247+
248248
return batch * std.view(1, -1, 1, 1) + mean.view(1, -1, 1, 1)
249249

250250

251251
######################################################################
252252
# Testing Function
253253
# ~~~~~~~~~~~~~~~~
254-
#
254+
#
255255
# Finally, the central result of this tutorial comes from the ``test``
256256
# function. Each call to this test function performs a full test step on
257257
# the MNIST test set and reports a final accuracy. However, notice that
@@ -264,7 +264,7 @@ def denorm(batch, mean=[0.1307], std=[0.3081]):
264264
# if the perturbed example is adversarial. In addition to testing the
265265
# accuracy of the model, the function also saves and returns some
266266
# successful adversarial examples to be visualized later.
267-
#
267+
#
268268

269269
def test( model, device, test_loader, epsilon ):
270270

@@ -338,15 +338,15 @@ def test( model, device, test_loader, epsilon ):
338338
######################################################################
339339
# Run Attack
340340
# ~~~~~~~~~~
341-
#
341+
#
342342
# The last part of the implementation is to actually run the attack. Here,
343343
# we run a full test step for each epsilon value in the *epsilons* input.
344344
# For each epsilon we also save the final accuracy and some successful
345345
# adversarial examples to be plotted in the coming sections. Notice how
346346
# the printed accuracies decrease as the epsilon value increases. Also,
347347
# note the :math:`\epsilon=0` case represents the original test accuracy,
348348
# with no attack.
349-
#
349+
#
350350

351351
accuracies = []
352352
examples = []
@@ -361,10 +361,10 @@ def test( model, device, test_loader, epsilon ):
361361
######################################################################
362362
# Results
363363
# -------
364-
#
364+
#
365365
# Accuracy vs Epsilon
366366
# ~~~~~~~~~~~~~~~~~~~
367-
#
367+
#
368368
# The first result is the accuracy versus epsilon plot. As alluded to
369369
# earlier, as epsilon increases we expect the test accuracy to decrease.
370370
# This is because larger epsilons mean we take a larger step in the
@@ -375,7 +375,7 @@ def test( model, device, test_loader, epsilon ):
375375
# lower than :math:`\epsilon=0.15`. Also, notice the accuracy of the model
376376
# hits random accuracy for a 10-class classifier between
377377
# :math:`\epsilon=0.25` and :math:`\epsilon=0.3`.
378-
#
378+
#
379379

380380
plt.figure(figsize=(5,5))
381381
plt.plot(epsilons, accuracies, "*-")
@@ -390,7 +390,7 @@ def test( model, device, test_loader, epsilon ):
390390
######################################################################
391391
# Sample Adversarial Examples
392392
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~
393-
#
393+
#
394394
# Remember the idea of no free lunch? In this case, as epsilon increases
395395
# the test accuracy decreases **BUT** the perturbations become more easily
396396
# perceptible. In reality, there is a tradeoff between accuracy
@@ -403,7 +403,7 @@ def test( model, device, test_loader, epsilon ):
403403
# perturbations start to become evident at :math:`\epsilon=0.15` and are
404404
# quite evident at :math:`\epsilon=0.3`. However, in all cases humans are
405405
# still capable of identifying the correct class despite the added noise.
406-
#
406+
#
407407

408408
# Plot several examples of adversarial samples at each epsilon
409409
cnt = 0
@@ -426,7 +426,7 @@ def test( model, device, test_loader, epsilon ):
426426
######################################################################
427427
# Where to go next?
428428
# -----------------
429-
#
429+
#
430430
# Hopefully this tutorial gives some insight into the topic of adversarial
431431
# machine learning. There are many potential directions to go from here.
432432
# This attack represents the very beginning of adversarial attack research
@@ -438,7 +438,7 @@ def test( model, device, test_loader, epsilon ):
438438
# on defense also leads into the idea of making machine learning models
439439
# more *robust* in general, to both naturally perturbed and adversarially
440440
# crafted inputs.
441-
#
441+
#
442442
# Another direction to go is adversarial attacks and defense in different
443443
# domains. Adversarial research is not limited to the image domain, check
444444
# out `this <https://arxiv.org/pdf/1801.01944.pdf>`__ attack on
@@ -447,4 +447,8 @@ def test( model, device, test_loader, epsilon ):
447447
# implement a different attack from the NIPS 2017 competition, and see how
448448
# it differs from FGSM. Then, try to defend the model from your own
449449
# attacks.
450-
#
450+
#
451+
# A further direction to go, depending on available resources, is to modify
452+
# the code to support processing work in batch, in parallel, and or distributed
453+
# vs working on one attack at a time in the above for each ``epsilon test()`` loop.
454+
#

0 commit comments

Comments
 (0)