Skip to content

Commit 8ab611d

Browse files
committed
Merge branch 'develop' of https://github.com/PaddlePaddle/Paddle into prior_box
2 parents 1ba3d29 + db65f49 commit 8ab611d

File tree

142 files changed

+5854
-1287
lines changed

Some content is hidden

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

142 files changed

+5854
-1287
lines changed

adversarial/README.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
# Advbox
2+
3+
Advbox is a Python toolbox to create adversarial examples that fool neural networks. It requires Python and paddle.
4+
5+
## How to use
6+
7+
1. train a model and save it's parameters. (like fluid_mnist.py)
8+
2. load the parameters which is trained in step1, then reconstruct the model.(like mnist_tutorial_fgsm.py)
9+
3. use advbox to generate the adversarial sample.

adversarial/advbox/__init__.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
# Copyright (c) 2017 PaddlePaddle Authors. All Rights Reserved
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
"""
15+
A set of tools for generating adversarial example on paddle platform
16+
"""

adversarial/advbox/attacks/base.py

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
"""
2+
The base model of the model.
3+
"""
4+
from abc import ABCMeta, abstractmethod
5+
6+
7+
class Attack(object):
8+
"""
9+
Abstract base class for adversarial attacks. `Attack` represent an adversarial attack
10+
which search an adversarial example. subclass should implement the _apply() method.
11+
12+
Args:
13+
model(Model): an instance of the class advbox.base.Model.
14+
15+
"""
16+
__metaclass__ = ABCMeta
17+
18+
def __init__(self, model):
19+
self.model = model
20+
21+
def __call__(self, image_label):
22+
"""
23+
Generate the adversarial sample.
24+
25+
Args:
26+
image_label(list): The image and label tuple list with one element.
27+
"""
28+
adv_img = self._apply(image_label)
29+
return adv_img
30+
31+
@abstractmethod
32+
def _apply(self, image_label):
33+
"""
34+
Search an adversarial example.
35+
36+
Args:
37+
image_batch(list): The image and label tuple list with one element.
38+
"""
39+
raise NotImplementedError
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
"""
2+
This module provide the attack method for FGSM's implement.
3+
"""
4+
from __future__ import division
5+
import numpy as np
6+
from collections import Iterable
7+
from .base import Attack
8+
9+
10+
class GradientSignAttack(Attack):
11+
"""
12+
This attack was originally implemented by Goodfellow et al. (2015) with the
13+
infinity norm (and is known as the "Fast Gradient Sign Method"). This is therefore called
14+
the Fast Gradient Method.
15+
Paper link: https://arxiv.org/abs/1412.6572
16+
"""
17+
18+
def _apply(self, image_label, epsilons=1000):
19+
assert len(image_label) == 1
20+
pre_label = np.argmax(self.model.predict(image_label))
21+
22+
min_, max_ = self.model.bounds()
23+
gradient = self.model.gradient(image_label)
24+
gradient_sign = np.sign(gradient) * (max_ - min_)
25+
26+
if not isinstance(epsilons, Iterable):
27+
epsilons = np.linspace(0, 1, num=epsilons + 1)
28+
29+
for epsilon in epsilons:
30+
adv_img = image_label[0][0].reshape(
31+
gradient_sign.shape) + epsilon * gradient_sign
32+
adv_img = np.clip(adv_img, min_, max_)
33+
adv_label = np.argmax(self.model.predict([(adv_img, 0)]))
34+
if pre_label != adv_label:
35+
return adv_img
36+
37+
38+
FGSM = GradientSignAttack

adversarial/advbox/models/__init__.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
# Copyright (c) 2017 PaddlePaddle Authors. All Rights Reserved
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
"""
15+
Paddle model for target of attack
16+
"""

