Merge branch 'develop' of https://github.com/PaddlePaddle/Paddle into blockexpand
commit
bfe7e24243
@ -0,0 +1,106 @@
|
|||||||
|
from __future__ import absolute_import
|
||||||
|
from __future__ import print_function
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
|
import argparse
|
||||||
|
import io, re
|
||||||
|
import sys, os
|
||||||
|
import subprocess
|
||||||
|
import platform
|
||||||
|
|
||||||
|
COPYRIGHT = '''
|
||||||
|
Copyright (c) 2016 PaddlePaddle Authors. All Rights Reserve.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
'''
|
||||||
|
|
||||||
|
LANG_COMMENT_MARK = None
|
||||||
|
|
||||||
|
NEW_LINE_MARK = None
|
||||||
|
|
||||||
|
COPYRIGHT_HEADER = None
|
||||||
|
|
||||||
|
if platform.system() == "Windows":
|
||||||
|
NEW_LINE_MARK = "\r\n"
|
||||||
|
else:
|
||||||
|
NEW_LINE_MARK = '\n'
|
||||||
|
COPYRIGHT_HEADER = COPYRIGHT.split(NEW_LINE_MARK)[1]
|
||||||
|
p = re.search('(\d{4})', COPYRIGHT_HEADER).group(0)
|
||||||
|
process = subprocess.Popen(["date", "+%Y"], stdout=subprocess.PIPE)
|
||||||
|
date, err = process.communicate()
|
||||||
|
date = date.decode("utf-8").rstrip("\n")
|
||||||
|
COPYRIGHT_HEADER = COPYRIGHT_HEADER.replace(p, date)
|
||||||
|
|
||||||
|
|
||||||
|
def generate_copyright(template, lang='C'):
|
||||||
|
if lang == 'Python':
|
||||||
|
LANG_COMMENT_MARK = '#'
|
||||||
|
else:
|
||||||
|
LANG_COMMENT_MARK = "//"
|
||||||
|
|
||||||
|
lines = template.split(NEW_LINE_MARK)
|
||||||
|
ans = LANG_COMMENT_MARK + COPYRIGHT_HEADER + NEW_LINE_MARK
|
||||||
|
for lino, line in enumerate(lines):
|
||||||
|
if lino == 0 or lino == 1 or lino == len(lines) - 1: continue
|
||||||
|
ans += LANG_COMMENT_MARK + line + NEW_LINE_MARK
|
||||||
|
|
||||||
|
return ans
|
||||||
|
|
||||||
|
|
||||||
|
def lang_type(filename):
|
||||||
|
if filename.endswith(".py"):
|
||||||
|
return "Python"
|
||||||
|
elif filename.endswith(".h"):
|
||||||
|
return "C"
|
||||||
|
elif filename.endswith(".hpp"):
|
||||||
|
return "C"
|
||||||
|
elif filename.endswith(".cc"):
|
||||||
|
return "C"
|
||||||
|
elif filename.endswith(".cpp"):
|
||||||
|
return "C"
|
||||||
|
elif filename.endswith(".cu"):
|
||||||
|
return "C"
|
||||||
|
elif filename.endswith(".cuh"):
|
||||||
|
return "C"
|
||||||
|
elif filename.endswith(".go"):
|
||||||
|
return "C"
|
||||||
|
elif filename.endswith(".proto"):
|
||||||
|
return "C"
|
||||||
|
else:
|
||||||
|
print("Unsupported filetype")
|
||||||
|
exit(0)
|
||||||
|
|
||||||
|
|
||||||
|
def main(argv=None):
|
||||||
|
parser = argparse.ArgumentParser(
|
||||||
|
description='Checker for copyright declaration.')
|
||||||
|
parser.add_argument('filenames', nargs='*', help='Filenames to check')
|
||||||
|
args = parser.parse_args(argv)
|
||||||
|
|
||||||
|
retv = 0
|
||||||
|
for filename in args.filenames:
|
||||||
|
first_line = io.open(filename).readline()
|
||||||
|
if "COPYRIGHT" in first_line.upper() : continue
|
||||||
|
original_contents = io.open(filename).read()
|
||||||
|
new_contents = generate_copyright(
|
||||||
|
COPYRIGHT, lang_type(filename)) + original_contents
|
||||||
|
print('Auto Insert Copyright Header {}'.format(filename))
|
||||||
|
retv = 1
|
||||||
|
with io.open(filename, 'w') as output_file:
|
||||||
|
output_file.write(new_contents)
|
||||||
|
|
||||||
|
return retv
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
exit(main())
|
@ -0,0 +1,9 @@
|
|||||||
|
# Advbox
|
||||||
|
|
||||||
|
Advbox is a Python toolbox to create adversarial examples that fool neural networks. It requires Python and paddle.
|
||||||
|
|
||||||
|
## How to use
|
||||||
|
|
||||||
|
1. train a model and save it's parameters. (like fluid_mnist.py)
|
||||||
|
2. load the parameters which is trained in step1, then reconstruct the model.(like mnist_tutorial_fgsm.py)
|
||||||
|
3. use advbox to generate the adversarial sample.
|
@ -0,0 +1,16 @@
|
|||||||
|
# Copyright (c) 2017 PaddlePaddle Authors. All Rights Reserved
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
# you may not use this file except in compliance with the License.
|
||||||
|
# You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
# See the License for the specific language governing permissions and
|
||||||
|
# limitations under the License.
|
||||||
|
"""
|
||||||
|
A set of tools for generating adversarial example on paddle platform
|
||||||
|
"""
|
@ -0,0 +1,52 @@
|
|||||||
|
# Copyright (c) 2018 PaddlePaddle Authors. All Rights Reserve.
|
||||||
|
#
|
||||||
|
#Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
#you may not use this file except in compliance with the License.
|
||||||
|
#You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
#Unless required by applicable law or agreed to in writing, software
|
||||||
|
#distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
#WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
#See the License for the specific language governing permissions and
|
||||||
|
#limitations under the License.
|
||||||
|
"""
|
||||||
|
The base model of the model.
|
||||||
|
"""
|
||||||
|
from abc import ABCMeta, abstractmethod
|
||||||
|
|
||||||
|
|
||||||
|
class Attack(object):
|
||||||
|
"""
|
||||||
|
Abstract base class for adversarial attacks. `Attack` represent an adversarial attack
|
||||||
|
which search an adversarial example. subclass should implement the _apply() method.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
model(Model): an instance of the class advbox.base.Model.
|
||||||
|
|
||||||
|
"""
|
||||||
|
__metaclass__ = ABCMeta
|
||||||
|
|
||||||
|
def __init__(self, model):
|
||||||
|
self.model = model
|
||||||
|
|
||||||
|
def __call__(self, image_label):
|
||||||
|
"""
|
||||||
|
Generate the adversarial sample.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
image_label(list): The image and label tuple list with one element.
|
||||||
|
"""
|
||||||
|
adv_img = self._apply(image_label)
|
||||||
|
return adv_img
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def _apply(self, image_label):
|
||||||
|
"""
|
||||||
|
Search an adversarial example.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
image_batch(list): The image and label tuple list with one element.
|
||||||
|
"""
|
||||||
|
raise NotImplementedError
|
@ -0,0 +1,87 @@
|
|||||||
|
# Copyright (c) 2018 PaddlePaddle Authors. All Rights Reserve.
|
||||||
|
#
|
||||||
|
#Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
#you may not use this file except in compliance with the License.
|
||||||
|
#You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
#Unless required by applicable law or agreed to in writing, software
|
||||||
|
#distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
#WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
#See the License for the specific language governing permissions and
|
||||||
|
#limitations under the License.
|
||||||
|
"""
|
||||||
|
This module provide the attack method for FGSM's implement.
|
||||||
|
"""
|
||||||
|
from __future__ import division
|
||||||
|
import numpy as np
|
||||||
|
from collections import Iterable
|
||||||
|
from .base import Attack
|
||||||
|
|
||||||
|
|
||||||
|
class GradientSignAttack(Attack):
|
||||||
|
"""
|
||||||
|
This attack was originally implemented by Goodfellow et al. (2015) with the
|
||||||
|
infinity norm (and is known as the "Fast Gradient Sign Method"). This is therefore called
|
||||||
|
the Fast Gradient Method.
|
||||||
|
Paper link: https://arxiv.org/abs/1412.6572
|
||||||
|
"""
|
||||||
|
|
||||||
|
def _apply(self, image_label, epsilons=1000):
|
||||||
|
assert len(image_label) == 1
|
||||||
|
pre_label = np.argmax(self.model.predict(image_label))
|
||||||
|
|
||||||
|
min_, max_ = self.model.bounds()
|
||||||
|
gradient = self.model.gradient(image_label)
|
||||||
|
gradient_sign = np.sign(gradient) * (max_ - min_)
|
||||||
|
|
||||||
|
if not isinstance(epsilons, Iterable):
|
||||||
|
epsilons = np.linspace(0, 1, num=epsilons + 1)
|
||||||
|
|
||||||
|
for epsilon in epsilons:
|
||||||
|
adv_img = image_label[0][0].reshape(
|
||||||
|
gradient_sign.shape) + epsilon * gradient_sign
|
||||||
|
adv_img = np.clip(adv_img, min_, max_)
|
||||||
|
adv_label = np.argmax(self.model.predict([(adv_img, 0)]))
|
||||||
|
if pre_label != adv_label:
|
||||||
|
return adv_img
|
||||||
|
|
||||||
|
|
||||||
|
FGSM = GradientSignAttack
|
||||||
|
|
||||||
|
|
||||||
|
class IteratorGradientSignAttack(Attack):
|
||||||
|
"""
|
||||||
|
This attack was originally implemented by Alexey Kurakin(Google Brain).
|
||||||
|
Paper link: https://arxiv.org/pdf/1607.02533.pdf
|
||||||
|
"""
|
||||||
|
|
||||||
|
def _apply(self, image_label, epsilons=100, steps=10):
|
||||||
|
"""
|
||||||
|
Apply the iterative gradient sign attack.
|
||||||
|
Args:
|
||||||
|
image_label(list): The image and label tuple list of one element.
|
||||||
|
epsilons(list|tuple|int): The epsilon (input variation parameter).
|
||||||
|
steps(int): The number of iterator steps.
|
||||||
|
Return:
|
||||||
|
numpy.ndarray: The adversarail sample generated by the algorithm.
|
||||||
|
"""
|
||||||
|
assert len(image_label) == 1
|
||||||
|
pre_label = np.argmax(self.model.predict(image_label))
|
||||||
|
gradient = self.model.gradient(image_label)
|
||||||
|
min_, max_ = self.model.bounds()
|
||||||
|
|
||||||
|
if not isinstance(epsilons, Iterable):
|
||||||
|
epsilons = np.linspace(0, 1, num=epsilons + 1)
|
||||||
|
|
||||||
|
for epsilon in epsilons:
|
||||||
|
adv_img = image_label[0][0].reshape(gradient.shape)
|
||||||
|
for _ in range(steps):
|
||||||
|
gradient = self.model.gradient([(adv_img, image_label[0][1])])
|
||||||
|
gradient_sign = np.sign(gradient) * (max_ - min_)
|
||||||
|
adv_img = adv_img + epsilon * gradient_sign
|
||||||
|
adv_img = np.clip(adv_img, min_, max_)
|
||||||
|
adv_label = np.argmax(self.model.predict([(adv_img, 0)]))
|
||||||
|
if pre_label != adv_label:
|
||||||
|
return adv_img
|
@ -0,0 +1,16 @@
|
|||||||
|
# Copyright (c) 2017 PaddlePaddle Authors. All Rights Reserved
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
# you may not use this file except in compliance with the License.
|
||||||
|
# You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
# See the License for the specific language governing permissions and
|
||||||
|
# limitations under the License.
|
||||||
|
"""
|
||||||
|
Paddle model for target of attack
|
||||||
|
"""
|
@ -0,0 +1,103 @@
|
|||||||
|
# Copyright (c) 2018 PaddlePaddle Authors. All Rights Reserve.
|
||||||
|
#
|
||||||
|
#Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
#you may not use this file except in compliance with the License.
|
||||||
|
#You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
#Unless required by applicable law or agreed to in writing, software
|
||||||
|
#distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
#WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
#See the License for the specific language governing permissions and
|
||||||
|
#limitations under the License.
|
||||||
|
"""
|
||||||
|
The base model of the model.
|
||||||
|
"""
|
||||||
|
from abc import ABCMeta
|
||||||
|
import abc
|
||||||
|
|
||||||
|
abstractmethod = abc.abstractmethod
|
||||||
|
|
||||||
|
|
||||||
|
class Model(object):
|
||||||
|
"""
|
||||||
|
Base class of model to provide attack.
|
||||||
|
|
||||||
|
|
||||||
|
Args:
|
||||||
|
bounds(tuple): The lower and upper bound for the image pixel.
|
||||||
|
channel_axis(int): The index of the axis that represents the color channel.
|
||||||
|
preprocess(tuple): Two element tuple used to preprocess the input. First
|
||||||
|
substract the first element, then divide the second element.
|
||||||
|
"""
|
||||||
|
__metaclass__ = ABCMeta
|
||||||
|
|
||||||
|
def __init__(self, bounds, channel_axis, preprocess=None):
|
||||||
|
assert len(bounds) == 2
|
||||||
|
assert channel_axis in [0, 1, 2, 3]
|
||||||
|
|
||||||
|
if preprocess is None:
|
||||||
|
preprocess = (0, 1)
|
||||||
|
self._bounds = bounds
|
||||||
|
self._channel_axis = channel_axis
|
||||||
|
self._preprocess = preprocess
|
||||||
|
|
||||||
|
def bounds(self):
|
||||||
|
"""
|
||||||
|
Return the upper and lower bounds of the model.
|
||||||
|
"""
|
||||||
|
return self._bounds
|
||||||
|
|
||||||
|
def channel_axis(self):
|
||||||
|
"""
|
||||||
|
Return the channel axis of the model.
|
||||||
|
"""
|
||||||
|
return self._channel_axis
|
||||||
|
|
||||||
|
def _process_input(self, input_):
|
||||||
|
res = input_
|
||||||
|
sub, div = self._preprocess
|
||||||
|
if sub != 0:
|
||||||
|
res = input_ - sub
|
||||||
|
assert div != 0
|
||||||
|
if div != 1:
|
||||||
|
res /= div
|
||||||
|
return res
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def predict(self, image_batch):
|
||||||
|
"""
|
||||||
|
Calculate the prediction of the image batch.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
image_batch(numpy.ndarray): image batch of shape (batch_size, height, width, channels).
|
||||||
|
|
||||||
|
Return:
|
||||||
|
numpy.ndarray: predictions of the images with shape (batch_size, num_of_classes).
|
||||||
|
"""
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def num_classes(self):
|
||||||
|
"""
|
||||||
|
Determine the number of the classes
|
||||||
|
|
||||||
|
Return:
|
||||||
|
int: the number of the classes
|
||||||
|
"""
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def gradient(self, image_batch):
|
||||||
|
"""
|
||||||
|
Calculate the gradient of the cross-entropy loss w.r.t the image.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
image_batch(list): The image and label tuple list.
|
||||||
|
|
||||||
|
Return:
|
||||||
|
numpy.ndarray: gradient of the cross-entropy loss w.r.t the image with
|
||||||
|
the shape (height, width, channel).
|
||||||
|
"""
|
||||||
|
raise NotImplementedError
|
@ -0,0 +1,114 @@
|
|||||||
|
# Copyright (c) 2018 PaddlePaddle Authors. All Rights Reserve.
|
||||||
|
#
|
||||||
|
#Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
#you may not use this file except in compliance with the License.
|
||||||
|
#You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
#Unless required by applicable law or agreed to in writing, software
|
||||||
|
#distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
#WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
#See the License for the specific language governing permissions and
|
||||||
|
#limitations under the License.
|
||||||
|
from __future__ import absolute_import
|
||||||
|
|
||||||
|
import numpy as np
|
||||||
|
import paddle.v2 as paddle
|
||||||
|
import paddle.v2.fluid as fluid
|
||||||
|
from paddle.v2.fluid.framework import program_guard
|
||||||
|
|
||||||
|
from .base import Model
|
||||||
|
|
||||||
|
|
||||||
|
class PaddleModel(Model):
|
||||||
|
"""
|
||||||
|
Create a PaddleModel instance.
|
||||||
|
When you need to generate a adversarial sample, you should construct an instance of PaddleModel.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
program(paddle.v2.fluid.framework.Program): The program of the model which generate the adversarial sample.
|
||||||
|
input_name(string): The name of the input.
|
||||||
|
logits_name(string): The name of the logits.
|
||||||
|
predict_name(string): The name of the predict.
|
||||||
|
cost_name(string): The name of the loss in the program.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self,
|
||||||
|
program,
|
||||||
|
input_name,
|
||||||
|
logits_name,
|
||||||
|
predict_name,
|
||||||
|
cost_name,
|
||||||
|
bounds,
|
||||||
|
channel_axis=3,
|
||||||
|
preprocess=None):
|
||||||
|
super(PaddleModel, self).__init__(
|
||||||
|
bounds=bounds, channel_axis=channel_axis, preprocess=preprocess)
|
||||||
|
|
||||||
|
if preprocess is None:
|
||||||
|
preprocess = (0, 1)
|
||||||
|
|
||||||
|
self._program = program
|
||||||
|
self._place = fluid.CPUPlace()
|
||||||
|
self._exe = fluid.Executor(self._place)
|
||||||
|
|
||||||
|
self._input_name = input_name
|
||||||
|
self._logits_name = logits_name
|
||||||
|
self._predict_name = predict_name
|
||||||
|
self._cost_name = cost_name
|
||||||
|
|
||||||
|
# gradient
|
||||||
|
loss = self._program.block(0).var(self._cost_name)
|
||||||
|
param_grads = fluid.backward.append_backward(
|
||||||
|
loss, parameter_list=[self._input_name])
|
||||||
|
self._gradient = dict(param_grads)[self._input_name]
|
||||||
|
|
||||||
|
def predict(self, image_batch):
|
||||||
|
"""
|
||||||
|
Predict the label of the image_batch.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
image_batch(list): The image and label tuple list.
|
||||||
|
Return:
|
||||||
|
numpy.ndarray: predictions of the images with shape (batch_size, num_of_classes).
|
||||||
|
"""
|
||||||
|
feeder = fluid.DataFeeder(
|
||||||
|
feed_list=[self._input_name, self._logits_name],
|
||||||
|
place=self._place,
|
||||||
|
program=self._program)
|
||||||
|
predict_var = self._program.block(0).var(self._predict_name)
|
||||||
|
predict = self._exe.run(self._program,
|
||||||
|
feed=feeder.feed(image_batch),
|
||||||
|
fetch_list=[predict_var])
|
||||||
|
return predict
|
||||||
|
|
||||||
|
def num_classes(self):
|
||||||
|
"""
|
||||||
|
Calculate the number of classes of the output label.
|
||||||
|
|
||||||
|
Return:
|
||||||
|
int: the number of classes
|
||||||
|
"""
|
||||||
|
predict_var = self._program.block(0).var(self._predict_name)
|
||||||
|
assert len(predict_var.shape) == 2
|
||||||
|
return predict_var.shape[1]
|
||||||
|
|
||||||
|
def gradient(self, image_batch):
|
||||||
|
"""
|
||||||
|
Calculate the gradient of the loss w.r.t the input.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
image_batch(list): The image and label tuple list.
|
||||||
|
Return:
|
||||||
|
list: The list of the gradient of the image.
|
||||||
|
"""
|
||||||
|
feeder = fluid.DataFeeder(
|
||||||
|
feed_list=[self._input_name, self._logits_name],
|
||||||
|
place=self._place,
|
||||||
|
program=self._program)
|
||||||
|
|
||||||
|
grad, = self._exe.run(self._program,
|
||||||
|
feed=feeder.feed(image_batch),
|
||||||
|
fetch_list=[self._gradient])
|
||||||
|
return grad
|
@ -0,0 +1,99 @@
|
|||||||
|
# Copyright (c) 2018 PaddlePaddle Authors. All Rights Reserve.
|
||||||
|
#
|
||||||
|
#Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
#you may not use this file except in compliance with the License.
|
||||||
|
#You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
#Unless required by applicable law or agreed to in writing, software
|
||||||
|
#distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
#WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
#See the License for the specific language governing permissions and
|
||||||
|
#limitations under the License.
|
||||||
|
"""
|
||||||
|
CNN on mnist data using fluid api of paddlepaddle
|
||||||
|
"""
|
||||||
|
import paddle.v2 as paddle
|
||||||
|
import paddle.v2.fluid as fluid
|
||||||
|
|
||||||
|
|
||||||
|
def mnist_cnn_model(img):
|
||||||
|
"""
|
||||||
|
Mnist cnn model
|
||||||
|
|
||||||
|
Args:
|
||||||
|
img(Varaible): the input image to be recognized
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
Variable: the label prediction
|
||||||
|
"""
|
||||||
|
conv_pool_1 = fluid.nets.simple_img_conv_pool(
|
||||||
|
input=img,
|
||||||
|
num_filters=20,
|
||||||
|
filter_size=5,
|
||||||
|
pool_size=2,
|
||||||
|
pool_stride=2,
|
||||||
|
act='relu')
|
||||||
|
|
||||||
|
conv_pool_2 = fluid.nets.simple_img_conv_pool(
|
||||||
|
input=conv_pool_1,
|
||||||
|
num_filters=50,
|
||||||
|
filter_size=5,
|
||||||
|
pool_size=2,
|
||||||
|
pool_stride=2,
|
||||||
|
act='relu')
|
||||||
|
|
||||||
|
logits = fluid.layers.fc(input=conv_pool_2, size=10, act='softmax')
|
||||||
|
return logits
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
"""
|
||||||
|
Train the cnn model on mnist datasets
|
||||||
|
"""
|
||||||
|
img = fluid.layers.data(name='img', shape=[1, 28, 28], dtype='float32')
|
||||||
|
label = fluid.layers.data(name='label', shape=[1], dtype='int64')
|
||||||
|
logits = mnist_cnn_model(img)
|
||||||
|
cost = fluid.layers.cross_entropy(input=logits, label=label)
|
||||||
|
avg_cost = fluid.layers.mean(x=cost)
|
||||||
|
optimizer = fluid.optimizer.Adam(learning_rate=0.01)
|
||||||
|
optimizer.minimize(avg_cost)
|
||||||
|
|
||||||
|
accuracy = fluid.evaluator.Accuracy(input=logits, label=label)
|
||||||
|
|
||||||
|
BATCH_SIZE = 50
|
||||||
|
PASS_NUM = 3
|
||||||
|
ACC_THRESHOLD = 0.98
|
||||||
|
LOSS_THRESHOLD = 10.0
|
||||||
|
train_reader = paddle.batch(
|
||||||
|
paddle.reader.shuffle(
|
||||||
|
paddle.dataset.mnist.train(), buf_size=500),
|
||||||
|
batch_size=BATCH_SIZE)
|
||||||
|
|
||||||
|
place = fluid.CPUPlace()
|
||||||
|
exe = fluid.Executor(place)
|
||||||
|
feeder = fluid.DataFeeder(feed_list=[img, label], place=place)
|
||||||
|
exe.run(fluid.default_startup_program())
|
||||||
|
|
||||||
|
for pass_id in range(PASS_NUM):
|
||||||
|
accuracy.reset(exe)
|
||||||
|
for data in train_reader():
|
||||||
|
loss, acc = exe.run(fluid.default_main_program(),
|
||||||
|
feed=feeder.feed(data),
|
||||||
|
fetch_list=[avg_cost] + accuracy.metrics)
|
||||||
|
pass_acc = accuracy.eval(exe)
|
||||||
|
print("pass_id=" + str(pass_id) + " acc=" + str(acc) + " pass_acc="
|
||||||
|
+ str(pass_acc))
|
||||||
|
if loss < LOSS_THRESHOLD and pass_acc > ACC_THRESHOLD:
|
||||||
|
break
|
||||||
|
|
||||||
|
pass_acc = accuracy.eval(exe)
|
||||||
|
print("pass_id=" + str(pass_id) + " pass_acc=" + str(pass_acc))
|
||||||
|
fluid.io.save_params(
|
||||||
|
exe, dirname='./mnist', main_program=fluid.default_main_program())
|
||||||
|
print('train mnist done')
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
main()
|
@ -0,0 +1,100 @@
|
|||||||
|
# Copyright (c) 2018 PaddlePaddle Authors. All Rights Reserve.
|
||||||
|
#
|
||||||
|
#Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
#you may not use this file except in compliance with the License.
|
||||||
|
#You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
#Unless required by applicable law or agreed to in writing, software
|
||||||
|
#distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
#WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
#See the License for the specific language governing permissions and
|
||||||
|
#limitations under the License.
|
||||||
|
"""
|
||||||
|
FGSM demos on mnist using advbox tool.
|
||||||
|
"""
|
||||||
|
import paddle.v2 as paddle
|
||||||
|
import paddle.v2.fluid as fluid
|
||||||
|
import matplotlib.pyplot as plt
|
||||||
|
import numpy as np
|
||||||
|
|
||||||
|
from advbox.models.paddle import PaddleModel
|
||||||
|
from advbox.attacks.gradientsign import GradientSignAttack
|
||||||
|
|
||||||
|
|
||||||
|
def cnn_model(img):
|
||||||
|
"""
|
||||||
|
Mnist cnn model
|
||||||
|
Args:
|
||||||
|
img(Varaible): the input image to be recognized
|
||||||
|
Returns:
|
||||||
|
Variable: the label prediction
|
||||||
|
"""
|
||||||
|
#conv1 = fluid.nets.conv2d()
|
||||||
|
conv_pool_1 = fluid.nets.simple_img_conv_pool(
|
||||||
|
input=img,
|
||||||
|
num_filters=20,
|
||||||
|
filter_size=5,
|
||||||
|
pool_size=2,
|
||||||
|
pool_stride=2,
|
||||||
|
act='relu')
|
||||||
|
|
||||||
|
conv_pool_2 = fluid.nets.simple_img_conv_pool(
|
||||||
|
input=conv_pool_1,
|
||||||
|
num_filters=50,
|
||||||
|
filter_size=5,
|
||||||
|
pool_size=2,
|
||||||
|
pool_stride=2,
|
||||||
|
act='relu')
|
||||||
|
|
||||||
|
logits = fluid.layers.fc(input=conv_pool_2, size=10, act='softmax')
|
||||||
|
return logits
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
"""
|
||||||
|
Advbox demo which demonstrate how to use advbox.
|
||||||
|
"""
|
||||||
|
IMG_NAME = 'img'
|
||||||
|
LABEL_NAME = 'label'
|
||||||
|
|
||||||
|
img = fluid.layers.data(name=IMG_NAME, shape=[1, 28, 28], dtype='float32')
|
||||||
|
# gradient should flow
|
||||||
|
img.stop_gradient = False
|
||||||
|
label = fluid.layers.data(name=LABEL_NAME, shape=[1], dtype='int64')
|
||||||
|
logits = cnn_model(img)
|
||||||
|
cost = fluid.layers.cross_entropy(input=logits, label=label)
|
||||||
|
avg_cost = fluid.layers.mean(x=cost)
|
||||||
|
|
||||||
|
place = fluid.CPUPlace()
|
||||||
|
exe = fluid.Executor(place)
|
||||||
|
|
||||||
|
BATCH_SIZE = 1
|
||||||
|
train_reader = paddle.batch(
|
||||||
|
paddle.reader.shuffle(
|
||||||
|
paddle.dataset.mnist.train(), buf_size=500),
|
||||||
|
batch_size=BATCH_SIZE)
|
||||||
|
feeder = fluid.DataFeeder(
|
||||||
|
feed_list=[IMG_NAME, LABEL_NAME],
|
||||||
|
place=place,
|
||||||
|
program=fluid.default_main_program())
|
||||||
|
|
||||||
|
fluid.io.load_params(
|
||||||
|
exe, "./mnist/", main_program=fluid.default_main_program())
|
||||||
|
|
||||||
|
# advbox demo
|
||||||
|
m = PaddleModel(fluid.default_main_program(), IMG_NAME, LABEL_NAME,
|
||||||
|
logits.name, avg_cost.name, (-1, 1))
|
||||||
|
att = GradientSignAttack(m)
|
||||||
|
for data in train_reader():
|
||||||
|
# fgsm attack
|
||||||
|
adv_img = att(data)
|
||||||
|
plt.imshow(n[0][0], cmap='Greys_r')
|
||||||
|
plt.show()
|
||||||
|
#np.save('adv_img', adv_img)
|
||||||
|
break
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
main()
|
@ -0,0 +1,78 @@
|
|||||||
|
# Cluster Training Benchmark
|
||||||
|
|
||||||
|
## Setup
|
||||||
|
|
||||||
|
- Platform
|
||||||
|
- Kubernetes: v1.6.2
|
||||||
|
- Linux Kernel: v3.10.0
|
||||||
|
|
||||||
|
- Resource
|
||||||
|
- CPU: 10 Cores per Pod
|
||||||
|
- Memory: 5GB per Pod
|
||||||
|
|
||||||
|
- Docker Image
|
||||||
|
|
||||||
|
We use different base Docker Image to run the benchmark on Kubernetes:
|
||||||
|
- PaddlePaddle v2: paddlepaddle/paddle:0.11.0
|
||||||
|
- PaddlePaddle Fluid: paddlepaddle/paddle:[commit-id]
|
||||||
|
- TensorFlow: tensorflow/tensorflow:1.5.0-rc0
|
||||||
|
|
||||||
|
- Model
|
||||||
|
vgg16 is used in this benchmark.
|
||||||
|
|
||||||
|
## Cases
|
||||||
|
|
||||||
|
- Variable
|
||||||
|
- Batch Size of training data.
|
||||||
|
- PServer count of the training job.
|
||||||
|
- The number of trainers.
|
||||||
|
|
||||||
|
- Invariant
|
||||||
|
- The resource of trainer/pserver Pod.
|
||||||
|
|
||||||
|
### Measure the Performance for Different Batch Size
|
||||||
|
|
||||||
|
- PServer Count: 40
|
||||||
|
- Trainer Count: 100
|
||||||
|
- Metrics: mini-batch / sec
|
||||||
|
|
||||||
|
| Batch Size | 32 | 64 | 128 | 256 |
|
||||||
|
| -- | -- | -- | -- | -- |
|
||||||
|
| PaddlePaddle Fluid | - | - | - | - |
|
||||||
|
| PaddlePaddle v2 | - | - | - | - |
|
||||||
|
| TensorFlow | - | - | - | - |
|
||||||
|
|
||||||
|
### Measure the Performance for Different PServer Count
|
||||||
|
|
||||||
|
- Trainer Count: 100
|
||||||
|
- Batch Size: 64
|
||||||
|
- Metrics: mini-batch / sec
|
||||||
|
|
||||||
|
| PServer Count | 10 | 20 | 40 | 60 |
|
||||||
|
| -- | -- | -- | -- | -- |
|
||||||
|
| PaddlePaddle Fluid | - | - | - | - |
|
||||||
|
| PaddlePaddle v2 | - | - | - | - |
|
||||||
|
| TensorFlow | - | - | - | - |
|
||||||
|
|
||||||
|
### Measure Parallel Efficiency By Increasing Trainer Count
|
||||||
|
|
||||||
|
- PServer Count: 20
|
||||||
|
- Batch Size: 64
|
||||||
|
- Metrics:
|
||||||
|
|
||||||
|
$S = \div(T1, TN)$
|
||||||
|
|
||||||
|
which S is the ratio of T1 over TN, training time of 1 and N trainers.
|
||||||
|
The parallel efficiency is:
|
||||||
|
|
||||||
|
$E = \div(S, N)$
|
||||||
|
|
||||||
|
| Trainer Counter | 1 | 10 | 20 | 30 | 40 | 50 | 60 | 70 | 80 | 90 | 100 |
|
||||||
|
| -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- |
|
||||||
|
| PaddlePaddle Fluid | - | - | - | - | - | - | - | - | - | - | - |
|
||||||
|
| PaddlePaddle v2 | - | - | - | - | - | - | - | - | - | - | - | - |
|
||||||
|
| TensorFlow | - | - | - | - | - | - | - | - | - | - | - | - | - |
|
||||||
|
|
||||||
|
## Reproduce the benchmark
|
||||||
|
|
||||||
|
TODO
|
After Width: | Height: | Size: 15 KiB |
After Width: | Height: | Size: 16 KiB |
After Width: | Height: | Size: 14 KiB |
After Width: | Height: | Size: 19 KiB |
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue