├── .gitignore ├── README.md ├── loaders.py ├── models ├── __init__.py ├── policy │ ├── __init__.py │ ├── cifar │ │ ├── __init__.py │ │ ├── carlinet_inv.py │ │ ├── empty.py │ │ ├── resnet_inv.py │ │ ├── unet.py │ │ ├── vgg_inv.py │ │ └── wrn_inv.py │ ├── common.py │ ├── debug │ │ ├── __init__.py │ │ ├── empty.py │ │ └── lr_inv.py │ ├── imagenet │ │ ├── __init__.py │ │ ├── empty.py │ │ └── vgg_inv.py │ └── mnist │ │ ├── __init__.py │ │ ├── carlinet_inv.py │ │ ├── empty.py │ │ ├── unet.py │ │ └── vgg_inv.py ├── standard_model.py └── victim │ ├── __init__.py │ ├── cifar │ ├── LICENSE │ ├── README.md │ ├── __init__.py │ ├── alexnet.py │ ├── carlinet.py │ ├── densenet.py │ ├── lenet.py │ ├── madry_resnet.py │ ├── preresnet.py │ ├── resnet.py │ ├── resnext.py │ ├── utils.py │ ├── vgg.py │ └── wrn.py │ ├── debug │ ├── __init__.py │ └── lr.py │ ├── imagenet │ ├── LICENSE.txt │ ├── README.md │ ├── __init__.py │ ├── bninception.py │ ├── cafferesnet.py │ ├── dpn.py │ ├── fbresnet.py │ ├── fbresnet │ │ ├── __init__.py │ │ ├── resnet152_dump.lua │ │ └── resnet152_load.py │ ├── inceptionresnetv2.py │ ├── inceptionv4.py │ ├── nasnet.py │ ├── nasnet_mobile.py │ ├── pnasnet.py │ ├── polynet.py │ ├── resnet.py │ ├── resnext.py │ ├── resnext_features │ │ ├── __init__.py │ │ ├── resnext101_32x4d_features.py │ │ └── resnext101_64x4d_features.py │ ├── senet.py │ ├── torchvision_models.py │ ├── utils.py │ ├── vgg.py │ ├── vggm.py │ ├── wideresnet.py │ └── xception.py │ └── mnist │ ├── __init__.py │ ├── carlinet.py │ ├── lenet.py │ ├── lr.py │ └── mlp.py ├── pda_cifar10_carlinet_untargeted_l2.sh ├── pda_cifar10_resnet50adv_untargeted_l2.sh ├── pda_cifar10_wrn_untargeted_l2.sh ├── pda_imagenet_resnet18_untargeted_l2.sh ├── pda_mnist_carlinet_untargeted_l2.sh ├── policy_attack.py ├── prepare_imagenet_valv2.py └── train_grad_model.py /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | *$py.class 5 | 6 | # C extensions 7 | *.so 8 | 9 | # Distribution / packaging 10 | .Python 11 | build/ 12 | develop-eggs/ 13 | dist/ 14 | downloads/ 15 | eggs/ 16 | .eggs/ 17 | lib64/ 18 | parts/ 19 | sdist/ 20 | var/ 21 | wheels/ 22 | *.egg-info/ 23 | .installed.cfg 24 | *.egg 25 | MANIFEST 26 | 27 | # PyInstaller 28 | # Usually these files are written by a python script from a template 29 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 30 | *.manifest 31 | *.spec 32 | 33 | # Installer logs 34 | pip-log.txt 35 | pip-delete-this-directory.txt 36 | 37 | # Unit test / coverage reports 38 | htmlcov/ 39 | .tox/ 40 | .coverage 41 | .coverage.* 42 | .cache 43 | nosetests.xml 44 | coverage.xml 45 | *.cover 46 | .hypothesis/ 47 | .pytest_cache/ 48 | 49 | # Translations 50 | *.mo 51 | *.pot 52 | 53 | # Django stuff: 54 | *.log 55 | local_settings.py 56 | db.sqlite3 57 | 58 | # Flask stuff: 59 | instance/ 60 | .webassets-cache 61 | 62 | # Scrapy stuff: 63 | .scrapy 64 | 65 | # Sphinx documentation 66 | docs/_build/ 67 | 68 | # PyBuilder 69 | target/ 70 | 71 | # Jupyter Notebook 72 | .ipynb_checkpoints 73 | 74 | # pyenv 75 | .python-version 76 | 77 | # celery beat schedule file 78 | celerybeat-schedule 79 | 80 | # SageMath parsed files 81 | *.sage.py 82 | 83 | # Environments 84 | .env 85 | .venv 86 | env/ 87 | venv/ 88 | ENV/ 89 | env.bak/ 90 | venv.bak/ 91 | 92 | # Spyder project settings 93 | .spyderproject 94 | .spyproject 95 | 96 | # Rope project settings 97 | .ropeproject 98 | 99 | # mkdocs documentation 100 | /site 101 | 102 | # mypy 103 | .mypy_cache/ 104 | 105 | # input & output 106 | data/ 107 | output/ 108 | 109 | # PyCharm 110 | .idea/ 111 | 112 | # OSX 113 | .DS_Store 114 | 115 | # data and models from google drive 116 | pda_data_and_models.tar.gz 117 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # pda.pytorch 2 | 3 | Code for our ICLR 2021 paper [Policy-Driven Attack: Learning to Query for Hard-label Black-box Adversarial Examples](https://openreview.net/forum?id=pzpytjk3Xb2). 4 | 5 | ## Environments 6 | Our code is tested on the following environment (probably also works on other environments without many changes): 7 | 8 | * Ubuntu 16.04 9 | * Python 3.5.2 10 | * CUDA 9.0.176 11 | * CUDNN 7501 12 | * PyTorch 1.1.0 13 | * torchvision 0.2.0 14 | * numpy 1.16.0 15 | * dill 0.3.2 16 | 17 | ## Datasets, Victim Models, and Pre-trained Policy Networks 18 | 19 | For the required dataset, victim models, and pre-trained weights of policy networks, please download a tarball at [this link](https://drive.google.com/file/d/1dvxCYiv5GGM8Zl-7b-MEm0G3vard69lE/view?usp=sharing) and extract it. 20 | 21 | After extraction, the ```data``` directory should include dataset and victim models for MNIST and CIFAR-10. 22 | 23 | For ImageNet dataset, we use the same data format as in the [Pytorch official ImageNet example](https://github.com/pytorch/examples/tree/master/imagenet), please put the dataset in ```data/imagenet```. 24 | 25 | As described in our paper, we also use [ImageNetV2](https://github.com/modestyachts/ImageNetV2) to provide additional images for ImageNet experiments, please download the ImageNetV2 dataset and then use ```prepare_imagenet_valv2.py``` to merge ImageNetV2 with ImageNet. 26 | 27 | The tarball also provides initial adversarial examples for targeted attacks (in ```data``` directory), and pre-trained policy networks (in ```output``` directory). 28 | 29 | The structure of ```data``` directory should be: 30 | 31 | 32 | ``` 33 | data 34 | ├── cifar10 35 | │   └── cifar-10-batches-py 36 | ├── cifar10-models 37 | │   ├── carlinet 38 | │   ├── madry_resnet50_l2_1_0 39 | │   └── wrn_28_10_drop 40 | ├── imagenet 41 | │   ├── train 42 | │   ├── val 43 | │   └── valv2 44 | ├── init-adv-images-cifar10-test-carlinet.pth 45 | ├── init-adv-images-cifar10-test-madry_resnet50_l2_1_0.pth 46 | ├── init-adv-images-cifar10-test-wrn_28_10_drop.pth 47 | ├── init-adv-images-imagenet-valv2-resnet18.pth 48 | ├── init-adv-images-mnist-test-carlinet.pth 49 | ├── mnist 50 | │   ├── processed 51 | │   └── raw 52 | └── mnist-models 53 | └── carlinet 54 | 55 | ``` 56 | 57 | 58 | ## Usage 59 | 60 | We provide off-the-shelf shell scripts to run attacks and reproduce the results in our paper. 61 | 62 | For example, the following command will reproduce the MNIST->CNN->Ours row in Table 1 of our paper: 63 | 64 | ``` 65 | ./pda_mnist_carlinet_untargeted_l2.sh 66 | ``` 67 | 68 | ## Acknowledgements 69 | The following resources are very helpful for our work: 70 | 71 | * [Pretrained models and for ImageNet](https://github.com/Cadene/pretrained-models.pytorch) 72 | * [Pretrained models for CIFAR-10](https://github.com/bearpaw/pytorch-classification) 73 | * [Carlini's CIFAR-10 ConvNet](https://github.com/carlini/nn_robust_attacks) 74 | * [Pretrained ConvNet models from AutoZoom](https://github.com/IBM/Autozoom-Attack) 75 | 76 | ## Citation 77 | Please cite our work in your publications if it helps your research: 78 | 79 | ``` 80 | @inproceedings{yan2021policy, 81 | title={Policy-Driven Attack: Learning to Query for Hard-label Black-box Adversarial Examples}, 82 | author={Yan, Ziang and Guo, Yiwen and Liang, Jian and Zhang, Changshui}, 83 | booktitle={International Conference on Learning Representations}, 84 | year={2021} 85 | } 86 | ``` 87 | 88 | -------------------------------------------------------------------------------- /models/policy/__init__.py: -------------------------------------------------------------------------------- 1 | import models.policy.debug 2 | import models.policy.mnist 3 | import models.policy.cifar 4 | import models.policy.imagenet 5 | -------------------------------------------------------------------------------- /models/policy/cifar/__init__.py: -------------------------------------------------------------------------------- 1 | from models.policy.cifar.empty import * 2 | from models.policy.cifar.unet import * 3 | from models.policy.cifar.carlinet_inv import * 4 | from models.policy.cifar.vgg_inv import * 5 | from models.policy.cifar.resnet_inv import * 6 | from models.policy.cifar.wrn_inv import * 7 | -------------------------------------------------------------------------------- /models/policy/cifar/carlinet_inv.py: -------------------------------------------------------------------------------- 1 | import math 2 | import torch 3 | import torch.nn as nn 4 | import torch.nn.functional as F 5 | from models.policy.common import inv_forward 6 | 7 | __all__ = ['carlinet_inv'] 8 | 9 | 10 | class CarliNetInv(nn.Module): 11 | def __init__(self, use_tanh=True, calibrate=True, input_size=32, init_std=1/32.): 12 | super(CarliNetInv, self).__init__() 13 | # save arguments 14 | self.input_size = input_size 15 | self.init_std = init_std 16 | self.use_tanh = use_tanh 17 | self.calibrate = calibrate 18 | 19 | # main body of carlinet inverse 20 | self.conv2d_1 = nn.Conv2d(3, 64, 3) 21 | self.conv2d_2 = nn.Conv2d(64, 64, 3) 22 | self.conv2d_3 = nn.Conv2d(64, 128, 3) 23 | self.conv2d_4 = nn.Conv2d(128, 128, 3) 24 | 25 | self.dense_1 = nn.Linear(3200, 256) 26 | self.dense_2 = nn.Linear(256, 256) 27 | self.dense_3 = nn.Linear(256, 10) 28 | 29 | # mean / std output 30 | self.normal_mean = nn.Parameter(torch.zeros(3, input_size, input_size)) 31 | self.normal_logstd = nn.Parameter(torch.ones(1) * math.log(self.init_std)) 32 | self.mean_shape = (3, input_size, input_size) 33 | 34 | # whiten function placeholder 35 | # we can not assign value to it now since input_mean / input_std is unknown yet 36 | # we will assign appropriate function in StandardPolicyModel.__init__ 37 | self.whiten_func = lambda t: 1 / 0 38 | 39 | # coefficient to tune between prior knowledge and empty network 40 | self.empty_coeff = nn.Parameter(torch.ones(1) * 0.5) 41 | self.empty_normal_mean = nn.Parameter(torch.zeros(3, input_size, input_size)) 42 | 43 | # init weights 44 | for m in self.modules(): 45 | if isinstance(m, (nn.Conv2d, nn.ConvTranspose2d, nn.Linear)): 46 | nn.init.kaiming_normal_(m.weight) 47 | if m.bias is not None: 48 | nn.init.constant_(m.bias, 0) 49 | elif isinstance(m, (nn.BatchNorm2d, nn.GroupNorm)): 50 | nn.init.constant_(m.weight, 1) 51 | nn.init.constant_(m.bias, 0) 52 | 53 | def get_logit(self, x): 54 | # whiten input 55 | x = self.whiten_func(x) 56 | 57 | x = self.conv2d_1(x) 58 | x = F.relu(x) 59 | x = self.conv2d_2(x) 60 | x = F.relu(x) 61 | x = F.max_pool2d(x, (2, 2)) 62 | 63 | x = self.conv2d_3(x) 64 | x = F.relu(x) 65 | x = self.conv2d_4(x) 66 | x = F.relu(x) 67 | x = F.max_pool2d(x, (2, 2)) 68 | 69 | # carlini's keras model data format: (N, H, W, C) 70 | # pytorch data format: (N, C, H, W) 71 | # we need to transpose pytorch data format into keras data format, to make sure the flatten operator 72 | # has the same effect. 73 | x = x.transpose(1, 2).transpose(2, 3).contiguous().view(x.shape[0], -1) 74 | x = self.dense_1(x) 75 | x = F.relu(x) 76 | x = self.dense_2(x) 77 | if self.use_tanh: 78 | x = F.tanh(x) 79 | else: 80 | x = F.relu(x) 81 | logit = self.dense_3(x) 82 | 83 | return logit 84 | 85 | def forward(self, adv_image, image, label, target, output_fields): 86 | output = inv_forward( 87 | adv_image=adv_image, image=image, label=label, target=target, get_logit=self.get_logit, 88 | normal_mean=self.normal_mean, empty_coeff=self.empty_coeff, empty_normal_mean=self.empty_normal_mean, 89 | training=self.training, calibrate=self.calibrate, output_fields=output_fields) 90 | if 'std' in output_fields: 91 | output['std'] = self.normal_logstd.exp() 92 | return output 93 | 94 | def rescale(self, scale): 95 | raise NotImplementedError 96 | 97 | 98 | def carlinet_inv(**kwargs): 99 | return CarliNetInv(**kwargs) 100 | -------------------------------------------------------------------------------- /models/policy/cifar/empty.py: -------------------------------------------------------------------------------- 1 | import math 2 | import torch 3 | import torch.nn as nn 4 | 5 | __all__ = ['empty'] 6 | 7 | 8 | class Empty(nn.Module): 9 | def __init__(self, input_size=32, init_std=1/32.): 10 | super(Empty, self).__init__() 11 | # save arguments 12 | self.init_std = init_std 13 | 14 | # mean / std output 15 | self.normal_mean = nn.Parameter(torch.zeros(3, input_size, input_size)) 16 | self.normal_logstd = nn.Parameter(torch.ones(1) * math.log(self.init_std)) 17 | self.mean_shape = (3, input_size, input_size) 18 | 19 | # whiten function placeholder 20 | # we can not assign value to it now since input_mean / input_std is unknown yet 21 | # we will assign appropriate function in StandardPolicyModel.__init__ 22 | self.whiten_func = lambda t: 1 / 0 23 | 24 | def forward(self, adv_image, image, label, target, output_fields): 25 | output = dict() 26 | if 'grad' in output_fields: 27 | output['grad'] = self.normal_mean.view(1, *self.mean_shape).repeat(adv_image.shape[0], 1, 1, 1) 28 | if 'std' in output_fields: 29 | output['std'] = self.normal_logstd.exp() 30 | return output 31 | 32 | def rescale(self, scale): 33 | self.normal_mean.data[:] *= scale 34 | 35 | 36 | def empty(**kwargs): 37 | return Empty(**kwargs) 38 | -------------------------------------------------------------------------------- /models/policy/cifar/resnet_inv.py: -------------------------------------------------------------------------------- 1 | import math 2 | import torch 3 | import torch.nn as nn 4 | from models.policy.common import normalization, inv_forward 5 | 6 | __all__ = ['resnet20_inv', 'resnet32_inv'] 7 | 8 | 9 | def conv3x3(in_planes, out_planes, stride=1): 10 | "3x3 convolution with padding" 11 | return nn.Conv2d(in_planes, out_planes, kernel_size=3, stride=stride, 12 | padding=1, bias=False) 13 | 14 | 15 | def normalization16(normalization_type, planes): 16 | return normalization(normalization_type, planes, group_size=16) 17 | 18 | 19 | class BasicBlock(nn.Module): 20 | expansion = 1 21 | 22 | def __init__(self, inplanes, planes, stride=1, downsample=None, normalization_type='none'): 23 | super(BasicBlock, self).__init__() 24 | self.conv1 = conv3x3(inplanes, planes, stride) 25 | self.bn1 = normalization16(normalization_type, planes) 26 | self.relu = nn.ReLU(inplace=True) 27 | self.conv2 = conv3x3(planes, planes) 28 | self.bn2 = normalization16(normalization_type, planes) 29 | self.downsample = downsample 30 | self.stride = stride 31 | 32 | def forward(self, x): 33 | residual = x 34 | 35 | out = self.conv1(x) 36 | out = self.bn1(out) 37 | out = self.relu(out) 38 | 39 | out = self.conv2(out) 40 | out = self.bn2(out) 41 | 42 | if self.downsample is not None: 43 | residual = self.downsample(x) 44 | 45 | out += residual 46 | out = self.relu(out) 47 | 48 | return out 49 | 50 | 51 | class Bottleneck(nn.Module): 52 | expansion = 4 53 | 54 | def __init__(self, inplanes, planes, stride=1, downsample=None, normalization_type='none'): 55 | super(Bottleneck, self).__init__() 56 | self.conv1 = nn.Conv2d(inplanes, planes, kernel_size=1, bias=False) 57 | self.bn1 = normalization16(normalization_type, planes) 58 | self.conv2 = nn.Conv2d(planes, planes, kernel_size=3, stride=stride, 59 | padding=1, bias=False) 60 | self.bn2 = normalization16(normalization_type, planes) 61 | self.conv3 = nn.Conv2d(planes, planes * 4, kernel_size=1, bias=False) 62 | self.bn3 = normalization16(normalization_type, planes * 4) 63 | self.relu = nn.ReLU(inplace=True) 64 | self.downsample = downsample 65 | self.stride = stride 66 | 67 | def forward(self, x): 68 | residual = x 69 | 70 | out = self.conv1(x) 71 | out = self.bn1(out) 72 | out = self.relu(out) 73 | 74 | out = self.conv2(out) 75 | out = self.bn2(out) 76 | out = self.relu(out) 77 | 78 | out = self.conv3(out) 79 | out = self.bn3(out) 80 | 81 | if self.downsample is not None: 82 | residual = self.downsample(x) 83 | 84 | out += residual 85 | out = self.relu(out) 86 | 87 | return out 88 | 89 | 90 | class ResNetInv(nn.Module): 91 | def __init__(self, depth, use_tanh=True, calibrate=True, normalization_type='none', input_size=32, init_std=1/32.): 92 | super(ResNetInv, self).__init__() 93 | # save arguments 94 | self.depth = depth 95 | self.input_size = input_size 96 | self.init_std = init_std 97 | self.normalization_type = normalization_type 98 | self.use_tanh = use_tanh 99 | self.calibrate = calibrate 100 | 101 | # main body of resnet inverse 102 | assert (depth - 2) % 6 == 0, 'depth should be 6n+2' 103 | n = (depth - 2) // 6 104 | block = Bottleneck if depth >= 44 else BasicBlock 105 | self.inplanes = 16 106 | self.conv1 = nn.Conv2d(3, 16, kernel_size=3, padding=1, 107 | bias=False) 108 | self.bn1 = normalization16(normalization_type, 16) 109 | self.relu = nn.ReLU(inplace=True) 110 | self.layer1 = self._make_layer(block, 16, n) 111 | self.layer2 = self._make_layer(block, 32, n, stride=2) 112 | self.layer3 = self._make_layer(block, 64, n, stride=2) 113 | self.avgpool = nn.AvgPool2d(8) 114 | self.fc = nn.Linear(64 * block.expansion, 10) 115 | 116 | # mean / std output 117 | self.normal_mean = nn.Parameter(torch.zeros(3, input_size, input_size)) 118 | self.normal_logstd = nn.Parameter(torch.ones(1) * math.log(self.init_std)) 119 | self.mean_shape = (3, input_size, input_size) 120 | 121 | # whiten function placeholder 122 | # we can not assign value to it now since input_mean / input_std is unknown yet 123 | # we will assign appropriate function in StandardPolicyModel.__init__ 124 | self.whiten_func = lambda t: 1 / 0 125 | 126 | # coefficient to tune between prior knowledge and empty network 127 | self.empty_coeff = nn.Parameter(torch.ones(1) * 0.5) 128 | self.empty_normal_mean = nn.Parameter(torch.zeros(3, input_size, input_size)) 129 | 130 | # init weights 131 | for m in self.modules(): 132 | if isinstance(m, nn.Conv2d): 133 | nn.init.kaiming_normal_(m.weight, mode='fan_out', nonlinearity='relu') 134 | elif isinstance(m, (nn.BatchNorm2d, nn.GroupNorm)): 135 | nn.init.constant_(m.weight, 1) 136 | nn.init.constant_(m.bias, 0) 137 | 138 | # Zero-initialize the last BN in each residual branch, 139 | # so that the residual branch starts with zeros, and each residual block behaves like an identity. 140 | # This improves the model by 0.2~0.3% according to https://arxiv.org/abs/1706.02677 141 | if normalization_type in ['bn', 'gn']: 142 | for m in self.modules(): 143 | if isinstance(m, Bottleneck): 144 | nn.init.constant_(m.bn3.weight, 0) 145 | elif isinstance(m, BasicBlock): 146 | nn.init.constant_(m.bn2.weight, 0) 147 | 148 | def _make_layer(self, block, planes, blocks, stride=1): 149 | downsample = None 150 | if stride != 1 or self.inplanes != planes * block.expansion: 151 | downsample = nn.Sequential( 152 | nn.Conv2d(self.inplanes, planes * block.expansion, 153 | kernel_size=1, stride=stride, bias=False), 154 | normalization16(self.normalization_type, planes * block.expansion) 155 | ) 156 | 157 | layers = [] 158 | layers.append(block(self.inplanes, planes, stride, downsample, normalization_type=self.normalization_type)) 159 | self.inplanes = planes * block.expansion 160 | for i in range(1, blocks): 161 | layers.append(block(self.inplanes, planes, normalization_type=self.normalization_type)) 162 | 163 | return nn.Sequential(*layers) 164 | 165 | def get_logit(self, x): 166 | # whiten input 167 | x = self.whiten_func(x) 168 | 169 | x = self.conv1(x) 170 | x = self.bn1(x) 171 | x = self.relu(x) # 32x32 172 | 173 | x = self.layer1(x) # 32x32 174 | x = self.layer2(x) # 16x16 175 | x = self.layer3(x) # 8x8 176 | 177 | x = self.avgpool(x) 178 | x = x.view(x.size(0), -1) 179 | x = self.fc(x) 180 | return x 181 | 182 | def forward(self, adv_image, image, label, target, output_fields): 183 | output = inv_forward( 184 | adv_image=adv_image, image=image, label=label, target=target, get_logit=self.get_logit, 185 | normal_mean=self.normal_mean, empty_coeff=self.empty_coeff, empty_normal_mean=self.empty_normal_mean, 186 | training=self.training, calibrate=self.calibrate, output_fields=output_fields) 187 | if 'std' in output_fields: 188 | output['std'] = self.normal_logstd.exp() 189 | return output 190 | 191 | def rescale(self, scale): 192 | raise NotImplementedError 193 | 194 | 195 | def resnet20_inv(**kwargs): 196 | return ResNetInv(depth=20, **kwargs) 197 | 198 | 199 | def resnet32_inv(**kwargs): 200 | return ResNetInv(depth=32, **kwargs) 201 | -------------------------------------------------------------------------------- /models/policy/cifar/unet.py: -------------------------------------------------------------------------------- 1 | # code borrowed from https://github.com/milesial/Pytorch-UNet 2 | import math 3 | import torch 4 | import torch.nn as nn 5 | import torch.nn.functional as F 6 | 7 | __all__ = ['unet'] 8 | 9 | 10 | def normalization(normalization_type, planes): 11 | if normalization_type == 'none': 12 | return nn.Identity() 13 | elif normalization_type == 'bn': 14 | return nn.BatchNorm2d(planes) 15 | elif normalization_type == 'gn': 16 | return nn.GroupNorm(num_groups=planes//32, num_channels=planes) 17 | else: 18 | raise ValueError('Unknown normalization method: {}'.format(normalization)) 19 | 20 | 21 | class DoubleConv(nn.Module): 22 | """(convolution => [BN] => ReLU) * 2""" 23 | 24 | def __init__(self, in_channels, out_channels, mid_channels=None, normalization_type='none'): 25 | super(DoubleConv, self).__init__() 26 | if not mid_channels: 27 | mid_channels = out_channels 28 | 29 | self.double_conv = list() 30 | self.double_conv.append(nn.Conv2d(in_channels, mid_channels, kernel_size=3, padding=1)) 31 | self.double_conv.append(normalization(normalization_type, mid_channels)) 32 | self.double_conv.append(nn.ReLU(inplace=True)) 33 | self.double_conv.append(nn.Conv2d(mid_channels, out_channels, kernel_size=3, padding=1)) 34 | self.double_conv.append(normalization(normalization_type, out_channels)) 35 | self.double_conv.append(nn.ReLU(inplace=True)) 36 | 37 | # make double_conv as a nn.Module with nn.Sequential 38 | self.double_conv = nn.Sequential(*self.double_conv) 39 | 40 | def forward(self, x): 41 | return self.double_conv(x) 42 | 43 | 44 | class Down(nn.Module): 45 | """Downscaling with maxpool then double conv""" 46 | 47 | def __init__(self, in_channels, out_channels, normalization_type='none'): 48 | super(Down, self).__init__() 49 | self.maxpool_conv = nn.Sequential( 50 | nn.MaxPool2d(2), 51 | DoubleConv(in_channels, out_channels, normalization_type=normalization_type) 52 | ) 53 | 54 | def forward(self, x): 55 | return self.maxpool_conv(x) 56 | 57 | 58 | class Up(nn.Module): 59 | """Upscaling then double conv""" 60 | 61 | def __init__(self, in_channels, out_channels, bilinear=True, normalization_type='none'): 62 | super(Up, self).__init__() 63 | 64 | # if not bilinear, use the normal convolutions to reduce the number of channels 65 | if bilinear: 66 | self.up = nn.Upsample(scale_factor=2, mode='bilinear', align_corners=True) 67 | self.conv = DoubleConv(in_channels, out_channels, mid_channels=in_channels // 2, 68 | normalization_type=normalization_type) 69 | else: 70 | self.up = nn.ConvTranspose2d(in_channels, in_channels // 2, kernel_size=2, stride=2) 71 | self.conv = DoubleConv(in_channels, out_channels, normalization_type=normalization_type) 72 | 73 | def forward(self, x1, x2): 74 | x1 = self.up(x1) 75 | # input is CHW 76 | diffY = x2.size()[2] - x1.size()[2] 77 | diffX = x2.size()[3] - x1.size()[3] 78 | 79 | x1 = F.pad(x1, (diffX // 2, diffX - diffX // 2, diffY // 2, diffY - diffY // 2)) 80 | # if you have padding issues, see 81 | # https://github.com/HaiyongJiang/U-Net-Pytorch-Unstructured-Buggy/commit/0e854509c2cea854e247a9c615f175f76fbb2e3a 82 | # https://github.com/xiaopeng-liao/Pytorch-UNet/commit/8ebac70e633bac59fc22bb5195e513d5832fb3bd 83 | x = torch.cat([x2, x1], dim=1) 84 | return self.conv(x) 85 | 86 | 87 | class OutConv(nn.Module): 88 | def __init__(self, in_channels, out_channels): 89 | super(OutConv, self).__init__() 90 | self.conv = nn.Conv2d(in_channels, out_channels, kernel_size=1, bias=False) 91 | 92 | def forward(self, x): 93 | return self.conv(x) 94 | 95 | 96 | class UNet(nn.Module): 97 | def __init__(self, input_size=32, n_channels=3, bilinear=True, 98 | normalization_type='none', base_width=16, init_std=1/32.): 99 | super(UNet, self).__init__() 100 | # save arguments 101 | self.input_size = input_size 102 | self.n_channels = n_channels 103 | self.bilinear = bilinear 104 | self.normalization_type = normalization_type 105 | self.base_width = base_width 106 | self.init_std = init_std 107 | 108 | # main body of unet 109 | widths = [base_width, base_width * 2, base_width * 4, base_width * 8] 110 | self.inc = DoubleConv(n_channels, widths[0], normalization_type=normalization_type) 111 | self.down1 = Down(widths[0], widths[1], normalization_type=normalization_type) 112 | self.down2 = Down(widths[1], widths[2], normalization_type=normalization_type) 113 | factor = 2 if bilinear else 1 114 | self.down3 = Down(widths[2], widths[3] // factor, normalization_type=normalization_type) 115 | self.up1 = Up(widths[3], widths[2] // factor, bilinear, normalization_type=normalization_type) 116 | self.up2 = Up(widths[2], widths[1] // factor, bilinear, normalization_type=normalization_type) 117 | self.up3 = Up(widths[1], widths[0], bilinear, normalization_type=normalization_type) 118 | self.outc = OutConv(widths[0], n_channels) 119 | 120 | # mean / std output 121 | self.normal_mean = nn.Parameter(torch.zeros(n_channels, input_size, input_size)) 122 | self.normal_logstd = nn.Parameter(torch.ones(1) * math.log(self.init_std)) 123 | self.mean_shape = (n_channels, input_size, input_size) 124 | 125 | # whiten function placeholder 126 | # we can not assign value to it now since input_mean / input_std is unknown yet 127 | # we will assign appropriate function in StandardPolicyModel.__init__ 128 | self.whiten_func = lambda t: 1 / 0 129 | 130 | # init weights 131 | for m in self.modules(): 132 | if isinstance(m, (nn.Conv2d, nn.ConvTranspose2d, nn.Linear)): 133 | nn.init.kaiming_normal_(m.weight) 134 | if m.bias is not None: 135 | nn.init.constant_(m.bias, 0) 136 | elif isinstance(m, (nn.BatchNorm2d, nn.GroupNorm)): 137 | nn.init.constant_(m.weight, 1) 138 | nn.init.constant_(m.bias, 0) 139 | 140 | def forward(self, adv_image, image, label, target, output_fields): 141 | output = dict() 142 | if 'grad' in output_fields: 143 | # whiten input 144 | adv_image = self.whiten_func(adv_image) 145 | 146 | x = adv_image 147 | x1 = self.inc(x) # widths[0] channels 148 | x2 = self.down1(x1) # widths[1] channels 149 | x3 = self.down2(x2) # widths[2] channels 150 | x4 = self.down3(x3) # widths[3] // 2 channels if bilinear, else widths[3] 151 | x = self.up1(x4, x3) # widths[2] // 2 channels if bilinear, else widths[2] 152 | x = self.up2(x, x2) # widths[1] // 2 channels if bilinear, else widths[1] 153 | x = self.up3(x, x1) # widths[0] channels 154 | x = self.outc(x) # n_channels, same as input image 155 | x = x + self.normal_mean.view(1, *self.mean_shape).repeat(x.shape[0], 1, 1, 1) 156 | 157 | output['grad'] = x 158 | 159 | if 'std' in output_fields: 160 | output['std'] = self.normal_logstd.exp() 161 | return output 162 | 163 | def rescale(self, scale): 164 | self.outc.conv.weight.data[:] *= scale 165 | if self.outc.conv.bias: 166 | self.outc.conv.bias.data[:] *= scale 167 | self.normal_mean.data[:] *= scale 168 | 169 | 170 | def unet(**kwargs): 171 | return UNet(**kwargs) 172 | -------------------------------------------------------------------------------- /models/policy/cifar/vgg_inv.py: -------------------------------------------------------------------------------- 1 | import math 2 | import torch 3 | import torch.nn as nn 4 | from models.policy.common import normalization, inv_forward 5 | 6 | __all__ = ['vgg11_inv', 'vgg13_inv', 'vgg16_inv', 'vgg19_inv'] 7 | 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 VGGInv(nn.Module): 18 | def __init__(self, vgg_name, use_tanh=True, calibrate=True, 19 | normalization_type='none', input_size=32, init_std=1/32.): 20 | super(VGGInv, self).__init__() 21 | # save arguments 22 | self.input_size = input_size 23 | self.init_std = init_std 24 | self.normalization_type = normalization_type 25 | self.use_tanh = use_tanh 26 | self.calibrate = calibrate 27 | 28 | # main body of vgg inverse 29 | self.features = self._make_layers(cfg[vgg_name]) 30 | self.classifier = nn.Linear(512, 10) 31 | 32 | # mean / std output 33 | self.normal_mean = nn.Parameter(torch.zeros(3, input_size, input_size)) 34 | self.normal_logstd = nn.Parameter(torch.ones(1) * math.log(self.init_std)) 35 | self.mean_shape = (3, input_size, input_size) 36 | 37 | # whiten function placeholder 38 | # we can not assign value to it now since input_mean / input_std is unknown yet 39 | # we will assign appropriate function in StandardPolicyModel.__init__ 40 | self.whiten_func = lambda t: 1 / 0 41 | 42 | # coefficient to tune between prior knowledge and empty network 43 | self.empty_coeff = nn.Parameter(torch.ones(1) * 0.5) 44 | self.empty_normal_mean = nn.Parameter(torch.zeros(3, input_size, input_size)) 45 | 46 | # init weights 47 | for m in self.modules(): 48 | if isinstance(m, (nn.Conv2d, nn.ConvTranspose2d, nn.Linear)): 49 | nn.init.kaiming_normal_(m.weight) 50 | if m.bias is not None: 51 | nn.init.constant_(m.bias, 0) 52 | elif isinstance(m, (nn.BatchNorm2d, nn.GroupNorm)): 53 | nn.init.constant_(m.weight, 1) 54 | nn.init.constant_(m.bias, 0) 55 | 56 | def _make_layers(self, cfg): 57 | layers = [] 58 | in_channels = 3 59 | for layer_index, x in enumerate(cfg): 60 | if x == 'M': 61 | # append max pooling layer 62 | layers += [nn.MaxPool2d(kernel_size=2, stride=2)] 63 | else: 64 | # append conv->(bn/gn)->activation layer 65 | # determine activation function: we use tanh for last layer if self.use_tanh is set to True 66 | is_last_layer = True 67 | for xx in cfg[layer_index+1:]: 68 | if xx != 'M': 69 | is_last_layer = False 70 | if self.use_tanh and is_last_layer: 71 | activation = nn.Tanh() 72 | else: 73 | activation = nn.ReLU(inplace=True) 74 | 75 | layers += [nn.Conv2d(in_channels, x, kernel_size=3, padding=1), 76 | normalization(self.normalization_type, x), 77 | activation] 78 | in_channels = x 79 | layers += [nn.AvgPool2d(kernel_size=1, stride=1)] 80 | return nn.Sequential(*layers) 81 | 82 | def get_logit(self, x): 83 | # whiten input 84 | x = self.whiten_func(x) 85 | 86 | out = self.features(x) 87 | out = out.view(out.size(0), -1) 88 | out = self.classifier(out) 89 | return out 90 | 91 | def forward(self, adv_image, image, label, target, output_fields): 92 | output = inv_forward( 93 | adv_image=adv_image, image=image, label=label, target=target, get_logit=self.get_logit, 94 | normal_mean=self.normal_mean, empty_coeff=self.empty_coeff, empty_normal_mean=self.empty_normal_mean, 95 | training=self.training, calibrate=self.calibrate, output_fields=output_fields) 96 | if 'std' in output_fields: 97 | output['std'] = self.normal_logstd.exp() 98 | return output 99 | 100 | def rescale(self, scale): 101 | raise NotImplementedError 102 | 103 | 104 | def vgg11_inv(**kwargs): 105 | return VGGInv('vgg11', **kwargs) 106 | 107 | 108 | def vgg13_inv(**kwargs): 109 | return VGGInv('vgg13', **kwargs) 110 | 111 | 112 | def vgg16_inv(**kwargs): 113 | return VGGInv('vgg16', **kwargs) 114 | 115 | 116 | def vgg19_inv(**kwargs): 117 | return VGGInv('vgg19', **kwargs) 118 | -------------------------------------------------------------------------------- /models/policy/cifar/wrn_inv.py: -------------------------------------------------------------------------------- 1 | import math 2 | import torch 3 | import torch.nn as nn 4 | import torch.nn.functional as F 5 | from models.policy.common import normalization, inv_forward 6 | 7 | __all__ = ['wrn_28_10_drop_inv'] 8 | 9 | 10 | def normalization16(normalization_type, planes): 11 | return normalization(normalization_type, planes, group_size=16) 12 | 13 | 14 | class BasicBlock(nn.Module): 15 | def __init__(self, in_planes, out_planes, stride, drop_rate=0.0, normalization_type='none'): 16 | super(BasicBlock, self).__init__() 17 | self.bn1 = normalization16(normalization_type, in_planes) 18 | self.relu1 = nn.ReLU(inplace=True) 19 | self.conv1 = nn.Conv2d(in_planes, out_planes, kernel_size=3, stride=stride, 20 | padding=1, bias=False) 21 | self.bn2 = normalization16(normalization_type, out_planes) 22 | self.relu2 = nn.ReLU(inplace=True) 23 | self.conv2 = nn.Conv2d(out_planes, out_planes, kernel_size=3, stride=1, 24 | padding=1, bias=False) 25 | self.droprate = drop_rate 26 | self.equalInOut = (in_planes == out_planes) 27 | self.convShortcut = (not self.equalInOut) and nn.Conv2d(in_planes, out_planes, kernel_size=1, stride=stride, 28 | padding=0, bias=False) or None 29 | 30 | def forward(self, x): 31 | if not self.equalInOut: 32 | x = self.relu1(self.bn1(x)) 33 | else: 34 | out = self.relu1(self.bn1(x)) 35 | out = self.relu2(self.bn2(self.conv1(out if self.equalInOut else x))) 36 | if self.droprate > 0: 37 | out = F.dropout(out, p=self.droprate, training=self.training) 38 | out = self.conv2(out) 39 | return torch.add(x if self.equalInOut else self.convShortcut(x), out) 40 | 41 | 42 | class NetworkBlock(nn.Module): 43 | def __init__(self, nb_layers, in_planes, out_planes, block, stride, drop_rate=0.0, normalization_type='none'): 44 | super(NetworkBlock, self).__init__() 45 | self.layer = self._make_layer(block, in_planes, out_planes, nb_layers, stride, drop_rate, normalization_type) 46 | 47 | def _make_layer(self, block, in_planes, out_planes, nb_layers, stride, drop_rate, normalization_type='none'): 48 | layers = [] 49 | for i in range(nb_layers): 50 | layers.append(block(i == 0 and in_planes or out_planes, out_planes, i == 0 and stride or 1, drop_rate, 51 | normalization_type)) 52 | return nn.Sequential(*layers) 53 | 54 | def forward(self, x): 55 | return self.layer(x) 56 | 57 | 58 | class WRNInv(nn.Module): 59 | def __init__(self, depth, widen_factor=1, drop_rate=0.0, use_tanh=True, calibrate=True, 60 | normalization_type='none', input_size=32, init_std=1 / 32.): 61 | super(WRNInv, self).__init__() 62 | # save arguments 63 | self.depth = depth 64 | self.input_size = input_size 65 | self.init_std = init_std 66 | self.normalization_type = normalization_type 67 | self.use_tanh = use_tanh 68 | self.calibrate = calibrate 69 | 70 | # main body of wrn inverse 71 | nChannels = [16, 16 * widen_factor, 32 * widen_factor, 64 * widen_factor] 72 | assert (depth - 4) % 6 == 0, 'depth should be 6n+4' 73 | n = (depth - 4) // 6 74 | block = BasicBlock 75 | # 1st conv before any network block 76 | self.conv1 = nn.Conv2d(3, nChannels[0], kernel_size=3, stride=1, 77 | padding=1, bias=False) 78 | # 1st block 79 | self.block1 = NetworkBlock(n, nChannels[0], nChannels[1], block, 1, drop_rate) 80 | # 2nd block 81 | self.block2 = NetworkBlock(n, nChannels[1], nChannels[2], block, 2, drop_rate) 82 | # 3rd block 83 | self.block3 = NetworkBlock(n, nChannels[2], nChannels[3], block, 2, drop_rate) 84 | # global average pooling and classifier 85 | self.bn1 = normalization16(normalization_type, nChannels[3]) 86 | self.relu = nn.ReLU(inplace=True) 87 | self.fc = nn.Linear(nChannels[3], 10) 88 | self.nChannels = nChannels[3] 89 | 90 | # mean / std output 91 | self.normal_mean = nn.Parameter(torch.zeros(3, input_size, input_size)) 92 | self.normal_logstd = nn.Parameter(torch.ones(1) * math.log(self.init_std)) 93 | self.mean_shape = (3, input_size, input_size) 94 | 95 | # whiten function placeholder 96 | # we can not assign value to it now since input_mean / input_std is unknown yet 97 | # we will assign appropriate function in StandardPolicyModel.__init__ 98 | self.whiten_func = lambda t: 1 / 0 99 | 100 | # coefficient to tune between prior knowledge and empty network 101 | self.empty_coeff = nn.Parameter(torch.ones(1) * 0.5) 102 | self.empty_normal_mean = nn.Parameter(torch.zeros(3, input_size, input_size)) 103 | 104 | # init weights 105 | for m in self.modules(): 106 | if isinstance(m, nn.Conv2d): 107 | n = m.kernel_size[0] * m.kernel_size[1] * m.out_channels 108 | m.weight.data.normal_(0, math.sqrt(2. / n)) 109 | elif isinstance(m, (nn.BatchNorm2d, nn.GroupNorm)): 110 | m.weight.data.fill_(1) 111 | m.bias.data.zero_() 112 | elif isinstance(m, nn.Linear): 113 | m.bias.data.zero_() 114 | 115 | def get_logit(self, x): 116 | # whiten input 117 | x = self.whiten_func(x) 118 | 119 | out = self.conv1(x) 120 | out = self.block1(out) 121 | out = self.block2(out) 122 | out = self.block3(out) 123 | out = self.relu(self.bn1(out)) 124 | out = F.avg_pool2d(out, 8) 125 | out = out.view(-1, self.nChannels) 126 | return self.fc(out) 127 | 128 | def forward(self, adv_image, image, label, target, output_fields): 129 | output = inv_forward( 130 | adv_image=adv_image, image=image, label=label, target=target, get_logit=self.get_logit, 131 | normal_mean=self.normal_mean, empty_coeff=self.empty_coeff, empty_normal_mean=self.empty_normal_mean, 132 | training=self.training, calibrate=self.calibrate, output_fields=output_fields) 133 | if 'std' in output_fields: 134 | output['std'] = self.normal_logstd.exp() 135 | return output 136 | 137 | def rescale(self, scale): 138 | raise NotImplementedError 139 | 140 | 141 | def wrn_28_10_drop_inv(**kwargs): 142 | return WRNInv(depth=28, widen_factor=10, drop_rate=0.3, **kwargs) 143 | -------------------------------------------------------------------------------- /models/policy/common.py: -------------------------------------------------------------------------------- 1 | import torch 2 | import torch.nn as nn 3 | import torch.nn.functional as F 4 | 5 | __all__ = ['normalization', 'inv_forward'] 6 | 7 | 8 | def normalization(normalization_type, planes, group_size=32): 9 | # return normalization layer given normalization_type and 10 | if normalization_type == 'none': 11 | return nn.Identity() 12 | elif normalization_type == 'bn': 13 | return nn.BatchNorm2d(planes) 14 | elif normalization_type == 'gn': 15 | assert planes % group_size == 0 16 | return nn.GroupNorm(num_groups=planes//group_size, num_channels=planes) 17 | else: 18 | raise ValueError('Unknown normalization method: {}'.format(normalization)) 19 | 20 | 21 | @torch.enable_grad() 22 | def inv_forward(adv_image, image, label, target, get_logit, normal_mean, empty_coeff, empty_normal_mean, 23 | training, calibrate, output_fields): 24 | assert empty_normal_mean.shape[-1] == normal_mean.shape[-1] 25 | assert adv_image.shape[-1] == image.shape[-1] 26 | batch_size = adv_image.shape[0] 27 | 28 | output = dict() 29 | if 'adv_logit' in output_fields or 'grad' in output_fields: 30 | # run the classification network first, then calculate cw loss, then calculate grad: d(cw_loss) / d(adv_image) 31 | if 'grad' in output_fields: 32 | adv_image.requires_grad = True 33 | adv_logit = get_logit(adv_image) 34 | if 'adv_logit' in output_fields: 35 | output['adv_logit'] = adv_logit 36 | 37 | if 'grad' in output_fields: 38 | # now calculate cw loss: logit_y - logit_t 39 | # the gradient direction which minimize the loss should point towards the adversarial region 40 | loss = adv_logit[torch.arange(batch_size), target] - adv_logit[torch.arange(batch_size), label] 41 | grad = torch.autograd.grad(loss.mean() * batch_size, adv_image, create_graph=training)[0] 42 | adv_image.requires_grad = False 43 | 44 | # resize grad to the scale of normal_mean 45 | if grad.shape[-1] != normal_mean.shape[-1]: 46 | grad = F.interpolate(grad, size=normal_mean.shape[-1], mode='bilinear', align_corners=True) 47 | 48 | # add normal mean 49 | grad = grad + normal_mean.view(1, *normal_mean.shape).repeat(batch_size, 1, 1, 1) 50 | 51 | # calibration: tune l2 norm of output then mix grad and empty_normal_mean using empty_coeff 52 | if calibrate: 53 | grad = grad / torch.clamp(grad.view(batch_size, -1).norm(dim=1).view(-1, 1, 1, 1), min=1e-2) 54 | empty_normal_mean = empty_normal_mean / torch.clamp(empty_normal_mean.norm(), min=1e-2) 55 | empty_coeff.data[:] = torch.clamp(empty_coeff.data, 0, 1) 56 | grad = (1. - empty_coeff) * grad + \ 57 | empty_coeff * empty_normal_mean.view(1, *empty_normal_mean.shape).repeat(batch_size, 1, 1, 1) 58 | output['grad'] = grad 59 | if 'logit' in output_fields: 60 | output['logit'] = get_logit(image) 61 | return output 62 | -------------------------------------------------------------------------------- /models/policy/debug/__init__.py: -------------------------------------------------------------------------------- 1 | from models.policy.debug.empty import * 2 | from models.policy.debug.lr_inv import * 3 | -------------------------------------------------------------------------------- /models/policy/debug/empty.py: -------------------------------------------------------------------------------- 1 | import math 2 | import torch 3 | import torch.nn as nn 4 | 5 | __all__ = ['empty'] 6 | 7 | 8 | class Empty(nn.Module): 9 | def __init__(self, init_std=0.001): 10 | super(Empty, self).__init__() 11 | # save arguments 12 | self.init_std = init_std 13 | 14 | # mean / std output 15 | self.normal_mean = nn.Parameter(torch.zeros(2)) 16 | self.normal_logstd = nn.Parameter(torch.ones(1) * math.log(self.init_std)) 17 | self.mean_shape = (2,) 18 | 19 | # whiten function placeholder 20 | # we can not assign value to it now since input_mean / input_std is unknown yet 21 | # we will assign appropriate function in StandardPolicyModel.__init__ 22 | self.whiten_func = lambda t: 1 / 0 23 | 24 | def forward(self, adv_image, image, label, target, output_fields): 25 | output = dict() 26 | if 'grad' in output_fields: 27 | output['grad'] = self.normal_mean.view(1, *self.mean_shape).repeat(adv_image.shape[0], 1) 28 | if 'std' in output_fields: 29 | output['std'] = self.normal_logstd.exp() 30 | return output 31 | 32 | def rescale(self, scale): 33 | self.normal_mean.data[:] *= scale 34 | 35 | 36 | def empty(**kwargs): 37 | return Empty(**kwargs) 38 | -------------------------------------------------------------------------------- /models/policy/debug/lr_inv.py: -------------------------------------------------------------------------------- 1 | import math 2 | import torch 3 | import torch.nn as nn 4 | import torch.nn.functional as F 5 | from models.policy.common import inv_forward 6 | 7 | __all__ = ['carlinet_inv'] 8 | 9 | 10 | class CarliNetInv(nn.Module): 11 | def __init__(self, use_tanh=True, calibrate=True, input_size=28, init_std=1/28.): 12 | super(CarliNetInv, self).__init__() 13 | # save arguments 14 | self.input_size = input_size 15 | self.init_std = init_std 16 | self.use_tanh = use_tanh 17 | self.calibrate = calibrate 18 | 19 | # main body of carlinet inverse 20 | self.conv2d_1 = nn.Conv2d(1, 32, 3) 21 | self.conv2d_2 = nn.Conv2d(32, 32, 3) 22 | self.conv2d_3 = nn.Conv2d(32, 64, 3) 23 | self.conv2d_4 = nn.Conv2d(64, 64, 3) 24 | 25 | self.dense_1 = nn.Linear(1024, 200) 26 | self.dense_2 = nn.Linear(200, 200) 27 | self.dense_3 = nn.Linear(200, 10) 28 | 29 | # mean / std output 30 | self.normal_mean = nn.Parameter(torch.zeros(1, input_size, input_size)) 31 | self.normal_logstd = nn.Parameter(torch.ones(1) * math.log(self.init_std)) 32 | self.mean_shape = (1, input_size, input_size) 33 | 34 | # whiten function placeholder 35 | # we can not assign value to it now since input_mean / input_std is unknown yet 36 | # we will assign appropriate function in StandardPolicyModel.__init__ 37 | self.whiten_func = lambda t: 1 / 0 38 | 39 | # coefficient to tune between prior knowledge and empty network 40 | self.empty_coeff = nn.Parameter(torch.ones(1) * 0.5) 41 | self.empty_normal_mean = nn.Parameter(torch.zeros(3, input_size, input_size)) 42 | 43 | # init weights 44 | for m in self.modules(): 45 | if isinstance(m, (nn.Conv2d, nn.ConvTranspose2d, nn.Linear)): 46 | nn.init.kaiming_normal_(m.weight) 47 | if m.bias is not None: 48 | nn.init.constant_(m.bias, 0) 49 | elif isinstance(m, (nn.BatchNorm2d, nn.GroupNorm)): 50 | nn.init.constant_(m.weight, 1) 51 | nn.init.constant_(m.bias, 0) 52 | 53 | def get_logit(self, x): 54 | # whiten input 55 | x = self.whiten_func(x) 56 | 57 | x = self.conv2d_1(x) 58 | x = F.relu(x) 59 | x = self.conv2d_2(x) 60 | x = F.relu(x) 61 | x = F.max_pool2d(x, (2, 2)) 62 | 63 | x = self.conv2d_3(x) 64 | x = F.relu(x) 65 | x = self.conv2d_4(x) 66 | x = F.relu(x) 67 | x = F.max_pool2d(x, (2, 2)) 68 | 69 | # carlini's keras model data format: (N, H, W, C) 70 | # pytorch data format: (N, C, H, W) 71 | # we need to transpose pytorch data format into keras data format, to make sure the flatten operator 72 | # has the same effect. 73 | x = x.transpose(1, 2).transpose(2, 3).contiguous().view(x.shape[0], -1) 74 | x = self.dense_1(x) 75 | x = F.relu(x) 76 | x = self.dense_2(x) 77 | if self.use_tanh: 78 | x = F.tanh(x) 79 | else: 80 | x = F.relu(x) 81 | logit = self.dense_3(x) 82 | 83 | return logit 84 | 85 | def forward(self, adv_image, image, label, target, output_fields): 86 | output = inv_forward( 87 | adv_image=adv_image, image=image, label=label, target=target, get_logit=self.get_logit, 88 | normal_mean=self.normal_mean, empty_coeff=self.empty_coeff, empty_normal_mean=self.empty_normal_mean, 89 | training=self.training, calibrate=self.calibrate, output_fields=output_fields) 90 | if 'std' in output_fields: 91 | output['std'] = self.normal_logstd.exp() 92 | return output 93 | 94 | def rescale(self, scale): 95 | raise NotImplementedError 96 | 97 | 98 | def carlinet_inv(**kwargs): 99 | return CarliNetInv(**kwargs) 100 | -------------------------------------------------------------------------------- /models/policy/imagenet/__init__.py: -------------------------------------------------------------------------------- 1 | from models.policy.imagenet.empty import * 2 | from models.policy.imagenet.vgg_inv import * 3 | -------------------------------------------------------------------------------- /models/policy/imagenet/empty.py: -------------------------------------------------------------------------------- 1 | import math 2 | import torch 3 | import torch.nn as nn 4 | 5 | __all__ = ['empty'] 6 | 7 | 8 | class Empty(nn.Module): 9 | def __init__(self, input_size=32, init_std=1/32.): 10 | super(Empty, self).__init__() 11 | # save arguments 12 | self.init_std = init_std 13 | 14 | # mean / std output 15 | self.normal_mean = nn.Parameter(torch.zeros(3, input_size, input_size)) 16 | self.normal_logstd = nn.Parameter(torch.ones(1) * math.log(self.init_std)) 17 | self.mean_shape = (3, input_size, input_size) 18 | 19 | # whiten function placeholder 20 | # we can not assign value to it now since input_mean / input_std is unknown yet 21 | # we will assign appropriate function in StandardPolicyModel.__init__ 22 | self.whiten_func = lambda t: 1 / 0 23 | 24 | def forward(self, adv_image, image, label, target, output_fields): 25 | output = dict() 26 | if 'grad' in output_fields: 27 | output['grad'] = self.normal_mean.view(1, *self.mean_shape).repeat(adv_image.shape[0], 1, 1, 1) 28 | if 'std' in output_fields: 29 | output['std'] = self.normal_logstd.exp() 30 | return output 31 | 32 | def rescale(self, scale): 33 | self.normal_mean.data[:] *= scale 34 | 35 | 36 | def empty(**kwargs): 37 | return Empty(**kwargs) 38 | -------------------------------------------------------------------------------- /models/policy/imagenet/vgg_inv.py: -------------------------------------------------------------------------------- 1 | import math 2 | import torch 3 | import torch.nn as nn 4 | from models.policy.common import normalization, inv_forward 5 | 6 | __all__ = ['vgg11_inv', 'vgg13_inv', 'vgg16_inv', 'vgg19_inv'] 7 | 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 VGGInv(nn.Module): 18 | def __init__(self, vgg_name, use_tanh=True, calibrate=True, 19 | normalization_type='none', input_size=224, init_std=1/224.): 20 | super(VGGInv, self).__init__() 21 | # save arguments 22 | self.input_size = input_size 23 | self.init_std = init_std 24 | self.normalization_type = normalization_type 25 | self.use_tanh = use_tanh 26 | self.calibrate = calibrate 27 | 28 | # main body of vgg inverse 29 | self.features = self._make_layers(cfg[vgg_name]) 30 | self.classifier = nn.Sequential( 31 | nn.Linear(512 * 7 * 7, 4096), 32 | nn.ReLU(True), 33 | nn.Linear(4096, 4096), 34 | nn.ReLU(True), 35 | nn.Linear(4096, 1000), 36 | ) 37 | 38 | # mean / std output 39 | self.normal_mean = nn.Parameter(torch.zeros(3, input_size, input_size)) 40 | self.normal_logstd = nn.Parameter(torch.ones(1) * math.log(self.init_std)) 41 | self.mean_shape = (3, input_size, input_size) 42 | 43 | # whiten function placeholder 44 | # we can not assign value to it now since input_mean / input_std is unknown yet 45 | # we will assign appropriate function in StandardPolicyModel.__init__ 46 | self.whiten_func = lambda t: 1 / 0 47 | 48 | # coefficient to tune between prior knowledge and empty network 49 | self.empty_coeff = nn.Parameter(torch.ones(1) * 0.5) 50 | self.empty_normal_mean = nn.Parameter(torch.zeros(3, input_size, input_size)) 51 | 52 | # init weights 53 | for m in self.modules(): 54 | if isinstance(m, (nn.Conv2d, nn.ConvTranspose2d, nn.Linear)): 55 | nn.init.kaiming_normal_(m.weight) 56 | if m.bias is not None: 57 | nn.init.constant_(m.bias, 0) 58 | elif isinstance(m, (nn.BatchNorm2d, nn.GroupNorm)): 59 | nn.init.constant_(m.weight, 1) 60 | nn.init.constant_(m.bias, 0) 61 | 62 | def _make_layers(self, cfg): 63 | layers = [] 64 | in_channels = 3 65 | for layer_index, x in enumerate(cfg): 66 | if x == 'M': 67 | # append max pooling layer 68 | layers += [nn.MaxPool2d(kernel_size=2, stride=2)] 69 | else: 70 | # append conv->(bn/gn)->activation layer 71 | # determine activation function: we use tanh for last layer if self.use_tanh is set to True 72 | is_last_layer = True 73 | for xx in cfg[layer_index+1:]: 74 | if xx != 'M': 75 | is_last_layer = False 76 | if self.use_tanh and is_last_layer: 77 | activation = nn.Tanh() 78 | else: 79 | activation = nn.ReLU(inplace=True) 80 | 81 | layers += [nn.Conv2d(in_channels, x, kernel_size=3, padding=1), 82 | normalization(self.normalization_type, x), 83 | activation] 84 | in_channels = x 85 | # imagenet vgg13 does not do that 86 | # layers += [nn.AvgPool2d(kernel_size=1, stride=1)] 87 | return nn.Sequential(*layers) 88 | 89 | def get_logit(self, x): 90 | # whiten input 91 | x = self.whiten_func(x) 92 | 93 | out = self.features(x) 94 | out = out.view(out.size(0), -1) 95 | out = self.classifier(out) 96 | return out 97 | 98 | def forward(self, adv_image, image, label, target, output_fields): 99 | output = inv_forward( 100 | adv_image=adv_image, image=image, label=label, target=target, get_logit=self.get_logit, 101 | normal_mean=self.normal_mean, empty_coeff=self.empty_coeff, empty_normal_mean=self.empty_normal_mean, 102 | training=self.training, calibrate=self.calibrate, output_fields=output_fields) 103 | if 'std' in output_fields: 104 | output['std'] = self.normal_logstd.exp() 105 | return output 106 | 107 | def rescale(self, scale): 108 | raise NotImplementedError 109 | 110 | 111 | def vgg11_inv(**kwargs): 112 | return VGGInv('vgg11', **kwargs) 113 | 114 | 115 | def vgg13_inv(**kwargs): 116 | return VGGInv('vgg13', **kwargs) 117 | 118 | 119 | def vgg16_inv(**kwargs): 120 | return VGGInv('vgg16', **kwargs) 121 | 122 | 123 | def vgg19_inv(**kwargs): 124 | return VGGInv('vgg19', **kwargs) 125 | -------------------------------------------------------------------------------- /models/policy/mnist/__init__.py: -------------------------------------------------------------------------------- 1 | from models.policy.mnist.empty import * 2 | from models.policy.mnist.unet import * 3 | from models.policy.mnist.carlinet_inv import * 4 | from models.policy.mnist.vgg_inv import * 5 | 6 | -------------------------------------------------------------------------------- /models/policy/mnist/carlinet_inv.py: -------------------------------------------------------------------------------- 1 | import math 2 | import torch 3 | import torch.nn as nn 4 | import torch.nn.functional as F 5 | from models.policy.common import inv_forward 6 | 7 | __all__ = ['carlinet_inv'] 8 | 9 | 10 | class CarliNetInv(nn.Module): 11 | def __init__(self, use_tanh=True, calibrate=True, input_size=28, init_std=1/28.): 12 | super(CarliNetInv, self).__init__() 13 | # save arguments 14 | self.input_size = input_size 15 | self.init_std = init_std 16 | self.use_tanh = use_tanh 17 | self.calibrate = calibrate 18 | 19 | # main body of carlinet inverse 20 | self.conv2d_1 = nn.Conv2d(1, 32, 3) 21 | self.conv2d_2 = nn.Conv2d(32, 32, 3) 22 | self.conv2d_3 = nn.Conv2d(32, 64, 3) 23 | self.conv2d_4 = nn.Conv2d(64, 64, 3) 24 | 25 | self.dense_1 = nn.Linear(1024, 200) 26 | self.dense_2 = nn.Linear(200, 200) 27 | self.dense_3 = nn.Linear(200, 10) 28 | 29 | # mean / std output 30 | self.normal_mean = nn.Parameter(torch.zeros(1, input_size, input_size)) 31 | self.normal_logstd = nn.Parameter(torch.ones(1) * math.log(self.init_std)) 32 | self.mean_shape = (1, input_size, input_size) 33 | 34 | # whiten function placeholder 35 | # we can not assign value to it now since input_mean / input_std is unknown yet 36 | # we will assign appropriate function in StandardPolicyModel.__init__ 37 | self.whiten_func = lambda t: 1 / 0 38 | 39 | # coefficient to tune between prior knowledge and empty network 40 | self.empty_coeff = nn.Parameter(torch.ones(1) * 0.5) 41 | self.empty_normal_mean = nn.Parameter(torch.zeros(1, input_size, input_size)) 42 | 43 | # init weights 44 | for m in self.modules(): 45 | if isinstance(m, (nn.Conv2d, nn.ConvTranspose2d, nn.Linear)): 46 | nn.init.kaiming_normal_(m.weight) 47 | if m.bias is not None: 48 | nn.init.constant_(m.bias, 0) 49 | elif isinstance(m, (nn.BatchNorm2d, nn.GroupNorm)): 50 | nn.init.constant_(m.weight, 1) 51 | nn.init.constant_(m.bias, 0) 52 | 53 | def get_logit(self, x): 54 | # whiten input 55 | x = self.whiten_func(x) 56 | 57 | x = self.conv2d_1(x) 58 | x = F.relu(x) 59 | x = self.conv2d_2(x) 60 | x = F.relu(x) 61 | x = F.max_pool2d(x, (2, 2)) 62 | 63 | x = self.conv2d_3(x) 64 | x = F.relu(x) 65 | x = self.conv2d_4(x) 66 | x = F.relu(x) 67 | x = F.max_pool2d(x, (2, 2)) 68 | 69 | # carlini's keras model data format: (N, H, W, C) 70 | # pytorch data format: (N, C, H, W) 71 | # we need to transpose pytorch data format into keras data format, to make sure the flatten operator 72 | # has the same effect. 73 | x = x.transpose(1, 2).transpose(2, 3).contiguous().view(x.shape[0], -1) 74 | x = self.dense_1(x) 75 | x = F.relu(x) 76 | x = self.dense_2(x) 77 | if self.use_tanh: 78 | x = F.tanh(x) 79 | else: 80 | x = F.relu(x) 81 | logit = self.dense_3(x) 82 | 83 | return logit 84 | 85 | def forward(self, adv_image, image, label, target, output_fields): 86 | output = inv_forward( 87 | adv_image=adv_image, image=image, label=label, target=target, get_logit=self.get_logit, 88 | normal_mean=self.normal_mean, empty_coeff=self.empty_coeff, empty_normal_mean=self.empty_normal_mean, 89 | training=self.training, calibrate=self.calibrate, output_fields=output_fields) 90 | if 'std' in output_fields: 91 | output['std'] = self.normal_logstd.exp() 92 | return output 93 | 94 | def rescale(self, scale): 95 | raise NotImplementedError 96 | 97 | 98 | def carlinet_inv(**kwargs): 99 | return CarliNetInv(**kwargs) 100 | -------------------------------------------------------------------------------- /models/policy/mnist/empty.py: -------------------------------------------------------------------------------- 1 | import math 2 | import torch 3 | import torch.nn as nn 4 | 5 | __all__ = ['empty'] 6 | 7 | 8 | class Empty(nn.Module): 9 | def __init__(self, input_size=28, init_std=1/28.): 10 | super(Empty, self).__init__() 11 | # save arguments 12 | self.init_std = init_std 13 | 14 | # mean / std output 15 | self.normal_mean = nn.Parameter(torch.zeros(1, input_size, input_size)) 16 | self.normal_logstd = nn.Parameter(torch.ones(1) * math.log(self.init_std)) 17 | self.mean_shape = (1, input_size, input_size) 18 | 19 | # whiten function placeholder 20 | # we can not assign value to it now since input_mean / input_std is unknown yet 21 | # we will assign appropriate function in StandardPolicyModel.__init__ 22 | self.whiten_func = lambda t: 1 / 0 23 | 24 | def forward(self, adv_image, image, label, target, output_fields): 25 | output = dict() 26 | if 'grad' in output_fields: 27 | output['grad'] = self.normal_mean.view(1, *self.mean_shape).repeat(adv_image.shape[0], 1, 1, 1) 28 | if 'std' in output_fields: 29 | output['std'] = self.normal_logstd.exp() 30 | return output 31 | 32 | def rescale(self, scale): 33 | self.normal_mean.data[:] *= scale 34 | 35 | 36 | def empty(**kwargs): 37 | return Empty(**kwargs) 38 | -------------------------------------------------------------------------------- /models/policy/mnist/unet.py: -------------------------------------------------------------------------------- 1 | # code borrowed from https://github.com/milesial/Pytorch-UNet 2 | import math 3 | import torch 4 | import torch.nn as nn 5 | import torch.nn.functional as F 6 | 7 | __all__ = ['unet'] 8 | 9 | 10 | def normalization(normalization_type, planes): 11 | if normalization_type == 'none': 12 | return nn.Identity() 13 | elif normalization_type == 'bn': 14 | return nn.BatchNorm2d(planes) 15 | elif normalization_type == 'gn': 16 | return nn.GroupNorm(num_groups=planes//32, num_channels=planes) 17 | else: 18 | raise ValueError('Unknown normalization method: {}'.format(normalization)) 19 | 20 | 21 | class DoubleConv(nn.Module): 22 | """(convolution => [BN] => ReLU) * 2""" 23 | 24 | def __init__(self, in_channels, out_channels, mid_channels=None, normalization_type='none'): 25 | super(DoubleConv, self).__init__() 26 | if not mid_channels: 27 | mid_channels = out_channels 28 | 29 | self.double_conv = list() 30 | self.double_conv.append(nn.Conv2d(in_channels, mid_channels, kernel_size=3, padding=1)) 31 | self.double_conv.append(normalization(normalization_type, mid_channels)) 32 | self.double_conv.append(nn.ReLU(inplace=True)) 33 | self.double_conv.append(nn.Conv2d(mid_channels, out_channels, kernel_size=3, padding=1)) 34 | self.double_conv.append(normalization(normalization_type, out_channels)) 35 | self.double_conv.append(nn.ReLU(inplace=True)) 36 | 37 | # make double_conv as a nn.Module with nn.Sequential 38 | self.double_conv = nn.Sequential(*self.double_conv) 39 | 40 | def forward(self, x): 41 | return self.double_conv(x) 42 | 43 | 44 | class Down(nn.Module): 45 | """Downscaling with maxpool then double conv""" 46 | 47 | def __init__(self, in_channels, out_channels, normalization_type='none'): 48 | super(Down, self).__init__() 49 | self.maxpool_conv = nn.Sequential( 50 | nn.MaxPool2d(2), 51 | DoubleConv(in_channels, out_channels, normalization_type=normalization_type) 52 | ) 53 | 54 | def forward(self, x): 55 | return self.maxpool_conv(x) 56 | 57 | 58 | class Up(nn.Module): 59 | """Upscaling then double conv""" 60 | 61 | def __init__(self, in_channels, out_channels, bilinear=True, normalization_type='none'): 62 | super(Up, self).__init__() 63 | 64 | # if not bilinear, use the normal convolutions to reduce the number of channels 65 | if bilinear: 66 | self.up = nn.Upsample(scale_factor=2, mode='bilinear', align_corners=True) 67 | self.conv = DoubleConv(in_channels, out_channels, mid_channels=in_channels // 2, 68 | normalization_type=normalization_type) 69 | else: 70 | self.up = nn.ConvTranspose2d(in_channels, in_channels // 2, kernel_size=2, stride=2) 71 | self.conv = DoubleConv(in_channels, out_channels, normalization_type=normalization_type) 72 | 73 | def forward(self, x1, x2): 74 | x1 = self.up(x1) 75 | # input is CHW 76 | diffY = x2.size()[2] - x1.size()[2] 77 | diffX = x2.size()[3] - x1.size()[3] 78 | 79 | x1 = F.pad(x1, (diffX // 2, diffX - diffX // 2, diffY // 2, diffY - diffY // 2)) 80 | # if you have padding issues, see 81 | # https://github.com/HaiyongJiang/U-Net-Pytorch-Unstructured-Buggy/commit/0e854509c2cea854e247a9c615f175f76fbb2e3a 82 | # https://github.com/xiaopeng-liao/Pytorch-UNet/commit/8ebac70e633bac59fc22bb5195e513d5832fb3bd 83 | x = torch.cat([x2, x1], dim=1) 84 | return self.conv(x) 85 | 86 | 87 | class OutConv(nn.Module): 88 | def __init__(self, in_channels, out_channels): 89 | super(OutConv, self).__init__() 90 | self.conv = nn.Conv2d(in_channels, out_channels, kernel_size=1, bias=False) 91 | 92 | def forward(self, x): 93 | return self.conv(x) 94 | 95 | 96 | class UNet(nn.Module): 97 | def __init__(self, input_size=28, n_channels=1, bilinear=True, 98 | normalization_type='none', base_width=16, init_std=1/28.): 99 | super(UNet, self).__init__() 100 | # save arguments 101 | self.input_size = input_size 102 | self.n_channels = n_channels 103 | self.bilinear = bilinear 104 | self.normalization_type = normalization_type 105 | self.base_width = base_width 106 | self.init_std = init_std 107 | 108 | # main body of unet 109 | widths = [base_width, base_width * 2, base_width * 4] 110 | self.inc = DoubleConv(n_channels, widths[0], normalization_type=normalization_type) 111 | self.down1 = Down(widths[0], widths[1], normalization_type=normalization_type) 112 | factor = 2 if bilinear else 1 113 | self.down2 = Down(widths[1], widths[2] // factor, normalization_type=normalization_type) 114 | self.up1 = Up(widths[2], widths[1] // factor, bilinear, normalization_type=normalization_type) 115 | self.up2 = Up(widths[1], widths[0], bilinear, normalization_type=normalization_type) 116 | self.outc = OutConv(widths[0], n_channels) 117 | 118 | # mean / std output 119 | self.normal_mean = nn.Parameter(torch.zeros(1, input_size, input_size)) 120 | self.normal_logstd = nn.Parameter(torch.ones(1) * math.log(self.init_std)) 121 | self.mean_shape = (1, input_size, input_size) 122 | 123 | # init weights 124 | for m in self.modules(): 125 | if isinstance(m, (nn.Conv2d, nn.ConvTranspose2d, nn.Linear)): 126 | nn.init.kaiming_normal_(m.weight) 127 | if m.bias is not None: 128 | nn.init.constant_(m.bias, 0) 129 | elif isinstance(m, (nn.BatchNorm2d, nn.GroupNorm)): 130 | nn.init.constant_(m.weight, 1) 131 | nn.init.constant_(m.bias, 0) 132 | 133 | def forward(self, adv_image, image, label, target, output_fields): 134 | output = dict() 135 | if 'grad' in output_fields: 136 | # whiten input 137 | adv_image = self.whiten_func(adv_image) 138 | 139 | x = adv_image 140 | x1 = self.inc(x) # widths[0] channels 141 | x2 = self.down1(x1) # widths[1] channels 142 | x3 = self.down2(x2) # widths[2] // 2 channels if bilinear, else widths[2] 143 | x = self.up1(x3, x2) # widths[1] // 2 channels if bilinear, else widths[1] 144 | x = self.up2(x, x1) # widths[0] channels 145 | x = self.outc(x) # n_channels, same as input image 146 | x = x + self.normal_mean.view(1, *self.mean_shape).repeat(x.shape[0], 1, 1, 1) 147 | 148 | output['grad'] = x 149 | 150 | if 'std' in output_fields: 151 | output['std'] = self.normal_logstd.exp() 152 | return output 153 | 154 | def rescale(self, scale): 155 | self.outc.conv.weight.data[:] *= scale 156 | if self.outc.conv.bias: 157 | self.outc.conv.bias.data[:] *= scale 158 | self.normal_mean.data[:] *= scale 159 | 160 | 161 | def unet(**kwargs): 162 | return UNet(**kwargs) 163 | -------------------------------------------------------------------------------- /models/policy/mnist/vgg_inv.py: -------------------------------------------------------------------------------- 1 | import math 2 | import torch 3 | import torch.nn as nn 4 | from models.policy.common import normalization, inv_forward 5 | 6 | __all__ = ['vgg11_inv', 'vgg13_inv', 'vgg16_inv', 'vgg19_inv'] 7 | 8 | 9 | cfg = { 10 | 'vgg11': [32, 'M', 64, 'M', 128, 128, 'M', 256, 256, 'M', 256, 256, 'M'], 11 | 'vgg13': [32, 32, 'M', 64, 64, 'M', 128, 128, 'M', 256, 256, 'M', 256, 256, 'M'], 12 | 'vgg16': [32, 32, 'M', 64, 64, 'M', 128, 128, 128, 'M', 256, 256, 256, 'M', 256, 256, 256, 'M'], 13 | 'vgg19': [32, 32, 'M', 64, 64, 'M', 128, 128, 128, 128, 'M', 256, 256, 256, 256, 'M', 256, 256, 256, 256, 'M'], 14 | } 15 | 16 | 17 | class VGGInv(nn.Module): 18 | def __init__(self, vgg_name, use_tanh=True, calibrate=True, 19 | normalization_type='none', input_size=28, init_std=1/28.): 20 | super(VGGInv, self).__init__() 21 | # save arguments 22 | self.input_size = input_size 23 | self.init_std = init_std 24 | self.normalization_type = normalization_type 25 | self.use_tanh = use_tanh 26 | self.calibrate = calibrate 27 | 28 | # main body of vgg inverse 29 | self.features = self._make_layers(cfg[vgg_name]) 30 | self.classifier = nn.Linear(256, 10) 31 | 32 | # mean / std output 33 | self.normal_mean = nn.Parameter(torch.zeros(1, input_size, input_size)) 34 | self.normal_logstd = nn.Parameter(torch.ones(1) * math.log(self.init_std)) 35 | self.mean_shape = (1, input_size, input_size) 36 | 37 | # whiten function placeholder 38 | # we can not assign value to it now since input_mean / input_std is unknown yet 39 | # we will assign appropriate function in StandardPolicyModel.__init__ 40 | self.whiten_func = lambda t: 1 / 0 41 | 42 | # coefficient to tune between prior knowledge and empty network 43 | self.empty_coeff = nn.Parameter(torch.ones(1) * 0.5) 44 | self.empty_normal_mean = nn.Parameter(torch.zeros(1, input_size, input_size)) 45 | 46 | # init weights 47 | for m in self.modules(): 48 | if isinstance(m, (nn.Conv2d, nn.ConvTranspose2d, nn.Linear)): 49 | nn.init.kaiming_normal_(m.weight) 50 | if m.bias is not None: 51 | nn.init.constant_(m.bias, 0) 52 | elif isinstance(m, (nn.BatchNorm2d, nn.GroupNorm)): 53 | nn.init.constant_(m.weight, 1) 54 | nn.init.constant_(m.bias, 0) 55 | 56 | def _make_layers(self, cfg): 57 | layers = [] 58 | in_channels = 1 59 | for layer_index, x in enumerate(cfg): 60 | if x == 'M': 61 | # append max pooling layer 62 | layers += [nn.MaxPool2d(kernel_size=2, stride=2)] 63 | else: 64 | # append conv->(bn/gn)->activation layer 65 | # determine activation function: we use tanh for last layer if self.use_tanh is set to True 66 | is_last_layer = True 67 | for xx in cfg[layer_index+1:]: 68 | if xx != 'M': 69 | is_last_layer = False 70 | if self.use_tanh and is_last_layer: 71 | activation = nn.Tanh() 72 | else: 73 | activation = nn.ReLU(inplace=True) 74 | 75 | layers += [nn.Conv2d(in_channels, x, kernel_size=3, padding=1), 76 | normalization(self.normalization_type, x), 77 | activation] 78 | in_channels = x 79 | layers += [nn.AvgPool2d(kernel_size=1, stride=1)] 80 | return nn.Sequential(*layers) 81 | 82 | def get_logit(self, x): 83 | # whiten input 84 | x = self.whiten_func(x) 85 | 86 | out = self.features(x) 87 | out = out.view(out.size(0), -1) 88 | out = self.classifier(out) 89 | return out 90 | 91 | def forward(self, adv_image, image, label, target, output_fields): 92 | output = inv_forward( 93 | adv_image=adv_image, image=image, label=label, target=target, get_logit=self.get_logit, 94 | normal_mean=self.normal_mean, empty_coeff=self.empty_coeff, empty_normal_mean=self.empty_normal_mean, 95 | training=self.training, calibrate=self.calibrate, output_fields=output_fields) 96 | if 'std' in output_fields: 97 | output['std'] = self.normal_logstd.exp() 98 | return output 99 | 100 | def rescale(self, scale): 101 | raise NotImplementedError 102 | 103 | 104 | def vgg11_inv(**kwargs): 105 | return VGGInv('vgg11', **kwargs) 106 | 107 | 108 | def vgg13_inv(**kwargs): 109 | return VGGInv('vgg13', **kwargs) 110 | 111 | 112 | def vgg16_inv(**kwargs): 113 | return VGGInv('vgg16', **kwargs) 114 | 115 | 116 | def vgg19_inv(**kwargs): 117 | return VGGInv('vgg19', **kwargs) 118 | -------------------------------------------------------------------------------- /models/standard_model.py: -------------------------------------------------------------------------------- 1 | import torch 2 | import torch.nn as nn 3 | import copy 4 | 5 | 6 | class StandardModel(nn.Module): 7 | """ 8 | This model always accept standard image: in [0, 1] range, RGB order, un-normalized, NCHW format 9 | """ 10 | def __init__(self, net): 11 | super(StandardModel, self).__init__() 12 | # init victim model 13 | self.net = net 14 | 15 | # init victim model meta-information 16 | if len(self.net.input_size) == 3: 17 | self.mean = torch.FloatTensor(self.net.mean).view(1, -1, 1, 1) 18 | self.std = torch.FloatTensor(self.net.std).view(1, -1, 1, 1) 19 | else: 20 | # must be debug dataset 21 | assert len(self.net.input_size) == 1 22 | self.mean = torch.FloatTensor(self.net.mean).view(1, -1) 23 | self.std = torch.FloatTensor(self.net.std).view(1, -1) 24 | self.input_space = self.net.input_space # 'RGB' or 'GBR' or 'GRAY' 25 | self.input_range = self.net.input_range # [0, 1] or [0, 255] 26 | self.input_size = self.net.input_size 27 | 28 | def whiten(self, x): 29 | # channel order 30 | if self.input_space == 'BGR': 31 | x = x[:, [2, 1, 0], :, :] # pytorch does not support negative stride index (::-1) yet 32 | 33 | # input range 34 | x = torch.clamp(x, 0, 1) 35 | if max(self.input_range) == 255: 36 | x = x * 255 37 | 38 | # normalization 39 | if self.mean.device != x.device: 40 | self.mean = self.mean.to(x.device) 41 | if self.std.device != x.device: 42 | self.std = self.std.to(x.device) 43 | x = (x - self.mean) / self.std 44 | 45 | return x 46 | 47 | def forward(self, x): 48 | raise NotImplementedError 49 | 50 | 51 | class StandardVictimModel(StandardModel): 52 | """ 53 | This model inherits StandardModel class, and maintain a record for query counts and best adversarial examples 54 | """ 55 | 56 | def __init__(self, net): 57 | super(StandardVictimModel, self).__init__(net=net) 58 | 59 | # init attack states 60 | self.image = None 61 | self.attack_type = None 62 | self.norm_type = None 63 | self.label = None 64 | self.target_label = None 65 | self.query_count = 0 66 | self.last_adv_image = None 67 | self.last_adv_label = None 68 | self.last_success = None 69 | self.last_distance = None 70 | self.best_adv_image = None 71 | self.best_adv_label = None 72 | self.best_distance = None 73 | # self.best_success = None # best adv image is always and success attack thus could be omitted 74 | 75 | def forward(self, x, no_count=False): 76 | if not no_count: 77 | # increase query counter 78 | self.query_count += x.shape[0] 79 | 80 | # whiten input 81 | x = self.whiten(x) 82 | 83 | # forward 84 | x = self.net(x) 85 | return x 86 | 87 | def reset(self, image, label, target_label, attack_type, norm_type): 88 | self.image = image.clone() 89 | self.attack_type = attack_type 90 | self.norm_type = norm_type 91 | if self.attack_type == 'untargeted': 92 | assert label is not None 93 | self.label = label.clone().view([]) 94 | elif self.attack_type == 'targeted': 95 | assert target_label is not None 96 | self.target_label = target_label.clone().view([]) 97 | else: 98 | raise NotImplementedError('Unknown attack type: {}'.format(self.attack_type)) 99 | 100 | self.query_count = 0 101 | self.last_adv_image = None 102 | self.last_adv_label = None 103 | self.last_distance = None 104 | self.last_success = None 105 | self.best_adv_image = None 106 | self.best_adv_label = None 107 | self.best_distance = None 108 | 109 | def calc_mse(self, adv_image): 110 | assert self.image is not None 111 | diff = adv_image - self.image 112 | diff = diff.view(diff.shape[0], -1) 113 | return (diff ** 2).sum(dim=1) / self.image.numel() 114 | 115 | def calc_distance(self, adv_image): 116 | assert self.image is not None 117 | diff = adv_image - self.image 118 | diff = diff.view(diff.shape[0], -1) 119 | if self.norm_type == 'l2': 120 | return torch.sqrt((diff ** 2).sum(dim=1)) 121 | elif self.norm_type == 'linf': 122 | return diff.abs().max(dim=1)[0] 123 | else: 124 | raise NotImplementedError('Unknown norm: {}'.format(self.norm_type)) 125 | 126 | def _is_valid_adv_pred(self, pred): 127 | if self.attack_type == 'untargeted': 128 | return ~(pred.eq(self.label)) 129 | elif self.attack_type == 'targeted': 130 | return pred.eq(self.target_label) 131 | else: 132 | raise NotImplementedError('Unknown attack type: {}'.format(self.attack_type)) 133 | 134 | def query(self, adv_image, sync_best=True, no_count=False): 135 | adv_image = adv_image.detach() 136 | assert self.attack_type is not None 137 | pred = self.forward(adv_image, no_count=no_count).argmax(dim=1) 138 | distance = self.calc_distance(adv_image) 139 | success = self._is_valid_adv_pred(pred) 140 | 141 | # check if better adversarial examples are found 142 | if sync_best: 143 | if success.any().item(): 144 | if self.best_distance is None or self.best_distance.item() > distance[success].min().item(): 145 | # if better adversarial examples are found, record it 146 | adv_index = distance[success].argmin() 147 | best_adv_image = adv_image[success][adv_index].view(self.image.shape) 148 | best_adv_label = pred[success][adv_index].view([]) 149 | best_distance = distance[success][adv_index].view([]) 150 | failed = False 151 | 152 | # Since cuda/cudnn is extensively optimized for batch-ed inputs, we might get slightly different 153 | # results for the following two scenarios: 154 | # 1. wrap example X and some other examples into a batch, forward and see logit for X 155 | # 2. forward example X only (i.e., batch size = 1), and see logit for X 156 | # As a result, if logit(label) is too close to logit(target), there might be some numerical problems 157 | # Since our program might think the predicted class as the label class sometimes, and think it as 158 | # the target class for other times, which will definitely destroy the assumption for binary search 159 | # So, here we try to fix this by adding a small vector to adv_image if this happens, and we 160 | # explicitly exclude these queries from total counts since this phenomenon is mainly caused by 161 | # unsatisfied computing infrastructure instead of intrinsic requirement of the attacking algorithm 162 | # And this problem could possibly been solved by future updates of gpus or cuda/cudnn 163 | if not self._is_valid_adv_pred(self.forward(best_adv_image, no_count=True).argmax()).item(): 164 | best_adv_image = self.image + (1 + 1e-6) * (best_adv_image - self.image) 165 | best_adv_label = self.forward(best_adv_image, no_count=True).argmax().view([]) 166 | best_distance = self.calc_distance(best_adv_image).view([]) 167 | if not self._is_valid_adv_pred(best_adv_label).item(): 168 | # cannot fix numerical problem after adding a small factor of (adv_image - image) 169 | failed = True 170 | 171 | if (not failed) and \ 172 | (self.best_distance is None or self.best_distance.item() > best_distance.item()): 173 | # if new adv image is still better than previous after fixing, we should record it 174 | self.best_adv_image = best_adv_image 175 | self.best_adv_label = best_adv_label 176 | self.best_distance = best_distance 177 | else: 178 | # or else we discard it 179 | pass 180 | 181 | self.last_adv_image = adv_image.clone() 182 | self.last_adv_label = pred 183 | self.last_distance = distance 184 | self.last_success = success 185 | return success 186 | 187 | 188 | class StandardPolicyModel(StandardModel): 189 | """ 190 | This model inherits StandardModel class 191 | """ 192 | 193 | def __init__(self, net): 194 | super(StandardPolicyModel, self).__init__(net=net) 195 | self.init_state_dict = copy.deepcopy(self.state_dict()) 196 | self.factor = 1.0 197 | 198 | # for policy models, we do whiten in policy.net.forward() instead of policy.forward() 199 | # since _inv models requires grad w.r.t. input in range [0, 1] 200 | self.net.whiten_func = self.whiten 201 | 202 | def forward(self, adv_image, image=None, label=None, target=None, 203 | output_fields=('grad', 'std', 'adv_logit', 'logit')): 204 | # get distribution mean, (other fields such as adv_logit and logit will also be in output) 205 | output = self.net(adv_image, image, label, target, output_fields) 206 | 207 | # we have two solutions for scaling: 208 | # 1. multiply scale factor into mean and keep std unchanged 209 | # 2. keep mean unchanged and make std divided by scale factor 210 | 211 | # since we only optimize mean (if args.exclude_std is True) and we often use some form of momentum (SGDM/Adam), 212 | # changing the scale of mean will change the scale of gradient and previous momentum may no longer be suitable 213 | # so we choose solution 2 for std here: std <-- std / self.factor 214 | if 'std' in output: 215 | output['std'] = output['std'] / self.factor 216 | 217 | # only return fields requested, since DistributedDataParallel throw error if unnecessary fields are returned 218 | return {field_key: output[field_key] for field_key in output_fields if field_key in output} 219 | 220 | def reinit(self): 221 | self.load_state_dict(self.init_state_dict) 222 | self.factor = 1.0 223 | 224 | def rescale(self, scale): 225 | self.factor *= scale 226 | -------------------------------------------------------------------------------- /models/victim/__init__.py: -------------------------------------------------------------------------------- 1 | import models.victim.debug 2 | import models.victim.mnist 3 | import models.victim.cifar 4 | import models.victim.imagenet 5 | -------------------------------------------------------------------------------- /models/victim/cifar/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Wei Yang 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 | -------------------------------------------------------------------------------- /models/victim/cifar/README.md: -------------------------------------------------------------------------------- 1 | # CIFAR-10 CNN models 2 | This folder contains a slightly modified version of the [pytorch-classification](https://github.com/bearpaw/pytorch-classification) project code (Copyright to [Wei Yang](https://github.com/bearpaw)). 3 | -------------------------------------------------------------------------------- /models/victim/cifar/__init__.py: -------------------------------------------------------------------------------- 1 | """The models subpackage contains definitions for the following model for CIFAR10/CIFAR100 2 | architectures: 3 | 4 | - `AlexNet`_ 5 | - `VGG`_ 6 | - `ResNet`_ 7 | - `SqueezeNet`_ 8 | - `DenseNet`_ 9 | 10 | You can construct a model with random weights by calling its constructor: 11 | 12 | .. code:: python 13 | 14 | import torchvision.models as models 15 | resnet18 = models.resnet18() 16 | alexnet = models.alexnet() 17 | squeezenet = models.squeezenet1_0() 18 | densenet = models.densenet_161() 19 | 20 | We provide pre-trained models for the ResNet variants and AlexNet, using the 21 | PyTorch :mod:`torch.utils.model_zoo`. These can constructed by passing 22 | ``pretrained=True``: 23 | 24 | .. code:: python 25 | 26 | import torchvision.models as models 27 | resnet18 = models.resnet18(pretrained=True) 28 | alexnet = models.alexnet(pretrained=True) 29 | 30 | ImageNet 1-crop error rates (224x224) 31 | 32 | ======================== ============= ============= 33 | Network Top-1 error Top-5 error 34 | ======================== ============= ============= 35 | ResNet-18 30.24 10.92 36 | ResNet-34 26.70 8.58 37 | ResNet-50 23.85 7.13 38 | ResNet-101 22.63 6.44 39 | ResNet-152 21.69 5.94 40 | Inception v3 22.55 6.44 41 | AlexNet 43.45 20.91 42 | VGG-11 30.98 11.37 43 | VGG-13 30.07 10.75 44 | VGG-16 28.41 9.62 45 | VGG-19 27.62 9.12 46 | SqueezeNet 1.0 41.90 19.58 47 | SqueezeNet 1.1 41.81 19.38 48 | Densenet-121 25.35 7.83 49 | Densenet-169 24.00 7.00 50 | Densenet-201 22.80 6.43 51 | Densenet-161 22.35 6.20 52 | ======================== ============= ============= 53 | 54 | 55 | .. _AlexNet: https://arxiv.org/abs/1404.5997 56 | .. _VGG: https://arxiv.org/abs/1409.1556 57 | .. _ResNet: https://arxiv.org/abs/1512.03385 58 | .. _SqueezeNet: https://arxiv.org/abs/1602.07360 59 | .. _DenseNet: https://arxiv.org/abs/1608.06993 60 | """ 61 | 62 | from models.victim.cifar.lenet import * 63 | from models.victim.cifar.alexnet import * 64 | from models.victim.cifar.carlinet import * 65 | from models.victim.cifar.vgg import * 66 | from models.victim.cifar.resnet import * 67 | from models.victim.cifar.preresnet import * 68 | from models.victim.cifar.densenet import * 69 | from models.victim.cifar.resnext import * 70 | from models.victim.cifar.wrn import * 71 | from models.victim.cifar.madry_resnet import * 72 | -------------------------------------------------------------------------------- /models/victim/cifar/alexnet.py: -------------------------------------------------------------------------------- 1 | '''AlexNet for CIFAR10. FC layers are removed. Paddings are adjusted. 2 | Without BN, the start learning rate should be 0.01 3 | (c) YANG, Wei 4 | ''' 5 | import torch.nn as nn 6 | import torch.nn.functional as F 7 | from .utils import DropoutConv2d 8 | 9 | __all__ = ['alexnet', 'alexnet_bn'] 10 | 11 | 12 | class AlexNet(nn.Module): 13 | 14 | def __init__(self, batch_norm=False, num_classes=10): 15 | super(AlexNet, self).__init__() 16 | layers = [ 17 | DropoutConv2d(3, 64, kernel_size=11, stride=4, padding=5) 18 | ] 19 | if batch_norm: 20 | layers += [nn.BatchNorm2d(64)] 21 | layers += [ 22 | nn.ReLU(inplace=True), 23 | nn.MaxPool2d(kernel_size=2, stride=2), 24 | DropoutConv2d(64, 192, kernel_size=5, padding=2), 25 | ] 26 | if batch_norm: 27 | layers += [nn.BatchNorm2d(192)] 28 | layers += [ 29 | nn.ReLU(inplace=True), 30 | nn.MaxPool2d(kernel_size=2, stride=2), 31 | DropoutConv2d(192, 384, kernel_size=3, padding=1), 32 | ] 33 | if batch_norm: 34 | layers += [nn.BatchNorm2d(384)] 35 | layers += [ 36 | nn.ReLU(inplace=True), 37 | DropoutConv2d(384, 256, kernel_size=3, padding=1), 38 | ] 39 | if batch_norm: 40 | layers += [nn.BatchNorm2d(256)] 41 | layers += [ 42 | nn.ReLU(inplace=True), 43 | DropoutConv2d(256, 256, kernel_size=3, padding=1), 44 | ] 45 | if batch_norm: 46 | layers += [nn.BatchNorm2d(256)] 47 | layers += [ 48 | nn.ReLU(inplace=True), 49 | nn.MaxPool2d(kernel_size=2, stride=2), 50 | ] 51 | self.features = nn.Sequential(*layers) 52 | self.classifier = nn.Linear(256, num_classes) 53 | 54 | # no dropout 55 | self.drop = 0 56 | 57 | def forward(self, x): 58 | for m in self.modules(): 59 | if isinstance(m, DropoutConv2d): 60 | m.drop = self.drop 61 | 62 | x = self.features(x) 63 | x = x.view(x.size(0), -1) 64 | x = F.dropout(x, p=self.drop, training=True) # force dropout 65 | x = self.classifier(x) 66 | return x 67 | 68 | 69 | def alexnet(**kwargs): 70 | r"""AlexNet model architecture from the 71 | `"One weird trick..." `_ paper. 72 | """ 73 | model = AlexNet(batch_norm=False, **kwargs) 74 | return model 75 | 76 | 77 | def alexnet_bn(**kwargs): 78 | r"""AlexNet model architecture from the 79 | `"One weird trick..." `_ paper. 80 | """ 81 | model = AlexNet(batch_norm=True, **kwargs) 82 | return model 83 | -------------------------------------------------------------------------------- /models/victim/cifar/carlinet.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Carlini's net for CIFAR-10 (https://arxiv.org/pdf/1608.04644.pdf) 3 | ''' 4 | 5 | import torch.nn as nn 6 | import torch.nn.functional as F 7 | 8 | __all__ = ['carlinet'] 9 | 10 | 11 | class CarliNet(nn.Module): 12 | def __init__(self, num_classes=10): 13 | super(CarliNet, self).__init__() 14 | 15 | self.conv2d_1 = nn.Conv2d(3, 64, 3) 16 | self.conv2d_2 = nn.Conv2d(64, 64, 3) 17 | self.conv2d_3 = nn.Conv2d(64, 128, 3) 18 | self.conv2d_4 = nn.Conv2d(128, 128, 3) 19 | 20 | self.dense_1 = nn.Linear(3200, 256) 21 | self.dense_2 = nn.Linear(256, 256) 22 | self.dense_3 = nn.Linear(256, num_classes) 23 | 24 | def forward(self, x): 25 | x = self.conv2d_1(x) 26 | x = F.relu(x) 27 | x = self.conv2d_2(x) 28 | x = F.relu(x) 29 | x = F.max_pool2d(x, (2, 2)) 30 | 31 | x = self.conv2d_3(x) 32 | x = F.relu(x) 33 | x = self.conv2d_4(x) 34 | x = F.relu(x) 35 | x = F.max_pool2d(x, (2, 2)) 36 | 37 | # carlini's keras model data format: (N, H, W, C) 38 | # pytorch data format: (N, C, H, W) 39 | # we need to transpose pytorch data format into keras data format, to make sure the flatten operator 40 | # has the same effect. 41 | x = x.transpose(1, 2).transpose(2, 3).contiguous().view(x.shape[0], -1) 42 | x = self.dense_1(x) 43 | x = F.relu(x) 44 | x = self.dense_2(x) 45 | x = F.relu(x) 46 | x = self.dense_3(x) 47 | return x 48 | 49 | 50 | def carlinet(**kwargs): 51 | return CarliNet(**kwargs) 52 | -------------------------------------------------------------------------------- /models/victim/cifar/densenet.py: -------------------------------------------------------------------------------- 1 | import torch 2 | import torch.nn as nn 3 | import torch.nn.functional as F 4 | import math 5 | 6 | 7 | __all__ = ['densenet'] 8 | 9 | 10 | from torch.autograd import Variable 11 | 12 | class Bottleneck(nn.Module): 13 | def __init__(self, inplanes, expansion=4, growthRate=12, dropRate=0): 14 | super(Bottleneck, self).__init__() 15 | planes = expansion * growthRate 16 | self.bn1 = nn.BatchNorm2d(inplanes) 17 | self.conv1 = nn.Conv2d(inplanes, planes, kernel_size=1, bias=False) 18 | self.bn2 = nn.BatchNorm2d(planes) 19 | self.conv2 = nn.Conv2d(planes, growthRate, kernel_size=3, 20 | padding=1, bias=False) 21 | self.relu = nn.ReLU(inplace=True) 22 | self.dropRate = dropRate 23 | 24 | def forward(self, x): 25 | out = self.bn1(x) 26 | out = self.relu(out) 27 | out = self.conv1(out) 28 | out = self.bn2(out) 29 | out = self.relu(out) 30 | out = self.conv2(out) 31 | if self.dropRate > 0: 32 | out = F.dropout(out, p=self.dropRate, training=self.training) 33 | 34 | out = torch.cat((x, out), 1) 35 | 36 | return out 37 | 38 | 39 | class BasicBlock(nn.Module): 40 | def __init__(self, inplanes, expansion=1, growthRate=12, dropRate=0): 41 | super(BasicBlock, self).__init__() 42 | planes = expansion * growthRate 43 | self.bn1 = nn.BatchNorm2d(inplanes) 44 | self.conv1 = nn.Conv2d(inplanes, growthRate, kernel_size=3, 45 | padding=1, bias=False) 46 | self.relu = nn.ReLU(inplace=True) 47 | self.dropRate = dropRate 48 | 49 | def forward(self, x): 50 | out = self.bn1(x) 51 | out = self.relu(out) 52 | out = self.conv1(out) 53 | if self.dropRate > 0: 54 | out = F.dropout(out, p=self.dropRate, training=self.training) 55 | 56 | out = torch.cat((x, out), 1) 57 | 58 | return out 59 | 60 | 61 | class Transition(nn.Module): 62 | def __init__(self, inplanes, outplanes): 63 | super(Transition, self).__init__() 64 | self.bn1 = nn.BatchNorm2d(inplanes) 65 | self.conv1 = nn.Conv2d(inplanes, outplanes, kernel_size=1, 66 | bias=False) 67 | self.relu = nn.ReLU(inplace=True) 68 | 69 | def forward(self, x): 70 | out = self.bn1(x) 71 | out = self.relu(out) 72 | out = self.conv1(out) 73 | out = F.avg_pool2d(out, 2) 74 | return out 75 | 76 | 77 | class DenseNet(nn.Module): 78 | 79 | def __init__(self, depth=22, block=Bottleneck, 80 | dropRate=0, num_classes=10, growthRate=12, compressionRate=2): 81 | super(DenseNet, self).__init__() 82 | 83 | assert (depth - 4) % 3 == 0, 'depth should be 3n+4' 84 | block = Bottleneck if depth > 50 else BasicBlock 85 | n = (depth - 4) // 3 if block == BasicBlock else (depth - 4) // 6 86 | 87 | self.growthRate = growthRate 88 | self.dropRate = dropRate 89 | 90 | # self.inplanes is a global variable used across multiple 91 | # helper functions 92 | self.inplanes = growthRate * 2 93 | self.conv1 = nn.Conv2d(3, self.inplanes, kernel_size=3, padding=1, 94 | bias=False) 95 | self.dense1 = self._make_denseblock(block, n) 96 | self.trans1 = self._make_transition(compressionRate) 97 | self.dense2 = self._make_denseblock(block, n) 98 | self.trans2 = self._make_transition(compressionRate) 99 | self.dense3 = self._make_denseblock(block, n) 100 | self.bn = nn.BatchNorm2d(self.inplanes) 101 | self.relu = nn.ReLU(inplace=True) 102 | self.avgpool = nn.AvgPool2d(8) 103 | self.fc = nn.Linear(self.inplanes, num_classes) 104 | 105 | # Weight initialization 106 | for m in self.modules(): 107 | if isinstance(m, nn.Conv2d): 108 | n = m.kernel_size[0] * m.kernel_size[1] * m.out_channels 109 | m.weight.data.normal_(0, math.sqrt(2. / n)) 110 | elif isinstance(m, nn.BatchNorm2d): 111 | m.weight.data.fill_(1) 112 | m.bias.data.zero_() 113 | 114 | def _make_denseblock(self, block, blocks): 115 | layers = [] 116 | for i in range(blocks): 117 | # Currently we fix the expansion ratio as the default value 118 | layers.append(block(self.inplanes, growthRate=self.growthRate, dropRate=self.dropRate)) 119 | self.inplanes += self.growthRate 120 | 121 | return nn.Sequential(*layers) 122 | 123 | def _make_transition(self, compressionRate): 124 | inplanes = self.inplanes 125 | outplanes = int(math.floor(self.inplanes // compressionRate)) 126 | self.inplanes = outplanes 127 | return Transition(inplanes, outplanes) 128 | 129 | 130 | def forward(self, x): 131 | x = self.conv1(x) 132 | 133 | x = self.trans1(self.dense1(x)) 134 | x = self.trans2(self.dense2(x)) 135 | x = self.dense3(x) 136 | x = self.bn(x) 137 | x = self.relu(x) 138 | 139 | x = self.avgpool(x) 140 | x = x.view(x.size(0), -1) 141 | x = self.fc(x) 142 | 143 | return x 144 | 145 | 146 | def densenet(**kwargs): 147 | """ 148 | Constructs a ResNet model. 149 | """ 150 | return DenseNet(**kwargs) -------------------------------------------------------------------------------- /models/victim/cifar/lenet.py: -------------------------------------------------------------------------------- 1 | import torch 2 | import torch.nn as nn 3 | import torch.nn.functional as F 4 | 5 | __all__ = ['lenet'] 6 | 7 | 8 | class LeNet(nn.Module): 9 | def __init__(self, num_classes=10): 10 | super(LeNet, self).__init__() 11 | self.conv1 = nn.Conv2d(3, 32, 5, padding=2) 12 | self.conv2 = nn.Conv2d(32, 32, 5, padding=2) 13 | self.conv3 = nn.Conv2d(32, 64, 5, padding=2) 14 | self.fc1 = nn.Linear(1024, 64) 15 | # self.drop1 = nn.Dropout(0.5) 16 | self.fc2 = nn.Linear(64, num_classes) 17 | 18 | for k in ['conv1', 'conv2', 'conv3', 'fc1', 'fc2']: 19 | w = self.__getattr__(k) 20 | torch.nn.init.kaiming_normal_(w.weight.data) 21 | w.bias.data.fill_(0) 22 | 23 | self.out = dict() 24 | 25 | def forward(self, x): 26 | x = self.conv1(x) 27 | x = F.max_pool2d(x, kernel_size=2, stride=2) 28 | x = F.relu(x) 29 | 30 | x = self.conv2(x) 31 | x = F.max_pool2d(x, kernel_size=2, stride=2) 32 | x = F.relu(x) 33 | 34 | x = self.conv3(x) 35 | x = F.max_pool2d(x, kernel_size=2, stride=2) 36 | x = F.relu(x) 37 | 38 | x = x.view(x.shape[0], -1) 39 | x = self.fc1(x) 40 | x = F.relu(x) 41 | # x = self.drop1(x) 42 | 43 | x = self.fc2(x) 44 | 45 | return x 46 | 47 | 48 | def lenet(**kwargs): 49 | return lenet(**kwargs) 50 | -------------------------------------------------------------------------------- /models/victim/cifar/madry_resnet.py: -------------------------------------------------------------------------------- 1 | """ 2 | This script is ported from https://github.com/MadryLab/robustness 3 | branch: master 4 | commit: 54f3375e428ad9a9ba4501dbbb3030f141e2ff78 5 | """ 6 | import torch 7 | import torch.nn as nn 8 | import torch.nn.functional as F 9 | 10 | 11 | __all__ = ['resnet50'] # https://github.com/MadryLab/robustness only provide pre-trained models for resnet50 12 | 13 | 14 | class BasicBlock(nn.Module): 15 | expansion = 1 16 | 17 | def __init__(self, in_planes, planes, stride=1): 18 | super(BasicBlock, self).__init__() 19 | self.conv1 = nn.Conv2d(in_planes, planes, kernel_size=3, stride=stride, 20 | padding=1, bias=False) 21 | self.bn1 = nn.BatchNorm2d(planes) 22 | self.conv2 = nn.Conv2d(planes, planes, kernel_size=3, stride=1, 23 | 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, 30 | stride=stride, bias=False), 31 | nn.BatchNorm2d(self.expansion * planes)) 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 | return F.relu(out) 38 | 39 | 40 | class Bottleneck(nn.Module): 41 | expansion = 4 42 | 43 | def __init__(self, in_planes, planes, stride=1): 44 | super(Bottleneck, self).__init__() 45 | self.conv1 = nn.Conv2d(in_planes, planes, kernel_size=1, bias=False) 46 | self.bn1 = nn.BatchNorm2d(planes) 47 | self.conv2 = nn.Conv2d(planes, planes, kernel_size=3, stride=stride, 48 | 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 | return F.relu(out) 66 | 67 | 68 | class ResNet(nn.Module): 69 | # feat_scale lets us deal with CelebA, other non-32x32 datasets 70 | def __init__(self, block, num_blocks, num_classes=10, feat_scale=1, wm=1): 71 | super(ResNet, self).__init__() 72 | 73 | widths = [64, 128, 256, 512] 74 | widths = [int(w * wm) for w in widths] 75 | 76 | self.in_planes = widths[0] 77 | self.conv1 = nn.Conv2d(3, self.in_planes, kernel_size=3, stride=1, 78 | padding=1, bias=False) 79 | self.bn1 = nn.BatchNorm2d(self.in_planes) 80 | self.layer1 = self._make_layer(block, widths[0], num_blocks[0], stride=1) 81 | self.layer2 = self._make_layer(block, widths[1], num_blocks[1], stride=2) 82 | self.layer3 = self._make_layer(block, widths[2], num_blocks[2], stride=2) 83 | self.layer4 = self._make_layer(block, widths[3], num_blocks[3], stride=2) 84 | self.linear = nn.Linear(feat_scale * widths[3] * block.expansion, num_classes) 85 | 86 | def _make_layer(self, block, planes, num_blocks, stride): 87 | strides = [stride] + [1] * (num_blocks - 1) 88 | layers = [] 89 | for stride in strides: 90 | layers.append(block(self.in_planes, planes, stride)) 91 | self.in_planes = planes * block.expansion 92 | return nn.Sequential(*layers) 93 | 94 | def forward(self, x, no_relu=False): 95 | out = F.relu(self.bn1(self.conv1(x))) 96 | out = self.layer1(out) 97 | out = self.layer2(out) 98 | out = self.layer3(out) 99 | out = self.layer4(out) 100 | out = F.avg_pool2d(out, 4) 101 | pre_out = out.view(out.size(0), -1) 102 | final = self.linear(pre_out) 103 | return final 104 | 105 | 106 | def ResNet18(**kwargs): 107 | return ResNet(BasicBlock, [2, 2, 2, 2], **kwargs) 108 | 109 | 110 | def ResNet18Wide(**kwargs): 111 | return ResNet(BasicBlock, [2, 2, 2, 2], wm=5, **kwargs) 112 | 113 | 114 | def ResNet18Thin(**kwargs): 115 | return ResNet(BasicBlock, [2, 2, 2, 2], wd=.75, **kwargs) 116 | 117 | 118 | def ResNet34(**kwargs): 119 | return ResNet(BasicBlock, [3, 4, 6, 3], **kwargs) 120 | 121 | 122 | def ResNet50(**kwargs): 123 | return ResNet(Bottleneck, [3, 4, 6, 3], **kwargs) 124 | 125 | 126 | def ResNet101(**kwargs): 127 | return ResNet(Bottleneck, [3, 4, 23, 3], **kwargs) 128 | 129 | 130 | def ResNet152(**kwargs): 131 | return ResNet(Bottleneck, [3, 8, 36, 3], **kwargs) 132 | 133 | 134 | resnet50 = ResNet50 135 | resnet18 = ResNet18 136 | resnet101 = ResNet101 137 | resnet152 = ResNet152 138 | resnet18wide = ResNet18Wide -------------------------------------------------------------------------------- /models/victim/cifar/preresnet.py: -------------------------------------------------------------------------------- 1 | 2 | from __future__ import absolute_import 3 | 4 | '''Resnet for cifar dataset. 5 | Ported form 6 | https://github.com/facebook/fb.resnet.torch 7 | and 8 | https://github.com/pytorch/vision/blob/master/torchvision/models/resnet.py 9 | (c) YANG, Wei 10 | ''' 11 | import torch.nn as nn 12 | import math 13 | 14 | 15 | __all__ = ['preresnet'] 16 | 17 | def conv3x3(in_planes, out_planes, stride=1): 18 | "3x3 convolution with padding" 19 | return nn.Conv2d(in_planes, out_planes, kernel_size=3, stride=stride, 20 | padding=1, bias=False) 21 | 22 | 23 | class BasicBlock(nn.Module): 24 | expansion = 1 25 | 26 | def __init__(self, inplanes, planes, stride=1, downsample=None): 27 | super(BasicBlock, self).__init__() 28 | self.bn1 = nn.BatchNorm2d(inplanes) 29 | self.relu = nn.ReLU(inplace=True) 30 | self.conv1 = conv3x3(inplanes, planes, stride) 31 | self.bn2 = nn.BatchNorm2d(planes) 32 | self.conv2 = conv3x3(planes, planes) 33 | self.downsample = downsample 34 | self.stride = stride 35 | 36 | def forward(self, x): 37 | residual = x 38 | 39 | out = self.bn1(x) 40 | out = self.relu(out) 41 | out = self.conv1(out) 42 | 43 | out = self.bn2(out) 44 | out = self.relu(out) 45 | out = self.conv2(out) 46 | 47 | if self.downsample is not None: 48 | residual = self.downsample(x) 49 | 50 | out += residual 51 | 52 | return out 53 | 54 | 55 | class Bottleneck(nn.Module): 56 | expansion = 4 57 | 58 | def __init__(self, inplanes, planes, stride=1, downsample=None): 59 | super(Bottleneck, self).__init__() 60 | self.bn1 = nn.BatchNorm2d(inplanes) 61 | self.conv1 = nn.Conv2d(inplanes, planes, kernel_size=1, bias=False) 62 | self.bn2 = nn.BatchNorm2d(planes) 63 | self.conv2 = nn.Conv2d(planes, planes, kernel_size=3, stride=stride, 64 | padding=1, bias=False) 65 | self.bn3 = nn.BatchNorm2d(planes) 66 | self.conv3 = nn.Conv2d(planes, planes * 4, kernel_size=1, bias=False) 67 | self.relu = nn.ReLU(inplace=True) 68 | self.downsample = downsample 69 | self.stride = stride 70 | 71 | def forward(self, x): 72 | residual = x 73 | 74 | out = self.bn1(x) 75 | out = self.relu(out) 76 | out = self.conv1(out) 77 | 78 | out = self.bn2(out) 79 | out = self.relu(out) 80 | out = self.conv2(out) 81 | 82 | out = self.bn3(out) 83 | out = self.relu(out) 84 | out = self.conv3(out) 85 | 86 | if self.downsample is not None: 87 | residual = self.downsample(x) 88 | 89 | out += residual 90 | 91 | return out 92 | 93 | 94 | class PreResNet(nn.Module): 95 | 96 | def __init__(self, depth, num_classes=1000): 97 | super(PreResNet, self).__init__() 98 | # Model type specifies number of layers for CIFAR-10 model 99 | assert (depth - 2) % 6 == 0, 'depth should be 6n+2' 100 | n = (depth - 2) // 6 101 | 102 | block = Bottleneck if depth >=44 else BasicBlock 103 | 104 | self.inplanes = 16 105 | self.conv1 = nn.Conv2d(3, 16, kernel_size=3, padding=1, 106 | bias=False) 107 | self.layer1 = self._make_layer(block, 16, n) 108 | self.layer2 = self._make_layer(block, 32, n, stride=2) 109 | self.layer3 = self._make_layer(block, 64, n, stride=2) 110 | self.bn = nn.BatchNorm2d(64 * block.expansion) 111 | self.relu = nn.ReLU(inplace=True) 112 | self.avgpool = nn.AvgPool2d(8) 113 | self.fc = nn.Linear(64 * block.expansion, num_classes) 114 | 115 | for m in self.modules(): 116 | if isinstance(m, nn.Conv2d): 117 | n = m.kernel_size[0] * m.kernel_size[1] * m.out_channels 118 | m.weight.data.normal_(0, math.sqrt(2. / n)) 119 | elif isinstance(m, nn.BatchNorm2d): 120 | m.weight.data.fill_(1) 121 | m.bias.data.zero_() 122 | 123 | def _make_layer(self, block, planes, blocks, stride=1): 124 | downsample = None 125 | if stride != 1 or self.inplanes != planes * block.expansion: 126 | downsample = nn.Sequential( 127 | nn.Conv2d(self.inplanes, planes * block.expansion, 128 | kernel_size=1, stride=stride, bias=False), 129 | ) 130 | 131 | layers = [] 132 | layers.append(block(self.inplanes, planes, stride, downsample)) 133 | self.inplanes = planes * block.expansion 134 | for i in range(1, blocks): 135 | layers.append(block(self.inplanes, planes)) 136 | 137 | return nn.Sequential(*layers) 138 | 139 | def forward(self, x): 140 | x = self.conv1(x) 141 | 142 | x = self.layer1(x) # 32x32 143 | x = self.layer2(x) # 16x16 144 | x = self.layer3(x) # 8x8 145 | x = self.bn(x) 146 | x = self.relu(x) 147 | 148 | x = self.avgpool(x) 149 | x = x.view(x.size(0), -1) 150 | x = self.fc(x) 151 | 152 | return x 153 | 154 | 155 | def preresnet(**kwargs): 156 | """ 157 | Constructs a ResNet model. 158 | """ 159 | return PreResNet(**kwargs) -------------------------------------------------------------------------------- /models/victim/cifar/resnet.py: -------------------------------------------------------------------------------- 1 | from __future__ import absolute_import 2 | 3 | '''Resnet for cifar dataset. 4 | Ported form 5 | https://github.com/facebook/fb.resnet.torch 6 | and 7 | https://github.com/pytorch/vision/blob/master/torchvision/models/resnet.py 8 | (c) YANG, Wei 9 | ''' 10 | import torch.nn as nn 11 | import math 12 | 13 | 14 | __all__ = ['resnet'] 15 | 16 | def conv3x3(in_planes, out_planes, stride=1): 17 | "3x3 convolution with padding" 18 | return nn.Conv2d(in_planes, out_planes, kernel_size=3, stride=stride, 19 | padding=1, bias=False) 20 | 21 | 22 | class BasicBlock(nn.Module): 23 | expansion = 1 24 | 25 | def __init__(self, inplanes, planes, stride=1, downsample=None): 26 | super(BasicBlock, self).__init__() 27 | self.conv1 = conv3x3(inplanes, planes, stride) 28 | self.bn1 = nn.BatchNorm2d(planes) 29 | self.relu = nn.ReLU(inplace=True) 30 | self.conv2 = conv3x3(planes, planes) 31 | self.bn2 = nn.BatchNorm2d(planes) 32 | self.downsample = downsample 33 | self.stride = stride 34 | 35 | def forward(self, x): 36 | residual = x 37 | 38 | out = self.conv1(x) 39 | out = self.bn1(out) 40 | out = self.relu(out) 41 | 42 | out = self.conv2(out) 43 | out = self.bn2(out) 44 | 45 | if self.downsample is not None: 46 | residual = self.downsample(x) 47 | 48 | out += residual 49 | out = self.relu(out) 50 | 51 | return out 52 | 53 | 54 | class Bottleneck(nn.Module): 55 | expansion = 4 56 | 57 | def __init__(self, inplanes, planes, stride=1, downsample=None): 58 | super(Bottleneck, self).__init__() 59 | self.conv1 = nn.Conv2d(inplanes, planes, kernel_size=1, bias=False) 60 | self.bn1 = nn.BatchNorm2d(planes) 61 | self.conv2 = nn.Conv2d(planes, planes, kernel_size=3, stride=stride, 62 | padding=1, bias=False) 63 | self.bn2 = nn.BatchNorm2d(planes) 64 | self.conv3 = nn.Conv2d(planes, planes * 4, kernel_size=1, bias=False) 65 | self.bn3 = nn.BatchNorm2d(planes * 4) 66 | self.relu = nn.ReLU(inplace=True) 67 | self.downsample = downsample 68 | self.stride = stride 69 | 70 | def forward(self, x): 71 | residual = x 72 | 73 | out = self.conv1(x) 74 | out = self.bn1(out) 75 | out = self.relu(out) 76 | 77 | out = self.conv2(out) 78 | out = self.bn2(out) 79 | out = self.relu(out) 80 | 81 | out = self.conv3(out) 82 | out = self.bn3(out) 83 | 84 | if self.downsample is not None: 85 | residual = self.downsample(x) 86 | 87 | out += residual 88 | out = self.relu(out) 89 | 90 | return out 91 | 92 | 93 | class ResNet(nn.Module): 94 | 95 | def __init__(self, depth, num_classes=1000, zero_init_residual=True): 96 | super(ResNet, self).__init__() 97 | # Model type specifies number of layers for CIFAR-10 model 98 | assert (depth - 2) % 6 == 0, 'depth should be 6n+2' 99 | n = (depth - 2) // 6 100 | 101 | block = Bottleneck if depth >=44 else BasicBlock 102 | 103 | self.inplanes = 16 104 | self.conv1 = nn.Conv2d(3, 16, kernel_size=3, padding=1, 105 | bias=False) 106 | self.bn1 = nn.BatchNorm2d(16) 107 | self.relu = nn.ReLU(inplace=True) 108 | self.layer1 = self._make_layer(block, 16, n) 109 | self.layer2 = self._make_layer(block, 32, n, stride=2) 110 | self.layer3 = self._make_layer(block, 64, n, stride=2) 111 | self.avgpool = nn.AvgPool2d(8) 112 | self.fc = nn.Linear(64 * block.expansion, num_classes) 113 | 114 | for m in self.modules(): 115 | if isinstance(m, nn.Conv2d): 116 | nn.init.kaiming_normal_(m.weight, mode='fan_out', nonlinearity='relu') 117 | elif isinstance(m, (nn.BatchNorm2d, nn.GroupNorm)): 118 | nn.init.constant_(m.weight, 1) 119 | nn.init.constant_(m.bias, 0) 120 | 121 | # Zero-initialize the last BN in each residual branch, 122 | # so that the residual branch starts with zeros, and each residual block behaves like an identity. 123 | # This improves the model by 0.2~0.3% according to https://arxiv.org/abs/1706.02677 124 | if zero_init_residual: 125 | for m in self.modules(): 126 | if isinstance(m, Bottleneck): 127 | nn.init.constant_(m.bn3.weight, 0) 128 | elif isinstance(m, BasicBlock): 129 | nn.init.constant_(m.bn2.weight, 0) 130 | 131 | def _make_layer(self, block, planes, blocks, stride=1): 132 | downsample = None 133 | if stride != 1 or self.inplanes != planes * block.expansion: 134 | downsample = nn.Sequential( 135 | nn.Conv2d(self.inplanes, planes * block.expansion, 136 | kernel_size=1, stride=stride, bias=False), 137 | nn.BatchNorm2d(planes * block.expansion), 138 | ) 139 | 140 | layers = [] 141 | layers.append(block(self.inplanes, planes, stride, downsample)) 142 | self.inplanes = planes * block.expansion 143 | for i in range(1, blocks): 144 | layers.append(block(self.inplanes, planes)) 145 | 146 | return nn.Sequential(*layers) 147 | 148 | def forward(self, x): 149 | x = self.conv1(x) 150 | x = self.bn1(x) 151 | x = self.relu(x) # 32x32 152 | 153 | x = self.layer1(x) # 32x32 154 | x = self.layer2(x) # 16x16 155 | x = self.layer3(x) # 8x8 156 | 157 | x = self.avgpool(x) 158 | x = x.view(x.size(0), -1) 159 | x = self.fc(x) 160 | 161 | return x 162 | 163 | 164 | def resnet(**kwargs): 165 | """ 166 | Constructs a ResNet model. 167 | """ 168 | return ResNet(**kwargs) 169 | -------------------------------------------------------------------------------- /models/victim/cifar/resnext.py: -------------------------------------------------------------------------------- 1 | from __future__ import division 2 | """ 3 | Creates a ResNeXt Model as defined in: 4 | Xie, S., Girshick, R., Dollar, P., Tu, Z., & He, K. (2016). 5 | Aggregated residual transformations for deep neural networks. 6 | arXiv preprint arXiv:1611.05431. 7 | import from https://github.com/prlz77/ResNeXt.pytorch/blob/master/models/model.py 8 | """ 9 | import torch.nn as nn 10 | import torch.nn.functional as F 11 | from torch.nn import init 12 | 13 | __all__ = ['resnext'] 14 | 15 | class ResNeXtBottleneck(nn.Module): 16 | """ 17 | RexNeXt bottleneck type C (https://github.com/facebookresearch/ResNeXt/blob/master/models/resnext.lua) 18 | """ 19 | def __init__(self, in_channels, out_channels, stride, cardinality, widen_factor): 20 | """ Constructor 21 | Args: 22 | in_channels: input channel dimensionality 23 | out_channels: output channel dimensionality 24 | stride: conv stride. Replaces pooling layer. 25 | cardinality: num of convolution groups. 26 | widen_factor: factor to reduce the input dimensionality before convolution. 27 | """ 28 | super(ResNeXtBottleneck, self).__init__() 29 | D = cardinality * out_channels // widen_factor 30 | self.conv_reduce = nn.Conv2d(in_channels, D, kernel_size=1, stride=1, padding=0, bias=False) 31 | self.bn_reduce = nn.BatchNorm2d(D) 32 | self.conv_conv = nn.Conv2d(D, D, kernel_size=3, stride=stride, padding=1, groups=cardinality, bias=False) 33 | self.bn = nn.BatchNorm2d(D) 34 | self.conv_expand = nn.Conv2d(D, out_channels, kernel_size=1, stride=1, padding=0, bias=False) 35 | self.bn_expand = nn.BatchNorm2d(out_channels) 36 | 37 | self.shortcut = nn.Sequential() 38 | if in_channels != out_channels: 39 | self.shortcut.add_module('shortcut_conv', nn.Conv2d(in_channels, out_channels, kernel_size=1, stride=stride, padding=0, bias=False)) 40 | self.shortcut.add_module('shortcut_bn', nn.BatchNorm2d(out_channels)) 41 | 42 | def forward(self, x): 43 | bottleneck = self.conv_reduce.forward(x) 44 | bottleneck = F.relu(self.bn_reduce.forward(bottleneck), inplace=True) 45 | bottleneck = self.conv_conv.forward(bottleneck) 46 | bottleneck = F.relu(self.bn.forward(bottleneck), inplace=True) 47 | bottleneck = self.conv_expand.forward(bottleneck) 48 | bottleneck = self.bn_expand.forward(bottleneck) 49 | residual = self.shortcut.forward(x) 50 | return F.relu(residual + bottleneck, inplace=True) 51 | 52 | 53 | class CifarResNeXt(nn.Module): 54 | """ 55 | ResNext optimized for the Cifar dataset, as specified in 56 | https://arxiv.org/pdf/1611.05431.pdf 57 | """ 58 | def __init__(self, cardinality, depth, num_classes, widen_factor=4, dropRate=0): 59 | """ Constructor 60 | Args: 61 | cardinality: number of convolution groups. 62 | depth: number of layers. 63 | num_classes: number of classes 64 | widen_factor: factor to adjust the channel dimensionality 65 | """ 66 | super(CifarResNeXt, self).__init__() 67 | self.cardinality = cardinality 68 | self.depth = depth 69 | self.block_depth = (self.depth - 2) // 9 70 | self.widen_factor = widen_factor 71 | self.num_classes = num_classes 72 | self.output_size = 64 73 | self.stages = [64, 64 * self.widen_factor, 128 * self.widen_factor, 256 * self.widen_factor] 74 | 75 | self.conv_1_3x3 = nn.Conv2d(3, 64, 3, 1, 1, bias=False) 76 | self.bn_1 = nn.BatchNorm2d(64) 77 | self.stage_1 = self.block('stage_1', self.stages[0], self.stages[1], 1) 78 | self.stage_2 = self.block('stage_2', self.stages[1], self.stages[2], 2) 79 | self.stage_3 = self.block('stage_3', self.stages[2], self.stages[3], 2) 80 | self.classifier = nn.Linear(1024, num_classes) 81 | init.kaiming_normal(self.classifier.weight) 82 | 83 | for key in self.state_dict(): 84 | if key.split('.')[-1] == 'weight': 85 | if 'conv' in key: 86 | init.kaiming_normal(self.state_dict()[key], mode='fan_out') 87 | if 'bn' in key: 88 | self.state_dict()[key][...] = 1 89 | elif key.split('.')[-1] == 'bias': 90 | self.state_dict()[key][...] = 0 91 | 92 | def block(self, name, in_channels, out_channels, pool_stride=2): 93 | """ Stack n bottleneck modules where n is inferred from the depth of the network. 94 | Args: 95 | name: string name of the current block. 96 | in_channels: number of input channels 97 | out_channels: number of output channels 98 | pool_stride: factor to reduce the spatial dimensionality in the first bottleneck of the block. 99 | Returns: a Module consisting of n sequential bottlenecks. 100 | """ 101 | block = nn.Sequential() 102 | for bottleneck in range(self.block_depth): 103 | name_ = '%s_bottleneck_%d' % (name, bottleneck) 104 | if bottleneck == 0: 105 | block.add_module(name_, ResNeXtBottleneck(in_channels, out_channels, pool_stride, self.cardinality, 106 | self.widen_factor)) 107 | else: 108 | block.add_module(name_, 109 | ResNeXtBottleneck(out_channels, out_channels, 1, self.cardinality, self.widen_factor)) 110 | return block 111 | 112 | def forward(self, x): 113 | x = self.conv_1_3x3.forward(x) 114 | x = F.relu(self.bn_1.forward(x), inplace=True) 115 | x = self.stage_1.forward(x) 116 | x = self.stage_2.forward(x) 117 | x = self.stage_3.forward(x) 118 | x = F.avg_pool2d(x, 8, 1) 119 | x = x.view(-1, 1024) 120 | return self.classifier(x) 121 | 122 | def resnext(**kwargs): 123 | """Constructs a ResNeXt. 124 | """ 125 | model = CifarResNeXt(**kwargs) 126 | return model -------------------------------------------------------------------------------- /models/victim/cifar/utils.py: -------------------------------------------------------------------------------- 1 | import torch.nn as nn 2 | import torch.nn.functional as F 3 | 4 | 5 | class DropoutConv2d(nn.Conv2d): 6 | def __init__(self, in_channels, out_channels, kernel_size, stride=1, 7 | padding=0, dilation=1, groups=1, bias=True, drop=0): 8 | super(DropoutConv2d, self).__init__( 9 | in_channels, out_channels, kernel_size, stride, padding, dilation, groups, bias) 10 | self.drop = drop 11 | 12 | def forward(self, x): 13 | x = super(DropoutConv2d, self).forward(x) 14 | x = F.dropout(x, p=self.drop, training=True) 15 | return x 16 | -------------------------------------------------------------------------------- /models/victim/cifar/vgg.py: -------------------------------------------------------------------------------- 1 | '''VGG for CIFAR10. FC layers are removed. 2 | (c) YANG, Wei 3 | ''' 4 | import torch.nn as nn 5 | import torch.nn.functional as F 6 | from .utils import DropoutConv2d 7 | import math 8 | 9 | 10 | __all__ = [ 11 | 'VGG', 'vgg11', 'vgg11_bn', 'vgg13', 'vgg13_bn', 'vgg16', 'vgg16_bn', 12 | 'vgg19_bn', 'vgg19', 13 | ] 14 | 15 | 16 | model_urls = { 17 | 'vgg11': 'https://download.pytorch.org/models/vgg11-bbd30ac9.pth', 18 | 'vgg13': 'https://download.pytorch.org/models/vgg13-c768596a.pth', 19 | 'vgg16': 'https://download.pytorch.org/models/vgg16-397923af.pth', 20 | 'vgg19': 'https://download.pytorch.org/models/vgg19-dcbb9e9d.pth', 21 | } 22 | 23 | 24 | class VGG(nn.Module): 25 | 26 | def __init__(self, features, num_classes=1000): 27 | super(VGG, self).__init__() 28 | self.features = features 29 | self.classifier = nn.Linear(512, num_classes) 30 | self._initialize_weights() 31 | 32 | # no dropout 33 | self.drop = 0 34 | 35 | def forward(self, x): 36 | for m in self.modules(): 37 | if isinstance(m, DropoutConv2d): 38 | m.drop = self.drop 39 | 40 | x = self.features(x) 41 | x = x.view(x.size(0), -1) 42 | x = F.dropout(x, p=self.drop, training=True) # force dropout 43 | x = self.classifier(x) 44 | return x 45 | 46 | def _initialize_weights(self): 47 | for m in self.modules(): 48 | if isinstance(m, DropoutConv2d): 49 | n = m.kernel_size[0] * m.kernel_size[1] * m.out_channels 50 | m.weight.data.normal_(0, math.sqrt(2. / n)) 51 | if m.bias is not None: 52 | m.bias.data.zero_() 53 | elif isinstance(m, nn.BatchNorm2d): 54 | m.weight.data.fill_(1) 55 | m.bias.data.zero_() 56 | elif isinstance(m, nn.Linear): 57 | n = m.weight.size(1) 58 | m.weight.data.normal_(0, 0.01) 59 | m.bias.data.zero_() 60 | 61 | 62 | def make_layers(cfg, batch_norm=False): 63 | layers = [] 64 | in_channels = 3 65 | for v in cfg: 66 | if v == 'M': 67 | layers += [nn.MaxPool2d(kernel_size=2, stride=2)] 68 | else: 69 | conv2d = DropoutConv2d(in_channels, v, kernel_size=3, padding=1) 70 | if batch_norm: 71 | layers += [conv2d, nn.BatchNorm2d(v), nn.ReLU(inplace=True)] 72 | else: 73 | layers += [conv2d, nn.ReLU(inplace=True)] 74 | in_channels = v 75 | return nn.Sequential(*layers) 76 | 77 | 78 | cfg = { 79 | 'A': [64, 'M', 128, 'M', 256, 256, 'M', 512, 512, 'M', 512, 512, 'M'], 80 | 'B': [64, 64, 'M', 128, 128, 'M', 256, 256, 'M', 512, 512, 'M', 512, 512, 'M'], 81 | 'D': [64, 64, 'M', 128, 128, 'M', 256, 256, 256, 'M', 512, 512, 512, 'M', 512, 512, 512, 'M'], 82 | 'E': [64, 64, 'M', 128, 128, 'M', 256, 256, 256, 256, 'M', 512, 512, 512, 512, 'M', 512, 512, 512, 512, 'M'], 83 | } 84 | 85 | 86 | def vgg11(**kwargs): 87 | """VGG 11-layer model (configuration "A") 88 | 89 | Args: 90 | pretrained (bool): If True, returns a model pre-trained on ImageNet 91 | """ 92 | model = VGG(make_layers(cfg['A']), **kwargs) 93 | return model 94 | 95 | 96 | def vgg11_bn(**kwargs): 97 | """VGG 11-layer model (configuration "A") with batch normalization""" 98 | model = VGG(make_layers(cfg['A'], batch_norm=True), **kwargs) 99 | return model 100 | 101 | 102 | def vgg13(**kwargs): 103 | """VGG 13-layer model (configuration "B") 104 | 105 | Args: 106 | pretrained (bool): If True, returns a model pre-trained on ImageNet 107 | """ 108 | model = VGG(make_layers(cfg['B']), **kwargs) 109 | return model 110 | 111 | 112 | def vgg13_bn(**kwargs): 113 | """VGG 13-layer model (configuration "B") with batch normalization""" 114 | model = VGG(make_layers(cfg['B'], batch_norm=True), **kwargs) 115 | return model 116 | 117 | 118 | def vgg16(**kwargs): 119 | """VGG 16-layer model (configuration "D") 120 | 121 | Args: 122 | pretrained (bool): If True, returns a model pre-trained on ImageNet 123 | """ 124 | model = VGG(make_layers(cfg['D']), **kwargs) 125 | return model 126 | 127 | 128 | def vgg16_bn(**kwargs): 129 | """VGG 16-layer model (configuration "D") with batch normalization""" 130 | model = VGG(make_layers(cfg['D'], batch_norm=True), **kwargs) 131 | return model 132 | 133 | 134 | def vgg19(**kwargs): 135 | """VGG 19-layer model (configuration "E") 136 | 137 | Args: 138 | pretrained (bool): If True, returns a model pre-trained on ImageNet 139 | """ 140 | model = VGG(make_layers(cfg['E']), **kwargs) 141 | return model 142 | 143 | 144 | def vgg19_bn(**kwargs): 145 | """VGG 19-layer model (configuration 'E') with batch normalization""" 146 | model = VGG(make_layers(cfg['E'], batch_norm=True), **kwargs) 147 | return model 148 | -------------------------------------------------------------------------------- /models/victim/cifar/wrn.py: -------------------------------------------------------------------------------- 1 | import math 2 | import torch 3 | import torch.nn as nn 4 | import torch.nn.functional as F 5 | 6 | __all__ = ['wrn'] 7 | 8 | 9 | class BasicBlock(nn.Module): 10 | def __init__(self, in_planes, out_planes, stride, dropRate=0.0): 11 | super(BasicBlock, self).__init__() 12 | self.bn1 = nn.BatchNorm2d(in_planes) 13 | self.relu1 = nn.ReLU(inplace=True) 14 | self.conv1 = nn.Conv2d(in_planes, out_planes, kernel_size=3, stride=stride, 15 | padding=1, bias=False) 16 | self.bn2 = nn.BatchNorm2d(out_planes) 17 | self.relu2 = nn.ReLU(inplace=True) 18 | self.conv2 = nn.Conv2d(out_planes, out_planes, kernel_size=3, stride=1, 19 | padding=1, bias=False) 20 | self.droprate = dropRate 21 | self.equalInOut = (in_planes == out_planes) 22 | self.convShortcut = (not self.equalInOut) and nn.Conv2d(in_planes, out_planes, kernel_size=1, stride=stride, 23 | padding=0, bias=False) or None 24 | 25 | def forward(self, x): 26 | if not self.equalInOut: 27 | x = self.relu1(self.bn1(x)) 28 | else: 29 | out = self.relu1(self.bn1(x)) 30 | out = self.relu2(self.bn2(self.conv1(out if self.equalInOut else x))) 31 | if self.droprate > 0: 32 | out = F.dropout(out, p=self.droprate, training=self.training) 33 | out = self.conv2(out) 34 | return torch.add(x if self.equalInOut else self.convShortcut(x), out) 35 | 36 | class NetworkBlock(nn.Module): 37 | def __init__(self, nb_layers, in_planes, out_planes, block, stride, dropRate=0.0): 38 | super(NetworkBlock, self).__init__() 39 | self.layer = self._make_layer(block, in_planes, out_planes, nb_layers, stride, dropRate) 40 | def _make_layer(self, block, in_planes, out_planes, nb_layers, stride, dropRate): 41 | layers = [] 42 | for i in range(nb_layers): 43 | layers.append(block(i == 0 and in_planes or out_planes, out_planes, i == 0 and stride or 1, dropRate)) 44 | return nn.Sequential(*layers) 45 | def forward(self, x): 46 | return self.layer(x) 47 | 48 | class WideResNet(nn.Module): 49 | def __init__(self, depth, num_classes, widen_factor=1, dropRate=0.0): 50 | super(WideResNet, self).__init__() 51 | nChannels = [16, 16*widen_factor, 32*widen_factor, 64*widen_factor] 52 | assert (depth - 4) % 6 == 0, 'depth should be 6n+4' 53 | n = (depth - 4) // 6 54 | block = BasicBlock 55 | # 1st conv before any network block 56 | self.conv1 = nn.Conv2d(3, nChannels[0], kernel_size=3, stride=1, 57 | padding=1, bias=False) 58 | # 1st block 59 | self.block1 = NetworkBlock(n, nChannels[0], nChannels[1], block, 1, dropRate) 60 | # 2nd block 61 | self.block2 = NetworkBlock(n, nChannels[1], nChannels[2], block, 2, dropRate) 62 | # 3rd block 63 | self.block3 = NetworkBlock(n, nChannels[2], nChannels[3], block, 2, dropRate) 64 | # global average pooling and classifier 65 | self.bn1 = nn.BatchNorm2d(nChannels[3]) 66 | self.relu = nn.ReLU(inplace=True) 67 | self.fc = nn.Linear(nChannels[3], num_classes) 68 | self.nChannels = nChannels[3] 69 | 70 | for m in self.modules(): 71 | if isinstance(m, nn.Conv2d): 72 | n = m.kernel_size[0] * m.kernel_size[1] * m.out_channels 73 | m.weight.data.normal_(0, math.sqrt(2. / n)) 74 | elif isinstance(m, nn.BatchNorm2d): 75 | m.weight.data.fill_(1) 76 | m.bias.data.zero_() 77 | elif isinstance(m, nn.Linear): 78 | m.bias.data.zero_() 79 | 80 | def forward(self, x): 81 | out = self.conv1(x) 82 | out = self.block1(out) 83 | out = self.block2(out) 84 | out = self.block3(out) 85 | out = self.relu(self.bn1(out)) 86 | out = F.avg_pool2d(out, 8) 87 | out = out.view(-1, self.nChannels) 88 | return self.fc(out) 89 | 90 | def wrn(**kwargs): 91 | """ 92 | Constructs a Wide Residual Networks. 93 | """ 94 | model = WideResNet(**kwargs) 95 | return model 96 | -------------------------------------------------------------------------------- /models/victim/debug/__init__.py: -------------------------------------------------------------------------------- 1 | from models.victim.debug.lr import * 2 | -------------------------------------------------------------------------------- /models/victim/debug/lr.py: -------------------------------------------------------------------------------- 1 | import torch 2 | import torch.nn as nn 3 | 4 | __all__ = ['lr'] 5 | 6 | 7 | class LR(nn.Module): 8 | def __init__(self, num_classes=2): 9 | super(LR, self).__init__() 10 | self.fc = nn.Linear(2, num_classes) 11 | self.fc.weight.data[:] = torch.FloatTensor([[0., -1.], [0., 1.]]) 12 | self.fc.bias.data[:] = torch.FloatTensor([0.5, -0.5]) 13 | 14 | def forward(self, x): 15 | x = x.view(x.shape[0], -1) 16 | x = self.fc(x) 17 | return x 18 | 19 | 20 | def lr(**kwargs): 21 | return LR(**kwargs) 22 | -------------------------------------------------------------------------------- /models/victim/imagenet/LICENSE.txt: -------------------------------------------------------------------------------- 1 | BSD 3-Clause License 2 | 3 | Copyright (c) 2017, Remi Cadene 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions are met: 8 | 9 | * Redistributions of source code must retain the above copyright notice, this 10 | list of conditions and the following disclaimer. 11 | 12 | * Redistributions in binary form must reproduce the above copyright notice, 13 | this list of conditions and the following disclaimer in the documentation 14 | and/or other materials provided with the distribution. 15 | 16 | * Neither the name of the copyright holder nor the names of its 17 | contributors may be used to endorse or promote products derived from 18 | this software without specific prior written permission. 19 | 20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 21 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 23 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 24 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 26 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 27 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 28 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | -------------------------------------------------------------------------------- /models/victim/imagenet/README.md: -------------------------------------------------------------------------------- 1 | # ImageNet CNN models 2 | This folder contains a slightly modified version of the [pretrained-models.pytorch](https://github.com/Cadene/pretrained-models.pytorch) project code (Copyright to [Remi Cadene](https://github.com/Cadene)). 3 | -------------------------------------------------------------------------------- /models/victim/imagenet/__init__.py: -------------------------------------------------------------------------------- 1 | from models.victim.imagenet.inceptionresnetv2 import inceptionresnetv2 2 | 3 | from models.victim.imagenet.nasnet import nasnetalarge 4 | 5 | from models.victim.imagenet.nasnet_mobile import nasnetamobile 6 | 7 | from models.victim.imagenet.torchvision_models import alexnet 8 | from models.victim.imagenet.torchvision_models import densenet121 9 | from models.victim.imagenet.torchvision_models import densenet169 10 | from models.victim.imagenet.torchvision_models import densenet201 11 | from models.victim.imagenet.torchvision_models import densenet161 12 | from models.victim.imagenet.torchvision_models import resnet18 13 | from models.victim.imagenet.torchvision_models import resnet34 14 | from models.victim.imagenet.torchvision_models import resnet50 15 | from models.victim.imagenet.torchvision_models import resnet101 16 | from models.victim.imagenet.torchvision_models import resnet152 17 | from models.victim.imagenet.torchvision_models import inceptionv3 18 | from models.victim.imagenet.torchvision_models import squeezenet1_0 19 | from models.victim.imagenet.torchvision_models import squeezenet1_1 20 | from models.victim.imagenet.torchvision_models import vgg11 21 | from models.victim.imagenet.torchvision_models import vgg11_bn 22 | from models.victim.imagenet.torchvision_models import vgg13 23 | from models.victim.imagenet.torchvision_models import vgg13_bn 24 | from models.victim.imagenet.torchvision_models import vgg16 25 | from models.victim.imagenet.torchvision_models import vgg16_bn 26 | from models.victim.imagenet.torchvision_models import vgg19_bn 27 | from models.victim.imagenet.torchvision_models import vgg19 28 | 29 | from models.victim.imagenet.dpn import dpn68 30 | from models.victim.imagenet.dpn import dpn68b 31 | from models.victim.imagenet.dpn import dpn92 32 | from models.victim.imagenet.dpn import dpn98 33 | from models.victim.imagenet.dpn import dpn131 34 | from models.victim.imagenet.dpn import dpn107 35 | 36 | from models.victim.imagenet.xception import xception 37 | 38 | from models.victim.imagenet.senet import senet154 39 | from models.victim.imagenet.senet import se_resnet50 40 | from models.victim.imagenet.senet import se_resnet101 41 | from models.victim.imagenet.senet import se_resnet152 42 | from models.victim.imagenet.senet import se_resnext50_32x4d 43 | from models.victim.imagenet.senet import se_resnext101_32x4d 44 | 45 | from models.victim.imagenet.pnasnet import pnasnet5large 46 | from models.victim.imagenet.polynet import polynet 47 | -------------------------------------------------------------------------------- /models/victim/imagenet/cafferesnet.py: -------------------------------------------------------------------------------- 1 | from __future__ import print_function, division, absolute_import 2 | import math 3 | import torch 4 | import torch.nn as nn 5 | import torch.nn.functional as F 6 | import torch.utils.model_zoo as model_zoo 7 | 8 | pretrained_settings = { 9 | 'cafferesnet101': { 10 | 'imagenet': { 11 | 'url': 'http://data.lip6.fr/cadene/pretrainedmodels/cafferesnet101-9d633cc0.pth', 12 | 'input_space': 'BGR', 13 | 'input_size': [3, 224, 224], 14 | 'input_range': [0, 255], 15 | 'mean': [102.9801, 115.9465, 122.7717], 16 | 'std': [1, 1, 1], 17 | 'num_classes': 1000 18 | } 19 | } 20 | } 21 | 22 | 23 | def conv3x3(in_planes, out_planes, stride=1): 24 | "3x3 convolution with padding" 25 | return nn.Conv2d(in_planes, out_planes, kernel_size=3, stride=stride, 26 | padding=1, bias=False) 27 | 28 | 29 | class BasicBlock(nn.Module): 30 | expansion = 1 31 | 32 | def __init__(self, inplanes, planes, stride=1, downsample=None): 33 | super(BasicBlock, self).__init__() 34 | self.conv1 = conv3x3(inplanes, planes, stride) 35 | self.bn1 = nn.BatchNorm2d(planes) 36 | self.relu = nn.ReLU(inplace=True) 37 | self.conv2 = conv3x3(planes, planes) 38 | self.bn2 = nn.BatchNorm2d(planes) 39 | self.downsample = downsample 40 | self.stride = stride 41 | 42 | def forward(self, x): 43 | residual = x 44 | 45 | out = self.conv1(x) 46 | out = self.bn1(out) 47 | out = self.relu(out) 48 | 49 | out = self.conv2(out) 50 | out = self.bn2(out) 51 | 52 | if self.downsample is not None: 53 | residual = self.downsample(x) 54 | 55 | out += residual 56 | out = self.relu(out) 57 | 58 | return out 59 | 60 | 61 | class Bottleneck(nn.Module): 62 | expansion = 4 63 | 64 | def __init__(self, inplanes, planes, stride=1, downsample=None): 65 | super(Bottleneck, self).__init__() 66 | self.conv1 = nn.Conv2d(inplanes, planes, kernel_size=1, stride=stride, bias=False) # change 67 | self.bn1 = nn.BatchNorm2d(planes) 68 | self.conv2 = nn.Conv2d(planes, planes, kernel_size=3, stride=1, # change 69 | padding=1, bias=False) 70 | self.bn2 = nn.BatchNorm2d(planes) 71 | self.conv3 = nn.Conv2d(planes, planes * 4, kernel_size=1, bias=False) 72 | self.bn3 = nn.BatchNorm2d(planes * 4) 73 | self.relu = nn.ReLU(inplace=True) 74 | self.downsample = downsample 75 | self.stride = stride 76 | 77 | def forward(self, x): 78 | residual = x 79 | 80 | out = self.conv1(x) 81 | out = self.bn1(out) 82 | out = self.relu(out) 83 | 84 | out = self.conv2(out) 85 | out = self.bn2(out) 86 | out = self.relu(out) 87 | 88 | out = self.conv3(out) 89 | out = self.bn3(out) 90 | 91 | if self.downsample is not None: 92 | residual = self.downsample(x) 93 | 94 | out += residual 95 | out = self.relu(out) 96 | 97 | return out 98 | 99 | 100 | class ResNet(nn.Module): 101 | 102 | def __init__(self, block, layers, num_classes=1000): 103 | self.inplanes = 64 104 | super(ResNet, self).__init__() 105 | self.conv1 = nn.Conv2d(3, 64, kernel_size=7, stride=2, padding=3, 106 | bias=False) 107 | self.bn1 = nn.BatchNorm2d(64) 108 | self.relu = nn.ReLU(inplace=True) 109 | self.maxpool = nn.MaxPool2d(kernel_size=3, stride=2, padding=0, ceil_mode=True) # change 110 | self.layer1 = self._make_layer(block, 64, layers[0]) 111 | self.layer2 = self._make_layer(block, 128, layers[1], stride=2) 112 | self.layer3 = self._make_layer(block, 256, layers[2], stride=2) 113 | self.layer4 = self._make_layer(block, 512, layers[3], stride=2) 114 | # it is slightly better whereas slower to set stride = 1 115 | # self.layer4 = self._make_layer(block, 512, layers[3], stride=1) 116 | self.avgpool = nn.AvgPool2d(7) 117 | self.last_linear = nn.Linear(512 * block.expansion, num_classes) 118 | 119 | for m in self.modules(): 120 | if isinstance(m, nn.Conv2d): 121 | n = m.kernel_size[0] * m.kernel_size[1] * m.out_channels 122 | m.weight.data.normal_(0, math.sqrt(2. / n)) 123 | elif isinstance(m, nn.BatchNorm2d): 124 | m.weight.data.fill_(1) 125 | m.bias.data.zero_() 126 | 127 | def _make_layer(self, block, planes, blocks, stride=1): 128 | downsample = None 129 | if stride != 1 or self.inplanes != planes * block.expansion: 130 | downsample = nn.Sequential( 131 | nn.Conv2d(self.inplanes, planes * block.expansion, 132 | kernel_size=1, stride=stride, bias=False), 133 | nn.BatchNorm2d(planes * block.expansion), 134 | ) 135 | 136 | layers = [] 137 | layers.append(block(self.inplanes, planes, stride, downsample)) 138 | self.inplanes = planes * block.expansion 139 | for i in range(1, blocks): 140 | layers.append(block(self.inplanes, planes)) 141 | 142 | return nn.Sequential(*layers) 143 | 144 | def features(self, x): 145 | x = self.conv1(x) 146 | x = self.bn1(x) 147 | x = self.relu(x) 148 | x = self.maxpool(x) 149 | 150 | x = self.layer1(x) 151 | x = self.layer2(x) 152 | x = self.layer3(x) 153 | x = self.layer4(x) 154 | return x 155 | 156 | def logits(self, x): 157 | x = self.avgpool(x) 158 | x = x.view(x.size(0), -1) 159 | x = self.last_linear(x) 160 | return x 161 | 162 | def forward(self, x): 163 | x = self.features(x) 164 | x = self.logits(x) 165 | return x 166 | 167 | 168 | def cafferesnet101(num_classes=1000, pretrained='imagenet'): 169 | """Constructs a ResNet-101 model. 170 | Args: 171 | pretrained (bool): If True, returns a model pre-trained on ImageNet 172 | """ 173 | model = ResNet(Bottleneck, [3, 4, 23, 3], num_classes=num_classes) 174 | if pretrained is not None: 175 | settings = pretrained_settings['cafferesnet101'][pretrained] 176 | assert num_classes == settings['num_classes'], \ 177 | "num_classes should be {}, but is {}".format(settings['num_classes'], num_classes) 178 | model.load_state_dict(model_zoo.load_url(settings['url'])) 179 | model.input_space = settings['input_space'] 180 | model.input_size = settings['input_size'] 181 | model.input_range = settings['input_range'] 182 | model.mean = settings['mean'] 183 | model.std = settings['std'] 184 | return model -------------------------------------------------------------------------------- /models/victim/imagenet/fbresnet.py: -------------------------------------------------------------------------------- 1 | from __future__ import print_function, division, absolute_import 2 | import torch.nn as nn 3 | import torch.nn.functional as F 4 | import math 5 | import torch.utils.model_zoo as model_zoo 6 | 7 | 8 | __all__ = ['FBResNet', 9 | #'fbresnet18', 'fbresnet34', 'fbresnet50', 'fbresnet101', 10 | 'fbresnet152'] 11 | 12 | pretrained_settings = { 13 | 'fbresnet152': { 14 | 'imagenet': { 15 | 'url': 'http://data.lip6.fr/cadene/pretrainedmodels/fbresnet152-2e20f6b4.pth', 16 | 'input_space': 'RGB', 17 | 'input_size': [3, 224, 224], 18 | 'input_range': [0, 1], 19 | 'mean': [0.485, 0.456, 0.406], 20 | 'std': [0.229, 0.224, 0.225], 21 | 'num_classes': 1000 22 | } 23 | } 24 | } 25 | 26 | 27 | def conv3x3(in_planes, out_planes, stride=1): 28 | "3x3 convolution with padding" 29 | return nn.Conv2d(in_planes, out_planes, kernel_size=3, stride=stride, 30 | padding=1, bias=True) 31 | 32 | 33 | class BasicBlock(nn.Module): 34 | expansion = 1 35 | 36 | def __init__(self, inplanes, planes, stride=1, downsample=None): 37 | super(BasicBlock, self).__init__() 38 | self.conv1 = conv3x3(inplanes, planes, stride) 39 | self.bn1 = nn.BatchNorm2d(planes) 40 | self.relu = nn.ReLU(inplace=True) 41 | self.conv2 = conv3x3(planes, planes) 42 | self.bn2 = nn.BatchNorm2d(planes) 43 | self.downsample = downsample 44 | self.stride = stride 45 | 46 | def forward(self, x): 47 | residual = x 48 | 49 | out = self.conv1(x) 50 | out = self.bn1(out) 51 | out = self.relu(out) 52 | 53 | out = self.conv2(out) 54 | out = self.bn2(out) 55 | 56 | if self.downsample is not None: 57 | residual = self.downsample(x) 58 | 59 | out += residual 60 | out = self.relu(out) 61 | 62 | return out 63 | 64 | 65 | class Bottleneck(nn.Module): 66 | expansion = 4 67 | 68 | def __init__(self, inplanes, planes, stride=1, downsample=None): 69 | super(Bottleneck, self).__init__() 70 | self.conv1 = nn.Conv2d(inplanes, planes, kernel_size=1, bias=True) 71 | self.bn1 = nn.BatchNorm2d(planes) 72 | self.conv2 = nn.Conv2d(planes, planes, kernel_size=3, stride=stride, 73 | padding=1, bias=True) 74 | self.bn2 = nn.BatchNorm2d(planes) 75 | self.conv3 = nn.Conv2d(planes, planes * 4, kernel_size=1, bias=True) 76 | self.bn3 = nn.BatchNorm2d(planes * 4) 77 | self.relu = nn.ReLU(inplace=True) 78 | self.downsample = downsample 79 | self.stride = stride 80 | 81 | def forward(self, x): 82 | residual = x 83 | 84 | out = self.conv1(x) 85 | out = self.bn1(out) 86 | out = self.relu(out) 87 | 88 | out = self.conv2(out) 89 | out = self.bn2(out) 90 | out = self.relu(out) 91 | 92 | out = self.conv3(out) 93 | out = self.bn3(out) 94 | 95 | if self.downsample is not None: 96 | residual = self.downsample(x) 97 | 98 | out += residual 99 | out = self.relu(out) 100 | 101 | return out 102 | 103 | class FBResNet(nn.Module): 104 | 105 | def __init__(self, block, layers, num_classes=1000): 106 | self.inplanes = 64 107 | # Special attributs 108 | self.input_space = None 109 | self.input_size = (299, 299, 3) 110 | self.mean = None 111 | self.std = None 112 | super(FBResNet, self).__init__() 113 | # Modules 114 | self.conv1 = nn.Conv2d(3, 64, kernel_size=7, stride=2, padding=3, 115 | bias=True) 116 | self.bn1 = nn.BatchNorm2d(64) 117 | self.relu = nn.ReLU(inplace=True) 118 | self.maxpool = nn.MaxPool2d(kernel_size=3, stride=2, padding=1) 119 | self.layer1 = self._make_layer(block, 64, layers[0]) 120 | self.layer2 = self._make_layer(block, 128, layers[1], stride=2) 121 | self.layer3 = self._make_layer(block, 256, layers[2], stride=2) 122 | self.layer4 = self._make_layer(block, 512, layers[3], stride=2) 123 | self.last_linear = nn.Linear(512 * block.expansion, num_classes) 124 | 125 | for m in self.modules(): 126 | if isinstance(m, nn.Conv2d): 127 | n = m.kernel_size[0] * m.kernel_size[1] * m.out_channels 128 | m.weight.data.normal_(0, math.sqrt(2. / n)) 129 | elif isinstance(m, nn.BatchNorm2d): 130 | m.weight.data.fill_(1) 131 | m.bias.data.zero_() 132 | 133 | def _make_layer(self, block, planes, blocks, stride=1): 134 | downsample = None 135 | if stride != 1 or self.inplanes != planes * block.expansion: 136 | downsample = nn.Sequential( 137 | nn.Conv2d(self.inplanes, planes * block.expansion, 138 | kernel_size=1, stride=stride, bias=True), 139 | nn.BatchNorm2d(planes * block.expansion), 140 | ) 141 | 142 | layers = [] 143 | layers.append(block(self.inplanes, planes, stride, downsample)) 144 | self.inplanes = planes * block.expansion 145 | for i in range(1, blocks): 146 | layers.append(block(self.inplanes, planes)) 147 | 148 | return nn.Sequential(*layers) 149 | 150 | def features(self, input): 151 | x = self.conv1(input) 152 | self.conv1_input = x.clone() 153 | x = self.bn1(x) 154 | x = self.relu(x) 155 | x = self.maxpool(x) 156 | 157 | x = self.layer1(x) 158 | x = self.layer2(x) 159 | x = self.layer3(x) 160 | x = self.layer4(x) 161 | return x 162 | 163 | def logits(self, features): 164 | adaptiveAvgPoolWidth = features.shape[2] 165 | x = F.avg_pool2d(features, kernel_size=adaptiveAvgPoolWidth) 166 | x = x.view(x.size(0), -1) 167 | x = self.last_linear(x) 168 | return x 169 | 170 | def forward(self, input): 171 | x = self.features(input) 172 | x = self.logits(x) 173 | return x 174 | 175 | 176 | def fbresnet18(num_classes=1000): 177 | """Constructs a ResNet-18 model. 178 | 179 | Args: 180 | pretrained (bool): If True, returns a model pre-trained on ImageNet 181 | """ 182 | model = FBResNet(BasicBlock, [2, 2, 2, 2], num_classes=num_classes) 183 | return model 184 | 185 | 186 | def fbresnet34(num_classes=1000): 187 | """Constructs a ResNet-34 model. 188 | 189 | Args: 190 | pretrained (bool): If True, returns a model pre-trained on ImageNet 191 | """ 192 | model = FBResNet(BasicBlock, [3, 4, 6, 3], num_classes=num_classes) 193 | return model 194 | 195 | 196 | def fbresnet50(num_classes=1000): 197 | """Constructs a ResNet-50 model. 198 | 199 | Args: 200 | pretrained (bool): If True, returns a model pre-trained on ImageNet 201 | """ 202 | model = FBResNet(Bottleneck, [3, 4, 6, 3], num_classes=num_classes) 203 | return model 204 | 205 | 206 | def fbresnet101(num_classes=1000): 207 | """Constructs a ResNet-101 model. 208 | 209 | Args: 210 | pretrained (bool): If True, returns a model pre-trained on ImageNet 211 | """ 212 | model = FBResNet(Bottleneck, [3, 4, 23, 3], num_classes=num_classes) 213 | return model 214 | 215 | 216 | def fbresnet152(num_classes=1000, pretrained='imagenet'): 217 | """Constructs a ResNet-152 model. 218 | 219 | Args: 220 | pretrained (bool): If True, returns a model pre-trained on ImageNet 221 | """ 222 | model = FBResNet(Bottleneck, [3, 8, 36, 3], num_classes=num_classes) 223 | if pretrained is not None: 224 | settings = pretrained_settings['fbresnet152'][pretrained] 225 | assert num_classes == settings['num_classes'], \ 226 | "num_classes should be {}, but is {}".format(settings['num_classes'], num_classes) 227 | model.load_state_dict(model_zoo.load_url(settings['url'])) 228 | model.input_space = settings['input_space'] 229 | model.input_size = settings['input_size'] 230 | model.input_range = settings['input_range'] 231 | model.mean = settings['mean'] 232 | model.std = settings['std'] 233 | return model 234 | 235 | 236 | -------------------------------------------------------------------------------- /models/victim/imagenet/fbresnet/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ZiangYan/pda.pytorch/982e4088934a4f0d2d8b71ee18ab08d3a32358f4/models/victim/imagenet/fbresnet/__init__.py -------------------------------------------------------------------------------- /models/victim/imagenet/fbresnet/resnet152_dump.lua: -------------------------------------------------------------------------------- 1 | require 'cutorch' 2 | require 'cunn' 3 | require 'cudnn' 4 | require 'image' 5 | vision=require 'torchnet-vision' 6 | 7 | net=vision.models.resnet.load{filename='data/resnet152/net.t7',length=152} 8 | print(net) 9 | 10 | require 'nn' 11 | nn.Module.parameters = function(self) 12 | if self.weight and self.bias and self.running_mean and self.running_var then 13 | return {self.weight, self.bias, self.running_mean, self.running_var}, {self.gradWeight, self.gradBias} 14 | 15 | elseif self.weight and self.bias then 16 | return {self.weight, self.bias}, {self.gradWeight, self.gradBias} 17 | elseif self.weight then 18 | return {self.weight}, {self.gradWeight} 19 | elseif self.bias then 20 | return {self.bias}, {self.gradBias} 21 | else 22 | return 23 | end 24 | end 25 | 26 | netparams, _ = net:parameters() 27 | print(#netparams) 28 | torch.save('data/resnet152/netparams.t7', netparams) 29 | 30 | net=net:cuda() 31 | net:evaluate() 32 | --p, gp = net:getParameters() 33 | input = torch.ones(1,3,224,224) 34 | input[{1,1,1,1}] = -1 35 | input[1] = image.load('data/cat_224.png') 36 | print(input:sum()) 37 | input = input:cuda() 38 | output=net:forward(input) 39 | 40 | for i=1, 11 do 41 | torch.save('data/resnet152/output'..i..'.t7', net:get(i).output:float()) 42 | end 43 | -------------------------------------------------------------------------------- /models/victim/imagenet/fbresnet/resnet152_load.py: -------------------------------------------------------------------------------- 1 | from __future__ import print_function, division, absolute_import 2 | import torch.nn as nn 3 | import math 4 | import torch.utils.model_zoo as model_zoo 5 | 6 | 7 | __all__ = ['ResNet', 'resnet18', 'resnet34', 'resnet50', 'resnet101', 8 | 'resnet152'] 9 | 10 | 11 | model_urls = { 12 | 'resnet18': 'https://download.pytorch.org/models/resnet18-5c106cde.pth', 13 | 'resnet34': 'https://download.pytorch.org/models/resnet34-333f7ec4.pth', 14 | 'resnet50': 'https://download.pytorch.org/models/resnet50-19c8e357.pth', 15 | 'resnet101': 'https://download.pytorch.org/models/resnet101-5d3b4d8f.pth', 16 | 'resnet152': 'https://download.pytorch.org/models/resnet152-b121ed2d.pth', 17 | } 18 | 19 | 20 | def conv3x3(in_planes, out_planes, stride=1): 21 | "3x3 convolution with padding" 22 | return nn.Conv2d(in_planes, out_planes, kernel_size=3, stride=stride, 23 | padding=1, bias=True) 24 | 25 | 26 | class BasicBlock(nn.Module): 27 | expansion = 1 28 | 29 | def __init__(self, inplanes, planes, stride=1, downsample=None): 30 | super(BasicBlock, self).__init__() 31 | self.conv1 = conv3x3(inplanes, planes, stride) 32 | self.bn1 = nn.BatchNorm2d(planes) 33 | self.relu = nn.ReLU(inplace=True) 34 | self.conv2 = conv3x3(planes, planes) 35 | self.bn2 = nn.BatchNorm2d(planes) 36 | self.downsample = downsample 37 | self.stride = stride 38 | 39 | def forward(self, x): 40 | residual = x 41 | 42 | out = self.conv1(x) 43 | out = self.bn1(out) 44 | out = self.relu(out) 45 | 46 | out = self.conv2(out) 47 | out = self.bn2(out) 48 | 49 | if self.downsample is not None: 50 | residual = self.downsample(x) 51 | 52 | out += residual 53 | out = self.relu(out) 54 | 55 | return out 56 | 57 | 58 | class Bottleneck(nn.Module): 59 | expansion = 4 60 | 61 | def __init__(self, inplanes, planes, stride=1, downsample=None): 62 | super(Bottleneck, self).__init__() 63 | self.conv1 = nn.Conv2d(inplanes, planes, kernel_size=1, bias=True) 64 | self.bn1 = nn.BatchNorm2d(planes) 65 | self.conv2 = nn.Conv2d(planes, planes, kernel_size=3, stride=stride, 66 | padding=1, bias=True) 67 | self.bn2 = nn.BatchNorm2d(planes) 68 | self.conv3 = nn.Conv2d(planes, planes * 4, kernel_size=1, bias=True) 69 | self.bn3 = nn.BatchNorm2d(planes * 4) 70 | self.relu = nn.ReLU(inplace=True) 71 | self.downsample = downsample 72 | self.stride = stride 73 | 74 | def forward(self, x): 75 | residual = x 76 | 77 | out = self.conv1(x) 78 | out = self.bn1(out) 79 | out = self.relu(out) 80 | 81 | out = self.conv2(out) 82 | out = self.bn2(out) 83 | out = self.relu(out) 84 | 85 | out = self.conv3(out) 86 | out = self.bn3(out) 87 | 88 | if self.downsample is not None: 89 | residual = self.downsample(x) 90 | 91 | out += residual 92 | out = self.relu(out) 93 | 94 | return out 95 | 96 | from torch.legacy import nn as nnl 97 | 98 | class ResNet(nn.Module): 99 | 100 | def __init__(self, block, layers, num_classes=1000): 101 | self.inplanes = 64 102 | super(ResNet, self).__init__() 103 | self.conv1 = nn.Conv2d(3, 64, kernel_size=7, stride=2, padding=3, 104 | bias=True) 105 | #self.conv1 = nnl.SpatialConvolution(3, 64, 7, 7, 2, 2, 3, 3) 106 | self.bn1 = nn.BatchNorm2d(64) 107 | self.relu = nn.ReLU(inplace=True) 108 | self.maxpool = nn.MaxPool2d(kernel_size=3, stride=2, padding=1) 109 | self.layer1 = self._make_layer(block, 64, layers[0]) 110 | self.layer2 = self._make_layer(block, 128, layers[1], stride=2) 111 | self.layer3 = self._make_layer(block, 256, layers[2], stride=2) 112 | self.layer4 = self._make_layer(block, 512, layers[3], stride=2) 113 | self.avgpool = nn.AvgPool2d(7) 114 | self.fc = nn.Linear(512 * block.expansion, num_classes) 115 | 116 | for m in self.modules(): 117 | if isinstance(m, nn.Conv2d): 118 | n = m.kernel_size[0] * m.kernel_size[1] * m.out_channels 119 | m.weight.data.normal_(0, math.sqrt(2. / n)) 120 | elif isinstance(m, nn.BatchNorm2d): 121 | m.weight.data.fill_(1) 122 | m.bias.data.zero_() 123 | 124 | def _make_layer(self, block, planes, blocks, stride=1): 125 | downsample = None 126 | if stride != 1 or self.inplanes != planes * block.expansion: 127 | downsample = nn.Sequential( 128 | nn.Conv2d(self.inplanes, planes * block.expansion, 129 | kernel_size=1, stride=stride, bias=True), 130 | nn.BatchNorm2d(planes * block.expansion), 131 | ) 132 | 133 | layers = [] 134 | layers.append(block(self.inplanes, planes, stride, downsample)) 135 | self.inplanes = planes * block.expansion 136 | for i in range(1, blocks): 137 | layers.append(block(self.inplanes, planes)) 138 | 139 | return nn.Sequential(*layers) 140 | 141 | def forward(self, x): 142 | x = self.conv1(x) 143 | self.conv1_input = x.clone() 144 | x = self.bn1(x) 145 | x = self.relu(x) 146 | x = self.maxpool(x) 147 | 148 | x = self.layer1(x) 149 | x = self.layer2(x) 150 | x = self.layer3(x) 151 | x = self.layer4(x) 152 | 153 | x = self.avgpool(x) 154 | x = x.view(x.size(0), -1) 155 | x = self.fc(x) 156 | 157 | return x 158 | 159 | 160 | def resnet18(pretrained=False, **kwargs): 161 | """Constructs a ResNet-18 model. 162 | 163 | Args: 164 | pretrained (bool): If True, returns a model pre-trained on ImageNet 165 | """ 166 | model = ResNet(BasicBlock, [2, 2, 2, 2], **kwargs) 167 | if pretrained: 168 | model.load_state_dict(model_zoo.load_url(model_urls['resnet18'])) 169 | return model 170 | 171 | 172 | def resnet34(pretrained=False, **kwargs): 173 | """Constructs a ResNet-34 model. 174 | 175 | Args: 176 | pretrained (bool): If True, returns a model pre-trained on ImageNet 177 | """ 178 | model = ResNet(BasicBlock, [3, 4, 6, 3], **kwargs) 179 | if pretrained: 180 | model.load_state_dict(model_zoo.load_url(model_urls['resnet34'])) 181 | return model 182 | 183 | 184 | def resnet50(pretrained=False, **kwargs): 185 | """Constructs a ResNet-50 model. 186 | 187 | Args: 188 | pretrained (bool): If True, returns a model pre-trained on ImageNet 189 | """ 190 | model = ResNet(Bottleneck, [3, 4, 6, 3], **kwargs) 191 | if pretrained: 192 | model.load_state_dict(model_zoo.load_url(model_urls['resnet50'])) 193 | return model 194 | 195 | 196 | def resnet101(pretrained=False, **kwargs): 197 | """Constructs a ResNet-101 model. 198 | 199 | Args: 200 | pretrained (bool): If True, returns a model pre-trained on ImageNet 201 | """ 202 | model = ResNet(Bottleneck, [3, 4, 23, 3], **kwargs) 203 | if pretrained: 204 | model.load_state_dict(model_zoo.load_url(model_urls['resnet101'])) 205 | return model 206 | 207 | 208 | def resnet152(pretrained=False, **kwargs): 209 | """Constructs a ResNet-152 model. 210 | 211 | Args: 212 | pretrained (bool): If True, returns a model pre-trained on ImageNet 213 | """ 214 | model = ResNet(Bottleneck, [3, 8, 36, 3], **kwargs) 215 | if pretrained: 216 | model.load_state_dict(model_zoo.load_url(model_urls['resnet152'])) 217 | return model 218 | 219 | import torchfile 220 | from torch.utils.serialization import load_lua 221 | import torch 222 | netparams = torchfile.load('data/resnet152/netparams.t7') 223 | #netparams2 = load_lua('data/resnet152/netparams.t7') 224 | #import ipdb; ipdb.set_trace() 225 | netoutputs = [] 226 | for i in range(1, 12): 227 | path = 'data/resnet152/output{}.t7'.format(i) 228 | out = load_lua(path) 229 | #print(out.size()) 230 | if out.dim()==4: 231 | pass#out.transpose_(2, 3) 232 | netoutputs.append(out) 233 | 234 | net = resnet152() 235 | state_dict = net.state_dict() 236 | 237 | import collections 238 | s = collections.OrderedDict() 239 | 240 | 241 | i=0 242 | for key in state_dict.keys(): 243 | new = torch.from_numpy(netparams[i]) 244 | s[key] = new 245 | if s[key].dim() == 4: 246 | pass#s[key].transpose_(2,3) 247 | i += 1 248 | 249 | net.load_state_dict(s) 250 | 251 | net.conv1.register_forward_hook(lambda self, input, output: \ 252 | print('conv1', torch.dist(output.data, netoutputs[0]))) 253 | net.bn1.register_forward_hook(lambda self, input, output: \ 254 | print('bn1', torch.dist(output.data, netoutputs[1]))) 255 | net.relu.register_forward_hook(lambda self, input, output: \ 256 | print('relu', torch.dist(output.data, netoutputs[2]))) 257 | net.maxpool.register_forward_hook(lambda self, input, output: \ 258 | print('maxpool', torch.dist(output.data, netoutputs[3]))) 259 | net.layer1.register_forward_hook(lambda self, input, output: \ 260 | print('layer1', torch.dist(output.data, netoutputs[4]))) 261 | net.layer2.register_forward_hook(lambda self, input, output: \ 262 | print('layer2', torch.dist(output.data, netoutputs[5]))) 263 | net.layer3.register_forward_hook(lambda self, input, output: \ 264 | print('layer3', torch.dist(output.data, netoutputs[6]))) 265 | net.layer4.register_forward_hook(lambda self, input, output: \ 266 | print('layer4', torch.dist(output.data, netoutputs[7]))) 267 | net.avgpool.register_forward_hook(lambda self, input, output: \ 268 | print('avgpool', torch.dist(output.data, netoutputs[8]))) 269 | net.fc.register_forward_hook(lambda self, input, output: \ 270 | print('fc', torch.dist(output.data, netoutputs[10]))) 271 | 272 | net.eval() 273 | input_data = torch.ones(1,3,224,224) 274 | input_data[0][0][0][0] = -1 275 | from PIL import Image 276 | import torchvision.transforms as transforms 277 | input_data[0] = transforms.ToTensor()(Image.open('data/cat_224.png')) 278 | print('cat sum', input_data.sum()) 279 | input = torch.autograd.Variable(input_data) 280 | output = net.forward(input) 281 | 282 | torch.save(s, 'data/resnet152.pth') 283 | 284 | 285 | -------------------------------------------------------------------------------- /models/victim/imagenet/resnet.py: -------------------------------------------------------------------------------- 1 | import torch.nn as nn 2 | import torch.nn.functional as F 3 | import math 4 | import random 5 | import torch.utils.model_zoo as model_zoo 6 | from .utils import DropoutConv2d 7 | 8 | 9 | __all__ = ['ResNet', 'resnet18', 'resnet34', 'resnet50', 'resnet101', 10 | 'resnet152'] 11 | 12 | 13 | model_urls = { 14 | 'resnet18': 'https://download.pytorch.org/models/resnet18-5c106cde.pth', 15 | 'resnet34': 'https://download.pytorch.org/models/resnet34-333f7ec4.pth', 16 | 'resnet50': 'https://download.pytorch.org/models/resnet50-19c8e357.pth', 17 | 'resnet101': 'https://download.pytorch.org/models/resnet101-5d3b4d8f.pth', 18 | 'resnet152': 'https://download.pytorch.org/models/resnet152-b121ed2d.pth', 19 | } 20 | 21 | 22 | def conv3x3(in_planes, out_planes, stride=1): 23 | """3x3 convolution with padding""" 24 | return nn.Conv2d(in_planes, out_planes, kernel_size=3, stride=stride, 25 | padding=1, bias=False) 26 | 27 | 28 | class BasicBlock(nn.Module): 29 | expansion = 1 30 | 31 | def __init__(self, inplanes, planes, stride=1, downsample=None): 32 | super(BasicBlock, self).__init__() 33 | self.conv1 = conv3x3(inplanes, planes, stride) 34 | self.bn1 = nn.BatchNorm2d(planes) 35 | self.relu = nn.ReLU(inplace=True) 36 | self.conv2 = conv3x3(planes, planes) 37 | self.bn2 = nn.BatchNorm2d(planes) 38 | self.downsample = downsample 39 | self.stride = stride 40 | 41 | # no drop 42 | self.drop = 0 43 | 44 | def forward(self, x): 45 | if (self.downsample is None) and (random.random() < self.drop): 46 | return x 47 | else: 48 | residual = x 49 | 50 | out = self.conv1(x) 51 | out = self.bn1(out) 52 | out = self.relu(out) 53 | 54 | out = self.conv2(out) 55 | out = self.bn2(out) 56 | 57 | if self.downsample is not None: 58 | residual = self.downsample(x) 59 | 60 | out += residual 61 | out = self.relu(out) 62 | 63 | return out 64 | 65 | 66 | class Bottleneck(nn.Module): 67 | expansion = 4 68 | 69 | def __init__(self, inplanes, planes, stride=1, downsample=None): 70 | super(Bottleneck, self).__init__() 71 | self.conv1 = nn.Conv2d(inplanes, planes, kernel_size=1, bias=False) 72 | self.bn1 = nn.BatchNorm2d(planes) 73 | self.conv2 = nn.Conv2d(planes, planes, kernel_size=3, stride=stride, 74 | padding=1, bias=False) 75 | self.bn2 = nn.BatchNorm2d(planes) 76 | self.conv3 = nn.Conv2d(planes, planes * 4, kernel_size=1, bias=False) 77 | self.bn3 = nn.BatchNorm2d(planes * 4) 78 | self.relu = nn.ReLU(inplace=True) 79 | self.downsample = downsample 80 | self.stride = stride 81 | 82 | # no drop 83 | self.drop = 0 84 | 85 | def forward(self, x): 86 | if (self.downsample is None) and (random.random() < self.drop): 87 | return x 88 | else: 89 | residual = x 90 | 91 | out = self.conv1(x) 92 | out = self.bn1(out) 93 | out = self.relu(out) 94 | 95 | out = self.conv2(out) 96 | out = self.bn2(out) 97 | out = self.relu(out) 98 | 99 | out = self.conv3(out) 100 | out = self.bn3(out) 101 | 102 | if self.downsample is not None: 103 | residual = self.downsample(x) 104 | 105 | out += residual 106 | out = self.relu(out) 107 | 108 | return out 109 | 110 | 111 | class ResNet(nn.Module): 112 | 113 | def __init__(self, block, layers, num_classes=1000): 114 | self.inplanes = 64 115 | super(ResNet, self).__init__() 116 | self.conv1 = nn.Conv2d(3, 64, kernel_size=7, stride=2, padding=3, 117 | bias=False) 118 | self.bn1 = nn.BatchNorm2d(64) 119 | self.relu = nn.ReLU(inplace=True) 120 | self.maxpool = nn.MaxPool2d(kernel_size=3, stride=2, padding=1) 121 | self.layer1 = self._make_layer(block, 64, layers[0]) 122 | self.layer2 = self._make_layer(block, 128, layers[1], stride=2) 123 | self.layer3 = self._make_layer(block, 256, layers[2], stride=2) 124 | self.layer4 = self._make_layer(block, 512, layers[3], stride=2) 125 | self.avgpool = nn.AvgPool2d(7, stride=1) 126 | self.fc = nn.Linear(512 * block.expansion, num_classes) 127 | 128 | for m in self.modules(): 129 | if isinstance(m, nn.Conv2d): 130 | n = m.kernel_size[0] * m.kernel_size[1] * m.out_channels 131 | m.weight.data.normal_(0, math.sqrt(2. / n)) 132 | elif isinstance(m, nn.BatchNorm2d): 133 | m.weight.data.fill_(1) 134 | m.bias.data.zero_() 135 | 136 | # no drop 137 | self.drop = 0 138 | 139 | def _make_layer(self, block, planes, blocks, stride=1): 140 | downsample = None 141 | if stride != 1 or self.inplanes != planes * block.expansion: 142 | downsample = nn.Sequential( 143 | nn.Conv2d(self.inplanes, planes * block.expansion, 144 | kernel_size=1, stride=stride, bias=False), 145 | nn.BatchNorm2d(planes * block.expansion), 146 | ) 147 | 148 | layers = [] 149 | layers.append(block(self.inplanes, planes, stride, downsample)) 150 | self.inplanes = planes * block.expansion 151 | for i in range(1, blocks): 152 | layers.append(block(self.inplanes, planes)) 153 | 154 | return nn.Sequential(*layers) 155 | 156 | def forward(self, x): 157 | for m in self.modules(): 158 | if isinstance(m, (DropoutConv2d, BasicBlock, Bottleneck)): 159 | m.drop = self.drop 160 | 161 | x = self.conv1(x) 162 | x = self.bn1(x) 163 | x = self.relu(x) 164 | x = self.maxpool(x) 165 | 166 | x = self.layer1(x) 167 | x = self.layer2(x) 168 | x = self.layer3(x) 169 | x = self.layer4(x) 170 | 171 | x = self.avgpool(x) 172 | x = x.view(x.size(0), -1) 173 | x = F.dropout(x, p=self.drop, training=True) # force dropout 174 | x = self.fc(x) 175 | 176 | return x 177 | 178 | 179 | def resnet18(pretrained=False, **kwargs): 180 | """Constructs a ResNet-18 model. 181 | 182 | Args: 183 | pretrained (bool): If True, returns a model pre-trained on ImageNet 184 | """ 185 | model = ResNet(BasicBlock, [2, 2, 2, 2], **kwargs) 186 | if pretrained: 187 | model.load_state_dict(model_zoo.load_url(model_urls['resnet18'])) 188 | return model 189 | 190 | 191 | def resnet34(pretrained=False, **kwargs): 192 | """Constructs a ResNet-34 model. 193 | 194 | Args: 195 | pretrained (bool): If True, returns a model pre-trained on ImageNet 196 | """ 197 | model = ResNet(BasicBlock, [3, 4, 6, 3], **kwargs) 198 | if pretrained: 199 | model.load_state_dict(model_zoo.load_url(model_urls['resnet34'])) 200 | return model 201 | 202 | 203 | def resnet50(pretrained=False, **kwargs): 204 | """Constructs a ResNet-50 model. 205 | 206 | Args: 207 | pretrained (bool): If True, returns a model pre-trained on ImageNet 208 | """ 209 | model = ResNet(Bottleneck, [3, 4, 6, 3], **kwargs) 210 | if pretrained: 211 | model.load_state_dict(model_zoo.load_url(model_urls['resnet50'])) 212 | return model 213 | 214 | 215 | def resnet101(pretrained=False, **kwargs): 216 | """Constructs a ResNet-101 model. 217 | 218 | Args: 219 | pretrained (bool): If True, returns a model pre-trained on ImageNet 220 | """ 221 | model = ResNet(Bottleneck, [3, 4, 23, 3], **kwargs) 222 | if pretrained: 223 | model.load_state_dict(model_zoo.load_url(model_urls['resnet101'])) 224 | return model 225 | 226 | 227 | def resnet152(pretrained=False, **kwargs): 228 | """Constructs a ResNet-152 model. 229 | 230 | Args: 231 | pretrained (bool): If True, returns a model pre-trained on ImageNet 232 | """ 233 | model = ResNet(Bottleneck, [3, 8, 36, 3], **kwargs) 234 | if pretrained: 235 | model.load_state_dict(model_zoo.load_url(model_urls['resnet152'])) 236 | return model 237 | -------------------------------------------------------------------------------- /models/victim/imagenet/resnext.py: -------------------------------------------------------------------------------- 1 | from __future__ import print_function, division, absolute_import 2 | import torch.nn as nn 3 | import torch.utils.model_zoo as model_zoo 4 | from models.victim.imagenet import resnext101_32x4d_features 5 | from models.victim.imagenet import resnext101_64x4d_features 6 | 7 | __all__ = ['ResNeXt101_32x4d', 'resnext101_32x4d', 8 | 'ResNeXt101_64x4d', 'resnext101_64x4d'] 9 | 10 | pretrained_settings = { 11 | 'resnext101_32x4d': { 12 | 'imagenet': { 13 | 'url': 'http://data.lip6.fr/cadene/pretrainedmodels/resnext101_32x4d-29e315fa.pth', 14 | 'input_space': 'RGB', 15 | 'input_size': [3, 224, 224], 16 | 'input_range': [0, 1], 17 | 'mean': [0.485, 0.456, 0.406], 18 | 'std': [0.229, 0.224, 0.225], 19 | 'num_classes': 1000 20 | } 21 | }, 22 | 'resnext101_64x4d': { 23 | 'imagenet': { 24 | 'url': 'http://data.lip6.fr/cadene/pretrainedmodels/resnext101_64x4d-e77a0586.pth', 25 | 'input_space': 'RGB', 26 | 'input_size': [3, 224, 224], 27 | 'input_range': [0, 1], 28 | 'mean': [0.485, 0.456, 0.406], 29 | 'std': [0.229, 0.224, 0.225], 30 | 'num_classes': 1000 31 | } 32 | } 33 | } 34 | 35 | class ResNeXt101_32x4d(nn.Module): 36 | 37 | def __init__(self, num_classes=1000): 38 | super(ResNeXt101_32x4d, self).__init__() 39 | self.num_classes = num_classes 40 | self.features = resnext101_32x4d_features 41 | self.avg_pool = nn.AvgPool2d((7, 7), (1, 1)) 42 | self.last_linear = nn.Linear(2048, num_classes) 43 | 44 | def logits(self, input): 45 | x = self.avg_pool(input) 46 | x = x.view(x.size(0), -1) 47 | x = self.last_linear(x) 48 | return x 49 | 50 | def forward(self, input): 51 | x = self.features(input) 52 | x = self.logits(x) 53 | return x 54 | 55 | 56 | class ResNeXt101_64x4d(nn.Module): 57 | 58 | def __init__(self, num_classes=1000): 59 | super(ResNeXt101_64x4d, self).__init__() 60 | self.num_classes = num_classes 61 | self.features = resnext101_64x4d_features 62 | self.avg_pool = nn.AvgPool2d((7, 7), (1, 1)) 63 | self.last_linear = nn.Linear(2048, num_classes) 64 | 65 | def logits(self, input): 66 | x = self.avg_pool(input) 67 | x = x.view(x.size(0), -1) 68 | x = self.last_linear(x) 69 | return x 70 | 71 | def forward(self, input): 72 | x = self.features(input) 73 | x = self.logits(x) 74 | return x 75 | 76 | 77 | def resnext101_32x4d(num_classes=1000, pretrained='imagenet'): 78 | model = ResNeXt101_32x4d(num_classes=num_classes) 79 | if pretrained is not None: 80 | settings = pretrained_settings['resnext101_32x4d'][pretrained] 81 | assert num_classes == settings['num_classes'], \ 82 | "num_classes should be {}, but is {}".format(settings['num_classes'], num_classes) 83 | model.load_state_dict(model_zoo.load_url(settings['url'])) 84 | model.input_space = settings['input_space'] 85 | model.input_size = settings['input_size'] 86 | model.input_range = settings['input_range'] 87 | model.mean = settings['mean'] 88 | model.std = settings['std'] 89 | return model 90 | 91 | def resnext101_64x4d(num_classes=1000, pretrained='imagenet'): 92 | model = ResNeXt101_64x4d(num_classes=num_classes) 93 | if pretrained is not None: 94 | settings = pretrained_settings['resnext101_64x4d'][pretrained] 95 | assert num_classes == settings['num_classes'], \ 96 | "num_classes should be {}, but is {}".format(settings['num_classes'], num_classes) 97 | model.load_state_dict(model_zoo.load_url(settings['url'])) 98 | model.input_space = settings['input_space'] 99 | model.input_size = settings['input_size'] 100 | model.input_range = settings['input_range'] 101 | model.mean = settings['mean'] 102 | model.std = settings['std'] 103 | return model 104 | -------------------------------------------------------------------------------- /models/victim/imagenet/resnext_features/__init__.py: -------------------------------------------------------------------------------- 1 | from models.victim.imagenet.resnext_features.resnext101_32x4d_features import resnext101_32x4d_features 2 | -------------------------------------------------------------------------------- /models/victim/imagenet/utils.py: -------------------------------------------------------------------------------- 1 | import torch.nn as nn 2 | import torch.nn.functional as F 3 | 4 | 5 | class DropoutConv2d(nn.Conv2d): 6 | def __init__(self, in_channels, out_channels, kernel_size, stride=1, 7 | padding=0, dilation=1, groups=1, bias=True, drop=0): 8 | super(DropoutConv2d, self).__init__( 9 | in_channels, out_channels, kernel_size, stride, padding, dilation, groups, bias) 10 | self.drop = drop 11 | 12 | def forward(self, x): 13 | x = super(DropoutConv2d, self).forward(x) 14 | x = F.dropout(x, p=self.drop, training=True) 15 | return x 16 | -------------------------------------------------------------------------------- /models/victim/imagenet/vgg.py: -------------------------------------------------------------------------------- 1 | import torch.nn as nn 2 | import torch.nn.functional as F 3 | import torch.utils.model_zoo as model_zoo 4 | from .utils import DropoutConv2d 5 | import math 6 | 7 | 8 | __all__ = [ 9 | 'VGG', 'vgg11', 'vgg11_bn', 'vgg13', 'vgg13_bn', 'vgg16', 'vgg16_bn', 10 | 'vgg19_bn', 'vgg19', 11 | ] 12 | 13 | 14 | model_urls = { 15 | 'vgg11': 'https://download.pytorch.org/models/vgg11-bbd30ac9.pth', 16 | 'vgg13': 'https://download.pytorch.org/models/vgg13-c768596a.pth', 17 | 'vgg16': 'https://download.pytorch.org/models/vgg16-397923af.pth', 18 | 'vgg19': 'https://download.pytorch.org/models/vgg19-dcbb9e9d.pth', 19 | 'vgg11_bn': 'https://download.pytorch.org/models/vgg11_bn-6002323d.pth', 20 | 'vgg13_bn': 'https://download.pytorch.org/models/vgg13_bn-abd245e5.pth', 21 | 'vgg16_bn': 'https://download.pytorch.org/models/vgg16_bn-6c64b313.pth', 22 | 'vgg19_bn': 'https://download.pytorch.org/models/vgg19_bn-c79401a0.pth', 23 | } 24 | 25 | 26 | class VGG(nn.Module): 27 | 28 | def __init__(self, features, num_classes=1000, init_weights=True): 29 | super(VGG, self).__init__() 30 | self.features = features 31 | self.classifier = nn.Sequential( 32 | nn.Linear(512 * 7 * 7, 4096), 33 | nn.ReLU(True), 34 | nn.Dropout(), 35 | nn.Linear(4096, 4096), 36 | nn.ReLU(True), 37 | nn.Dropout(), 38 | nn.Linear(4096, num_classes), 39 | ) 40 | if init_weights: 41 | self._initialize_weights() 42 | 43 | # no dropout 44 | self.drop = 0 45 | 46 | def forward(self, x): 47 | for m in self.modules(): 48 | if isinstance(m, DropoutConv2d): 49 | m.drop = self.drop 50 | 51 | x = self.features(x) 52 | x = x.view(x.size(0), -1) 53 | x = F.dropout(x, p=self.drop, training=True) # force dropout 54 | x = self.classifier(x) 55 | return x 56 | 57 | def _initialize_weights(self): 58 | for m in self.modules(): 59 | if isinstance(m, DropoutConv2d): 60 | n = m.kernel_size[0] * m.kernel_size[1] * m.out_channels 61 | m.weight.data.normal_(0, math.sqrt(2. / n)) 62 | if m.bias is not None: 63 | m.bias.data.zero_() 64 | elif isinstance(m, nn.BatchNorm2d): 65 | m.weight.data.fill_(1) 66 | m.bias.data.zero_() 67 | elif isinstance(m, nn.Linear): 68 | m.weight.data.normal_(0, 0.01) 69 | m.bias.data.zero_() 70 | 71 | 72 | def make_layers(cfg, batch_norm=False): 73 | layers = [] 74 | in_channels = 3 75 | for v in cfg: 76 | if v == 'M': 77 | layers += [nn.MaxPool2d(kernel_size=2, stride=2)] 78 | else: 79 | conv2d = DropoutConv2d(in_channels, v, kernel_size=3, padding=1) 80 | if batch_norm: 81 | layers += [conv2d, nn.BatchNorm2d(v), nn.ReLU(inplace=True)] 82 | else: 83 | layers += [conv2d, nn.ReLU(inplace=True)] 84 | in_channels = v 85 | return nn.Sequential(*layers) 86 | 87 | 88 | cfg = { 89 | 'A': [64, 'M', 128, 'M', 256, 256, 'M', 512, 512, 'M', 512, 512, 'M'], 90 | 'B': [64, 64, 'M', 128, 128, 'M', 256, 256, 'M', 512, 512, 'M', 512, 512, 'M'], 91 | 'D': [64, 64, 'M', 128, 128, 'M', 256, 256, 256, 'M', 512, 512, 512, 'M', 512, 512, 512, 'M'], 92 | 'E': [64, 64, 'M', 128, 128, 'M', 256, 256, 256, 256, 'M', 512, 512, 512, 512, 'M', 512, 512, 512, 512, 'M'], 93 | } 94 | 95 | 96 | def vgg11(pretrained=False, **kwargs): 97 | """VGG 11-layer model (configuration "A") 98 | 99 | Args: 100 | pretrained (bool): If True, returns a model pre-trained on ImageNet 101 | """ 102 | if pretrained: 103 | kwargs['init_weights'] = False 104 | model = VGG(make_layers(cfg['A']), **kwargs) 105 | if pretrained: 106 | model.load_state_dict(model_zoo.load_url(model_urls['vgg11'])) 107 | return model 108 | 109 | 110 | def vgg11_bn(pretrained=False, **kwargs): 111 | """VGG 11-layer model (configuration "A") with batch normalization 112 | 113 | Args: 114 | pretrained (bool): If True, returns a model pre-trained on ImageNet 115 | """ 116 | if pretrained: 117 | kwargs['init_weights'] = False 118 | model = VGG(make_layers(cfg['A'], batch_norm=True), **kwargs) 119 | if pretrained: 120 | model.load_state_dict(model_zoo.load_url(model_urls['vgg11_bn'])) 121 | return model 122 | 123 | 124 | def vgg13(pretrained=False, **kwargs): 125 | """VGG 13-layer model (configuration "B") 126 | 127 | Args: 128 | pretrained (bool): If True, returns a model pre-trained on ImageNet 129 | """ 130 | if pretrained: 131 | kwargs['init_weights'] = False 132 | model = VGG(make_layers(cfg['B']), **kwargs) 133 | if pretrained: 134 | model.load_state_dict(model_zoo.load_url(model_urls['vgg13'])) 135 | return model 136 | 137 | 138 | def vgg13_bn(pretrained=False, **kwargs): 139 | """VGG 13-layer model (configuration "B") with batch normalization 140 | 141 | Args: 142 | pretrained (bool): If True, returns a model pre-trained on ImageNet 143 | """ 144 | if pretrained: 145 | kwargs['init_weights'] = False 146 | model = VGG(make_layers(cfg['B'], batch_norm=True), **kwargs) 147 | if pretrained: 148 | model.load_state_dict(model_zoo.load_url(model_urls['vgg13_bn'])) 149 | return model 150 | 151 | 152 | def vgg16(pretrained=False, **kwargs): 153 | """VGG 16-layer model (configuration "D") 154 | 155 | Args: 156 | pretrained (bool): If True, returns a model pre-trained on ImageNet 157 | """ 158 | if pretrained: 159 | kwargs['init_weights'] = False 160 | model = VGG(make_layers(cfg['D']), **kwargs) 161 | if pretrained: 162 | model.load_state_dict(model_zoo.load_url(model_urls['vgg16'])) 163 | return model 164 | 165 | 166 | def vgg16_bn(pretrained=False, **kwargs): 167 | """VGG 16-layer model (configuration "D") with batch normalization 168 | 169 | Args: 170 | pretrained (bool): If True, returns a model pre-trained on ImageNet 171 | """ 172 | if pretrained: 173 | kwargs['init_weights'] = False 174 | model = VGG(make_layers(cfg['D'], batch_norm=True), **kwargs) 175 | if pretrained: 176 | model.load_state_dict(model_zoo.load_url(model_urls['vgg16_bn'])) 177 | return model 178 | 179 | 180 | def vgg19(pretrained=False, **kwargs): 181 | """VGG 19-layer model (configuration "E") 182 | 183 | Args: 184 | pretrained (bool): If True, returns a model pre-trained on ImageNet 185 | """ 186 | if pretrained: 187 | kwargs['init_weights'] = False 188 | model = VGG(make_layers(cfg['E']), **kwargs) 189 | if pretrained: 190 | model.load_state_dict(model_zoo.load_url(model_urls['vgg19'])) 191 | return model 192 | 193 | 194 | def vgg19_bn(pretrained=False, **kwargs): 195 | """VGG 19-layer model (configuration 'E') with batch normalization 196 | 197 | Args: 198 | pretrained (bool): If True, returns a model pre-trained on ImageNet 199 | """ 200 | if pretrained: 201 | kwargs['init_weights'] = False 202 | model = VGG(make_layers(cfg['E'], batch_norm=True), **kwargs) 203 | if pretrained: 204 | model.load_state_dict(model_zoo.load_url(model_urls['vgg19_bn'])) 205 | return model 206 | -------------------------------------------------------------------------------- /models/victim/imagenet/vggm.py: -------------------------------------------------------------------------------- 1 | from __future__ import print_function, division, absolute_import 2 | import torch 3 | import torch.nn as nn 4 | from torch.autograd import Variable 5 | #from torch.legacy import nn as nnl 6 | import torch.utils.model_zoo as model_zoo 7 | 8 | __all__ = ['vggm'] 9 | 10 | pretrained_settings = { 11 | 'vggm': { 12 | 'imagenet': { 13 | 'url': 'http://data.lip6.fr/cadene/pretrainedmodels/vggm-786f2434.pth', 14 | 'input_space': 'BGR', 15 | 'input_size': [3, 221, 221], 16 | 'input_range': [0, 255], 17 | 'mean': [123.68, 116.779, 103.939], 18 | 'std': [1, 1, 1], 19 | 'num_classes': 1000 20 | } 21 | } 22 | } 23 | 24 | class SpatialCrossMapLRN(nn.Module): 25 | def __init__(self, local_size=1, alpha=1.0, beta=0.75, k=1, ACROSS_CHANNELS=True): 26 | super(SpatialCrossMapLRN, self).__init__() 27 | self.ACROSS_CHANNELS = ACROSS_CHANNELS 28 | if ACROSS_CHANNELS: 29 | self.average=nn.AvgPool3d(kernel_size=(local_size, 1, 1), 30 | stride=1, 31 | padding=(int((local_size-1.0)/2), 0, 0)) 32 | else: 33 | self.average=nn.AvgPool2d(kernel_size=local_size, 34 | stride=1, 35 | padding=int((local_size-1.0)/2)) 36 | self.alpha = alpha 37 | self.beta = beta 38 | self.k = k 39 | 40 | def forward(self, x): 41 | if self.ACROSS_CHANNELS: 42 | div = x.pow(2).unsqueeze(1) 43 | div = self.average(div).squeeze(1) 44 | div = div.mul(self.alpha).add(self.k).pow(self.beta) 45 | else: 46 | div = x.pow(2) 47 | div = self.average(div) 48 | div = div.mul(self.alpha).add(self.k).pow(self.beta) 49 | x = x.div(div) 50 | return x 51 | 52 | class LambdaBase(nn.Sequential): 53 | def __init__(self, fn, *args): 54 | super(LambdaBase, self).__init__(*args) 55 | self.lambda_func = fn 56 | 57 | def forward_prepare(self, input): 58 | output = [] 59 | for module in self._modules.values(): 60 | output.append(module(input)) 61 | return output if output else input 62 | 63 | class Lambda(LambdaBase): 64 | def forward(self, input): 65 | return self.lambda_func(self.forward_prepare(input)) 66 | 67 | class VGGM(nn.Module): 68 | 69 | def __init__(self, num_classes=1000): 70 | super(VGGM, self).__init__() 71 | self.num_classes = num_classes 72 | self.features = nn.Sequential( 73 | nn.Conv2d(3,96,(7, 7),(2, 2)), 74 | nn.ReLU(), 75 | SpatialCrossMapLRN(5, 0.0005, 0.75, 2), 76 | nn.MaxPool2d((3, 3),(2, 2),(0, 0),ceil_mode=True), 77 | nn.Conv2d(96,256,(5, 5),(2, 2),(1, 1)), 78 | nn.ReLU(), 79 | SpatialCrossMapLRN(5, 0.0005, 0.75, 2), 80 | nn.MaxPool2d((3, 3),(2, 2),(0, 0),ceil_mode=True), 81 | nn.Conv2d(256,512,(3, 3),(1, 1),(1, 1)), 82 | nn.ReLU(), 83 | nn.Conv2d(512,512,(3, 3),(1, 1),(1, 1)), 84 | nn.ReLU(), 85 | nn.Conv2d(512,512,(3, 3),(1, 1),(1, 1)), 86 | nn.ReLU(), 87 | nn.MaxPool2d((3, 3),(2, 2),(0, 0),ceil_mode=True) 88 | ) 89 | self.classif = nn.Sequential( 90 | nn.Linear(18432,4096), 91 | nn.ReLU(), 92 | nn.Dropout(0.5), 93 | nn.Linear(4096,4096), 94 | nn.ReLU(), 95 | nn.Dropout(0.5), 96 | nn.Linear(4096,num_classes) 97 | ) 98 | 99 | def forward(self, x): 100 | x = self.features(x) 101 | x = x.view(x.size(0), -1) 102 | x = self.classif(x) 103 | return x 104 | 105 | def vggm(num_classes=1000, pretrained='imagenet'): 106 | if pretrained: 107 | settings = pretrained_settings['vggm'][pretrained] 108 | assert num_classes == settings['num_classes'], \ 109 | "num_classes should be {}, but is {}".format(settings['num_classes'], num_classes) 110 | 111 | model = VGGM(num_classes=1000) 112 | model.load_state_dict(model_zoo.load_url(settings['url'])) 113 | 114 | model.input_space = settings['input_space'] 115 | model.input_size = settings['input_size'] 116 | model.input_range = settings['input_range'] 117 | model.mean = settings['mean'] 118 | model.std = settings['std'] 119 | else: 120 | model = VGGM(num_classes=num_classes) 121 | return model -------------------------------------------------------------------------------- /models/victim/imagenet/wideresnet.py: -------------------------------------------------------------------------------- 1 | from __future__ import print_function, division, absolute_import 2 | import os 3 | from os.path import expanduser 4 | import hickle as hkl 5 | import torch 6 | import torch.nn.functional as F 7 | from torch.autograd import Variable 8 | 9 | __all__ = ['wideresnet50'] 10 | 11 | model_urls = { 12 | 'wideresnet152': 'https://s3.amazonaws.com/pytorch/h5models/wide-resnet-50-2-export.hkl' 13 | } 14 | 15 | def define_model(params): 16 | def conv2d(input, params, base, stride=1, pad=0): 17 | return F.conv2d(input, params[base + '.weight'], 18 | params[base + '.bias'], stride, pad) 19 | 20 | def group(input, params, base, stride, n): 21 | o = input 22 | for i in range(0,n): 23 | b_base = ('%s.block%d.conv') % (base, i) 24 | x = o 25 | o = conv2d(x, params, b_base + '0') 26 | o = F.relu(o) 27 | o = conv2d(o, params, b_base + '1', stride=i==0 and stride or 1, pad=1) 28 | o = F.relu(o) 29 | o = conv2d(o, params, b_base + '2') 30 | if i == 0: 31 | o += conv2d(x, params, b_base + '_dim', stride=stride) 32 | else: 33 | o += x 34 | o = F.relu(o) 35 | return o 36 | 37 | # determine network size by parameters 38 | blocks = [sum([re.match('group%d.block\d+.conv0.weight'%j, k) is not None 39 | for k in params.keys()]) for j in range(4)] 40 | 41 | def f(input, params, pooling_classif=True): 42 | o = F.conv2d(input, params['conv0.weight'], params['conv0.bias'], 2, 3) 43 | o = F.relu(o) 44 | o = F.max_pool2d(o, 3, 2, 1) 45 | o_g0 = group(o, params, 'group0', 1, blocks[0]) 46 | o_g1 = group(o_g0, params, 'group1', 2, blocks[1]) 47 | o_g2 = group(o_g1, params, 'group2', 2, blocks[2]) 48 | o_g3 = group(o_g2, params, 'group3', 2, blocks[3]) 49 | if pooling_classif: 50 | o = F.avg_pool2d(o_g3, 7, 1, 0) 51 | o = o.view(o.size(0), -1) 52 | o = F.linear(o, params['fc.weight'], params['fc.bias']) 53 | return o 54 | 55 | return f 56 | 57 | 58 | class WideResNet(nn.Module): 59 | 60 | def __init__(self, pooling): 61 | super(WideResNet, self).__init__() 62 | self.pooling = pooling 63 | self.params = params 64 | 65 | def forward(self, x): 66 | x = f(x, self.params, self.pooling) 67 | return x 68 | 69 | 70 | def wideresnet50(pooling): 71 | dir_models = os.path.join(expanduser("~"), '.torch/wideresnet') 72 | path_hkl = os.path.join(dir_models, 'wideresnet50.hkl') 73 | if os.path.isfile(path_hkl): 74 | params = hkl.load(path_hkl) 75 | # convert numpy arrays to torch Variables 76 | for k,v in sorted(params.items()): 77 | print(k, v.shape) 78 | params[k] = Variable(torch.from_numpy(v), requires_grad=True) 79 | else: 80 | os.system('mkdir -p ' + dir_models) 81 | os.system('wget {} -O {}'.format(model_urls['wideresnet50'], path_hkl)) 82 | f = define_model(params) 83 | model = WideResNet(pooling) 84 | return model 85 | 86 | 87 | -------------------------------------------------------------------------------- /models/victim/imagenet/xception.py: -------------------------------------------------------------------------------- 1 | """ 2 | Ported to pytorch thanks to [tstandley](https://github.com/tstandley/Xception-PyTorch) 3 | 4 | @author: tstandley 5 | Adapted by cadene 6 | 7 | Creates an Xception Model as defined in: 8 | 9 | Francois Chollet 10 | Xception: Deep Learning with Depthwise Separable Convolutions 11 | https://arxiv.org/pdf/1610.02357.pdf 12 | 13 | This weights ported from the Keras implementation. Achieves the following performance on the validation set: 14 | 15 | Loss:0.9173 Prec@1:78.892 Prec@5:94.292 16 | 17 | REMEMBER to set your image size to 3x299x299 for both test and validation 18 | 19 | normalize = transforms.Normalize(mean=[0.5, 0.5, 0.5], 20 | std=[0.5, 0.5, 0.5]) 21 | 22 | The resize parameter of the validation transform should be 333, and make sure to center crop at 299x299 23 | """ 24 | from __future__ import print_function, division, absolute_import 25 | import math 26 | import torch 27 | import torch.nn as nn 28 | import torch.nn.functional as F 29 | import torch.utils.model_zoo as model_zoo 30 | from torch.nn import init 31 | 32 | __all__ = ['xception'] 33 | 34 | pretrained_settings = { 35 | 'xception': { 36 | 'imagenet': { 37 | 'url': 'http://data.lip6.fr/cadene/pretrainedmodels/xception-43020ad28.pth', 38 | 'input_space': 'RGB', 39 | 'input_size': [3, 299, 299], 40 | 'input_range': [0, 1], 41 | 'mean': [0.5, 0.5, 0.5], 42 | 'std': [0.5, 0.5, 0.5], 43 | 'num_classes': 1000, 44 | 'scale': 0.8975 # The resize parameter of the validation transform should be 333, and make sure to center crop at 299x299 45 | } 46 | } 47 | } 48 | 49 | 50 | class SeparableConv2d(nn.Module): 51 | def __init__(self,in_channels,out_channels,kernel_size=1,stride=1,padding=0,dilation=1,bias=False): 52 | super(SeparableConv2d,self).__init__() 53 | 54 | self.conv1 = nn.Conv2d(in_channels,in_channels,kernel_size,stride,padding,dilation,groups=in_channels,bias=bias) 55 | self.pointwise = nn.Conv2d(in_channels,out_channels,1,1,0,1,1,bias=bias) 56 | 57 | def forward(self,x): 58 | x = self.conv1(x) 59 | x = self.pointwise(x) 60 | return x 61 | 62 | 63 | class Block(nn.Module): 64 | def __init__(self,in_filters,out_filters,reps,strides=1,start_with_relu=True,grow_first=True): 65 | super(Block, self).__init__() 66 | 67 | if out_filters != in_filters or strides!=1: 68 | self.skip = nn.Conv2d(in_filters,out_filters,1,stride=strides, bias=False) 69 | self.skipbn = nn.BatchNorm2d(out_filters) 70 | else: 71 | self.skip=None 72 | 73 | rep=[] 74 | 75 | filters=in_filters 76 | if grow_first: 77 | rep.append(nn.ReLU(inplace=True)) 78 | rep.append(SeparableConv2d(in_filters,out_filters,3,stride=1,padding=1,bias=False)) 79 | rep.append(nn.BatchNorm2d(out_filters)) 80 | filters = out_filters 81 | 82 | for i in range(reps-1): 83 | rep.append(nn.ReLU(inplace=True)) 84 | rep.append(SeparableConv2d(filters,filters,3,stride=1,padding=1,bias=False)) 85 | rep.append(nn.BatchNorm2d(filters)) 86 | 87 | if not grow_first: 88 | rep.append(nn.ReLU(inplace=True)) 89 | rep.append(SeparableConv2d(in_filters,out_filters,3,stride=1,padding=1,bias=False)) 90 | rep.append(nn.BatchNorm2d(out_filters)) 91 | 92 | if not start_with_relu: 93 | rep = rep[1:] 94 | else: 95 | rep[0] = nn.ReLU(inplace=False) 96 | 97 | if strides != 1: 98 | rep.append(nn.MaxPool2d(3,strides,1)) 99 | self.rep = nn.Sequential(*rep) 100 | 101 | def forward(self,inp): 102 | x = self.rep(inp) 103 | 104 | if self.skip is not None: 105 | skip = self.skip(inp) 106 | skip = self.skipbn(skip) 107 | else: 108 | skip = inp 109 | 110 | x+=skip 111 | return x 112 | 113 | 114 | class Xception(nn.Module): 115 | """ 116 | Xception optimized for the ImageNet dataset, as specified in 117 | https://arxiv.org/pdf/1610.02357.pdf 118 | """ 119 | def __init__(self, num_classes=1000): 120 | """ Constructor 121 | Args: 122 | num_classes: number of classes 123 | """ 124 | super(Xception, self).__init__() 125 | self.num_classes = num_classes 126 | 127 | self.conv1 = nn.Conv2d(3, 32, 3,2, 0, bias=False) 128 | self.bn1 = nn.BatchNorm2d(32) 129 | self.relu1 = nn.ReLU(inplace=True) 130 | 131 | self.conv2 = nn.Conv2d(32,64,3,bias=False) 132 | self.bn2 = nn.BatchNorm2d(64) 133 | self.relu2 = nn.ReLU(inplace=True) 134 | #do relu here 135 | 136 | self.block1=Block(64,128,2,2,start_with_relu=False,grow_first=True) 137 | self.block2=Block(128,256,2,2,start_with_relu=True,grow_first=True) 138 | self.block3=Block(256,728,2,2,start_with_relu=True,grow_first=True) 139 | 140 | self.block4=Block(728,728,3,1,start_with_relu=True,grow_first=True) 141 | self.block5=Block(728,728,3,1,start_with_relu=True,grow_first=True) 142 | self.block6=Block(728,728,3,1,start_with_relu=True,grow_first=True) 143 | self.block7=Block(728,728,3,1,start_with_relu=True,grow_first=True) 144 | 145 | self.block8=Block(728,728,3,1,start_with_relu=True,grow_first=True) 146 | self.block9=Block(728,728,3,1,start_with_relu=True,grow_first=True) 147 | self.block10=Block(728,728,3,1,start_with_relu=True,grow_first=True) 148 | self.block11=Block(728,728,3,1,start_with_relu=True,grow_first=True) 149 | 150 | self.block12=Block(728,1024,2,2,start_with_relu=True,grow_first=False) 151 | 152 | self.conv3 = SeparableConv2d(1024,1536,3,1,1) 153 | self.bn3 = nn.BatchNorm2d(1536) 154 | self.relu3 = nn.ReLU(inplace=True) 155 | 156 | #do relu here 157 | self.conv4 = SeparableConv2d(1536,2048,3,1,1) 158 | self.bn4 = nn.BatchNorm2d(2048) 159 | 160 | self.fc = nn.Linear(2048, num_classes) 161 | 162 | # #------- init weights -------- 163 | # for m in self.modules(): 164 | # if isinstance(m, nn.Conv2d): 165 | # n = m.kernel_size[0] * m.kernel_size[1] * m.out_channels 166 | # m.weight.data.normal_(0, math.sqrt(2. / n)) 167 | # elif isinstance(m, nn.BatchNorm2d): 168 | # m.weight.data.fill_(1) 169 | # m.bias.data.zero_() 170 | # #----------------------------- 171 | 172 | def features(self, input): 173 | x = self.conv1(input) 174 | x = self.bn1(x) 175 | x = self.relu1(x) 176 | 177 | x = self.conv2(x) 178 | x = self.bn2(x) 179 | x = self.relu2(x) 180 | 181 | x = self.block1(x) 182 | x = self.block2(x) 183 | x = self.block3(x) 184 | x = self.block4(x) 185 | x = self.block5(x) 186 | x = self.block6(x) 187 | x = self.block7(x) 188 | x = self.block8(x) 189 | x = self.block9(x) 190 | x = self.block10(x) 191 | x = self.block11(x) 192 | x = self.block12(x) 193 | 194 | x = self.conv3(x) 195 | x = self.bn3(x) 196 | x = self.relu3(x) 197 | 198 | x = self.conv4(x) 199 | x = self.bn4(x) 200 | return x 201 | 202 | def logits(self, features): 203 | x = nn.ReLU(inplace=True)(features) 204 | 205 | x = F.adaptive_avg_pool2d(x, (1, 1)) 206 | x = x.view(x.size(0), -1) 207 | x = self.last_linear(x) 208 | return x 209 | 210 | def forward(self, input): 211 | x = self.features(input) 212 | x = self.logits(x) 213 | return x 214 | 215 | 216 | def xception(num_classes=1000, pretrained='imagenet'): 217 | model = Xception(num_classes=num_classes) 218 | if pretrained: 219 | settings = pretrained_settings['xception'][pretrained] 220 | assert num_classes == settings['num_classes'], \ 221 | "num_classes should be {}, but is {}".format(settings['num_classes'], num_classes) 222 | 223 | model = Xception(num_classes=num_classes) 224 | model.load_state_dict(model_zoo.load_url(settings['url'])) 225 | 226 | model.input_space = settings['input_space'] 227 | model.input_size = settings['input_size'] 228 | model.input_range = settings['input_range'] 229 | model.mean = settings['mean'] 230 | model.std = settings['std'] 231 | 232 | # TODO: ugly 233 | model.last_linear = model.fc 234 | del model.fc 235 | return model 236 | -------------------------------------------------------------------------------- /models/victim/mnist/__init__.py: -------------------------------------------------------------------------------- 1 | from models.victim.mnist.lr import * 2 | from models.victim.mnist.mlp import * 3 | from models.victim.mnist.lenet import * 4 | from models.victim.mnist.carlinet import * 5 | -------------------------------------------------------------------------------- /models/victim/mnist/carlinet.py: -------------------------------------------------------------------------------- 1 | import torch.nn as nn 2 | import torch.nn.functional as F 3 | 4 | __all__ = ['carlinet'] 5 | 6 | 7 | class CarliNet(nn.Module): 8 | def __init__(self, num_classes=10): 9 | super(CarliNet, self).__init__() 10 | 11 | self.conv2d_1 = nn.Conv2d(1, 32, 3) 12 | self.conv2d_2 = nn.Conv2d(32, 32, 3) 13 | self.conv2d_3 = nn.Conv2d(32, 64, 3) 14 | self.conv2d_4 = nn.Conv2d(64, 64, 3) 15 | 16 | self.dense_1 = nn.Linear(1024, 200) 17 | self.dense_2 = nn.Linear(200, 200) 18 | self.dense_3 = nn.Linear(200, num_classes) 19 | 20 | def forward(self, x): 21 | x = self.conv2d_1(x) 22 | x = F.relu(x) 23 | x = self.conv2d_2(x) 24 | x = F.relu(x) 25 | x = F.max_pool2d(x, (2, 2)) 26 | 27 | x = self.conv2d_3(x) 28 | x = F.relu(x) 29 | x = self.conv2d_4(x) 30 | x = F.relu(x) 31 | x = F.max_pool2d(x, (2, 2)) 32 | 33 | # carlini's keras model data format: (N, H, W, C) 34 | # pytorch data format: (N, C, H, W) 35 | # we need to transpose pytorch data format into keras data format, to make sure the flatten operator 36 | # has the same effect. 37 | x = x.transpose(1, 2).transpose(2, 3).contiguous().view(x.shape[0], -1) 38 | x = self.dense_1(x) 39 | x = F.relu(x) 40 | x = self.dense_2(x) 41 | x = F.relu(x) 42 | x = self.dense_3(x) 43 | return x 44 | 45 | 46 | def carlinet(**kwargs): 47 | return CarliNet(**kwargs) 48 | -------------------------------------------------------------------------------- /models/victim/mnist/lenet.py: -------------------------------------------------------------------------------- 1 | import torch 2 | import torch.nn as nn 3 | import torch.nn.functional as F 4 | 5 | __all__ = ['lenet', 'lenet150'] 6 | 7 | 8 | class LeNet(nn.Module): 9 | def __init__(self, num_classes=10): 10 | super(LeNet, self).__init__() 11 | # 1 input image channel, 6 output channels, 5x5 square convolution 12 | # kernel 13 | self.conv1 = nn.Conv2d(1, 20, 5) 14 | self.conv2 = nn.Conv2d(20, 50, 5) 15 | # an affine operation: y = Wx + b 16 | self.fc1 = nn.Linear(50 * 4 * 4, 500) 17 | self.fc2 = nn.Linear(500, num_classes) 18 | 19 | for m in self.modules(): 20 | if isinstance(m, nn.Conv2d) or isinstance(m, nn.Linear): 21 | torch.nn.init.kaiming_normal_(m.weight) 22 | m.bias.data.zero_() 23 | 24 | def forward(self, x): 25 | # Max pooling over a (2, 2) window 26 | self.x = x 27 | self.conv1_out = self.conv1(self.x) 28 | self.pool1_out, self.pool1_ind = F.max_pool2d(self.conv1_out, (2, 2), return_indices=True) 29 | self.conv2_out = self.conv2(self.pool1_out) 30 | self.pool2_out, self.pool2_ind = F.max_pool2d(self.conv2_out, (2, 2), return_indices=True) 31 | self.flat_out = self.pool2_out.view(-1, self.num_flat_features(self.pool2_out)) 32 | self.fc1_out = self.fc1(self.flat_out) 33 | self.relu1_out = F.relu(self.fc1_out) 34 | self.fc2_out = self.fc2(self.relu1_out) 35 | 36 | return self.fc2_out 37 | 38 | @staticmethod 39 | def num_flat_features(x): 40 | size = x.size()[1:] # all dimensions except the batch dimension 41 | num_features = 1 42 | for s in size: 43 | num_features *= s 44 | return num_features 45 | 46 | 47 | class LeNet150(nn.Module): 48 | def __init__(self, num_classes=10): 49 | super(LeNet150, self).__init__() 50 | # kernel 51 | self.conv1 = nn.Conv2d(1, 32, 5) 52 | self.conv2 = nn.Conv2d(32, 64, 5) 53 | # an affine operation: y = Wx + b 54 | self.fc1 = nn.Linear(64 * 4 * 4, 150) 55 | self.fc2 = nn.Linear(150, num_classes) 56 | 57 | for m in self.modules(): 58 | if isinstance(m, nn.Conv2d) or isinstance(m, nn.Linear): 59 | torch.nn.init.kaiming_normal_(m.weight) 60 | m.bias.data.zero_() 61 | 62 | def forward(self, x): 63 | # Max pooling over a (2, 2) window 64 | self.x = x 65 | self.conv1_out = self.conv1(self.x) 66 | self.pool1_out, self.pool1_ind = F.max_pool2d(self.conv1_out, (2, 2), return_indices=True) 67 | self.conv2_out = self.conv2(self.pool1_out) 68 | self.pool2_out, self.pool2_ind = F.max_pool2d(self.conv2_out, (2, 2), return_indices=True) 69 | self.flat_out = self.pool2_out.view(-1, self.num_flat_features(self.pool2_out)) 70 | self.fc1_out = self.fc1(self.flat_out) 71 | self.relu1_out = F.relu(self.fc1_out) 72 | self.fc2_out = self.fc2(self.relu1_out) 73 | 74 | return self.fc2_out 75 | 76 | @staticmethod 77 | def num_flat_features(x): 78 | size = x.size()[1:] # all dimensions except the batch dimension 79 | num_features = 1 80 | for s in size: 81 | num_features *= s 82 | return num_features 83 | 84 | 85 | def lenet(**kwargs): 86 | return LeNet(**kwargs) 87 | 88 | 89 | def lenet150(**kwargs): 90 | return LeNet150(**kwargs) 91 | 92 | -------------------------------------------------------------------------------- /models/victim/mnist/lr.py: -------------------------------------------------------------------------------- 1 | import torch.nn as nn 2 | 3 | __all__ = ['lr'] 4 | 5 | 6 | class LR(nn.Module): 7 | def __init__(self, num_classes=10): 8 | super(LR, self).__init__() 9 | self.fc = nn.Linear(784, num_classes) 10 | 11 | def forward(self, x): 12 | x = x.view(x.shape[0], -1) 13 | x = self.fc(x) 14 | return x 15 | 16 | 17 | def lr(**kwargs): 18 | return LR(**kwargs) 19 | -------------------------------------------------------------------------------- /models/victim/mnist/mlp.py: -------------------------------------------------------------------------------- 1 | import torch 2 | import torch.nn as nn 3 | import torch.nn.functional as F 4 | 5 | __all__ = ['mlp'] 6 | 7 | 8 | class MLP(nn.Module): 9 | def __init__(self, num_classes=10): 10 | super(MLP, self).__init__() 11 | # an affine operation: y = Wx + b 12 | self.fc1 = nn.Linear(784, 500) 13 | self.fc2 = nn.Linear(500, 150) 14 | self.fc3 = nn.Linear(150, num_classes) 15 | 16 | for m in self.modules(): 17 | if isinstance(m, nn.Conv2d) or isinstance(m, nn.Linear): 18 | torch.nn.init.kaiming_normal_(m.weight) 19 | m.bias.data.zero_() 20 | 21 | def forward(self, x): 22 | self.x = x 23 | self.flat_out = self.x.view(-1, 784) 24 | self.fc1_out = self.fc1(self.flat_out) 25 | self.relu1_out = F.relu(self.fc1_out) 26 | self.fc2_out = self.fc2(self.relu1_out) 27 | self.relu2_out = F.relu(self.fc2_out) 28 | self.fc3_out = self.fc3(self.relu2_out) 29 | return self.fc3_out 30 | 31 | 32 | def mlp(**kwargs): 33 | return MLP(**kwargs) 34 | -------------------------------------------------------------------------------- /pda_cifar10_carlinet_untargeted_l2.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -x 3 | set -e 4 | set -u 5 | 6 | python3.5 policy_attack.py --attack-type untargeted --ce-lmbd 1.0 3e-3 1.5e-3 1.5e-3 --clip-grad 5 --cosine-epsilon-round 0 --current-mean-mult 1 --dataset cifar10 --decay 0 --delta-mult 1 --empty-coeff 0.5 --empty-normal-mean-norm 0.003 --epsilon-schema fixed --exclude-std --exp-dir output/policy-s2-final-cifar10-carlinet-untargeted-l2 --fix-num-eval --fixed-epsilon-mult 0.4 --gamma 50.0 --grad-method policy_distance --grad-size 0 --image-id-ref output/policy-smtrain-30epoch-500test-cifar10-carlinet-untargeted-l2/2020-08-02_22-32-16-CQUSS38n --init-boost --init-boost-stop 250 --init-boost-th 0.1 --init-empty-normal-mean --init-num-eval 25 --jump-count 1 --lr 0.0001 --lr-step-freq 0 --lr-step-mult 1.0 --max-baseline 1.0 --max-num-eval 10000 --max-query 25000 --max-sharp 0.5 --mean-reward --min-baseline 0.05 --min-epsilon-mult 0.01 --min-sharp 0.02 --minus-ca-sim 0.0 --momentum 0.0 --norm-type l2 --num-image 1000 --num-pre-tune-step 0 --optimizer Adam --part-id 0 --phase test --policy-arch vgg13_inv --policy-base-width 32 --policy-bilinear --policy-calibrate --policy-init-std 0.003 --policy-normalization-type none --policy-weight-fname output/policy-smtrain-30epoch-500test-cifar10-carlinet-untargeted-l2/2020-08-02_22-32-16-CQUSS38n/results/model_best.pth --pre-tune-lr 0.0001 --pre-tune-th 1.0 --rescale-factor 0.5 --save-grad-pct 0.0 --seed 1234 --std-lr-mult 1 --std-reward --sub-base --tan-jump --try-split 0.0 0.25 --victim-arch carlinet --victim-batch-size 50 7 | 8 | -------------------------------------------------------------------------------- /pda_cifar10_resnet50adv_untargeted_l2.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -x 3 | set -e 4 | set -u 5 | 6 | python3.5 policy_attack.py --attack-type untargeted --ce-lmbd 1.0 3e-3 1.5e-3 1.5e-3 --clip-grad 5 --cosine-epsilon-round 0 --current-mean-mult 1 --dataset cifar10 --decay 0 --delta-mult 1 --empty-coeff 0.5 --empty-normal-mean-norm 0.003 --epsilon-schema fixed --exclude-std --exp-dir output/policy-s2-final-cifar10-madry_resnet50_l2_1_0-untargeted-l2 --fix-num-eval --fixed-epsilon-mult 0.4 --gamma 50.0 --grad-method policy_distance --grad-size 0 --image-id-ref output/policy-smtrain-large-batch-cifar10-madry_resnet50_l2_1_0-untargeted-l2/2020-08-27_02-10-49-fTNXN7Mv --init-boost --init-boost-stop 250 --init-boost-th 0.1 --init-empty-normal-mean --init-num-eval 25 --jump-count 1 --lr 0.0001 --lr-step-freq 0 --lr-step-mult 1.0 --max-baseline 1.0 --max-num-eval 10000 --max-query 25000 --max-sharp 0.5 --mean-reward --min-baseline 0.05 --min-epsilon-mult 0.01 --min-sharp 0.02 --minus-ca-sim 0.0 --momentum 0.0 --norm-type l2 --num-image 1000 --num-pre-tune-step 0 --optimizer Adam --part-id 0 --phase test --policy-arch vgg13_inv --policy-base-width 32 --policy-bilinear --policy-calibrate --policy-init-std 0.003 --policy-normalization-type none --policy-weight-fname output/policy-smtrain-large-batch-cifar10-madry_resnet50_l2_1_0-untargeted-l2/2020-08-27_02-10-49-fTNXN7Mv/results/model_best.pth --pre-tune-lr 0.0001 --pre-tune-th 1.0 --rescale-factor 0.5 --save-grad-pct 0.0 --seed 1234 --std-lr-mult 1 --std-reward --sub-base --tan-jump --try-split 0.0 0.25 --victim-arch madry_resnet50_l2_1_0 --victim-batch-size 50 7 | 8 | -------------------------------------------------------------------------------- /pda_cifar10_wrn_untargeted_l2.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -x 3 | set -e 4 | set -u 5 | 6 | python3.5 policy_attack.py --attack-type untargeted --ce-lmbd 1.0 3e-3 1.5e-3 1.5e-3 --clip-grad 5 --cosine-epsilon-round 0 --current-mean-mult 1 --dataset cifar10 --decay 0 --delta-mult 1 --empty-coeff 0.5 --empty-normal-mean-norm 0.003 --epsilon-schema fixed --exclude-std --exp-dir output/policy-s2-final-cifar10-wrn_28_10_drop-untargeted-l2 --fix-num-eval --fixed-epsilon-mult 0.4 --gamma 50.0 --grad-method policy_distance --grad-size 0 --image-id-ref output/policy-smtrain-large-batch-cifar10-wrn_28_10_drop-untargeted-l2/2020-08-22_14-19-59-vUfOtLWE --init-boost --init-boost-stop 250 --init-boost-th 0.1 --init-empty-normal-mean --init-num-eval 25 --jump-count 1 --lr 0.0001 --lr-step-freq 0 --lr-step-mult 1.0 --max-baseline 1.0 --max-num-eval 10000 --max-query 25000 --max-sharp 0.5 --mean-reward --min-baseline 0.05 --min-epsilon-mult 0.01 --min-sharp 0.02 --minus-ca-sim 0.0 --momentum 0.0 --norm-type l2 --num-image 1000 --num-pre-tune-step 0 --optimizer Adam --part-id 0 --phase test --policy-arch vgg13_inv --policy-base-width 32 --policy-bilinear --policy-calibrate --policy-init-std 0.003 --policy-normalization-type none --policy-weight-fname output/policy-smtrain-large-batch-cifar10-wrn_28_10_drop-untargeted-l2/2020-08-22_14-19-59-vUfOtLWE/results/model_best.pth --pre-tune-lr 0.0001 --pre-tune-th 1.0 --rescale-factor 0.5 --save-grad-pct 0.0 --seed 1234 --std-lr-mult 1 --std-reward --sub-base --tan-jump --try-split 0.0 0.25 --victim-arch wrn_28_10_drop --victim-batch-size 50 7 | 8 | -------------------------------------------------------------------------------- /pda_imagenet_resnet18_untargeted_l2.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -x 3 | set -e 4 | set -u 5 | 6 | python3.5 policy_attack.py --attack-type untargeted --ce-lmbd 1.0 3e-3 1.5e-3 1.5e-3 --clip-grad 5 --cosine-epsilon-round 0 --current-mean-mult 1 --dataset imagenet --decay 0 --delta-mult 1 --empty-coeff 0.5 --empty-normal-mean-norm 0.003 --epsilon-schema fixed --exclude-std --exp-dir output/policy-s2-final-imagenet-resnet18-untargeted-l2 --fix-num-eval --fixed-epsilon-mult 0.4 --gamma 50.0 --grad-method policy_distance --grad-size 0 --image-id-ref output/policy-smtrain-large-batch-imagenet-resnet18-untargeted-l2/2020-11-02_15-20-05-WFF8TMe1 --init-boost --init-boost-stop 250 --init-boost-th 0.1 --init-empty-normal-mean --init-num-eval 25 --jump-count 1 --lr 0.0001 --lr-step-freq 0 --lr-step-mult 1.0 --max-baseline 1.0 --max-num-eval 10000 --max-query 25000 --max-sharp 0.5 --mean-reward --min-baseline 0.05 --min-epsilon-mult 0.01 --min-sharp 0.02 --minus-ca-sim 0.0 --momentum 0.0 --norm-type l2 --num-image 1000 --num-pre-tune-step 0 --optimizer Adam --part-id 0 --phase valv2 --policy-arch vgg13_inv --policy-base-width 32 --policy-bilinear --policy-calibrate --policy-init-std 0.003 --policy-normalization-type none --policy-weight-fname output/policy-smtrain-large-batch-imagenet-resnet18-untargeted-l2/2020-11-02_15-20-05-WFF8TMe1/results/model_best.pth --pre-tune-lr 0.0001 --pre-tune-th 1.0 --rescale-factor 0.5 --save-grad-pct 0.0 --seed 1234 --std-lr-mult 1 --std-reward --sub-base --tan-jump --try-split 0.0 0.25 --victim-arch resnet18 --victim-batch-size 50 7 | 8 | -------------------------------------------------------------------------------- /pda_mnist_carlinet_untargeted_l2.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -x 3 | set -e 4 | set -u 5 | 6 | python3.5 policy_attack.py --attack-type untargeted --ce-lmbd 1.0 3e-3 1.5e-3 1.5e-3 --clip-grad 5 --cosine-epsilon-round 0 --current-mean-mult 1 --dataset mnist --decay 0 --delta-mult 1 --empty-coeff 0.5 --empty-normal-mean-norm 0.003 --epsilon-schema fixed --exclude-std --exp-dir output/policy-s2-final-mnist-carlinet-untargeted-l2 --fix-num-eval --fixed-epsilon-mult 0.4 --gamma 50.0 --grad-method policy_distance --grad-size 0 --image-id-ref output/policy-smtrain-inv-mnist-carlinet-untargeted-l2/2020-09-28_13-41-55-DgrgzXkj --init-boost --init-boost-stop 250 --init-boost-th 0.1 --init-empty-normal-mean --init-num-eval 25 --jump-count 1 --lr 0.0001 --lr-step-freq 0 --lr-step-mult 1.0 --max-baseline 1.0 --max-num-eval 10000 --max-query 25000 --max-sharp 0.5 --mean-reward --min-baseline 0.05 --min-epsilon-mult 0.01 --min-sharp 0.02 --minus-ca-sim 0.0 --momentum 0.0 --norm-type l2 --num-image 1000 --num-pre-tune-step 0 --optimizer Adam --part-id 0 --phase test --policy-arch vgg13_inv --policy-base-width 32 --policy-bilinear --policy-calibrate --policy-init-std 0.003 --policy-normalization-type none --policy-weight-fname output/policy-smtrain-inv-mnist-carlinet-untargeted-l2/2020-09-28_13-41-55-DgrgzXkj/results/model_best.pth --pre-tune-lr 0.0001 --pre-tune-th 1.0 --rescale-factor 0.5 --save-grad-pct 0.0 --seed 1234 --std-lr-mult 1 --std-reward --sub-base --tan-jump --try-split 0.0 0.25 --victim-arch carlinet --victim-batch-size 50 7 | 8 | -------------------------------------------------------------------------------- /prepare_imagenet_valv2.py: -------------------------------------------------------------------------------- 1 | from glob import glob 2 | import os 3 | import os.path as osp 4 | import glog as log 5 | import json 6 | 7 | 8 | def main(): 9 | imagenet_dirname = 'data/imagenet' 10 | output_dirname = 'data/imagenet/valv2' 11 | imagenetv2_raw_dirname = 'data/imagenetv2-raw' 12 | imagenetv2_keys = ['matched-frequency', 'threshold0.7', 'topimages'] 13 | 14 | # copy imagenet val into output directory 15 | log.info('Copy imagenet val images into output directory') 16 | fnames = glob(osp.join(imagenet_dirname, 'val', '*', '*.JPEG')) 17 | assert len(fnames) == 50000 18 | for fname in fnames: 19 | split = fname.split('/') 20 | output_fname = osp.join(output_dirname, split[-2], split[-1]) 21 | if not osp.exists(output_fname): 22 | os.makedirs(osp.dirname(output_fname), exist_ok=True) 23 | shell_cmd = 'ln -s {} {}'.format(osp.realpath(fname), output_fname) 24 | os.system(shell_cmd) 25 | 26 | # copy imagenetv2 into output directory 27 | log.info('Copy imagenetv2 images into output directory') 28 | with open(osp.join(imagenet_dirname, 'imagenet_class_index.json'), 'r') as f: 29 | class_mapping = json.load(f) 30 | 31 | for class_index in class_mapping.keys(): 32 | wnid = class_mapping[class_index][0] 33 | for key in imagenetv2_keys: 34 | fnames = glob(osp.join(imagenetv2_raw_dirname, 'imagenetv2-{}'.format(key), class_index, '*.jpeg')) 35 | assert len(fnames) == 10 36 | for fname in fnames: 37 | split = fname.split('/') 38 | fid = split[-1].split('.')[0] 39 | output_fname = osp.join(output_dirname, wnid, 40 | 'imagenetv2-{}-{}.JPEG'.format(key, fid)) 41 | if not osp.exists(output_fname): 42 | os.makedirs(osp.dirname(output_fname), exist_ok=True) 43 | shell_cmd = 'ln -s {} {}'.format(osp.realpath(fname), output_fname) 44 | os.system(shell_cmd) 45 | 46 | log.info('Done') 47 | 48 | 49 | if __name__ == '__main__': 50 | main() 51 | 52 | --------------------------------------------------------------------------------