├── .gitignore
├── .pydevproject
├── README.md
├── cascade_adv_training
├── README.md
├── cifar_load.py
├── convert_pickle.py
├── dataset.py
├── evaluation.py
├── helpers.py
├── layers.py
├── lenet.py
├── main.py
├── model.py
├── provider.py
├── re_li_attack.py
├── re_li_attack_notanh.py
├── resnet.py
├── resnet_layers.py
├── run_all_gpu0
├── runstep.npz
├── tf_rename_variables.py
└── utils.py
├── confusion.py
├── guided-denoiser
├── LICENSE.txt
├── README.md
├── dataset.py
├── defense.py
├── helpers.py
├── inception.py
├── inceptionresnet.py
├── inceptionresnetv2.py
├── inres.py
├── metadata.json
├── provider.py
├── re_li_attack.py
├── re_li_attack_notanh.py
├── res152_wide.py
├── resnet.py
├── resnext.py
├── resnext101.py
├── resnext_features
│ ├── __init__.py
│ ├── resnext101_32x4d_features.py
│ └── resnext101_64x4d_features.py
└── v3.py
├── inputtransformations
├── .gitignore
├── README.md
├── bitdepth.ipynb
├── crop.ipynb
├── defense.py
├── helpers.py
├── imagenet_labels.py
├── inceptionv3.py
├── jpeg.ipynb
├── quilt.ipynb
├── quilt_preprocess.py
├── re_l2_attack.py
├── re_l2_attack_clipimage.py
├── re_l2_attack_clipimage_notanh.py
├── re_li_attack.py
├── robustml_attack.py
├── robustml_model.py
├── robustml_model_origin.py
├── setup.sh
├── tv.ipynb
└── utils.py
├── lid
├── README.md
├── attack_lid.py
├── cifar10_input.py
├── detect_adv_samples.py
├── evaluation.py
├── evaluation_bpda.py
├── extract_artifacts.py
├── helpers.py
├── re_li_attack.py
└── util.py
├── pixel-deflection
├── README.md
├── demo.ipynb
├── helpers.py
├── imagenet_labels.json
├── images
│ ├── n02443114_00000055.png
│ ├── n02443114_00032317.png
│ └── n02447366_00008562.png
├── main.py
├── maps
│ ├── n02443114_00000055.png
│ ├── n02443114_00032317.png
│ └── n02447366_00008562.png
├── methods.py
├── originals
│ ├── n02443114_00000055.png
│ ├── n02443114_00032317.png
│ └── n02447366_00008562.png
├── re_li_attack.py
└── utils.py
├── randomization
├── .gitignore
├── README.md
├── defense.py
├── defense_batch.py
├── getperturb_li_attack32_tfmultigpu.py
├── helpers.py
├── imagenet_labels.py
├── inceptionv3.py
├── nohup.out
├── provider.py
├── re_li_attack.py
├── re_li_attack299.py
├── re_li_attack32.py
├── re_li_attack32_multigpu.py
├── re_li_attack32_tf.py
├── re_li_attack32_tfmultigpu.py
├── re_li_attack32_tfmultigpu_notanh.py
├── robustml_attack.py
├── robustml_model.py
├── setup.sh
└── utils.py
├── robustnet
├── LICENSE
├── README.md
├── attack.py
├── evaluation.py
├── helpers.py
├── main.py
├── main2.py
├── models
│ ├── __init__.py
│ ├── densenet.py
│ ├── dpn.py
│ ├── googlenet.py
│ ├── layer.py
│ ├── lenet.py
│ ├── mobilenet.py
│ ├── preact_resnet.py
│ ├── resnet.py
│ ├── resnext.py
│ ├── senet.py
│ ├── shufflenet.py
│ └── vgg.py
├── plot_accu.py
├── re_li_attack.py
├── run.sh
├── test.py
├── utils.py
└── utils2.py
├── sap
├── README.md
├── cifar10_input.py
├── cifar_model.py
├── evaluation.py
├── evaluation_bpda.py
├── helpers.py
├── re_li_attack.py
├── robustml_attack.py
├── robustml_model.py
└── sap_model.py
├── therm-adv
├── README.md
├── cifar10_input.py
├── cifar_model.py
├── discretization_attacks.py
├── discretization_utils.py
├── evaluation.py
├── evaluation_bpda.py
├── helpers.py
├── re_li_attack.py
├── re_li_attack_notanh.py
├── robustml_attack.py
├── robustml_model.py
└── train.py
└── wideresnet28
├── README.md
├── cifar10_input.py
├── cifar_model.py
├── config.json
├── discretization_attacks.py
├── discretization_utils.py
├── evaluation.py
├── helpers.py
├── setup.sh
├── test.py
├── test_wres.py
└── train.py
/.gitignore:
--------------------------------------------------------------------------------
1 | cifar10_data/
2 | all_models/
3 | imageNetTest/
4 | data/
5 | *.tar
6 | *.pyc
7 | *.ckpt
8 | *.pth
9 | *.pkl
10 | *.log
11 | .idea/
12 | .settings/
13 | .project
14 | *.zip
15 |
16 |
17 |
--------------------------------------------------------------------------------
/.pydevproject:
--------------------------------------------------------------------------------
1 |
2 |
3 | Default
4 | python interpreter
5 |
6 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # NATTACK: A STRONG AND UNIVERSAL GAUSSIAN BLACK-BOX ADVERSARIAL ATTACK
2 |
3 |
4 | Data and model can be found here: [data and model](https://knightsucfedu39751-my.sharepoint.com/:f:/g/personal/liyandong_knights_ucf_edu/EnmkFaQkvwdDq0xcqIbbEfYBAhSkQK16ONPgjMJncbCwmg).
5 |
6 |
7 | Please download the data&&model and unzip them to './cifar-data' and './all_models'
8 |
9 |
10 | Below is Table 1 from our paper, where we show the robustness of each accepted defense to the adversarial examples we can construct:
11 |
12 |
13 |
14 | | Defense | Dataset | Distance | Success rate |
15 | |---|---|---|---|
16 | | ADV-TRAIN [Madry et al. (2018)](https://arxiv.org/abs/1706.06083) | CIFAR | 0.031 (linf) | 47.9% |
17 | | ADV-BNN [Liu et al. (2019)](https://arxiv.org/abs/1810.01279) | CIFAR | 0.035 (linf) | 75.3% |
18 | | THERM-ADV [Buckman et al. (2018)](https://openreview.net/forum?id=S18Su--CW)[Madry et al. (2018)](https://arxiv.org/abs/1706.06083) | CIFAR | 0.031 (linf) | 91.2% |
19 | | CAS-ADV [Na et al. (2018)](https://arxiv.org/abs/1708.02582) | CIFAR | 0.031 (linf) | 97.7% |
20 | | ADV-GAN [Wang & Yu (2019)](https://openreview.net/forum?id=S1lIMn05F7) | CIFAR | 0.015 (linf) | 98.3% |
21 | | LID [Ma et al. (2018)](https://arxiv.org/abs/1801.02613) | CIFAR | 0.031 (linf) | 100.0% |
22 | | THERM [Buckman et al. (2018)](https://openreview.net/forum?id=S18Su--CW) | CIFAR | 0.031 (linf) | 100.0% |
23 | | SAP [Dhillon et al. (2018)](https://arxiv.org/abs/1803.01442) | CIFAR | 0.031 (linf) | 100.0% |
24 | | RSE [Liu et al. (2018)](https://arxiv.org/abs/1712.00673) | CIFAR | 0.031 (linf) | 100.0% |
25 | | GUIDED DENOISER [(Liao et al., 2018)](https://arxiv.org/abs/1711.00117) | ImageNet | 0.031 (linf) | 95.5% |
26 | | RANDOMIZATION [Xie et al. (2018)](https://arxiv.org/abs/1711.01991) | ImageNet | 0.031 (linf) | 96.5% |
27 | | INPUT-TRANS [Guo et al. (2018)](https://arxiv.org/abs/1711.00117) | ImageNet | 0.05 (l2) | 100.0% |
28 | | PIXEL DEFLECTION [Prakash et al. (2018)](https://arxiv.org/abs/1801.08926) | ImageNet | 0.031 (linf) | 100.0% |
29 |
30 |
31 |
32 |
33 | ## Paper
34 |
35 | **Abstract:**
36 |
37 | Powerful adversarial attack methods are vital for understanding how to construct robust deep neural networks (DNNs) and for thoroughly testing defense techniques. In this paper, we propose a black-box adversarial attack algorithm that can defeat both vanilla DNNs and those generated by various defense techniques developed recently. Instead of searching for an "optimal" adversarial example for a benign input to a targeted DNN, our algorithm finds a probability density distribution over a small region centered around the input, such that a sample drawn from this distribution is likely an adversarial example, without the need of accessing the DNN's internal layers or weights. Our approach is universal as it can successfully attack different neural networks by a single algorithm. It is also strong; according to the testing against 2 vanilla DNNs and 13 defended ones, it outperforms state-of-the-art black-box or white-box attack methods for most test cases. Additionally, our results reveal that adversarial training remains one of the best defense techniques, and the adversarial examples are not as transferable across defended DNNs as them across vanilla DNNs.
38 |
39 |
40 | ## Source code
41 |
42 | This repository contains our implemenation of the black-box attack algorithm described in our paper, six defense methods (SAP, LID, RANDOMIZATION, INPUT-TRANS, THERM, and THERM-DAV) borrowed from the code of Anish et al. (2018), two defended models (GUIDED DENOISER and PIXEL DEFLECTION) based on the code of Athalye & Carlini, (2018), and two defended models (RSE and CAS-ADV) from the original papers.
43 |
44 | ## Note
45 |
--------------------------------------------------------------------------------
/cascade_adv_training/README.md:
--------------------------------------------------------------------------------
1 | # Cascade Adversarial Training Regularized with a Unified Embedding
2 |
3 |
4 |
5 | “[Cascade Adversarial Machine Learning Regularized with a Unified Embedding](https://arxiv.org/pdf/1708.02582.pdf),”
6 |
7 | Taesik Na, Jong Hwan Ko and Saibal Mukhopadhyay,
8 | International Conference on Learning Representations (ICLR), Apr 2018
9 |
10 |
11 | ## Requirements
12 |
13 | The code was tested with Python 2.7.12 and Tensorflow 1.4.0.
14 |
15 | ## [NATTACK] evaluation
16 |
17 | Run with:
18 |
19 | ```bash
20 | python re_li_attack.py
21 |
--------------------------------------------------------------------------------
/cascade_adv_training/cifar_load.py:
--------------------------------------------------------------------------------
1 | import numpy as np
2 | import os
3 | import tarfile
4 | from six.moves import urllib
5 | import sys
6 |
7 |
8 | CIFAR10_DATA_URL = 'http://www.cs.toronto.edu/~kriz/cifar-10-python.tar.gz'
9 | CIFAR100_DATA_URL = 'http://www.cs.toronto.edu/~kriz/cifar-100-python.tar.gz'
10 |
11 | def maybe_download_and_extract(dest_directory, is_cifar10):
12 | """Download and extract the tarball from Alex's website."""
13 | if not os.path.exists(dest_directory):
14 | os.makedirs(dest_directory)
15 | DATA_URL = CIFAR10_DATA_URL if is_cifar10 else CIFAR100_DATA_URL
16 | filename = DATA_URL.split('/')[-1]
17 | filepath = os.path.join(dest_directory, filename)
18 | if not os.path.exists(filepath):
19 | def _progress(count, block_size, total_size):
20 | sys.stdout.write('\r>> Downloading %s %.1f%%' % (filename,
21 | float(count * block_size) / float(total_size) * 100.0))
22 | sys.stdout.flush()
23 | filepath, _ = urllib.request.urlretrieve(DATA_URL, filepath, _progress)
24 | print()
25 | statinfo = os.stat(filepath)
26 | print('Successfully downloaded', filename, statinfo.st_size, 'bytes.')
27 |
28 | tarfile.open(filepath, 'r:gz').extractall(dest_directory)
29 |
30 |
31 | def one_hot(x, n):
32 | """
33 | convert index representation to one-hot representation
34 | """
35 | x = np.array(x)
36 | assert x.ndim == 1
37 | return np.eye(n)[x]
38 |
39 |
40 | def _load_batch_cifar10(data_dir, filename, dtype='float32'):
41 | """
42 | load a batch in the CIFAR-10 format
43 | """
44 | #data_dir_cifar10 = os.path.join(data_dir, "cifar-10-batches-py")
45 | data_dir_cifar10 = data_dir
46 | path = os.path.join(data_dir_cifar10, filename)
47 | batch = np.load(path)
48 | data = batch['data']
49 | data = data.reshape([-1, 3, 32, 32])
50 | data = data.transpose([0, 2, 3, 1])
51 | # convert labels to one-hot representation
52 | labels = one_hot(batch['labels'], n=10)
53 | return data.astype(dtype), labels.astype(dtype)
54 |
55 |
56 | def _grayscale(a):
57 | return np.expand_dims(a.reshape(-1, 32, 32, 3).mean(3), 3)
58 | # return a.reshape(a.shape[0], 32, 32, 3).mean(3).reshape(a.shape[0], -1)
59 |
60 |
61 | def cifar10(data_dir, dtype='float32', grayscale=False):
62 | # train
63 | x_train = []
64 | t_train = []
65 | for k in range(5):
66 | x, t = _load_batch_cifar10(data_dir, "data_batch_%d" % (k + 1), dtype=dtype)
67 | x_train.append(x)
68 | t_train.append(t)
69 |
70 | x_train = np.concatenate(x_train, axis=0)
71 | t_train = np.concatenate(t_train, axis=0)
72 |
73 | # test
74 | x_test, t_test = _load_batch_cifar10(data_dir, "test_batch", dtype=dtype)
75 |
76 | if grayscale:
77 | x_train = _grayscale(x_train)
78 | x_test = _grayscale(x_test)
79 |
80 | return x_train, t_train, x_test, t_test
81 |
82 |
83 | def _load_batch_cifar100(data_dir, filename, dtype='float32'):
84 | """
85 | load a batch in the CIFAR-100 format
86 | """
87 | data_dir_cifar100 = os.path.join(data_dir, "cifar-100-python")
88 | path = os.path.join(data_dir_cifar100, filename)
89 | batch = np.load(path)
90 | data = batch['data']
91 | data = data.reshape([-1, 3, 32, 32])
92 | data = data.transpose([0, 2, 3, 1])
93 | labels = one_hot(batch['fine_labels'], n=100)
94 | return data.astype(dtype), labels.astype(dtype)
95 |
96 |
97 | def cifar100(data_dir, dtype='float32', grayscale=False):
98 | x_train, t_train = _load_batch_cifar100(data_dir, "train", dtype=dtype)
99 | x_test, t_test = _load_batch_cifar100(data_dir, "test", dtype=dtype)
100 |
101 | if grayscale:
102 | x_train = _grayscale(x_train)
103 | x_test = _grayscale(x_test)
104 |
105 | return x_train, t_train, x_test, t_test
106 |
107 |
--------------------------------------------------------------------------------
/cascade_adv_training/convert_pickle.py:
--------------------------------------------------------------------------------
1 | import pickle
2 | import os
3 |
4 | y=[]
5 | dirs = os.listdir('./')
6 | for x in dirs:
7 | if 'perturb' in x and ('cascade' not in x and 'thermo' not in x):
8 | y.append(x)
9 | files = os.listdir(x)
10 | for z in files:
11 | temp = pickle.load(open(x + '/' +z,'rb'))
12 | pickle.dump(temp, open(x + '/' +z,'wb'), protocol=2)
13 |
--------------------------------------------------------------------------------
/cascade_adv_training/dataset.py:
--------------------------------------------------------------------------------
1 | # Copyright 2015 The TensorFlow 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 |
16 | from __future__ import absolute_import
17 | from __future__ import division
18 | from __future__ import print_function
19 |
20 | import numpy
21 | from six.moves import xrange
22 |
23 | from tensorflow.python.framework import dtypes
24 |
25 | class DataSet(object):
26 |
27 | def __init__(self,
28 | images,
29 | labels,
30 | fake_data=False,
31 | one_hot=False,
32 | dtype=dtypes.float32,
33 | reshape=True):
34 | """Construct a DataSet.
35 | one_hot arg is used only if fake_data is true. `dtype` can be either
36 | `uint8` to leave the input as `[0, 255]`, or `float32` to rescale into
37 | `[0, 1]`.
38 | """
39 | dtype = dtypes.as_dtype(dtype).base_dtype
40 | if dtype not in (dtypes.uint8, dtypes.float32):
41 | raise TypeError('Invalid image dtype %r, expected uint8 or float32' %
42 | dtype)
43 | if fake_data:
44 | self._num_examples = 10000
45 | self.one_hot = one_hot
46 | else:
47 | assert images.shape[0] == labels.shape[0], (
48 | 'images.shape: %s labels.shape: %s' % (images.shape, labels.shape))
49 | self._num_examples = images.shape[0]
50 |
51 | # Convert shape from [num examples, rows, columns, depth]
52 | # to [num examples, rows*columns] (assuming depth == 1)
53 | if reshape:
54 | assert images.shape[3] == 1
55 | images = images.reshape(images.shape[0],
56 | images.shape[1] * images.shape[2])
57 | if dtype == dtypes.float32:
58 | # Convert from [0, 255] -> [0.0, 1.0].
59 | images = images.astype(numpy.float32)
60 | images = numpy.multiply(images, 1.0 / 255.0)
61 | self._images = images
62 | self._labels = labels
63 | self._epochs_completed = 0
64 | self._index_in_epoch = 0
65 |
66 | @property
67 | def images(self):
68 | return self._images
69 |
70 | @property
71 | def labels(self):
72 | return self._labels
73 |
74 | @property
75 | def num_examples(self):
76 | return self._num_examples
77 |
78 | @property
79 | def epochs_completed(self):
80 | return self._epochs_completed
81 |
82 | def next_batch(self, batch_size, fake_data=False, perm=None):
83 | """Return the next `batch_size` examples from this data set."""
84 | if fake_data:
85 | fake_image = [1] * 784
86 | if self.one_hot:
87 | fake_label = [1] + [0] * 9
88 | else:
89 | fake_label = 0
90 | return [fake_image for _ in xrange(batch_size)], [
91 | fake_label for _ in xrange(batch_size)], None
92 | start = self._index_in_epoch
93 | self._index_in_epoch += batch_size
94 | if self._index_in_epoch > self._num_examples:
95 | # Finished epoch
96 | self._epochs_completed += 1
97 | # Shuffle the data
98 | if perm is None:
99 | perm = numpy.arange(self._num_examples)
100 | numpy.random.shuffle(perm)
101 | self._images = self._images[perm]
102 | self._labels = self._labels[perm]
103 | # Start next epoch
104 | start = 0
105 | self._index_in_epoch = batch_size
106 | assert batch_size <= self._num_examples
107 | else:
108 | perm = None
109 | end = self._index_in_epoch
110 | return self._images[start:end], self._labels[start:end], perm
111 |
112 |
113 |
--------------------------------------------------------------------------------
/cascade_adv_training/helpers.py:
--------------------------------------------------------------------------------
1 | import operator as op
2 | import functools as ft
3 | import numpy as np
4 |
5 |
6 | '''reduce_* helper functions reduce tensors on all dimensions but the first.
7 | They are intended to be used on batched tensors where dim 0 is the batch dim.
8 | '''
9 |
10 |
11 | def reduce_sum(x, keepdim=True):
12 | # silly PyTorch, when will you get proper reducing sums/means?
13 | for a in reversed(range(1, x.dim())):
14 | x = x.sum(a, keepdim=keepdim)
15 | return x
16 |
17 |
18 | def reduce_mean(x, keepdim=True):
19 | numel = ft.reduce(op.mul, x.size()[1:])
20 | x = reduce_sum(x, keepdim=keepdim)
21 | return x / numel
22 |
23 |
24 | def reduce_min(x, keepdim=True):
25 | for a in reversed(range(1, x.dim())):
26 | x = x.min(a, keepdim=keepdim)[0]
27 | return x
28 |
29 |
30 | def reduce_max(x, keepdim=True):
31 | for a in reversed(range(1, x.dim())):
32 | x = x.max(a, keepdim=keepdim)[0]
33 | return x
34 |
35 |
36 | def torch_arctanh(x, eps=1e-6):
37 | x *= (1. - eps)
38 | return (np.log((1 + x) / (1 - x))) * 0.5
39 |
40 |
41 | def l2r_dist(x, y, keepdim=True, eps=1e-8):
42 | d = (x - y)**2
43 | d = reduce_sum(d, keepdim=keepdim)
44 | d += eps # to prevent infinite gradient at 0
45 | return d.sqrt()
46 |
47 |
48 | def l2_dist(x, y, keepdim=True):
49 | d = (x - y)**2
50 | return reduce_sum(d, keepdim=keepdim)
51 |
52 |
53 | def l1_dist(x, y, keepdim=True):
54 | d = torch.abs(x - y)
55 | return reduce_sum(d, keepdim=keepdim)
56 |
57 |
58 | def l2_norm(x, keepdim=True):
59 | norm = reduce_sum(x*x, keepdim=keepdim)
60 | return norm.sqrt()
61 |
62 |
63 | def l1_norm(x, keepdim=True):
64 | return reduce_sum(x.abs(), keepdim=keepdim)
65 |
66 |
67 | def rescale(x, x_min=-1., x_max=1.):
68 | return x * (x_max - x_min) + x_min
69 |
70 |
71 | def tanh_rescale(x, x_min=-1., x_max=1.):
72 | return (torch.tanh(x) + 1) * 0.5 * (x_max - x_min) + x_min
73 |
--------------------------------------------------------------------------------
/cascade_adv_training/lenet.py:
--------------------------------------------------------------------------------
1 | # Copyright 2015 The TensorFlow 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 |
16 | """Builds the CIFAR-10 network.
17 |
18 | Summary of available functions:
19 |
20 | # Compute input images and labels for training. If you would like to run
21 | # evaluations, use inputs() instead.
22 | inputs, labels = distorted_inputs()
23 |
24 | # Compute inference on the model inputs to make a prediction.
25 | predictions = inference(inputs)
26 |
27 | # Compute the total loss of the prediction with respect to the labels.
28 | loss = loss(predictions, labels)
29 |
30 | # Create a graph to run one step of training with respect to the loss.
31 | train_op = train(loss, global_step)
32 | """
33 | # pylint: disable=missing-docstring
34 | import tensorflow as tf
35 |
36 | from layers import *
37 |
38 | def lenet(images, img_size, num_channels, num_classes,
39 | embedding_at=2):
40 | # conv1
41 | with tf.variable_scope('gated_conv1') as scope:
42 | pre_activation = gated_conv(images, 5, 5, num_channels, 64, None)
43 | conv1 = tf.nn.relu(pre_activation, name=scope.name)
44 | activation_summary(conv1)
45 | # pool1
46 | pool1 = tf.nn.max_pool(conv1, ksize=[1, 3, 3, 1], strides=[1, 2, 2, 1],
47 | padding='SAME', name='pool1')
48 | # norm1
49 | norm1 = tf.nn.lrn(pool1, 4, bias=1.0, alpha=0.001 / 9.0, beta=0.75,
50 | name='norm1')
51 |
52 | if embedding_at == 1:
53 | nrof_embeddings = img_size*img_size*16
54 | embedding = tf.reshape(norm1, [-1, nrof_embeddings])
55 |
56 | # conv2
57 | with tf.variable_scope('gated_conv2') as scope:
58 | pre_activation = gated_conv(norm1, 5, 5, 64, 64, None)
59 | conv2 = tf.nn.relu(pre_activation, name=scope.name)
60 | activation_summary(conv2)
61 | # norm2
62 | norm2 = tf.nn.lrn(conv2, 4, bias=1.0, alpha=0.001 / 9.0, beta=0.75,
63 | name='norm2')
64 | # pool2
65 | pool2 = tf.nn.max_pool(norm2, ksize=[1, 3, 3, 1],
66 | strides=[1, 2, 2, 1], padding='SAME', name='pool2')
67 |
68 | assert pool2.get_shape().as_list()[1:] == [img_size/4, img_size/4, 64]
69 |
70 | dim_unroll = img_size*img_size*4
71 | reshape = tf.reshape(pool2, [-1, dim_unroll])
72 | if embedding_at == 2:
73 | embedding = reshape
74 |
75 | # local3
76 | with tf.variable_scope('local3') as scope:
77 | # Move everything into depth so we can perform a single matrix multiply.
78 | pre_activation = fc(reshape,
79 | dim_unroll, 384, 0.04, 0.004,
80 | 'pre_' + scope.name)
81 | local3 = tf.nn.relu(pre_activation, name=scope.name)
82 | activation_summary(local3)
83 |
84 | if embedding_at == 3:
85 | embedding = local3
86 |
87 | # local4
88 | with tf.variable_scope('local4') as scope:
89 | pre_activation = fc(local3,
90 | 384, 192, 0.04, 0.004,
91 | 'pre_' + scope.name)
92 | local4 = tf.nn.relu(pre_activation, name=scope.name)
93 | activation_summary(local4)
94 |
95 | if embedding_at == 4:
96 | embedding = local4
97 |
98 | # linear layer(WX + b),
99 | # We don't apply softmax here because
100 | # tf.nn.sparse_softmax_cross_entropy_with_logits accepts the unscaled logits
101 | # and performs the softmax internally for efficiency.
102 | with tf.variable_scope('logit') as scope:
103 | logit = fc(local4,
104 | 192, num_classes, 1/192.0, 0.0,
105 | scope.name)
106 | activation_summary(logit)
107 |
108 | if embedding_at > 4:
109 | embedding = logit
110 |
111 | return embedding, logit
112 |
113 |
--------------------------------------------------------------------------------
/cascade_adv_training/run_all_gpu0:
--------------------------------------------------------------------------------
1 | # Initial Training
2 | CUDA_VISIBLE_DEVICES=0 python main.py --max_epochs=10 --is_train=True --adversarial=False --train_dir=./ref/resnet20_cifar10
3 | # Adversarial Training
4 | CUDA_VISIBLE_DEVICES=0 python main.py --is_train=True --adversarial=True --restore=True --checkpoint_dir=./ref/resnet20_cifar10 --train_dir=./checkpoint/resnet20_cifar10_adv
5 | # Training with Pivot
6 | CUDA_VISIBLE_DEVICES=0 python main.py --is_train=True --adversarial=True --pivot_loss_factor=0.0001 --restore=True --checkpoint_dir=./ref/resnet20_cifar10 --train_dir=./checkpoint/resnet20_cifar10_pivot
7 | # Cascade Training with Pivot
8 | CUDA_VISIBLE_DEVICES=0 python main.py --is_train=False --restore_inplace=True --save_iter_fgsm_images=True --test_data_from=train --train_dir=./checkpoint/resnet20_cifar10_pivot
9 | CUDA_VISIBLE_DEVICES=0 python main.py --is_train=True --adversarial=True --pivot_loss_factor=0.0001 --cascade=True --saved_iter_fgsm_dir=./checkpoint/resnet20_cifar10_pivot --restore=True --checkpoint_dir=./ref/resnet20_cifar10 --train_dir=./checkpoint/resnet20_cifar10_pivot_cascade
10 |
11 | # Ensemble Training with Pivot
12 | CUDA_VISIBLE_DEVICES=0 python main.py --is_train=True --adversarial=False --train_dir=./checkpoint/r20_ens_source
13 | CUDA_VISIBLE_DEVICES=0 python main.py --is_train=True --adversarial=False --resnet_n=18 --train_dir=./checkpoint/r110_ens_source
14 | CUDA_VISIBLE_DEVICES=0 python tf_rename_variables.py --checkpoint_dir=checkpoint/r20_ens_source --replace_from=main --replace_to=r20_ens_source
15 | CUDA_VISIBLE_DEVICES=0 python tf_rename_variables.py --checkpoint_dir=checkpoint/r110_ens_source --replace_from=main --replace_to=r110_ens_source
16 | CUDA_VISIBLE_DEVICES=0 python main.py --is_train=True --adversarial=True --pivot_loss_factor=0.0001 --ensemble=True --restore=True --checkpoint_dir=./ref/resnet20_cifar10 --train_dir=./checkpoint/resnet20_cifar10_pivot_ensemble
17 |
18 | # Test with adversarial images from different source network
19 | CUDA_VISIBLE_DEVICES=0 python main.py --is_train=False --restore_inplace=True --save_adver_images=True --test_data_from=validation --train_dir=./checkpoint/resnet20_cifar10_pivot
20 | CUDA_VISIBLE_DEVICES=0 python main.py --is_train=False --restore_inplace=True --use_saved_images=True --saved_data_dir=./checkpoint/resnet20_cifar10_pivot --train_dir=./checkpoint/resnet20_cifar10_pivot_cascade
21 |
22 |
--------------------------------------------------------------------------------
/cascade_adv_training/runstep.npz:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Cold-Winter/Nattack/2c5ce052f0298d52a2972dfce8bbfd9fed6a6fcb/cascade_adv_training/runstep.npz
--------------------------------------------------------------------------------
/cascade_adv_training/tf_rename_variables.py:
--------------------------------------------------------------------------------
1 | # This code is from
2 | # https://gist.github.com/batzner/7c24802dd9c5e15870b4b56e22135c96
3 |
4 | import sys, getopt
5 |
6 | import tensorflow as tf
7 |
8 | usage_str = 'python tensorflow_rename_variables.py --checkpoint_dir=path/to/dir/ ' \
9 | '--replace_from=substr --replace_to=substr --add_prefix=abc --dry_run'
10 |
11 |
12 | def rename(checkpoint_dir, replace_from, replace_to, add_prefix, dry_run):
13 | checkpoint = tf.train.get_checkpoint_state(checkpoint_dir)
14 | with tf.Session() as sess:
15 | for var_name, _ in tf.contrib.framework.list_variables(checkpoint_dir):
16 | # Load the variable
17 | var = tf.contrib.framework.load_variable(checkpoint_dir, var_name)
18 |
19 | # Set the new name
20 | new_name = var_name
21 | if None not in [replace_from, replace_to]:
22 | new_name = new_name.replace(replace_from, replace_to)
23 | if add_prefix:
24 | new_name = add_prefix + new_name
25 |
26 | if dry_run:
27 | print('%s would be renamed to %s.' % (var_name, new_name))
28 | else:
29 | print('Renaming %s to %s.' % (var_name, new_name))
30 | # Rename the variable
31 | var = tf.Variable(var, name=new_name)
32 |
33 | if not dry_run:
34 | # Save the variables
35 | saver = tf.train.Saver()
36 | sess.run(tf.global_variables_initializer())
37 | saver.save(sess, checkpoint.model_checkpoint_path)
38 |
39 |
40 | def main(argv):
41 | checkpoint_dir = None
42 | replace_from = None
43 | replace_to = None
44 | add_prefix = None
45 | dry_run = False
46 |
47 | try:
48 | opts, args = getopt.getopt(argv, 'h', ['help=', 'checkpoint_dir=', 'replace_from=',
49 | 'replace_to=', 'add_prefix=', 'dry_run'])
50 | except getopt.GetoptError:
51 | print(usage_str)
52 | sys.exit(2)
53 | for opt, arg in opts:
54 | if opt in ('-h', '--help'):
55 | print(usage_str)
56 | sys.exit()
57 | elif opt == '--checkpoint_dir':
58 | checkpoint_dir = arg
59 | elif opt == '--replace_from':
60 | replace_from = arg
61 | elif opt == '--replace_to':
62 | replace_to = arg
63 | elif opt == '--add_prefix':
64 | add_prefix = arg
65 | elif opt == '--dry_run':
66 | dry_run = True
67 |
68 | if not checkpoint_dir:
69 | print('Please specify a checkpoint_dir. Usage:')
70 | print(usage_str)
71 | sys.exit(2)
72 |
73 | rename(checkpoint_dir, replace_from, replace_to, add_prefix, dry_run)
74 |
75 |
76 | if __name__ == '__main__':
77 | main(sys.argv[1:])
78 |
--------------------------------------------------------------------------------
/confusion.py:
--------------------------------------------------------------------------------
1 | import matplotlib.pyplot as plt
2 | import numpy as np
3 | import itertools
4 |
5 | target_names = ['THERM','THERM-ADV','LID','SAP','RSE','CAS-ADV','ORIGIN','WRES-28']
6 | cm = np.array([[100.00 ,2.90 , 3.27 , 5.38 , 7.67 , 1.80 , 5.30,11.06],
7 | [2.01 , 100 , 1.11 , 1.47 , 1.73, 1.42 , 1.69, 1.9],
8 | [10.77 , 10.34 , 100 , 6.68, 11.27, 6.18,28.58, 15.66],
9 | [20.00 , 6.13 , 4.14 , 100 , 17.98 , 4.70 , 10.72,26.63],
10 | [ 15.85 , 3.74 , 4.84 , 8.51 , 100 , 2.28 , 10.83,18.11],
11 | [3.70 , 7.42 , 1.67 , 3.83 , 2.76 , 100 , 11.66, 12.88],
12 | [ 9.14 , 6.16 ,15.64 ,4.89 , 10.29 , 4.69, 100.00, 12.49],
13 | [26.51,4.95,7.05,14.75,20.26,4.15,14.59,100.0]])
14 |
15 | # target_names = ['SAP','THERM-ADV','THERM','LID','ORIGIN','WRES-28']
16 | # cm = np.array([[100,19.64,80.02 ,30.54, 2.12, 8.51],
17 | # [4.13, 100, 2.15, 3.14, 1.23, 1.13],
18 | # [67.11, 20.02 ,100 ,52.66, 1.34 ,2.17],
19 | # [30.1, 20.83, 34.26, 100, 8.92, 3.15],
20 | # [22.15, 12.75, 25.16, 48.51, 100, 0.21],
21 | # [97.62, 17.1, 88.23, 37.93, 0.36 ,100]])
22 |
23 |
24 | #if cmap is None:
25 | cmap = plt.get_cmap('tab20b') ### RdGy cool tab20b tab20c
26 |
27 | plt.figure(figsize=(8, 6.5))
28 | #plt.subplot(1,2,1)
29 |
30 | plt.imshow(cm, interpolation='nearest', cmap=cmap)
31 | #plt.title('Confusion Matrix')
32 | plt.colorbar()
33 |
34 | if target_names is not None:
35 | tick_marks = np.arange(len(target_names))
36 | plt.xticks(tick_marks, target_names, rotation=45)
37 | plt.yticks(tick_marks, target_names)
38 |
39 | #if normalize:
40 | #cm = cm.astype('float') / cm.sum(axis=1)[:, np.newaxis]
41 |
42 |
43 | thresh = cm.max() / 100
44 |
45 | for i, j in itertools.product(range(cm.shape[0]), range(cm.shape[1])):
46 | plt.text(j, i, "{:0.2f}".format(cm[i, j]),
47 | horizontalalignment="center",
48 | color="white" if cm[i, j] > thresh else "black", fontsize= 12)
49 | # plt.text(j, i, "{:,}".format(cm[i, j]),
50 | # horizontalalignment="center",
51 | # color="white" if cm[i, j] > thresh else "black")
52 |
53 |
54 | plt.tight_layout()
55 | #plt.ylabel('Defense methods', fontsize = 16)
56 | #plt.xlabel('Perturbation', fontsize = 16)
57 |
58 | #plt.subplot(1,2,2)
59 |
60 |
61 | plt.show()
62 |
--------------------------------------------------------------------------------
/guided-denoiser/README.md:
--------------------------------------------------------------------------------
1 | # Paper
2 | https://arxiv.org/abs/1712.02976
3 |
4 | # Description
5 |
6 | This code is based on the defense solution of team TSAIL in the NIPS 2017: Defense Against Adversarial Attack competition, which is the winner of the competition.
7 |
8 | Our basic idea of defense is to put a denoiser before the a baseline neural network. The denoiser is trained to reduce the pertubation of adversarial examples. And a denoiser is specifically trained for a baseline neural network.
9 |
10 | The solution is an ensemble of 4 independent models and their denoiser (ResNet, ResNext, InceptionV3, inceptionResNetV2).
11 |
12 |
14 |
15 |
16 | ## Requirements
17 |
18 | * Python2 + pytorch0.3.1
19 |
20 | ## [NATTACK] evaluation
21 |
22 | Run with:
23 |
24 | ```bash
25 | python re_li_attack.py --imagenet-path
26 |
27 |
--------------------------------------------------------------------------------
/guided-denoiser/dataset.py:
--------------------------------------------------------------------------------
1 | import torch.utils.data as data
2 |
3 | from PIL import Image
4 | import os
5 | import re
6 | import torch
7 |
8 | IMG_EXTENSIONS = ['.png', '.jpg', '.jpeg']
9 |
10 |
11 | def natural_key(string_):
12 | """See http://www.codinghorror.com/blog/archives/001018.html"""
13 | return [int(s) if s.isdigit() else s for s in re.split(r'(\d+)', string_.lower())]
14 |
15 |
16 | def find_images_and_targets(folder, types=IMG_EXTENSIONS, class_to_idx=None, leaf_name_only=True, sort=True):
17 | if class_to_idx is None:
18 | class_to_idx = dict()
19 | build_class_idx = True
20 | else:
21 | build_class_idx = False
22 | labels = []
23 | filenames = []
24 | for root, subdirs, files in os.walk(folder, topdown=False):
25 | rel_path = os.path.relpath(root, folder) if (root != folder) else ''
26 | label = os.path.basename(rel_path) if leaf_name_only else rel_path.replace(os.path.sep, '_')
27 | if build_class_idx and not subdirs:
28 | class_to_idx[label] = 0
29 | for f in files:
30 | base, ext = os.path.splitext(f)
31 | if ext.lower() in types:
32 | filenames.append(os.path.join(root,f))
33 | labels.append(label)
34 | if build_class_idx:
35 | classes = sorted(class_to_idx.keys(), key=natural_key)
36 | for idx, c in enumerate(classes):
37 | class_to_idx[c] = idx
38 | images_and_targets = zip(filenames, [class_to_idx[l] for l in labels])
39 | if sort:
40 | images_and_targets = sorted(images_and_targets, key=lambda k: natural_key(k[0]))
41 | if build_class_idx:
42 | return images_and_targets, classes, class_to_idx
43 | else:
44 | return images_and_targets
45 |
46 |
47 | class Dataset(data.Dataset):
48 |
49 | def __init__(self, root, transform=None):
50 | imgs, classes, class_to_idx = find_images_and_targets(root)
51 | if len(imgs) == 0:
52 | raise(RuntimeError("Found 0 images in subfolders of: " + root + "\n"
53 | "Supported image extensions are: " + ",".join(IMG_EXTENSIONS)))
54 |
55 | self.root = root
56 | self.imgs = imgs
57 | self.classes = classes
58 | self.class_to_idx = class_to_idx
59 | self.transform = transform
60 |
61 | def __getitem__(self, index):
62 | path, target = self.imgs[index]
63 | img = Image.open(path).convert('RGB')
64 | if self.transform is not None:
65 | img = self.transform(img)
66 | if target is None:
67 | target = torch.zeros(1).long()
68 | return img, target
69 |
70 | def __len__(self):
71 | return len(self.imgs)
72 |
73 | def filenames(self, indices=[]):
74 | if indices:
75 | return [self.imgs[i][0] for i in indices]
76 | else:
77 | return [x[0] for x in self.imgs]
78 |
--------------------------------------------------------------------------------
/guided-denoiser/helpers.py:
--------------------------------------------------------------------------------
1 | import operator as op
2 | import functools as ft
3 | import numpy as np
4 |
5 |
6 | '''reduce_* helper functions reduce tensors on all dimensions but the first.
7 | They are intended to be used on batched tensors where dim 0 is the batch dim.
8 | '''
9 |
10 |
11 | def reduce_sum(x, keepdim=True):
12 | # silly PyTorch, when will you get proper reducing sums/means?
13 | for a in reversed(range(1, x.dim())):
14 | x = x.sum(a, keepdim=keepdim)
15 | return x
16 |
17 |
18 | def reduce_mean(x, keepdim=True):
19 | numel = ft.reduce(op.mul, x.size()[1:])
20 | x = reduce_sum(x, keepdim=keepdim)
21 | return x / numel
22 |
23 |
24 | def reduce_min(x, keepdim=True):
25 | for a in reversed(range(1, x.dim())):
26 | x = x.min(a, keepdim=keepdim)[0]
27 | return x
28 |
29 |
30 | def reduce_max(x, keepdim=True):
31 | for a in reversed(range(1, x.dim())):
32 | x = x.max(a, keepdim=keepdim)[0]
33 | return x
34 |
35 |
36 | def torch_arctanh(x, eps=1e-6):
37 | x *= (1. - eps)
38 | return (np.log((1 + x) / (1 - x))) * 0.5
39 |
40 |
41 | def l2r_dist(x, y, keepdim=True, eps=1e-8):
42 | d = (x - y)**2
43 | d = reduce_sum(d, keepdim=keepdim)
44 | d += eps # to prevent infinite gradient at 0
45 | return d.sqrt()
46 |
47 |
48 | def l2_dist(x, y, keepdim=True):
49 | d = (x - y)**2
50 | return reduce_sum(d, keepdim=keepdim)
51 |
52 |
53 | def l1_dist(x, y, keepdim=True):
54 | d = torch.abs(x - y)
55 | return reduce_sum(d, keepdim=keepdim)
56 |
57 |
58 | def l2_norm(x, keepdim=True):
59 | norm = reduce_sum(x*x, keepdim=keepdim)
60 | return norm.sqrt()
61 |
62 |
63 | def l1_norm(x, keepdim=True):
64 | return reduce_sum(x.abs(), keepdim=keepdim)
65 |
66 |
67 | def rescale(x, x_min=-1., x_max=1.):
68 | return x * (x_max - x_min) + x_min
69 |
70 |
71 | def tanh_rescale(x, x_min=-1., x_max=1.):
72 | return (torch.tanh(x) + 1) * 0.5 * (x_max - x_min) + x_min
73 |
--------------------------------------------------------------------------------
/guided-denoiser/inres.py:
--------------------------------------------------------------------------------
1 | import torch
2 | import numpy as np
3 | from inceptionresnet import get_net, Conv, Bottleneck
4 |
5 | config = dict()
6 | config['flip'] = True
7 | config['loss_idcs'] = [4]
8 | config['net_type'] = 'inceptionresnetv2'
9 |
10 | input_size = [299, 299]
11 | block = [Conv, None, None, None, None]
12 | fwd_out = [
13 | [64, 128, 256, 256, 256],
14 | [],
15 | [],
16 | [],
17 | []]
18 | num_fwd = [
19 | [2, 3, 3, 3, 3],
20 | [],
21 | [],
22 | [],
23 | []]
24 | back_out = [
25 | [64, 128, 256, 256],
26 | [],
27 | [],
28 | [],
29 | []]
30 | num_back = [
31 | [2, 3, 3, 3],
32 | [],
33 | [],
34 | [],
35 | []]
36 | n = 1
37 | hard_mining = 0
38 | loss_norm = False
39 |
40 | def get_model():
41 | net = get_net(input_size, block, fwd_out, num_fwd, back_out, num_back, n, hard_mining, loss_norm)
42 | return config, net
43 |
--------------------------------------------------------------------------------
/guided-denoiser/metadata.json:
--------------------------------------------------------------------------------
1 | {
2 | "type": "defense",
3 | "container":"floydhub/pytorch:0.2.0-py2.11",
4 | "container_gpu": "floydhub/pytorch:0.2.0-gpu-py2.11",
5 | "entry_point": "run_defense.sh"
6 | }
7 |
--------------------------------------------------------------------------------
/guided-denoiser/res152_wide.py:
--------------------------------------------------------------------------------
1 | import torch
2 | import numpy as np
3 | from resnet import get_net, Conv, Bottleneck
4 |
5 | config = dict()
6 | config['flip'] = True
7 | config['loss_idcs'] = [4]
8 |
9 | net_type = 'resnet152'
10 | input_size = [299, 299]
11 | block = [Conv, None, None, None, None]
12 | fwd_out = [
13 | [64, 128, 256, 256, 256],
14 | [128, 256, 256, 256],
15 | [],
16 | [],
17 | []]
18 | num_fwd = [
19 | [2, 3, 3, 3, 3],
20 | [2, 3, 3, 3],
21 | [],
22 | [],
23 | []]
24 | back_out = [
25 | [64, 128, 256, 256],
26 | [128, 256, 256],
27 | [],
28 | [],
29 | []]
30 | num_back = [
31 | [2, 3, 3, 3],
32 | [2, 3, 3],
33 | [],
34 | [],
35 | []]
36 | n = 1
37 | hard_mining = 0
38 | loss_norm = False
39 |
40 | def get_model():
41 | net = get_net(net_type, input_size, block, fwd_out, num_fwd, back_out, num_back, n, hard_mining, loss_norm)
42 | return config, net
43 |
--------------------------------------------------------------------------------
/guided-denoiser/resnext101.py:
--------------------------------------------------------------------------------
1 | import torch
2 | import numpy as np
3 | from resnext import get_net, Conv, Bottleneck
4 |
5 | config = dict()
6 | config['flip'] = True
7 | config['loss_idcs'] = [1]
8 |
9 | net_type = 'resnext101'
10 | config['net_type'] = net_type
11 | input_size = [299, 299]
12 | block = Conv
13 | fwd_out = [64, 128, 256, 256, 256]
14 | num_fwd = [2, 3, 3, 3, 3]
15 | back_out = [64, 128, 256, 256]
16 | num_back = [2, 3, 3, 3]
17 | n = 1
18 | hard_mining = 0
19 | loss_norm = False
20 |
21 | def get_model():
22 | net = get_net(input_size, block, fwd_out, num_fwd, back_out, num_back, n, hard_mining, loss_norm)
23 | return config, net
24 |
--------------------------------------------------------------------------------
/guided-denoiser/resnext_features/__init__.py:
--------------------------------------------------------------------------------
1 | from .resnext101_32x4d_features import resnext101_32x4d_features
2 | from .resnext101_64x4d_features import resnext101_64x4d_features
--------------------------------------------------------------------------------
/guided-denoiser/v3.py:
--------------------------------------------------------------------------------
1 | import torch
2 | import numpy as np
3 | from inception import get_net, Conv, Bottleneck
4 |
5 | config = dict()
6 | config['flip'] = True
7 | config['loss_idcs'] = [1]
8 | config['net_type'] = 'inceptionresnetv2'
9 | input_size = [299, 299]
10 | block = Conv
11 | fwd_out = [64, 128, 256, 256, 256]
12 | num_fwd = [2, 3, 3, 3, 3]
13 | back_out = [64, 128, 256, 256]
14 | num_back = [2, 3, 3, 3]
15 | n = 1
16 | hard_mining = 0
17 | loss_norm = False
18 |
19 | def get_model():
20 | net = get_net(input_size, block, fwd_out, num_fwd, back_out, num_back, n, hard_mining, loss_norm)
21 |
22 |
23 | return config, net
24 |
--------------------------------------------------------------------------------
/inputtransformations/.gitignore:
--------------------------------------------------------------------------------
1 | quilt_db.npy
2 |
--------------------------------------------------------------------------------
/inputtransformations/README.md:
--------------------------------------------------------------------------------
1 | # Countering Adversarial Images using Input Transformations
2 |
3 | Paper: [Guo et al. 2018](https://arxiv.org/abs/1711.00117)
4 |
5 |
6 | ## Requirements
7 |
8 | * Python3 + tensorflow
9 |
10 | ## [NATTACK] evaluation
11 |
12 | Run with:
13 |
14 | ```bash
15 | python re_l2_attack_clipimage.py --imagenet-path
16 | ````
17 | You can define the defense type in re_l2_attack_clipimage.py
18 | Where `` is one of `bitdepth`, `jpeg`, `crop`, `quilt`, or `tv`.
19 |
20 | [robustml]: https://github.com/robust-ml/robustml
21 |
--------------------------------------------------------------------------------
/inputtransformations/helpers.py:
--------------------------------------------------------------------------------
1 | import operator as op
2 | import functools as ft
3 | import numpy as np
4 |
5 |
6 | '''reduce_* helper functions reduce tensors on all dimensions but the first.
7 | They are intended to be used on batched tensors where dim 0 is the batch dim.
8 | '''
9 |
10 |
11 | def reduce_sum(x, keepdim=True):
12 | # silly PyTorch, when will you get proper reducing sums/means?
13 | for a in reversed(range(1, x.dim())):
14 | x = x.sum(a, keepdim=keepdim)
15 | return x
16 |
17 |
18 | def reduce_mean(x, keepdim=True):
19 | numel = ft.reduce(op.mul, x.size()[1:])
20 | x = reduce_sum(x, keepdim=keepdim)
21 | return x / numel
22 |
23 |
24 | def reduce_min(x, keepdim=True):
25 | for a in reversed(range(1, x.dim())):
26 | x = x.min(a, keepdim=keepdim)[0]
27 | return x
28 |
29 |
30 | def reduce_max(x, keepdim=True):
31 | for a in reversed(range(1, x.dim())):
32 | x = x.max(a, keepdim=keepdim)[0]
33 | return x
34 |
35 |
36 | def torch_arctanh(x, eps=1e-6):
37 | x *= (1. - eps)
38 | return (np.log((1 + x) / (1 - x))) * 0.5
39 |
40 |
41 | def l2r_dist(x, y, keepdim=True, eps=1e-8):
42 | d = (x - y)**2
43 | d = reduce_sum(d, keepdim=keepdim)
44 | d += eps # to prevent infinite gradient at 0
45 | return d.sqrt()
46 |
47 |
48 | def l2_dist(x, y, keepdim=True):
49 | d = (x - y)**2
50 | return reduce_sum(d, keepdim=keepdim)
51 |
52 |
53 | def l1_dist(x, y, keepdim=True):
54 | d = torch.abs(x - y)
55 | return reduce_sum(d, keepdim=keepdim)
56 |
57 |
58 | def l2_norm(x, keepdim=True):
59 | norm = reduce_sum(x*x, keepdim=keepdim)
60 | return norm.sqrt()
61 |
62 |
63 | def l1_norm(x, keepdim=True):
64 | return reduce_sum(x.abs(), keepdim=keepdim)
65 |
66 |
67 | def rescale(x, x_min=-1., x_max=1.):
68 | return x * (x_max - x_min) + x_min
69 |
70 |
71 | def tanh_rescale(x, x_min=-1., x_max=1.):
72 | return (torch.tanh(x) + 1) * 0.5 * (x_max - x_min) + x_min
73 |
--------------------------------------------------------------------------------
/inputtransformations/inceptionv3.py:
--------------------------------------------------------------------------------
1 | from utils import optimistic_restore
2 | import tensorflow as tf
3 | import tensorflow.contrib.slim as slim
4 | import tensorflow.contrib.slim.nets as nets
5 | import functools
6 | import os
7 |
8 | _INCEPTION_CHECKPOINT_NAME = 'inception_v3.ckpt'
9 | INCEPTION_CHECKPOINT_PATH = os.path.join(
10 | os.path.dirname(__file__),
11 | 'data',
12 | _INCEPTION_CHECKPOINT_NAME
13 | )
14 | INCEPTION_CHECKPOINT_PATH = '../all_models/random/inception_v3.ckpt'
15 | def _get_model(reuse):
16 | arg_scope = nets.inception.inception_v3_arg_scope(weight_decay=0.0)
17 | func = nets.inception.inception_v3
18 | @functools.wraps(func)
19 | def network_fn(images):
20 | with slim.arg_scope(arg_scope):
21 | return func(images, 1001, is_training=False, reuse=reuse)
22 | if hasattr(func, 'default_image_size'):
23 | network_fn.default_image_size = func.default_image_size
24 | return network_fn
25 |
26 | def _preprocess(image, height, width, scope=None):
27 | with tf.name_scope(scope, 'eval_image', [image, height, width]):
28 | if image.dtype != tf.float32:
29 | image = tf.image.convert_image_dtype(image, dtype=tf.float32)
30 | image = tf.image.resize_bilinear(image, [height, width], align_corners=False)
31 | image = tf.subtract(image, 0.5)
32 | image = tf.multiply(image, 2.0)
33 | return image
34 |
35 | # input is [batch, ?, ?, 3], pixels in [0, 1]
36 | # it's rescaled to [batch, 299, 299, 3] and shifted to [-1, 1]
37 | # output is [batch, 1000] (imagenet classes)
38 | _inception_initialized = False
39 | def model(sess, image):
40 | global _inception_initialized
41 | network_fn = _get_model(reuse=_inception_initialized)
42 | size = network_fn.default_image_size
43 | preprocessed = _preprocess(image, size, size)
44 | logits, _ = network_fn(preprocessed)
45 | logits = logits[:,1:] # ignore background class
46 | predictions = tf.argmax(logits, 1)
47 |
48 | if not _inception_initialized:
49 | optimistic_restore(sess, INCEPTION_CHECKPOINT_PATH)
50 | _inception_initialized = True
51 |
52 | return logits, predictions
53 |
--------------------------------------------------------------------------------
/inputtransformations/quilt_preprocess.py:
--------------------------------------------------------------------------------
1 | import os
2 | import random
3 | import PIL
4 | import PIL.Image
5 | import numpy as np
6 | import sys
7 |
8 |
9 | SAMPLES = 1000000
10 | DIM = 5
11 | RESIZE = True
12 | RESIZE_DIM = 300
13 | OUTPUT_FILE = 'quilt_db.npy'
14 |
15 | def main(argv):
16 | imagenet_train_dir = argv[1]
17 |
18 | assert SAMPLES % 1000 == 0
19 |
20 | db = np.zeros((SAMPLES, DIM, DIM, 3), dtype=np.float32)
21 |
22 | idx = 0
23 | files = []
24 | for d in os.listdir(imagenet_train_dir):
25 | d = os.path.join(imagenet_train_dir, d)
26 | files.extend(os.path.join(d, i) for i in os.listdir(d) if i.endswith('.JPEG'))
27 | for f in random.sample(files, SAMPLES):
28 | img = load_image(f)
29 | h, w, _ = img.shape
30 | h_start = random.randint(0, h - DIM)
31 | w_start = random.randint(0, w - DIM)
32 | crop = img[h_start:h_start+DIM, w_start:w_start+DIM, :]
33 | db[idx, :, :, :] = crop
34 | idx += 1
35 |
36 | if idx % 100 == 0:
37 | print('%.2f%% done' % (100 * (float(idx) / SAMPLES)))
38 |
39 | np.save(OUTPUT_FILE, db)
40 |
41 |
42 | def load_image(path):
43 | image = PIL.Image.open(path)
44 | if RESIZE:
45 | if image.height > image.width:
46 | image = image.resize((int(float(image.width) / image.height * RESIZE_DIM), RESIZE_DIM))
47 | elif image.width > image.height:
48 | image = image.resize((RESIZE_DIM, int(float(image.height) / image.width * RESIZE_DIM)))
49 | img = np.asarray(image).astype(np.float32) / 255.0
50 | if img.ndim == 2:
51 | img = np.repeat(img[:,:,np.newaxis], repeats=3, axis=2)
52 | if img.shape[2] == 4:
53 | # alpha channel
54 | img = img[:,:,:3]
55 | return img
56 |
57 |
58 | if __name__ == '__main__':
59 | main(sys.argv)
60 |
61 |
--------------------------------------------------------------------------------
/inputtransformations/robustml_attack.py:
--------------------------------------------------------------------------------
1 | import robustml
2 | from robustml_model_origin import InputTransformations
3 | import sys
4 | import argparse
5 | import tensorflow as tf
6 | import numpy as np
7 | import time
8 |
9 | class BPDA(robustml.attack.Attack):
10 | def __init__(self, sess, model, epsilon, max_steps=1000, learning_rate=0.1, lam=1e-6, debug=False):
11 | self._sess = sess
12 |
13 | self._model = model
14 | self._input = model.input
15 | self._l2_input = tf.placeholder(tf.float32, self._input.shape) # using BPDA, so we want this to pass the original adversarial example
16 | self._original = tf.placeholder(tf.float32, self._input.shape)
17 | self._label = tf.placeholder(tf.int32, ())
18 | one_hot = tf.expand_dims(tf.one_hot(self._label, 1000), axis=0)
19 | ensemble_labels = tf.tile(one_hot, (model.logits.shape[0], 1))
20 | self._l2 = tf.sqrt(2*tf.nn.l2_loss(self._l2_input - self._original))
21 | self._xent = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits_v2(logits=model.logits, labels=ensemble_labels))
22 | self._loss = lam * tf.maximum(self._l2 - epsilon, 0) + self._xent
23 | self._grad, = tf.gradients(self._loss, self._input)
24 |
25 | self._epsilon = epsilon
26 | self._max_steps = max_steps
27 | self._learning_rate = learning_rate
28 | self._debug = debug
29 |
30 | def run(self, x, y, target):
31 | if target is not None:
32 | raise NotImplementedError
33 | adv = np.copy(x)
34 | for i in range(self._max_steps):
35 | adv_def = self._model.defend(adv)
36 | p, ll2, lxent, g = self._sess.run(
37 | [self._model.predictions, self._l2, self._xent, self._grad],
38 | {self._input: adv_def, self._label: y, self._l2_input: adv, self._original: x}
39 | )
40 | if self._debug:
41 | print(
42 | 'attack: step %d/%d, xent loss = %g, l2 loss = %g (max %g), (true %d, predicted %s)' % (
43 | i+1,
44 | self._max_steps,
45 | lxent,
46 | ll2,
47 | self._epsilon,
48 | y,
49 | p
50 | ),
51 | file=sys.stderr
52 | )
53 | if y not in p and ll2 < self._epsilon:
54 | # we're done
55 | if self._debug:
56 | print('returning early', file=sys.stderr)
57 | break
58 | adv += self._learning_rate * g
59 | adv = np.clip(adv, 0, 1)
60 | return adv
61 |
62 | def main():
63 | parser = argparse.ArgumentParser()
64 | parser.add_argument('--imagenet-path', type=str, required=True,
65 | help='directory containing `val.txt` and `val/` folder')
66 | parser.add_argument('--defense', type=str, required=True,
67 | help='bitdepth | jpeg | crop | quilt | tv')
68 | parser.add_argument('--start', type=int, default=0)
69 | parser.add_argument('--end', type=int, default=100)
70 | parser.add_argument('--debug', action='store_true')
71 | args = parser.parse_args()
72 |
73 | # set up TensorFlow session
74 | sess = tf.Session()
75 | start = time.time()
76 | # initialize a model
77 | model = InputTransformations(sess, args.defense)
78 | print(model.threat_model.targeted)
79 |
80 | # initialize an attack (it's a white box attack, and it's allowed to look
81 | # at the internals of the model in any way it wants)
82 | # XXX restore
83 | attack = BPDA(sess, model, model.threat_model.epsilon, debug=args.debug)
84 |
85 | # initialize a data provider for ImageNet images
86 | provider = robustml.provider.ImageNet(args.imagenet_path, model.dataset.shape)
87 |
88 | success_rate = robustml.evaluate.evaluate(
89 | model,
90 | attack,
91 | provider,
92 | start=args.start,
93 | end=args.end,
94 | deterministic=True,
95 | debug=args.debug,
96 | )
97 | print('attack time',time.time()-start)
98 |
99 | print('attack success rate: %.2f%% (over %d data points)' % (success_rate*100, args.end-args.start))
100 |
101 | if __name__ == '__main__':
102 | main()
103 |
--------------------------------------------------------------------------------
/inputtransformations/robustml_model.py:
--------------------------------------------------------------------------------
1 | import robustml
2 | from defense import *
3 | from inceptionv3 import model as inceptionv3_model
4 | import tensorflow as tf
5 |
6 | class InputTransformations(robustml.model.Model):
7 | def __init__(self, sess, defense):
8 | self._sess = sess
9 | self._input = tf.placeholder(tf.float32, (None, 299, 299, 3))
10 | #input_expanded = tf.expand_dims(self._input, axis=0)
11 |
12 | if defense == 'crop':
13 | cropped_xs = defend_crop(self._input)
14 | self._logits, _ = inceptionv3_model(sess, cropped_xs)
15 | self._probs = tf.reduce_mean(tf.nn.softmax(self._logits), axis=0, keepdims=True)
16 | else:
17 | self._logits, _ = inceptionv3_model(sess, self._input)
18 | self._probs = tf.nn.softmax(self._logits)
19 |
20 | self._predictions = tf.argmax(self._probs, 1)
21 |
22 | if defense == 'bitdepth':
23 | self._defend = defend_reduce
24 | elif defense == 'jpeg':
25 | self._defend = defend_jpeg
26 | elif defense == 'crop':
27 | self._defend = lambda x: x # implemented as part of model so it's differentiable
28 | elif defense == 'quilt':
29 | self._defend = make_defend_quilt(sess)
30 | elif defense == 'tv':
31 | self._defend = defend_tv
32 | else:
33 | raise ValueError('invalid defense: %s' % defense)
34 |
35 | self._dataset = robustml.dataset.ImageNet((299, 299, 3))
36 | #self._threat_model = robustml.threat_model.L2(epsilon=0.005*(299*299))
37 | self._threat_model = robustml.threat_model.L2(epsilon=0.05*299)
38 |
39 | @property
40 | def dataset(self):
41 | return self._dataset
42 |
43 | @property
44 | def threat_model(self):
45 | return self._threat_model
46 |
47 | def classify(self, x):
48 | x_defended = self.defend(x)
49 | return self._sess.run(self._predictions, {self._input: x_defended})[0]
50 |
51 | def outlogits(self, x):
52 | x_defended = self.defend(x)
53 | return self._sess.run(self._logits, {self._input: x_defended})
54 |
55 | def outlogits_modify(self, x):
56 | x_defended = self.defend(x)
57 | return self._sess.run(self._logits, {self._input: x_defended})
58 |
59 | # expose internals for white box attacks
60 |
61 | def defend(self, x):
62 | return self._defend(x)
63 |
64 | @property
65 | def input(self):
66 | return self._input
67 |
68 | @property
69 | def logits(self):
70 | return self._logits
71 |
72 | @property
73 | def predictions(self):
74 | return self._predictions
75 |
--------------------------------------------------------------------------------
/inputtransformations/robustml_model_origin.py:
--------------------------------------------------------------------------------
1 | import robustml
2 | from defense import *
3 | from inceptionv3 import model as inceptionv3_model
4 | import tensorflow as tf
5 |
6 | class InputTransformations(robustml.model.Model):
7 | def __init__(self, sess, defense):
8 | self._sess = sess
9 | self._input = tf.placeholder(tf.float32, (299, 299, 3))
10 | input_expanded = tf.expand_dims(self._input, axis=0)
11 |
12 | if defense == 'crop':
13 | cropped_xs = defend_crop(self._input)
14 | self._logits, _ = inceptionv3_model(sess, cropped_xs)
15 | self._probs = tf.reduce_mean(tf.nn.softmax(self._logits), axis=0, keepdims=True)
16 | else:
17 | self._logits, _ = inceptionv3_model(sess, input_expanded)
18 | self._probs = tf.nn.softmax(self._logits)
19 |
20 | self._predictions = tf.argmax(self._probs, 1)
21 |
22 | if defense == 'bitdepth':
23 | self._defend = defend_reduce
24 | elif defense == 'jpeg':
25 | self._defend = defend_jpeg
26 | elif defense == 'crop':
27 | self._defend = lambda x: x # implemented as part of model so it's differentiable
28 | elif defense == 'quilt':
29 | self._defend = make_defend_quilt(sess)
30 | elif defense == 'tv':
31 | self._defend = defend_tv
32 | else:
33 | raise ValueError('invalid defense: %s' % defense)
34 |
35 | self._dataset = robustml.dataset.ImageNet((299, 299, 3))
36 | #self._threat_model = robustml.threat_model.L2(epsilon=0.005*(299*299))
37 | self._threat_model = robustml.threat_model.L2(epsilon=2.58942)
38 |
39 | @property
40 | def dataset(self):
41 | return self._dataset
42 |
43 | @property
44 | def threat_model(self):
45 | return self._threat_model
46 |
47 | def classify(self, x):
48 | x_defended = self.defend(x)
49 | return self._sess.run(self._predictions, {self._input: x_defended})[0]
50 |
51 | def outlogits(self, x):
52 | x_defended = self.defend(x)
53 | return self._sess.run(self._logits, {self._input: x_defended})
54 |
55 | # expose internals for white box attacks
56 |
57 | def defend(self, x):
58 | return self._defend(x)
59 |
60 | @property
61 | def input(self):
62 | return self._input
63 |
64 | @property
65 | def logits(self):
66 | return self._logits
67 |
68 | @property
69 | def predictions(self):
70 | return self._predictions
71 |
--------------------------------------------------------------------------------
/inputtransformations/setup.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | cd "$(dirname "$0")" # cd to directory of this script
4 |
5 | # $1 is filename
6 | # $2 is expected sha
7 | check_sha1() {
8 | computed=$(sha1sum "$1" 2>/dev/null | awk '{print $1}') || return 1
9 | if [ "$computed" == "$2" ]; then
10 | return 0;
11 | else
12 | return 1;
13 | fi
14 | }
15 |
16 | # $1 is URL
17 | # $2 is extracted file name
18 | # $3 is the checksum
19 | fetch() {
20 | if check_sha1 $2 $3; then
21 | echo "$2 already downloaded"
22 | return
23 | fi
24 | echo "downloading $1"
25 | f=${1##*/}
26 | wget -q $1 -O $f
27 | tar xf $f
28 | rm -f $f
29 | if check_sha1 $2 $3; then
30 | echo "downloaded $2"
31 | else
32 | echo "HASH MISMATCH, SHA1($2) != $3"
33 | fi
34 | }
35 |
36 | cd data
37 |
38 | fetch \
39 | http://download.tensorflow.org/models/inception_v3_2016_08_28.tar.gz \
40 | inception_v3.ckpt 606fd6953c58c817c56fd3bc2f0384fc2ecaba92
41 |
42 | fetch \
43 | https://github.com/anishathalye/obfuscated-gradients/releases/download/v0/quilt_db.tar.gz \
44 | quilt_db.npy ff4b94f45c9e8441b341fd5ffcf2adb0a8049873
45 |
--------------------------------------------------------------------------------
/inputtransformations/utils.py:
--------------------------------------------------------------------------------
1 | import tensorflow as tf
2 | from tensorflow.python.framework import ops
3 | import numpy as np
4 | import PIL.Image
5 | from imagenet_labels import label_to_name
6 | #import matplotlib.pyplot as plt
7 |
8 | def one_hot(index, total):
9 | arr = np.zeros((total))
10 | arr[index] = 1.0
11 | return arr
12 |
13 | def optimistic_restore(session, save_file):
14 | reader = tf.train.NewCheckpointReader(save_file)
15 | saved_shapes = reader.get_variable_to_shape_map()
16 | var_names = sorted([(var.name, var.name.split(':')[0]) for var in tf.global_variables()
17 | if var.name.split(':')[0] in saved_shapes])
18 | restore_vars = []
19 | with tf.variable_scope('', reuse=True):
20 | for var_name, saved_var_name in var_names:
21 | curr_var = tf.get_variable(saved_var_name)
22 | var_shape = curr_var.get_shape().as_list()
23 | if var_shape == saved_shapes[saved_var_name]:
24 | restore_vars.append(curr_var)
25 | saver = tf.train.Saver(restore_vars)
26 | saver.restore(session, save_file)
27 |
28 | def load_image(path):
29 | return (np.asarray(PIL.Image.open(path).resize((299, 299)))/255.0).astype(np.float32)
30 |
31 | def make_classify(sess, input_, probs):
32 | def classify(img, correct_class=None, target_class=None):
33 | #fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(10, 8))
34 | fig.sca(ax1)
35 | p = sess.run(probs, feed_dict={input_: img})[0]
36 | ax1.imshow(img)
37 | fig.sca(ax1)
38 |
39 | topk = list(p.argsort()[-10:][::-1])
40 | topprobs = p[topk]
41 | barlist = ax2.bar(range(10), topprobs)
42 | if target_class in topk:
43 | barlist[topk.index(target_class)].set_color('r')
44 | if correct_class in topk:
45 | barlist[topk.index(correct_class)].set_color('g')
46 | #plt.sca(ax2)
47 | #plt.ylim([0, 1.1])
48 | #plt.xticks(range(10),
49 | # [label_to_name(i)[:15] for i in topk],
50 | # rotation='vertical')
51 | fig.subplots_adjust(bottom=0.2)
52 | #plt.show()
53 | return classify
54 |
--------------------------------------------------------------------------------
/lid/README.md:
--------------------------------------------------------------------------------
1 | # Characterizing Adversarial Subspaces Using Local Intrinsic Dimensionality
2 |
3 | Paper: [Ma et al. 2018](https://arxiv.org/abs/1801.02613)
4 |
5 | ## Requirements
6 |
7 | * Python3 + tensorflow
8 |
9 | ## [NATTACK] evaluation
10 |
11 | Run with:
12 |
13 | ```bash
14 | python re_li_attack.py --cifar-path
15 | ````
16 |
17 | [robustml]: https://github.com/robust-ml/robustml
18 |
--------------------------------------------------------------------------------
/lid/attack_lid.py:
--------------------------------------------------------------------------------
1 | import tensorflow as tf
2 | import numpy as np
3 | import matplotlib.pyplot as plt
4 | from keras.models import load_model
5 | import pickle
6 | import keras.backend as K
7 | from util import get_model
8 | from extract_artifacts import get_lid
9 | import collections
10 | from detect_adv_samples import detect
11 |
12 | import robustml
13 |
14 |
15 | class Attack:
16 | def __init__(self, model, tol, num_steps, step_size, random_start):
17 | self.model = model
18 | self.tol = tol
19 | self.num_steps = num_steps
20 | self.step_size = step_size
21 | self.rand = random_start
22 |
23 | self.xs = tf.Variable(np.zeros((1000, 32, 32, 3), dtype=np.float32),
24 | name='modifier')
25 | self.orig_xs = tf.placeholder(tf.float32, [None, 32, 32, 3])
26 |
27 | self.ys = tf.placeholder(tf.int32, [None])
28 |
29 | self.epsilon = 8.0/255
30 |
31 | delta = tf.clip_by_value(self.xs, 0, 255) - self.orig_xs
32 | delta = tf.clip_by_value(delta, -self.epsilon, self.epsilon)
33 |
34 | self.do_clip_xs = tf.assign(self.xs, self.orig_xs+delta)
35 |
36 | self.logits = logits = model(self.xs)
37 |
38 | label_mask = tf.one_hot(self.ys, 10)
39 | correct_logit = tf.reduce_sum(label_mask * logits, axis=1)
40 | wrong_logit = tf.reduce_max((1-label_mask) * logits - 1e4*label_mask, axis=1)
41 |
42 | self.loss = (correct_logit - wrong_logit)
43 |
44 | start_vars = set(x.name for x in tf.global_variables())
45 | optimizer = tf.train.AdamOptimizer(step_size*1)
46 |
47 | grad,var = optimizer.compute_gradients(self.loss, [self.xs])[0]
48 | self.train = optimizer.apply_gradients([(tf.sign(grad),var)])
49 |
50 | end_vars = tf.global_variables()
51 | self.new_vars = [x for x in end_vars if x.name not in start_vars]
52 |
53 | def perturb(self, x, y, sess):
54 | sess.run(tf.variables_initializer(self.new_vars))
55 | sess.run(self.xs.initializer)
56 | sess.run(self.do_clip_xs,
57 | {self.orig_xs: x})
58 |
59 | for i in range(self.num_steps):
60 |
61 | sess.run(self.train, feed_dict={self.ys: y})
62 | sess.run(self.do_clip_xs,
63 | {self.orig_xs: x})
64 |
65 | return sess.run(self.xs)
66 |
67 | provider = robustml.provider.CIFAR10("../cifar10_data/test_batch")
68 | model = get_model("cifar", softmax=True)
69 | model.load_weights("data/lid_model_cifar.h5")
70 | model_logits = get_model("cifar", softmax=False)
71 | model_logits.load_weights("data/lid_model_cifar.h5")
72 | sess = K.get_session()
73 | attack = Attack(model_logits,
74 | 1,
75 | 100,
76 | 1/255.0,
77 | False)
78 | xs = tf.placeholder(tf.float32, (1, 32, 32, 3))
79 |
80 | x_input = tf.placeholder(tf.float32, [None, 32, 32, 3])
81 | real_logits = model_logits(x_input)
82 |
83 | succImages = 0
84 | faillist = []
85 | start = 0
86 | end = 1000
87 | totalImages = 0
88 | outpath = 'perturb/lid_'
89 | for i in range(start, end):
90 | outpath_pkl = outpath + str(i) + '.pkl'
91 | success = False
92 | inputs, targets= provider[i]
93 | logits = sess.run(real_logits, feed_dict={x_input: [inputs]})
94 | if np.argmax(logits) != targets:
95 | print('skip the wrong example ', i)
96 | continue
97 | totalImages += 1
98 |
99 | adversarial = attack.perturb([inputs], [targets], sess)
100 |
101 | if np.argmax(sess.run(real_logits, {x_input: adversarial[1:2]})) != targets:
102 | succImages += 1
103 | pickle.dump(adversarial[1:2],open(outpath_pkl,'wb'),-1)
104 | success = True
105 | if not success:
106 | faillist.append(i)
107 | print(faillist)
108 | success_rate = succImages/float(totalImages)
109 | print('succc rate', success_rate)
110 |
111 |
112 |
--------------------------------------------------------------------------------
/lid/evaluation.py:
--------------------------------------------------------------------------------
1 | import robustml
2 | import time
3 | import pickle
4 | from util import get_model
5 | import sys
6 | import argparse
7 | import tensorflow as tf
8 | import numpy as np
9 | from helpers import *
10 | import keras.backend as K
11 | import os
12 | import cv2
13 |
14 | npop = 300 # population size
15 | sigma = 0.1 # noise standard deviation
16 | alpha = 0.008 # learning rate
17 | # alpha = 0.001 # learning rate
18 | boxmin = 0
19 | boxmax = 1
20 | boxplus = (boxmin + boxmax) / 2.
21 | boxmul = (boxmax - boxmin) / 2.
22 | folder = './liclipadvImages/'
23 | epsi = 0.031
24 |
25 |
26 | def softmax(x):
27 | return np.divide(np.exp(x), np.sum(np.exp(x), -1, keepdims=True))
28 |
29 | def main():
30 |
31 | parser = argparse.ArgumentParser()
32 | parser.add_argument('--cifar-path', type=str, default='../cifar10_data/test_batch',
33 | help='path to the test_batch file from http://www.cs.toronto.edu/~kriz/cifar-10-python.tar.gz')
34 | parser.add_argument('--perturb', type=str, default='perturb')
35 | parser.add_argument('--start', type=int, default=0)
36 | parser.add_argument('--end', type=int, default=100)
37 | parser.add_argument('--debug', action='store_true')
38 | args = parser.parse_args()
39 |
40 | test_loss = 0
41 | correct = 0
42 | total = 0
43 | totalImages = 0
44 | succImages = 0
45 | faillist = []
46 |
47 |
48 |
49 | # set up TensorFlow session
50 |
51 | config = tf.ConfigProto()
52 | config.gpu_options.allow_growth = True
53 | sess = tf.Session(config=config)
54 | K.set_session(sess)
55 |
56 |
57 | # initialize a model
58 | model = get_model('cifar', softmax=False)
59 | ### change lid model path llj
60 | model.load_weights("./data/lid_model_cifar.h5")
61 |
62 | # initialize an attack (it's a white box attack, and it's allowed to look
63 | # at the internals of the model in any way it wants)
64 | # attack = BPDA(sess, model, epsilon=model.threat_model.epsilon, debug=args.debug)
65 | # attack = Attack(sess, model.model, epsilon=model.threat_model.epsilon)
66 |
67 | # initialize a data provider for CIFAR-10 images
68 | provider = robustml.provider.CIFAR10(args.cifar_path)
69 | input_xs = tf.placeholder(tf.float32, [None, 32, 32, 3])
70 | start = 0
71 | end = 10000
72 | total = 0
73 | real_logits0 = model(input_xs)
74 | real_logits = tf.nn.softmax(real_logits0)
75 | successlist = []
76 | printlist = []
77 |
78 | start_time = time.time()
79 |
80 | perturb_files = os.listdir(args.perturb)
81 | numbers = []
82 | for x in perturb_files:
83 | number = x.split('_')[1]
84 | name = x.split('_')[0]
85 | number1 = int(number.split('.pkl')[0])
86 | numbers.append(number1)
87 |
88 | for i in numbers:
89 | success = False
90 | print('evaluating %d of [%d, %d)' % (i, start, end), file=sys.stderr)
91 | inputs, targets= provider[i]
92 | modify = np.random.randn(1,3,32,32) * 0.001
93 | in_pkl = name + '_' + str(i)+'.pkl'
94 | ##### thermometer encoding
95 |
96 | logits = sess.run(real_logits,feed_dict={input_xs: [inputs]})
97 | if np.argmax(logits) != targets:
98 | print('skip the wrong example ', i)
99 | continue
100 | totalImages += 1
101 | modify = pickle.load(open(in_pkl, 'rb'))
102 | if 'cascade' in in_pkl:
103 | modify = cv2.resize(modify.transpose(1,2,0), dsize=(32,32), interpolation=cv2.INTER_LINEAR)
104 | modify = modify.transpose(2, 0, 1)
105 | newimg = torch_arctanh((inputs - boxplus) / boxmul).transpose(2, 0, 1)
106 | realinputimg = np.tanh(newimg + modify) * boxmul + boxplus
107 | realdist = realinputimg - (np.tanh(newimg) * boxmul + boxplus)
108 | realclipdist = np.clip(realdist, -epsi, epsi)
109 | realclipinput = realclipdist + (np.tanh(newimg) * boxmul + boxplus)
110 | l2real = np.sum((realclipinput - (np.tanh(newimg) * boxmul + boxplus)) ** 2) ** 0.5
111 | outputsreal = sess.run(real_logits, feed_dict={input_xs: realclipinput.transpose(0, 2, 3, 1)})
112 | if (np.argmax(outputsreal) != targets) and (np.abs(realclipdist).max() <= epsi):
113 | succImages += 1
114 |
115 | success_rate = succImages / float(totalImages)
116 | print('succ rate', success_rate)
117 | print('succ {} , total {}'.format(succImages, totalImages))
118 |
119 |
120 | if __name__ == '__main__':
121 | main()
122 |
--------------------------------------------------------------------------------
/lid/evaluation_bpda.py:
--------------------------------------------------------------------------------
1 | import robustml
2 | import time
3 | import pickle
4 | from util import get_model
5 | import sys
6 | import argparse
7 | import tensorflow as tf
8 | import numpy as np
9 | from helpers import *
10 | import keras.backend as K
11 | import os
12 | import cv2
13 |
14 | npop = 300 # population size
15 | sigma = 0.1 # noise standard deviation
16 | alpha = 0.008 # learning rate
17 | # alpha = 0.001 # learning rate
18 | boxmin = 0
19 | boxmax = 1
20 | boxplus = (boxmin + boxmax) / 2.
21 | boxmul = (boxmax - boxmin) / 2.
22 | folder = './liclipadvImages/'
23 | epsi = 0.032
24 |
25 |
26 | def softmax(x):
27 | return np.divide(np.exp(x), np.sum(np.exp(x), -1, keepdims=True))
28 |
29 | def main():
30 |
31 | parser = argparse.ArgumentParser()
32 | parser.add_argument('--cifar-path', type=str, default='../cifar10_data/test_batch',
33 | help='path to the test_batch file from http://www.cs.toronto.edu/~kriz/cifar-10-python.tar.gz')
34 | parser.add_argument('--perturb', type=str, default='perturb')
35 | parser.add_argument('--start', type=int, default=0)
36 | parser.add_argument('--end', type=int, default=100)
37 | parser.add_argument('--debug', action='store_true')
38 | args = parser.parse_args()
39 |
40 | test_loss = 0
41 | correct = 0
42 | total = 0
43 | totalImages = 0
44 | succImages = 0
45 | faillist = []
46 |
47 |
48 |
49 | # set up TensorFlow session
50 |
51 | config = tf.ConfigProto()
52 | config.gpu_options.allow_growth = True
53 | sess = tf.Session(config=config)
54 | K.set_session(sess)
55 |
56 |
57 | # initialize a model
58 | model = get_model('cifar', softmax=False)
59 | ### change lid model path llj
60 | model.load_weights("./data/lid_model_cifar.h5")
61 |
62 | # initialize an attack (it's a white box attack, and it's allowed to look
63 | # at the internals of the model in any way it wants)
64 | # attack = BPDA(sess, model, epsilon=model.threat_model.epsilon, debug=args.debug)
65 | # attack = Attack(sess, model.model, epsilon=model.threat_model.epsilon)
66 |
67 | # initialize a data provider for CIFAR-10 images
68 | provider = robustml.provider.CIFAR10(args.cifar_path)
69 | input_xs = tf.placeholder(tf.float32, [None, 32, 32, 3])
70 | start = 0
71 | end = 10000
72 | total = 0
73 | real_logits0 = model(input_xs)
74 | real_logits = tf.nn.softmax(real_logits0)
75 | successlist = []
76 | printlist = []
77 |
78 | start_time = time.time()
79 |
80 | perturb_files = os.listdir(args.perturb)
81 | numbers = []
82 | for x in perturb_files:
83 | number = x.split('_')[-1]
84 | name = x.split('_')[0]
85 | number1 = int(number.split('.pkl')[0])
86 | numbers.append(number1)
87 |
88 | for i in numbers:
89 | success = False
90 | print('evaluating %d of [%d, %d)' % (i, start, end), file=sys.stderr)
91 | inputs, targets= provider[i]
92 | modify = np.random.randn(1,3,32,32) * 0.001
93 | in_pkl = args.perturb+ name + '_' + str(i)+'.pkl'
94 | ##### thermometer encoding
95 |
96 | logits = sess.run(real_logits,feed_dict={input_xs: [inputs]})
97 | if np.argmax(logits) != targets:
98 | print('skip the wrong example ', i)
99 | continue
100 | totalImages += 1
101 | modify = pickle.load(open(in_pkl, 'rb'))
102 | if 'cascade' in in_pkl:
103 | modify = cv2.resize(modify.transpose(1,2,0), dsize=(32,32), interpolation=cv2.INTER_LINEAR)
104 | modify = modify.transpose(2, 0, 1)
105 | print(modify.shape)
106 | realclipinput = modify.reshape(1,32,32,3)+0.5
107 | realclipdist = realclipinput - inputs
108 | # print(np.abs(realclipdist).max())
109 | outputsreal = sess.run(real_logits, feed_dict={input_xs: realclipinput})
110 | print(np.abs(realclipdist).max())
111 |
112 | if (np.argmax(outputsreal) != targets) and (np.abs(realclipdist).max() <= epsi):
113 | succImages += 1
114 |
115 | success_rate = succImages / float(totalImages)
116 | print('succ rate', success_rate)
117 | print('succ {} , total {}'.format(succImages, totalImages))
118 |
119 |
120 | if __name__ == '__main__':
121 | main()
122 |
--------------------------------------------------------------------------------
/lid/helpers.py:
--------------------------------------------------------------------------------
1 | import operator as op
2 | import functools as ft
3 | import numpy as np
4 |
5 |
6 | '''reduce_* helper functions reduce tensors on all dimensions but the first.
7 | They are intended to be used on batched tensors where dim 0 is the batch dim.
8 | '''
9 |
10 |
11 | def reduce_sum(x, keepdim=True):
12 | # silly PyTorch, when will you get proper reducing sums/means?
13 | for a in reversed(range(1, x.dim())):
14 | x = x.sum(a, keepdim=keepdim)
15 | return x
16 |
17 |
18 | def reduce_mean(x, keepdim=True):
19 | numel = ft.reduce(op.mul, x.size()[1:])
20 | x = reduce_sum(x, keepdim=keepdim)
21 | return x / numel
22 |
23 |
24 | def reduce_min(x, keepdim=True):
25 | for a in reversed(range(1, x.dim())):
26 | x = x.min(a, keepdim=keepdim)[0]
27 | return x
28 |
29 |
30 | def reduce_max(x, keepdim=True):
31 | for a in reversed(range(1, x.dim())):
32 | x = x.max(a, keepdim=keepdim)[0]
33 | return x
34 |
35 |
36 | def torch_arctanh(x, eps=1e-6):
37 | x *= (1. - eps)
38 | return (np.log((1 + x) / (1 - x))) * 0.5
39 |
40 |
41 | def l2r_dist(x, y, keepdim=True, eps=1e-8):
42 | d = (x - y)**2
43 | d = reduce_sum(d, keepdim=keepdim)
44 | d += eps # to prevent infinite gradient at 0
45 | return d.sqrt()
46 |
47 |
48 | def l2_dist(x, y, keepdim=True):
49 | d = (x - y)**2
50 | return reduce_sum(d, keepdim=keepdim)
51 |
52 |
53 | def l1_dist(x, y, keepdim=True):
54 | d = torch.abs(x - y)
55 | return reduce_sum(d, keepdim=keepdim)
56 |
57 |
58 | def l2_norm(x, keepdim=True):
59 | norm = reduce_sum(x*x, keepdim=keepdim)
60 | return norm.sqrt()
61 |
62 |
63 | def l1_norm(x, keepdim=True):
64 | return reduce_sum(x.abs(), keepdim=keepdim)
65 |
66 |
67 | def rescale(x, x_min=-1., x_max=1.):
68 | return x * (x_max - x_min) + x_min
69 |
70 |
71 | def tanh_rescale(x, x_min=-1., x_max=1.):
72 | return (torch.tanh(x) + 1) * 0.5 * (x_max - x_min) + x_min
73 |
--------------------------------------------------------------------------------
/pixel-deflection/README.md:
--------------------------------------------------------------------------------
1 | # Deflecting Adversarial Attacks with Pixel Deflection
2 |
3 | 
4 |
5 | Code for paper: https://arxiv.org/abs/1801.08926
6 |
7 | Blog with demo: https://iamaaditya.github.io/2018/02/demo-for-pixel-deflection/
8 |
9 | Requirements:
10 |
11 | 1. Keras 2.0+
12 | (only used for classification - Pixel Deflection itself is deep learning platform independent)
13 |
14 | 2. Scipy 1.0+
15 |
16 | (Older version of scipy wavelet transform does not have BayesShrink)
17 |
18 | * Python3 + tensorflow
19 |
20 | ## [NATTACK] evaluation
21 |
22 | Run with:
23 |
24 | ```bash
25 | python re_li_attack.py --imagenet-path
26 | ````
27 |
--------------------------------------------------------------------------------
/pixel-deflection/helpers.py:
--------------------------------------------------------------------------------
1 | import operator as op
2 | import functools as ft
3 | import numpy as np
4 |
5 |
6 | '''reduce_* helper functions reduce tensors on all dimensions but the first.
7 | They are intended to be used on batched tensors where dim 0 is the batch dim.
8 | '''
9 |
10 |
11 | def reduce_sum(x, keepdim=True):
12 | # silly PyTorch, when will you get proper reducing sums/means?
13 | for a in reversed(range(1, x.dim())):
14 | x = x.sum(a, keepdim=keepdim)
15 | return x
16 |
17 |
18 | def reduce_mean(x, keepdim=True):
19 | numel = ft.reduce(op.mul, x.size()[1:])
20 | x = reduce_sum(x, keepdim=keepdim)
21 | return x / numel
22 |
23 |
24 | def reduce_min(x, keepdim=True):
25 | for a in reversed(range(1, x.dim())):
26 | x = x.min(a, keepdim=keepdim)[0]
27 | return x
28 |
29 |
30 | def reduce_max(x, keepdim=True):
31 | for a in reversed(range(1, x.dim())):
32 | x = x.max(a, keepdim=keepdim)[0]
33 | return x
34 |
35 |
36 | def torch_arctanh(x, eps=1e-6):
37 | x *= (1. - eps)
38 | return (np.log((1 + x) / (1 - x))) * 0.5
39 |
40 |
41 | def l2r_dist(x, y, keepdim=True, eps=1e-8):
42 | d = (x - y)**2
43 | d = reduce_sum(d, keepdim=keepdim)
44 | d += eps # to prevent infinite gradient at 0
45 | return d.sqrt()
46 |
47 |
48 | def l2_dist(x, y, keepdim=True):
49 | d = (x - y)**2
50 | return reduce_sum(d, keepdim=keepdim)
51 |
52 |
53 | def l1_dist(x, y, keepdim=True):
54 | d = torch.abs(x - y)
55 | return reduce_sum(d, keepdim=keepdim)
56 |
57 |
58 | def l2_norm(x, keepdim=True):
59 | norm = reduce_sum(x*x, keepdim=keepdim)
60 | return norm.sqrt()
61 |
62 |
63 | def l1_norm(x, keepdim=True):
64 | return reduce_sum(x.abs(), keepdim=keepdim)
65 |
66 |
67 | def rescale(x, x_min=-1., x_max=1.):
68 | return x * (x_max - x_min) + x_min
69 |
70 |
71 | def tanh_rescale(x, x_min=-1., x_max=1.):
72 | return (torch.tanh(x) + 1) * 0.5 * (x_max - x_min) + x_min
73 |
--------------------------------------------------------------------------------
/pixel-deflection/images/n02443114_00000055.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Cold-Winter/Nattack/2c5ce052f0298d52a2972dfce8bbfd9fed6a6fcb/pixel-deflection/images/n02443114_00000055.png
--------------------------------------------------------------------------------
/pixel-deflection/images/n02443114_00032317.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Cold-Winter/Nattack/2c5ce052f0298d52a2972dfce8bbfd9fed6a6fcb/pixel-deflection/images/n02443114_00032317.png
--------------------------------------------------------------------------------
/pixel-deflection/images/n02447366_00008562.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Cold-Winter/Nattack/2c5ce052f0298d52a2972dfce8bbfd9fed6a6fcb/pixel-deflection/images/n02447366_00008562.png
--------------------------------------------------------------------------------
/pixel-deflection/main.py:
--------------------------------------------------------------------------------
1 | from __future__ import division
2 | import os, sys, argparse, multiprocessing
3 | from joblib import Parallel, delayed
4 | from glob import glob
5 | import numpy as np
6 | from utils import *
7 | from methods import pixel_deflection, denoiser
8 | os.environ['TF_CPP_MIN_LOG_LEVEL'] = '3' # silences the TF INFO messages
9 |
10 | def get_arguments():
11 | parser = argparse.ArgumentParser()
12 | parser.add_argument('-image' , type=str , default= 'images/n02447366_00008562.png')
13 | parser.add_argument('-map' , type=str , default= 'maps/n02447366_00008562.png')
14 | parser.add_argument('-directory' , type=str , default= './images/')
15 | parser.add_argument('-disable_map' , action='store_true')
16 | parser.add_argument('-process_batch' , action='store_true')
17 | parser.add_argument('-classifier' , type=str , default= 'resnet50', help='options: resnet50, inception_v3, vgg19, xception')
18 | parser.add_argument('-denoiser' , type=str , default= 'wavelet', help='options: wavelet, TVM, bilateral, deconv, NLM')
19 | parser.add_argument('-batch_size' , type=int, default= 64)
20 | parser.add_argument('-sigma' , type=float, default= 0.04)
21 | parser.add_argument('-window' , type=int, default= 10)
22 | parser.add_argument('-deflections' , type=int, default= 200)
23 | return parser.parse_args()
24 |
25 | def classify_images(images, class_names, supress_print=False):
26 | total, top1, top5 = 0,0,0
27 | images = preprocess_input(np.stack(images,axis=0))
28 | predictions = decode_predictions(model.predict(images),top=5)
29 | for p,true_class in zip(predictions,class_names):
30 | ans= [' {0}:{1:.2f} '.format(i[1],i[2]) for i in p]
31 | if not supress_print: print('Predicted Class {}'.format(','.join(ans)))
32 | total += 1
33 | r = [i[0] for i in p]
34 | top1 += int(true_class == r[0])
35 | top5 += int(true_class in r)
36 | return top1*100.0/total, top5*100.0/total
37 |
38 | def process_image(args, image_name, defend=True):
39 | image = get_img(image_name)
40 | # assumes map is same name as image but inside maps directory
41 | if not args.disable_map:
42 | map = get_map('./maps/'+image_name.split('/')[-1])
43 | else:
44 | map = np.zeros((image.shape[0],image.shape[1]))
45 |
46 | if defend:
47 | img = pixel_deflection(image, map, args.deflections, args.window, args.sigma)
48 | return denoiser(args.denoiser, img/255.0, args.sigma)*255.0
49 | else:
50 | return image
51 |
52 | def process_image_parallel(args):
53 | num_cores = multiprocessing.cpu_count()
54 | scores = []
55 | for image_names in batches(glob(args.directory+'/*'), args.batch_size):
56 | images = Parallel(n_jobs=num_cores)(delayed(process_image)(args, image_name) for image_name in image_names)
57 | class_names = [image_name.split('/')[-1].split('_')[0] for image_name in image_names]
58 | scores.append(classify_images(images, class_names, supress_print=True))
59 |
60 | t1,t5 = sum([i[0] for i in scores])/len(scores), sum([i[1] for i in scores])/len(scores)
61 | print('After recovery Top 1 accuracy is {0:.2f} and Top 5 accuracy is {1:.2f}'.format(t1,t5))
62 |
63 | if __name__ == '__main__':
64 | args = get_arguments()
65 | if args.classifier == 'resnet50':
66 | from keras.applications.resnet50 import ResNet50, preprocess_input, decode_predictions
67 | model = ResNet50(weights='imagenet')
68 | elif args.classifier == 'inception_v3':
69 | from keras.applications.inception_v3 import InceptionV3, preprocess_input, decode_predictions
70 | model = InceptionV3(weights='imagenet')
71 | elif args.classifier == 'vgg19':
72 | from keras.applications.vgg19 import VGG19, preprocess_input, decode_predictions
73 | model = VGG19(weights='imagenet')
74 | elif args.classifier == 'xception':
75 | from keras.applications.xception import Xception, preprocess_input, decode_predictions
76 | model = Xception(weights='imagenet')
77 | else:
78 | raise Exception('Incorrect classifier mentioned. Options: resnet50, inception_v3, vgg19, xception')
79 |
80 | imagenet_labels = get_imagenet_labels()
81 | if args.process_batch:
82 | images = process_image_parallel(args)
83 | else:
84 | class_name = args.image.split('/')[-1].split('_')[0]
85 | print("Image: {}, True Class: '{}'".format(args.image, imagenet_labels[class_name]))
86 | print('Before Defense :')
87 | image = process_image(args, args.image, defend=False)
88 | classify_images([image], [class_name])
89 | print('After Defense :')
90 | image = process_image(args, args.image, defend=True)
91 | classify_images([image], [class_name])
92 |
--------------------------------------------------------------------------------
/pixel-deflection/maps/n02443114_00000055.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Cold-Winter/Nattack/2c5ce052f0298d52a2972dfce8bbfd9fed6a6fcb/pixel-deflection/maps/n02443114_00000055.png
--------------------------------------------------------------------------------
/pixel-deflection/maps/n02443114_00032317.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Cold-Winter/Nattack/2c5ce052f0298d52a2972dfce8bbfd9fed6a6fcb/pixel-deflection/maps/n02443114_00032317.png
--------------------------------------------------------------------------------
/pixel-deflection/maps/n02447366_00008562.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Cold-Winter/Nattack/2c5ce052f0298d52a2972dfce8bbfd9fed6a6fcb/pixel-deflection/maps/n02447366_00008562.png
--------------------------------------------------------------------------------
/pixel-deflection/methods.py:
--------------------------------------------------------------------------------
1 | from __future__ import division
2 | from random import randint, uniform
3 | import os, sys, argparse, matplotlib, multiprocessing
4 | matplotlib.use('Agg')
5 | from keras.preprocessing import image
6 | from scipy.misc import imread
7 | #from joblib import Parallel, delayed
8 | from glob import glob
9 | import numpy as np
10 | os.environ['TF_CPP_MIN_LOG_LEVEL'] = '3'
11 | norm = matplotlib.colors.Normalize()
12 |
13 |
14 | def denoiser(denoiser_name, img,sigma):
15 | from skimage.restoration import (denoise_tv_chambolle, denoise_bilateral, denoise_wavelet, denoise_nl_means, wiener)
16 | if denoiser_name == 'wavelet':
17 | return denoise_wavelet(img,sigma=sigma, mode='soft', multichannel=True,convert2ycbcr=True)#, method='BayesShrink')
18 | elif denoiser_name == 'TVM':
19 | return denoise_tv_chambolle(img, multichannel=True)
20 | elif denoiser_name == 'bilateral':
21 | return denoise_bilateral(img, bins=1000, multichannel=True)
22 | elif denoiser_name == 'deconv':
23 | return wiener(img)
24 | elif denoiser_name == 'NLM':
25 | return denoise_nl_means(img, multichannel=True)
26 | else:
27 | raise Exception('Incorrect denoiser mentioned. Options: wavelet, TVM, bilateral, deconv, NLM')
28 |
29 | def pixel_deflection(img, rcam_prob, deflections, window, sigma):
30 | H, W, C = img.shape
31 | while deflections > 0:
32 | for c in range(C):
33 | x,y = randint(0,H-1), randint(0,W-1)
34 |
35 | if uniform(0,1) < rcam_prob[x,y]:
36 | continue
37 |
38 | while True: #this is to ensure that PD pixel lies inside the image
39 | a,b = randint(-1*window,window), randint(-1*window,window)
40 | if x+a < H and x+a > 0 and y+b < W and y+b > 0: break
41 | img[x,y,c] = img[x+a,y+b,c]
42 | deflections -= 1
43 | return img
44 |
--------------------------------------------------------------------------------
/pixel-deflection/originals/n02443114_00000055.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Cold-Winter/Nattack/2c5ce052f0298d52a2972dfce8bbfd9fed6a6fcb/pixel-deflection/originals/n02443114_00000055.png
--------------------------------------------------------------------------------
/pixel-deflection/originals/n02443114_00032317.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Cold-Winter/Nattack/2c5ce052f0298d52a2972dfce8bbfd9fed6a6fcb/pixel-deflection/originals/n02443114_00032317.png
--------------------------------------------------------------------------------
/pixel-deflection/originals/n02447366_00008562.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Cold-Winter/Nattack/2c5ce052f0298d52a2972dfce8bbfd9fed6a6fcb/pixel-deflection/originals/n02447366_00008562.png
--------------------------------------------------------------------------------
/pixel-deflection/utils.py:
--------------------------------------------------------------------------------
1 | import matplotlib
2 | import numpy as np
3 | from keras.preprocessing import image
4 | from scipy.misc import imread
5 | import json
6 |
7 | def batches(array, batch_size):
8 | return (array[i:i + batch_size] for i in range(0, len(array), batch_size))
9 |
10 | def rgb2ycc(im):
11 | xform = np.array([[.299, .587, .114], [-.1687, -.3313, .5], [.5, -.4187, -.0813]])
12 | ycbcr = im.dot(xform.T)
13 | ycbcr[:,:,[1,2]] += 128
14 | return ycbcr
15 |
16 | def ycc2rgb(im):
17 | xform = np.array([[1, 0, 1.402], [1, -0.34414, -.71414], [1, 1.772, 0]])
18 | rgb = im.astype(np.float)
19 | rgb[:,:,[1,2]] -= 128
20 | return rgb.dot(xform.T)
21 |
22 |
23 | def get_img(file):
24 | img = image.load_img(file, target_size=(224, 224))
25 | return image.img_to_array(img)
26 |
27 | def get_map(file):
28 | norm = matplotlib.colors.Normalize()
29 | return norm(imread(file))
30 |
31 | def get_imagenet_labels():
32 | imagenet = json.load(open('./imagenet_labels.json'))
33 | return {i[0]:i[1] for i in imagenet.values()}
34 |
35 |
--------------------------------------------------------------------------------
/randomization/.gitignore:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Cold-Winter/Nattack/2c5ce052f0298d52a2972dfce8bbfd9fed6a6fcb/randomization/.gitignore
--------------------------------------------------------------------------------
/randomization/README.md:
--------------------------------------------------------------------------------
1 | # Mitigating Adversarial Effects Through Randomization
2 |
3 | Paper: [Xie et al. 2018](https://arxiv.org/abs/1711.01991)
4 |
5 | ## Requirements
6 |
7 | * Python3 + tensorflow
8 |
9 |
10 | ## [robustml] evaluation
11 |
12 | Run with:
13 |
14 | ```bash
15 | python re_li_attack32_tfmultigpu.py --imagenet-path
16 | ````
17 |
18 | [robustml]: https://github.com/robust-ml/robustml
19 |
--------------------------------------------------------------------------------
/randomization/defense.py:
--------------------------------------------------------------------------------
1 | import tensorflow as tf
2 |
3 | # implements defense described in https://openreview.net/forum?id=Sk9yuql0Z
4 | #
5 | # except they don't mention what value they pad with, so we assume it's 0.5
6 | PAD_VALUE = 0.5
7 |
8 | # input_tensor should be of shape [1, 299, 299, 3]
9 | # output is of shape [1, 331, 331, 3]
10 | def defend(input_tensor):
11 | rnd = tf.random_uniform((), 299, 331, dtype=tf.int32)
12 | rescaled = tf.image.crop_and_resize(input_tensor, [[0, 0, 1, 1]], [0], [rnd, rnd])
13 | h_rem = 331 - rnd
14 | w_rem = 331 - rnd
15 | pad_left = tf.random_uniform((), 0, w_rem, dtype=tf.int32)
16 | pad_right = w_rem - pad_left
17 | pad_top = tf.random_uniform((), 0, h_rem, dtype=tf.int32)
18 | pad_bottom = h_rem - pad_top
19 | padded = tf.pad(rescaled, [[0, 0], [pad_top, pad_bottom], [pad_left, pad_right], [0, 0]], constant_values=PAD_VALUE)
20 | padded.set_shape((1, 331, 331, 3))
21 | return padded
22 |
--------------------------------------------------------------------------------
/randomization/defense_batch.py:
--------------------------------------------------------------------------------
1 | import tensorflow as tf
2 |
3 | # implements defense described in https://openreview.net/forum?id=Sk9yuql0Z
4 | #
5 | # except they don't mention what value they pad with, so we assume it's 0.5
6 | PAD_VALUE = 0.5
7 |
8 | # input_tensor should be of shape [300, 299, 299, 3]
9 | # output is of shape [300, 331, 331, 3]
10 | def defend_batch(input_tensor):
11 | rnd = tf.random_uniform([tf.to_int32(input_tensor.shape[0]),1], 299, 331, dtype=tf.int32)
12 | tensor = tf.tile([[0,0,1,1]],[tf.to_int32(input_tensor.shape[0]),1])
13 | rescaled = tf.image.crop_and_resize(input_tensor, tf.to_float(tensor), tf.range(input_tensor.shape[0]), [rnd, rnd])
14 | h_rem = 331 - rnd
15 | w_rem = 331 - rnd
16 | pad_left = tf.random_uniform([tf.to_int32(input_tensor.shape[0]),1], 0, w_rem, dtype=tf.int32)
17 | pad_right = w_rem - pad_left
18 | pad_top = tf.random_uniform([tf.to_int32(input_tensor.shape[0]),1], 0, h_rem, dtype=tf.int32)
19 | pad_bottom = h_rem - pad_top
20 | padded = tf.pad(rescaled, [[0, 0], [pad_top, pad_bottom], [pad_left, pad_right], [0, 0]], constant_values=PAD_VALUE)
21 | padded.set_shape((tf.to_int32(input_tensor.shape[0]), 331, 331, 3))
22 | return padded
--------------------------------------------------------------------------------
/randomization/helpers.py:
--------------------------------------------------------------------------------
1 | import operator as op
2 | import functools as ft
3 | import numpy as np
4 |
5 |
6 | '''reduce_* helper functions reduce tensors on all dimensions but the first.
7 | They are intended to be used on batched tensors where dim 0 is the batch dim.
8 | '''
9 |
10 |
11 | def reduce_sum(x, keepdim=True):
12 | # silly PyTorch, when will you get proper reducing sums/means?
13 | for a in reversed(range(1, x.dim())):
14 | x = x.sum(a, keepdim=keepdim)
15 | return x
16 |
17 |
18 | def reduce_mean(x, keepdim=True):
19 | numel = ft.reduce(op.mul, x.size()[1:])
20 | x = reduce_sum(x, keepdim=keepdim)
21 | return x / numel
22 |
23 |
24 | def reduce_min(x, keepdim=True):
25 | for a in reversed(range(1, x.dim())):
26 | x = x.min(a, keepdim=keepdim)[0]
27 | return x
28 |
29 |
30 | def reduce_max(x, keepdim=True):
31 | for a in reversed(range(1, x.dim())):
32 | x = x.max(a, keepdim=keepdim)[0]
33 | return x
34 |
35 |
36 | def torch_arctanh(x, eps=1e-6):
37 | x *= (1. - eps)
38 | return (np.log((1 + x) / (1 - x))) * 0.5
39 |
40 |
41 | def l2r_dist(x, y, keepdim=True, eps=1e-8):
42 | d = (x - y)**2
43 | d = reduce_sum(d, keepdim=keepdim)
44 | d += eps # to prevent infinite gradient at 0
45 | return d.sqrt()
46 |
47 |
48 | def l2_dist(x, y, keepdim=True):
49 | d = (x - y)**2
50 | return reduce_sum(d, keepdim=keepdim)
51 |
52 |
53 | def l1_dist(x, y, keepdim=True):
54 | d = torch.abs(x - y)
55 | return reduce_sum(d, keepdim=keepdim)
56 |
57 |
58 | def l2_norm(x, keepdim=True):
59 | norm = reduce_sum(x*x, keepdim=keepdim)
60 | return norm.sqrt()
61 |
62 |
63 | def l1_norm(x, keepdim=True):
64 | return reduce_sum(x.abs(), keepdim=keepdim)
65 |
66 |
67 | def rescale(x, x_min=-1., x_max=1.):
68 | return x * (x_max - x_min) + x_min
69 |
70 |
71 | def tanh_rescale(x, x_min=-1., x_max=1.):
72 | return (torch.tanh(x) + 1) * 0.5 * (x_max - x_min) + x_min
73 |
--------------------------------------------------------------------------------
/randomization/inceptionv3.py:
--------------------------------------------------------------------------------
1 | from utils import optimistic_restore
2 | import tensorflow as tf
3 | import tensorflow.contrib.slim as slim
4 | import tensorflow.contrib.slim.nets as nets
5 | import functools
6 | import os
7 |
8 | _INCEPTION_CHECKPOINT_NAME = '../all_models/random/inception_v3.ckpt'
9 | # INCEPTION_CHECKPOINT_PATH = os.path.join(
10 | # os.path.dirname(__file__),
11 | # 'data',
12 | # _INCEPTION_CHECKPOINT_NAME
13 | # )
14 | INCEPTION_CHECKPOINT_PATH = '../all_models/random/inception_v3.ckpt'
15 |
16 | def _get_model(reuse):
17 | arg_scope = nets.inception.inception_v3_arg_scope(weight_decay=0.0)
18 | func = nets.inception.inception_v3
19 | @functools.wraps(func)
20 | def network_fn(images):
21 | with slim.arg_scope(arg_scope):
22 | return func(images, 1001, is_training=False, reuse=reuse)
23 | if hasattr(func, 'default_image_size'):
24 | network_fn.default_image_size = func.default_image_size
25 | return network_fn
26 |
27 | def _preprocess(image, height, width, scope=None):
28 | with tf.name_scope(scope, 'eval_image', [image, height, width]):
29 | if image.dtype != tf.float32:
30 | image = tf.image.convert_image_dtype(image, dtype=tf.float32)
31 | image = tf.image.resize_bilinear(image, [height, width], align_corners=False)
32 | image = tf.subtract(image, 0.5)
33 | image = tf.multiply(image, 2.0)
34 | return image
35 |
36 | # input is [batch, ?, ?, 3], pixels in [0, 1]
37 | # it's rescaled to [batch, 299, 299, 3] and shifted to [-1, 1]
38 | # output is [batch, 1000] (imagenet classes)
39 | _inception_initialized = False
40 | def model(sess, image):
41 | global _inception_initialized
42 | network_fn = _get_model(reuse=_inception_initialized)
43 | size = network_fn.default_image_size
44 | preprocessed = _preprocess(image, size, size)
45 | logits, _ = network_fn(preprocessed)
46 | logits = logits[:,1:] # ignore background class
47 | predictions = tf.argmax(logits, 1)
48 |
49 | if not _inception_initialized:
50 | optimistic_restore(sess, INCEPTION_CHECKPOINT_PATH)
51 | _inception_initialized = True
52 |
53 | return logits, predictions
54 |
--------------------------------------------------------------------------------
/randomization/nohup.out:
--------------------------------------------------------------------------------
1 | 2018-09-20 23:54:29.729038: I tensorflow/core/platform/cpu_feature_guard.cc:137] Your CPU supports instructions that this TensorFlow binary was not compiled to use: SSE4.1 SSE4.2 AVX AVX2 AVX512F FMA
2 | 2018-09-20 23:54:33.178383: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1030] Found device 0 with properties:
3 | name: Graphics Device major: 6 minor: 1 memoryClockRate(GHz): 1.582
4 | pciBusID: 0000:18:00.0
5 | totalMemory: 11.90GiB freeMemory: 11.75GiB
6 | 2018-09-20 23:54:33.780051: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1030] Found device 1 with properties:
7 | name: Graphics Device major: 6 minor: 1 memoryClockRate(GHz): 1.582
8 | pciBusID: 0000:3b:00.0
9 | totalMemory: 11.90GiB freeMemory: 11.75GiB
10 | 2018-09-20 23:54:34.279893: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1030] Found device 2 with properties:
11 | name: Graphics Device major: 6 minor: 1 memoryClockRate(GHz): 1.582
12 | pciBusID: 0000:86:00.0
13 | totalMemory: 11.90GiB freeMemory: 11.75GiB
14 | 2018-09-20 23:54:34.766308: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1030] Found device 3 with properties:
15 | name: Graphics Device major: 6 minor: 1 memoryClockRate(GHz): 1.582
16 | pciBusID: 0000:af:00.0
17 | totalMemory: 11.90GiB freeMemory: 11.75GiB
18 | 2018-09-20 23:54:34.766743: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1045] Device peer to peer matrix
19 | 2018-09-20 23:54:34.766826: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1051] DMA: 0 1 2 3
20 | 2018-09-20 23:54:34.766842: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1061] 0: Y N N N
21 | 2018-09-20 23:54:34.766849: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1061] 1: N Y N N
22 | 2018-09-20 23:54:34.766856: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1061] 2: N N Y N
23 | 2018-09-20 23:54:34.766863: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1061] 3: N N N Y
24 | 2018-09-20 23:54:34.766876: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1120] Creating TensorFlow device (/device:GPU:0) -> (device: 0, name: Graphics Device, pci bus id: 0000:18:00.0, compute capability: 6.1)
25 | 2018-09-20 23:54:34.766886: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1120] Creating TensorFlow device (/device:GPU:1) -> (device: 1, name: Graphics Device, pci bus id: 0000:3b:00.0, compute capability: 6.1)
26 | 2018-09-20 23:54:34.766894: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1120] Creating TensorFlow device (/device:GPU:2) -> (device: 2, name: Graphics Device, pci bus id: 0000:86:00.0, compute capability: 6.1)
27 | 2018-09-20 23:54:34.766901: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1120] Creating TensorFlow device (/device:GPU:3) -> (device: 3, name: Graphics Device, pci bus id: 0000:af:00.0, compute capability: 6.1)
28 | /home/yandong/anaconda3/lib/python3.6/importlib/_bootstrap.py:219: RuntimeWarning: compiletime version 3.5 of module 'tensorflow.python.framework.fast_tensor_util' does not match runtime version 3.6
29 | return f(*args, **kwds)
30 | /home/yandong/anaconda3/lib/python3.6/site-packages/h5py/__init__.py:36: FutureWarning: Conversion of the second argument of issubdtype from `float` to `np.floating` is deprecated. In future, it will be treated as `np.float64 == np.dtype(float).type`.
31 | from ._conv import register_converters as _register_converters
32 | Traceback (most recent call last):
33 | File "re_li_attack32_tfmultigpu.py", line 194, in
34 | main()
35 | File "re_li_attack32_tfmultigpu.py", line 48, in main
36 | sess = tf.Session(config=config)
37 | File "/home/yandong/anaconda3/lib/python3.6/site-packages/tensorflow/python/client/session.py", line 1482, in __init__
38 | super(Session, self).__init__(target, graph, config=config)
39 | File "/home/yandong/anaconda3/lib/python3.6/site-packages/tensorflow/python/client/session.py", line 622, in __init__
40 | self._session = tf_session.TF_NewDeprecatedSession(opts, status)
41 | KeyboardInterrupt
42 |
--------------------------------------------------------------------------------
/randomization/robustml_attack.py:
--------------------------------------------------------------------------------
1 | import robustml
2 | from defense import defend
3 | from inceptionv3 import model as inceptionv3_model
4 | from robustml_model import Randomization
5 | import sys
6 | import argparse
7 | import tensorflow as tf
8 | import numpy as np
9 | import time
10 | class EOT(robustml.attack.Attack):
11 | def __init__(self, sess, epsilon, sample_size=30, max_steps=1000, learning_rate=0.1, debug=False):
12 | self._sess = sess
13 |
14 | self._input = tf.placeholder(tf.float32, (299, 299, 3))
15 | x_expanded = tf.expand_dims(self._input, axis=0)
16 | ensemble_xs = tf.concat([defend(x_expanded) for _ in range(sample_size)], axis=0)
17 | self._logits, self._preds = inceptionv3_model(sess, ensemble_xs)
18 |
19 | self._label = tf.placeholder(tf.int32, ())
20 | one_hot = tf.expand_dims(tf.one_hot(self._label, 1000), axis=0)
21 | ensemble_labels = tf.tile(one_hot, (self._logits.shape[0], 1))
22 | self._loss = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(logits=self._logits, labels=ensemble_labels))
23 | self._grad, = tf.gradients(self._loss, self._input)
24 |
25 | self._epsilon = epsilon
26 | self._max_steps = max_steps
27 | self._learning_rate = learning_rate
28 | self._debug = debug
29 |
30 | def run(self, x, y, target):
31 | if target is not None:
32 | raise NotImplementedError
33 | adv = np.copy(x)
34 | lower = np.clip(x - self._epsilon, 0, 1)
35 | upper = np.clip(x + self._epsilon, 0, 1)
36 | for i in range(self._max_steps):
37 | p, l, g = self._sess.run(
38 | [self._preds, self._loss, self._grad],
39 | {self._input: adv, self._label: y}
40 | )
41 | if self._debug:
42 | print(
43 | 'attack: step %d/%d, loss = %g (true %d, predicted %s)' % (i+1, self._max_steps, l, y, p),
44 | file=sys.stderr
45 | )
46 | if y not in p:
47 | # we're done
48 | if self._debug:
49 | print('returning early', file=sys.stderr)
50 | break
51 | adv += self._learning_rate * g
52 | adv = np.clip(adv, lower, upper)
53 | return adv
54 |
55 | def main():
56 | parser = argparse.ArgumentParser()
57 | parser.add_argument('--imagenet-path', type=str, required=True,
58 | help='directory containing `val.txt` and `val/` folder')
59 | parser.add_argument('--start', type=int, default=0)
60 | parser.add_argument('--end', type=int, default=100)
61 | parser.add_argument('--debug', action='store_true')
62 | args = parser.parse_args()
63 |
64 | # set up TensorFlow session
65 | sess = tf.Session()
66 |
67 | # initialize a model
68 | model = Randomization(sess)
69 |
70 | # initialize an attack (it's a white box attack, and it's allowed to look
71 | # at the internals of the model in any way it wants)
72 | attack = EOT(sess, model.threat_model.epsilon, debug=args.debug)
73 |
74 | # initialize a data provider for ImageNet images
75 | provider = robustml.provider.ImageNet(args.imagenet_path, model.dataset.shape)
76 | attack_start = time.time()
77 | success_rate = robustml.evaluate.evaluate(
78 | model,
79 | attack,
80 | provider,
81 | start=args.start,
82 | end=args.end,
83 | deterministic=True,
84 | debug=args.debug,
85 | )
86 | print('attack time : ', time.time()-attack_start,flush=True)
87 | print('attack success rate: %.2f%% (over %d data points)' % (success_rate*100, args.end-args.start))
88 |
89 | if __name__ == '__main__':
90 | main()
91 |
--------------------------------------------------------------------------------
/randomization/setup.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | cd "$(dirname "$0")" # cd to directory of this script
4 |
5 | # $1 is filename
6 | # $2 is expected sha
7 | check_sha1() {
8 | computed=$(sha1sum "$1" 2>/dev/null | awk '{print $1}') || return 1
9 | if [ "$computed" == "$2" ]; then
10 | return 0;
11 | else
12 | return 1;
13 | fi
14 | }
15 |
16 | # $1 is URL
17 | # $2 is extracted file name
18 | # $3 is the checksum
19 | fetch() {
20 | if check_sha1 $2 $3; then
21 | echo "$2 already downloaded"
22 | return
23 | fi
24 | echo "downloading $1"
25 | f=${1##*/}
26 | wget -q $1 -O $f
27 | tar xf $f
28 | rm -f $f
29 | if check_sha1 $2 $3; then
30 | echo "downloaded $2"
31 | else
32 | echo "HASH MISMATCH, SHA1($2) != $3"
33 | fi
34 | }
35 |
36 | cd data
37 |
38 | fetch \
39 | http://download.tensorflow.org/models/inception_v3_2016_08_28.tar.gz \
40 | inception_v3.ckpt 606fd6953c58c817c56fd3bc2f0384fc2ecaba92
41 |
--------------------------------------------------------------------------------
/randomization/utils.py:
--------------------------------------------------------------------------------
1 | import tensorflow as tf
2 | from tensorflow.python.framework import ops
3 | import numpy as np
4 | import PIL.Image
5 | from imagenet_labels import label_to_name
6 | import matplotlib.pyplot as plt
7 |
8 | def one_hot(index, total):
9 | arr = np.zeros((total))
10 | arr[index] = 1.0
11 | return arr
12 |
13 | def optimistic_restore(session, save_file):
14 | reader = tf.train.NewCheckpointReader(save_file)
15 | saved_shapes = reader.get_variable_to_shape_map()
16 | var_names = sorted([(var.name, var.name.split(':')[0]) for var in tf.global_variables()
17 | if var.name.split(':')[0] in saved_shapes])
18 | restore_vars = []
19 | with tf.variable_scope('', reuse=True):
20 | for var_name, saved_var_name in var_names:
21 | curr_var = tf.get_variable(saved_var_name)
22 | var_shape = curr_var.get_shape().as_list()
23 | if var_shape == saved_shapes[saved_var_name]:
24 | restore_vars.append(curr_var)
25 | saver = tf.train.Saver(restore_vars)
26 | saver.restore(session, save_file)
27 |
28 | def load_image(path):
29 | return (np.asarray(PIL.Image.open(path).resize((299, 299)))/255.0).astype(np.float32)
30 |
31 | def make_classify(sess, input_, probs):
32 | def classify(img, correct_class=None, target_class=None):
33 | fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(10, 8))
34 | fig.sca(ax1)
35 | p = sess.run(probs, feed_dict={input_: img})[0]
36 | ax1.imshow(img)
37 | fig.sca(ax1)
38 |
39 | topk = list(p.argsort()[-10:][::-1])
40 | topprobs = p[topk]
41 | barlist = ax2.bar(range(10), topprobs)
42 | if target_class in topk:
43 | barlist[topk.index(target_class)].set_color('r')
44 | if correct_class in topk:
45 | barlist[topk.index(correct_class)].set_color('g')
46 | plt.sca(ax2)
47 | plt.ylim([0, 1.1])
48 | plt.xticks(range(10),
49 | [label_to_name(i)[:15] for i in topk],
50 | rotation='vertical')
51 | fig.subplots_adjust(bottom=0.2)
52 | plt.show()
53 | return classify
--------------------------------------------------------------------------------
/robustnet/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2017 Xuanqing Liu
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/robustnet/README.md:
--------------------------------------------------------------------------------
1 | # Towards robust neural networks via random self-ensemble
2 |
3 | Paper: [Liu et al. (2018)](https://arxiv.org/abs/1712.00673)
4 | ## Requirements
5 |
6 | * Python3 + pytorch0.4.0
7 |
8 | ## [NATTACK] evaluation
9 |
10 | Run with:
11 |
12 | ```bash
13 | python re_li_attack.py --cifar-path
14 | ````
15 |
16 | [robustml]: https://github.com/robust-ml/robustml
17 |
--------------------------------------------------------------------------------
/robustnet/attack.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python3
2 |
3 | import argparse
4 | import torch
5 | from torch.autograd import Variable
6 | import torch.optim as optim
7 | import torchvision.transforms as tfs
8 | import torchvision.datasets as dst
9 | from torch.utils.data import DataLoader
10 | import matplotlib.pyplot as plt
11 | from models import *
12 | import numpy as np
13 |
14 | classes = ('plane', 'car', 'bird', 'cat', 'deer', 'dog', 'frog', 'horse', 'ship', 'truck')
15 |
16 | def attack(input_v, label_v, net, c, TARGETED=False):
17 | n_class = len(classes)
18 | index = label_v.data.cpu().view(-1,1)
19 | label_onehot = torch.FloatTensor(input_v.size()[0] , n_class)
20 | label_onehot.zero_()
21 | label_onehot.scatter_(1,index,1)
22 | label_onehot_v = Variable(label_onehot, requires_grad = False).cuda()
23 | #print(label_onehot.scatter)
24 | adverse = input_v.data #torch.FloatTensor(input_v.size()).zero_().cuda()
25 | adverse_v = Variable(adverse, requires_grad=True)
26 | optimizer = optim.Adam([adverse_v], lr=0.1)
27 | for _ in range(300):
28 | optimizer.zero_grad()
29 | diff = adverse_v - input_v
30 | output = net(adverse_v)
31 | real = torch.sum(torch.max(torch.mul(output, label_onehot_v), 1)[0])
32 | other = torch.sum(torch.max(torch.mul(output, (1-label_onehot_v))-label_onehot_v*10000,1)[0])
33 | error = c * torch.sum(diff * diff)
34 | #print(error.size())
35 | if TARGETED:
36 | error += torch.clamp(other - real, min=0)
37 | else:
38 | error += torch.clamp(real - other, min=0)
39 | error.backward()
40 | optimizer.step()
41 | return adverse_v
42 |
43 | def weights_init(m):
44 | classname = m.__class__.__name__
45 | if classname.find('Linear') != -1:
46 | m.weight.data.normal_(0.0, 0.02)
47 | elif classname.find('Conv') != -1:
48 | m.weight.data.normal_(0.0, 0.02)
49 | elif classname.find('BatchNorm') != -1 and m.affine:
50 | m.weight.data.normal_(1.0, 0.02)
51 | m.bias.data.fill_(0)
52 |
53 |
54 | if __name__ == "__main__":
55 | parser = argparse.ArgumentParser()
56 | parser.add_argument('--modelIn', type=str, default=None)
57 | parser.add_argument('--c', type=float, default=1.0)
58 | parser.add_argument('--noise', type=float, default=0)
59 | opt = parser.parse_args()
60 |
61 | net = VGG("VGG16", opt.noise)
62 | net = nn.DataParallel(net, device_ids=range(1))
63 | loss_f = nn.CrossEntropyLoss()
64 | net.apply(weights_init)
65 | if opt.modelIn is not None:
66 | net.load_state_dict(torch.load(opt.modelIn))
67 | net.cuda()
68 | loss_f.cuda()
69 | mean = (0.4914, 0.4822, 0.4465)
70 | mean_t = torch.FloatTensor(mean).resize_(1, 3, 1, 1).cuda()
71 | std = (0.2023, 0.1994, 0.2010)
72 | std_t = torch.FloatTensor(std).resize_(1, 3, 1, 1).cuda()
73 | transform_train = tfs.Compose([
74 | tfs.ToTensor(),
75 | tfs.Normalize((0.4914, 0.4822, 0.4465), (0.2023, 0.1994, 0.2010)),
76 | ])
77 | transform_test = tfs.Compose([
78 | tfs.ToTensor(),
79 | tfs.Normalize((0.4914, 0.4822, 0.4465), (0.2023, 0.1994, 0.2010)),
80 | ])
81 | data = dst.CIFAR10("/home/luinx/data/cifar10-py", download=True, train=True, transform=transform_train)
82 | data_test = dst.CIFAR10("/home/luinx/data/cifar10-py", download=True, train=False, transform=transform_test)
83 | assert data, data_test
84 | dataloader = DataLoader(data, batch_size=100, shuffle=True, num_workers=2)
85 | dataloader_test = DataLoader(data_test, batch_size=100, shuffle=True, num_workers=2)
86 | count, count2 = 0, 0
87 | for input, output in dataloader_test:
88 | input_v, label_v = Variable(input.cuda()), Variable(output.cuda())
89 | adverse_v = attack(input_v, label_v, net, opt.c)
90 | _, idx = torch.max(net(input_v), 1)
91 | _, idx2 = torch.max(net(adverse_v), 1)
92 | count += torch.sum(label_v.eq(idx)).data[0]
93 | count2 += torch.sum(label_v.eq(idx2)).data[0]
94 | print("Count: {}, Count2: {}".format(count, count2))
95 |
96 | adverse_v.data = adverse_v.data * std_t + mean_t
97 | input_v.data = input_v.data * std_t + mean_t
98 | adverse_np = adverse_v.cpu().data.numpy().swapaxes(1, 3)
99 | input_np = input_v.cpu().data.numpy().swapaxes(1, 3)
100 | plt.subplot(121)
101 | plt.imshow(np.abs(input_np[0, :, :, :].squeeze()))
102 | plt.subplot(122)
103 | plt.imshow(np.abs(adverse_np[0, :, :, :].squeeze()))
104 | plt.show()
105 |
106 | print("Accuracy: {}, Attach: {}".format(count / len(data), count2 / len(data)))
107 |
--------------------------------------------------------------------------------
/robustnet/helpers.py:
--------------------------------------------------------------------------------
1 | import operator as op
2 | import functools as ft
3 | import numpy as np
4 |
5 |
6 | '''reduce_* helper functions reduce tensors on all dimensions but the first.
7 | They are intended to be used on batched tensors where dim 0 is the batch dim.
8 | '''
9 |
10 |
11 | def reduce_sum(x, keepdim=True):
12 | # silly PyTorch, when will you get proper reducing sums/means?
13 | for a in reversed(range(1, x.dim())):
14 | x = x.sum(a, keepdim=keepdim)
15 | return x
16 |
17 |
18 | def reduce_mean(x, keepdim=True):
19 | numel = ft.reduce(op.mul, x.size()[1:])
20 | x = reduce_sum(x, keepdim=keepdim)
21 | return x / numel
22 |
23 |
24 | def reduce_min(x, keepdim=True):
25 | for a in reversed(range(1, x.dim())):
26 | x = x.min(a, keepdim=keepdim)[0]
27 | return x
28 |
29 |
30 | def reduce_max(x, keepdim=True):
31 | for a in reversed(range(1, x.dim())):
32 | x = x.max(a, keepdim=keepdim)[0]
33 | return x
34 |
35 |
36 | def torch_arctanh(x, eps=1e-6):
37 | x *= (1. - eps)
38 | return (np.log((1 + x) / (1 - x))) * 0.5
39 |
40 |
41 | def l2r_dist(x, y, keepdim=True, eps=1e-8):
42 | d = (x - y)**2
43 | d = reduce_sum(d, keepdim=keepdim)
44 | d += eps # to prevent infinite gradient at 0
45 | return d.sqrt()
46 |
47 |
48 | def l2_dist(x, y, keepdim=True):
49 | d = (x - y)**2
50 | return reduce_sum(d, keepdim=keepdim)
51 |
52 |
53 | def l1_dist(x, y, keepdim=True):
54 | d = torch.abs(x - y)
55 | return reduce_sum(d, keepdim=keepdim)
56 |
57 |
58 | def l2_norm(x, keepdim=True):
59 | norm = reduce_sum(x*x, keepdim=keepdim)
60 | return norm.sqrt()
61 |
62 |
63 | def l1_norm(x, keepdim=True):
64 | return reduce_sum(x.abs(), keepdim=keepdim)
65 |
66 |
67 | def rescale(x, x_min=-1., x_max=1.):
68 | return x * (x_max - x_min) + x_min
69 |
70 |
71 | def tanh_rescale(x, x_min=-1., x_max=1.):
72 | return (torch.tanh(x) + 1) * 0.5 * (x_max - x_min) + x_min
73 |
--------------------------------------------------------------------------------
/robustnet/main.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python3
2 | '''Train CIFAR10 with PyTorch.'''
3 | from __future__ import print_function
4 |
5 | import torch
6 | import torch.nn as nn
7 | import torch.optim as optim
8 | import torch.nn.functional as F
9 | import torch.backends.cudnn as cudnn
10 |
11 | import torchvision
12 | import torchvision.transforms as transforms
13 |
14 | import os
15 | import argparse
16 |
17 | from models import *
18 | from utils import progress_bar
19 | from torch.autograd import Variable
20 |
21 |
22 | parser = argparse.ArgumentParser(description='PyTorch CIFAR10 Training')
23 | parser.add_argument('--lr', default=0.1, type=float, help='learning rate')
24 | parser.add_argument('--resume', '-r', action='store_true', help='resume from checkpoint')
25 | args = parser.parse_args()
26 |
27 | use_cuda = torch.cuda.is_available()
28 | best_acc = 0 # best test accuracy
29 | start_epoch = 0 # start from epoch 0 or last checkpoint epoch
30 |
31 | # Data
32 | print('==> Preparing data..')
33 | transform_train = transforms.Compose([
34 | transforms.RandomCrop(32, padding=4),
35 | transforms.RandomHorizontalFlip(),
36 | transforms.ToTensor(),
37 | transforms.Normalize((0.4914, 0.4822, 0.4465), (0.2023, 0.1994, 0.2010)),
38 | ])
39 |
40 | transform_test = transforms.Compose([
41 | transforms.ToTensor(),
42 | transforms.Normalize((0.4914, 0.4822, 0.4465), (0.2023, 0.1994, 0.2010)),
43 | ])
44 |
45 | trainset = torchvision.datasets.CIFAR10(root='/home/luinx/data', train=True, download=True, transform=transform_train)
46 | trainloader = torch.utils.data.DataLoader(trainset, batch_size=128, shuffle=True, num_workers=2)
47 |
48 | testset = torchvision.datasets.CIFAR10(root='/home/luinx/data', train=False, download=True, transform=transform_test)
49 | testloader = torch.utils.data.DataLoader(testset, batch_size=100, shuffle=False, num_workers=2)
50 |
51 | classes = ('plane', 'car', 'bird', 'cat', 'deer', 'dog', 'frog', 'horse', 'ship', 'truck')
52 |
53 | # Model
54 | if args.resume:
55 | # Load checkpoint.
56 | print('==> Resuming from checkpoint..')
57 | assert os.path.isdir('checkpoint'), 'Error: no checkpoint directory found!'
58 | checkpoint = torch.load('./checkpoint/ckpt.t7')
59 | net = checkpoint['net']
60 | best_acc = checkpoint['acc']
61 | start_epoch = checkpoint['epoch']
62 | else:
63 | print('==> Building model..')
64 | net = VGG('VGG16', 0)
65 | # net = ResNet18()
66 | # net = PreActResNet18()
67 | # net = GoogLeNet()
68 | # net = DenseNet121()
69 | # net = ResNeXt29_2x64d()
70 | # net = MobileNet()
71 | # net = DPN92()
72 | # net = ShuffleNetG2()
73 | # net = SENet18()
74 |
75 | if use_cuda:
76 | net.cuda()
77 | net = torch.nn.DataParallel(net, device_ids=range(torch.cuda.device_count()))
78 | cudnn.benchmark = True
79 |
80 | criterion = nn.CrossEntropyLoss()
81 | optimizer = optim.SGD(net.parameters(), lr=args.lr, momentum=0.9, weight_decay=5e-4)
82 |
83 | # Training
84 | def train(epoch):
85 | print('\nEpoch: %d' % epoch)
86 | net.train()
87 | train_loss = 0
88 | correct = 0
89 | total = 0
90 | for batch_idx, (inputs, targets) in enumerate(trainloader):
91 | if use_cuda:
92 | inputs, targets = inputs.cuda(), targets.cuda()
93 | optimizer.zero_grad()
94 | inputs, targets = Variable(inputs), Variable(targets)
95 | outputs = net(inputs)
96 | loss = criterion(outputs, targets)
97 | loss.backward()
98 | optimizer.step()
99 |
100 | train_loss += loss.data[0]
101 | _, predicted = torch.max(outputs.data, 1)
102 | total += targets.size(0)
103 | correct += predicted.eq(targets.data).cpu().sum()
104 |
105 | progress_bar(batch_idx, len(trainloader), 'Loss: %.3f | Acc: %.3f%% (%d/%d)'
106 | % (train_loss/(batch_idx+1), 100.*correct/total, correct, total))
107 |
108 | def test(epoch):
109 | global best_acc
110 | net.eval()
111 | test_loss = 0
112 | correct = 0
113 | total = 0
114 | for batch_idx, (inputs, targets) in enumerate(testloader):
115 | if use_cuda:
116 | inputs, targets = inputs.cuda(), targets.cuda()
117 | inputs, targets = Variable(inputs, volatile=True), Variable(targets)
118 | outputs = net(inputs)
119 | loss = criterion(outputs, targets)
120 |
121 | test_loss += loss.data[0]
122 | _, predicted = torch.max(outputs.data, 1)
123 | total += targets.size(0)
124 | correct += predicted.eq(targets.data).cpu().sum()
125 |
126 | progress_bar(batch_idx, len(testloader), 'Loss: %.3f | Acc: %.3f%% (%d/%d)'
127 | % (test_loss/(batch_idx+1), 100.*correct/total, correct, total))
128 |
129 | # Save checkpoint.
130 | acc = 100.*correct/total
131 | if acc > best_acc:
132 | print('Saving..')
133 | state = {
134 | 'net': net.module if use_cuda else net,
135 | 'acc': acc,
136 | 'epoch': epoch,
137 | }
138 | if not os.path.isdir('checkpoint'):
139 | os.mkdir('checkpoint')
140 | torch.save(state, './checkpoint/ckpt.t7')
141 | best_acc = acc
142 |
143 |
144 | for epoch in range(start_epoch, start_epoch+200):
145 | train(epoch)
146 | test(epoch)
147 |
--------------------------------------------------------------------------------
/robustnet/main2.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python3
2 |
3 | import argparse
4 | import numpy as np
5 | import torch
6 | import torch.optim as optim
7 | import torch.nn as nn
8 | from torch.autograd import Variable
9 | import torchvision.datasets as dst
10 | import torchvision.transforms as tfs
11 | from models import *
12 | from torch.utils.data import DataLoader
13 | import time
14 |
15 | def accuracy(dataloader, net):
16 | data_iter = iter(dataloader)
17 | count = 0
18 | total = 0
19 | for x, y in data_iter:
20 | vx = Variable(x, volatile=True).cuda()
21 | tmp = torch.sum(torch.eq(y.cuda(), torch.max(net(vx), dim=1)[1]).data)
22 | count += int(tmp)
23 | total += y.size()[0]
24 | return count / total
25 |
26 | def loss(dataloader, net, loss_f):
27 | data_iter = iter(dataloader)
28 | total_loss = 0.0
29 | count = 0
30 | for x, y in data_iter:
31 | vx = Variable(x, volatile=True).cuda()
32 | vy = Variable(y).cuda()
33 | total_loss += torch.sum(loss_f(net(vx), vy).data)
34 | count += y.size()[0]
35 | return total_loss / count
36 |
37 | def train_other(dataloader, dataloader_test, net, loss_f, lr, name='adam', max_epoch=10):
38 | run_time = 0.0
39 | if name == 'adam':
40 | optimizer = optim.Adam(net.parameters(), lr=lr)
41 | elif name == 'rmsprop':
42 | optimizer = optim.RMSprop(net.parameters(), lr=lr)
43 | elif name == 'momsgd':
44 | optimizer = optim.SGD(net.parameters(), lr=lr, momentum=0.9, weight_decay=5.0e-4)
45 | else:
46 | print('Not implemented')
47 | exit(-1)
48 | for epoch in range(max_epoch):
49 | beg = time.time()
50 | data_iter = iter(dataloader)
51 | for x, y in data_iter:
52 | vx, vy = Variable(x).cuda(), Variable(y).cuda()
53 | optimizer.zero_grad()
54 | lossv = loss_f(net(vx), vy)
55 | lossv.backward()
56 | optimizer.step()
57 | run_time += time.time() - beg
58 | print("[Epoch {}] Time: {}, Train loss: {}, Train accuracy: {}, Test loss: {}, Test accuracy: {}".format(epoch, run_time, loss(dataloader, net, loss_f), accuracy(dataloader, net), loss(dataloader_test, net, loss_f), accuracy(dataloader_test, net)))
59 |
60 |
61 | def weights_init(m):
62 | classname = m.__class__.__name__
63 | if classname.find('Linear') != -1:
64 | m.weight.data.normal_(0.0, 0.02)
65 | elif classname.find('Conv') != -1:
66 | m.weight.data.normal_(0.0, 0.02)
67 | elif classname.find('BatchNorm') != -1 and m.affine:
68 | m.weight.data.normal_(1.0, 0.02)
69 | m.bias.data.fill_(0)
70 |
71 | def main():
72 | parser = argparse.ArgumentParser()
73 | parser.add_argument('--batchSize', type=int, default=128)
74 | parser.add_argument('--epoch', type=int, default=300)
75 | parser.add_argument('--lr', type=float, default=1.0)
76 | parser.add_argument('--ngpu', type=int, default=1)
77 | parser.add_argument('--modelIn', type=str, default=None)
78 | parser.add_argument('--modelOut', type=str, default=None)
79 | parser.add_argument('--method', type=str, default="momsgd")
80 | parser.add_argument('--noise', type=float, default=0.0)
81 | opt = parser.parse_args()
82 | print(opt)
83 | net = VGG("VGG16", opt.noise)
84 | #net = densenet_cifar()
85 | #net = GoogLeNet()
86 | #net = MobileNet(num_classes=100)
87 | #net = stl10(32)
88 | net = nn.DataParallel(net, device_ids=range(opt.ngpu))
89 | #net = Test()
90 | net.apply(weights_init)
91 | if opt.modelIn is not None:
92 | net.load_state_dict(torch.load(opt.modelIn))
93 | loss_f = nn.CrossEntropyLoss()
94 | net.cuda()
95 | loss_f.cuda()
96 | transform_train = tfs.Compose([
97 | tfs.RandomCrop(32, padding=4),
98 | tfs.RandomHorizontalFlip(),
99 | tfs.ToTensor(),
100 | tfs.Normalize((0.4914, 0.4822, 0.4465), (0.2023, 0.1994, 0.2010)),
101 | ])
102 |
103 | transform_test = tfs.Compose([
104 | tfs.ToTensor(),
105 | tfs.Normalize((0.4914, 0.4822, 0.4465), (0.2023, 0.1994, 0.2010)),
106 | ])
107 | data = dst.CIFAR10("../cifar10_data", download=True, train=True, transform=transform_train)
108 | data_test = dst.CIFAR10("../cifar10_data", download=True, train=False, transform=transform_test)
109 | assert data, data_test
110 | dataloader = DataLoader(data, batch_size=opt.batchSize, shuffle=True, num_workers=2)
111 | dataloader_test = DataLoader(data_test, batch_size=opt.batchSize, shuffle=True, num_workers=2)
112 | for period in range(opt.epoch // 100):
113 | train_other(dataloader, dataloader_test, net, loss_f, opt.lr, opt.method, 100)
114 | opt.lr /= 10
115 | # save model
116 | if opt.modelOut is not None:
117 | torch.save(net.state_dict(), opt.modelOut)
118 |
119 | if __name__ == "__main__":
120 | main()
121 |
--------------------------------------------------------------------------------
/robustnet/models/__init__.py:
--------------------------------------------------------------------------------
1 | from .vgg import *
2 | from .dpn import *
3 | from .lenet import *
4 | from .senet import *
5 | from .resnet import *
6 | from .resnext import *
7 | from .densenet import *
8 | from .googlenet import *
9 | from .mobilenet import *
10 | from .shufflenet import *
11 | from .preact_resnet import *
12 |
--------------------------------------------------------------------------------
/robustnet/models/densenet.py:
--------------------------------------------------------------------------------
1 | '''DenseNet in PyTorch.'''
2 | import math
3 |
4 | import torch
5 | import torch.nn as nn
6 | import torch.nn.functional as F
7 |
8 | from torch.autograd import Variable
9 |
10 |
11 | class Bottleneck(nn.Module):
12 | def __init__(self, in_planes, growth_rate):
13 | super(Bottleneck, self).__init__()
14 | self.bn1 = nn.BatchNorm2d(in_planes)
15 | self.conv1 = nn.Conv2d(in_planes, 4*growth_rate, kernel_size=1, bias=False)
16 | self.bn2 = nn.BatchNorm2d(4*growth_rate)
17 | self.conv2 = nn.Conv2d(4*growth_rate, growth_rate, kernel_size=3, padding=1, bias=False)
18 |
19 | def forward(self, x):
20 | out = self.conv1(F.relu(self.bn1(x)))
21 | out = self.conv2(F.relu(self.bn2(out)))
22 | out = torch.cat([out,x], 1)
23 | return out
24 |
25 |
26 | class Transition(nn.Module):
27 | def __init__(self, in_planes, out_planes):
28 | super(Transition, self).__init__()
29 | self.bn = nn.BatchNorm2d(in_planes)
30 | self.conv = nn.Conv2d(in_planes, out_planes, kernel_size=1, bias=False)
31 |
32 | def forward(self, x):
33 | out = self.conv(F.relu(self.bn(x)))
34 | out = F.avg_pool2d(out, 2)
35 | return out
36 |
37 |
38 | class DenseNet(nn.Module):
39 | def __init__(self, block, nblocks, growth_rate=12, reduction=0.5, num_classes=10):
40 | super(DenseNet, self).__init__()
41 | self.growth_rate = growth_rate
42 |
43 | num_planes = 2*growth_rate
44 | self.conv1 = nn.Conv2d(3, num_planes, kernel_size=3, padding=1, bias=False)
45 |
46 | self.dense1 = self._make_dense_layers(block, num_planes, nblocks[0])
47 | num_planes += nblocks[0]*growth_rate
48 | out_planes = int(math.floor(num_planes*reduction))
49 | self.trans1 = Transition(num_planes, out_planes)
50 | num_planes = out_planes
51 |
52 | self.dense2 = self._make_dense_layers(block, num_planes, nblocks[1])
53 | num_planes += nblocks[1]*growth_rate
54 | out_planes = int(math.floor(num_planes*reduction))
55 | self.trans2 = Transition(num_planes, out_planes)
56 | num_planes = out_planes
57 |
58 | self.dense3 = self._make_dense_layers(block, num_planes, nblocks[2])
59 | num_planes += nblocks[2]*growth_rate
60 | out_planes = int(math.floor(num_planes*reduction))
61 | self.trans3 = Transition(num_planes, out_planes)
62 | num_planes = out_planes
63 |
64 | self.dense4 = self._make_dense_layers(block, num_planes, nblocks[3])
65 | num_planes += nblocks[3]*growth_rate
66 |
67 | self.bn = nn.BatchNorm2d(num_planes)
68 | self.linear = nn.Linear(num_planes, num_classes)
69 |
70 | def _make_dense_layers(self, block, in_planes, nblock):
71 | layers = []
72 | for i in range(nblock):
73 | layers.append(block(in_planes, self.growth_rate))
74 | in_planes += self.growth_rate
75 | return nn.Sequential(*layers)
76 |
77 | def forward(self, x):
78 | out = self.conv1(x)
79 | out = self.trans1(self.dense1(out))
80 | out = self.trans2(self.dense2(out))
81 | out = self.trans3(self.dense3(out))
82 | out = self.dense4(out)
83 | out = F.avg_pool2d(F.relu(self.bn(out)), 4)
84 | out = out.view(out.size(0), -1)
85 | out = self.linear(out)
86 | return out
87 |
88 | def DenseNet121():
89 | return DenseNet(Bottleneck, [6,12,24,16], growth_rate=32)
90 |
91 | def DenseNet169():
92 | return DenseNet(Bottleneck, [6,12,32,32], growth_rate=32)
93 |
94 | def DenseNet201():
95 | return DenseNet(Bottleneck, [6,12,48,32], growth_rate=32)
96 |
97 | def DenseNet161():
98 | return DenseNet(Bottleneck, [6,12,36,24], growth_rate=48)
99 |
100 | def densenet_cifar():
101 | return DenseNet(Bottleneck, [6,12,24,16], growth_rate=12)
102 |
103 | def test_densenet():
104 | net = densenet_cifar()
105 | x = torch.randn(1,3,32,32)
106 | y = net(Variable(x))
107 | print(y)
108 |
109 | # test_densenet()
110 |
--------------------------------------------------------------------------------
/robustnet/models/dpn.py:
--------------------------------------------------------------------------------
1 | '''Dual Path Networks in PyTorch.'''
2 | import torch
3 | import torch.nn as nn
4 | import torch.nn.functional as F
5 |
6 | from torch.autograd import Variable
7 |
8 |
9 | class Bottleneck(nn.Module):
10 | def __init__(self, last_planes, in_planes, out_planes, dense_depth, stride, first_layer):
11 | super(Bottleneck, self).__init__()
12 | self.out_planes = out_planes
13 | self.dense_depth = dense_depth
14 |
15 | self.conv1 = nn.Conv2d(last_planes, in_planes, kernel_size=1, bias=False)
16 | self.bn1 = nn.BatchNorm2d(in_planes)
17 | self.conv2 = nn.Conv2d(in_planes, in_planes, kernel_size=3, stride=stride, padding=1, groups=32, bias=False)
18 | self.bn2 = nn.BatchNorm2d(in_planes)
19 | self.conv3 = nn.Conv2d(in_planes, out_planes+dense_depth, kernel_size=1, bias=False)
20 | self.bn3 = nn.BatchNorm2d(out_planes+dense_depth)
21 |
22 | self.shortcut = nn.Sequential()
23 | if first_layer:
24 | self.shortcut = nn.Sequential(
25 | nn.Conv2d(last_planes, out_planes+dense_depth, kernel_size=1, stride=stride, bias=False),
26 | nn.BatchNorm2d(out_planes+dense_depth)
27 | )
28 |
29 | def forward(self, x):
30 | out = F.relu(self.bn1(self.conv1(x)))
31 | out = F.relu(self.bn2(self.conv2(out)))
32 | out = self.bn3(self.conv3(out))
33 | x = self.shortcut(x)
34 | d = self.out_planes
35 | out = torch.cat([x[:,:d,:,:]+out[:,:d,:,:], x[:,d:,:,:], out[:,d:,:,:]], 1)
36 | out = F.relu(out)
37 | return out
38 |
39 |
40 | class DPN(nn.Module):
41 | def __init__(self, cfg):
42 | super(DPN, self).__init__()
43 | in_planes, out_planes = cfg['in_planes'], cfg['out_planes']
44 | num_blocks, dense_depth = cfg['num_blocks'], cfg['dense_depth']
45 |
46 | self.conv1 = nn.Conv2d(3, 64, kernel_size=3, stride=1, padding=1, bias=False)
47 | self.bn1 = nn.BatchNorm2d(64)
48 | self.last_planes = 64
49 | self.layer1 = self._make_layer(in_planes[0], out_planes[0], num_blocks[0], dense_depth[0], stride=1)
50 | self.layer2 = self._make_layer(in_planes[1], out_planes[1], num_blocks[1], dense_depth[1], stride=2)
51 | self.layer3 = self._make_layer(in_planes[2], out_planes[2], num_blocks[2], dense_depth[2], stride=2)
52 | self.layer4 = self._make_layer(in_planes[3], out_planes[3], num_blocks[3], dense_depth[3], stride=2)
53 | self.linear = nn.Linear(out_planes[3]+(num_blocks[3]+1)*dense_depth[3], 10)
54 |
55 | def _make_layer(self, in_planes, out_planes, num_blocks, dense_depth, stride):
56 | strides = [stride] + [1]*(num_blocks-1)
57 | layers = []
58 | for i,stride in enumerate(strides):
59 | layers.append(Bottleneck(self.last_planes, in_planes, out_planes, dense_depth, stride, i==0))
60 | self.last_planes = out_planes + (i+2) * dense_depth
61 | return nn.Sequential(*layers)
62 |
63 | def forward(self, x):
64 | out = F.relu(self.bn1(self.conv1(x)))
65 | out = self.layer1(out)
66 | out = self.layer2(out)
67 | out = self.layer3(out)
68 | out = self.layer4(out)
69 | out = F.avg_pool2d(out, 4)
70 | out = out.view(out.size(0), -1)
71 | out = self.linear(out)
72 | return out
73 |
74 |
75 | def DPN26():
76 | cfg = {
77 | 'in_planes': (96,192,384,768),
78 | 'out_planes': (256,512,1024,2048),
79 | 'num_blocks': (2,2,2,2),
80 | 'dense_depth': (16,32,24,128)
81 | }
82 | return DPN(cfg)
83 |
84 | def DPN92():
85 | cfg = {
86 | 'in_planes': (96,192,384,768),
87 | 'out_planes': (256,512,1024,2048),
88 | 'num_blocks': (3,4,20,3),
89 | 'dense_depth': (16,32,24,128)
90 | }
91 | return DPN(cfg)
92 |
93 |
94 | def test():
95 | net = DPN92()
96 | x = Variable(torch.randn(1,3,32,32))
97 | y = net(x)
98 | print(y)
99 |
100 | # test()
101 |
--------------------------------------------------------------------------------
/robustnet/models/googlenet.py:
--------------------------------------------------------------------------------
1 | '''GoogLeNet with PyTorch.'''
2 | import torch
3 | import torch.nn as nn
4 | import torch.nn.functional as F
5 |
6 | from torch.autograd import Variable
7 |
8 |
9 | class Inception(nn.Module):
10 | def __init__(self, in_planes, n1x1, n3x3red, n3x3, n5x5red, n5x5, pool_planes):
11 | super(Inception, self).__init__()
12 | # 1x1 conv branch
13 | self.b1 = nn.Sequential(
14 | nn.Conv2d(in_planes, n1x1, kernel_size=1),
15 | nn.BatchNorm2d(n1x1),
16 | nn.ReLU(True),
17 | )
18 |
19 | # 1x1 conv -> 3x3 conv branch
20 | self.b2 = nn.Sequential(
21 | nn.Conv2d(in_planes, n3x3red, kernel_size=1),
22 | nn.BatchNorm2d(n3x3red),
23 | nn.ReLU(True),
24 | nn.Conv2d(n3x3red, n3x3, kernel_size=3, padding=1),
25 | nn.BatchNorm2d(n3x3),
26 | nn.ReLU(True),
27 | )
28 |
29 | # 1x1 conv -> 5x5 conv branch
30 | self.b3 = nn.Sequential(
31 | nn.Conv2d(in_planes, n5x5red, kernel_size=1),
32 | nn.BatchNorm2d(n5x5red),
33 | nn.ReLU(True),
34 | nn.Conv2d(n5x5red, n5x5, kernel_size=3, padding=1),
35 | nn.BatchNorm2d(n5x5),
36 | nn.ReLU(True),
37 | nn.Conv2d(n5x5, n5x5, kernel_size=3, padding=1),
38 | nn.BatchNorm2d(n5x5),
39 | nn.ReLU(True),
40 | )
41 |
42 | # 3x3 pool -> 1x1 conv branch
43 | self.b4 = nn.Sequential(
44 | nn.MaxPool2d(3, stride=1, padding=1),
45 | nn.Conv2d(in_planes, pool_planes, kernel_size=1),
46 | nn.BatchNorm2d(pool_planes),
47 | nn.ReLU(True),
48 | )
49 |
50 | def forward(self, x):
51 | y1 = self.b1(x)
52 | y2 = self.b2(x)
53 | y3 = self.b3(x)
54 | y4 = self.b4(x)
55 | return torch.cat([y1,y2,y3,y4], 1)
56 |
57 |
58 | class GoogLeNet(nn.Module):
59 | def __init__(self):
60 | super(GoogLeNet, self).__init__()
61 | self.pre_layers = nn.Sequential(
62 | nn.Conv2d(3, 192, kernel_size=3, padding=1),
63 | nn.BatchNorm2d(192),
64 | nn.ReLU(True),
65 | )
66 |
67 | self.a3 = Inception(192, 64, 96, 128, 16, 32, 32)
68 | self.b3 = Inception(256, 128, 128, 192, 32, 96, 64)
69 |
70 | self.maxpool = nn.MaxPool2d(3, stride=2, padding=1)
71 |
72 | self.a4 = Inception(480, 192, 96, 208, 16, 48, 64)
73 | self.b4 = Inception(512, 160, 112, 224, 24, 64, 64)
74 | self.c4 = Inception(512, 128, 128, 256, 24, 64, 64)
75 | self.d4 = Inception(512, 112, 144, 288, 32, 64, 64)
76 | self.e4 = Inception(528, 256, 160, 320, 32, 128, 128)
77 |
78 | self.a5 = Inception(832, 256, 160, 320, 32, 128, 128)
79 | self.b5 = Inception(832, 384, 192, 384, 48, 128, 128)
80 |
81 | self.avgpool = nn.AvgPool2d(8, stride=1)
82 | self.linear = nn.Linear(1024, 10)
83 |
84 | def forward(self, x):
85 | out = self.pre_layers(x)
86 | out = self.a3(out)
87 | out = self.b3(out)
88 | out = self.maxpool(out)
89 | out = self.a4(out)
90 | out = self.b4(out)
91 | out = self.c4(out)
92 | out = self.d4(out)
93 | out = self.e4(out)
94 | out = self.maxpool(out)
95 | out = self.a5(out)
96 | out = self.b5(out)
97 | out = self.avgpool(out)
98 | out = out.view(out.size(0), -1)
99 | out = self.linear(out)
100 | return out
101 |
102 | # net = GoogLeNet()
103 | # x = torch.randn(1,3,32,32)
104 | # y = net(Variable(x))
105 | # print(y.size())
106 |
--------------------------------------------------------------------------------
/robustnet/models/layer.py:
--------------------------------------------------------------------------------
1 | import torch
2 | import torch.nn as nn
3 |
4 | class Noise(nn.Module):
5 | def __init__(self, std):
6 | super(Noise, self, ).__init__()
7 | self.std = std
8 | self.buffer = None
9 |
10 | def forward(self, x):
11 | if self.training and self.std > 1.0e-6:
12 | if self.buffer is None:
13 | self.buffer = torch.Tensor(x.size()).normal_(0, self.std).cuda()
14 | else:
15 | self.buffer.resize_(x.size()).normal_(0, self.std)
16 | x.data += self.buffer
17 | return x
18 |
19 |
--------------------------------------------------------------------------------
/robustnet/models/lenet.py:
--------------------------------------------------------------------------------
1 | '''LeNet in PyTorch.'''
2 | import torch.nn as nn
3 | import torch.nn.functional as F
4 |
5 | class LeNet(nn.Module):
6 | def __init__(self):
7 | super(LeNet, self).__init__()
8 | self.conv1 = nn.Conv2d(3, 6, 5)
9 | self.conv2 = nn.Conv2d(6, 16, 5)
10 | self.fc1 = nn.Linear(16*5*5, 120)
11 | self.fc2 = nn.Linear(120, 84)
12 | self.fc3 = nn.Linear(84, 10)
13 |
14 | def forward(self, x):
15 | out = F.relu(self.conv1(x))
16 | out = F.max_pool2d(out, 2)
17 | out = F.relu(self.conv2(out))
18 | out = F.max_pool2d(out, 2)
19 | out = out.view(out.size(0), -1)
20 | out = F.relu(self.fc1(out))
21 | out = F.relu(self.fc2(out))
22 | out = self.fc3(out)
23 | return out
24 |
--------------------------------------------------------------------------------
/robustnet/models/mobilenet.py:
--------------------------------------------------------------------------------
1 | '''MobileNet in PyTorch.
2 |
3 | See the paper "MobileNets: Efficient Convolutional Neural Networks for Mobile Vision Applications"
4 | for more details.
5 | '''
6 | import torch
7 | import torch.nn as nn
8 | import torch.nn.functional as F
9 |
10 | from torch.autograd import Variable
11 |
12 |
13 | class Block(nn.Module):
14 | '''Depthwise conv + Pointwise conv'''
15 | def __init__(self, in_planes, out_planes, stride=1):
16 | super(Block, self).__init__()
17 | self.conv1 = nn.Conv2d(in_planes, in_planes, kernel_size=3, stride=stride, padding=1, groups=in_planes, bias=False)
18 | self.bn1 = nn.BatchNorm2d(in_planes)
19 | self.conv2 = nn.Conv2d(in_planes, out_planes, kernel_size=1, stride=1, padding=0, bias=False)
20 | self.bn2 = nn.BatchNorm2d(out_planes)
21 |
22 | def forward(self, x):
23 | out = F.relu(self.bn1(self.conv1(x)))
24 | out = F.relu(self.bn2(self.conv2(out)))
25 | return out
26 |
27 |
28 | class MobileNet(nn.Module):
29 | # (128,2) means conv planes=128, conv stride=2, by default conv stride=1
30 | cfg = [64, (128,2), 128, (256,2), 256, (512,2), 512, 512, 512, 512, 512, (1024,2), 1024]
31 |
32 | def __init__(self, num_classes=10):
33 | super(MobileNet, self).__init__()
34 | self.conv1 = nn.Conv2d(3, 32, kernel_size=3, stride=1, padding=1, bias=False)
35 | self.bn1 = nn.BatchNorm2d(32)
36 | self.layers = self._make_layers(in_planes=32)
37 | self.linear = nn.Linear(1024, num_classes)
38 |
39 | def _make_layers(self, in_planes):
40 | layers = []
41 | for x in self.cfg:
42 | out_planes = x if isinstance(x, int) else x[0]
43 | stride = 1 if isinstance(x, int) else x[1]
44 | layers.append(Block(in_planes, out_planes, stride))
45 | in_planes = out_planes
46 | return nn.Sequential(*layers)
47 |
48 | def forward(self, x):
49 | out = F.relu(self.bn1(self.conv1(x)))
50 | out = self.layers(out)
51 | out = F.avg_pool2d(out, 2)
52 | out = out.view(out.size(0), -1)
53 | out = self.linear(out)
54 | return out
55 |
56 |
57 | def test():
58 | net = MobileNet()
59 | x = torch.randn(1,3,32,32)
60 | y = net(Variable(x))
61 | print(y.size())
62 |
63 | # test()
64 |
--------------------------------------------------------------------------------
/robustnet/models/preact_resnet.py:
--------------------------------------------------------------------------------
1 | '''Pre-activation ResNet in PyTorch.
2 |
3 | Reference:
4 | [1] Kaiming He, Xiangyu Zhang, Shaoqing Ren, Jian Sun
5 | Identity Mappings in Deep Residual Networks. arXiv:1603.05027
6 | '''
7 | import torch
8 | import torch.nn as nn
9 | import torch.nn.functional as F
10 |
11 | from torch.autograd import Variable
12 |
13 |
14 | class PreActBlock(nn.Module):
15 | '''Pre-activation version of the BasicBlock.'''
16 | expansion = 1
17 |
18 | def __init__(self, in_planes, planes, stride=1):
19 | super(PreActBlock, self).__init__()
20 | self.bn1 = nn.BatchNorm2d(in_planes)
21 | self.conv1 = nn.Conv2d(in_planes, planes, kernel_size=3, stride=stride, padding=1, bias=False)
22 | self.bn2 = nn.BatchNorm2d(planes)
23 | self.conv2 = nn.Conv2d(planes, planes, kernel_size=3, stride=1, padding=1, bias=False)
24 |
25 | if stride != 1 or in_planes != self.expansion*planes:
26 | self.shortcut = nn.Sequential(
27 | nn.Conv2d(in_planes, self.expansion*planes, kernel_size=1, stride=stride, bias=False)
28 | )
29 |
30 | def forward(self, x):
31 | out = F.relu(self.bn1(x))
32 | shortcut = self.shortcut(out) if hasattr(self, 'shortcut') else x
33 | out = self.conv1(out)
34 | out = self.conv2(F.relu(self.bn2(out)))
35 | out += shortcut
36 | return out
37 |
38 |
39 | class PreActBottleneck(nn.Module):
40 | '''Pre-activation version of the original Bottleneck module.'''
41 | expansion = 4
42 |
43 | def __init__(self, in_planes, planes, stride=1):
44 | super(PreActBottleneck, self).__init__()
45 | self.bn1 = nn.BatchNorm2d(in_planes)
46 | self.conv1 = nn.Conv2d(in_planes, planes, kernel_size=1, bias=False)
47 | self.bn2 = nn.BatchNorm2d(planes)
48 | self.conv2 = nn.Conv2d(planes, planes, kernel_size=3, stride=stride, padding=1, bias=False)
49 | self.bn3 = nn.BatchNorm2d(planes)
50 | self.conv3 = nn.Conv2d(planes, self.expansion*planes, kernel_size=1, bias=False)
51 |
52 | if stride != 1 or in_planes != self.expansion*planes:
53 | self.shortcut = nn.Sequential(
54 | nn.Conv2d(in_planes, self.expansion*planes, kernel_size=1, stride=stride, bias=False)
55 | )
56 |
57 | def forward(self, x):
58 | out = F.relu(self.bn1(x))
59 | shortcut = self.shortcut(out) if hasattr(self, 'shortcut') else x
60 | out = self.conv1(out)
61 | out = self.conv2(F.relu(self.bn2(out)))
62 | out = self.conv3(F.relu(self.bn3(out)))
63 | out += shortcut
64 | return out
65 |
66 |
67 | class PreActResNet(nn.Module):
68 | def __init__(self, block, num_blocks, num_classes=10):
69 | super(PreActResNet, self).__init__()
70 | self.in_planes = 64
71 |
72 | self.conv1 = nn.Conv2d(3, 64, kernel_size=3, stride=1, padding=1, bias=False)
73 | self.layer1 = self._make_layer(block, 64, num_blocks[0], stride=1)
74 | self.layer2 = self._make_layer(block, 128, num_blocks[1], stride=2)
75 | self.layer3 = self._make_layer(block, 256, num_blocks[2], stride=2)
76 | self.layer4 = self._make_layer(block, 512, num_blocks[3], stride=2)
77 | self.linear = nn.Linear(512*block.expansion, num_classes)
78 |
79 | def _make_layer(self, block, planes, num_blocks, stride):
80 | strides = [stride] + [1]*(num_blocks-1)
81 | layers = []
82 | for stride in strides:
83 | layers.append(block(self.in_planes, planes, stride))
84 | self.in_planes = planes * block.expansion
85 | return nn.Sequential(*layers)
86 |
87 | def forward(self, x):
88 | out = self.conv1(x)
89 | out = self.layer1(out)
90 | out = self.layer2(out)
91 | out = self.layer3(out)
92 | out = self.layer4(out)
93 | out = F.avg_pool2d(out, 4)
94 | out = out.view(out.size(0), -1)
95 | out = self.linear(out)
96 | return out
97 |
98 |
99 | def PreActResNet18():
100 | return PreActResNet(PreActBlock, [2,2,2,2])
101 |
102 | def PreActResNet34():
103 | return PreActResNet(PreActBlock, [3,4,6,3])
104 |
105 | def PreActResNet50():
106 | return PreActResNet(PreActBottleneck, [3,4,6,3])
107 |
108 | def PreActResNet101():
109 | return PreActResNet(PreActBottleneck, [3,4,23,3])
110 |
111 | def PreActResNet152():
112 | return PreActResNet(PreActBottleneck, [3,8,36,3])
113 |
114 |
115 | def test():
116 | net = PreActResNet18()
117 | y = net(Variable(torch.randn(1,3,32,32)))
118 | print(y.size())
119 |
120 | # test()
121 |
--------------------------------------------------------------------------------
/robustnet/models/resnet.py:
--------------------------------------------------------------------------------
1 | '''ResNet in PyTorch.
2 |
3 | For Pre-activation ResNet, see 'preact_resnet.py'.
4 |
5 | Reference:
6 | [1] Kaiming He, Xiangyu Zhang, Shaoqing Ren, Jian Sun
7 | Deep Residual Learning for Image Recognition. arXiv:1512.03385
8 | '''
9 | import torch
10 | import torch.nn as nn
11 | import torch.nn.functional as F
12 |
13 | from torch.autograd import Variable
14 |
15 |
16 | class BasicBlock(nn.Module):
17 | expansion = 1
18 |
19 | def __init__(self, in_planes, planes, stride=1):
20 | super(BasicBlock, self).__init__()
21 | self.conv1 = nn.Conv2d(in_planes, planes, kernel_size=3, stride=stride, padding=1, bias=False)
22 | self.bn1 = nn.BatchNorm2d(planes)
23 | self.conv2 = nn.Conv2d(planes, planes, kernel_size=3, stride=1, padding=1, bias=False)
24 | self.bn2 = nn.BatchNorm2d(planes)
25 |
26 | self.shortcut = nn.Sequential()
27 | if stride != 1 or in_planes != self.expansion*planes:
28 | self.shortcut = nn.Sequential(
29 | nn.Conv2d(in_planes, self.expansion*planes, kernel_size=1, stride=stride, bias=False),
30 | nn.BatchNorm2d(self.expansion*planes)
31 | )
32 |
33 | def forward(self, x):
34 | out = F.relu(self.bn1(self.conv1(x)))
35 | out = self.bn2(self.conv2(out))
36 | out += self.shortcut(x)
37 | out = F.relu(out)
38 | return out
39 |
40 |
41 | class Bottleneck(nn.Module):
42 | expansion = 4
43 |
44 | def __init__(self, in_planes, planes, stride=1):
45 | super(Bottleneck, self).__init__()
46 | self.conv1 = nn.Conv2d(in_planes, planes, kernel_size=1, bias=False)
47 | self.bn1 = nn.BatchNorm2d(planes)
48 | self.conv2 = nn.Conv2d(planes, planes, kernel_size=3, stride=stride, padding=1, bias=False)
49 | self.bn2 = nn.BatchNorm2d(planes)
50 | self.conv3 = nn.Conv2d(planes, self.expansion*planes, kernel_size=1, bias=False)
51 | self.bn3 = nn.BatchNorm2d(self.expansion*planes)
52 |
53 | self.shortcut = nn.Sequential()
54 | if stride != 1 or in_planes != self.expansion*planes:
55 | self.shortcut = nn.Sequential(
56 | nn.Conv2d(in_planes, self.expansion*planes, kernel_size=1, stride=stride, bias=False),
57 | nn.BatchNorm2d(self.expansion*planes)
58 | )
59 |
60 | def forward(self, x):
61 | out = F.relu(self.bn1(self.conv1(x)))
62 | out = F.relu(self.bn2(self.conv2(out)))
63 | out = self.bn3(self.conv3(out))
64 | out += self.shortcut(x)
65 | out = F.relu(out)
66 | return out
67 |
68 |
69 | class ResNet(nn.Module):
70 | def __init__(self, block, num_blocks, num_classes=10):
71 | super(ResNet, self).__init__()
72 | self.in_planes = 64
73 |
74 | self.conv1 = nn.Conv2d(3, 64, kernel_size=3, stride=1, padding=1, bias=False)
75 | self.bn1 = nn.BatchNorm2d(64)
76 | self.layer1 = self._make_layer(block, 64, num_blocks[0], stride=1)
77 | self.layer2 = self._make_layer(block, 128, num_blocks[1], stride=2)
78 | self.layer3 = self._make_layer(block, 256, num_blocks[2], stride=2)
79 | self.layer4 = self._make_layer(block, 512, num_blocks[3], stride=2)
80 | self.linear = nn.Linear(512*block.expansion, num_classes)
81 |
82 | def _make_layer(self, block, planes, num_blocks, stride):
83 | strides = [stride] + [1]*(num_blocks-1)
84 | layers = []
85 | for stride in strides:
86 | layers.append(block(self.in_planes, planes, stride))
87 | self.in_planes = planes * block.expansion
88 | return nn.Sequential(*layers)
89 |
90 | def forward(self, x):
91 | out = F.relu(self.bn1(self.conv1(x)))
92 | out = self.layer1(out)
93 | out = self.layer2(out)
94 | out = self.layer3(out)
95 | out = self.layer4(out)
96 | out = F.avg_pool2d(out, 4)
97 | out = out.view(out.size(0), -1)
98 | out = self.linear(out)
99 | return out
100 |
101 |
102 | def ResNet18():
103 | return ResNet(BasicBlock, [2,2,2,2])
104 |
105 | def ResNet34():
106 | return ResNet(BasicBlock, [3,4,6,3])
107 |
108 | def ResNet50():
109 | return ResNet(Bottleneck, [3,4,6,3])
110 |
111 | def ResNet101():
112 | return ResNet(Bottleneck, [3,4,23,3])
113 |
114 | def ResNet152():
115 | return ResNet(Bottleneck, [3,8,36,3])
116 |
117 |
118 | def test():
119 | net = ResNet18()
120 | y = net(Variable(torch.randn(1,3,32,32)))
121 | print(y.size())
122 |
123 | # test()
124 |
--------------------------------------------------------------------------------
/robustnet/models/resnext.py:
--------------------------------------------------------------------------------
1 | '''ResNeXt in PyTorch.
2 |
3 | See the paper "Aggregated Residual Transformations for Deep Neural Networks" for more details.
4 | '''
5 | import torch
6 | import torch.nn as nn
7 | import torch.nn.functional as F
8 |
9 | from torch.autograd import Variable
10 | from . import layer
11 |
12 | Noise = layer.Noise
13 |
14 | class Block(nn.Module):
15 | '''Grouped convolution block.'''
16 | expansion = 2
17 |
18 | def __init__(self, in_planes, cardinality=32, bottleneck_width=4, stride=1):
19 | super(Block, self).__init__()
20 | group_width = cardinality * bottleneck_width
21 | self.conv1 = nn.Conv2d(in_planes, group_width, kernel_size=1, bias=False)
22 | self.bn1 = nn.BatchNorm2d(group_width)
23 | self.conv2 = nn.Conv2d(group_width, group_width, kernel_size=3, stride=stride, padding=1, groups=cardinality, bias=False)
24 | self.bn2 = nn.BatchNorm2d(group_width)
25 | self.conv3 = nn.Conv2d(group_width, self.expansion*group_width, kernel_size=1, bias=False)
26 | self.bn3 = nn.BatchNorm2d(self.expansion*group_width)
27 |
28 | self.shortcut = nn.Sequential()
29 | if stride != 1 or in_planes != self.expansion*group_width:
30 | self.shortcut = nn.Sequential(
31 | nn.Conv2d(in_planes, self.expansion*group_width, kernel_size=1, stride=stride, bias=False),
32 | nn.BatchNorm2d(self.expansion*group_width)
33 | )
34 |
35 | def forward(self, x):
36 | out = F.relu(self.bn1(self.conv1(x)))
37 | out = F.relu(self.bn2(self.conv2(out)))
38 | out = self.bn3(self.conv3(out))
39 | out += self.shortcut(x)
40 | out = F.relu(out)
41 | return out
42 |
43 |
44 | class ResNeXt(nn.Module):
45 | def __init__(self, num_blocks, cardinality, bottleneck_width, num_classes=10):
46 | super(ResNeXt, self).__init__()
47 | self.cardinality = cardinality
48 | self.bottleneck_width = bottleneck_width
49 | self.in_planes = 64
50 |
51 | self.conv1 = nn.Conv2d(3, 64, kernel_size=1, bias=False)
52 | self.bn1 = nn.BatchNorm2d(64)
53 | self.layer1 = self._make_layer(num_blocks[0], 1)
54 | self.layer2 = self._make_layer(num_blocks[1], 2)
55 | self.layer3 = self._make_layer(num_blocks[2], 2)
56 | # self.layer4 = self._make_layer(num_blocks[3], 2)
57 | self.linear = nn.Linear(cardinality*bottleneck_width*8, num_classes)
58 |
59 | def _make_layer(self, num_blocks, stride):
60 | strides = [stride] + [1]*(num_blocks-1)
61 | layers = []
62 | for stride in strides:
63 | layers.append(Block(self.in_planes, self.cardinality, self.bottleneck_width, stride))
64 | self.in_planes = Block.expansion * self.cardinality * self.bottleneck_width
65 | # Increase bottleneck_width by 2 after each stage.
66 | self.bottleneck_width *= 2
67 | return nn.Sequential(*layers)
68 |
69 | def forward(self, x):
70 | out = F.relu(self.bn1(self.conv1(x)))
71 | out = self.layer1(out)
72 | out = self.layer2(out)
73 | out = self.layer3(out)
74 | # out = self.layer4(out)
75 | out = F.avg_pool2d(out, 8)
76 | out = out.view(out.size(0), -1)
77 | out = self.linear(out)
78 | return out
79 |
80 |
81 | def ResNeXt29_2x64d():
82 | return ResNeXt(num_blocks=[3,3,3], cardinality=2, bottleneck_width=64)
83 |
84 | def ResNeXt29_4x64d():
85 | return ResNeXt(num_blocks=[3,3,3], cardinality=4, bottleneck_width=64)
86 |
87 | def ResNeXt29_8x64d():
88 | return ResNeXt(num_blocks=[3,3,3], cardinality=8, bottleneck_width=64)
89 |
90 | def ResNeXt29_32x4d():
91 | return ResNeXt(num_blocks=[3,3,3], cardinality=32, bottleneck_width=4)
92 |
93 | def test_resnext():
94 | net = ResNeXt29_2x64d()
95 | x = torch.randn(1,3,32,32)
96 | y = net(Variable(x))
97 | print(y.size())
98 |
99 | # test_resnext()
100 |
--------------------------------------------------------------------------------
/robustnet/models/senet.py:
--------------------------------------------------------------------------------
1 | '''SENet in PyTorch.
2 |
3 | SENet is the winner of ImageNet-2017. The paper is not released yet.
4 | '''
5 | import torch
6 | import torch.nn as nn
7 | import torch.nn.functional as F
8 |
9 | from torch.autograd import Variable
10 |
11 |
12 | class BasicBlock(nn.Module):
13 | def __init__(self, in_planes, planes, stride=1):
14 | super(BasicBlock, self).__init__()
15 | self.conv1 = nn.Conv2d(in_planes, planes, kernel_size=3, stride=stride, padding=1, bias=False)
16 | self.bn1 = nn.BatchNorm2d(planes)
17 | self.conv2 = nn.Conv2d(planes, planes, kernel_size=3, stride=1, padding=1, bias=False)
18 | self.bn2 = nn.BatchNorm2d(planes)
19 |
20 | self.shortcut = nn.Sequential()
21 | if stride != 1 or in_planes != planes:
22 | self.shortcut = nn.Sequential(
23 | nn.Conv2d(in_planes, planes, kernel_size=1, stride=stride, bias=False),
24 | nn.BatchNorm2d(planes)
25 | )
26 |
27 | # SE layers
28 | self.fc1 = nn.Conv2d(planes, planes//16, kernel_size=1) # Use nn.Conv2d instead of nn.Linear
29 | self.fc2 = nn.Conv2d(planes//16, planes, kernel_size=1)
30 |
31 | def forward(self, x):
32 | out = F.relu(self.bn1(self.conv1(x)))
33 | out = self.bn2(self.conv2(out))
34 |
35 | # Squeeze
36 | w = F.avg_pool2d(out, out.size(2))
37 | w = F.relu(self.fc1(w))
38 | w = F.sigmoid(self.fc2(w))
39 | # Excitation
40 | out = out * w # New broadcasting feature from v0.2!
41 |
42 | out += self.shortcut(x)
43 | out = F.relu(out)
44 | return out
45 |
46 |
47 | class PreActBlock(nn.Module):
48 | def __init__(self, in_planes, planes, stride=1):
49 | super(PreActBlock, self).__init__()
50 | self.bn1 = nn.BatchNorm2d(in_planes)
51 | self.conv1 = nn.Conv2d(in_planes, planes, kernel_size=3, stride=stride, padding=1, bias=False)
52 | self.bn2 = nn.BatchNorm2d(planes)
53 | self.conv2 = nn.Conv2d(planes, planes, kernel_size=3, stride=1, padding=1, bias=False)
54 |
55 | if stride != 1 or in_planes != planes:
56 | self.shortcut = nn.Sequential(
57 | nn.Conv2d(in_planes, planes, kernel_size=1, stride=stride, bias=False)
58 | )
59 |
60 | # SE layers
61 | self.fc1 = nn.Conv2d(planes, planes//16, kernel_size=1)
62 | self.fc2 = nn.Conv2d(planes//16, planes, kernel_size=1)
63 |
64 | def forward(self, x):
65 | out = F.relu(self.bn1(x))
66 | shortcut = self.shortcut(out) if hasattr(self, 'shortcut') else x
67 | out = self.conv1(out)
68 | out = self.conv2(F.relu(self.bn2(out)))
69 |
70 | # Squeeze
71 | w = F.avg_pool2d(out, out.size(2))
72 | w = F.relu(self.fc1(w))
73 | w = F.sigmoid(self.fc2(w))
74 | # Excitation
75 | out = out * w
76 |
77 | out += shortcut
78 | return out
79 |
80 |
81 | class SENet(nn.Module):
82 | def __init__(self, block, num_blocks, num_classes=10):
83 | super(SENet, self).__init__()
84 | self.in_planes = 64
85 |
86 | self.conv1 = nn.Conv2d(3, 64, kernel_size=3, stride=1, padding=1, bias=False)
87 | self.bn1 = nn.BatchNorm2d(64)
88 | self.layer1 = self._make_layer(block, 64, num_blocks[0], stride=1)
89 | self.layer2 = self._make_layer(block, 128, num_blocks[1], stride=2)
90 | self.layer3 = self._make_layer(block, 256, num_blocks[2], stride=2)
91 | self.layer4 = self._make_layer(block, 512, num_blocks[3], stride=2)
92 | self.linear = nn.Linear(512, num_classes)
93 |
94 | def _make_layer(self, block, planes, num_blocks, stride):
95 | strides = [stride] + [1]*(num_blocks-1)
96 | layers = []
97 | for stride in strides:
98 | layers.append(block(self.in_planes, planes, stride))
99 | self.in_planes = planes
100 | return nn.Sequential(*layers)
101 |
102 | def forward(self, x):
103 | out = F.relu(self.bn1(self.conv1(x)))
104 | out = self.layer1(out)
105 | out = self.layer2(out)
106 | out = self.layer3(out)
107 | out = self.layer4(out)
108 | out = F.avg_pool2d(out, 4)
109 | out = out.view(out.size(0), -1)
110 | out = self.linear(out)
111 | return out
112 |
113 |
114 | def SENet18():
115 | return SENet(PreActBlock, [2,2,2,2])
116 |
117 |
118 | def test():
119 | net = SENet18()
120 | y = net(Variable(torch.randn(1,3,32,32)))
121 | print(y.size())
122 |
123 | # test()
124 |
--------------------------------------------------------------------------------
/robustnet/models/shufflenet.py:
--------------------------------------------------------------------------------
1 | '''ShuffleNet in PyTorch.
2 |
3 | See the paper "ShuffleNet: An Extremely Efficient Convolutional Neural Network for Mobile Devices" for more details.
4 | '''
5 | import torch
6 | import torch.nn as nn
7 | import torch.nn.functional as F
8 |
9 | from torch.autograd import Variable
10 |
11 |
12 | class ShuffleBlock(nn.Module):
13 | def __init__(self, groups):
14 | super(ShuffleBlock, self).__init__()
15 | self.groups = groups
16 |
17 | def forward(self, x):
18 | '''Channel shuffle: [N,C,H,W] -> [N,g,C/g,H,W] -> [N,C/g,g,H,w] -> [N,C,H,W]'''
19 | N,C,H,W = x.size()
20 | g = self.groups
21 | return x.view(N,g,C/g,H,W).permute(0,2,1,3,4).contiguous().view(N,C,H,W)
22 |
23 |
24 | class Bottleneck(nn.Module):
25 | def __init__(self, in_planes, out_planes, stride, groups):
26 | super(Bottleneck, self).__init__()
27 | self.stride = stride
28 |
29 | mid_planes = out_planes/4
30 | g = 1 if in_planes==24 else groups
31 | self.conv1 = nn.Conv2d(in_planes, mid_planes, kernel_size=1, groups=g, bias=False)
32 | self.bn1 = nn.BatchNorm2d(mid_planes)
33 | self.shuffle1 = ShuffleBlock(groups=g)
34 | self.conv2 = nn.Conv2d(mid_planes, mid_planes, kernel_size=3, stride=stride, padding=1, groups=mid_planes, bias=False)
35 | self.bn2 = nn.BatchNorm2d(mid_planes)
36 | self.conv3 = nn.Conv2d(mid_planes, out_planes, kernel_size=1, groups=groups, bias=False)
37 | self.bn3 = nn.BatchNorm2d(out_planes)
38 |
39 | self.shortcut = nn.Sequential()
40 | if stride == 2:
41 | self.shortcut = nn.Sequential(nn.AvgPool2d(3, stride=2, padding=1))
42 |
43 | def forward(self, x):
44 | out = F.relu(self.bn1(self.conv1(x)))
45 | out = self.shuffle1(out)
46 | out = F.relu(self.bn2(self.conv2(out)))
47 | out = self.bn3(self.conv3(out))
48 | res = self.shortcut(x)
49 | out = F.relu(torch.cat([out,res], 1)) if self.stride==2 else F.relu(out+res)
50 | return out
51 |
52 |
53 | class ShuffleNet(nn.Module):
54 | def __init__(self, cfg):
55 | super(ShuffleNet, self).__init__()
56 | out_planes = cfg['out_planes']
57 | num_blocks = cfg['num_blocks']
58 | groups = cfg['groups']
59 |
60 | self.conv1 = nn.Conv2d(3, 24, kernel_size=1, bias=False)
61 | self.bn1 = nn.BatchNorm2d(24)
62 | self.in_planes = 24
63 | self.layer1 = self._make_layer(out_planes[0], num_blocks[0], groups)
64 | self.layer2 = self._make_layer(out_planes[1], num_blocks[1], groups)
65 | self.layer3 = self._make_layer(out_planes[2], num_blocks[2], groups)
66 | self.linear = nn.Linear(out_planes[2], 10)
67 |
68 | def _make_layer(self, out_planes, num_blocks, groups):
69 | layers = []
70 | for i in range(num_blocks):
71 | stride = 2 if i == 0 else 1
72 | cat_planes = self.in_planes if i == 0 else 0
73 | layers.append(Bottleneck(self.in_planes, out_planes-cat_planes, stride=stride, groups=groups))
74 | self.in_planes = out_planes
75 | return nn.Sequential(*layers)
76 |
77 | def forward(self, x):
78 | out = F.relu(self.bn1(self.conv1(x)))
79 | out = self.layer1(out)
80 | out = self.layer2(out)
81 | out = self.layer3(out)
82 | out = F.avg_pool2d(out, 4)
83 | out = out.view(out.size(0), -1)
84 | out = self.linear(out)
85 | return out
86 |
87 |
88 | def ShuffleNetG2():
89 | cfg = {
90 | 'out_planes': [200,400,800],
91 | 'num_blocks': [4,8,4],
92 | 'groups': 2
93 | }
94 | return ShuffleNet(cfg)
95 |
96 | def ShuffleNetG3():
97 | cfg = {
98 | 'out_planes': [240,480,960],
99 | 'num_blocks': [4,8,4],
100 | 'groups': 3
101 | }
102 | return ShuffleNet(cfg)
103 |
104 |
105 | def test():
106 | net = ShuffleNetG2()
107 | x = Variable(torch.randn(1,3,32,32))
108 | y = net(x)
109 | print(y)
110 |
111 | # test()
112 |
--------------------------------------------------------------------------------
/robustnet/models/vgg.py:
--------------------------------------------------------------------------------
1 | '''VGG11/13/16/19 in Pytorch.'''
2 | import torch
3 | import torch.nn as nn
4 | from torch.autograd import Variable
5 | from . import layer
6 |
7 | Noise = layer.Noise
8 |
9 | cfg = {
10 | 'VGG11': [64, 'M', 128, 'M', 256, 256, 'M', 512, 512, 'M', 512, 512, 'M'],
11 | 'VGG13': [64, 64, 'M', 128, 128, 'M', 256, 256, 'M', 512, 512, 'M', 512, 512, 'M'],
12 | 'VGG16': [64, 64, 'M', 128, 128, 'M', 256, 256, 256, 'M', 512, 512, 512, 'M', 512, 512, 512, 'M'],
13 | 'VGG19': [64, 64, 'M', 128, 128, 'M', 256, 256, 256, 256, 'M', 512, 512, 512, 512, 'M', 512, 512, 512, 512, 'M'],
14 | }
15 |
16 |
17 | class VGG(nn.Module):
18 | def __init__(self, vgg_name, std):
19 | super(VGG, self).__init__()
20 | self.std = std
21 | self.features = self._make_layers(cfg[vgg_name])
22 | self.classifier = nn.Linear(512, 10)
23 | self.init_noise = Noise(std)
24 |
25 | def forward(self, x):
26 | out = self.features(x)
27 | out = out.view(out.size(0), -1)
28 | out = self.init_noise(out)
29 | out = self.classifier(out)
30 | return out
31 |
32 | def _make_layers(self, cfg):
33 | layers = []
34 | in_channels = 3
35 | for x in cfg:
36 | if x == 'M':
37 | layers += [nn.MaxPool2d(kernel_size=2, stride=2)]
38 | else:
39 | layers += [nn.Conv2d(in_channels, x, kernel_size=3, padding=1),
40 | Noise(self.std),
41 | nn.BatchNorm2d(x),
42 | nn.ReLU(inplace=True)]
43 | in_channels = x
44 | layers += [nn.AvgPool2d(kernel_size=1, stride=1)]
45 | return nn.Sequential(*layers)
46 |
47 | # net = VGG('VGG11')
48 | # x = torch.randn(2,3,32,32)
49 | # print(net(Variable(x)).size())
50 |
--------------------------------------------------------------------------------
/robustnet/plot_accu.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python3
2 |
3 | import numpy as np
4 | import matplotlib.pyplot as plt
5 |
6 |
7 | def parse_line(l):
8 | train = float(l.split(',')[2].split(':')[1].strip())
9 | test = float(l.split(',')[4].split(':')[1].strip())
10 | return train, test
11 |
12 | def read_f(fn):
13 | train_noise = []
14 | test_noise = []
15 | for l in open(fn, 'r'):
16 | if l[0] != '[':
17 | continue
18 | train, test = parse_line(l)
19 | train_noise.append(train)
20 | test_noise.append(test)
21 | return train_noise, test_noise
22 |
23 |
24 | def data():
25 | model = "./vgg16/"
26 | noise_level = ["0", "0.1", "0.2", "0.3"]
27 | level_color = ['firebrick', 'olivedrab', 'deepskyblue', 'darkorchid']
28 | dataf = [model + 'log_noise_{}.txt'.format(level) for level in noise_level]
29 | data = {}
30 | for i, level in enumerate(noise_level):
31 | data_level = {'train': [], 'test': []}
32 | f = dataf[i]
33 | train_noise, test_noise = read_f(f)
34 | data_level['train'] = train_noise
35 | data_level['test'] = test_noise
36 | data[level] = data_level
37 |
38 | for col, level in zip(level_color, noise_level):
39 | plt.plot(100 - 100 * np.array(data[level]['train']), color=col, linestyle='-', label='train, noise='+level)
40 | plt.plot(100 - 100 * np.array(data[level]['test']), color=col, linestyle='--', label='test, noise='+level)
41 | plt.legend()
42 | plt.ylim(0, 30)
43 | plt.show()
44 |
45 | if __name__ == "__main__":
46 | data()
47 |
--------------------------------------------------------------------------------
/robustnet/run.sh:
--------------------------------------------------------------------------------
1 | model=vgg16
2 | noise=0.3
3 | CUDA_VISIBLE_DEVICES=3 ./main2.py --lr 0.1 --noise ${noise} --modelOut ./${model}/noise_${noise}.pth > ./${model}/log_noise_${noise}.txt
4 |
5 |
--------------------------------------------------------------------------------
/robustnet/test.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python3
2 |
3 | import argparse
4 | import numpy as np
5 | import torch
6 | import torch.optim as optim
7 | import torch.nn as nn
8 | from torch.autograd import Variable
9 | import torchvision.datasets as dst
10 | import torchvision.transforms as tfs
11 | from models import *
12 | from torch.utils.data import DataLoader
13 | import time
14 |
15 | def accuracy(dataloader, net):
16 | data_iter = iter(dataloader)
17 | count = 0
18 | total = 0
19 | for x, y in data_iter:
20 | vx = Variable(x, volatile=True).cuda()
21 | tmp = torch.sum(torch.eq(y.cuda(), torch.max(net(vx), dim=1)[1]).data)
22 | count += int(tmp)
23 | total += y.size()[0]
24 | return count / total
25 |
26 | def loss(dataloader, net, loss_f):
27 | data_iter = iter(dataloader)
28 | total_loss = 0.0
29 | count = 0
30 | for x, y in data_iter:
31 | vx = Variable(x, volatile=True).cuda()
32 | vy = Variable(y).cuda()
33 | total_loss += torch.sum(loss_f(net(vx), vy).data)
34 | count += y.size()[0]
35 | return total_loss / count
36 |
37 | def train_other(dataloader_test, net, loss_f, lr, name='adam', max_epoch=10):
38 | run_time = 0.0
39 | for epoch in range(max_epoch):
40 | beg = time.time()
41 | run_time += time.time() - beg
42 | print("[Epoch {}] Time: {}, Test loss: {}, Test accuracy: {}".format(epoch, run_time, loss(dataloader_test, net, loss_f), accuracy(dataloader_test, net)))
43 |
44 |
45 | def weights_init(m):
46 | classname = m.__class__.__name__
47 | if classname.find('Linear') != -1:
48 | m.weight.data.normal_(0.0, 0.02)
49 | elif classname.find('Conv') != -1:
50 | m.weight.data.normal_(0.0, 0.02)
51 | elif classname.find('BatchNorm') != -1 and m.affine:
52 | m.weight.data.normal_(1.0, 0.02)
53 | m.bias.data.fill_(0)
54 |
55 | def main():
56 | parser = argparse.ArgumentParser()
57 | parser.add_argument('--batchSize', type=int, default=20)
58 | parser.add_argument('--epoch', type=int, default=300)
59 | parser.add_argument('--lr', type=float, default=1.0)
60 | parser.add_argument('--ngpu', type=int, default=1)
61 | parser.add_argument('--modelIn', type=str, default=None)
62 | parser.add_argument('--modelOut', type=str, default=None)
63 | parser.add_argument('--method', type=str, default="momsgd")
64 | parser.add_argument('--noise', type=float, default=0.0)
65 | opt = parser.parse_args()
66 | print(opt)
67 | net = VGG("VGG16", opt.noise)
68 | #net = densenet_cifar()
69 | #net = GoogLeNet()
70 | #net = MobileNet(num_classes=100)
71 | #net = stl10(32)
72 | net = nn.DataParallel(net, device_ids=range(opt.ngpu))
73 | #net = Test()
74 | net.apply(weights_init)
75 | if opt.modelIn is not None:
76 | net.load_state_dict(torch.load(opt.modelIn))
77 | loss_f = nn.CrossEntropyLoss()
78 | net.cuda()
79 | loss_f.cuda()
80 |
81 | net.eval()
82 | transform_test = tfs.Compose([
83 | tfs.ToTensor(),
84 | tfs.Normalize((0.4914, 0.4822, 0.4465), (0.2023, 0.1994, 0.2010)),
85 | ])
86 |
87 | data_test = dst.CIFAR10("../cifar10_data", download=True, train=False, transform=transform_test)
88 | assert data_test
89 | dataloader_test = DataLoader(data_test, batch_size=opt.batchSize, shuffle=False, num_workers=2)
90 | for period in range(opt.epoch // 100):
91 | train_other(dataloader_test, net, loss_f, opt.lr, opt.method, 100)
92 | opt.lr /= 10
93 | # save model
94 | if opt.modelOut is not None:
95 | torch.save(net.state_dict(), opt.modelOut)
96 |
97 | if __name__ == "__main__":
98 | main()
99 |
--------------------------------------------------------------------------------
/robustnet/utils.py:
--------------------------------------------------------------------------------
1 | '''Some helper functions for PyTorch, including:
2 | - get_mean_and_std: calculate the mean and std value of dataset.
3 | - msr_init: net parameter initialization.
4 | - progress_bar: progress bar mimic xlua.progress.
5 | '''
6 | import os
7 | import sys
8 | import time
9 | import math
10 |
11 | import torch.nn as nn
12 | import torch.nn.init as init
13 |
14 |
15 | def get_mean_and_std(dataset):
16 | '''Compute the mean and std value of dataset.'''
17 | dataloader = torch.utils.data.DataLoader(dataset, batch_size=1, shuffle=True, num_workers=2)
18 | mean = torch.zeros(3)
19 | std = torch.zeros(3)
20 | print('==> Computing mean and std..')
21 | for inputs, targets in dataloader:
22 | for i in range(3):
23 | mean[i] += inputs[:,i,:,:].mean()
24 | std[i] += inputs[:,i,:,:].std()
25 | mean.div_(len(dataset))
26 | std.div_(len(dataset))
27 | return mean, std
28 |
29 | def init_params(net):
30 | '''Init layer parameters.'''
31 | for m in net.modules():
32 | if isinstance(m, nn.Conv2d):
33 | init.kaiming_normal(m.weight, mode='fan_out')
34 | if m.bias:
35 | init.constant(m.bias, 0)
36 | elif isinstance(m, nn.BatchNorm2d):
37 | init.constant(m.weight, 1)
38 | init.constant(m.bias, 0)
39 | elif isinstance(m, nn.Linear):
40 | init.normal(m.weight, std=1e-3)
41 | if m.bias:
42 | init.constant(m.bias, 0)
43 |
44 |
45 |
46 | TOTAL_BAR_LENGTH = 65.
47 | last_time = time.time()
48 | begin_time = last_time
49 |
50 | def format_time(seconds):
51 | days = int(seconds / 3600/24)
52 | seconds = seconds - days*3600*24
53 | hours = int(seconds / 3600)
54 | seconds = seconds - hours*3600
55 | minutes = int(seconds / 60)
56 | seconds = seconds - minutes*60
57 | secondsf = int(seconds)
58 | seconds = seconds - secondsf
59 | millis = int(seconds*1000)
60 |
61 | f = ''
62 | i = 1
63 | if days > 0:
64 | f += str(days) + 'D'
65 | i += 1
66 | if hours > 0 and i <= 2:
67 | f += str(hours) + 'h'
68 | i += 1
69 | if minutes > 0 and i <= 2:
70 | f += str(minutes) + 'm'
71 | i += 1
72 | if secondsf > 0 and i <= 2:
73 | f += str(secondsf) + 's'
74 | i += 1
75 | if millis > 0 and i <= 2:
76 | f += str(millis) + 'ms'
77 | i += 1
78 | if f == '':
79 | f = '0ms'
80 | return f
81 |
--------------------------------------------------------------------------------
/robustnet/utils2.py:
--------------------------------------------------------------------------------
1 | '''Some helper functions for PyTorch, including:
2 | - get_mean_and_std: calculate the mean and std value of dataset.
3 | - msr_init: net parameter initialization.
4 | - progress_bar: progress bar mimic xlua.progress.
5 | '''
6 | import os
7 | import sys
8 | import time
9 | import math
10 |
11 | import torch.nn as nn
12 | import torch.nn.init as init
13 |
14 |
15 | def get_mean_and_std(dataset):
16 | '''Compute the mean and std value of dataset.'''
17 | dataloader = torch.utils.data.DataLoader(dataset, batch_size=1, shuffle=True, num_workers=2)
18 | mean = torch.zeros(3)
19 | std = torch.zeros(3)
20 | print('==> Computing mean and std..')
21 | for inputs, targets in dataloader:
22 | for i in range(3):
23 | mean[i] += inputs[:,i,:,:].mean()
24 | std[i] += inputs[:,i,:,:].std()
25 | mean.div_(len(dataset))
26 | std.div_(len(dataset))
27 | return mean, std
28 |
29 | def init_params(net):
30 | '''Init layer parameters.'''
31 | for m in net.modules():
32 | if isinstance(m, nn.Conv2d):
33 | init.kaiming_normal(m.weight, mode='fan_out')
34 | if m.bias:
35 | init.constant(m.bias, 0)
36 | elif isinstance(m, nn.BatchNorm2d):
37 | init.constant(m.weight, 1)
38 | init.constant(m.bias, 0)
39 | elif isinstance(m, nn.Linear):
40 | init.normal(m.weight, std=1e-3)
41 | if m.bias:
42 | init.constant(m.bias, 0)
43 |
44 |
45 | _, term_width = os.popen('stty size', 'r').read().split()
46 | term_width = int(term_width)
47 |
48 | TOTAL_BAR_LENGTH = 65.
49 | last_time = time.time()
50 | begin_time = last_time
51 | def progress_bar(current, total, msg=None):
52 | global last_time, begin_time
53 | if current == 0:
54 | begin_time = time.time() # Reset for new bar.
55 |
56 | cur_len = int(TOTAL_BAR_LENGTH*current/total)
57 | rest_len = int(TOTAL_BAR_LENGTH - cur_len) - 1
58 |
59 | sys.stdout.write(' [')
60 | for i in range(cur_len):
61 | sys.stdout.write('=')
62 | sys.stdout.write('>')
63 | for i in range(rest_len):
64 | sys.stdout.write('.')
65 | sys.stdout.write(']')
66 |
67 | cur_time = time.time()
68 | step_time = cur_time - last_time
69 | last_time = cur_time
70 | tot_time = cur_time - begin_time
71 |
72 | L = []
73 | L.append(' Step: %s' % format_time(step_time))
74 | L.append(' | Tot: %s' % format_time(tot_time))
75 | if msg:
76 | L.append(' | ' + msg)
77 |
78 | msg = ''.join(L)
79 | sys.stdout.write(msg)
80 | for i in range(term_width-int(TOTAL_BAR_LENGTH)-len(msg)-3):
81 | sys.stdout.write(' ')
82 |
83 | # Go back to the center of the bar.
84 | for i in range(term_width-int(TOTAL_BAR_LENGTH/2)+2):
85 | sys.stdout.write('\b')
86 | sys.stdout.write(' %d/%d ' % (current+1, total))
87 |
88 | if current < total-1:
89 | sys.stdout.write('\r')
90 | else:
91 | sys.stdout.write('\n')
92 | sys.stdout.flush()
93 |
94 | def format_time(seconds):
95 | days = int(seconds / 3600/24)
96 | seconds = seconds - days*3600*24
97 | hours = int(seconds / 3600)
98 | seconds = seconds - hours*3600
99 | minutes = int(seconds / 60)
100 | seconds = seconds - minutes*60
101 | secondsf = int(seconds)
102 | seconds = seconds - secondsf
103 | millis = int(seconds*1000)
104 |
105 | f = ''
106 | i = 1
107 | if days > 0:
108 | f += str(days) + 'D'
109 | i += 1
110 | if hours > 0 and i <= 2:
111 | f += str(hours) + 'h'
112 | i += 1
113 | if minutes > 0 and i <= 2:
114 | f += str(minutes) + 'm'
115 | i += 1
116 | if secondsf > 0 and i <= 2:
117 | f += str(secondsf) + 's'
118 | i += 1
119 | if millis > 0 and i <= 2:
120 | f += str(millis) + 'ms'
121 | i += 1
122 | if f == '':
123 | f = '0ms'
124 | return f
125 |
--------------------------------------------------------------------------------
/sap/README.md:
--------------------------------------------------------------------------------
1 | # Stochastic activation pruning for robust adversarial defense
2 |
3 | Paper: [Dhillon et al. 2018](https://openreview.net/pdf?id=H1uR4GZRZ)
4 | ## Requirements
5 |
6 | * Python3 + tensorflow
7 |
8 | ## [NATTACK] evaluation
9 |
10 | Run with:
11 |
12 | ```bash
13 | python re_li_attack.py --cifar-path
14 | ````
15 |
16 | [robustml]: https://github.com/robust-ml/robustml
17 |
--------------------------------------------------------------------------------
/sap/evaluation.py:
--------------------------------------------------------------------------------
1 | import robustml
2 | import pickle
3 | from robustml_model import SAP
4 | import sys
5 | import argparse
6 | import tensorflow as tf
7 | import numpy as np
8 | from helpers import *
9 | import time
10 | import os
11 | import cv2
12 |
13 |
14 | npop = 300 # population size
15 | sigma = 0.1 # noise standard deviation
16 | alpha = 0.008 # learning rate
17 | # alpha = 0.001 # learning rate
18 | boxmin = 0
19 | boxmax = 1
20 | boxplus = (boxmin + boxmax) / 2.
21 | boxmul = (boxmax - boxmin) / 2.
22 | folder = './liclipadvImages/'
23 | epsi = 0.031
24 |
25 | def main():
26 |
27 | parser = argparse.ArgumentParser()
28 | parser.add_argument('--cifar-path', type=str, default='../cifar10_data/test_batch',
29 | help='path to the test_batch file from http://www.cs.toronto.edu/~kriz/cifar-10-python.tar.gz')
30 | parser.add_argument('--perturb', type=str, default='perturb')
31 | parser.add_argument('--start', type=int, default=0)
32 | parser.add_argument('--end', type=int, default=100)
33 | parser.add_argument('--debug', action='store_true')
34 | args = parser.parse_args()
35 |
36 | test_loss = 0
37 | correct = 0
38 | total = 0
39 | totalImages = 0
40 | succImages = 0
41 | faillist = []
42 |
43 |
44 |
45 | # set up TensorFlow session
46 |
47 | config = tf.ConfigProto()
48 | config.gpu_options.allow_growth = True
49 | sess = tf.Session(config=config)
50 |
51 |
52 | # initialize a model
53 | model = SAP(sess)
54 |
55 | # initialize an attack (it's a white box attack, and it's allowed to look
56 | # at the internals of the model in any way it wants)
57 | # attack = BPDA(sess, model, epsilon=model.threat_model.epsilon, debug=args.debug)
58 | # attack = Attack(sess, model.model, epsilon=model.threat_model.epsilon)
59 |
60 | # initialize a data provider for CIFAR-10 images
61 | provider = robustml.provider.CIFAR10(args.cifar_path)
62 | input_xs = tf.placeholder(tf.float32, [None, 32, 32, 3])
63 | start = 0
64 | end = 10000
65 | total = 0
66 | real_logits_pre = model.model(input_xs)
67 | real_logits = tf.nn.softmax(real_logits_pre)
68 | successlist = []
69 | printlist = []
70 |
71 | start_time = time.time()
72 | perturbs = os.listdir('./')
73 | all_dir = []
74 | for x in perturbs:
75 | if 'perturb' in x:
76 | all_dir.append(x)
77 |
78 |
79 | for y in all_dir:
80 | perturb_files = os.listdir(y)
81 | numbers = []
82 | totalImages = 0
83 | succImages = 0
84 |
85 | perturb_files = os.listdir(y)
86 | numbers = []
87 | for x in perturb_files:
88 | number = x.split('_')[1]
89 | name = x.split('_')[0]
90 | number1 = int(number.split('.pkl')[0])
91 | numbers.append(number1)
92 |
93 | for i in numbers:
94 | success = False
95 | print('evaluating %d of [%d, %d)' % (i, start, end), file=sys.stderr)
96 | inputs, targets= provider[i]
97 | modify = np.random.randn(1,3,32,32) * 0.001
98 | in_pkl = y + '/'+name + '_' + str(i)+'.pkl'
99 | ##### thermometer encoding
100 |
101 | logits = sess.run(real_logits,feed_dict={input_xs: [inputs]})
102 | if np.argmax(logits) != targets:
103 | print('skip the wrong example ', i)
104 | continue
105 | totalImages += 1
106 | try:
107 | modify = pickle.load(open(in_pkl, 'rb'))
108 | except:
109 | modify = pickle.load(open(in_pkl,'rb'),encoding='bytes')
110 | if 'cascade' in in_pkl:
111 | modify = cv2.resize(modify[0].transpose(1, 2, 0), dsize=(32, 32), interpolation=cv2.INTER_LINEAR)
112 | modify = modify.transpose(2, 0, 1)
113 | modify = modify.reshape((1,3,32,32))
114 | newimg = torch_arctanh((inputs - boxplus) / boxmul).transpose(2, 0, 1)
115 | realinputimg = np.tanh(newimg + modify) * boxmul + boxplus
116 | realdist = realinputimg - (np.tanh(newimg) * boxmul + boxplus)
117 | realclipdist = np.clip(realdist, -epsi, epsi)
118 | realclipinput = realclipdist + (np.tanh(newimg) * boxmul + boxplus)
119 | l2real = np.sum((realclipinput - (np.tanh(newimg) * boxmul + boxplus)) ** 2) ** 0.5
120 | outputsreal = sess.run(real_logits, feed_dict={input_xs: realclipinput.transpose(0, 2, 3, 1)})
121 | if (np.argmax(outputsreal) != targets) and (np.abs(realclipdist).max() <= epsi):
122 | succImages += 1
123 |
124 | success_rate = succImages / float(totalImages)
125 | print('name:',y)
126 | print('succ rate', success_rate)
127 | print('succ {} , total {}'.format(succImages, totalImages))
128 |
129 |
130 | if __name__ == '__main__':
131 | main()
132 |
--------------------------------------------------------------------------------
/sap/evaluation_bpda.py:
--------------------------------------------------------------------------------
1 | import robustml
2 | import pickle
3 | from robustml_model import SAP
4 | import sys
5 | import argparse
6 | import tensorflow as tf
7 | import numpy as np
8 | from helpers import *
9 | import time
10 | import os
11 | import cv2
12 |
13 |
14 | npop = 300 # population size
15 | sigma = 0.1 # noise standard deviation
16 | alpha = 0.008 # learning rate
17 | # alpha = 0.001 # learning rate
18 | boxmin = 0
19 | boxmax = 1
20 | boxplus = (boxmin + boxmax) / 2.
21 | boxmul = (boxmax - boxmin) / 2.
22 | folder = './liclipadvImages/'
23 | epsi = 0.032
24 |
25 | def main():
26 |
27 | parser = argparse.ArgumentParser()
28 | parser.add_argument('--cifar-path', type=str, default='../cifar10_data/test_batch',
29 | help='path to the test_batch file from http://www.cs.toronto.edu/~kriz/cifar-10-python.tar.gz')
30 | parser.add_argument('--perturb', type=str, default='perturb')
31 | parser.add_argument('--start', type=int, default=0)
32 | parser.add_argument('--end', type=int, default=100)
33 | parser.add_argument('--debug', action='store_true')
34 | args = parser.parse_args()
35 |
36 | test_loss = 0
37 | correct = 0
38 | total = 0
39 | totalImages = 0
40 | succImages = 0
41 | faillist = []
42 |
43 |
44 |
45 | # set up TensorFlow session
46 |
47 | config = tf.ConfigProto()
48 | config.gpu_options.allow_growth = True
49 | sess = tf.Session(config=config)
50 |
51 |
52 | # initialize a model
53 | model = SAP(sess)
54 |
55 | # initialize an attack (it's a white box attack, and it's allowed to look
56 | # at the internals of the model in any way it wants)
57 | # attack = BPDA(sess, model, epsilon=model.threat_model.epsilon, debug=args.debug)
58 | # attack = Attack(sess, model.model, epsilon=model.threat_model.epsilon)
59 |
60 | # initialize a data provider for CIFAR-10 images
61 | provider = robustml.provider.CIFAR10(args.cifar_path)
62 | input_xs = tf.placeholder(tf.float32, [None, 32, 32, 3])
63 | start = 0
64 | end = 10000
65 | total = 0
66 | real_logits_pre = model.model(input_xs)
67 | real_logits = tf.nn.softmax(real_logits_pre)
68 | successlist = []
69 | printlist = []
70 |
71 | start_time = time.time()
72 | perturbs = os.listdir('./')
73 | all_dir = []
74 | for x in perturbs:
75 | if 'perturb' in x:
76 | all_dir.append(x)
77 |
78 |
79 | for y in all_dir:
80 | perturb_files = os.listdir(y)
81 | numbers = []
82 | totalImages = 0
83 | succImages = 0
84 |
85 | perturb_files = os.listdir(y)
86 | numbers = []
87 | for x in perturb_files:
88 |
89 | number = x.split('_')[-1]
90 | name = x.split('_')[0]
91 | number1 = int(number.split('.pkl')[0])
92 |
93 | numbers.append(number1)
94 |
95 | for i in numbers:
96 | success = False
97 | print('evaluating %d of [%d, %d)' % (i, start, end), file=sys.stderr)
98 | inputs, targets= provider[i]
99 | modify = np.random.randn(1,3,32,32) * 0.001
100 | in_pkl = y + '/'+name + '_' + str(i)+'.pkl'
101 | ##### thermometer encoding
102 |
103 | logits = sess.run(real_logits,feed_dict={input_xs: [inputs]})
104 | if np.argmax(logits) != targets:
105 | print('skip the wrong example ', i)
106 | continue
107 | totalImages += 1
108 | try:
109 | modify = pickle.load(open(in_pkl, 'rb'))
110 | except:
111 | modify = pickle.load(open(in_pkl,'rb'),encoding='bytes')
112 | # if 'cascade' in in_pkl:
113 | # modify = cv2.resize(modify[0].transpose(1, 2, 0), dsize=(32, 32), interpolation=cv2.INTER_LINEAR)
114 | # modify = modify.transpose(2, 0, 1)
115 | # modify = modify.reshape((1,3,32,32))
116 | realclipinput = modify.reshape(1,32,32,3)+0.5
117 | realclipdist = realclipinput - inputs
118 | print(np.abs(realclipdist).max())
119 | outputsreal = sess.run(real_logits, feed_dict={input_xs: realclipinput})
120 | # print('logits ',np.argmax(outputsreal))
121 | # print('targets ',targets)
122 | if (np.argmax(outputsreal) != targets) and (np.abs(realclipdist).max() <= epsi):
123 | succImages += 1
124 |
125 | success_rate = succImages / float(totalImages)
126 | print('name:',y)
127 | print('succ rate', success_rate)
128 | print('succ {} , total {}'.format(succImages, totalImages))
129 |
130 |
131 | if __name__ == '__main__':
132 | main()
133 |
--------------------------------------------------------------------------------
/sap/helpers.py:
--------------------------------------------------------------------------------
1 | import operator as op
2 | import functools as ft
3 | import numpy as np
4 |
5 |
6 | '''reduce_* helper functions reduce tensors on all dimensions but the first.
7 | They are intended to be used on batched tensors where dim 0 is the batch dim.
8 | '''
9 |
10 |
11 | def reduce_sum(x, keepdim=True):
12 | # silly PyTorch, when will you get proper reducing sums/means?
13 | for a in reversed(range(1, x.dim())):
14 | x = x.sum(a, keepdim=keepdim)
15 | return x
16 |
17 |
18 | def reduce_mean(x, keepdim=True):
19 | numel = ft.reduce(op.mul, x.size()[1:])
20 | x = reduce_sum(x, keepdim=keepdim)
21 | return x / numel
22 |
23 |
24 | def reduce_min(x, keepdim=True):
25 | for a in reversed(range(1, x.dim())):
26 | x = x.min(a, keepdim=keepdim)[0]
27 | return x
28 |
29 |
30 | def reduce_max(x, keepdim=True):
31 | for a in reversed(range(1, x.dim())):
32 | x = x.max(a, keepdim=keepdim)[0]
33 | return x
34 |
35 |
36 | def torch_arctanh(x, eps=1e-6):
37 | x *= (1. - eps)
38 | return (np.log((1 + x) / (1 - x))) * 0.5
39 |
40 |
41 | def l2r_dist(x, y, keepdim=True, eps=1e-8):
42 | d = (x - y)**2
43 | d = reduce_sum(d, keepdim=keepdim)
44 | d += eps # to prevent infinite gradient at 0
45 | return d.sqrt()
46 |
47 |
48 | def l2_dist(x, y, keepdim=True):
49 | d = (x - y)**2
50 | return reduce_sum(d, keepdim=keepdim)
51 |
52 |
53 | def l1_dist(x, y, keepdim=True):
54 | d = torch.abs(x - y)
55 | return reduce_sum(d, keepdim=keepdim)
56 |
57 |
58 | def l2_norm(x, keepdim=True):
59 | norm = reduce_sum(x*x, keepdim=keepdim)
60 | return norm.sqrt()
61 |
62 |
63 | def l1_norm(x, keepdim=True):
64 | return reduce_sum(x.abs(), keepdim=keepdim)
65 |
66 |
67 | def rescale(x, x_min=-1., x_max=1.):
68 | return x * (x_max - x_min) + x_min
69 |
70 |
71 | def tanh_rescale(x, x_min=-1., x_max=1.):
72 | return (torch.tanh(x) + 1) * 0.5 * (x_max - x_min) + x_min
73 |
--------------------------------------------------------------------------------
/sap/robustml_attack.py:
--------------------------------------------------------------------------------
1 | import robustml
2 | from robustml_model import SAP
3 | print(robustml.__file__)
4 | import sys
5 | import argparse
6 | import tensorflow as tf
7 | import numpy as np
8 | import time
9 |
10 | class Attack:
11 | def __init__(self, sess, model, epsilon, tol=1, num_steps=500, step_size=.1, random_start=False):
12 | self._sess = sess
13 | self.model = model
14 | self.tol = tol
15 | self.num_steps = num_steps
16 | self.step_size = step_size
17 | self.rand = random_start
18 |
19 | self.xs = tf.Variable(np.zeros((1, 32, 32, 3), dtype=np.float32),
20 | name='modifier')
21 | self.orig_xs = tf.placeholder(tf.float32, [None, 32, 32, 3])
22 |
23 | self.ys = tf.placeholder(tf.int32, [None])
24 |
25 | self.epsilon = epsilon * 255
26 |
27 | delta = tf.clip_by_value(self.xs, 0, 255) - self.orig_xs
28 | delta = tf.clip_by_value(delta, -self.epsilon, self.epsilon)
29 |
30 | self.do_clip_xs = tf.assign(self.xs, self.orig_xs+delta)
31 |
32 | self.logits = logits = model(self.xs)
33 |
34 | label_mask = tf.one_hot(self.ys, 10)
35 | correct_logit = tf.reduce_sum(label_mask * logits, axis=1)
36 | wrong_logit = tf.reduce_max((1-label_mask) * logits - 1e4*label_mask, axis=1)
37 |
38 | self.loss = (correct_logit - wrong_logit)
39 |
40 | start_vars = set(x.name for x in tf.global_variables())
41 | optimizer = tf.train.AdamOptimizer(step_size*1)
42 |
43 | grad,var = optimizer.compute_gradients(self.loss, [self.xs])[0]
44 | self.train = optimizer.apply_gradients([(tf.sign(grad),var)])
45 |
46 | end_vars = tf.global_variables()
47 | self.new_vars = [x for x in end_vars if x.name not in start_vars]
48 |
49 | def perturb(self, x, y, sess):
50 | sess.run(tf.variables_initializer(self.new_vars))
51 | sess.run(self.xs.initializer)
52 | sess.run(self.do_clip_xs,
53 | {self.orig_xs: x})
54 |
55 | for i in range(self.num_steps):
56 |
57 | sess.run(self.train, feed_dict={self.ys: y})
58 | sess.run(self.do_clip_xs,
59 | {self.orig_xs: x})
60 |
61 | return sess.run(self.xs)
62 |
63 | def run(self, x, y, target):
64 | if target is not None:
65 | raise NotImplementedError
66 | return self.perturb(np.array([x]) * 255.0, [y], self._sess)[0] / 255.0
67 |
68 | def main():
69 | parser = argparse.ArgumentParser()
70 | parser.add_argument('--cifar-path', type=str, required=True,
71 | help='path to the test_batch file from http://www.cs.toronto.edu/~kriz/cifar-10-python.tar.gz')
72 | parser.add_argument('--start', type=int, default=170)
73 | parser.add_argument('--end', type=int, default=1000)
74 | parser.add_argument('--debug', action='store_true')
75 | args = parser.parse_args()
76 | config = tf.ConfigProto()
77 | config.gpu_options.allow_growth = True
78 | sess = tf.Session(config=config)
79 | # set up TensorFlow session
80 | # sess = tf.Session()
81 |
82 | # initialize a model
83 | model = SAP(sess)
84 |
85 | # initialize an attack (it's a white box attack, and it's allowed to look
86 | # at the internals of the model in any way it wants)
87 | # attack = BPDA(sess, model, epsilon=model.threat_model.epsilon, debug=args.debug)
88 | attack_start = time.time()
89 | attack = Attack(sess, model.model, epsilon=model.threat_model.epsilon)
90 |
91 | # initialize a data provider for CIFAR-10 images
92 | provider = robustml.provider.CIFAR10(args.cifar_path)
93 |
94 | success_rate = robustml.evaluate.evaluate(
95 | model,
96 | attack,
97 | provider,
98 | start=args.start,
99 | end=args.end,
100 | deterministic=True,
101 | debug=args.debug,
102 | )
103 |
104 | print('attack success rate: %.2f%% (over %d data points)' % (success_rate*100, args.end-args.start))
105 | print('attack time : ', time.time()-attack_start,flush=True)
106 |
107 |
108 | if __name__ == '__main__':
109 | main()
110 |
--------------------------------------------------------------------------------
/sap/robustml_model.py:
--------------------------------------------------------------------------------
1 | import robustml
2 | import tensorflow as tf
3 | import numpy as np
4 | from sap_model import SAPModel
5 |
6 | class SAP(robustml.model.Model):
7 | def __init__(self, sess):
8 | self._sess = sess
9 |
10 | self._model = SAPModel(
11 | '../all_models/standard/',
12 | tiny=False,
13 | mode='eval',
14 | sess=sess,
15 | )
16 |
17 | self._dataset = robustml.dataset.CIFAR10()
18 | self._threat_model = robustml.threat_model.Linf(epsilon=8.0/255.0)
19 |
20 | @property
21 | def dataset(self):
22 | return self._dataset
23 |
24 | @property
25 | def threat_model(self):
26 | return self._threat_model
27 |
28 | def classify(self, x):
29 | x = x * 255.0
30 | # first encode the input, then classify it
31 | return self._sess.run(self._model.predictions, {self._model.x_input: [x]})[0]
32 |
33 | # expose internals for white box attacks
34 |
35 | @property
36 | def model(self):
37 | return self._model
38 |
--------------------------------------------------------------------------------
/sap/sap_model.py:
--------------------------------------------------------------------------------
1 | import tensorflow as tf
2 | import numpy as np
3 |
4 | from cifar_model import Model
5 |
6 | class SAPModel(Model):
7 | image_size = 32
8 | num_labels = 10
9 | num_channels = 3
10 |
11 | def __init__(self, *args, **kwargs):
12 | if 'fix' in kwargs:
13 | self.fix_randomness = kwargs['fix'] == True
14 | del kwargs['fix']
15 | else:
16 | self.fix_randomness = False
17 | super().__init__(*args, **kwargs)
18 |
19 | def _conv(self, name, x, filter_size, in_filters, out_filters, strides):
20 | r = super()._conv(name, x, filter_size, in_filters, out_filters, strides)
21 | r = tf.check_numerics(r, "okay")
22 | p = tf.abs(r)/tf.reduce_sum(tf.abs(r), axis=(1,2,3), keep_dims=True)
23 | w,h,c = p.get_shape().as_list()[1:]
24 | N = w*h*c*2
25 | if self.fix_randomness:
26 | p_keep = 1-tf.exp(-N*p)
27 | rand = tf.constant(np.random.uniform(size=(p_keep.shape[0],w,h,c)),
28 | dtype=tf.float32)
29 | else:
30 | p_keep = 1-tf.exp(-N*p)
31 | rand = tf.random_uniform(tf.shape(p_keep))
32 | keep = rand
15 | ````
16 |
17 | [robustml]: https://github.com/robust-ml/robustml
18 |
--------------------------------------------------------------------------------
/therm-adv/evaluation.py:
--------------------------------------------------------------------------------
1 | import time
2 | import pickle
3 | import robustml
4 | from robustml_model import Thermometer, LEVELS
5 | from discretization_utils import discretize_uniform
6 | import sys
7 | import argparse
8 | import tensorflow as tf
9 | import numpy as np
10 | from helpers import *
11 | import os
12 | import cv2
13 |
14 |
15 | npop = 300 # population size
16 | sigma = 0.1 # noise standard deviation
17 | alpha = 0.008 # learning rate
18 | # alpha = 0.001 # learning rate
19 | boxmin = 0
20 | boxmax = 1
21 | boxplus = (boxmin + boxmax) / 2.
22 | boxmul = (boxmax - boxmin) / 2.
23 | folder = './liclipadvImages/'
24 | epsi = 0.031
25 |
26 | def main():
27 |
28 | parser = argparse.ArgumentParser()
29 | parser.add_argument('--cifar-path', type=str, default='../cifar10_data/test_batch',
30 | help='path to the test_batch file from http://www.cs.toronto.edu/~kriz/cifar-10-python.tar.gz')
31 | parser.add_argument('--perturb', type=str, default='lid_perturb')
32 | parser.add_argument('--start', type=int, default=0)
33 | parser.add_argument('--end', type=int, default=100)
34 | parser.add_argument('--debug', action='store_true')
35 | args = parser.parse_args()
36 |
37 | test_loss = 0
38 | correct = 0
39 | total = 0
40 | totalImages = 0
41 | succImages = 0
42 | faillist = []
43 |
44 |
45 |
46 | # set up TensorFlow session
47 |
48 | config = tf.ConfigProto()
49 | config.gpu_options.allow_growth = True
50 | sess = tf.Session(config=config)
51 |
52 |
53 | # initialize a model
54 | model = Thermometer(sess)
55 |
56 | print(model.threat_model.targeted)
57 | # initialize an attack (it's a white box attack, and it's allowed to look
58 | # at the internals of the model in any way it wants)
59 | # attack = BPDA(sess, model, epsilon=model.threat_model.epsilon, debug=args.debug)
60 | # attack = Attack(sess, model.model, epsilon=model.threat_model.epsilon)
61 |
62 | # initialize a data provider for CIFAR-10 images
63 | provider = robustml.provider.CIFAR10(args.cifar_path)
64 | input_xs = tf.placeholder(tf.float32, [None, 32, 32, 3])
65 | start = 0
66 | end = 10000
67 | total = 0
68 | uniform = discretize_uniform(input_xs, levels=LEVELS, thermometer=True)
69 | real_logits = tf.nn.softmax(model.model(uniform))
70 | successlist = []
71 | printlist = []
72 |
73 | start_time = time.time()
74 | perturbs = os.listdir('./')
75 | all_dir = []
76 | for x in perturbs:
77 | if 'perturb' in x:
78 | all_dir.append(x)
79 |
80 |
81 | for y in all_dir:
82 | perturb_files = os.listdir(y)
83 | numbers = []
84 | totalImages = 0
85 | succImages = 0
86 |
87 | numbers = []
88 | for x in perturb_files:
89 | number = x.split('_')[1]
90 | name = x.split('_')[0]
91 | number1 = int(number.split('.pkl')[0])
92 | numbers.append(number1)
93 |
94 | for i in numbers:
95 | success = False
96 | #print('evaluating %d of [%d, %d)' % (i, start, end), file=sys.stderr)
97 | inputs, targets= provider[i]
98 | modify = np.random.randn(1,3,32,32) * 0.001
99 | in_pkl = y + '/' +name + '_' + str(i)+'.pkl'
100 | ##### thermometer encoding
101 |
102 | logits = sess.run(real_logits,feed_dict={input_xs: [inputs]})
103 | if np.argmax(logits) != targets:
104 | print('skip the wrong example ', i)
105 | continue
106 | totalImages += 1
107 | try:
108 | modify = pickle.load(open(in_pkl, 'rb'))
109 | except:
110 | modify = pickle.load(open(in_pkl,'rb'),encoding='bytes')
111 | if 'cascade' in in_pkl:
112 | modify = cv2.resize(modify[0].transpose(1, 2, 0), dsize=(32, 32), interpolation=cv2.INTER_LINEAR)
113 | modify = modify.transpose(2,0,1)
114 | modify = modify.reshape((1,3,32,32))
115 | newimg = torch_arctanh((inputs - boxplus) / boxmul).transpose(2, 0, 1)
116 | realinputimg = np.tanh(newimg + modify) * boxmul + boxplus
117 | realdist = realinputimg - (np.tanh(newimg) * boxmul + boxplus)
118 | realclipdist = np.clip(realdist, -epsi, epsi)
119 | realclipinput = realclipdist + (np.tanh(newimg) * boxmul + boxplus)
120 | l2real = np.sum((realclipinput - (np.tanh(newimg) * boxmul + boxplus)) ** 2) ** 0.5
121 | outputsreal = sess.run(real_logits, feed_dict={input_xs: realclipinput.transpose(0, 2, 3, 1)})
122 | if (np.argmax(outputsreal) != targets) and (np.abs(realclipdist).max() <= epsi):
123 | succImages += 1
124 |
125 | success_rate = succImages / float(totalImages)
126 | print('name:',y)
127 | print('succ rate', success_rate)
128 | print('succ {} , total {}'.format(succImages, totalImages))
129 |
130 |
131 | if __name__ == '__main__':
132 | main()
133 |
--------------------------------------------------------------------------------
/therm-adv/evaluation_bpda.py:
--------------------------------------------------------------------------------
1 | import time
2 | import pickle
3 | import robustml
4 | from robustml_model import Thermometer, LEVELS
5 | from discretization_utils import discretize_uniform
6 | import sys
7 | import argparse
8 | import tensorflow as tf
9 | import numpy as np
10 | from helpers import *
11 | import os
12 | import cv2
13 |
14 |
15 | npop = 300 # population size
16 | sigma = 0.1 # noise standard deviation
17 | alpha = 0.008 # learning rate
18 | # alpha = 0.001 # learning rate
19 | boxmin = 0
20 | boxmax = 1
21 | boxplus = (boxmin + boxmax) / 2.
22 | boxmul = (boxmax - boxmin) / 2.
23 | folder = './liclipadvImages/'
24 | epsi = 0.032
25 |
26 | def main():
27 |
28 | parser = argparse.ArgumentParser()
29 | parser.add_argument('--cifar-path', type=str, default='../cifar10_data/test_batch',
30 | help='path to the test_batch file from http://www.cs.toronto.edu/~kriz/cifar-10-python.tar.gz')
31 | parser.add_argument('--perturb', type=str, default='lid_perturb')
32 | parser.add_argument('--start', type=int, default=0)
33 | parser.add_argument('--end', type=int, default=100)
34 | parser.add_argument('--debug', action='store_true')
35 | args = parser.parse_args()
36 |
37 | test_loss = 0
38 | correct = 0
39 | total = 0
40 | totalImages = 0
41 | succImages = 0
42 | faillist = []
43 |
44 |
45 |
46 | # set up TensorFlow session
47 |
48 | config = tf.ConfigProto()
49 | config.gpu_options.allow_growth = True
50 | sess = tf.Session(config=config)
51 |
52 |
53 | # initialize a model
54 | model = Thermometer(sess)
55 |
56 | print(model.threat_model.targeted)
57 | # initialize an attack (it's a white box attack, and it's allowed to look
58 | # at the internals of the model in any way it wants)
59 | # attack = BPDA(sess, model, epsilon=model.threat_model.epsilon, debug=args.debug)
60 | # attack = Attack(sess, model.model, epsilon=model.threat_model.epsilon)
61 |
62 | # initialize a data provider for CIFAR-10 images
63 | provider = robustml.provider.CIFAR10(args.cifar_path)
64 | input_xs = tf.placeholder(tf.float32, [None, 32, 32, 3])
65 | start = 0
66 | end = 10000
67 | total = 0
68 | uniform = discretize_uniform(input_xs, levels=LEVELS, thermometer=True)
69 | real_logits = tf.nn.softmax(model.model(uniform))
70 | successlist = []
71 | printlist = []
72 |
73 | start_time = time.time()
74 | perturbs = os.listdir('./')
75 | all_dir = []
76 | for x in perturbs:
77 | if 'perturb' in x:
78 | all_dir.append(x)
79 |
80 |
81 | for y in all_dir:
82 | perturb_files = os.listdir(y)
83 | numbers = []
84 | totalImages = 0
85 | succImages = 0
86 |
87 | numbers = []
88 | for x in perturb_files:
89 | number = x.split('_')[-1]
90 | name = x.split('_')[0]
91 | number1 = int(number.split('.pkl')[0])
92 | numbers.append(number1)
93 |
94 | for i in numbers:
95 | success = False
96 | print('evaluating %d of [%d, %d)' % (i, start, end), file=sys.stderr)
97 | inputs, targets= provider[i]
98 | modify = np.random.randn(1,3,32,32) * 0.001
99 | in_pkl = y + '/' +name +'_' + str(i)+'.pkl'
100 | ##### thermometer encoding
101 |
102 | logits = sess.run(real_logits,feed_dict={input_xs: [inputs]})
103 | if np.argmax(logits) != targets:
104 | print('skip the wrong example ', i)
105 | continue
106 | totalImages += 1
107 | try:
108 | modify = pickle.load(open(in_pkl, 'rb'))
109 | except:
110 | modify = pickle.load(open(in_pkl,'rb'),encoding='bytes')
111 | # if 'cascade' in in_pkl:
112 | # modify = cv2.resize(modify[0].transpose(1, 2, 0), dsize=(32, 32), interpolation=cv2.INTER_LINEAR)
113 | # modify = modify.transpose(2,0,1)
114 | # modify = modify.reshape((1,3,32,32))
115 | realclipinput = modify.reshape(1,32,32,3)+0.5
116 | realclipdist = realclipinput - inputs
117 | print(np.abs(realclipdist).max())
118 | outputsreal = sess.run(real_logits, feed_dict={input_xs: realclipinput})
119 |
120 | outputsreal = sess.run(real_logits, feed_dict={input_xs: realclipinput})
121 | if (np.argmax(outputsreal) != targets) and (np.abs(realclipdist).max() <= epsi):
122 | succImages += 1
123 |
124 | success_rate = succImages / float(totalImages)
125 | print('name:',y)
126 | print('succ rate', success_rate)
127 | print('succ {} , total {}'.format(succImages, totalImages))
128 |
129 |
130 | if __name__ == '__main__':
131 | main()
132 |
--------------------------------------------------------------------------------
/therm-adv/helpers.py:
--------------------------------------------------------------------------------
1 | import operator as op
2 | import functools as ft
3 | import numpy as np
4 |
5 |
6 | '''reduce_* helper functions reduce tensors on all dimensions but the first.
7 | They are intended to be used on batched tensors where dim 0 is the batch dim.
8 | '''
9 |
10 |
11 | def reduce_sum(x, keepdim=True):
12 | # silly PyTorch, when will you get proper reducing sums/means?
13 | for a in reversed(range(1, x.dim())):
14 | x = x.sum(a, keepdim=keepdim)
15 | return x
16 |
17 |
18 | def reduce_mean(x, keepdim=True):
19 | numel = ft.reduce(op.mul, x.size()[1:])
20 | x = reduce_sum(x, keepdim=keepdim)
21 | return x / numel
22 |
23 |
24 | def reduce_min(x, keepdim=True):
25 | for a in reversed(range(1, x.dim())):
26 | x = x.min(a, keepdim=keepdim)[0]
27 | return x
28 |
29 |
30 | def reduce_max(x, keepdim=True):
31 | for a in reversed(range(1, x.dim())):
32 | x = x.max(a, keepdim=keepdim)[0]
33 | return x
34 |
35 |
36 | def torch_arctanh(x, eps=1e-6):
37 | x *= (1. - eps)
38 | return (np.log((1 + x) / (1 - x))) * 0.5
39 |
40 |
41 | def l2r_dist(x, y, keepdim=True, eps=1e-8):
42 | d = (x - y)**2
43 | d = reduce_sum(d, keepdim=keepdim)
44 | d += eps # to prevent infinite gradient at 0
45 | return d.sqrt()
46 |
47 |
48 | def l2_dist(x, y, keepdim=True):
49 | d = (x - y)**2
50 | return reduce_sum(d, keepdim=keepdim)
51 |
52 |
53 | def l1_dist(x, y, keepdim=True):
54 | d = torch.abs(x - y)
55 | return reduce_sum(d, keepdim=keepdim)
56 |
57 |
58 | def l2_norm(x, keepdim=True):
59 | norm = reduce_sum(x*x, keepdim=keepdim)
60 | return norm.sqrt()
61 |
62 |
63 | def l1_norm(x, keepdim=True):
64 | return reduce_sum(x.abs(), keepdim=keepdim)
65 |
66 |
67 | def rescale(x, x_min=-1., x_max=1.):
68 | return x * (x_max - x_min) + x_min
69 |
70 |
71 | def tanh_rescale(x, x_min=-1., x_max=1.):
72 | return (torch.tanh(x) + 1) * 0.5 * (x_max - x_min) + x_min
73 |
--------------------------------------------------------------------------------
/therm-adv/robustml_attack.py:
--------------------------------------------------------------------------------
1 | import robustml
2 | from robustml_model import Thermometer, LEVELS
3 | from discretization_utils import discretize_uniform
4 | import sys
5 | import argparse
6 | import tensorflow as tf
7 | import numpy as np
8 |
9 | class Attack:
10 | def __init__(self, sess, model, epsilon, num_steps=100, step_size=1):
11 | self._sess = sess
12 | self.model = model
13 | self.num_steps = num_steps
14 | self.step_size = step_size
15 |
16 | self.xs = tf.Variable(np.zeros((1, 32, 32, 3), dtype=np.float32),
17 | name='modifier')
18 | self.orig_xs = tf.placeholder(tf.float32, [None, 32, 32, 3])
19 |
20 | self.ys = tf.placeholder(tf.int32, [None])
21 |
22 | self.epsilon = epsilon * 255
23 |
24 | delta = tf.clip_by_value(self.xs, 0, 255) - self.orig_xs
25 | delta = tf.clip_by_value(delta, -self.epsilon, self.epsilon)
26 |
27 | self.do_clip_xs = tf.assign(self.xs, self.orig_xs+delta)
28 |
29 | compare = tf.constant((256.0/LEVELS)*np.arange(-1,LEVELS-1).reshape((1,1,1,1,LEVELS)),
30 | dtype=tf.float32)
31 | inner = tf.reshape(self.xs,(-1, 32, 32, 3, 1)) - compare
32 | inner = tf.maximum(tf.minimum(inner/(256.0/LEVELS), 1.0), 0.0)
33 |
34 | self.therm = tf.reshape(inner, (-1, 32, 32, LEVELS*3))
35 |
36 | self.logits = logits = model(self.therm)
37 |
38 | self.uniform = discretize_uniform(self.xs/255.0, levels=LEVELS, thermometer=True)
39 | self.real_logits = model(self.uniform)
40 |
41 | label_mask = tf.one_hot(self.ys, 10)
42 | correct_logit = tf.reduce_sum(label_mask * logits, axis=1)
43 | wrong_logit = tf.reduce_max((1-label_mask) * logits - 1e4*label_mask, axis=1)
44 |
45 | self.loss = (correct_logit - wrong_logit)
46 |
47 | start_vars = set(x.name for x in tf.global_variables())
48 | optimizer = tf.train.AdamOptimizer(step_size*1)
49 | self.grad = tf.sign(tf.gradients(self.loss, self.xs)[0])
50 |
51 | grad,var = optimizer.compute_gradients(self.loss, [self.xs])[0]
52 | self.train = optimizer.apply_gradients([(tf.sign(grad),var)])
53 |
54 | end_vars = tf.global_variables()
55 | self.new_vars = [x for x in end_vars if x.name not in start_vars]
56 |
57 | def perturb(self, x, y, sess):
58 | sess.run(tf.variables_initializer(self.new_vars))
59 | sess.run(self.xs.initializer)
60 | sess.run(self.do_clip_xs,
61 | {self.orig_xs: x})
62 |
63 | for i in range(self.num_steps):
64 |
65 | t = sess.run(self.uniform)
66 | sess.run(self.train, feed_dict={self.ys: y,
67 | self.therm: t})
68 | sess.run(self.do_clip_xs,
69 | {self.orig_xs: x})
70 |
71 | return sess.run(self.xs)
72 |
73 | def run(self, x, y, target):
74 | if target is not None:
75 | raise NotImplementedError
76 | return self.perturb(np.array([x]) * 255.0, [y], self._sess)[0] / 255.0
77 |
78 | def main():
79 | parser = argparse.ArgumentParser()
80 | parser.add_argument('--cifar-path', type=str, required=True,
81 | help='path to the test_batch file from http://www.cs.toronto.edu/~kriz/cifar-10-python.tar.gz')
82 | parser.add_argument('--start', type=int, default=0)
83 | parser.add_argument('--end', type=int, default=1000)
84 | parser.add_argument('--debug', action='store_true')
85 | args = parser.parse_args()
86 |
87 | # set up TensorFlow session
88 | config = tf.ConfigProto()
89 | config.gpu_options.allow_growth = True
90 | sess = tf.Session(config=config)
91 |
92 | # initialize a model
93 | model = Thermometer(sess)
94 |
95 | # initialize an attack (it's a white box attack, and it's allowed to look
96 | # at the internals of the model in any way it wants)
97 | # attack = BPDA(sess, model, epsilon=model.threat_model.epsilon, debug=args.debug)
98 | attack = Attack(sess, model.model, epsilon=model.threat_model.epsilon)
99 |
100 | # initialize a data provider for CIFAR-10 images
101 | provider = robustml.provider.CIFAR10(args.cifar_path)
102 |
103 | success_rate = robustml.evaluate.evaluate(
104 | model,
105 | attack,
106 | provider,
107 | start=args.start,
108 | end=args.end,
109 | deterministic=True,
110 | debug=args.debug,
111 | )
112 |
113 | print('attack success rate: %.2f%% (over %d data points)' % (success_rate*100, args.end-args.start))
114 |
115 | if __name__ == '__main__':
116 | main()
117 |
--------------------------------------------------------------------------------
/therm-adv/robustml_model.py:
--------------------------------------------------------------------------------
1 | import robustml
2 | import tensorflow as tf
3 | from discretization_utils import discretize_uniform
4 | import numpy as np
5 | from cifar_model import Model
6 |
7 | LEVELS = 16
8 |
9 | class Thermometer(robustml.model.Model):
10 | def __init__(self, sess):
11 | self._sess = sess
12 |
13 | self._x = tf.placeholder(tf.float32, (1, 32, 32, 3))
14 | self._encode = discretize_uniform(self._x/255.0, levels=LEVELS, thermometer=True)
15 |
16 | self._model = Model(
17 | '../all_models/thermometer_advtrain',
18 | # '../therm_models/tiny_16',
19 | sess,
20 | tiny=False,
21 | # tiny=True,
22 | mode='eval',
23 | thermometer=True,
24 | levels=LEVELS
25 | )
26 |
27 | self._dataset = robustml.dataset.CIFAR10()
28 | self._threat_model = robustml.threat_model.Linf(epsilon=8.0/255.0)
29 |
30 | @property
31 | def dataset(self):
32 | return self._dataset
33 |
34 | @property
35 | def threat_model(self):
36 | return self._threat_model
37 |
38 | def classify(self, x):
39 | x = x * 255.0
40 | # first encode the input, then classify it
41 | encoded = self.encode(x)
42 | return self._sess.run(self._model.predictions, {self._model.x_input: encoded})[0]
43 |
44 | # expose internals for white box attacks
45 |
46 | @property
47 | def model(self):
48 | return self._model
49 |
50 | # x should be in [0, 255]
51 | def encode(self, x):
52 | return self._sess.run(self._encode, {self._x: [x]})
53 |
--------------------------------------------------------------------------------
/wideresnet28/README.md:
--------------------------------------------------------------------------------
1 | # Thermometer Encoding: One Hot Way To Resist Adversarial Examples
2 |
3 | Paper: [Buckman et al. 2018](https://openreview.net/forum?id=S18Su--CW)
4 |
5 | ## Setup
6 |
7 | Run `./setup.sh` to fetch models.
8 |
9 | ## Breaks
10 |
11 | * Thermometer Encoding: BPDA
12 |
13 | ## [robustml] evaluation
14 |
15 | Run with:
16 |
17 | ```bash
18 | python robustml_attack.py --cifar-path
19 | ````
20 |
21 | [robustml]: https://github.com/robust-ml/robustml
22 |
--------------------------------------------------------------------------------
/wideresnet28/config.json:
--------------------------------------------------------------------------------
1 | {
2 | "_comment": "===== MODEL CONFIGURATION =====",
3 | "model_dir": "models/adv_train_clean",
4 |
5 | "_comment": "===== DATASET CONFIGURATION =====",
6 | "data_path": "cifar10_data",
7 |
8 | "_comment": "===== TRAINING CONFIGURATION =====",
9 | "tf_random_seed": 451760341,
10 | "np_random_seed": 216105420,
11 | "max_num_training_steps": 80000,
12 | "num_output_steps": 100,
13 | "num_summary_steps": 100,
14 | "num_checkpoint_steps": 1000,
15 | "training_batch_size": 128,
16 | "step_size_schedule": [[0, 0.1], [40000, 0.01], [60000, 0.001]],
17 | "weight_decay": 0.0002,
18 | "momentum": 0.9,
19 |
20 | "_comment": "===== EVAL CONFIGURATION =====",
21 | "num_eval_examples": 10000,
22 | "eval_batch_size": 100,
23 | "eval_on_cpu": false,
24 |
25 | "_comment": "=====ADVERSARIAL EXAMPLES CONFIGURATION=====",
26 | "epsilon": 8.0,
27 | "num_steps": 7,
28 | "step_size": 2.0,
29 | "random_start": true,
30 | "loss_func": "xent",
31 | "store_adv_path": "attack.npy"
32 | }
33 |
--------------------------------------------------------------------------------
/wideresnet28/evaluation.py:
--------------------------------------------------------------------------------
1 | import time
2 | import pickle
3 | import robustml
4 | from robustml_model import Thermometer, LEVELS
5 | from discretization_utils import discretize_uniform
6 | import sys
7 | import argparse
8 | import tensorflow as tf
9 | import numpy as np
10 | from helpers import *
11 | import os
12 | import cv2
13 |
14 |
15 | npop = 300 # population size
16 | sigma = 0.1 # noise standard deviation
17 | alpha = 0.008 # learning rate
18 | # alpha = 0.001 # learning rate
19 | boxmin = 0
20 | boxmax = 1
21 | boxplus = (boxmin + boxmax) / 2.
22 | boxmul = (boxmax - boxmin) / 2.
23 | folder = './liclipadvImages/'
24 | epsi = 0.031
25 |
26 | def main():
27 |
28 | parser = argparse.ArgumentParser()
29 | parser.add_argument('--cifar-path', type=str, default='../cifar10_data/test_batch',
30 | help='path to the test_batch file from http://www.cs.toronto.edu/~kriz/cifar-10-python.tar.gz')
31 | parser.add_argument('--perturb', type=str, default='lid_perturb')
32 | parser.add_argument('--start', type=int, default=0)
33 | parser.add_argument('--end', type=int, default=100)
34 | parser.add_argument('--debug', action='store_true')
35 | args = parser.parse_args()
36 |
37 | test_loss = 0
38 | correct = 0
39 | total = 0
40 | totalImages = 0
41 | succImages = 0
42 | faillist = []
43 |
44 |
45 |
46 | # set up TensorFlow session
47 |
48 | config = tf.ConfigProto()
49 | config.gpu_options.allow_growth = True
50 | sess = tf.Session(config=config)
51 |
52 |
53 | # initialize a model
54 | model = Thermometer(sess)
55 |
56 | print(model.threat_model.targeted)
57 | # initialize an attack (it's a white box attack, and it's allowed to look
58 | # at the internals of the model in any way it wants)
59 | # attack = BPDA(sess, model, epsilon=model.threat_model.epsilon, debug=args.debug)
60 | # attack = Attack(sess, model.model, epsilon=model.threat_model.epsilon)
61 |
62 | # initialize a data provider for CIFAR-10 images
63 | provider = robustml.provider.CIFAR10(args.cifar_path)
64 | input_xs = tf.placeholder(tf.float32, [None, 32, 32, 3])
65 | start = 0
66 | end = 10000
67 | total = 0
68 | uniform = discretize_uniform(input_xs, levels=LEVELS, thermometer=True)
69 | real_logits = tf.nn.softmax(model.model(uniform))
70 | successlist = []
71 | printlist = []
72 |
73 | start_time = time.time()
74 | perturbs = os.listdir('./')
75 | all_dir = []
76 | for x in perturbs:
77 | if 'perturb' in x:
78 | all_dir.append(x)
79 |
80 |
81 | for y in all_dir:
82 | perturb_files = os.listdir(y)
83 | numbers = []
84 | totalImages = 0
85 | succImages = 0
86 |
87 | numbers = []
88 | for x in perturb_files:
89 | number = x.split('_')[1]
90 | name = x.split('_')[0]
91 | number1 = int(number.split('.pkl')[0])
92 | numbers.append(number1)
93 |
94 | for i in numbers:
95 | success = False
96 | #print('evaluating %d of [%d, %d)' % (i, start, end), file=sys.stderr)
97 | inputs, targets= provider[i]
98 | modify = np.random.randn(1,3,32,32) * 0.001
99 | in_pkl = y + '/' +name + '_' + str(i)+'.pkl'
100 | ##### thermometer encoding
101 |
102 | logits = sess.run(real_logits,feed_dict={input_xs: [inputs]})
103 | if np.argmax(logits) != targets:
104 | print('skip the wrong example ', i)
105 | continue
106 | totalImages += 1
107 | try:
108 | modify = pickle.load(open(in_pkl, 'rb'))
109 | except:
110 | modify = pickle.load(open(in_pkl,'rb'),encoding='bytes')
111 | if 'cascade' in in_pkl:
112 | modify = cv2.resize(modify[0].transpose(1, 2, 0), dsize=(32, 32), interpolation=cv2.INTER_LINEAR)
113 | modify = modify.transpose(2,0,1)
114 | modify = modify.reshape((1,3,32,32))
115 | newimg = torch_arctanh((inputs - boxplus) / boxmul).transpose(2, 0, 1)
116 | realinputimg = np.tanh(newimg + modify) * boxmul + boxplus
117 | realdist = realinputimg - (np.tanh(newimg) * boxmul + boxplus)
118 | realclipdist = np.clip(realdist, -epsi, epsi)
119 | realclipinput = realclipdist + (np.tanh(newimg) * boxmul + boxplus)
120 | l2real = np.sum((realclipinput - (np.tanh(newimg) * boxmul + boxplus)) ** 2) ** 0.5
121 | outputsreal = sess.run(real_logits, feed_dict={input_xs: realclipinput.transpose(0, 2, 3, 1)})
122 | if (np.argmax(outputsreal) != targets) and (np.abs(realclipdist).max() <= epsi):
123 | succImages += 1
124 |
125 | success_rate = succImages / float(totalImages)
126 | print('name:',y)
127 | print('succ rate', success_rate)
128 | print('succ {} , total {}'.format(succImages, totalImages))
129 |
130 |
131 | if __name__ == '__main__':
132 | main()
133 |
--------------------------------------------------------------------------------
/wideresnet28/helpers.py:
--------------------------------------------------------------------------------
1 | import operator as op
2 | import functools as ft
3 | import numpy as np
4 |
5 |
6 | '''reduce_* helper functions reduce tensors on all dimensions but the first.
7 | They are intended to be used on batched tensors where dim 0 is the batch dim.
8 | '''
9 |
10 |
11 | def reduce_sum(x, keepdim=True):
12 | # silly PyTorch, when will you get proper reducing sums/means?
13 | for a in reversed(range(1, x.dim())):
14 | x = x.sum(a, keepdim=keepdim)
15 | return x
16 |
17 |
18 | def reduce_mean(x, keepdim=True):
19 | numel = ft.reduce(op.mul, x.size()[1:])
20 | x = reduce_sum(x, keepdim=keepdim)
21 | return x / numel
22 |
23 |
24 | def reduce_min(x, keepdim=True):
25 | for a in reversed(range(1, x.dim())):
26 | x = x.min(a, keepdim=keepdim)[0]
27 | return x
28 |
29 |
30 | def reduce_max(x, keepdim=True):
31 | for a in reversed(range(1, x.dim())):
32 | x = x.max(a, keepdim=keepdim)[0]
33 | return x
34 |
35 |
36 | def torch_arctanh(x, eps=1e-6):
37 | x *= (1. - eps)
38 | return (np.log((1 + x) / (1 - x))) * 0.5
39 |
40 |
41 | def l2r_dist(x, y, keepdim=True, eps=1e-8):
42 | d = (x - y)**2
43 | d = reduce_sum(d, keepdim=keepdim)
44 | d += eps # to prevent infinite gradient at 0
45 | return d.sqrt()
46 |
47 |
48 | def l2_dist(x, y, keepdim=True):
49 | d = (x - y)**2
50 | return reduce_sum(d, keepdim=keepdim)
51 |
52 |
53 | def l1_dist(x, y, keepdim=True):
54 | d = torch.abs(x - y)
55 | return reduce_sum(d, keepdim=keepdim)
56 |
57 |
58 | def l2_norm(x, keepdim=True):
59 | norm = reduce_sum(x*x, keepdim=keepdim)
60 | return norm.sqrt()
61 |
62 |
63 | def l1_norm(x, keepdim=True):
64 | return reduce_sum(x.abs(), keepdim=keepdim)
65 |
66 |
67 | def rescale(x, x_min=-1., x_max=1.):
68 | return x * (x_max - x_min) + x_min
69 |
70 |
71 | def tanh_rescale(x, x_min=-1., x_max=1.):
72 | return (torch.tanh(x) + 1) * 0.5 * (x_max - x_min) + x_min
73 |
--------------------------------------------------------------------------------
/wideresnet28/setup.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | cd "$(dirname "$0")" # cd to directory of this script
4 |
5 | # $1 is filename
6 | # $2 is expected sha
7 | check_sha1() {
8 | computed=$(sha1sum "$1" 2>/dev/null | awk '{print $1}') || return 1
9 | if [ "$computed" == "$2" ]; then
10 | return 0;
11 | else
12 | return 1;
13 | fi
14 | }
15 |
16 | # $1 is URL
17 | # $2 is extracted file name
18 | # $3 is the checksum
19 | fetch() {
20 | f=${1##*/}
21 | if check_sha1 $f $3; then
22 | echo "$2 already downloaded"
23 | return
24 | fi
25 | echo "downloading $1"
26 | wget -q $1 -O $f
27 | if check_sha1 $f $3; then
28 | echo "downloaded $2"
29 | else
30 | echo "HASH MISMATCH, SHA1($f) != $3"
31 | return
32 | fi
33 |
34 | tar xzf $f
35 | }
36 |
37 | cd ..
38 | fetch https://github.com/anishathalye/obfuscated-gradients/releases/download/v0/cifar10_data.tgz cifar10_data 6d011cbb029aec2c18dc10bce32adea9e27c2068
39 | mkdir -p models
40 | cd models
41 | fetch https://github.com/anishathalye/obfuscated-gradients/releases/download/v0/model_thermometer_advtrain.tgz models/thermometer_advtrain 595261189ee9a78911f312cd2443ee088ef59bee
42 |
--------------------------------------------------------------------------------
/wideresnet28/test_wres.py:
--------------------------------------------------------------------------------
1 | from __future__ import absolute_import
2 | from __future__ import division
3 | from __future__ import print_function
4 |
5 | import scipy.misc
6 | from datetime import datetime
7 | import json
8 | import os
9 | import shutil
10 | from timeit import default_timer as timer
11 | from discretization_utils import discretize_uniform
12 | from discretization_attacks import adv_lspga
13 |
14 | import tensorflow as tf
15 | import numpy as np
16 |
17 | from cifar_model import Model
18 | import cifar10_input
19 | import sys
20 | import robustml
21 | import argparse
22 |
23 | levels = 16
24 |
25 |
26 |
27 |
28 |
29 |
30 | steps = 7
31 | eps = 0.031
32 |
33 |
34 |
35 | parser = argparse.ArgumentParser()
36 | parser.add_argument('--cifar-path', type=str, default='../cifar10_data/test_batch',
37 | help='path to the test_batch file from http://www.cs.toronto.edu/~kriz/cifar-10-python.tar.gz')
38 | parser.add_argument('--start', type=int, default=0)
39 | parser.add_argument('--end', type=int, default=100)
40 | parser.add_argument('--debug', action='store_true')
41 | args = parser.parse_args()
42 |
43 |
44 | provider = robustml.provider.CIFAR10(args.cifar_path)
45 | # saver = tf.train.Saver(max_to_keep=3)
46 |
47 | start = 0
48 | end = 100
49 |
50 | config = tf.ConfigProto()
51 | config.gpu_options.allow_growth = True
52 | sess = tf.Session(config=config)
53 |
54 | model = Model( './models/adv_train_clean/',
55 | sess,mode='eval', tiny=False,
56 | thermometer=False, levels=levels)
57 | # initialize data augmentation
58 |
59 |
60 | input_xs = tf.placeholder(tf.float32, [None, 32, 32, 3])
61 | real_logits = tf.nn.softmax(model(input_xs))
62 |
63 | # saver.restore(sess,
64 | # os.path.join("models/adv_train_clean", 'checkpoint-65000'))
65 |
66 | for i in range(start, end):
67 | x_batch, y_batch = provider[i]
68 |
69 | logits = sess.run(real_logits,feed_dict={input_xs: [x_batch]})
70 | # nat_dict = {model.x_input: [x_batch],model.y_input: [y_batch]}
71 | # logits = sess.run(model.pre_softmax, feed_dict=nat_dict)
72 |
73 | print(logits)
74 |
75 |
76 |
77 |
78 |
--------------------------------------------------------------------------------