adversarial/advbox/models/base.py

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
"""
2+
The base model of the model.
3+
"""
4+
from abc import ABCMeta
5+
import abc
6+
7+
abstractmethod = abc.abstractmethod
8+
9+
10+
class Model(object):
11+
"""
12+
Base class of model to provide attack.
13+
14+
15+
Args:
16+
bounds(tuple): The lower and upper bound for the image pixel.
17+
channel_axis(int): The index of the axis that represents the color channel.
18+
preprocess(tuple): Two element tuple used to preprocess the input. First
19+
substract the first element, then divide the second element.
20+
"""
21+
__metaclass__ = ABCMeta
22+
23+
def __init__(self, bounds, channel_axis, preprocess=None):
24+
assert len(bounds) == 2
25+
assert channel_axis in [0, 1, 2, 3]
26+
27+
if preprocess is None:
28+
preprocess = (0, 1)
29+
self._bounds = bounds
30+
self._channel_axis = channel_axis
31+
self._preprocess = preprocess
32+
33+
def bounds(self):
34+
"""
35+
Return the upper and lower bounds of the model.
36+
"""
37+
return self._bounds
38+
39+
def channel_axis(self):
40+
"""
41+
Return the channel axis of the model.
42+
"""
43+
return self._channel_axis
44+
45+
def _process_input(self, input_):
46+
res = input_
47+
sub, div = self._preprocess
48+
if sub != 0:
49+
res = input_ - sub
50+
assert div != 0
51+
if div != 1:
52+
res /= div
53+
return res
54+
55+
@abstractmethod
56+
def predict(self, image_batch):
57+
"""
58+
Calculate the prediction of the image batch.
59+
60+
Args:
61+
image_batch(numpy.ndarray): image batch of shape (batch_size, height, width, channels).
62+
63+
Return:
64+
numpy.ndarray: predictions of the images with shape (batch_size, num_of_classes).
65+
"""
66+
raise NotImplementedError
67+
68+
@abstractmethod
69+
def num_classes(self):
70+
"""
71+
Determine the number of the classes
72+
73+
Return:
74+
int: the number of the classes
75+
"""
76+
raise NotImplementedError
77+
78+
@abstractmethod
79+
def gradient(self, image_batch):
80+
"""
81+
Calculate the gradient of the cross-entropy loss w.r.t the image.
82+
83+
Args:
84+
image_batch(list): The image and label tuple list.
85+
86+
Return:
87+
numpy.ndarray: gradient of the cross-entropy loss w.r.t the image with
88+
the shape (height, width, channel).
89+
"""
90+
raise NotImplementedError

adversarial/advbox/models/paddle.py

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
from __future__ import absolute_import
2+
3+
import numpy as np
4+
import paddle.v2 as paddle
5+
import paddle.v2.fluid as fluid
6+
from paddle.v2.fluid.framework import program_guard
7+
8+
from .base import Model
9+
10+
11+
class PaddleModel(Model):
12+
"""
13+
Create a PaddleModel instance.
14+
When you need to generate a adversarial sample, you should construct an instance of PaddleModel.
15+
16+
Args:
17+
program(paddle.v2.fluid.framework.Program): The program of the model which generate the adversarial sample.
18+
input_name(string): The name of the input.
19+
logits_name(string): The name of the logits.
20+
predict_name(string): The name of the predict.
21+
cost_name(string): The name of the loss in the program.
22+
"""
23+
24+
def __init__(self,
25+
program,
26+
input_name,
27+
logits_name,
28+
predict_name,
29+
cost_name,
30+
bounds,
31+
channel_axis=3,
32+
preprocess=None):
33+
super(PaddleModel, self).__init__(
34+
bounds=bounds, channel_axis=channel_axis, preprocess=preprocess)
35+
36+
if preprocess is None:
37+
preprocess = (0, 1)
38+
39+
self._program = program
40+
self._place = fluid.CPUPlace()
41+
self._exe = fluid.Executor(self._place)
42+
43+
self._input_name = input_name
44+
self._logits_name = logits_name
45+
self._predict_name = predict_name
46+
self._cost_name = cost_name
47+
48+
# gradient
49+
loss = self._program.block(0).var(self._cost_name)
50+
param_grads = fluid.backward.append_backward(
51+
loss, parameter_list=[self._input_name])
52+
self._gradient = dict(param_grads)[self._input_name]
53+
54+
def predict(self, image_batch):
55+
"""
56+
Predict the label of the image_batch.
57+
58+
Args:
59+
image_batch(list): The image and label tuple list.
60+
Return:
61+
numpy.ndarray: predictions of the images with shape (batch_size, num_of_classes).
62+
"""
63+
feeder = fluid.DataFeeder(
64+
feed_list=[self._input_name, self._logits_name],
65+
place=self._place,
66+
program=self._program)
67+
predict_var = self._program.block(0).var(self._predict_name)
68+
predict = self._exe.run(self._program,
69+
feed=feeder.feed(image_batch),
70+
fetch_list=[predict_var])
71+
return predict
72+
73+
def num_classes(self):
74+
"""
75+
Calculate the number of classes of the output label.
76+
77+
Return:
78+
int: the number of classes
79+
"""
80+
predict_var = self._program.block(0).var(self._predict_name)
81+
assert len(predict_var.shape) == 2
82+
return predict_var.shape[1]
83+
84+
def gradient(self, image_batch):
85+
"""
86+
Calculate the gradient of the loss w.r.t the input.
87+
88+
Args:
89+
image_batch(list): The image and label tuple list.
90+
Return:
91+
list: The list of the gradient of the image.
92+
"""
93+
feeder = fluid.DataFeeder(
94+
feed_list=[self._input_name, self._logits_name],
95+
place=self._place,
96+
program=self._program)
97+
98+
grad, = self._exe.run(self._program,
99+
feed=feeder.feed(image_batch),
100+
fetch_list=[self._gradient])
101+
return grad

0 commit comments

Comments
 (0)