├── requirements.txt ├── WriteUp.pdf ├── src ├── README.md ├── run_untargeted_with_eot_conf_15_noise_6_ensemble_13.sh ├── run_untargeted_without_eot_conf_15_ensemble_16.sh ├── run_targeted_without_eot_conf_18_ensemble_17.sh ├── models │ ├── __init__.py │ ├── vgg.py │ ├── darknet.py │ ├── model_libs.py │ ├── squeezenet.py │ ├── fast_imagenet.py │ ├── resnext101_wsl.py │ ├── alexnet.py │ ├── resnet_vc.py │ ├── resnext.py │ ├── mobilenet_v1.py │ ├── densenet.py │ ├── mobilenet_v2.py │ ├── res2net.py │ ├── resnet.py │ ├── layers.py │ ├── mobilenet_v2_old.py │ ├── resnext_vd.py │ ├── se_resnext.py │ ├── googlenet.py │ ├── xception.py │ ├── res2net_vd.py │ ├── resnet_vd.py │ ├── shufflenet_v2_swish.py │ └── shufflenet_v2.py ├── utils.py ├── attack_pgd_l2.py └── check_label.py └── ReadMe.md /requirements.txt: -------------------------------------------------------------------------------- 1 | paddlepaddle -------------------------------------------------------------------------------- /WriteUp.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/persistz/baidu_ai_attack_SSC/HEAD/WriteUp.pdf -------------------------------------------------------------------------------- /src/README.md: -------------------------------------------------------------------------------- 1 | ### Usage 2 | ``` 3 | bash run_untargeted_with_eot_conf_15_noise_6_ensemble_13.sh 4 | bash run_untargeted_without_eot_conf_15_ensemble_16.sh 5 | bash run_targeted_without_eot_conf_18_ensemble_17.sh 6 | ``` 7 | 8 | ## All models copy from [PaddlePaddle][pdpd] 9 | 10 | 11 | [pdpd]:https://github.com/PaddlePaddle/models/tree/develop/PaddleCV/image_classification/models 12 | -------------------------------------------------------------------------------- /ReadMe.md: -------------------------------------------------------------------------------- 1 | # 百度AI安全对抗赛1st solution 2 | 3 | 本项目基于飞桨PaddlePaddle实现。 4 | 5 | 项目内容为百度AI安全对抗赛第一名团队示例代码,基于官方给出的PGD修改,主要内容为L2-PGD+EOT。 6 | 7 | 该团队成功攻击了赛事主办方给出全部模型和全部图片,达到了100%的白盒攻击+黑盒迁移攻击成功率,同时获得了全场最低的MSE。 8 | 9 | ## Usage 10 | 11 | 比赛中使用的攻击思想已放入[attack_demo.ipynb](https://github.com/persistz/baidu_ai_attack_SSC/blob/master/attack_demo.ipynb "attack_demo.ipynb") 12 | 13 | 如需要复现完整攻击,请下载如下数据集: 14 | [AIStudio链接](https://aistudio.baidu.com/aistudio/datasetdetail/19743)并参考目录src下的文件 15 | 16 | 17 | ## Main Idea 18 | 19 | - 使用$L_2$ norm约束对抗样本的扰动 20 | - 合理定义loss函数实现confidence较高的对抗样本 21 | 22 | 更多细节可参考 write up 23 | 24 | 25 | ## Related Links 26 | 27 | 比赛链接:[https://aistudio.baidu.com/aistudio/competition/detail/15](https://aistudio.baidu.com/aistudio/competition/detail/15) 28 | 29 | PaddlePaddle官方文档: 30 | [https://www.paddlepaddle.org.cn/](https://www.paddlepaddle.org.cn/) 31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /src/run_untargeted_with_eot_conf_15_noise_6_ensemble_13.sh: -------------------------------------------------------------------------------- 1 | export FLAGS_fraction_of_gpu_memory_to_use=0.9 2 | 3 | model_name_list=("MobileNetV2" 4 | "ResNeXt50_32x4d" 5 | "EfficientNetB0" 6 | "Res2Net50_26w_4s" 7 | "SE_ResNet34_vd" 8 | "ShuffleNetV2_x2_0" 9 | "MobileNetV2_x2_0" 10 | "SE_ResNet50_vd" 11 | "ResNet50" 12 | "SqueezeNet1_1" 13 | "ResNeXt50_vd_32x4d" 14 | "ShuffleNetV2" 15 | "ResNet34" 16 | # "VGG19" 17 | # "VGG16" 18 | # "MobileNetV1" 19 | ) 20 | fold_prefix=img_pgdl2_with_eot 21 | log_prefix=log_pgdl2_with_eot 22 | 23 | num=${#model_name_list[@]} 24 | GPU_ID=0 25 | start_idx=0 26 | end_idx=120 27 | for id in `seq 0 $((num-1))` 28 | do 29 | mkdir ${fold_prefix}_m${id} 30 | echo ${id} 31 | echo ${model_name_list[$id]} 32 | done 33 | 34 | 35 | 36 | CUDA_VISIBLE_DEVICES=${GPU_ID} nohup python attack_pgd_l2.py \ 37 | --input="./input_image/" \ 38 | --output=./${fold_prefix}_m0/\ 39 | --model_name=MobileNetV2 \ 40 | --subfix=.jpg \ 41 | --eps=20.0 \ 42 | --confidence=15 \ 43 | --step_size=0.01 \ 44 | --is_targeted=0 \ 45 | --num_samples=5 \ 46 | --noise_scale=0.6 \ 47 | --start_idx=${start_idx} \ 48 | --end_idx=${end_idx} > ${log_prefix}_0_${GPU_ID}.txt & 49 | 50 | wait 51 | 52 | for m in `seq 1 $((num-1))` 53 | do 54 | wait 55 | CUDA_VISIBLE_DEVICES=${GPU_ID} nohup python attack_pgd_l2.py \ 56 | --input=./${fold_prefix}_m$((m-1))/ \ 57 | --output=./${fold_prefix}_m${m}/ \ 58 | --model_name=${model_name_list[$m]} \ 59 | --subfix=.png \ 60 | --eps=20.0 \ 61 | --confidence=15 \ 62 | --step_size=0.01 \ 63 | --is_targeted=0 \ 64 | --num_samples=5 \ 65 | --noise_scale=0.6 \ 66 | --start_idx=${start_idx} \ 67 | --end_idx=${end_idx}> ${log_prefix}_${m}_${GPU_ID}.txt & 68 | done 69 | -------------------------------------------------------------------------------- /src/run_untargeted_without_eot_conf_15_ensemble_16.sh: -------------------------------------------------------------------------------- 1 | export FLAGS_fraction_of_gpu_memory_to_use=0.9 2 | 3 | model_name_list=("ResNeXt50_32x4d" 4 | "MobileNetV2" 5 | "EfficientNetB0" 6 | "Res2Net50_26w_4s" 7 | "SE_ResNet34_vd" 8 | "ShuffleNetV2_x2_0" 9 | "MobileNetV2_x2_0" 10 | "SE_ResNet50_vd" 11 | "ResNet50" 12 | "SqueezeNet1_1" 13 | "ResNeXt50_vd_32x4d" 14 | "ShuffleNetV2" 15 | "ResNet34" 16 | "VGG19" 17 | "VGG16" 18 | "MobileNetV1" 19 | ) 20 | fold_prefix=img_pgdl2_without_eot 21 | log_prefix=log_pgdl2_without_eot 22 | 23 | num=${#model_name_list[@]} 24 | GPU_ID=0 25 | for id in `seq 0 $((num-1))` 26 | do 27 | mkdir ${fold_prefix}_m${id} 28 | echo ${id} 29 | echo ${model_name_list[$id]} 30 | done 31 | 32 | 33 | # gray box model is ResNeXt50, so we only apply EoT on ResNeXt50_32x4d model 34 | CUDA_VISIBLE_DEVICES=${GPU_ID} nohup python attack_pgd_l2.py \ 35 | --input="./input_image/" \ 36 | --output=./${fold_prefix}_m0/\ 37 | --model_name=ResNeXt50_32x4d \ 38 | --subfix=.jpg \ 39 | --eps=20.0 \ 40 | --confidence=20 \ 41 | --step_size=0.01 \ 42 | --is_targeted=0 \ 43 | --num_samples=5 \ 44 | --noise_scale=0.6 \ 45 | --start_idx=0 \ 46 | --end_idx=120 > ${log_prefix}_0_${GPU_ID}.txt & 47 | 48 | wait 49 | 50 | for m in `seq 1 $((num-1))` 51 | do 52 | wait 53 | CUDA_VISIBLE_DEVICES=${GPU_ID} nohup python attack_pgd_l2.py \ 54 | --input=./${fold_prefix}_m$((m-1))/ \ 55 | --output=./${fold_prefix}_m${m}/ \ 56 | --model_name=${model_name_list[$m]} \ 57 | --subfix=.png \ 58 | --eps=20.0 \ 59 | --confidence=15 \ 60 | --step_size=0.01 \ 61 | --is_targeted=0 \ 62 | --num_samples=1 \ 63 | --noise_scale=0.00001 \ 64 | --start_idx=0 \ 65 | --end_idx=120 > ${log_prefix}_${m}_${GPU_ID}.txt & 66 | done 67 | -------------------------------------------------------------------------------- /src/run_targeted_without_eot_conf_18_ensemble_17.sh: -------------------------------------------------------------------------------- 1 | export FLAGS_fraction_of_gpu_memory_to_use=0.9 2 | 3 | model_name_list=("ResNeXt50_32x4d" 4 | "MobileNetV2" 5 | "EfficientNetB0" 6 | "Res2Net50_26w_4s" 7 | "SE_ResNet34_vd" 8 | "ShuffleNetV2_x2_0" 9 | "MobileNetV2_x2_0" 10 | "SE_ResNet50_vd" 11 | "ResNet50" 12 | "SqueezeNet1_1" 13 | "ResNeXt50_vd_32x4d" 14 | "ShuffleNetV2" 15 | "ResNet34" 16 | "VGG19" 17 | "VGG16" 18 | "MobileNetV1" 19 | "DPN92" 20 | ) 21 | fold_prefix=img_pgdl2_without_eot_targeted 22 | log_prefix=log_pgdl2_without_eot_targeted 23 | 24 | num=${#model_name_list[@]} 25 | GPU_ID=0 26 | for id in `seq 0 $((num-1))` 27 | do 28 | mkdir ${fold_prefix}_m${id} 29 | echo ${id} 30 | echo ${model_name_list[$id]} 31 | done 32 | 33 | 34 | # gray box model is ResNeXt50, so we only apply EoT on ResNeXt50_32x4d model 35 | for idx in 120 14 48 66 87 93 97 107 109 110 113 117 118 36 | do 37 | wait 38 | CUDA_VISIBLE_DEVICES=${GPU_ID} nohup python attack_pgd_l2.py \ 39 | --input="./input_image/" \ 40 | --output=./${fold_prefix}_m0/\ 41 | --model_name=ResNeXt50_32x4d \ 42 | --subfix=.jpg \ 43 | --eps=20.0 \ 44 | --confidence=30 \ 45 | --step_size=0.02 \ 46 | --is_targeted=1 \ 47 | --num_samples=6 \ 48 | --noise_scale=0.6 \ 49 | --start_idx=$((idx-1)) \ 50 | --end_idx=${idx} > ${log_prefix}_0_${GPU_ID}_image_idx_${idx}.txt & 51 | done 52 | 53 | wait 54 | 55 | for m in `seq 1 $((num-1))` 56 | do 57 | for idx in 120 14 48 66 87 93 97 107 109 110 113 117 118 58 | do 59 | wait 60 | CUDA_VISIBLE_DEVICES=${GPU_ID} nohup python attack_pgd_l2.py \ 61 | --input=./${fold_prefix}_m$((m-1))/ \ 62 | --output=./${fold_prefix}_m${m}/ \ 63 | --model_name=${model_name_list[$m]} \ 64 | --subfix=.png \ 65 | --eps=20.0 \ 66 | --confidence=18 \ 67 | --step_size=0.01 \ 68 | --is_targeted=1 \ 69 | --num_samples=1 \ 70 | --noise_scale=0.00001 \ 71 | --start_idx=$((idx-1)) \ 72 | --end_idx=${idx} > ${log_prefix}_${m}_${GPU_ID}_image_idx_${idx}.txt & 73 | done 74 | done 75 | -------------------------------------------------------------------------------- /src/models/__init__.py: -------------------------------------------------------------------------------- 1 | #copyright (c) 2019 PaddlePaddle Authors. All Rights Reserve. 2 | # 3 | #Licensed under the Apache License, Version 2.0 (the "License"); 4 | #you may not use this file except in compliance with the License. 5 | #You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | #Unless required by applicable law or agreed to in writing, software 10 | #distributed under the License is distributed on an "AS IS" BASIS, 11 | #WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | #See the License for the specific language governing permissions and 13 | #limitations under the License. 14 | 15 | from .alexnet import AlexNet 16 | from .mobilenet_v1 import MobileNetV1_x0_25, MobileNetV1_x0_5, MobileNetV1_x1_0, MobileNetV1_x0_75, MobileNetV1 17 | from .mobilenet_v2 import MobileNetV2_x0_25, MobileNetV2_x0_5, MobileNetV2_x1_0, MobileNetV2_x1_5, MobileNetV2_x2_0 18 | from .mobilenet_v2_old import MobileNetV2 19 | from .mobilenet_v3 import MobileNetV3_small_x0_25, MobileNetV3_small_x0_5, MobileNetV3_small_x0_75, MobileNetV3_small_x1_0, MobileNetV3_small_x1_25, MobileNetV3_large_x0_25, MobileNetV3_large_x0_5, MobileNetV3_large_x0_75, MobileNetV3_large_x1_0, MobileNetV3_large_x1_25 20 | from .googlenet import GoogLeNet 21 | from .vgg import VGG11, VGG13, VGG16, VGG19 22 | from .resnet import ResNet18, ResNet34, ResNet50, ResNet101, ResNet152 23 | from .resnet_vc import ResNet50_vc, ResNet101_vc, ResNet152_vc 24 | from .resnet_vd import ResNet18_vd, ResNet34_vd, ResNet50_vd, ResNet101_vd, ResNet152_vd, ResNet200_vd 25 | from .resnext import ResNeXt50_64x4d, ResNeXt101_64x4d, ResNeXt152_64x4d, ResNeXt50_32x4d, ResNeXt101_32x4d, ResNeXt152_32x4d 26 | from .resnext_vd import ResNeXt50_vd_64x4d, ResNeXt101_vd_64x4d, ResNeXt152_vd_64x4d, ResNeXt50_vd_32x4d, ResNeXt101_vd_32x4d, ResNeXt152_vd_32x4d 27 | from .inception_v4 import InceptionV4 28 | from .se_resnet_vd import SE_ResNet18_vd, SE_ResNet34_vd, SE_ResNet50_vd, SE_ResNet101_vd, SE_ResNet152_vd, SE_ResNet200_vd 29 | from .se_resnext import SE_ResNeXt50_32x4d, SE_ResNeXt101_32x4d, SE_ResNeXt152_32x4d 30 | from .se_resnext_vd import SE_ResNeXt50_vd_32x4d, SE_ResNeXt101_vd_32x4d, SENet154_vd 31 | from .dpn import DPN68, DPN92, DPN98, DPN107, DPN131 32 | from .shufflenet_v2_swish import ShuffleNetV2_swish, ShuffleNetV2_x0_5_swish, ShuffleNetV2_x1_0_swish, ShuffleNetV2_x1_5_swish, ShuffleNetV2_x2_0_swish 33 | from .shufflenet_v2 import ShuffleNetV2_x0_25, ShuffleNetV2_x0_33, ShuffleNetV2_x0_5, ShuffleNetV2_x1_0, ShuffleNetV2_x1_5, ShuffleNetV2_x2_0, ShuffleNetV2 34 | from .fast_imagenet import FastImageNet 35 | from .xception import Xception41, Xception65, Xception71 36 | from .xception_deeplab import Xception41_deeplab, Xception65_deeplab, Xception71_deeplab 37 | from .densenet import DenseNet121, DenseNet161, DenseNet169, DenseNet201, DenseNet264 38 | from .squeezenet import SqueezeNet1_0, SqueezeNet1_1 39 | from .darknet import DarkNet53 40 | from .resnext101_wsl import ResNeXt101_32x8d_wsl, ResNeXt101_32x16d_wsl, ResNeXt101_32x32d_wsl, ResNeXt101_32x48d_wsl, Fix_ResNeXt101_32x48d_wsl 41 | from .efficientnet import EfficientNet, EfficientNetB0, EfficientNetB1, EfficientNetB2, EfficientNetB3, EfficientNetB4, EfficientNetB5, EfficientNetB6, EfficientNetB7 42 | from .res2net import Res2Net50_48w_2s, Res2Net50_26w_4s, Res2Net50_14w_8s, Res2Net50_26w_6s, Res2Net50_26w_8s, Res2Net101_26w_4s, Res2Net152_26w_4s 43 | from .res2net_vd import Res2Net50_vd_48w_2s, Res2Net50_vd_26w_4s, Res2Net50_vd_14w_8s, Res2Net50_vd_26w_6s, Res2Net50_vd_26w_8s, Res2Net101_vd_26w_4s, Res2Net152_vd_26w_4s, Res2Net200_vd_26w_4s 44 | from .hrnet import HRNet_W18_C, HRNet_W30_C, HRNet_W32_C, HRNet_W40_C, HRNet_W44_C, HRNet_W48_C, HRNet_W60_C, HRNet_W64_C, SE_HRNet_W18_C, SE_HRNet_W30_C, SE_HRNet_W32_C, SE_HRNet_W40_C, SE_HRNet_W44_C, SE_HRNet_W48_C, SE_HRNet_W60_C, SE_HRNet_W64_C 45 | -------------------------------------------------------------------------------- /src/models/vgg.py: -------------------------------------------------------------------------------- 1 | #copyright (c) 2019 PaddlePaddle Authors. All Rights Reserve. 2 | # 3 | #Licensed under the Apache License, Version 2.0 (the "License"); 4 | #you may not use this file except in compliance with the License. 5 | #You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | #Unless required by applicable law or agreed to in writing, software 10 | #distributed under the License is distributed on an "AS IS" BASIS, 11 | #WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | #See the License for the specific language governing permissions and 13 | #limitations under the License. 14 | 15 | from __future__ import absolute_import 16 | from __future__ import division 17 | from __future__ import print_function 18 | 19 | import paddle 20 | import paddle.fluid as fluid 21 | 22 | __all__ = ["VGGNet", "VGG11", "VGG13", "VGG16", "VGG19"] 23 | 24 | 25 | class VGGNet(): 26 | def __init__(self, layers=16): 27 | self.layers = layers 28 | 29 | def net(self, input, class_dim=1000): 30 | layers = self.layers 31 | vgg_spec = { 32 | 11: ([1, 1, 2, 2, 2]), 33 | 13: ([2, 2, 2, 2, 2]), 34 | 16: ([2, 2, 3, 3, 3]), 35 | 19: ([2, 2, 4, 4, 4]) 36 | } 37 | assert layers in vgg_spec.keys(), \ 38 | "supported layers are {} but input layer is {}".format(vgg_spec.keys(), layers) 39 | 40 | nums = vgg_spec[layers] 41 | conv1 = self.conv_block(input, 64, nums[0], name="conv1_") 42 | conv2 = self.conv_block(conv1, 128, nums[1], name="conv2_") 43 | conv3 = self.conv_block(conv2, 256, nums[2], name="conv3_") 44 | conv4 = self.conv_block(conv3, 512, nums[3], name="conv4_") 45 | conv5 = self.conv_block(conv4, 512, nums[4], name="conv5_") 46 | 47 | fc_dim = 4096 48 | fc_name = ["fc6", "fc7", "fc8"] 49 | fc1 = fluid.layers.fc( 50 | input=conv5, 51 | size=fc_dim, 52 | act='relu', 53 | param_attr=fluid.param_attr.ParamAttr(name=fc_name[0] + "_weights"), 54 | bias_attr=fluid.param_attr.ParamAttr(name=fc_name[0] + "_offset")) 55 | fc1 = fluid.layers.dropout(x=fc1, dropout_prob=0.5) 56 | fc2 = fluid.layers.fc( 57 | input=fc1, 58 | size=fc_dim, 59 | act='relu', 60 | param_attr=fluid.param_attr.ParamAttr(name=fc_name[1] + "_weights"), 61 | bias_attr=fluid.param_attr.ParamAttr(name=fc_name[1] + "_offset")) 62 | fc2 = fluid.layers.dropout(x=fc2, dropout_prob=0.5) 63 | out = fluid.layers.fc( 64 | input=fc2, 65 | size=class_dim, 66 | param_attr=fluid.param_attr.ParamAttr(name=fc_name[2] + "_weights"), 67 | bias_attr=fluid.param_attr.ParamAttr(name=fc_name[2] + "_offset")) 68 | 69 | return out 70 | 71 | def conv_block(self, input, num_filter, groups, name=None): 72 | conv = input 73 | for i in range(groups): 74 | conv = fluid.layers.conv2d( 75 | input=conv, 76 | num_filters=num_filter, 77 | filter_size=3, 78 | stride=1, 79 | padding=1, 80 | act='relu', 81 | param_attr=fluid.param_attr.ParamAttr( 82 | name=name + str(i + 1) + "_weights"), 83 | bias_attr=False) 84 | return fluid.layers.pool2d( 85 | input=conv, pool_size=2, pool_type='max', pool_stride=2) 86 | 87 | 88 | def VGG11(): 89 | model = VGGNet(layers=11) 90 | return model 91 | 92 | 93 | def VGG13(): 94 | model = VGGNet(layers=13) 95 | return model 96 | 97 | 98 | def VGG16(): 99 | model = VGGNet(layers=16) 100 | return model 101 | 102 | 103 | def VGG19(): 104 | model = VGGNet(layers=19) 105 | return model 106 | -------------------------------------------------------------------------------- /src/models/darknet.py: -------------------------------------------------------------------------------- 1 | #copyright (c) 2019 PaddlePaddle Authors. All Rights Reserve. 2 | # 3 | #Licensed under the Apache License, Version 2.0 (the "License"); 4 | #you may not use this file except in compliance with the License. 5 | #You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | #Unless required by applicable law or agreed to in writing, software 10 | #distributed under the License is distributed on an "AS IS" BASIS, 11 | #WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | #See the License for the specific language governing permissions and 13 | #limitations under the License. 14 | from __future__ import absolute_import 15 | from __future__ import division 16 | from __future__ import print_function 17 | 18 | import paddle.fluid as fluid 19 | from paddle.fluid.param_attr import ParamAttr 20 | import math 21 | __all__ = ["DarkNet53"] 22 | 23 | 24 | class DarkNet53(): 25 | def __init__(self): 26 | 27 | pass 28 | 29 | def net(self, input, class_dim=1000): 30 | DarkNet_cfg = {53: ([1, 2, 8, 8, 4], self.basicblock)} 31 | stages, block_func = DarkNet_cfg[53] 32 | stages = stages[0:5] 33 | conv1 = self.conv_bn_layer( 34 | input, 35 | ch_out=32, 36 | filter_size=3, 37 | stride=1, 38 | padding=1, 39 | name="yolo_input") 40 | conv = self.downsample( 41 | conv1, ch_out=conv1.shape[1] * 2, name="yolo_input.downsample") 42 | 43 | for i, stage in enumerate(stages): 44 | conv = self.layer_warp( 45 | block_func, conv, 32 * (2**i), stage, name="stage.{}".format(i)) 46 | if i < len(stages) - 1: # do not downsaple in the last stage 47 | conv = self.downsample( 48 | conv, 49 | ch_out=conv.shape[1] * 2, 50 | name="stage.{}.downsample".format(i)) 51 | pool = fluid.layers.pool2d( 52 | input=conv, pool_type='avg', global_pooling=True) 53 | stdv = 1.0 / math.sqrt(pool.shape[1] * 1.0) 54 | out = fluid.layers.fc( 55 | input=pool, 56 | size=class_dim, 57 | param_attr=ParamAttr( 58 | initializer=fluid.initializer.Uniform(-stdv, stdv), 59 | name='fc_weights'), 60 | bias_attr=ParamAttr(name='fc_offset')) 61 | return out 62 | 63 | def conv_bn_layer(self, 64 | input, 65 | ch_out, 66 | filter_size, 67 | stride, 68 | padding, 69 | name=None): 70 | conv = fluid.layers.conv2d( 71 | input=input, 72 | num_filters=ch_out, 73 | filter_size=filter_size, 74 | stride=stride, 75 | padding=padding, 76 | act=None, 77 | param_attr=ParamAttr(name=name + ".conv.weights"), 78 | bias_attr=False) 79 | 80 | bn_name = name + ".bn" 81 | out = fluid.layers.batch_norm( 82 | input=conv, 83 | act='relu', 84 | param_attr=ParamAttr(name=bn_name + '.scale'), 85 | bias_attr=ParamAttr(name=bn_name + '.offset'), 86 | moving_mean_name=bn_name + '.mean', 87 | moving_variance_name=bn_name + '.var') 88 | return out 89 | 90 | def downsample(self, 91 | input, 92 | ch_out, 93 | filter_size=3, 94 | stride=2, 95 | padding=1, 96 | name=None): 97 | return self.conv_bn_layer( 98 | input, 99 | ch_out=ch_out, 100 | filter_size=filter_size, 101 | stride=stride, 102 | padding=padding, 103 | name=name) 104 | 105 | def basicblock(self, input, ch_out, name=None): 106 | conv1 = self.conv_bn_layer(input, ch_out, 1, 1, 0, name=name + ".0") 107 | conv2 = self.conv_bn_layer(conv1, ch_out * 2, 3, 1, 1, name=name + ".1") 108 | out = fluid.layers.elementwise_add(x=input, y=conv2, act=None) 109 | return out 110 | 111 | def layer_warp(self, block_func, input, ch_out, count, name=None): 112 | res_out = block_func(input, ch_out, name='{}.0'.format(name)) 113 | for j in range(1, count): 114 | res_out = block_func(res_out, ch_out, name='{}.{}'.format(name, j)) 115 | return res_out 116 | -------------------------------------------------------------------------------- /src/models/model_libs.py: -------------------------------------------------------------------------------- 1 | #copyright (c) 2019 PaddlePaddle Authors. All Rights Reserve. 2 | # 3 | #Licensed under the Apache License, Version 2.0 (the "License"); 4 | #you may not use this file except in compliance with the License. 5 | #You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | #Unless required by applicable law or agreed to in writing, software 10 | #distributed under the License is distributed on an "AS IS" BASIS, 11 | #WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | #See the License for the specific language governing permissions and 13 | #limitations under the License. 14 | 15 | from __future__ import absolute_import 16 | from __future__ import division 17 | from __future__ import print_function 18 | import paddle 19 | import paddle.fluid as fluid 20 | import contextlib 21 | 22 | bn_regularizer = fluid.regularizer.L2DecayRegularizer(regularization_coeff=0.0) 23 | name_scope = "" 24 | 25 | @contextlib.contextmanager 26 | def scope(name): 27 | global name_scope 28 | bk = name_scope 29 | name_scope = name_scope + name + '/' 30 | yield 31 | name_scope = bk 32 | 33 | def max_pool(input, kernel, stride, padding): 34 | data = fluid.layers.pool2d(input, pool_size=kernel, pool_type='max', 35 | pool_stride=stride, pool_padding=padding) 36 | return data 37 | 38 | def group_norm(input, G, eps=1e-5, param_attr=None, bias_attr=None): 39 | N, C, H, W = input.shape 40 | if C % G != 0: 41 | # print "group can not divide channle:", C, G 42 | for d in range(10): 43 | for t in [d, -d]: 44 | if G + t <= 0: continue 45 | if C % (G + t) == 0: 46 | G = G + t 47 | break 48 | if C % G == 0: 49 | # print "use group size:", G 50 | break 51 | assert C % G == 0 52 | x = fluid.layers.group_norm( 53 | input, 54 | groups=G, 55 | param_attr=param_attr, 56 | bias_attr=bias_attr, 57 | name=name_scope + 'group_norm') 58 | return x 59 | 60 | def bn(*args, **kargs): 61 | with scope('BatchNorm'): 62 | return fluid.layers.batch_norm( 63 | *args, 64 | epsilon=1e-3, 65 | momentum=0.99, 66 | param_attr=fluid.ParamAttr( 67 | name=name_scope + 'gamma', regularizer=bn_regularizer), 68 | bias_attr=fluid.ParamAttr( 69 | name=name_scope + 'beta', regularizer=bn_regularizer), 70 | moving_mean_name=name_scope + 'moving_mean', 71 | moving_variance_name=name_scope + 'moving_variance', 72 | **kargs) 73 | 74 | def bn_relu(data): 75 | return fluid.layers.relu(bn(data)) 76 | 77 | def relu(data): 78 | return fluid.layers.relu(data) 79 | 80 | def conv(*args, **kargs): 81 | kargs['param_attr'] = name_scope + 'weights' 82 | if 'bias_attr' in kargs and kargs['bias_attr']: 83 | kargs['bias_attr'] = fluid.ParamAttr( 84 | name=name_scope + 'biases', 85 | regularizer=None, 86 | initializer=fluid.initializer.ConstantInitializer(value=0.0)) 87 | else: 88 | kargs['bias_attr'] = False 89 | return fluid.layers.conv2d(*args, **kargs) 90 | 91 | def deconv(*args, **kargs): 92 | kargs['param_attr'] = name_scope + 'weights' 93 | if 'bias_attr' in kargs and kargs['bias_attr']: 94 | kargs['bias_attr'] = name_scope + 'biases' 95 | else: 96 | kargs['bias_attr'] = False 97 | return fluid.layers.conv2d_transpose(*args, **kargs) 98 | 99 | def seperate_conv(input, channel, stride, filter, dilation=1, act=None): 100 | param_attr = fluid.ParamAttr( 101 | name=name_scope + 'weights', 102 | regularizer=fluid.regularizer.L2DecayRegularizer( 103 | regularization_coeff=0.0), 104 | initializer=fluid.initializer.TruncatedNormal(loc=0.0, scale=0.33)) 105 | with scope('depthwise'): 106 | input = conv( 107 | input, 108 | input.shape[1], 109 | filter, 110 | stride, 111 | groups=input.shape[1], 112 | padding=(filter // 2) * dilation, 113 | dilation=dilation, 114 | use_cudnn=False, 115 | param_attr=param_attr) 116 | input = bn(input) 117 | if act: input = act(input) 118 | 119 | param_attr = fluid.ParamAttr( 120 | name=name_scope + 'weights', 121 | regularizer=None, 122 | initializer=fluid.initializer.TruncatedNormal(loc=0.0, scale=0.06)) 123 | with scope('pointwise'): 124 | input = conv(input, channel, 1, 1, groups=1, padding=0, 125 | param_attr=param_attr) 126 | input = bn(input) 127 | if act: input = act(input) 128 | return input 129 | -------------------------------------------------------------------------------- /src/utils.py: -------------------------------------------------------------------------------- 1 | #coding=utf-8 2 | 3 | from __future__ import absolute_import 4 | from __future__ import division 5 | from __future__ import print_function 6 | 7 | import os 8 | import cv2 9 | import time 10 | import sys 11 | import math 12 | import numpy as np 13 | import argparse 14 | import functools 15 | import distutils.util 16 | import six 17 | 18 | from PIL import Image, ImageOps 19 | #绘图函数 20 | import matplotlib 21 | #服务器环境设置 22 | import matplotlib.pyplot as plt 23 | 24 | 25 | #去除batch_norm的影响 26 | def init_prog(prog): 27 | for op in prog.block(0).ops: 28 | #print("op type is {}".format(op.type)) 29 | if op.type in ["batch_norm"]: 30 | # 兼容旧版本 paddle 31 | if hasattr(op, 'set_attr'): 32 | op.set_attr('is_test', False) 33 | op.set_attr('use_global_stats', True) 34 | else: 35 | op._set_attr('is_test', False) 36 | op._set_attr('use_global_stats', True) 37 | op.desc.check_attrs() 38 | 39 | def img2tensor(img,image_shape=[3,224,224]): 40 | 41 | mean = [0.485, 0.456, 0.406] 42 | std = [0.229, 0.224, 0.225] 43 | 44 | img = cv2.resize(img,(image_shape[1],image_shape[2])) 45 | 46 | #RGB img [224,224,3]->[3,224,224] 47 | img = img[:, :, ::-1].astype('float32').transpose((2, 0, 1)) / 255 48 | 49 | img_mean = np.array(mean).reshape((3, 1, 1)) 50 | img_std = np.array(std).reshape((3, 1, 1)) 51 | img -= img_mean 52 | img /= img_std 53 | 54 | img=img.astype('float32') 55 | img=np.expand_dims(img, axis=0) 56 | 57 | return img 58 | 59 | def crop_image(img, target_size, center): 60 | """ crop_image """ 61 | height, width = img.shape[:2] 62 | size = target_size 63 | if center == True: 64 | w_start = (width - size) // 2 65 | h_start = (height - size) // 2 66 | else: 67 | w_start = np.random.randint(0, width - size + 1) 68 | h_start = np.random.randint(0, height - size + 1) 69 | w_end = w_start + size 70 | h_end = h_start + size 71 | img = img[h_start:h_end, w_start:w_end, :] 72 | return img 73 | 74 | def process_img(img_path="",image_shape=[3,224,224]): 75 | 76 | mean = [0.485, 0.456, 0.406] 77 | std = [0.229, 0.224, 0.225] 78 | 79 | img = cv2.imread(img_path) 80 | img = cv2.resize(img,(image_shape[1],image_shape[2])) 81 | #img = cv2.resize(img,(256,256)) 82 | #img = crop_image(img, image_shape[1], True) 83 | 84 | # RBG img [224,224,3]->[3,224,224] 85 | img = img[:, :, ::-1].astype('float32').transpose((2, 0, 1)) / 255 86 | # img = img.astype('float32').transpose((2, 0, 1)) / 255 87 | img_mean = np.array(mean).reshape((3, 1, 1)) 88 | img_std = np.array(std).reshape((3, 1, 1)) 89 | img -= img_mean 90 | img /= img_std 91 | 92 | img=img.astype('float32') 93 | img=np.expand_dims(img, axis=0) 94 | 95 | return img 96 | 97 | def tensor2img(tensor): 98 | 99 | mean = [0.485, 0.456, 0.406] 100 | std = [0.229, 0.224, 0.225] 101 | 102 | img_mean = np.array(mean).reshape((3, 1, 1)) 103 | img_std = np.array(std).reshape((3, 1, 1)) 104 | 105 | img = tensor.copy() 106 | 107 | img *= img_std 108 | img += img_mean 109 | 110 | img = np.round(img*255) 111 | img = np.clip(img,0,255) 112 | 113 | img = img[0].astype(np.uint8) 114 | 115 | img = img.transpose(1, 2, 0) 116 | img = img[:, :, ::-1] 117 | 118 | return img 119 | 120 | def save_adv_image(img, output_path): 121 | cv2.imwrite(output_path, img, [int(cv2.IMWRITE_PNG_COMPRESSION), 0]) 122 | return 123 | 124 | def calc_mse(org_img, adv_img): 125 | org_img = org_img.astype(np.float32) 126 | adv_img = adv_img.astype(np.float32) 127 | diff = org_img.reshape((-1, 3)) - adv_img.reshape((-1, 3)) 128 | distance = np.mean(np.sqrt(np.sum((diff ** 2), axis=1))) 129 | return distance 130 | 131 | def print_arguments(args): 132 | """Print argparse's arguments. 133 | 134 | Usage: 135 | 136 | .. code-block:: python 137 | 138 | parser = argparse.ArgumentParser() 139 | parser.add_argument("name", default="Jonh", type=str, help="User name.") 140 | args = parser.parse_args() 141 | print_arguments(args) 142 | 143 | :param args: Input argparse.Namespace for printing. 144 | :type args: argparse.Namespace 145 | """ 146 | print("------------- Configuration Arguments -------------") 147 | for arg, value in sorted(six.iteritems(vars(args))): 148 | print("%25s : %s" % (arg, value)) 149 | print("----------------------------------------------------") 150 | 151 | 152 | def add_arguments(argname, type, default, help, argparser, **kwargs): 153 | """Add argparse's argument. 154 | 155 | Usage: 156 | 157 | .. code-block:: python 158 | 159 | parser = argparse.ArgumentParser() 160 | add_argument("name", str, "Jonh", "User name.", parser) 161 | args = parser.parse_args() 162 | """ 163 | type = distutils.util.strtobool if type == bool else type 164 | argparser.add_argument( 165 | "--" + argname, 166 | default=default, 167 | type=type, 168 | help=help + ' Default: %(default)s.', 169 | **kwargs) 170 | -------------------------------------------------------------------------------- /src/models/squeezenet.py: -------------------------------------------------------------------------------- 1 | #copyright (c) 2019 PaddlePaddle Authors. All Rights Reserve. 2 | # 3 | #Licensed under the Apache License, Version 2.0 (the "License"); 4 | #you may not use this file except in compliance with the License. 5 | #You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | #Unless required by applicable law or agreed to in writing, software 10 | #distributed under the License is distributed on an "AS IS" BASIS, 11 | #WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | #See the License for the specific language governing permissions and 13 | #limitations under the License. 14 | from __future__ import absolute_import 15 | from __future__ import division 16 | from __future__ import print_function 17 | 18 | import paddle 19 | import paddle.fluid as fluid 20 | import math 21 | from paddle.fluid.param_attr import ParamAttr 22 | 23 | __all__ = ["SqueezeNet", "SqueezeNet1_0", "SqueezeNet1_1"] 24 | 25 | 26 | class SqueezeNet(): 27 | def __init__(self, version='1.0'): 28 | self.version = version 29 | 30 | def net(self, input, class_dim=1000): 31 | version = self.version 32 | assert version in ['1.0', '1.1'], \ 33 | "supported version are {} but input version is {}".format(['1.0', '1.1'], version) 34 | if version == '1.0': 35 | conv = fluid.layers.conv2d( 36 | input, 37 | num_filters=96, 38 | filter_size=7, 39 | stride=2, 40 | act='relu', 41 | param_attr=fluid.param_attr.ParamAttr(name="conv1_weights"), 42 | bias_attr=ParamAttr(name='conv1_offset')) 43 | conv = fluid.layers.pool2d( 44 | conv, pool_size=3, pool_stride=2, pool_type='max') 45 | conv = self.make_fire(conv, 16, 64, 64, name='fire2') 46 | conv = self.make_fire(conv, 16, 64, 64, name='fire3') 47 | conv = self.make_fire(conv, 32, 128, 128, name='fire4') 48 | conv = fluid.layers.pool2d( 49 | conv, pool_size=3, pool_stride=2, pool_type='max') 50 | conv = self.make_fire(conv, 32, 128, 128, name='fire5') 51 | conv = self.make_fire(conv, 48, 192, 192, name='fire6') 52 | conv = self.make_fire(conv, 48, 192, 192, name='fire7') 53 | conv = self.make_fire(conv, 64, 256, 256, name='fire8') 54 | conv = fluid.layers.pool2d( 55 | conv, pool_size=3, pool_stride=2, pool_type='max') 56 | conv = self.make_fire(conv, 64, 256, 256, name='fire9') 57 | else: 58 | conv = fluid.layers.conv2d( 59 | input, 60 | num_filters=64, 61 | filter_size=3, 62 | stride=2, 63 | padding=1, 64 | act='relu', 65 | param_attr=fluid.param_attr.ParamAttr(name="conv1_weights"), 66 | bias_attr=ParamAttr(name='conv1_offset')) 67 | conv = fluid.layers.pool2d( 68 | conv, pool_size=3, pool_stride=2, pool_type='max') 69 | conv = self.make_fire(conv, 16, 64, 64, name='fire2') 70 | conv = self.make_fire(conv, 16, 64, 64, name='fire3') 71 | conv = fluid.layers.pool2d( 72 | conv, pool_size=3, pool_stride=2, pool_type='max') 73 | conv = self.make_fire(conv, 32, 128, 128, name='fire4') 74 | conv = self.make_fire(conv, 32, 128, 128, name='fire5') 75 | conv = fluid.layers.pool2d( 76 | conv, pool_size=3, pool_stride=2, pool_type='max') 77 | conv = self.make_fire(conv, 48, 192, 192, name='fire6') 78 | conv = self.make_fire(conv, 48, 192, 192, name='fire7') 79 | conv = self.make_fire(conv, 64, 256, 256, name='fire8') 80 | conv = self.make_fire(conv, 64, 256, 256, name='fire9') 81 | conv = fluid.layers.dropout(conv, dropout_prob=0.5) 82 | conv = fluid.layers.conv2d( 83 | conv, 84 | num_filters=class_dim, 85 | filter_size=1, 86 | act='relu', 87 | param_attr=fluid.param_attr.ParamAttr(name="conv10_weights"), 88 | bias_attr=ParamAttr(name='conv10_offset')) 89 | conv = fluid.layers.pool2d(conv, pool_type='avg', global_pooling=True) 90 | out = fluid.layers.flatten(conv) 91 | return out 92 | 93 | def make_fire_conv(self, 94 | input, 95 | num_filters, 96 | filter_size, 97 | padding=0, 98 | name=None): 99 | conv = fluid.layers.conv2d( 100 | input, 101 | num_filters=num_filters, 102 | filter_size=filter_size, 103 | padding=padding, 104 | act='relu', 105 | param_attr=fluid.param_attr.ParamAttr(name=name + "_weights"), 106 | bias_attr=ParamAttr(name=name + '_offset')) 107 | return conv 108 | 109 | def make_fire(self, 110 | input, 111 | squeeze_channels, 112 | expand1x1_channels, 113 | expand3x3_channels, 114 | name=None): 115 | conv = self.make_fire_conv( 116 | input, squeeze_channels, 1, name=name + '_squeeze1x1') 117 | conv_path1 = self.make_fire_conv( 118 | conv, expand1x1_channels, 1, name=name + '_expand1x1') 119 | conv_path2 = self.make_fire_conv( 120 | conv, expand3x3_channels, 3, 1, name=name + '_expand3x3') 121 | out = fluid.layers.concat([conv_path1, conv_path2], axis=1) 122 | return out 123 | 124 | 125 | def SqueezeNet1_0(): 126 | model = SqueezeNet(version='1.0') 127 | return model 128 | 129 | 130 | def SqueezeNet1_1(): 131 | model = SqueezeNet(version='1.1') 132 | return model 133 | -------------------------------------------------------------------------------- /src/models/fast_imagenet.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2018 PaddlePaddle Authors. All Rights Reserved. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | from __future__ import absolute_import 16 | from __future__ import division 17 | from __future__ import print_function 18 | 19 | import functools 20 | import numpy as np 21 | import time 22 | import os 23 | import math 24 | 25 | import paddle 26 | import paddle.fluid as fluid 27 | import paddle.fluid.profiler as profiler 28 | import utils 29 | 30 | __all__ = ["FastImageNet"] 31 | 32 | 33 | class FastImageNet(): 34 | def __init__(self, layers=50, is_train=True): 35 | self.layers = layers 36 | self.is_train = is_train 37 | 38 | def net(self, input, class_dim=1000, img_size=224, is_train=True): 39 | layers = self.layers 40 | supported_layers = [50, 101, 152] 41 | assert layers in supported_layers, \ 42 | "supported layers are {} but input layer is {}".format(supported_layers, layers) 43 | 44 | if layers == 50: 45 | depth = [3, 4, 6, 3] 46 | elif layers == 101: 47 | depth = [3, 4, 23, 3] 48 | elif layers == 152: 49 | depth = [3, 8, 36, 3] 50 | num_filters = [64, 128, 256, 512] 51 | 52 | conv = self.conv_bn_layer( 53 | input=input, num_filters=64, filter_size=7, stride=2, act='relu') 54 | conv = fluid.layers.pool2d( 55 | input=conv, 56 | pool_size=3, 57 | pool_stride=2, 58 | pool_padding=1, 59 | pool_type='max') 60 | 61 | for block in range(len(depth)): 62 | for i in range(depth[block]): 63 | conv = self.bottleneck_block( 64 | input=conv, 65 | num_filters=num_filters[block], 66 | stride=2 if i == 0 and block != 0 else 1) 67 | pool_size = int(img_size / 32) 68 | pool = fluid.layers.pool2d( 69 | input=conv, pool_type='avg', global_pooling=True) 70 | out = fluid.layers.fc( 71 | input=pool, 72 | size=class_dim, 73 | act=None, 74 | param_attr=fluid.param_attr.ParamAttr( 75 | initializer=fluid.initializer.NormalInitializer(0.0, 0.01), 76 | regularizer=fluid.regularizer.L2Decay(1e-4)), 77 | bias_attr=fluid.ParamAttr( 78 | regularizer=fluid.regularizer.L2Decay(1e-4))) 79 | return out 80 | 81 | def conv_bn_layer(self, 82 | input, 83 | num_filters, 84 | filter_size, 85 | stride=1, 86 | groups=1, 87 | act=None, 88 | bn_init_value=1.0): 89 | conv = fluid.layers.conv2d( 90 | input=input, 91 | num_filters=num_filters, 92 | filter_size=filter_size, 93 | stride=stride, 94 | padding=(filter_size - 1) // 2, 95 | groups=groups, 96 | act=None, 97 | bias_attr=False, 98 | param_attr=fluid.ParamAttr( 99 | regularizer=fluid.regularizer.L2Decay(1e-4))) 100 | return fluid.layers.batch_norm( 101 | input=conv, 102 | act=act, 103 | is_test=not self.is_train, 104 | param_attr=fluid.param_attr.ParamAttr( 105 | initializer=fluid.initializer.Constant(bn_init_value), 106 | regularizer=None)) 107 | 108 | def shortcut(self, input, ch_out, stride): 109 | ch_in = input.shape[1] 110 | if ch_in != ch_out or stride != 1: 111 | return self.conv_bn_layer(input, ch_out, 1, stride) 112 | else: 113 | return input 114 | 115 | def bottleneck_block(self, input, num_filters, stride): 116 | conv0 = self.conv_bn_layer( 117 | input=input, num_filters=num_filters, filter_size=1, act='relu') 118 | conv1 = self.conv_bn_layer( 119 | input=conv0, 120 | num_filters=num_filters, 121 | filter_size=3, 122 | stride=stride, 123 | act='relu') 124 | # init bn-weight0 125 | conv2 = self.conv_bn_layer( 126 | input=conv1, 127 | num_filters=num_filters * 4, 128 | filter_size=1, 129 | act=None, 130 | bn_init_value=0.0) 131 | 132 | short = self.shortcut(input, num_filters * 4, stride) 133 | 134 | return fluid.layers.elementwise_add(x=short, y=conv2, act='relu') 135 | 136 | 137 | def lr_decay(lrs, epochs, bs, total_image): 138 | boundaries = [] 139 | values = [] 140 | for idx, epoch in enumerate(epochs): 141 | step = total_image // bs[idx] 142 | if step * bs[idx] < total_image: 143 | step += 1 144 | ratio = (lrs[idx][1] - lrs[idx][0]) * 1.0 / (epoch[1] - epoch[0]) 145 | lr_base = lrs[idx][0] 146 | for s in range(epoch[0], epoch[1]): 147 | if boundaries: 148 | boundaries.append(boundaries[-1] + step + 1) 149 | else: 150 | boundaries = [step] 151 | lr = lr_base + ratio * (s - epoch[0]) 152 | values.append(lr) 153 | print("epoch: [%d], steps: [%d], lr: [%f]" % 154 | (s, boundaries[-1], values[-1])) 155 | values.append(lrs[-1]) 156 | print("epoch: [%d:], steps: [%d:], lr:[%f]" % 157 | (epochs[-1][-1], boundaries[-1], values[-1])) 158 | return boundaries, values 159 | -------------------------------------------------------------------------------- /src/models/resnext101_wsl.py: -------------------------------------------------------------------------------- 1 | #copyright (c) 2019 PaddlePaddle Authors. All Rights Reserve. 2 | # 3 | #Licensed under the Apache License, Version 2.0 (the "License"); 4 | #you may not use this file except in compliance with the License. 5 | #You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | #Unless required by applicable law or agreed to in writing, software 10 | #distributed under the License is distributed on an "AS IS" BASIS, 11 | #WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | #See the License for the specific language governing permissions and 13 | #limitations under the License. 14 | from __future__ import absolute_import 15 | from __future__ import division 16 | from __future__ import print_function 17 | import paddle 18 | import paddle.fluid as fluid 19 | import math 20 | from paddle.fluid.param_attr import ParamAttr 21 | 22 | __all__ = [ 23 | "ResNeXt101_32x8d_wsl", "ResNeXt101_32x16d_wsl", "ResNeXt101_32x32d_wsl", 24 | "ResNeXt101_32x48d_wsl", "Fix_ResNeXt101_32x48d_wsl" 25 | ] 26 | 27 | 28 | class ResNeXt101_wsl(): 29 | def __init__(self, layers=101, cardinality=32, width=48): 30 | self.layers = layers 31 | self.cardinality = cardinality 32 | self.width = width 33 | 34 | def net(self, input, class_dim=1000): 35 | layers = self.layers 36 | cardinality = self.cardinality 37 | width = self.width 38 | 39 | depth = [3, 4, 23, 3] 40 | base_width = cardinality * width 41 | num_filters = [base_width * i for i in [1, 2, 4, 8]] 42 | 43 | conv = self.conv_bn_layer( 44 | input=input, 45 | num_filters=64, 46 | filter_size=7, 47 | stride=2, 48 | act='relu', 49 | name="conv1") #debug 50 | conv = fluid.layers.pool2d( 51 | input=conv, 52 | pool_size=3, 53 | pool_stride=2, 54 | pool_padding=1, 55 | pool_type='max') 56 | 57 | for block in range(len(depth)): 58 | for i in range(depth[block]): 59 | conv_name = 'layer' + str(block + 1) + "." + str(i) 60 | conv = self.bottleneck_block( 61 | input=conv, 62 | num_filters=num_filters[block], 63 | stride=2 if i == 0 and block != 0 else 1, 64 | cardinality=cardinality, 65 | name=conv_name) 66 | 67 | pool = fluid.layers.pool2d( 68 | input=conv, pool_type='avg', global_pooling=True) 69 | stdv = 1.0 / math.sqrt(pool.shape[1] * 1.0) 70 | out = fluid.layers.fc( 71 | input=pool, 72 | size=class_dim, 73 | param_attr=fluid.param_attr.ParamAttr( 74 | initializer=fluid.initializer.Uniform(-stdv, stdv), 75 | name='fc.weight'), 76 | bias_attr=fluid.param_attr.ParamAttr(name='fc.bias')) 77 | return out 78 | 79 | def conv_bn_layer(self, 80 | input, 81 | num_filters, 82 | filter_size, 83 | stride=1, 84 | groups=1, 85 | act=None, 86 | name=None): 87 | if "downsample" in name: 88 | conv_name = name + '.0' 89 | else: 90 | conv_name = name 91 | conv = fluid.layers.conv2d( 92 | input=input, 93 | num_filters=num_filters, 94 | filter_size=filter_size, 95 | stride=stride, 96 | padding=(filter_size - 1) // 2, 97 | groups=groups, 98 | act=None, 99 | param_attr=ParamAttr(name=conv_name + ".weight"), 100 | bias_attr=False) 101 | if "downsample" in name: 102 | bn_name = name[:9] + 'downsample' + '.1' 103 | else: 104 | if "conv1" == name: 105 | bn_name = 'bn' + name[-1] 106 | else: 107 | bn_name = (name[:10] if name[7:9].isdigit() else name[:9] 108 | ) + 'bn' + name[-1] 109 | return fluid.layers.batch_norm( 110 | input=conv, 111 | act=act, 112 | param_attr=ParamAttr(name=bn_name + '.weight'), 113 | bias_attr=ParamAttr(bn_name + '.bias'), 114 | moving_mean_name=bn_name + '.running_mean', 115 | moving_variance_name=bn_name + '.running_var', ) 116 | 117 | def shortcut(self, input, ch_out, stride, name): 118 | ch_in = input.shape[1] 119 | if ch_in != ch_out or stride != 1: 120 | return self.conv_bn_layer(input, ch_out, 1, stride, name=name) 121 | else: 122 | return input 123 | 124 | def bottleneck_block(self, input, num_filters, stride, cardinality, name): 125 | cardinality = self.cardinality 126 | width = self.width 127 | conv0 = self.conv_bn_layer( 128 | input=input, 129 | num_filters=num_filters, 130 | filter_size=1, 131 | act='relu', 132 | name=name + ".conv1") 133 | conv1 = self.conv_bn_layer( 134 | input=conv0, 135 | num_filters=num_filters, 136 | filter_size=3, 137 | stride=stride, 138 | groups=cardinality, 139 | act='relu', 140 | name=name + ".conv2") 141 | conv2 = self.conv_bn_layer( 142 | input=conv1, 143 | num_filters=num_filters // (width // 8), 144 | filter_size=1, 145 | act=None, 146 | name=name + ".conv3") 147 | 148 | short = self.shortcut( 149 | input, 150 | num_filters // (width // 8), 151 | stride, 152 | name=name + ".downsample") 153 | 154 | return fluid.layers.elementwise_add(x=short, y=conv2, act='relu') 155 | 156 | 157 | def ResNeXt101_32x8d_wsl(): 158 | model = ResNeXt101_wsl(cardinality=32, width=8) 159 | return model 160 | 161 | 162 | def ResNeXt101_32x16d_wsl(): 163 | model = ResNeXt101_wsl(cardinality=32, width=16) 164 | return model 165 | 166 | 167 | def ResNeXt101_32x32d_wsl(): 168 | model = ResNeXt101_wsl(cardinality=32, width=32) 169 | return model 170 | 171 | 172 | def ResNeXt101_32x48d_wsl(): 173 | model = ResNeXt101_wsl(cardinality=32, width=48) 174 | return model 175 | 176 | 177 | def Fix_ResNeXt101_32x48d_wsl(): 178 | model = ResNeXt101_wsl(cardinality=32, width=48) 179 | return model 180 | -------------------------------------------------------------------------------- /src/models/alexnet.py: -------------------------------------------------------------------------------- 1 | #copyright (c) 2019 PaddlePaddle Authors. All Rights Reserve. 2 | # 3 | #Licensed under the Apache License, Version 2.0 (the "License"); 4 | #you may not use this file except in compliance with the License. 5 | #You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | #Unless required by applicable law or agreed to in writing, software 10 | #distributed under the License is distributed on an "AS IS" BASIS, 11 | #WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | #See the License for the specific language governing permissions and 13 | #limitations under the License. 14 | 15 | from __future__ import absolute_import 16 | from __future__ import division 17 | from __future__ import print_function 18 | 19 | import math 20 | 21 | import paddle 22 | import paddle.fluid as fluid 23 | 24 | __all__ = ['AlexNet'] 25 | 26 | 27 | class AlexNet(): 28 | def __init__(self): 29 | pass 30 | 31 | def net(self, input, class_dim=1000): 32 | stdv = 1.0 / math.sqrt(input.shape[1] * 11 * 11) 33 | layer_name = [ 34 | "conv1", "conv2", "conv3", "conv4", "conv5", "fc6", "fc7", "fc8" 35 | ] 36 | conv1 = fluid.layers.conv2d( 37 | input=input, 38 | num_filters=64, 39 | filter_size=11, 40 | stride=4, 41 | padding=2, 42 | groups=1, 43 | act='relu', 44 | bias_attr=fluid.param_attr.ParamAttr( 45 | initializer=fluid.initializer.Uniform(-stdv, stdv), 46 | name=layer_name[0] + "_offset"), 47 | param_attr=fluid.param_attr.ParamAttr( 48 | initializer=fluid.initializer.Uniform(-stdv, stdv), 49 | name=layer_name[0] + "_weights")) 50 | pool1 = fluid.layers.pool2d( 51 | input=conv1, 52 | pool_size=3, 53 | pool_stride=2, 54 | pool_padding=0, 55 | pool_type='max') 56 | 57 | stdv = 1.0 / math.sqrt(pool1.shape[1] * 5 * 5) 58 | conv2 = fluid.layers.conv2d( 59 | input=pool1, 60 | num_filters=192, 61 | filter_size=5, 62 | stride=1, 63 | padding=2, 64 | groups=1, 65 | act='relu', 66 | bias_attr=fluid.param_attr.ParamAttr( 67 | initializer=fluid.initializer.Uniform(-stdv, stdv), 68 | name=layer_name[1] + "_offset"), 69 | param_attr=fluid.param_attr.ParamAttr( 70 | initializer=fluid.initializer.Uniform(-stdv, stdv), 71 | name=layer_name[1] + "_weights")) 72 | pool2 = fluid.layers.pool2d( 73 | input=conv2, 74 | pool_size=3, 75 | pool_stride=2, 76 | pool_padding=0, 77 | pool_type='max') 78 | 79 | stdv = 1.0 / math.sqrt(pool2.shape[1] * 3 * 3) 80 | conv3 = fluid.layers.conv2d( 81 | input=pool2, 82 | num_filters=384, 83 | filter_size=3, 84 | stride=1, 85 | padding=1, 86 | groups=1, 87 | act='relu', 88 | bias_attr=fluid.param_attr.ParamAttr( 89 | initializer=fluid.initializer.Uniform(-stdv, stdv), 90 | name=layer_name[2] + "_offset"), 91 | param_attr=fluid.param_attr.ParamAttr( 92 | initializer=fluid.initializer.Uniform(-stdv, stdv), 93 | name=layer_name[2] + "_weights")) 94 | 95 | stdv = 1.0 / math.sqrt(conv3.shape[1] * 3 * 3) 96 | conv4 = fluid.layers.conv2d( 97 | input=conv3, 98 | num_filters=256, 99 | filter_size=3, 100 | stride=1, 101 | padding=1, 102 | groups=1, 103 | act='relu', 104 | bias_attr=fluid.param_attr.ParamAttr( 105 | initializer=fluid.initializer.Uniform(-stdv, stdv), 106 | name=layer_name[3] + "_offset"), 107 | param_attr=fluid.param_attr.ParamAttr( 108 | initializer=fluid.initializer.Uniform(-stdv, stdv), 109 | name=layer_name[3] + "_weights")) 110 | 111 | stdv = 1.0 / math.sqrt(conv4.shape[1] * 3 * 3) 112 | conv5 = fluid.layers.conv2d( 113 | input=conv4, 114 | num_filters=256, 115 | filter_size=3, 116 | stride=1, 117 | padding=1, 118 | groups=1, 119 | act='relu', 120 | bias_attr=fluid.param_attr.ParamAttr( 121 | initializer=fluid.initializer.Uniform(-stdv, stdv), 122 | name=layer_name[4] + "_offset"), 123 | param_attr=fluid.param_attr.ParamAttr( 124 | initializer=fluid.initializer.Uniform(-stdv, stdv), 125 | name=layer_name[4] + "_weights")) 126 | pool5 = fluid.layers.pool2d( 127 | input=conv5, 128 | pool_size=3, 129 | pool_stride=2, 130 | pool_padding=0, 131 | pool_type='max') 132 | 133 | drop6 = fluid.layers.dropout(x=pool5, dropout_prob=0.5) 134 | stdv = 1.0 / math.sqrt(drop6.shape[1] * drop6.shape[2] * 135 | drop6.shape[3] * 1.0) 136 | 137 | fc6 = fluid.layers.fc( 138 | input=drop6, 139 | size=4096, 140 | act='relu', 141 | bias_attr=fluid.param_attr.ParamAttr( 142 | initializer=fluid.initializer.Uniform(-stdv, stdv), 143 | name=layer_name[5] + "_offset"), 144 | param_attr=fluid.param_attr.ParamAttr( 145 | initializer=fluid.initializer.Uniform(-stdv, stdv), 146 | name=layer_name[5] + "_weights")) 147 | 148 | drop7 = fluid.layers.dropout(x=fc6, dropout_prob=0.5) 149 | stdv = 1.0 / math.sqrt(drop7.shape[1] * 1.0) 150 | 151 | fc7 = fluid.layers.fc( 152 | input=drop7, 153 | size=4096, 154 | act='relu', 155 | bias_attr=fluid.param_attr.ParamAttr( 156 | initializer=fluid.initializer.Uniform(-stdv, stdv), 157 | name=layer_name[6] + "_offset"), 158 | param_attr=fluid.param_attr.ParamAttr( 159 | initializer=fluid.initializer.Uniform(-stdv, stdv), 160 | name=layer_name[6] + "_weights")) 161 | 162 | stdv = 1.0 / math.sqrt(fc7.shape[1] * 1.0) 163 | out = fluid.layers.fc( 164 | input=fc7, 165 | size=class_dim, 166 | bias_attr=fluid.param_attr.ParamAttr( 167 | initializer=fluid.initializer.Uniform(-stdv, stdv), 168 | name=layer_name[7] + "_offset"), 169 | param_attr=fluid.param_attr.ParamAttr( 170 | initializer=fluid.initializer.Uniform(-stdv, stdv), 171 | name=layer_name[7] + "_weights")) 172 | return out 173 | -------------------------------------------------------------------------------- /src/models/resnet_vc.py: -------------------------------------------------------------------------------- 1 | #copyright (c) 2019 PaddlePaddle Authors. All Rights Reserve. 2 | # 3 | #Licensed under the Apache License, Version 2.0 (the "License"); 4 | #you may not use this file except in compliance with the License. 5 | #You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | #Unless required by applicable law or agreed to in writing, software 10 | #distributed under the License is distributed on an "AS IS" BASIS, 11 | #WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | #See the License for the specific language governing permissions and 13 | #limitations under the License. 14 | 15 | from __future__ import absolute_import 16 | from __future__ import division 17 | from __future__ import print_function 18 | 19 | import math 20 | 21 | import paddle 22 | import paddle.fluid as fluid 23 | from paddle.fluid.param_attr import ParamAttr 24 | 25 | __all__ = ["ResNet", "ResNet50_vc", "ResNet101_vc", "ResNet152_vc"] 26 | 27 | train_parameters = { 28 | "input_size": [3, 224, 224], 29 | "input_mean": [0.485, 0.456, 0.406], 30 | "input_std": [0.229, 0.224, 0.225], 31 | "learning_strategy": { 32 | "name": "piecewise_decay", 33 | "batch_size": 256, 34 | "epochs": [30, 60, 90], 35 | "steps": [0.1, 0.01, 0.001, 0.0001] 36 | } 37 | } 38 | 39 | 40 | class ResNet(): 41 | def __init__(self, layers=50): 42 | self.params = train_parameters 43 | self.layers = layers 44 | 45 | def net(self, input, class_dim=1000): 46 | layers = self.layers 47 | supported_layers = [50, 101, 152] 48 | assert layers in supported_layers, \ 49 | "supported layers are {} but input layer is {}".format(supported_layers, layers) 50 | 51 | if layers == 50: 52 | depth = [3, 4, 6, 3] 53 | elif layers == 101: 54 | depth = [3, 4, 23, 3] 55 | elif layers == 152: 56 | depth = [3, 8, 36, 3] 57 | num_filters = [64, 128, 256, 512] 58 | 59 | conv = self.conv_bn_layer( 60 | input=input, 61 | num_filters=32, 62 | filter_size=3, 63 | stride=2, 64 | act='relu', 65 | name='conv1_1') 66 | conv = self.conv_bn_layer( 67 | input=conv, 68 | num_filters=32, 69 | filter_size=3, 70 | stride=1, 71 | act='relu', 72 | name='conv1_2') 73 | conv = self.conv_bn_layer( 74 | input=conv, 75 | num_filters=64, 76 | filter_size=3, 77 | stride=1, 78 | act='relu', 79 | name='conv1_3') 80 | 81 | conv = fluid.layers.pool2d( 82 | input=conv, 83 | pool_size=3, 84 | pool_stride=2, 85 | pool_padding=1, 86 | pool_type='max') 87 | 88 | for block in range(len(depth)): 89 | for i in range(depth[block]): 90 | if layers in [101, 152] and block == 2: 91 | if i == 0: 92 | conv_name = "res" + str(block + 2) + "a" 93 | else: 94 | conv_name = "res" + str(block + 2) + "b" + str(i) 95 | else: 96 | conv_name = "res" + str(block + 2) + chr(97 + i) 97 | conv = self.bottleneck_block( 98 | input=conv, 99 | num_filters=num_filters[block], 100 | stride=2 if i == 0 and block != 0 else 1, 101 | name=conv_name) 102 | 103 | pool = fluid.layers.pool2d( 104 | input=conv, pool_type='avg', global_pooling=True) 105 | stdv = 1.0 / math.sqrt(pool.shape[1] * 1.0) 106 | out = fluid.layers.fc(input=pool, 107 | size=class_dim, 108 | param_attr=fluid.param_attr.ParamAttr( 109 | initializer=fluid.initializer.Uniform(-stdv, 110 | stdv))) 111 | return out 112 | 113 | def conv_bn_layer(self, 114 | input, 115 | num_filters, 116 | filter_size, 117 | stride=1, 118 | groups=1, 119 | act=None, 120 | name=None): 121 | conv = fluid.layers.conv2d( 122 | input=input, 123 | num_filters=num_filters, 124 | filter_size=filter_size, 125 | stride=stride, 126 | padding=(filter_size - 1) // 2, 127 | groups=groups, 128 | act=None, 129 | param_attr=ParamAttr(name=name + "_weights"), 130 | bias_attr=False, 131 | name=name + '.conv2d.output.1') 132 | if name == "conv1": 133 | bn_name = "bn_" + name 134 | else: 135 | bn_name = "bn" + name[3:] 136 | return fluid.layers.batch_norm( 137 | input=conv, 138 | act=act, 139 | name=bn_name + '.output.1', 140 | param_attr=ParamAttr(name=bn_name + '_scale'), 141 | bias_attr=ParamAttr(bn_name + '_offset'), 142 | moving_mean_name=bn_name + '_mean', 143 | moving_variance_name=bn_name + '_variance', ) 144 | 145 | def shortcut(self, input, ch_out, stride, name): 146 | ch_in = input.shape[1] 147 | if ch_in != ch_out or stride != 1: 148 | return self.conv_bn_layer(input, ch_out, 1, stride, name=name) 149 | else: 150 | return input 151 | 152 | def bottleneck_block(self, input, num_filters, stride, name): 153 | conv0 = self.conv_bn_layer( 154 | input=input, 155 | num_filters=num_filters, 156 | filter_size=1, 157 | act='relu', 158 | name=name + "_branch2a") 159 | conv1 = self.conv_bn_layer( 160 | input=conv0, 161 | num_filters=num_filters, 162 | filter_size=3, 163 | stride=stride, 164 | act='relu', 165 | name=name + "_branch2b") 166 | conv2 = self.conv_bn_layer( 167 | input=conv1, 168 | num_filters=num_filters * 4, 169 | filter_size=1, 170 | act=None, 171 | name=name + "_branch2c") 172 | 173 | short = self.shortcut( 174 | input, num_filters * 4, stride, name=name + "_branch1") 175 | 176 | return fluid.layers.elementwise_add( 177 | x=short, y=conv2, act='relu', name=name + ".add.output.5") 178 | 179 | 180 | def ResNet50_vc(): 181 | model = ResNet(layers=50) 182 | return model 183 | 184 | 185 | def ResNet101_vc(): 186 | model = ResNet(layers=101) 187 | return model 188 | 189 | 190 | def ResNet152_vc(): 191 | model = ResNet(layers=152) 192 | return model 193 | -------------------------------------------------------------------------------- /src/models/resnext.py: -------------------------------------------------------------------------------- 1 | #copyright (c) 2019 PaddlePaddle Authors. All Rights Reserve. 2 | # 3 | #Licensed under the Apache License, Version 2.0 (the "License"); 4 | #you may not use this file except in compliance with the License. 5 | #You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | #Unless required by applicable law or agreed to in writing, software 10 | #distributed under the License is distributed on an "AS IS" BASIS, 11 | #WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | #See the License for the specific language governing permissions and 13 | #limitations under the License. 14 | 15 | from __future__ import absolute_import 16 | from __future__ import division 17 | from __future__ import print_function 18 | 19 | import math 20 | 21 | import paddle 22 | import paddle.fluid as fluid 23 | from paddle.fluid.param_attr import ParamAttr 24 | 25 | __all__ = [ 26 | "ResNeXt", "ResNeXt50_64x4d", "ResNeXt101_64x4d", "ResNeXt152_64x4d", 27 | "ResNeXt50_32x4d", "ResNeXt101_32x4d", "ResNeXt152_32x4d" 28 | ] 29 | 30 | 31 | class ResNeXt(): 32 | def __init__(self, layers=50, cardinality=64): 33 | self.layers = layers 34 | self.cardinality = cardinality 35 | 36 | def net(self, input, class_dim=1000): 37 | layers = self.layers 38 | cardinality = self.cardinality 39 | supported_layers = [50, 101, 152] 40 | assert layers in supported_layers, \ 41 | "supported layers are {} but input layer is {}".format(supported_layers, layers) 42 | 43 | if layers == 50: 44 | depth = [3, 4, 6, 3] 45 | elif layers == 101: 46 | depth = [3, 4, 23, 3] 47 | elif layers == 152: 48 | depth = [3, 8, 36, 3] 49 | 50 | num_filters1 = [256, 512, 1024, 2048] 51 | num_filters2 = [128, 256, 512, 1024] 52 | 53 | conv = self.conv_bn_layer( 54 | input=input, 55 | num_filters=64, 56 | filter_size=7, 57 | stride=2, 58 | act='relu', 59 | name="res_conv1") #debug 60 | conv = fluid.layers.pool2d( 61 | input=conv, 62 | pool_size=3, 63 | pool_stride=2, 64 | pool_padding=1, 65 | pool_type='max') 66 | 67 | for block in range(len(depth)): 68 | for i in range(depth[block]): 69 | if layers in [101, 152] and block == 2: 70 | if i == 0: 71 | conv_name = "res" + str(block + 2) + "a" 72 | else: 73 | conv_name = "res" + str(block + 2) + "b" + str(i) 74 | else: 75 | conv_name = "res" + str(block + 2) + chr(97 + i) 76 | conv = self.bottleneck_block( 77 | input=conv, 78 | num_filters=num_filters1[block] 79 | if cardinality == 64 else num_filters2[block], 80 | stride=2 if i == 0 and block != 0 else 1, 81 | cardinality=cardinality, 82 | name=conv_name) 83 | 84 | pool = fluid.layers.pool2d( 85 | input=conv, pool_type='avg', global_pooling=True) 86 | stdv = 1.0 / math.sqrt(pool.shape[1] * 1.0) 87 | out = fluid.layers.fc( 88 | input=pool, 89 | size=class_dim, 90 | param_attr=fluid.param_attr.ParamAttr( 91 | initializer=fluid.initializer.Uniform(-stdv, stdv), 92 | name='fc_weights'), 93 | bias_attr=fluid.param_attr.ParamAttr(name='fc_offset')) 94 | return out 95 | 96 | def conv_bn_layer(self, 97 | input, 98 | num_filters, 99 | filter_size, 100 | stride=1, 101 | groups=1, 102 | act=None, 103 | name=None): 104 | conv = fluid.layers.conv2d( 105 | input=input, 106 | num_filters=num_filters, 107 | filter_size=filter_size, 108 | stride=stride, 109 | padding=(filter_size - 1) // 2, 110 | groups=groups, 111 | act=None, 112 | param_attr=ParamAttr(name=name + "_weights"), 113 | bias_attr=False, 114 | name=name + '.conv2d.output.1') 115 | if name == "conv1": 116 | bn_name = "bn_" + name 117 | else: 118 | bn_name = "bn" + name[3:] 119 | return fluid.layers.batch_norm( 120 | input=conv, 121 | act=act, 122 | name=bn_name + '.output.1', 123 | param_attr=ParamAttr(name=bn_name + '_scale'), 124 | bias_attr=ParamAttr(bn_name + '_offset'), 125 | moving_mean_name=bn_name + '_mean', 126 | moving_variance_name=bn_name + '_variance', ) 127 | 128 | def shortcut(self, input, ch_out, stride, name): 129 | ch_in = input.shape[1] 130 | if ch_in != ch_out or stride != 1: 131 | return self.conv_bn_layer(input, ch_out, 1, stride, name=name) 132 | else: 133 | return input 134 | 135 | def bottleneck_block(self, input, num_filters, stride, cardinality, name): 136 | cardinality = self.cardinality 137 | conv0 = self.conv_bn_layer( 138 | input=input, 139 | num_filters=num_filters, 140 | filter_size=1, 141 | act='relu', 142 | name=name + "_branch2a") 143 | conv1 = self.conv_bn_layer( 144 | input=conv0, 145 | num_filters=num_filters, 146 | filter_size=3, 147 | stride=stride, 148 | groups=cardinality, 149 | act='relu', 150 | name=name + "_branch2b") 151 | conv2 = self.conv_bn_layer( 152 | input=conv1, 153 | num_filters=num_filters if cardinality == 64 else num_filters * 2, 154 | filter_size=1, 155 | act=None, 156 | name=name + "_branch2c") 157 | 158 | short = self.shortcut( 159 | input, 160 | num_filters if cardinality == 64 else num_filters * 2, 161 | stride, 162 | name=name + "_branch1") 163 | 164 | return fluid.layers.elementwise_add( 165 | x=short, y=conv2, act='relu', name=name + ".add.output.5") 166 | 167 | 168 | def ResNeXt50_64x4d(): 169 | model = ResNeXt(layers=50, cardinality=64) 170 | return model 171 | 172 | 173 | def ResNeXt50_32x4d(): 174 | model = ResNeXt(layers=50, cardinality=32) 175 | return model 176 | 177 | 178 | def ResNeXt101_64x4d(): 179 | model = ResNeXt(layers=101, cardinality=64) 180 | return model 181 | 182 | 183 | def ResNeXt101_32x4d(): 184 | model = ResNeXt(layers=101, cardinality=32) 185 | return model 186 | 187 | 188 | def ResNeXt152_64x4d(): 189 | model = ResNeXt(layers=152, cardinality=64) 190 | return model 191 | 192 | 193 | def ResNeXt152_32x4d(): 194 | model = ResNeXt(layers=152, cardinality=32) 195 | return model 196 | -------------------------------------------------------------------------------- /src/models/mobilenet_v1.py: -------------------------------------------------------------------------------- 1 | #copyright (c) 2019 PaddlePaddle Authors. All Rights Reserve. 2 | # 3 | #Licensed under the Apache License, Version 2.0 (the "License"); 4 | #you may not use this file except in compliance with the License. 5 | #You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | #Unless required by applicable law or agreed to in writing, software 10 | #distributed under the License is distributed on an "AS IS" BASIS, 11 | #WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | #See the License for the specific language governing permissions and 13 | #limitations under the License. 14 | 15 | from __future__ import absolute_import 16 | from __future__ import division 17 | from __future__ import print_function 18 | 19 | import paddle.fluid as fluid 20 | from paddle.fluid.initializer import MSRA 21 | from paddle.fluid.param_attr import ParamAttr 22 | 23 | __all__ = [ 24 | 'MobileNetV1', 'MobileNetV1_x0_25', 'MobileNetV1_x0_5', 'MobileNetV1_x1_0', 25 | 'MobileNetV1_x0_75' 26 | ] 27 | 28 | 29 | class MobileNetV1(): 30 | def __init__(self, scale=1.0): 31 | self.scale = scale 32 | 33 | def net(self, input, class_dim=1000): 34 | scale = self.scale 35 | # conv1: 112x112 36 | input = self.conv_bn_layer( 37 | input, 38 | filter_size=3, 39 | channels=3, 40 | num_filters=int(32 * scale), 41 | stride=2, 42 | padding=1, 43 | name="conv1") 44 | 45 | # 56x56 46 | input = self.depthwise_separable( 47 | input, 48 | num_filters1=32, 49 | num_filters2=64, 50 | num_groups=32, 51 | stride=1, 52 | scale=scale, 53 | name="conv2_1") 54 | 55 | input = self.depthwise_separable( 56 | input, 57 | num_filters1=64, 58 | num_filters2=128, 59 | num_groups=64, 60 | stride=2, 61 | scale=scale, 62 | name="conv2_2") 63 | 64 | # 28x28 65 | input = self.depthwise_separable( 66 | input, 67 | num_filters1=128, 68 | num_filters2=128, 69 | num_groups=128, 70 | stride=1, 71 | scale=scale, 72 | name="conv3_1") 73 | 74 | input = self.depthwise_separable( 75 | input, 76 | num_filters1=128, 77 | num_filters2=256, 78 | num_groups=128, 79 | stride=2, 80 | scale=scale, 81 | name="conv3_2") 82 | 83 | # 14x14 84 | input = self.depthwise_separable( 85 | input, 86 | num_filters1=256, 87 | num_filters2=256, 88 | num_groups=256, 89 | stride=1, 90 | scale=scale, 91 | name="conv4_1") 92 | 93 | input = self.depthwise_separable( 94 | input, 95 | num_filters1=256, 96 | num_filters2=512, 97 | num_groups=256, 98 | stride=2, 99 | scale=scale, 100 | name="conv4_2") 101 | 102 | # 14x14 103 | for i in range(5): 104 | input = self.depthwise_separable( 105 | input, 106 | num_filters1=512, 107 | num_filters2=512, 108 | num_groups=512, 109 | stride=1, 110 | scale=scale, 111 | name="conv5" + "_" + str(i + 1)) 112 | # 7x7 113 | input = self.depthwise_separable( 114 | input, 115 | num_filters1=512, 116 | num_filters2=1024, 117 | num_groups=512, 118 | stride=2, 119 | scale=scale, 120 | name="conv5_6") 121 | 122 | input = self.depthwise_separable( 123 | input, 124 | num_filters1=1024, 125 | num_filters2=1024, 126 | num_groups=1024, 127 | stride=1, 128 | scale=scale, 129 | name="conv6") 130 | 131 | input = fluid.layers.pool2d( 132 | input=input, pool_type='avg', global_pooling=True) 133 | 134 | output = fluid.layers.fc(input=input, 135 | size=class_dim, 136 | param_attr=ParamAttr( 137 | initializer=MSRA(), name="fc7_weights"), 138 | bias_attr=ParamAttr(name="fc7_offset")) 139 | return output 140 | 141 | def conv_bn_layer(self, 142 | input, 143 | filter_size, 144 | num_filters, 145 | stride, 146 | padding, 147 | channels=None, 148 | num_groups=1, 149 | act='relu', 150 | use_cudnn=True, 151 | name=None): 152 | conv = fluid.layers.conv2d( 153 | input=input, 154 | num_filters=num_filters, 155 | filter_size=filter_size, 156 | stride=stride, 157 | padding=padding, 158 | groups=num_groups, 159 | act=None, 160 | use_cudnn=use_cudnn, 161 | param_attr=ParamAttr( 162 | initializer=MSRA(), name=name + "_weights"), 163 | bias_attr=False) 164 | bn_name = name + "_bn" 165 | return fluid.layers.batch_norm( 166 | input=conv, 167 | act=act, 168 | param_attr=ParamAttr(name=bn_name + "_scale"), 169 | bias_attr=ParamAttr(name=bn_name + "_offset"), 170 | moving_mean_name=bn_name + '_mean', 171 | moving_variance_name=bn_name + '_variance') 172 | 173 | def depthwise_separable(self, 174 | input, 175 | num_filters1, 176 | num_filters2, 177 | num_groups, 178 | stride, 179 | scale, 180 | name=None): 181 | depthwise_conv = self.conv_bn_layer( 182 | input=input, 183 | filter_size=3, 184 | num_filters=int(num_filters1 * scale), 185 | stride=stride, 186 | padding=1, 187 | num_groups=int(num_groups * scale), 188 | use_cudnn=False, 189 | name=name + "_dw") 190 | 191 | pointwise_conv = self.conv_bn_layer( 192 | input=depthwise_conv, 193 | filter_size=1, 194 | num_filters=int(num_filters2 * scale), 195 | stride=1, 196 | padding=0, 197 | name=name + "_sep") 198 | return pointwise_conv 199 | 200 | 201 | def MobileNetV1_x0_25(): 202 | model = MobileNetV1(scale=0.25) 203 | return model 204 | 205 | 206 | def MobileNetV1_x0_5(): 207 | model = MobileNetV1(scale=0.5) 208 | return model 209 | 210 | 211 | def MobileNetV1_x1_0(): 212 | model = MobileNetV1(scale=1.0) 213 | return model 214 | 215 | 216 | def MobileNetV1_x0_75(): 217 | model = MobileNetV1(scale=0.75) 218 | return model 219 | -------------------------------------------------------------------------------- /src/models/densenet.py: -------------------------------------------------------------------------------- 1 | #copyright (c) 2019 PaddlePaddle Authors. All Rights Reserve. 2 | # 3 | #Licensed under the Apache License, Version 2.0 (the "License"); 4 | #you may not use this file except in compliance with the License. 5 | #You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | #Unless required by applicable law or agreed to in writing, software 10 | #distributed under the License is distributed on an "AS IS" BASIS, 11 | #WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | #See the License for the specific language governing permissions and 13 | #limitations under the License. 14 | from __future__ import absolute_import 15 | from __future__ import division 16 | from __future__ import print_function 17 | 18 | import paddle 19 | import paddle.fluid as fluid 20 | import math 21 | from paddle.fluid.param_attr import ParamAttr 22 | 23 | __all__ = [ 24 | "DenseNet", "DenseNet121", "DenseNet161", "DenseNet169", "DenseNet201", 25 | "DenseNet264" 26 | ] 27 | 28 | 29 | class DenseNet(): 30 | def __init__(self, layers=121): 31 | self.layers = layers 32 | 33 | def net(self, input, bn_size=4, dropout=0, class_dim=1000): 34 | layers = self.layers 35 | supported_layers = [121, 161, 169, 201, 264] 36 | assert layers in supported_layers, \ 37 | "supported layers are {} but input layer is {}".format(supported_layers, layers) 38 | densenet_spec = { 39 | 121: (64, 32, [6, 12, 24, 16]), 40 | 161: (96, 48, [6, 12, 36, 24]), 41 | 169: (64, 32, [6, 12, 32, 32]), 42 | 201: (64, 32, [6, 12, 48, 32]), 43 | 264: (64, 32, [6, 12, 64, 48]) 44 | } 45 | 46 | num_init_features, growth_rate, block_config = densenet_spec[layers] 47 | conv = fluid.layers.conv2d( 48 | input=input, 49 | num_filters=num_init_features, 50 | filter_size=7, 51 | stride=2, 52 | padding=3, 53 | act=None, 54 | param_attr=ParamAttr(name="conv1_weights"), 55 | bias_attr=False) 56 | conv = fluid.layers.batch_norm( 57 | input=conv, 58 | act='relu', 59 | param_attr=ParamAttr(name='conv1_bn_scale'), 60 | bias_attr=ParamAttr(name='conv1_bn_offset'), 61 | moving_mean_name='conv1_bn_mean', 62 | moving_variance_name='conv1_bn_variance') 63 | conv = fluid.layers.pool2d( 64 | input=conv, 65 | pool_size=3, 66 | pool_stride=2, 67 | pool_padding=1, 68 | pool_type='max') 69 | num_features = num_init_features 70 | for i, num_layers in enumerate(block_config): 71 | conv = self.make_dense_block( 72 | conv, 73 | num_layers, 74 | bn_size, 75 | growth_rate, 76 | dropout, 77 | name='conv' + str(i + 2)) 78 | num_features = num_features + num_layers * growth_rate 79 | if i != len(block_config) - 1: 80 | conv = self.make_transition( 81 | conv, num_features // 2, name='conv' + str(i + 2) + '_blk') 82 | num_features = num_features // 2 83 | conv = fluid.layers.batch_norm( 84 | input=conv, 85 | act='relu', 86 | param_attr=ParamAttr(name='conv5_blk_bn_scale'), 87 | bias_attr=ParamAttr(name='conv5_blk_bn_offset'), 88 | moving_mean_name='conv5_blk_bn_mean', 89 | moving_variance_name='conv5_blk_bn_variance') 90 | conv = fluid.layers.pool2d( 91 | input=conv, pool_type='avg', global_pooling=True) 92 | stdv = 1.0 / math.sqrt(conv.shape[1] * 1.0) 93 | out = fluid.layers.fc( 94 | input=conv, 95 | size=class_dim, 96 | param_attr=fluid.param_attr.ParamAttr( 97 | initializer=fluid.initializer.Uniform(-stdv, stdv), 98 | name="fc_weights"), 99 | bias_attr=ParamAttr(name='fc_offset')) 100 | return out 101 | 102 | def make_transition(self, input, num_output_features, name=None): 103 | bn_ac = fluid.layers.batch_norm( 104 | input, 105 | act='relu', 106 | param_attr=ParamAttr(name=name + '_bn_scale'), 107 | bias_attr=ParamAttr(name + '_bn_offset'), 108 | moving_mean_name=name + '_bn_mean', 109 | moving_variance_name=name + '_bn_variance') 110 | 111 | bn_ac_conv = fluid.layers.conv2d( 112 | input=bn_ac, 113 | num_filters=num_output_features, 114 | filter_size=1, 115 | stride=1, 116 | act=None, 117 | bias_attr=False, 118 | param_attr=ParamAttr(name=name + "_weights")) 119 | pool = fluid.layers.pool2d( 120 | input=bn_ac_conv, pool_size=2, pool_stride=2, pool_type='avg') 121 | return pool 122 | 123 | def make_dense_block(self, 124 | input, 125 | num_layers, 126 | bn_size, 127 | growth_rate, 128 | dropout, 129 | name=None): 130 | conv = input 131 | for layer in range(num_layers): 132 | conv = self.make_dense_layer( 133 | conv, 134 | growth_rate, 135 | bn_size, 136 | dropout, 137 | name=name + '_' + str(layer + 1)) 138 | return conv 139 | 140 | def make_dense_layer(self, input, growth_rate, bn_size, dropout, name=None): 141 | bn_ac = fluid.layers.batch_norm( 142 | input, 143 | act='relu', 144 | param_attr=ParamAttr(name=name + '_x1_bn_scale'), 145 | bias_attr=ParamAttr(name + '_x1_bn_offset'), 146 | moving_mean_name=name + '_x1_bn_mean', 147 | moving_variance_name=name + '_x1_bn_variance') 148 | bn_ac_conv = fluid.layers.conv2d( 149 | input=bn_ac, 150 | num_filters=bn_size * growth_rate, 151 | filter_size=1, 152 | stride=1, 153 | act=None, 154 | bias_attr=False, 155 | param_attr=ParamAttr(name=name + "_x1_weights")) 156 | bn_ac = fluid.layers.batch_norm( 157 | bn_ac_conv, 158 | act='relu', 159 | param_attr=ParamAttr(name=name + '_x2_bn_scale'), 160 | bias_attr=ParamAttr(name + '_x2_bn_offset'), 161 | moving_mean_name=name + '_x2_bn_mean', 162 | moving_variance_name=name + '_x2_bn_variance') 163 | bn_ac_conv = fluid.layers.conv2d( 164 | input=bn_ac, 165 | num_filters=growth_rate, 166 | filter_size=3, 167 | stride=1, 168 | padding=1, 169 | act=None, 170 | bias_attr=False, 171 | param_attr=ParamAttr(name=name + "_x2_weights")) 172 | if dropout: 173 | bn_ac_conv = fluid.layers.dropout( 174 | x=bn_ac_conv, dropout_prob=dropout) 175 | bn_ac_conv = fluid.layers.concat([input, bn_ac_conv], axis=1) 176 | return bn_ac_conv 177 | 178 | 179 | def DenseNet121(): 180 | model = DenseNet(layers=121) 181 | return model 182 | 183 | 184 | def DenseNet161(): 185 | model = DenseNet(layers=161) 186 | return model 187 | 188 | 189 | def DenseNet169(): 190 | model = DenseNet(layers=169) 191 | return model 192 | 193 | 194 | def DenseNet201(): 195 | model = DenseNet(layers=201) 196 | return model 197 | 198 | 199 | def DenseNet264(): 200 | model = DenseNet(layers=264) 201 | return model 202 | -------------------------------------------------------------------------------- /src/models/mobilenet_v2.py: -------------------------------------------------------------------------------- 1 | #copyright (c) 2019 PaddlePaddle Authors. All Rights Reserve. 2 | # 3 | #Licensed under the Apache License, Version 2.0 (the "License"); 4 | #you may not use this file except in compliance with the License. 5 | #You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | #Unless required by applicable law or agreed to in writing, software 10 | #distributed under the License is distributed on an "AS IS" BASIS, 11 | #WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | #See the License for the specific language governing permissions and 13 | #limitations under the License. 14 | 15 | from __future__ import absolute_import 16 | from __future__ import division 17 | from __future__ import print_function 18 | import paddle.fluid as fluid 19 | from paddle.fluid.initializer import MSRA 20 | from paddle.fluid.param_attr import ParamAttr 21 | 22 | __all__ = [ 23 | 'MobileNetV2_x0_25', 'MobileNetV2_x0_5' 24 | 'MobileNetV2_x0_75', 'MobileNetV2_x1_0', 'MobileNetV2_x1_5', 25 | 'MobileNetV2_x2_0', 'MobileNetV2' 26 | ] 27 | 28 | 29 | class MobileNetV2(): 30 | def __init__(self, scale=1.0): 31 | self.scale = scale 32 | 33 | def net(self, input, class_dim=1000): 34 | scale = self.scale 35 | bottleneck_params_list = [ 36 | (1, 16, 1, 1), 37 | (6, 24, 2, 2), 38 | (6, 32, 3, 2), 39 | (6, 64, 4, 2), 40 | (6, 96, 3, 1), 41 | (6, 160, 3, 2), 42 | (6, 320, 1, 1), 43 | ] 44 | 45 | #conv1 46 | input = self.conv_bn_layer( 47 | input, 48 | num_filters=int(32 * scale), 49 | filter_size=3, 50 | stride=2, 51 | padding=1, 52 | if_act=True, 53 | name='conv1_1') 54 | 55 | # bottleneck sequences 56 | i = 1 57 | in_c = int(32 * scale) 58 | for layer_setting in bottleneck_params_list: 59 | t, c, n, s = layer_setting 60 | i += 1 61 | input = self.invresi_blocks( 62 | input=input, 63 | in_c=in_c, 64 | t=t, 65 | c=int(c * scale), 66 | n=n, 67 | s=s, 68 | name='conv' + str(i)) 69 | in_c = int(c * scale) 70 | #last_conv 71 | input = self.conv_bn_layer( 72 | input=input, 73 | num_filters=int(1280 * scale) if scale > 1.0 else 1280, 74 | filter_size=1, 75 | stride=1, 76 | padding=0, 77 | if_act=True, 78 | name='conv9') 79 | 80 | input = fluid.layers.pool2d( 81 | input=input, pool_type='avg', global_pooling=True) 82 | 83 | output = fluid.layers.fc(input=input, 84 | size=class_dim, 85 | param_attr=ParamAttr(name='fc10_weights'), 86 | bias_attr=ParamAttr(name='fc10_offset')) 87 | return output 88 | 89 | def conv_bn_layer(self, 90 | input, 91 | filter_size, 92 | num_filters, 93 | stride, 94 | padding, 95 | channels=None, 96 | num_groups=1, 97 | if_act=True, 98 | name=None, 99 | use_cudnn=True): 100 | conv = fluid.layers.conv2d( 101 | input=input, 102 | num_filters=num_filters, 103 | filter_size=filter_size, 104 | stride=stride, 105 | padding=padding, 106 | groups=num_groups, 107 | act=None, 108 | use_cudnn=use_cudnn, 109 | param_attr=ParamAttr(name=name + '_weights'), 110 | bias_attr=False) 111 | bn_name = name + '_bn' 112 | bn = fluid.layers.batch_norm( 113 | input=conv, 114 | param_attr=ParamAttr(name=bn_name + "_scale"), 115 | bias_attr=ParamAttr(name=bn_name + "_offset"), 116 | moving_mean_name=bn_name + '_mean', 117 | moving_variance_name=bn_name + '_variance') 118 | if if_act: 119 | return fluid.layers.relu6(bn) 120 | else: 121 | return bn 122 | 123 | def shortcut(self, input, data_residual): 124 | return fluid.layers.elementwise_add(input, data_residual) 125 | 126 | def inverted_residual_unit(self, 127 | input, 128 | num_in_filter, 129 | num_filters, 130 | ifshortcut, 131 | stride, 132 | filter_size, 133 | padding, 134 | expansion_factor, 135 | name=None): 136 | num_expfilter = int(round(num_in_filter * expansion_factor)) 137 | 138 | channel_expand = self.conv_bn_layer( 139 | input=input, 140 | num_filters=num_expfilter, 141 | filter_size=1, 142 | stride=1, 143 | padding=0, 144 | num_groups=1, 145 | if_act=True, 146 | name=name + '_expand') 147 | 148 | bottleneck_conv = self.conv_bn_layer( 149 | input=channel_expand, 150 | num_filters=num_expfilter, 151 | filter_size=filter_size, 152 | stride=stride, 153 | padding=padding, 154 | num_groups=num_expfilter, 155 | if_act=True, 156 | name=name + '_dwise', 157 | use_cudnn=False) 158 | 159 | linear_out = self.conv_bn_layer( 160 | input=bottleneck_conv, 161 | num_filters=num_filters, 162 | filter_size=1, 163 | stride=1, 164 | padding=0, 165 | num_groups=1, 166 | if_act=False, 167 | name=name + '_linear') 168 | if ifshortcut: 169 | out = self.shortcut(input=input, data_residual=linear_out) 170 | return out 171 | else: 172 | return linear_out 173 | 174 | def invresi_blocks(self, input, in_c, t, c, n, s, name=None): 175 | first_block = self.inverted_residual_unit( 176 | input=input, 177 | num_in_filter=in_c, 178 | num_filters=c, 179 | ifshortcut=False, 180 | stride=s, 181 | filter_size=3, 182 | padding=1, 183 | expansion_factor=t, 184 | name=name + '_1') 185 | 186 | last_residual_block = first_block 187 | last_c = c 188 | 189 | for i in range(1, n): 190 | last_residual_block = self.inverted_residual_unit( 191 | input=last_residual_block, 192 | num_in_filter=last_c, 193 | num_filters=c, 194 | ifshortcut=True, 195 | stride=1, 196 | filter_size=3, 197 | padding=1, 198 | expansion_factor=t, 199 | name=name + '_' + str(i + 1)) 200 | return last_residual_block 201 | 202 | 203 | def MobileNetV2_x0_25(): 204 | model = MobileNetV2(scale=0.25) 205 | return model 206 | 207 | 208 | def MobileNetV2_x0_5(): 209 | model = MobileNetV2(scale=0.5) 210 | return model 211 | 212 | 213 | def MobileNetV2_x0_75(): 214 | model = MobileNetV2(scale=0.75) 215 | return model 216 | 217 | 218 | def MobileNetV2_x1_0(): 219 | model = MobileNetV2(scale=1.0) 220 | return model 221 | 222 | 223 | def MobileNetV2_x1_5(): 224 | model = MobileNetV2(scale=1.5) 225 | return model 226 | 227 | 228 | def MobileNetV2_x2_0(): 229 | model = MobileNetV2(scale=2.0) 230 | return model 231 | -------------------------------------------------------------------------------- /src/models/res2net.py: -------------------------------------------------------------------------------- 1 | #copyright (c) 2019 PaddlePaddle Authors. All Rights Reserve. 2 | # 3 | #Licensed under the Apache License, Version 2.0 (the "License"); 4 | #you may not use this file except in compliance with the License. 5 | #You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | #Unless required by applicable law or agreed to in writing, software 10 | #distributed under the License is distributed on an "AS IS" BASIS, 11 | #WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | #See the License for the specific language governing permissions and 13 | #limitations under the License. 14 | 15 | from __future__ import absolute_import 16 | from __future__ import division 17 | from __future__ import print_function 18 | 19 | import paddle 20 | import paddle.fluid as fluid 21 | import math 22 | from paddle.fluid.param_attr import ParamAttr 23 | 24 | __all__ = ["Res2Net", "Res2Net50_48w_2s", "Res2Net50_26w_4s", "Res2Net50_14w_8s", "Res2Net50_26w_6s", "Res2Net50_26w_8s", 25 | "Res2Net101_26w_4s", "Res2Net152_26w_4s"] 26 | 27 | 28 | class Res2Net(): 29 | 30 | def __init__(self, layers=50, scales=4, width=26): 31 | self.layers = layers 32 | self.scales = scales 33 | self.width = width 34 | 35 | def net(self, input, class_dim=1000): 36 | layers = self.layers 37 | supported_layers = [50, 101, 152] 38 | assert layers in supported_layers, \ 39 | "supported layers are {} but input layer is {}".format(supported_layers, layers) 40 | basic_width = self.width * self.scales 41 | num_filters1 = [basic_width * t for t in [1, 2, 4, 8]] 42 | num_filters2 = [256 * t for t in [1, 2, 4, 8]] 43 | 44 | if layers == 50: 45 | depth = [3, 4, 6, 3] 46 | elif layers == 101: 47 | depth = [3, 4, 23, 3] 48 | elif layers == 152: 49 | depth = [3, 8, 36, 3] 50 | conv = self.conv_bn_layer( 51 | input=input, num_filters=64, filter_size=7, stride=2, act='relu', name="conv1") 52 | 53 | 54 | conv = fluid.layers.pool2d( 55 | input=conv, pool_size=3, pool_stride=2, pool_padding=1, pool_type='max') 56 | 57 | for block in range(len(depth)): 58 | for i in range(depth[block]): 59 | if layers in [101, 152] and block == 2: 60 | if i == 0: 61 | conv_name = "res" + str(block+2) + "a" 62 | else: 63 | conv_name = "res" + str(block+2) + "b" + str(i) 64 | else: 65 | conv_name = "res" + str(block+2) + chr(97+i) 66 | conv = self.bottleneck_block( 67 | input=conv, 68 | num_filters1=num_filters1[block], 69 | num_filters2=num_filters2[block], 70 | stride=2 if i==0 and block !=0 else 1, name=conv_name) 71 | pool = fluid.layers.pool2d( 72 | input=conv, pool_size=7, pool_stride=1, pool_type='avg', global_pooling=True) 73 | 74 | stdv = 1.0 / math.sqrt(pool.shape[1] * 1.0) 75 | out = fluid.layers.fc( 76 | input=pool, 77 | size=class_dim, 78 | param_attr=fluid.param_attr.ParamAttr( 79 | initializer=fluid.initializer.Uniform(-stdv, stdv),name='fc_weights'), 80 | bias_attr=fluid.param_attr.ParamAttr(name='fc_offset')) 81 | return out 82 | 83 | 84 | def conv_bn_layer(self, 85 | input, 86 | num_filters, 87 | filter_size, 88 | stride=1, 89 | groups=1, 90 | act=None, 91 | name=None): 92 | conv = fluid.layers.conv2d( 93 | input=input, 94 | num_filters=num_filters, 95 | filter_size=filter_size, 96 | stride=stride, 97 | padding=(filter_size - 1)//2, 98 | groups=groups, 99 | act=None, 100 | param_attr=ParamAttr(name=name + "_weights"), 101 | bias_attr=False) 102 | 103 | if name == "conv1": 104 | bn_name = "bn_" + name 105 | else: 106 | bn_name = "bn" + name[3:] 107 | 108 | return fluid.layers.batch_norm(input=conv, 109 | act=act, 110 | param_attr=ParamAttr(name=bn_name+'_scale'), 111 | bias_attr=ParamAttr(bn_name+'_offset'), 112 | moving_mean_name=bn_name+'_mean', 113 | moving_variance_name=bn_name+'_variance') 114 | 115 | 116 | def shortcut(self, input, ch_out, stride, name): 117 | ch_in = input.shape[1] 118 | if ch_in != ch_out or stride != 1: 119 | return self.conv_bn_layer(input, ch_out, 1, stride, name=name) 120 | else: 121 | return input 122 | 123 | 124 | def bottleneck_block(self, input, num_filters1, num_filters2, stride, name): 125 | conv0 = self.conv_bn_layer( 126 | input=input, 127 | num_filters=num_filters1, 128 | filter_size=1, 129 | stride=1, 130 | act='relu', 131 | name=name+'_branch2a') 132 | xs = fluid.layers.split(conv0, self.scales, 1) 133 | ys = [] 134 | for s in range(self.scales - 1): 135 | if s == 0 or stride == 2: 136 | ys.append(self.conv_bn_layer(input=xs[s], 137 | num_filters=num_filters1//self.scales, 138 | stride=stride, 139 | filter_size=3, 140 | act='relu', 141 | name=name+'_branch2b_'+str(s+1))) 142 | else: 143 | ys.append(self.conv_bn_layer(input=xs[s]+ys[-1], 144 | num_filters=num_filters1//self.scales, 145 | stride=stride, 146 | filter_size=3, 147 | act='relu', 148 | name=name+'_branch2b_'+str(s+1))) 149 | if stride == 1: 150 | ys.append(xs[-1]) 151 | else: 152 | ys.append(fluid.layers.pool2d(input=xs[-1], 153 | pool_size=3, 154 | pool_stride=stride, 155 | pool_padding=1, 156 | pool_type='avg')) 157 | 158 | conv1 = fluid.layers.concat(ys, axis=1) 159 | conv2 = self.conv_bn_layer( 160 | input=conv1, num_filters=num_filters2, filter_size=1, act=None, name=name+"_branch2c") 161 | 162 | short = self.shortcut(input, num_filters2, stride, name=name+"_branch1") 163 | 164 | return fluid.layers.elementwise_add(x=short, y=conv2, act='relu') 165 | 166 | 167 | 168 | def Res2Net50_48w_2s(): 169 | model = Res2Net(layers=50, scales=2, width=48) 170 | return model 171 | 172 | 173 | def Res2Net50_26w_4s(): 174 | model = Res2Net(layers=50, scales=4, width=26) 175 | return model 176 | 177 | 178 | def Res2Net50_14w_8s(): 179 | model = Res2Net(layers=50, scales=8, width=14) 180 | return model 181 | 182 | 183 | def Res2Net50_26w_6s(): 184 | model = Res2Net(layers=50, scales=6, width=26) 185 | return model 186 | 187 | 188 | def Res2Net50_26w_8s(): 189 | model = Res2Net(layers=50, scales=8, width=26) 190 | return model 191 | 192 | 193 | def Res2Net101_26w_4s(): 194 | model = Res2Net(layers=101, scales=4, width=26) 195 | return model 196 | 197 | 198 | def Res2Net152_26w_4s(): 199 | model = Res2Net(layers=152, scales=4, width=26) 200 | return model 201 | -------------------------------------------------------------------------------- /src/models/resnet.py: -------------------------------------------------------------------------------- 1 | #copyright (c) 2019 PaddlePaddle Authors. All Rights Reserve. 2 | # 3 | #Licensed under the Apache License, Version 2.0 (the "License"); 4 | #you may not use this file except in compliance with the License. 5 | #You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | #Unless required by applicable law or agreed to in writing, software 10 | #distributed under the License is distributed on an "AS IS" BASIS, 11 | #WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | #See the License for the specific language governing permissions and 13 | #limitations under the License. 14 | 15 | from __future__ import absolute_import 16 | from __future__ import division 17 | from __future__ import print_function 18 | 19 | import math 20 | 21 | import paddle 22 | import paddle.fluid as fluid 23 | from paddle.fluid.param_attr import ParamAttr 24 | 25 | __all__ = [ 26 | "ResNet", "ResNet18", "ResNet34", "ResNet50", "ResNet101", "ResNet152" 27 | ] 28 | 29 | 30 | class ResNet(): 31 | def __init__(self, layers=50): 32 | self.layers = layers 33 | 34 | def net(self, input, class_dim=1000): 35 | layers = self.layers 36 | supported_layers = [18, 34, 50, 101, 152] 37 | assert layers in supported_layers, \ 38 | "supported layers are {} but input layer is {}".format(supported_layers, layers) 39 | 40 | if layers == 18: 41 | depth = [2, 2, 2, 2] 42 | elif layers == 34 or layers == 50: 43 | depth = [3, 4, 6, 3] 44 | elif layers == 101: 45 | depth = [3, 4, 23, 3] 46 | elif layers == 152: 47 | depth = [3, 8, 36, 3] 48 | num_filters = [64, 128, 256, 512] 49 | 50 | conv = self.conv_bn_layer( 51 | input=input, 52 | num_filters=64, 53 | filter_size=7, 54 | stride=2, 55 | act='relu', 56 | name="conv1") 57 | conv = fluid.layers.pool2d( 58 | input=conv, 59 | pool_size=3, 60 | pool_stride=2, 61 | pool_padding=1, 62 | pool_type='max') 63 | if layers >= 50: 64 | for block in range(len(depth)): 65 | for i in range(depth[block]): 66 | if layers in [101, 152] and block == 2: 67 | if i == 0: 68 | conv_name = "res" + str(block + 2) + "a" 69 | else: 70 | conv_name = "res" + str(block + 2) + "b" + str(i) 71 | else: 72 | conv_name = "res" + str(block + 2) + chr(97 + i) 73 | conv = self.bottleneck_block( 74 | input=conv, 75 | num_filters=num_filters[block], 76 | stride=2 if i == 0 and block != 0 else 1, 77 | name=conv_name) 78 | 79 | pool = fluid.layers.pool2d( 80 | input=conv, pool_type='avg', global_pooling=True) 81 | stdv = 1.0 / math.sqrt(pool.shape[1] * 1.0) 82 | out = fluid.layers.fc( 83 | input=pool, 84 | size=class_dim, 85 | # param_attr=fluid.param_attr.ParamAttr( 86 | # initializer=fluid.initializer.Uniform(-stdv, stdv))) 87 | param_attr=fluid.param_attr.ParamAttr( 88 | initializer=fluid.initializer.Uniform(-stdv, stdv), name='fc_weights'), 89 | bias_attr=fluid.param_attr.ParamAttr(name='fc_offset')) 90 | else: 91 | for block in range(len(depth)): 92 | for i in range(depth[block]): 93 | conv_name = "res" + str(block + 2) + chr(97 + i) 94 | conv = self.basic_block( 95 | input=conv, 96 | num_filters=num_filters[block], 97 | stride=2 if i == 0 and block != 0 else 1, 98 | is_first=block == i == 0, 99 | name=conv_name) 100 | 101 | pool = fluid.layers.pool2d( 102 | input=conv, pool_type='avg', global_pooling=True) 103 | stdv = 1.0 / math.sqrt(pool.shape[1] * 1.0) 104 | out = fluid.layers.fc( 105 | input=pool, 106 | size=class_dim, 107 | # param_attr=fluid.param_attr.ParamAttr( 108 | # initializer=fluid.initializer.Uniform(-stdv, stdv))) 109 | param_attr=fluid.param_attr.ParamAttr( 110 | initializer=fluid.initializer.Uniform(-stdv, stdv), name='fc_weights'), 111 | bias_attr=fluid.param_attr.ParamAttr(name='fc_offset')) 112 | return out 113 | 114 | def conv_bn_layer(self, 115 | input, 116 | num_filters, 117 | filter_size, 118 | stride=1, 119 | groups=1, 120 | act=None, 121 | name=None): 122 | conv = fluid.layers.conv2d( 123 | input=input, 124 | num_filters=num_filters, 125 | filter_size=filter_size, 126 | stride=stride, 127 | padding=(filter_size - 1) // 2, 128 | groups=groups, 129 | act=None, 130 | param_attr=ParamAttr(name=name + "_weights"), 131 | bias_attr=False, 132 | name=name + '.conv2d.output.1') 133 | 134 | if name == "conv1": 135 | bn_name = "bn_" + name 136 | else: 137 | bn_name = "bn" + name[3:] 138 | return fluid.layers.batch_norm( 139 | input=conv, 140 | act=act, 141 | name=bn_name + '.output.1', 142 | param_attr=ParamAttr(name=bn_name + '_scale'), 143 | bias_attr=ParamAttr(bn_name + '_offset'), 144 | moving_mean_name=bn_name + '_mean', 145 | moving_variance_name=bn_name + '_variance', ) 146 | 147 | def shortcut(self, input, ch_out, stride, is_first, name): 148 | ch_in = input.shape[1] 149 | if ch_in != ch_out or stride != 1 or is_first == True: 150 | return self.conv_bn_layer(input, ch_out, 1, stride, name=name) 151 | else: 152 | return input 153 | 154 | def bottleneck_block(self, input, num_filters, stride, name): 155 | conv0 = self.conv_bn_layer( 156 | input=input, 157 | num_filters=num_filters, 158 | filter_size=1, 159 | act='relu', 160 | name=name + "_branch2a") 161 | conv1 = self.conv_bn_layer( 162 | input=conv0, 163 | num_filters=num_filters, 164 | filter_size=3, 165 | stride=stride, 166 | act='relu', 167 | name=name + "_branch2b") 168 | conv2 = self.conv_bn_layer( 169 | input=conv1, 170 | num_filters=num_filters * 4, 171 | filter_size=1, 172 | act=None, 173 | name=name + "_branch2c") 174 | 175 | short = self.shortcut( 176 | input, 177 | num_filters * 4, 178 | stride, 179 | is_first=False, 180 | name=name + "_branch1") 181 | 182 | return fluid.layers.elementwise_add( 183 | x=short, y=conv2, act='relu', name=name + ".add.output.5") 184 | 185 | def basic_block(self, input, num_filters, stride, is_first, name): 186 | conv0 = self.conv_bn_layer( 187 | input=input, 188 | num_filters=num_filters, 189 | filter_size=3, 190 | act='relu', 191 | stride=stride, 192 | name=name + "_branch2a") 193 | conv1 = self.conv_bn_layer( 194 | input=conv0, 195 | num_filters=num_filters, 196 | filter_size=3, 197 | act=None, 198 | name=name + "_branch2b") 199 | short = self.shortcut( 200 | input, num_filters, stride, is_first, name=name + "_branch1") 201 | return fluid.layers.elementwise_add(x=short, y=conv1, act='relu') 202 | 203 | 204 | def ResNet18(): 205 | model = ResNet(layers=18) 206 | return model 207 | 208 | 209 | def ResNet34(): 210 | model = ResNet(layers=34) 211 | return model 212 | 213 | 214 | def ResNet50(): 215 | model = ResNet(layers=50) 216 | return model 217 | 218 | 219 | def ResNet101(): 220 | model = ResNet(layers=101) 221 | return model 222 | 223 | 224 | def ResNet152(): 225 | model = ResNet(layers=152) 226 | return model 227 | -------------------------------------------------------------------------------- /src/models/layers.py: -------------------------------------------------------------------------------- 1 | from __future__ import absolute_import 2 | from __future__ import division 3 | from __future__ import print_function 4 | import paddle.fluid as fluid 5 | import math 6 | import warnings 7 | 8 | def initial_type(name, 9 | input, 10 | op_type, 11 | fan_out, 12 | init="google", 13 | use_bias=False, 14 | filter_size=0, 15 | stddev=0.02): 16 | if init == "kaiming": 17 | if op_type == 'conv': 18 | fan_in = input.shape[1] * filter_size * filter_size 19 | elif op_type == 'deconv': 20 | fan_in = fan_out * filter_size * filter_size 21 | else: 22 | if len(input.shape) > 2: 23 | fan_in = input.shape[1] * input.shape[2] * input.shape[3] 24 | else: 25 | fan_in = input.shape[1] 26 | bound = 1 / math.sqrt(fan_in) 27 | param_attr = fluid.ParamAttr( 28 | name=name + "_weights", 29 | initializer=fluid.initializer.Uniform( 30 | low=-bound, high=bound)) 31 | if use_bias == True: 32 | bias_attr = fluid.ParamAttr( 33 | name=name + '_offset', 34 | initializer=fluid.initializer.Uniform( 35 | low=-bound, high=bound)) 36 | else: 37 | bias_attr = False 38 | elif init == 'google': 39 | n = filter_size * filter_size * fan_out 40 | param_attr = fluid.ParamAttr( 41 | name=name + "_weights", 42 | initializer=fluid.initializer.NormalInitializer( 43 | loc=0.0, scale=math.sqrt(2.0 / n))) 44 | if use_bias == True: 45 | bias_attr = fluid.ParamAttr( 46 | name=name + "_offset", initializer=fluid.initializer.Constant(0.0)) 47 | else: 48 | bias_attr = False 49 | 50 | else: 51 | param_attr = fluid.ParamAttr( 52 | name=name + "_weights", 53 | initializer=fluid.initializer.NormalInitializer( 54 | loc=0.0, scale=stddev)) 55 | if use_bias == True: 56 | bias_attr = fluid.ParamAttr( 57 | name=name + "_offset", initializer=fluid.initializer.Constant(0.0)) 58 | else: 59 | bias_attr = False 60 | return param_attr, bias_attr 61 | 62 | def cal_padding(img_size, stride, filter_size, dilation=1): 63 | """Calculate padding size.""" 64 | if img_size % stride == 0: 65 | out_size = max(filter_size - stride, 0) 66 | else: 67 | out_size = max(filter_size - (img_size % stride), 0) 68 | return out_size // 2, out_size - out_size // 2 69 | 70 | def init_batch_norm_layer(name="batch_norm"): 71 | param_attr = fluid.ParamAttr( 72 | name=name + '_scale', initializer=fluid.initializer.Constant(1.0)) 73 | bias_attr = fluid.ParamAttr( 74 | name=name + '_offset', initializer=fluid.initializer.Constant(value=0.0)) 75 | return param_attr, bias_attr 76 | 77 | def init_fc_layer(fout, name='fc'): 78 | n = fout # fan-out 79 | init_range = 1.0 / math.sqrt(n) 80 | 81 | param_attr = fluid.ParamAttr( 82 | name=name + '_weights', initializer=fluid.initializer.UniformInitializer( 83 | low=-init_range, high=init_range)) 84 | bias_attr = fluid.ParamAttr( 85 | name=name + '_offset', initializer=fluid.initializer.Constant(value=0.0)) 86 | return param_attr, bias_attr 87 | 88 | def norm_layer(input, norm_type='batch_norm', name=None): 89 | if norm_type == 'batch_norm': 90 | param_attr = fluid.ParamAttr( 91 | name=name + '_weights', initializer=fluid.initializer.Constant(1.0)) 92 | bias_attr = fluid.ParamAttr( 93 | name=name + '_offset', initializer=fluid.initializer.Constant(value=0.0)) 94 | return fluid.layers.batch_norm( 95 | input, 96 | param_attr=param_attr, 97 | bias_attr=bias_attr, 98 | moving_mean_name=name + '_mean', 99 | moving_variance_name=name + '_variance') 100 | 101 | elif norm_type == 'instance_norm': 102 | helper = fluid.layer_helper.LayerHelper("instance_norm", **locals()) 103 | dtype = helper.input_dtype() 104 | epsilon = 1e-5 105 | mean = fluid.layers.reduce_mean(input, dim=[2, 3], keep_dim=True) 106 | var = fluid.layers.reduce_mean( 107 | fluid.layers.square(input - mean), dim=[2, 3], keep_dim=True) 108 | if name is not None: 109 | scale_name = name + "_scale" 110 | offset_name = name + "_offset" 111 | scale_param = fluid.ParamAttr( 112 | name=scale_name, 113 | initializer=fluid.initializer.Constant(1.0), 114 | trainable=True) 115 | offset_param = fluid.ParamAttr( 116 | name=offset_name, 117 | initializer=fluid.initializer.Constant(0.0), 118 | trainable=True) 119 | scale = helper.create_parameter( 120 | attr=scale_param, shape=input.shape[1:2], dtype=dtype) 121 | offset = helper.create_parameter( 122 | attr=offset_param, shape=input.shape[1:2], dtype=dtype) 123 | 124 | tmp = fluid.layers.elementwise_mul(x=(input - mean), y=scale, axis=1) 125 | tmp = tmp / fluid.layers.sqrt(var + epsilon) 126 | tmp = fluid.layers.elementwise_add(tmp, offset, axis=1) 127 | return tmp 128 | else: 129 | raise NotImplementedError("norm tyoe: [%s] is not support" % norm_type) 130 | 131 | 132 | def conv2d(input, 133 | num_filters=64, 134 | filter_size=7, 135 | stride=1, 136 | stddev=0.02, 137 | padding=0, 138 | groups=None, 139 | name="conv2d", 140 | norm=None, 141 | act=None, 142 | relufactor=0.0, 143 | use_bias=False, 144 | padding_type=None, 145 | initial="normal", 146 | use_cudnn=True): 147 | 148 | if padding != 0 and padding_type != None: 149 | warnings.warn( 150 | 'padding value and padding type are set in the same time, and the final padding width and padding height are computed by padding_type' 151 | ) 152 | 153 | param_attr, bias_attr = initial_type( 154 | name=name, 155 | input=input, 156 | op_type='conv', 157 | fan_out=num_filters, 158 | init=initial, 159 | use_bias=use_bias, 160 | filter_size=filter_size, 161 | stddev=stddev) 162 | 163 | def get_padding(filter_size, stride=1, dilation=1): 164 | padding = ((stride - 1) + dilation * (filter_size - 1)) // 2 165 | return padding 166 | 167 | need_crop = False 168 | if padding_type == "SAME": 169 | top_padding, bottom_padding = cal_padding(input.shape[2], stride, 170 | filter_size) 171 | left_padding, right_padding = cal_padding(input.shape[2], stride, 172 | filter_size) 173 | height_padding = bottom_padding 174 | width_padding = right_padding 175 | if top_padding != bottom_padding or left_padding != right_padding: 176 | height_padding = top_padding + stride 177 | width_padding = left_padding + stride 178 | need_crop = True 179 | padding = [height_padding, width_padding] 180 | elif padding_type == "VALID": 181 | height_padding = 0 182 | width_padding = 0 183 | padding = [height_padding, width_padding] 184 | elif padding_type == "DYNAMIC": 185 | padding = get_padding(filter_size, stride) 186 | else: 187 | padding = padding 188 | 189 | conv = fluid.layers.conv2d( 190 | input, 191 | num_filters, 192 | filter_size, 193 | groups=groups, 194 | name=name, 195 | stride=stride, 196 | padding=padding, 197 | use_cudnn=use_cudnn, 198 | param_attr=param_attr, 199 | bias_attr=bias_attr) 200 | 201 | if need_crop: 202 | conv = conv[:, :, 1:, 1:] 203 | 204 | if norm is not None: 205 | conv = norm_layer(input=conv, norm_type=norm, name=name + "_norm") 206 | if act == 'relu': 207 | conv = fluid.layers.relu(conv, name=name + '_relu') 208 | elif act == 'leaky_relu': 209 | conv = fluid.layers.leaky_relu( 210 | conv, alpha=relufactor, name=name + '_leaky_relu') 211 | elif act == 'tanh': 212 | conv = fluid.layers.tanh(conv, name=name + '_tanh') 213 | elif act == 'sigmoid': 214 | conv = fluid.layers.sigmoid(conv, name=name + '_sigmoid') 215 | elif act == 'swish': 216 | conv = fluid.layers.swish(conv, name=name + '_swish') 217 | elif act == None: 218 | conv = conv 219 | else: 220 | raise NotImplementedError("activation: [%s] is not support" %act) 221 | 222 | return conv -------------------------------------------------------------------------------- /src/models/mobilenet_v2_old.py: -------------------------------------------------------------------------------- 1 | # copyright (c) 2019 PaddlePaddle Authors. All Rights Reserve. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | from __future__ import absolute_import 16 | from __future__ import division 17 | from __future__ import print_function 18 | import paddle.fluid as fluid 19 | from paddle.fluid.initializer import MSRA 20 | from paddle.fluid.param_attr import ParamAttr 21 | 22 | __all__ = ['MobileNetV2', 'MobileNetV2_x0_25, ''MobileNetV2_x0_5', 'MobileNetV2_x1_0', 'MobileNetV2_x1_5', 23 | 'MobileNetV2_x2_0', 24 | 'MobileNetV2_scale'] 25 | 26 | train_parameters = { 27 | "input_size": [3, 224, 224], 28 | "input_mean": [0.485, 0.456, 0.406], 29 | "input_std": [0.229, 0.224, 0.225], 30 | "learning_strategy": { 31 | "name": "piecewise_decay", 32 | "batch_size": 256, 33 | "epochs": [30, 60, 90], 34 | "steps": [0.1, 0.01, 0.001, 0.0001] 35 | } 36 | } 37 | 38 | 39 | class MobileNetV2(): 40 | def __init__(self, scale=1.0, change_depth=False): 41 | self.params = train_parameters 42 | self.scale = scale 43 | self.change_depth = change_depth 44 | 45 | def net(self, input, class_dim=1000): 46 | scale = self.scale 47 | change_depth = self.change_depth 48 | # if change_depth is True, the new depth is 1.4 times as deep as before. 49 | bottleneck_params_list = [ 50 | # (1, 16, 1, 1), 51 | # (6, 24, 2, 2), 52 | # (6, 32, 3, 2), 53 | # (6, 64, 4, 2), 54 | # (6, 96, 3, 1), 55 | # (6, 160, 3, 2), 56 | # (6, 320, 1, 1), 57 | (1, 32, 1, 1), 58 | (6, 48, 2, 2), 59 | (6, 64, 3, 2), 60 | (6, 128, 4, 2), 61 | (6, 192, 3, 1), 62 | (6, 320, 3, 2), 63 | (6, 640, 1, 1), 64 | ] if change_depth == False else [ 65 | (1, 16, 1, 1), 66 | (6, 24, 2, 2), 67 | (6, 32, 5, 2), 68 | (6, 64, 7, 2), 69 | (6, 96, 5, 1), 70 | (6, 160, 3, 2), 71 | (6, 320, 1, 1), 72 | ] 73 | 74 | # conv1 75 | input = self.conv_bn_layer( 76 | input, 77 | num_filters=int(64 * scale), 78 | filter_size=3, 79 | stride=2, 80 | padding=1, 81 | if_act=True, 82 | name='conv1_1') 83 | 84 | # bottleneck sequences 85 | i = 1 86 | in_c = int(64 * scale) 87 | for layer_setting in bottleneck_params_list: 88 | t, c, n, s = layer_setting 89 | i += 1 90 | input = self.invresi_blocks( 91 | input=input, 92 | in_c=in_c, 93 | t=t, 94 | c=int(c * scale), 95 | n=n, 96 | s=s, 97 | name='conv' + str(i)) 98 | in_c = int(c * scale) 99 | # last_conv 100 | input = self.conv_bn_layer( 101 | input=input, 102 | num_filters=int(2560 * scale) if scale > 1.0 else 2560, 103 | filter_size=1, 104 | stride=1, 105 | padding=0, 106 | if_act=True, 107 | name='conv9') 108 | 109 | input = fluid.layers.pool2d( 110 | input=input, 111 | pool_size=7, 112 | pool_stride=1, 113 | pool_type='avg', 114 | global_pooling=True) 115 | 116 | output = fluid.layers.fc(input=input, 117 | size=class_dim, 118 | param_attr=ParamAttr(name='fc10_weights'), 119 | bias_attr=ParamAttr(name='fc10_offset')) 120 | return output 121 | 122 | def conv_bn_layer(self, 123 | input, 124 | filter_size, 125 | num_filters, 126 | stride, 127 | padding, 128 | channels=None, 129 | num_groups=1, 130 | if_act=True, 131 | name=None, 132 | use_cudnn=True): 133 | conv = fluid.layers.conv2d( 134 | input=input, 135 | num_filters=num_filters, 136 | filter_size=filter_size, 137 | stride=stride, 138 | padding=padding, 139 | groups=num_groups, 140 | act=None, 141 | use_cudnn=use_cudnn, 142 | param_attr=ParamAttr(name=name + '_weights'), 143 | bias_attr=False) 144 | bn_name = name + '_bn' 145 | bn = fluid.layers.batch_norm( 146 | input=conv, 147 | param_attr=ParamAttr(name=bn_name + "_scale"), 148 | bias_attr=ParamAttr(name=bn_name + "_offset"), 149 | moving_mean_name=bn_name + '_mean', 150 | moving_variance_name=bn_name + '_variance') 151 | if if_act: 152 | return fluid.layers.relu6(bn) 153 | else: 154 | return bn 155 | 156 | def shortcut(self, input, data_residual): 157 | return fluid.layers.elementwise_add(input, data_residual) 158 | 159 | def inverted_residual_unit(self, 160 | input, 161 | num_in_filter, 162 | num_filters, 163 | ifshortcut, 164 | stride, 165 | filter_size, 166 | padding, 167 | expansion_factor, 168 | name=None): 169 | num_expfilter = int(round(num_in_filter * expansion_factor)) 170 | 171 | channel_expand = self.conv_bn_layer( 172 | input=input, 173 | num_filters=num_expfilter, 174 | filter_size=1, 175 | stride=1, 176 | padding=0, 177 | num_groups=1, 178 | if_act=True, 179 | name=name + '_expand') 180 | 181 | bottleneck_conv = self.conv_bn_layer( 182 | input=channel_expand, 183 | num_filters=num_expfilter, 184 | filter_size=filter_size, 185 | stride=stride, 186 | padding=padding, 187 | num_groups=num_expfilter, 188 | if_act=True, 189 | name=name + '_dwise', 190 | use_cudnn=False) 191 | 192 | linear_out = self.conv_bn_layer( 193 | input=bottleneck_conv, 194 | num_filters=num_filters, 195 | filter_size=1, 196 | stride=1, 197 | padding=0, 198 | num_groups=1, 199 | if_act=False, 200 | name=name + '_linear') 201 | if ifshortcut: 202 | out = self.shortcut(input=input, data_residual=linear_out) 203 | return out 204 | else: 205 | return linear_out 206 | 207 | def invresi_blocks(self, input, in_c, t, c, n, s, name=None): 208 | first_block = self.inverted_residual_unit( 209 | input=input, 210 | num_in_filter=in_c, 211 | num_filters=c, 212 | ifshortcut=False, 213 | stride=s, 214 | filter_size=3, 215 | padding=1, 216 | expansion_factor=t, 217 | name=name + '_1') 218 | 219 | last_residual_block = first_block 220 | last_c = c 221 | 222 | for i in range(1, n): 223 | last_residual_block = self.inverted_residual_unit( 224 | input=last_residual_block, 225 | num_in_filter=last_c, 226 | num_filters=c, 227 | ifshortcut=True, 228 | stride=1, 229 | filter_size=3, 230 | padding=1, 231 | expansion_factor=t, 232 | name=name + '_' + str(i + 1)) 233 | return last_residual_block 234 | 235 | 236 | def MobileNetV2_x0_25(): 237 | model = MobileNetV2(scale=0.25) 238 | return model 239 | 240 | 241 | def MobileNetV2_x0_5(): 242 | model = MobileNetV2(scale=0.5) 243 | return model 244 | 245 | 246 | def MobileNetV2_x1_0(): 247 | model = MobileNetV2(scale=1.0) 248 | return model 249 | 250 | 251 | def MobileNetV2_x1_5(): 252 | model = MobileNetV2(scale=1.5) 253 | return model 254 | 255 | 256 | def MobileNetV2_x2_0(): 257 | model = MobileNetV2(scale=2.0) 258 | return model 259 | 260 | 261 | def MobileNetV2_scale(): 262 | model = MobileNetV2(scale=1.2, change_depth=True) 263 | return model -------------------------------------------------------------------------------- /src/attack_pgd_l2.py: -------------------------------------------------------------------------------- 1 | #coding=utf-8 2 | 3 | from __future__ import absolute_import 4 | from __future__ import division 5 | from __future__ import print_function 6 | 7 | import argparse 8 | import functools 9 | import numpy as np 10 | import paddle.fluid as fluid 11 | import os 12 | import sys 13 | 14 | #加载自定义文件 15 | import models 16 | from attack.attack_pp import FGSM, PGD, PGDL2 17 | from utils import init_prog, save_adv_image, process_img, tensor2img, calc_mse, add_arguments, print_arguments 18 | 19 | #######parse parameters 20 | parser = argparse.ArgumentParser(description=__doc__) 21 | add_arg = functools.partial(add_arguments, argparser=parser) 22 | 23 | # attack second time 24 | add_arg('class_dim', int, 121, "Class number.") 25 | add_arg('start_idx', int, 0, "start_idx.") 26 | add_arg('end_idx', int, 120, "end_idx.") 27 | add_arg('num_steps', int, 250, "num pgd steps.") 28 | add_arg('eps', float, 32., "eps") 29 | add_arg('step_size', float, 0.01, "step size") 30 | add_arg('noise_scale', float, 0.6, "noise scale") 31 | add_arg('confidence', float, 45., "early stop logit confidence") 32 | add_arg('num_samples', int, 5, "EOT samples") 33 | add_arg('is_targeted', int, 0, "0: means untargeted, 1: means targeted") 34 | add_arg('shape', str, "3,224,224", "output image shape") 35 | add_arg('input', str, "./input_image/", "Input directory with images") 36 | add_arg('output', str, "./pgdl2_output_image_resnet_eot/", "Output directory with images") 37 | add_arg('model_name', str, "MobileNetV2", "model name") 38 | add_arg('subfix', str, ".jpg", "sub fix") 39 | 40 | args = parser.parse_args() 41 | print_arguments(args) 42 | # "./output_image_mobile_eot/" 43 | # "./output_image_mobile_resnet_eot/" 44 | ######Init args 45 | image_shape = [int(m) for m in args.shape.split(",")] 46 | class_dim=args.class_dim 47 | input_dir = args.input 48 | output_dir = args.output 49 | # if os.path.exists(output_dir) is False: 50 | # os.mkdir(output_dir) 51 | model_name=args.model_name 52 | pretrained_model="./models_parameters/" + model_name 53 | # model_name = "MobileNetV2" 54 | # pretrained_model="./models_parameters/MobileNetV2" 55 | val_list = 'val_list.txt' 56 | use_gpu=True 57 | 58 | if args.is_targeted == 0: 59 | IsTarget = False 60 | elif args.is_targeted == 1: 61 | IsTarget = True 62 | 63 | 64 | ######Attack graph 65 | adv_program=fluid.Program() 66 | NUM_SAMPLES = args.num_samples 67 | model = models.__dict__[model_name]() 68 | 69 | #完成初始化 70 | with fluid.program_guard(adv_program): 71 | # model definition 72 | input_layer = fluid.layers.data(name='image', shape=image_shape, dtype='float32') 73 | label = fluid.layers.data(name="label", shape=[1], dtype='int64') 74 | #设置为可以计算梯度 75 | input_layer.stop_gradient=False 76 | 77 | # add different transformations 78 | loss = 0 79 | for i in range(NUM_SAMPLES): 80 | if i == 0: 81 | scale_ratio = 1 82 | random_noise = fluid.layers.uniform_random(shape=[1, 3, 224, 224], min=-0.0001, 83 | max=0.0001) 84 | else: 85 | # scale_ratio = np.random.uniform(low=1, high=9, size=1)[0] 86 | scale_ratio = i*1.0 87 | print(scale_ratio) 88 | # 1. random crop 89 | # cropped_img = fluid.layers.random_crop(input_layer, shape=[3, 170, 170]) 90 | # 2. random noise 91 | random_noise = fluid.layers.uniform_random(shape=[1, 3, 224, 224], min=-args.noise_scale, max=args.noise_scale) 92 | noised_img = fluid.layers.elementwise_add(input_layer, random_noise) 93 | # 3. random scaling 94 | scale_down = fluid.layers.image_resize(noised_img, scale=scale_ratio, name='scale_down_%d'%i, resample='BILINEAR') 95 | scale_back = fluid.layers.image_resize(scale_down, out_shape=(224, 224), name='scale_back_%d'%i, resample='BILINEAR') 96 | 97 | out_logits = model.net(input=scale_back, class_dim=class_dim) 98 | out = fluid.layers.softmax(out_logits) 99 | tmp_loss = fluid.layers.cross_entropy(input=out, label=label) 100 | loss += tmp_loss 101 | 102 | place = fluid.CUDAPlace(0) if use_gpu else fluid.CPUPlace() 103 | exe = fluid.Executor(place) 104 | exe.run(fluid.default_startup_program()) 105 | # print(fluid.default_startup_program()) 106 | #记载模型参数 107 | fluid.io.load_persistables(exe, pretrained_model) 108 | 109 | #设置adv_program的BN层状态 110 | init_prog(adv_program) 111 | 112 | evala_program = fluid.Program() 113 | with fluid.program_guard(evala_program): 114 | input_layer_eval = fluid.layers.data(name='image', shape=image_shape, dtype='float32') 115 | out_logits_eval = model.net(input=input_layer_eval, class_dim=class_dim) 116 | out_eval = fluid.layers.softmax(out_logits_eval) 117 | 118 | #创建测试用评估模式 119 | eval_program = evala_program.clone(for_test=True) 120 | init_prog(eval_program) 121 | 122 | #定义梯度 123 | with fluid.program_guard(adv_program): 124 | gradients = fluid.backward.gradients(targets=loss, inputs=[input_layer])[0] 125 | 126 | ######Inference 127 | def inference(img): 128 | fetch_list = [out_eval.name] 129 | 130 | result = exe.run(eval_program, 131 | fetch_list=fetch_list, 132 | feed={ 'image':img }) 133 | result = result[0][0] 134 | pred_label = np.argmax(result) 135 | 136 | result_least = result[1:121] 137 | least_label = np.argmin(result_least) + 1 138 | pred_score = result[pred_label].copy() 139 | 140 | return pred_label, pred_score, least_label 141 | 142 | ######FGSM attack 143 | #untarget attack 144 | def attack_nontarget_by_FGSM(img, src_label, target): 145 | pred_label = src_label 146 | 147 | step = float(args.step_size) 148 | eps = float(args.eps) 149 | while pred_label == src_label: 150 | #生成对抗样本 151 | adv = PGDL2(adv_program=adv_program, eval_program=eval_program,loss=loss, 152 | gradients=gradients,o=img, input_layer=input_layer,output_layer=out_logits, 153 | input_layer_eval=input_layer_eval,output_layer_eval=out_eval, 154 | step_size=step,epsilon=eps,iteration=int(args.eps/step),isTarget=IsTarget,target_label=target,src_label=src_label, 155 | use_gpu=True, discrete=False, confidence=args.confidence) 156 | 157 | pred_label, pred_score, _ = inference(adv) 158 | step *= 2 159 | if step > eps: 160 | break 161 | 162 | print("Test-score: {0}, class {1}".format(pred_score, pred_label)) 163 | 164 | adv_img=tensor2img(adv) 165 | return adv_img 166 | 167 | ####### Main ####### 168 | def get_original_file(filepath): 169 | with open(filepath, 'r') as cfile: 170 | full_lines = [line.strip() for line in cfile] 171 | cfile.close() 172 | original_files = [] 173 | for line in full_lines: 174 | label, file_name = line.split() 175 | original_files.append([file_name, int(label)]) 176 | return original_files 177 | 178 | def gen_adv(): 179 | mse = 0 180 | original_files = get_original_file('./input_image/' + val_list) 181 | 182 | target_label_list = [76, 18, 104, 36, 72, 72, 47, 92, 113, 5, 84, 74, 82, 34, 42, 84, 70, 98, 29, 87, 104, 94, 103, 183 | 61, 21, 83, 108, 104, 26, 112, 84, 107, 104, 45, 72, 19, 72, 75, 55, 104, 54, 104, 72, 74, 91, 184 | 25, 68, 107, 91, 185 | 41, 116, 21, 104, 56, 102, 51, 46, 87, 113, 19, 113, 85, 24, 93, 110, 102, 24, 84, 27, 38, 48, 186 | 43, 10, 32, 187 | 68, 87, 54, 12, 84, 29, 3, 13, 26, 2, 3, 106, 105, 34, 118, 66, 19, 74, 63, 42, 9, 113, 21, 6, 188 | 40, 40, 21, 104, 189 | 86, 23, 40, 12, 37, 20, 40, 12, 79, 15, 9, 48, 74, 51, 91, 79, 46, 80] 190 | # hard examples need use targeted attack 191 | for filename, label in original_files[args.start_idx:args.end_idx]: 192 | img_path = input_dir + filename.split('.')[0] + args.subfix 193 | print("Image: {0} ".format(img_path)) 194 | img=process_img(img_path) 195 | 196 | target = target_label_list[label - 1] 197 | if IsTarget: 198 | print('target class', target) 199 | adv_img = attack_nontarget_by_FGSM(img, label, target) 200 | 201 | # adv_img = attack_nontarget_by_FGSM(img, label) 202 | image_name, image_ext = filename.split('.') 203 | 204 | ##Save adversarial image(.png) 205 | save_adv_image(adv_img, output_dir+image_name+'.png') 206 | 207 | org_img = tensor2img(img) 208 | score = calc_mse(org_img, adv_img) 209 | mse += score 210 | print('MSE %.2f'%(score)) 211 | sys.stdout.flush() 212 | print("ADV {} files, AVG MSE: {} ".format(len(original_files), mse/len(original_files))) 213 | 214 | def main(): 215 | gen_adv() 216 | 217 | 218 | if __name__ == '__main__': 219 | main() 220 | -------------------------------------------------------------------------------- /src/models/resnext_vd.py: -------------------------------------------------------------------------------- 1 | #copyright (c) 2019 PaddlePaddle Authors. All Rights Reserve. 2 | # 3 | #Licensed under the Apache License, Version 2.0 (the "License"); 4 | #you may not use this file except in compliance with the License. 5 | #You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | #Unless required by applicable law or agreed to in writing, software 10 | #distributed under the License is distributed on an "AS IS" BASIS, 11 | #WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | #See the License for the specific language governing permissions and 13 | #limitations under the License. 14 | import paddle 15 | import paddle.fluid as fluid 16 | from paddle.fluid.param_attr import ParamAttr 17 | import math 18 | 19 | __all__ = [ 20 | "ResNeXt", "ResNeXt50_vd_64x4d", "ResNeXt101_vd_64x4d", 21 | "ResNeXt152_vd_64x4d", "ResNeXt50_vd_32x4d", "ResNeXt101_vd_32x4d", 22 | "ResNeXt152_vd_32x4d" 23 | ] 24 | 25 | 26 | class ResNeXt(): 27 | def __init__(self, layers=50, is_3x3=False, cardinality=64): 28 | self.layers = layers 29 | self.is_3x3 = is_3x3 30 | self.cardinality = cardinality 31 | 32 | def net(self, input, class_dim=1000): 33 | is_3x3 = self.is_3x3 34 | layers = self.layers 35 | cardinality = self.cardinality 36 | supported_layers = [50, 101, 152] 37 | assert layers in supported_layers, \ 38 | "supported layers are {} but input layer is {}".format(supported_layers, layers) 39 | 40 | if layers == 50: 41 | depth = [3, 4, 6, 3] 42 | elif layers == 101: 43 | depth = [3, 4, 23, 3] 44 | elif layers == 152: 45 | depth = [3, 8, 36, 3] 46 | num_filters1 = [256, 512, 1024, 2048] 47 | num_filters2 = [128, 256, 512, 1024] 48 | 49 | if is_3x3 == False: 50 | conv = self.conv_bn_layer( 51 | input=input, 52 | num_filters=64, 53 | filter_size=7, 54 | stride=2, 55 | act='relu') 56 | else: 57 | conv = self.conv_bn_layer( 58 | input=input, 59 | num_filters=32, 60 | filter_size=3, 61 | stride=2, 62 | act='relu', 63 | name='conv1_1') 64 | conv = self.conv_bn_layer( 65 | input=conv, 66 | num_filters=32, 67 | filter_size=3, 68 | stride=1, 69 | act='relu', 70 | name='conv1_2') 71 | conv = self.conv_bn_layer( 72 | input=conv, 73 | num_filters=64, 74 | filter_size=3, 75 | stride=1, 76 | act='relu', 77 | name='conv1_3') 78 | 79 | conv = fluid.layers.pool2d( 80 | input=conv, 81 | pool_size=3, 82 | pool_stride=2, 83 | pool_padding=1, 84 | pool_type='max') 85 | 86 | for block in range(len(depth)): 87 | for i in range(depth[block]): 88 | if layers in [101, 152, 200] and block == 2: 89 | if i == 0: 90 | conv_name = "res" + str(block + 2) + "a" 91 | else: 92 | conv_name = "res" + str(block + 2) + "b" + str(i) 93 | else: 94 | conv_name = "res" + str(block + 2) + chr(97 + i) 95 | conv = self.bottleneck_block( 96 | input=conv, 97 | num_filters=num_filters1[block] 98 | if cardinality == 64 else num_filters2[block], 99 | stride=2 if i == 0 and block != 0 else 1, 100 | cardinality=cardinality, 101 | if_first=block == 0, 102 | name=conv_name) 103 | 104 | pool = fluid.layers.pool2d( 105 | input=conv, pool_type='avg', global_pooling=True) 106 | stdv = 1.0 / math.sqrt(pool.shape[1] * 1.0) 107 | out = fluid.layers.fc( 108 | input=pool, 109 | size=class_dim, 110 | param_attr=fluid.param_attr.ParamAttr( 111 | initializer=fluid.initializer.Uniform(-stdv, stdv), 112 | name='fc_weights'), 113 | bias_attr=fluid.param_attr.ParamAttr(name='fc_offset')) 114 | 115 | return out 116 | 117 | def conv_bn_layer(self, 118 | input, 119 | num_filters, 120 | filter_size, 121 | stride=1, 122 | groups=1, 123 | act=None, 124 | name=None): 125 | conv = fluid.layers.conv2d( 126 | input=input, 127 | num_filters=num_filters, 128 | filter_size=filter_size, 129 | stride=stride, 130 | padding=(filter_size - 1) // 2, 131 | groups=groups, 132 | act=None, 133 | param_attr=ParamAttr(name=name + "_weights"), 134 | bias_attr=False) 135 | if name == "conv1": 136 | bn_name = "bn_" + name 137 | else: 138 | bn_name = "bn" + name[3:] 139 | return fluid.layers.batch_norm( 140 | input=conv, 141 | act=act, 142 | param_attr=ParamAttr(name=bn_name + '_scale'), 143 | bias_attr=ParamAttr(bn_name + '_offset'), 144 | moving_mean_name=bn_name + '_mean', 145 | moving_variance_name=bn_name + '_variance') 146 | 147 | def conv_bn_layer_new(self, 148 | input, 149 | num_filters, 150 | filter_size, 151 | stride=1, 152 | groups=1, 153 | act=None, 154 | name=None): 155 | pool = fluid.layers.pool2d( 156 | input=input, 157 | pool_size=2, 158 | pool_stride=2, 159 | pool_padding=0, 160 | pool_type='avg', 161 | ceil_mode=True) 162 | 163 | conv = fluid.layers.conv2d( 164 | input=pool, 165 | num_filters=num_filters, 166 | filter_size=filter_size, 167 | stride=1, 168 | padding=(filter_size - 1) // 2, 169 | groups=groups, 170 | act=None, 171 | param_attr=ParamAttr(name=name + "_weights"), 172 | bias_attr=False) 173 | if name == "conv1": 174 | bn_name = "bn_" + name 175 | else: 176 | bn_name = "bn" + name[3:] 177 | return fluid.layers.batch_norm( 178 | input=conv, 179 | act=act, 180 | param_attr=ParamAttr(name=bn_name + '_scale'), 181 | bias_attr=ParamAttr(bn_name + '_offset'), 182 | moving_mean_name=bn_name + '_mean', 183 | moving_variance_name=bn_name + '_variance') 184 | 185 | def shortcut(self, input, ch_out, stride, name, if_first=False): 186 | ch_in = input.shape[1] 187 | if ch_in != ch_out or stride != 1: 188 | if if_first: 189 | return self.conv_bn_layer(input, ch_out, 1, stride, name=name) 190 | else: 191 | return self.conv_bn_layer_new( 192 | input, ch_out, 1, stride, name=name) 193 | else: 194 | return input 195 | 196 | def bottleneck_block(self, input, num_filters, stride, cardinality, name, 197 | if_first): 198 | conv0 = self.conv_bn_layer( 199 | input=input, 200 | num_filters=num_filters, 201 | filter_size=1, 202 | act='relu', 203 | name=name + "_branch2a") 204 | conv1 = self.conv_bn_layer( 205 | input=conv0, 206 | num_filters=num_filters, 207 | filter_size=3, 208 | stride=stride, 209 | act='relu', 210 | groups=cardinality, 211 | name=name + "_branch2b") 212 | conv2 = self.conv_bn_layer( 213 | input=conv1, 214 | num_filters=num_filters if cardinality == 64 else num_filters * 2, 215 | filter_size=1, 216 | act=None, 217 | name=name + "_branch2c") 218 | 219 | short = self.shortcut( 220 | input, 221 | num_filters if cardinality == 64 else num_filters * 2, 222 | stride, 223 | if_first=if_first, 224 | name=name + "_branch1") 225 | 226 | return fluid.layers.elementwise_add(x=short, y=conv2, act='relu') 227 | 228 | 229 | def ResNeXt50_vd_64x4d(): 230 | model = ResNeXt(layers=50, is_3x3=True) 231 | return model 232 | 233 | 234 | def ResNeXt50_vd_32x4d(): 235 | model = ResNeXt(layers=50, cardinality=32, is_3x3=True) 236 | return model 237 | 238 | 239 | def ResNeXt101_vd_64x4d(): 240 | model = ResNeXt(layers=101, is_3x3=True) 241 | return model 242 | 243 | 244 | def ResNeXt101_vd_32x4d(): 245 | model = ResNeXt(layers=101, cardinality=32, is_3x3=True) 246 | return model 247 | 248 | 249 | def ResNeXt152_vd_64x4d(): 250 | model = ResNeXt(layers=152, is_3x3=True) 251 | return model 252 | 253 | 254 | def ResNeXt152_vd_32x4d(): 255 | model = ResNeXt(layers=152, cardinality=32, is_3x3=True) 256 | return model 257 | -------------------------------------------------------------------------------- /src/models/se_resnext.py: -------------------------------------------------------------------------------- 1 | #copyright (c) 2019 PaddlePaddle Authors. All Rights Reserve. 2 | # 3 | #Licensed under the Apache License, Version 2.0 (the "License"); 4 | #you may not use this file except in compliance with the License. 5 | #You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | #Unless required by applicable law or agreed to in writing, software 10 | #distributed under the License is distributed on an "AS IS" BASIS, 11 | #WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | #See the License for the specific language governing permissions and 13 | #limitations under the License. 14 | 15 | from __future__ import absolute_import 16 | from __future__ import division 17 | from __future__ import print_function 18 | 19 | import math 20 | 21 | import paddle 22 | import paddle.fluid as fluid 23 | from paddle.fluid.param_attr import ParamAttr 24 | 25 | __all__ = [ 26 | "SE_ResNeXt", "SE_ResNeXt50_32x4d", "SE_ResNeXt101_32x4d", 27 | "SE_ResNeXt152_32x4d" 28 | ] 29 | 30 | 31 | class SE_ResNeXt(): 32 | def __init__(self, layers=50): 33 | self.layers = layers 34 | 35 | def net(self, input, class_dim=1000): 36 | layers = self.layers 37 | supported_layers = [50, 101, 152] 38 | assert layers in supported_layers, \ 39 | "supported layers are {} but input layer is {}".format(supported_layers, layers) 40 | if layers == 50: 41 | cardinality = 32 42 | reduction_ratio = 16 43 | depth = [3, 4, 6, 3] 44 | num_filters = [128, 256, 512, 1024] 45 | 46 | conv = self.conv_bn_layer( 47 | input=input, 48 | num_filters=64, 49 | filter_size=7, 50 | stride=2, 51 | act='relu', 52 | name='conv1', ) 53 | conv = fluid.layers.pool2d( 54 | input=conv, 55 | pool_size=3, 56 | pool_stride=2, 57 | pool_padding=1, 58 | pool_type='max', 59 | use_cudnn=False) 60 | elif layers == 101: 61 | cardinality = 32 62 | reduction_ratio = 16 63 | depth = [3, 4, 23, 3] 64 | num_filters = [128, 256, 512, 1024] 65 | 66 | conv = self.conv_bn_layer( 67 | input=input, 68 | num_filters=64, 69 | filter_size=7, 70 | stride=2, 71 | act='relu', 72 | name="conv1", ) 73 | conv = fluid.layers.pool2d( 74 | input=conv, 75 | pool_size=3, 76 | pool_stride=2, 77 | pool_padding=1, 78 | pool_type='max', 79 | use_cudnn=False) 80 | elif layers == 152: 81 | cardinality = 64 82 | reduction_ratio = 16 83 | depth = [3, 8, 36, 3] 84 | num_filters = [128, 256, 512, 1024] 85 | 86 | conv = self.conv_bn_layer( 87 | input=input, 88 | num_filters=64, 89 | filter_size=3, 90 | stride=2, 91 | act='relu', 92 | name='conv1') 93 | conv = self.conv_bn_layer( 94 | input=conv, 95 | num_filters=64, 96 | filter_size=3, 97 | stride=1, 98 | act='relu', 99 | name='conv2') 100 | conv = self.conv_bn_layer( 101 | input=conv, 102 | num_filters=128, 103 | filter_size=3, 104 | stride=1, 105 | act='relu', 106 | name='conv3') 107 | conv = fluid.layers.pool2d( 108 | input=conv, pool_size=3, pool_stride=2, pool_padding=1, \ 109 | pool_type='max', use_cudnn=False) 110 | n = 1 if layers == 50 or layers == 101 else 3 111 | for block in range(len(depth)): 112 | n += 1 113 | for i in range(depth[block]): 114 | conv = self.bottleneck_block( 115 | input=conv, 116 | num_filters=num_filters[block], 117 | stride=2 if i == 0 and block != 0 else 1, 118 | cardinality=cardinality, 119 | reduction_ratio=reduction_ratio, 120 | name=str(n) + '_' + str(i + 1)) 121 | 122 | pool = fluid.layers.pool2d( 123 | input=conv, pool_type='avg', global_pooling=True, use_cudnn=False) 124 | drop = fluid.layers.dropout(x=pool, dropout_prob=0.5) 125 | stdv = 1.0 / math.sqrt(drop.shape[1] * 1.0) 126 | out = fluid.layers.fc( 127 | input=drop, 128 | size=class_dim, 129 | param_attr=ParamAttr( 130 | initializer=fluid.initializer.Uniform(-stdv, stdv), 131 | name='fc6_weights'), 132 | bias_attr=ParamAttr(name='fc6_offset')) 133 | return out 134 | 135 | def shortcut(self, input, ch_out, stride, name): 136 | ch_in = input.shape[1] 137 | if ch_in != ch_out or stride != 1: 138 | filter_size = 1 139 | return self.conv_bn_layer( 140 | input, ch_out, filter_size, stride, name='conv' + name + '_prj') 141 | else: 142 | return input 143 | 144 | def bottleneck_block(self, 145 | input, 146 | num_filters, 147 | stride, 148 | cardinality, 149 | reduction_ratio, 150 | name=None): 151 | conv0 = self.conv_bn_layer( 152 | input=input, 153 | num_filters=num_filters, 154 | filter_size=1, 155 | act='relu', 156 | name='conv' + name + '_x1') 157 | conv1 = self.conv_bn_layer( 158 | input=conv0, 159 | num_filters=num_filters, 160 | filter_size=3, 161 | stride=stride, 162 | groups=cardinality, 163 | act='relu', 164 | name='conv' + name + '_x2') 165 | conv2 = self.conv_bn_layer( 166 | input=conv1, 167 | num_filters=num_filters * 2, 168 | filter_size=1, 169 | act=None, 170 | name='conv' + name + '_x3') 171 | scale = self.squeeze_excitation( 172 | input=conv2, 173 | num_channels=num_filters * 2, 174 | reduction_ratio=reduction_ratio, 175 | name='fc' + name) 176 | 177 | short = self.shortcut(input, num_filters * 2, stride, name=name) 178 | 179 | return fluid.layers.elementwise_add(x=short, y=scale, act='relu') 180 | 181 | def conv_bn_layer(self, 182 | input, 183 | num_filters, 184 | filter_size, 185 | stride=1, 186 | groups=1, 187 | act=None, 188 | name=None): 189 | conv = fluid.layers.conv2d( 190 | input=input, 191 | num_filters=num_filters, 192 | filter_size=filter_size, 193 | stride=stride, 194 | padding=(filter_size - 1) // 2, 195 | groups=groups, 196 | act=None, 197 | bias_attr=False, 198 | param_attr=ParamAttr(name=name + '_weights'), ) 199 | bn_name = name + "_bn" 200 | return fluid.layers.batch_norm( 201 | input=conv, 202 | act=act, 203 | param_attr=ParamAttr(name=bn_name + '_scale'), 204 | bias_attr=ParamAttr(bn_name + '_offset'), 205 | moving_mean_name=bn_name + '_mean', 206 | moving_variance_name=bn_name + '_variance') 207 | 208 | def squeeze_excitation(self, 209 | input, 210 | num_channels, 211 | reduction_ratio, 212 | name=None): 213 | pool = fluid.layers.pool2d( 214 | input=input, pool_type='avg', global_pooling=True, use_cudnn=False) 215 | stdv = 1.0 / math.sqrt(pool.shape[1] * 1.0) 216 | squeeze = fluid.layers.fc( 217 | input=pool, 218 | size=num_channels // reduction_ratio, 219 | act='relu', 220 | param_attr=fluid.param_attr.ParamAttr( 221 | initializer=fluid.initializer.Uniform(-stdv, stdv), 222 | name=name + '_sqz_weights'), 223 | bias_attr=ParamAttr(name=name + '_sqz_offset')) 224 | stdv = 1.0 / math.sqrt(squeeze.shape[1] * 1.0) 225 | excitation = fluid.layers.fc( 226 | input=squeeze, 227 | size=num_channels, 228 | act='sigmoid', 229 | param_attr=fluid.param_attr.ParamAttr( 230 | initializer=fluid.initializer.Uniform(-stdv, stdv), 231 | name=name + '_exc_weights'), 232 | bias_attr=ParamAttr(name=name + '_exc_offset')) 233 | scale = fluid.layers.elementwise_mul(x=input, y=excitation, axis=0) 234 | return scale 235 | 236 | 237 | def SE_ResNeXt50_32x4d(): 238 | model = SE_ResNeXt(layers=50) 239 | return model 240 | 241 | 242 | def SE_ResNeXt101_32x4d(): 243 | model = SE_ResNeXt(layers=101) 244 | return model 245 | 246 | 247 | def SE_ResNeXt152_32x4d(): 248 | model = SE_ResNeXt(layers=152) 249 | return model 250 | -------------------------------------------------------------------------------- /src/models/googlenet.py: -------------------------------------------------------------------------------- 1 | #copyright (c) 2019 PaddlePaddle Authors. All Rights Reserve. 2 | # 3 | #Licensed under the Apache License, Version 2.0 (the "License"); 4 | #you may not use this file except in compliance with the License. 5 | #You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | #Unless required by applicable law or agreed to in writing, software 10 | #distributed under the License is distributed on an "AS IS" BASIS, 11 | #WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | #See the License for the specific language governing permissions and 13 | #limitations under the License. 14 | 15 | from __future__ import absolute_import 16 | from __future__ import division 17 | from __future__ import print_function 18 | 19 | import paddle 20 | import paddle.fluid as fluid 21 | from paddle.fluid.param_attr import ParamAttr 22 | 23 | __all__ = ['GoogLeNet'] 24 | 25 | 26 | class GoogLeNet(): 27 | def __init__(self): 28 | 29 | pass 30 | 31 | def conv_layer(self, 32 | input, 33 | num_filters, 34 | filter_size, 35 | stride=1, 36 | groups=1, 37 | act=None, 38 | name=None): 39 | channels = input.shape[1] 40 | stdv = (3.0 / (filter_size**2 * channels))**0.5 41 | param_attr = ParamAttr( 42 | initializer=fluid.initializer.Uniform(-stdv, stdv), 43 | name=name + "_weights") 44 | conv = fluid.layers.conv2d( 45 | input=input, 46 | num_filters=num_filters, 47 | filter_size=filter_size, 48 | stride=stride, 49 | padding=(filter_size - 1) // 2, 50 | groups=groups, 51 | act=act, 52 | param_attr=param_attr, 53 | bias_attr=False, 54 | name=name) 55 | return conv 56 | 57 | def xavier(self, channels, filter_size, name): 58 | stdv = (3.0 / (filter_size**2 * channels))**0.5 59 | param_attr = ParamAttr( 60 | initializer=fluid.initializer.Uniform(-stdv, stdv), 61 | name=name + "_weights") 62 | 63 | return param_attr 64 | 65 | def inception(self, 66 | input, 67 | channels, 68 | filter1, 69 | filter3R, 70 | filter3, 71 | filter5R, 72 | filter5, 73 | proj, 74 | name=None): 75 | conv1 = self.conv_layer( 76 | input=input, 77 | num_filters=filter1, 78 | filter_size=1, 79 | stride=1, 80 | act=None, 81 | name="inception_" + name + "_1x1") 82 | conv3r = self.conv_layer( 83 | input=input, 84 | num_filters=filter3R, 85 | filter_size=1, 86 | stride=1, 87 | act=None, 88 | name="inception_" + name + "_3x3_reduce") 89 | conv3 = self.conv_layer( 90 | input=conv3r, 91 | num_filters=filter3, 92 | filter_size=3, 93 | stride=1, 94 | act=None, 95 | name="inception_" + name + "_3x3") 96 | conv5r = self.conv_layer( 97 | input=input, 98 | num_filters=filter5R, 99 | filter_size=1, 100 | stride=1, 101 | act=None, 102 | name="inception_" + name + "_5x5_reduce") 103 | conv5 = self.conv_layer( 104 | input=conv5r, 105 | num_filters=filter5, 106 | filter_size=5, 107 | stride=1, 108 | act=None, 109 | name="inception_" + name + "_5x5") 110 | pool = fluid.layers.pool2d( 111 | input=input, 112 | pool_size=3, 113 | pool_stride=1, 114 | pool_padding=1, 115 | pool_type='max') 116 | convprj = fluid.layers.conv2d( 117 | input=pool, 118 | filter_size=1, 119 | num_filters=proj, 120 | stride=1, 121 | padding=0, 122 | name="inception_" + name + "_3x3_proj", 123 | param_attr=ParamAttr( 124 | name="inception_" + name + "_3x3_proj_weights"), 125 | bias_attr=False) 126 | cat = fluid.layers.concat(input=[conv1, conv3, conv5, convprj], axis=1) 127 | cat = fluid.layers.relu(cat) 128 | return cat 129 | 130 | def net(self, input, class_dim=1000): 131 | conv = self.conv_layer( 132 | input=input, 133 | num_filters=64, 134 | filter_size=7, 135 | stride=2, 136 | act=None, 137 | name="conv1") 138 | pool = fluid.layers.pool2d( 139 | input=conv, pool_size=3, pool_type='max', pool_stride=2) 140 | 141 | conv = self.conv_layer( 142 | input=pool, 143 | num_filters=64, 144 | filter_size=1, 145 | stride=1, 146 | act=None, 147 | name="conv2_1x1") 148 | conv = self.conv_layer( 149 | input=conv, 150 | num_filters=192, 151 | filter_size=3, 152 | stride=1, 153 | act=None, 154 | name="conv2_3x3") 155 | pool = fluid.layers.pool2d( 156 | input=conv, pool_size=3, pool_type='max', pool_stride=2) 157 | 158 | ince3a = self.inception(pool, 192, 64, 96, 128, 16, 32, 32, "ince3a") 159 | ince3b = self.inception(ince3a, 256, 128, 128, 192, 32, 96, 64, 160 | "ince3b") 161 | pool3 = fluid.layers.pool2d( 162 | input=ince3b, pool_size=3, pool_type='max', pool_stride=2) 163 | 164 | ince4a = self.inception(pool3, 480, 192, 96, 208, 16, 48, 64, "ince4a") 165 | ince4b = self.inception(ince4a, 512, 160, 112, 224, 24, 64, 64, 166 | "ince4b") 167 | ince4c = self.inception(ince4b, 512, 128, 128, 256, 24, 64, 64, 168 | "ince4c") 169 | ince4d = self.inception(ince4c, 512, 112, 144, 288, 32, 64, 64, 170 | "ince4d") 171 | ince4e = self.inception(ince4d, 528, 256, 160, 320, 32, 128, 128, 172 | "ince4e") 173 | pool4 = fluid.layers.pool2d( 174 | input=ince4e, pool_size=3, pool_type='max', pool_stride=2) 175 | 176 | ince5a = self.inception(pool4, 832, 256, 160, 320, 32, 128, 128, 177 | "ince5a") 178 | ince5b = self.inception(ince5a, 832, 384, 192, 384, 48, 128, 128, 179 | "ince5b") 180 | pool5 = fluid.layers.pool2d( 181 | input=ince5b, pool_size=7, pool_type='avg', pool_stride=7) 182 | dropout = fluid.layers.dropout(x=pool5, dropout_prob=0.4) 183 | out = fluid.layers.fc(input=dropout, 184 | size=class_dim, 185 | act='softmax', 186 | param_attr=self.xavier(1024, 1, "out"), 187 | name="out", 188 | bias_attr=ParamAttr(name="out_offset")) 189 | 190 | pool_o1 = fluid.layers.pool2d( 191 | input=ince4a, pool_size=5, pool_type='avg', pool_stride=3) 192 | conv_o1 = self.conv_layer( 193 | input=pool_o1, 194 | num_filters=128, 195 | filter_size=1, 196 | stride=1, 197 | act=None, 198 | name="conv_o1") 199 | fc_o1 = fluid.layers.fc(input=conv_o1, 200 | size=1024, 201 | act='relu', 202 | param_attr=self.xavier(2048, 1, "fc_o1"), 203 | name="fc_o1", 204 | bias_attr=ParamAttr(name="fc_o1_offset")) 205 | dropout_o1 = fluid.layers.dropout(x=fc_o1, dropout_prob=0.7) 206 | out1 = fluid.layers.fc(input=dropout_o1, 207 | size=class_dim, 208 | act='softmax', 209 | param_attr=self.xavier(1024, 1, "out1"), 210 | name="out1", 211 | bias_attr=ParamAttr(name="out1_offset")) 212 | 213 | pool_o2 = fluid.layers.pool2d( 214 | input=ince4d, pool_size=5, pool_type='avg', pool_stride=3) 215 | conv_o2 = self.conv_layer( 216 | input=pool_o2, 217 | num_filters=128, 218 | filter_size=1, 219 | stride=1, 220 | act=None, 221 | name="conv_o2") 222 | fc_o2 = fluid.layers.fc(input=conv_o2, 223 | size=1024, 224 | act='relu', 225 | param_attr=self.xavier(2048, 1, "fc_o2"), 226 | name="fc_o2", 227 | bias_attr=ParamAttr(name="fc_o2_offset")) 228 | dropout_o2 = fluid.layers.dropout(x=fc_o2, dropout_prob=0.7) 229 | out2 = fluid.layers.fc(input=dropout_o2, 230 | size=class_dim, 231 | act='softmax', 232 | param_attr=self.xavier(1024, 1, "out2"), 233 | name="out2", 234 | bias_attr=ParamAttr(name="out2_offset")) 235 | 236 | # last fc layer is "out" 237 | return out, out1, out2 238 | -------------------------------------------------------------------------------- /src/check_label.py: -------------------------------------------------------------------------------- 1 | # coding=utf-8 2 | 3 | from __future__ import absolute_import 4 | from __future__ import division 5 | from __future__ import print_function 6 | 7 | import argparse 8 | import functools 9 | import numpy as np 10 | import paddle.fluid as fluid 11 | from tqdm import tqdm 12 | # 加载自定义文件 13 | import models 14 | from attack.attack_pp import FGSM, PGD 15 | from utils import init_prog, save_adv_image, process_img, tensor2img, calc_mse, add_arguments, print_arguments 16 | 17 | #######parse parameters 18 | parser = argparse.ArgumentParser(description=__doc__) 19 | add_arg = functools.partial(add_arguments, argparser=parser) 20 | 21 | add_arg('class_dim', int, 121, "Class number.") 22 | add_arg('model_type', int, 1, "model name type") 23 | add_arg('noise', int, 1, "large than 0 use random noise") 24 | add_arg('shape', str, "3,224,224", "output image shape") 25 | add_arg('input', str, "./input_image/", "Input directory with images") 26 | add_arg('output', str, "./pgdl2_output_image_mobile_resnet_eot_l2_15_early_stop_30_mobile_l2_5/", "Output directory with images") 27 | # "output_image_resnet_eot_eps_32" 28 | # "./input_image/" 29 | args = parser.parse_args() 30 | print_arguments(args) 31 | 32 | ######Init args 33 | image_shape = [int(m) for m in args.shape.split(",")] 34 | class_dim = args.class_dim 35 | input_dir = args.input 36 | output_dir = args.output 37 | model_name_list = ["ResNeXt50_32x4d", 38 | "MobileNetV2", 39 | "EfficientNetB0", 40 | "Res2Net50_26w_4s", 41 | "SE_ResNet34_vd", 42 | "ShuffleNetV2_x2_0", 43 | "MobileNetV2_x2_0", 44 | "ResNet50", 45 | "SE_ResNet50_vd", 46 | "ResNeXt50_vd_32x4d", 47 | "MobileNetV1", 48 | "ShuffleNetV2", 49 | "ResNet34", 50 | "VGG19", 51 | "VGG16", 52 | "SqueezeNet1_1", 53 | "DPN92", 54 | ] 55 | # model_name = "ResNeXt50_32x4d" 56 | # model_name = "MobileNetV2" 57 | # model_name = "EfficientNetB0" 58 | # model_name = "Res2Net50_26w_4s" 59 | model_name = model_name_list[args.model_type] 60 | print('model name: ', model_name) 61 | pretrained_model="./models_parameters/" + model_name 62 | val_list = 'val_list.txt' 63 | use_gpu = True 64 | 65 | ######Attack graph 66 | adv_program = fluid.Program() 67 | 68 | # 完成初始化 69 | with fluid.program_guard(adv_program): 70 | input_layer = fluid.layers.data(name='image', shape=image_shape, dtype='float32') 71 | # 设置为可以计算梯度 72 | input_layer.stop_gradient = False 73 | 74 | # model definition 75 | model = models.__dict__[model_name]() 76 | if args.noise >= 10: 77 | print('uniform noise') 78 | random_noise = fluid.layers.uniform_random(shape=[1, 3, 224, 224], min=-.6, max=.6, seed=0) 79 | noised_img = fluid.layers.elementwise_add(input_layer, random_noise) 80 | out_logits = model.net(input=noised_img, class_dim=class_dim) 81 | elif args.noise >= 1: 82 | print('gaussian noise') 83 | gaussian_noise = fluid.layers.gaussian_random_batch_size_like(input_layer, shape=[-1, 3, 224, 224], mean=0., std=0.45) 84 | noised_img = fluid.layers.elementwise_add(input_layer, gaussian_noise) 85 | out_logits = model.net(input=noised_img, class_dim=class_dim) 86 | else: 87 | out_logits = model.net(input=input_layer, class_dim=class_dim) 88 | out = fluid.layers.softmax(out_logits) 89 | 90 | place = fluid.CUDAPlace(0) if use_gpu else fluid.CPUPlace() 91 | exe = fluid.Executor(place) 92 | exe.run(fluid.default_startup_program()) 93 | 94 | # 记载模型参数 95 | fluid.io.load_persistables(exe, pretrained_model) 96 | 97 | # 设置adv_program的BN层状态 98 | init_prog(adv_program) 99 | 100 | # 创建测试用评估模式 101 | eval_program = adv_program.clone(for_test=True) 102 | 103 | # 定义梯度 104 | with fluid.program_guard(adv_program): 105 | label = fluid.layers.data(name="label", shape=[1], dtype='int64') 106 | loss = fluid.layers.cross_entropy(input=out, label=label) 107 | gradients = fluid.backward.gradients(targets=loss, inputs=[input_layer])[0] 108 | 109 | 110 | ######Inference 111 | ''' 112 | def inference(img): 113 | fetch_list = [out.name] 114 | 115 | result = exe.run(eval_program, 116 | fetch_list=fetch_list, 117 | feed={ 'image':img }) 118 | result = result[0][0] 119 | pred_label = np.argmax(result) 120 | pred_score = result[pred_label].copy() 121 | 122 | # add by s3l 123 | least_class = np.argmin(result) 124 | return pred_label, pred_score, least_class 125 | ''' 126 | 127 | # inference for ResNet 128 | def inference(img): 129 | fetch_list = [out.name] 130 | 131 | result = exe.run(eval_program, 132 | fetch_list=fetch_list, 133 | feed={ 'image':img }) 134 | result = result[0][0] 135 | pred_label = np.argmax(result) 136 | 137 | result_least = result[1:121] 138 | least_label = np.argmin(result_least) + 1 139 | pred_score = result[pred_label].copy() 140 | 141 | return pred_label, pred_score, least_label 142 | 143 | 144 | # output logits 145 | def inference_logits(img): 146 | fetch_list = [out_logits.name] 147 | 148 | result = exe.run(eval_program, 149 | fetch_list=fetch_list, 150 | feed={ 'image':img }) 151 | 152 | logits_value = result[0][0] 153 | 154 | return logits_value 155 | 156 | 157 | ######FGSM attack 158 | # untarget attack 159 | def attack_nontarget_by_FGSM(img, src_label): 160 | pred_label = src_label 161 | 162 | step = 8.0 / 256.0 163 | eps = 32.0 / 256.0 164 | while pred_label == src_label: 165 | # 生成对抗样本 166 | # adv=FGSM(adv_program=adv_program,eval_program=eval_program,gradients=gradients,o=img, 167 | # input_layer=input_layer,output_layer=out,step_size=step,epsilon=eps, 168 | # isTarget=False,target_label=0,use_gpu=use_gpu) 169 | 170 | adv = PGD(adv_program=adv_program, eval_program=eval_program, 171 | gradients=gradients, o=img, input_layer=input_layer, output_layer=out, 172 | step_size=2.0 / 256, epsilon=16.0 / 256, iteration=20, isTarget=True, target_label=100, use_gpu=True) 173 | 174 | pred_label, pred_score = inference(adv) 175 | step *= 2 176 | if step > eps: 177 | break 178 | 179 | print("Test-score: {0}, class {1}".format(pred_score, pred_label)) 180 | 181 | adv_img = tensor2img(adv) 182 | return adv_img 183 | 184 | 185 | ####### Main ####### 186 | def get_original_file(filepath): 187 | with open(filepath, 'r') as cfile: 188 | full_lines = [line.strip() for line in cfile] 189 | cfile.close() 190 | original_files = [] 191 | for line in full_lines: 192 | label, file_name = line.split() 193 | original_files.append([file_name, int(label)]) 194 | return original_files 195 | 196 | 197 | def gen_adv(): 198 | print('gen adv') 199 | 200 | mse = 0 201 | adv_files = get_original_file(input_dir + val_list) 202 | print("read original files", len(adv_files)) 203 | 204 | target_label_list = [76, 18, 104, 36, 72, 72, 47, 92, 113, 5, 84, 74, 82, 34, 42, 84, 70, 205 | 98, 29, 87, 104, 94, 103, 61, 21, 83, 108, 104, 26, 112, 84, 107, 104, 206 | 45, 72, 19, 72, 75, 55, 104, 54, 104, 72, 74, 91, 25, 68, 107, 91, 207 | 41, 116, 21, 104, 56, 102, 51, 46, 87, 113, 19, 113, 85, 24, 93, 110, 208 | 102, 24, 84, 27, 38, 48, 43, 10, 32, 68, 87, 54, 12, 84, 29, 3, 13, 26, 209 | 2, 3, 106, 105, 34, 118, 66, 19, 74, 63, 42, 9, 113, 21, 6, 40, 40, 21, 104, 210 | 86, 23, 40, 12, 37, 20, 40, 12, 79, 15, 9, 48, 74, 51, 91, 79, 46, 80] 211 | 212 | least_list = [] 213 | counter = 0 214 | unt_counter = 0 215 | # 记录logits 216 | logits_list = [] 217 | mse_list = [] 218 | # 记录max和second logit的差值 219 | logits_diff = [] 220 | count = 0 221 | for filename, label in tqdm(adv_files): 222 | if args.output == 'input_image/': 223 | img_path = output_dir + filename.split('.')[0] + '.jpg' 224 | else: 225 | img_path = output_dir + filename.split('.')[0] + '.png' 226 | 227 | # print("Image: {0} ".format(img_path)) 228 | 229 | # !ssize.empty() in function 'resize' 230 | img = process_img(img_path) 231 | 232 | # print('Image range', np.min(img), np.max(img)) 233 | 234 | pred_label, pred_score, least_class = inference(img) 235 | logits = inference_logits(img) 236 | # print(logits) 237 | return_logits = np.sort(logits)[::-1] 238 | logits_list.append(return_logits) 239 | # logits_diff.append(return_logits[0] - return_logits[1]) 240 | logits_diff.append(return_logits[0] - logits[label]) 241 | 242 | # print("Test-score: {0}, class {1}".format(pred_score, pred_label)) 243 | 244 | # if pred_label == target_label_list[label - 1]: 245 | # counter += 1 246 | if pred_label != label: 247 | # print("Failed target image: {0} ".format(img_path)) 248 | unt_counter += 1 249 | else: 250 | # print("Serious!!!Failed untarget image: {0} ".format(img_path)) 251 | pass 252 | 253 | least_list.append(least_class) 254 | 255 | # adv_img = attack_nontarget_by_FGSM(img, label) 256 | # image_name, image_ext = filename.split('.') 257 | ## Save adversarial image(.png) 258 | # save_adv_image(adv_img, output_dir + image_name + '.png') 259 | 260 | ## check MSE 261 | # org_img = tensor2img(img) 262 | org_filename = filename.split('.')[0] + '.jpg' 263 | org_img_path = input_dir + org_filename 264 | org_img = process_img(org_img_path) 265 | score = calc_mse(tensor2img(org_img), tensor2img(img)) 266 | mse_list.append(score) 267 | mse += score 268 | count += 1 269 | 270 | 271 | # print('Least likely list', least_list) 272 | # print('logits', logits_list) 273 | print('logits diff: ') 274 | for i, logit in enumerate(logits_diff): 275 | if logit < 0.001: 276 | print('id: %d, mse: %.10f, diff logits: %.2f, ******************'%(i+1, mse_list[i], logit)) 277 | else: 278 | print('id: %d, mse: %.10f, diff logits: %.2f'%(i+1, mse_list[i], logit)) 279 | print('logits diff', np.mean(logits_diff)) 280 | print('The LL success number is', counter) 281 | print('The untargeted success number is', unt_counter) 282 | print("AVG MSE: {} ", mse / count) 283 | 284 | 285 | def main(): 286 | print('Run...') 287 | gen_adv() 288 | 289 | if __name__ == '__main__': 290 | main() -------------------------------------------------------------------------------- /src/models/xception.py: -------------------------------------------------------------------------------- 1 | #copyright (c) 2019 PaddlePaddle Authors. All Rights Reserve. 2 | # 3 | #Licensed under the Apache License, Version 2.0 (the "License"); 4 | #you may not use this file except in compliance with the License. 5 | #You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | #Unless required by applicable law or agreed to in writing, software 10 | #distributed under the License is distributed on an "AS IS" BASIS, 11 | #WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | #See the License for the specific language governing permissions and 13 | #limitations under the License. 14 | 15 | from __future__ import absolute_import 16 | from __future__ import division 17 | from __future__ import print_function 18 | 19 | import paddle 20 | import paddle.fluid as fluid 21 | import math 22 | import sys 23 | from paddle.fluid.param_attr import ParamAttr 24 | 25 | __all__ = ['Xception', 'Xception41', 'Xception65', 'Xception71'] 26 | 27 | 28 | class Xception(object): 29 | """Xception""" 30 | 31 | def __init__(self, entry_flow_block_num=3, middle_flow_block_num=8): 32 | self.entry_flow_block_num = entry_flow_block_num 33 | self.middle_flow_block_num = middle_flow_block_num 34 | return 35 | 36 | def net(self, input, class_dim=1000): 37 | conv = self.entry_flow(input, self.entry_flow_block_num) 38 | conv = self.middle_flow(conv, self.middle_flow_block_num) 39 | conv = self.exit_flow(conv, class_dim) 40 | 41 | return conv 42 | 43 | def entry_flow(self, input, block_num=3): 44 | '''xception entry_flow''' 45 | name = "entry_flow" 46 | conv = self.conv_bn_layer( 47 | input=input, 48 | num_filters=32, 49 | filter_size=3, 50 | stride=2, 51 | act='relu', 52 | name=name + "_conv1") 53 | conv = self.conv_bn_layer( 54 | input=conv, 55 | num_filters=64, 56 | filter_size=3, 57 | stride=1, 58 | act='relu', 59 | name=name + "_conv2") 60 | 61 | if block_num == 3: 62 | relu_first = [False, True, True] 63 | num_filters = [128, 256, 728] 64 | stride = [2, 2, 2] 65 | elif block_num == 5: 66 | relu_first = [False, True, True, True, True] 67 | num_filters = [128, 256, 256, 728, 728] 68 | stride = [2, 1, 2, 1, 2] 69 | else: 70 | sys.exit(-1) 71 | 72 | for block in range(block_num): 73 | curr_name = "{}_{}".format(name, block) 74 | conv = self.entry_flow_bottleneck_block( 75 | conv, 76 | num_filters=num_filters[block], 77 | name=curr_name, 78 | stride=stride[block], 79 | relu_first=relu_first[block]) 80 | 81 | return conv 82 | 83 | def entry_flow_bottleneck_block(self, 84 | input, 85 | num_filters, 86 | name, 87 | stride=2, 88 | relu_first=False): 89 | '''entry_flow_bottleneck_block''' 90 | short = fluid.layers.conv2d( 91 | input=input, 92 | num_filters=num_filters, 93 | filter_size=1, 94 | stride=stride, 95 | padding=0, 96 | act=None, 97 | param_attr=ParamAttr(name + "_branch1_weights"), 98 | bias_attr=False) 99 | 100 | conv0 = input 101 | if relu_first: 102 | conv0 = fluid.layers.relu(conv0) 103 | 104 | conv1 = self.separable_conv( 105 | conv0, num_filters, stride=1, name=name + "_branch2a_weights") 106 | 107 | conv2 = fluid.layers.relu(conv1) 108 | conv2 = self.separable_conv( 109 | conv2, num_filters, stride=1, name=name + "_branch2b_weights") 110 | 111 | pool = fluid.layers.pool2d( 112 | input=conv2, 113 | pool_size=3, 114 | pool_stride=stride, 115 | pool_padding=1, 116 | pool_type='max') 117 | 118 | return fluid.layers.elementwise_add(x=short, y=pool) 119 | 120 | def middle_flow(self, input, block_num=8): 121 | '''xception middle_flow''' 122 | num_filters = 728 123 | conv = input 124 | for block in range(block_num): 125 | name = "middle_flow_{}".format(block) 126 | conv = self.middle_flow_bottleneck_block(conv, num_filters, name) 127 | 128 | return conv 129 | 130 | def middle_flow_bottleneck_block(self, input, num_filters, name): 131 | '''middle_flow_bottleneck_block''' 132 | conv0 = fluid.layers.relu(input) 133 | conv0 = self.separable_conv( 134 | conv0, 135 | num_filters=num_filters, 136 | stride=1, 137 | name=name + "_branch2a_weights") 138 | 139 | conv1 = fluid.layers.relu(conv0) 140 | conv1 = self.separable_conv( 141 | conv1, 142 | num_filters=num_filters, 143 | stride=1, 144 | name=name + "_branch2b_weights") 145 | 146 | conv2 = fluid.layers.relu(conv1) 147 | conv2 = self.separable_conv( 148 | conv2, 149 | num_filters=num_filters, 150 | stride=1, 151 | name=name + "_branch2c_weights") 152 | 153 | return fluid.layers.elementwise_add(x=input, y=conv2) 154 | 155 | def exit_flow(self, input, class_dim): 156 | '''xception exit flow''' 157 | name = "exit_flow" 158 | num_filters1 = 728 159 | num_filters2 = 1024 160 | conv0 = self.exit_flow_bottleneck_block( 161 | input, num_filters1, num_filters2, name=name + "_1") 162 | 163 | conv1 = self.separable_conv( 164 | conv0, num_filters=1536, stride=1, name=name + "_2") 165 | conv1 = fluid.layers.relu(conv1) 166 | 167 | conv2 = self.separable_conv( 168 | conv1, num_filters=2048, stride=1, name=name + "_3") 169 | conv2 = fluid.layers.relu(conv2) 170 | 171 | pool = fluid.layers.pool2d( 172 | input=conv2, pool_type='avg', global_pooling=True) 173 | 174 | stdv = 1.0 / math.sqrt(pool.shape[1] * 1.0) 175 | out = fluid.layers.fc( 176 | input=pool, 177 | size=class_dim, 178 | param_attr=fluid.param_attr.ParamAttr( 179 | name='fc_weights', 180 | initializer=fluid.initializer.Uniform(-stdv, stdv)), 181 | bias_attr=fluid.param_attr.ParamAttr(name='fc_offset')) 182 | 183 | return out 184 | 185 | def exit_flow_bottleneck_block(self, input, num_filters1, num_filters2, 186 | name): 187 | '''entry_flow_bottleneck_block''' 188 | short = fluid.layers.conv2d( 189 | input=input, 190 | num_filters=num_filters2, 191 | filter_size=1, 192 | stride=2, 193 | padding=0, 194 | act=None, 195 | param_attr=ParamAttr(name + "_branch1_weights"), 196 | bias_attr=False) 197 | 198 | conv0 = fluid.layers.relu(input) 199 | conv1 = self.separable_conv( 200 | conv0, num_filters1, stride=1, name=name + "_branch2a_weights") 201 | 202 | conv2 = fluid.layers.relu(conv1) 203 | conv2 = self.separable_conv( 204 | conv2, num_filters2, stride=1, name=name + "_branch2b_weights") 205 | 206 | pool = fluid.layers.pool2d( 207 | input=conv2, 208 | pool_size=3, 209 | pool_stride=2, 210 | pool_padding=1, 211 | pool_type='max') 212 | 213 | return fluid.layers.elementwise_add(x=short, y=pool) 214 | 215 | def separable_conv(self, input, num_filters, stride=1, name=None): 216 | """separable_conv""" 217 | pointwise_conv = self.conv_bn_layer( 218 | input=input, 219 | filter_size=1, 220 | num_filters=num_filters, 221 | stride=1, 222 | name=name + "_sep") 223 | 224 | depthwise_conv = self.conv_bn_layer( 225 | input=pointwise_conv, 226 | filter_size=3, 227 | num_filters=num_filters, 228 | stride=stride, 229 | groups=num_filters, 230 | use_cudnn=False, 231 | name=name + "_dw") 232 | 233 | return depthwise_conv 234 | 235 | def conv_bn_layer(self, 236 | input, 237 | num_filters, 238 | filter_size, 239 | stride=1, 240 | groups=1, 241 | act=None, 242 | use_cudnn=True, 243 | name=None): 244 | """conv_bn_layer""" 245 | conv = fluid.layers.conv2d( 246 | input=input, 247 | num_filters=num_filters, 248 | filter_size=filter_size, 249 | stride=stride, 250 | padding=(filter_size - 1) // 2, 251 | groups=groups, 252 | act=None, 253 | param_attr=ParamAttr(name=name + "_weights"), 254 | bias_attr=False, 255 | use_cudnn=use_cudnn) 256 | 257 | bn_name = "bn_" + name 258 | 259 | return fluid.layers.batch_norm( 260 | input=conv, 261 | act=act, 262 | param_attr=ParamAttr(name=bn_name + '_scale'), 263 | bias_attr=ParamAttr(bn_name + '_offset'), 264 | moving_mean_name=bn_name + '_mean', 265 | moving_variance_name=bn_name + '_variance') 266 | 267 | 268 | def Xception41(): 269 | model = Xception(entry_flow_block_num=3, middle_flow_block_num=8) 270 | return model 271 | 272 | 273 | def Xception65(): 274 | model = Xception(entry_flow_block_num=3, middle_flow_block_num=16) 275 | return model 276 | 277 | 278 | def Xception71(): 279 | model = Xception(entry_flow_block_num=5, middle_flow_block_num=16) 280 | return model 281 | -------------------------------------------------------------------------------- /src/models/res2net_vd.py: -------------------------------------------------------------------------------- 1 | #copyright (c) 2019 PaddlePaddle Authors. All Rights Reserve. 2 | # 3 | #Licensed under the Apache License, Version 2.0 (the "License"); 4 | #you may not use this file except in compliance with the License. 5 | #You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | #Unless required by applicable law or agreed to in writing, software 10 | #distributed under the License is distributed on an "AS IS" BASIS, 11 | #WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | #See the License for the specific language governing permissions and 13 | #limitations under the License. 14 | 15 | from __future__ import absolute_import 16 | from __future__ import division 17 | from __future__ import print_function 18 | 19 | import paddle 20 | import paddle.fluid as fluid 21 | import math 22 | from paddle.fluid.param_attr import ParamAttr 23 | __all__ = ["Res2Net_vd", "Res2Net50_vd_48w_2s", "Res2Net50_vd_26w_4s", "Res2Net50_vd_14w_8s", "Res2Net50_vd_26w_6s", 24 | "Res2Net50_vd_26w_8s", "Res2Net101_vd_26w_4s", "Res2Net152_vd_26w_4s", "Res2Net200_vd_26w_4s"] 25 | 26 | 27 | class Res2Net_vd(): 28 | 29 | def __init__(self, layers=50, scales=4, width=26): 30 | self.layers = layers 31 | self.scales = scales 32 | self.width = width 33 | 34 | def net(self, input, class_dim=1000): 35 | layers = self.layers 36 | supported_layers = [50, 101, 152, 200] 37 | assert layers in supported_layers, \ 38 | "supported layers are {} but input layer is {}".format(supported_layers, layers) 39 | basic_width = self.width * self.scales 40 | num_filters1 = [basic_width * t for t in [1, 2, 4, 8]] 41 | num_filters2 = [256 * t for t in [1, 2, 4, 8]] 42 | if layers == 50: 43 | depth = [3, 4, 6, 3] 44 | elif layers == 101: 45 | depth = [3, 4, 23, 3] 46 | elif layers == 152: 47 | depth = [3, 8, 36, 3] 48 | elif layers == 200: 49 | depth = [3, 12, 48, 3] 50 | conv = self.conv_bn_layer( 51 | input=input, num_filters=32, filter_size=3, stride=2, act='relu', name='conv1_1') 52 | conv = self.conv_bn_layer( 53 | input=conv, num_filters=32, filter_size=3, stride=1, act='relu', name='conv1_2') 54 | conv = self.conv_bn_layer( 55 | input=conv, num_filters=64, filter_size=3, stride=1, act='relu', name='conv1_3') 56 | 57 | conv = fluid.layers.pool2d( 58 | input=conv, pool_size=3, pool_stride=2, pool_padding=1, pool_type='max') 59 | for block in range(len(depth)): 60 | for i in range(depth[block]): 61 | if layers in [101, 152] and block == 2: 62 | if i == 0: 63 | conv_name = "res" + str(block+2 )+ "a" 64 | else: 65 | conv_name = "res" + str(block+2) + "b" + str(i) 66 | else: 67 | conv_name = "res" + str(block+2) + chr(97+i) 68 | conv = self.bottleneck_block( 69 | input=conv, 70 | num_filters1=num_filters1[block], 71 | num_filters2=num_filters2[block], 72 | stride=2 if i==0 and block!=0 else 1, 73 | if_first=block==i==0, 74 | name=conv_name) 75 | pool = fluid.layers.pool2d( 76 | input=conv, pool_size=7, pool_stride=1, pool_type='avg', global_pooling=True) 77 | 78 | stdv = 1.0 / math.sqrt(pool.shape[1] * 1.0) 79 | out = fluid.layers.fc( 80 | input=pool, 81 | size=class_dim, 82 | param_attr=fluid.param_attr.ParamAttr( 83 | initializer=fluid.initializer.Uniform(-stdv, stdv), name='fc_weights'), 84 | bias_attr=fluid.param_attr.ParamAttr(name='fc_offset')) 85 | return out 86 | 87 | def conv_bn_layer(self, 88 | input, 89 | num_filters, 90 | filter_size, 91 | stride=1, 92 | groups=1, 93 | act=None, 94 | name=None): 95 | conv = fluid.layers.conv2d( 96 | input=input, 97 | num_filters=num_filters, 98 | filter_size=filter_size, 99 | stride=stride, 100 | padding=(filter_size - 1) // 2, 101 | groups=groups, 102 | act=None, 103 | param_attr=ParamAttr(name=name+"_weights"), 104 | bias_attr=False) 105 | if name == "conv1": 106 | bn_name = "bn_" + name 107 | else: 108 | bn_name = "bn" + name[3:] 109 | return fluid.layers.batch_norm(input=conv, 110 | act=act, 111 | param_attr=ParamAttr(name=bn_name+'_scale'), 112 | bias_attr=ParamAttr(bn_name+'_offset'), 113 | moving_mean_name=bn_name+'_mean', 114 | moving_variance_name=bn_name+'_variance') 115 | 116 | def conv_bn_layer_new(self, 117 | input, 118 | num_filters, 119 | filter_size, 120 | stride=1, 121 | groups=1, 122 | act=None, 123 | name=None): 124 | pool = fluid.layers.pool2d(input=input, 125 | pool_size=2, 126 | pool_stride=2, 127 | pool_padding=0, 128 | pool_type='avg', 129 | ceil_mode=True) 130 | 131 | conv = fluid.layers.conv2d( 132 | input=pool, 133 | num_filters=num_filters, 134 | filter_size=filter_size, 135 | stride=1, 136 | padding=(filter_size - 1)//2, 137 | groups=groups, 138 | act=None, 139 | param_attr=ParamAttr(name=name+"_weights"), 140 | bias_attr=False) 141 | if name == "conv1": 142 | bn_name = "bn_" + name 143 | else: 144 | bn_name = "bn" + name[3:] 145 | return fluid.layers.batch_norm(input=conv, 146 | act=act, 147 | param_attr=ParamAttr(name=bn_name+'_scale'), 148 | bias_attr=ParamAttr(bn_name+'_offset'), 149 | moving_mean_name=bn_name+'_mean', 150 | moving_variance_name=bn_name+'_variance') 151 | 152 | 153 | def shortcut(self, input, ch_out, stride, name, if_first=False): 154 | ch_in = input.shape[1] 155 | if ch_in != ch_out or stride != 1: 156 | if if_first: 157 | return self.conv_bn_layer(input, ch_out, 1, stride, name=name) 158 | else: 159 | return self.conv_bn_layer_new(input, ch_out, 1, stride, name=name) 160 | elif if_first: 161 | return self.conv_bn_layer(input, ch_out, 1, stride, name=name) 162 | else: 163 | return input 164 | 165 | 166 | def bottleneck_block(self, input, num_filters1, num_filters2, stride, name, if_first): 167 | conv0 = self.conv_bn_layer( 168 | input=input, 169 | num_filters=num_filters1, 170 | filter_size=1, 171 | stride=1, 172 | act='relu', 173 | name=name+'_branch2a') 174 | 175 | xs = fluid.layers.split(conv0, self.scales, 1) 176 | ys = [] 177 | for s in range(self.scales - 1): 178 | if s == 0 or stride == 2: 179 | ys.append(self.conv_bn_layer(input=xs[s], 180 | num_filters=num_filters1//self.scales, 181 | stride=stride, 182 | filter_size=3, 183 | act='relu', 184 | name=name+'_branch2b_'+str(s+1))) 185 | else: 186 | ys.append(self.conv_bn_layer(input=xs[s]+ys[-1], 187 | num_filters=num_filters1//self.scales, 188 | stride=stride, 189 | filter_size=3, 190 | act='relu', 191 | name=name+'_branch2b_'+str(s+1))) 192 | 193 | if stride == 1: 194 | ys.append(xs[-1]) 195 | else: 196 | ys.append(fluid.layers.pool2d(input=xs[-1], 197 | pool_size=3, 198 | pool_stride=stride, 199 | pool_padding=1, 200 | pool_type='avg')) 201 | 202 | conv1 = fluid.layers.concat(ys, axis=1) 203 | conv2 = self.conv_bn_layer( 204 | input=conv1, num_filters=num_filters2, filter_size=1, act=None, name=name+"_branch2c") 205 | 206 | short = self.shortcut(input, num_filters2, stride, if_first=if_first, name=name+"_branch1") 207 | 208 | return fluid.layers.elementwise_add(x=short, y=conv2, act='relu') 209 | 210 | 211 | 212 | 213 | def Res2Net50_vd_48w_2s(): 214 | model = Res2Net_vd(layers=50, scales=2, width=48) 215 | return model 216 | 217 | 218 | def Res2Net50_vd_26w_4s(): 219 | model = Res2Net_vd(layers=50, scales=4, width=26) 220 | return model 221 | 222 | 223 | def Res2Net50_vd_14w_8s(): 224 | model = Res2Net_vd(layers=50, scales=8, width=14) 225 | return model 226 | 227 | 228 | def Res2Net50_vd_26w_6s(): 229 | model = Res2Net_vd(layers=50, scales=6, width=26) 230 | return model 231 | 232 | 233 | def Res2Net50_vd_26w_8s(): 234 | model = Res2Net_vd(layers=50, scales=8, width=26) 235 | return model 236 | 237 | 238 | def Res2Net101_vd_26w_4s(): 239 | model = Res2Net_vd(layers=101, scales=4, width=26) 240 | return model 241 | 242 | 243 | def Res2Net152_vd_26w_4s(): 244 | model = Res2Net_vd(layers=152, scales=4, width=26) 245 | return model 246 | 247 | 248 | def Res2Net200_vd_26w_4s(): 249 | model = Res2Net_vd(layers=200, scales=4, width=26) 250 | return model 251 | -------------------------------------------------------------------------------- /src/models/resnet_vd.py: -------------------------------------------------------------------------------- 1 | #copyright (c) 2019 PaddlePaddle Authors. All Rights Reserve. 2 | # 3 | #Licensed under the Apache License, Version 2.0 (the "License"); 4 | #you may not use this file except in compliance with the License. 5 | #You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | #Unless required by applicable law or agreed to in writing, software 10 | #distributed under the License is distributed on an "AS IS" BASIS, 11 | #WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | #See the License for the specific language governing permissions and 13 | #limitations under the License. 14 | 15 | from __future__ import absolute_import 16 | from __future__ import division 17 | from __future__ import print_function 18 | 19 | import math 20 | 21 | import paddle 22 | import paddle.fluid as fluid 23 | from paddle.fluid.param_attr import ParamAttr 24 | 25 | __all__ = [ 26 | "ResNet", "ResNet18_vd", "ResNet34_vd", "ResNet50_vd", "ResNet101_vd", "ResNet152_vd", "ResNet200_vd" 27 | ] 28 | 29 | 30 | class ResNet(): 31 | def __init__(self, layers=50, is_3x3=False): 32 | self.layers = layers 33 | self.is_3x3 = is_3x3 34 | 35 | def net(self, input, class_dim=1000): 36 | is_3x3 = self.is_3x3 37 | layers = self.layers 38 | supported_layers = [18, 34, 50, 101, 152, 200] 39 | assert layers in supported_layers, \ 40 | "supported layers are {} but input layer is {}".format(supported_layers, layers) 41 | 42 | if layers == 18: 43 | depth = [2, 2, 2, 2] 44 | elif layers == 34 or layers == 50: 45 | depth = [3, 4, 6, 3] 46 | elif layers == 101: 47 | depth = [3, 4, 23, 3] 48 | elif layers == 152: 49 | depth = [3, 8, 36, 3] 50 | elif layers == 200: 51 | depth = [3, 12, 48, 3] 52 | num_filters = [64, 128, 256, 512] 53 | if is_3x3 == False: 54 | conv = self.conv_bn_layer( 55 | input=input, 56 | num_filters=64, 57 | filter_size=7, 58 | stride=2, 59 | act='relu') 60 | else: 61 | conv = self.conv_bn_layer( 62 | input=input, 63 | num_filters=32, 64 | filter_size=3, 65 | stride=2, 66 | act='relu', 67 | name='conv1_1') 68 | conv = self.conv_bn_layer( 69 | input=conv, 70 | num_filters=32, 71 | filter_size=3, 72 | stride=1, 73 | act='relu', 74 | name='conv1_2') 75 | conv = self.conv_bn_layer( 76 | input=conv, 77 | num_filters=64, 78 | filter_size=3, 79 | stride=1, 80 | act='relu', 81 | name='conv1_3') 82 | 83 | conv = fluid.layers.pool2d( 84 | input=conv, 85 | pool_size=3, 86 | pool_stride=2, 87 | pool_padding=1, 88 | pool_type='max') 89 | 90 | if layers >= 50: 91 | for block in range(len(depth)): 92 | for i in range(depth[block]): 93 | if layers in [101, 152, 200] and block == 2: 94 | if i == 0: 95 | conv_name = "res" + str(block + 2) + "a" 96 | else: 97 | conv_name = "res" + str(block + 2) + "b" + str(i) 98 | else: 99 | conv_name = "res" + str(block + 2) + chr(97 + i) 100 | conv = self.bottleneck_block( 101 | input=conv, 102 | num_filters=num_filters[block], 103 | stride=2 if i == 0 and block != 0 else 1, 104 | if_first=block==i==0, 105 | name=conv_name) 106 | else: 107 | for block in range(len(depth)): 108 | for i in range(depth[block]): 109 | conv_name="res"+str(block+2)+chr(97+i) 110 | conv = self.basic_block( 111 | input=conv, 112 | num_filters=num_filters[block], 113 | stride=2 if i == 0 and block != 0 else 1, 114 | if_first=block==i==0, 115 | name=conv_name) 116 | 117 | pool = fluid.layers.pool2d( 118 | input=conv, pool_type='avg', global_pooling=True) 119 | stdv = 1.0 / math.sqrt(pool.shape[1] * 1.0) 120 | 121 | out = fluid.layers.fc( 122 | input=pool, 123 | size=class_dim, 124 | param_attr=fluid.param_attr.ParamAttr( 125 | initializer=fluid.initializer.Uniform(-stdv, stdv))) 126 | 127 | return out 128 | 129 | def conv_bn_layer(self, 130 | input, 131 | num_filters, 132 | filter_size, 133 | stride=1, 134 | groups=1, 135 | act=None, 136 | name=None): 137 | conv = fluid.layers.conv2d( 138 | input=input, 139 | num_filters=num_filters, 140 | filter_size=filter_size, 141 | stride=stride, 142 | padding=(filter_size - 1) // 2, 143 | groups=groups, 144 | act=None, 145 | param_attr=ParamAttr(name=name + "_weights"), 146 | bias_attr=False) 147 | if name == "conv1": 148 | bn_name = "bn_" + name 149 | else: 150 | bn_name = "bn" + name[3:] 151 | return fluid.layers.batch_norm( 152 | input=conv, 153 | act=act, 154 | param_attr=ParamAttr(name=bn_name + '_scale'), 155 | bias_attr=ParamAttr(bn_name + '_offset'), 156 | moving_mean_name=bn_name + '_mean', 157 | moving_variance_name=bn_name + '_variance') 158 | 159 | def conv_bn_layer_new(self, 160 | input, 161 | num_filters, 162 | filter_size, 163 | stride=1, 164 | groups=1, 165 | act=None, 166 | name=None): 167 | pool = fluid.layers.pool2d( 168 | input=input, 169 | pool_size=2, 170 | pool_stride=2, 171 | pool_padding=0, 172 | pool_type='avg', 173 | ceil_mode=True) 174 | 175 | conv = fluid.layers.conv2d( 176 | input=pool, 177 | num_filters=num_filters, 178 | filter_size=filter_size, 179 | stride=1, 180 | padding=(filter_size - 1) // 2, 181 | groups=groups, 182 | act=None, 183 | param_attr=ParamAttr(name=name + "_weights"), 184 | bias_attr=False) 185 | if name == "conv1": 186 | bn_name = "bn_" + name 187 | else: 188 | bn_name = "bn" + name[3:] 189 | return fluid.layers.batch_norm( 190 | input=conv, 191 | act=act, 192 | param_attr=ParamAttr(name=bn_name + '_scale'), 193 | bias_attr=ParamAttr(bn_name + '_offset'), 194 | moving_mean_name=bn_name + '_mean', 195 | moving_variance_name=bn_name + '_variance') 196 | 197 | def shortcut(self, input, ch_out, stride, name, if_first=False): 198 | ch_in = input.shape[1] 199 | if ch_in != ch_out or stride != 1: 200 | if if_first: 201 | return self.conv_bn_layer(input, ch_out, 1, stride, name=name) 202 | else: 203 | return self.conv_bn_layer_new(input, ch_out, 1, stride, name=name) 204 | elif if_first: 205 | return self.conv_bn_layer(input, ch_out, 1, stride, name=name) 206 | else: 207 | return input 208 | 209 | 210 | def bottleneck_block(self, input, num_filters, stride, name, if_first): 211 | conv0 = self.conv_bn_layer( 212 | input=input, 213 | num_filters=num_filters, 214 | filter_size=1, 215 | act='relu', 216 | name=name + "_branch2a") 217 | conv1 = self.conv_bn_layer( 218 | input=conv0, 219 | num_filters=num_filters, 220 | filter_size=3, 221 | stride=stride, 222 | act='relu', 223 | name=name + "_branch2b") 224 | conv2 = self.conv_bn_layer( 225 | input=conv1, 226 | num_filters=num_filters * 4, 227 | filter_size=1, 228 | act=None, 229 | name=name + "_branch2c") 230 | 231 | short = self.shortcut( 232 | input, 233 | num_filters * 4, 234 | stride, 235 | if_first=if_first, 236 | name=name + "_branch1") 237 | 238 | return fluid.layers.elementwise_add(x=short, y=conv2, act='relu') 239 | 240 | 241 | def basic_block(self, input, num_filters, stride, name, if_first): 242 | conv0 = self.conv_bn_layer( 243 | input=input, 244 | num_filters=num_filters, 245 | filter_size=3, 246 | act='relu', 247 | stride=stride, 248 | name=name+"_branch2a") 249 | conv1 = self.conv_bn_layer( 250 | input=conv0, 251 | num_filters=num_filters, 252 | filter_size=3, 253 | act=None, 254 | name=name+"_branch2b") 255 | short = self.shortcut( 256 | input, 257 | num_filters, 258 | stride, 259 | if_first=if_first, 260 | name=name + "_branch1") 261 | return fluid.layers.elementwise_add(x=short, y=conv1, act='relu') 262 | 263 | def ResNet18_vd(): 264 | model=ResNet(layers=18, is_3x3=True) 265 | return model 266 | 267 | 268 | def ResNet34_vd(): 269 | model=ResNet(layers=34, is_3x3=True) 270 | return model 271 | 272 | 273 | def ResNet50_vd(): 274 | model = ResNet(layers=50, is_3x3=True) 275 | return model 276 | 277 | 278 | def ResNet101_vd(): 279 | model = ResNet(layers=101, is_3x3=True) 280 | return model 281 | 282 | 283 | def ResNet152_vd(): 284 | model = ResNet(layers=152, is_3x3=True) 285 | return model 286 | 287 | 288 | def ResNet200_vd(): 289 | model = ResNet(layers=200, is_3x3=True) 290 | return model 291 | -------------------------------------------------------------------------------- /src/models/shufflenet_v2_swish.py: -------------------------------------------------------------------------------- 1 | #copyright (c) 2019 PaddlePaddle Authors. All Rights Reserve. 2 | # 3 | #Licensed under the Apache License, Version 2.0 (the "License"); 4 | #you may not use this file except in compliance with the License. 5 | #You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | #Unless required by applicable law or agreed to in writing, software 10 | #distributed under the License is distributed on an "AS IS" BASIS, 11 | #WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | #See the License for the specific language governing permissions and 13 | #limitations under the License. 14 | 15 | from __future__ import absolute_import 16 | from __future__ import division 17 | from __future__ import print_function 18 | 19 | import math 20 | 21 | import paddle.fluid as fluid 22 | from paddle.fluid.initializer import MSRA 23 | from paddle.fluid.param_attr import ParamAttr 24 | 25 | __all__ = [ 26 | 'ShuffleNetV2_x0_5_swish', 'ShuffleNetV2_x1_0_swish', 27 | 'ShuffleNetV2_x1_5_swish', 'ShuffleNetV2_x2_0_swish', 'ShuffleNetV2_swish' 28 | ] 29 | 30 | 31 | class ShuffleNetV2_swish(): 32 | def __init__(self, scale=1.0): 33 | self.scale = scale 34 | 35 | def net(self, input, class_dim=1000): 36 | scale = self.scale 37 | stage_repeats = [4, 8, 4] 38 | 39 | if scale == 0.5: 40 | stage_out_channels = [-1, 24, 48, 96, 192, 1024] 41 | elif scale == 1.0: 42 | stage_out_channels = [-1, 24, 116, 232, 464, 1024] 43 | elif scale == 1.5: 44 | stage_out_channels = [-1, 24, 176, 352, 704, 1024] 45 | elif scale == 2.0: 46 | stage_out_channels = [-1, 24, 224, 488, 976, 2048] 47 | else: 48 | raise ValueError("""{} groups is not supported for 49 | 1x1 Grouped Convolutions""".format(num_groups)) 50 | 51 | #conv1 52 | 53 | input_channel = stage_out_channels[1] 54 | conv1 = self.conv_bn_layer( 55 | input=input, 56 | filter_size=3, 57 | num_filters=input_channel, 58 | padding=1, 59 | stride=2, 60 | name='stage1_conv') 61 | pool1 = fluid.layers.pool2d( 62 | input=conv1, 63 | pool_size=3, 64 | pool_stride=2, 65 | pool_padding=1, 66 | pool_type='max') 67 | conv = pool1 68 | # bottleneck sequences 69 | for idxstage in range(len(stage_repeats)): 70 | numrepeat = stage_repeats[idxstage] 71 | output_channel = stage_out_channels[idxstage + 2] 72 | for i in range(numrepeat): 73 | if i == 0: 74 | conv = self.inverted_residual_unit( 75 | input=conv, 76 | num_filters=output_channel, 77 | stride=2, 78 | benchmodel=2, 79 | name=str(idxstage + 2) + '_' + str(i + 1)) 80 | else: 81 | conv = self.inverted_residual_unit( 82 | input=conv, 83 | num_filters=output_channel, 84 | stride=1, 85 | benchmodel=1, 86 | name=str(idxstage + 2) + '_' + str(i + 1)) 87 | 88 | conv_last = self.conv_bn_layer( 89 | input=conv, 90 | filter_size=1, 91 | num_filters=stage_out_channels[-1], 92 | padding=0, 93 | stride=1, 94 | name='conv5') 95 | pool_last = fluid.layers.pool2d( 96 | input=conv_last, 97 | pool_size=7, 98 | pool_stride=1, 99 | pool_padding=0, 100 | pool_type='avg') 101 | 102 | output = fluid.layers.fc(input=pool_last, 103 | size=class_dim, 104 | param_attr=ParamAttr( 105 | initializer=MSRA(), name='fc6_weights'), 106 | bias_attr=ParamAttr(name='fc6_offset')) 107 | return output 108 | 109 | def conv_bn_layer(self, 110 | input, 111 | filter_size, 112 | num_filters, 113 | stride, 114 | padding, 115 | num_groups=1, 116 | use_cudnn=True, 117 | if_act=True, 118 | name=None): 119 | conv = fluid.layers.conv2d( 120 | input=input, 121 | num_filters=num_filters, 122 | filter_size=filter_size, 123 | stride=stride, 124 | padding=padding, 125 | groups=num_groups, 126 | act=None, 127 | use_cudnn=use_cudnn, 128 | param_attr=ParamAttr( 129 | initializer=MSRA(), name=name + '_weights'), 130 | bias_attr=False) 131 | out = int((input.shape[2] - 1) / float(stride) + 1) 132 | bn_name = name + '_bn' 133 | if if_act: 134 | return fluid.layers.batch_norm( 135 | input=conv, 136 | act='swish', 137 | param_attr=ParamAttr(name=bn_name + "_scale"), 138 | bias_attr=ParamAttr(name=bn_name + "_offset"), 139 | moving_mean_name=bn_name + '_mean', 140 | moving_variance_name=bn_name + '_variance') 141 | else: 142 | return fluid.layers.batch_norm( 143 | input=conv, 144 | param_attr=ParamAttr(name=bn_name + "_scale"), 145 | bias_attr=ParamAttr(name=bn_name + "_offset"), 146 | moving_mean_name=bn_name + '_mean', 147 | moving_variance_name=bn_name + '_variance') 148 | 149 | def channel_shuffle(self, x, groups): 150 | batchsize, num_channels, height, width = x.shape[0], x.shape[ 151 | 1], x.shape[2], x.shape[3] 152 | channels_per_group = num_channels // groups 153 | 154 | # reshape 155 | x = fluid.layers.reshape( 156 | x=x, shape=[batchsize, groups, channels_per_group, height, width]) 157 | 158 | x = fluid.layers.transpose(x=x, perm=[0, 2, 1, 3, 4]) 159 | 160 | # flatten 161 | x = fluid.layers.reshape( 162 | x=x, shape=[batchsize, num_channels, height, width]) 163 | 164 | return x 165 | 166 | def inverted_residual_unit(self, 167 | input, 168 | num_filters, 169 | stride, 170 | benchmodel, 171 | name=None): 172 | assert stride in [1, 2], \ 173 | "supported stride are {} but your stride is {}".format([1,2], stride) 174 | 175 | oup_inc = num_filters // 2 176 | inp = input.shape[1] 177 | 178 | if benchmodel == 1: 179 | x1, x2 = fluid.layers.split( 180 | input, 181 | num_or_sections=[input.shape[1] // 2, input.shape[1] // 2], 182 | dim=1) 183 | 184 | conv_pw = self.conv_bn_layer( 185 | input=x2, 186 | num_filters=oup_inc, 187 | filter_size=1, 188 | stride=1, 189 | padding=0, 190 | num_groups=1, 191 | if_act=True, 192 | name='stage_' + name + '_conv1') 193 | 194 | conv_dw = self.conv_bn_layer( 195 | input=conv_pw, 196 | num_filters=oup_inc, 197 | filter_size=3, 198 | stride=stride, 199 | padding=1, 200 | num_groups=oup_inc, 201 | if_act=False, 202 | use_cudnn=False, 203 | name='stage_' + name + '_conv2') 204 | 205 | conv_linear = self.conv_bn_layer( 206 | input=conv_dw, 207 | num_filters=oup_inc, 208 | filter_size=1, 209 | stride=1, 210 | padding=0, 211 | num_groups=1, 212 | if_act=True, 213 | name='stage_' + name + '_conv3') 214 | 215 | out = fluid.layers.concat([x1, conv_linear], axis=1) 216 | 217 | else: 218 | #branch1 219 | conv_dw_1 = self.conv_bn_layer( 220 | input=input, 221 | num_filters=inp, 222 | filter_size=3, 223 | stride=stride, 224 | padding=1, 225 | num_groups=inp, 226 | if_act=False, 227 | use_cudnn=False, 228 | name='stage_' + name + '_conv4') 229 | 230 | conv_linear_1 = self.conv_bn_layer( 231 | input=conv_dw_1, 232 | num_filters=oup_inc, 233 | filter_size=1, 234 | stride=1, 235 | padding=0, 236 | num_groups=1, 237 | if_act=True, 238 | name='stage_' + name + '_conv5') 239 | 240 | #branch2 241 | conv_pw_2 = self.conv_bn_layer( 242 | input=input, 243 | num_filters=oup_inc, 244 | filter_size=1, 245 | stride=1, 246 | padding=0, 247 | num_groups=1, 248 | if_act=True, 249 | name='stage_' + name + '_conv1') 250 | 251 | conv_dw_2 = self.conv_bn_layer( 252 | input=conv_pw_2, 253 | num_filters=oup_inc, 254 | filter_size=3, 255 | stride=stride, 256 | padding=1, 257 | num_groups=oup_inc, 258 | if_act=False, 259 | use_cudnn=False, 260 | name='stage_' + name + '_conv2') 261 | 262 | conv_linear_2 = self.conv_bn_layer( 263 | input=conv_dw_2, 264 | num_filters=oup_inc, 265 | filter_size=1, 266 | stride=1, 267 | padding=0, 268 | num_groups=1, 269 | if_act=True, 270 | name='stage_' + name + '_conv3') 271 | out = fluid.layers.concat([conv_linear_1, conv_linear_2], axis=1) 272 | 273 | return self.channel_shuffle(out, 2) 274 | 275 | 276 | def ShuffleNetV2_x0_5_swish(): 277 | model = ShuffleNetV2_swish(scale=0.5) 278 | return model 279 | 280 | 281 | def ShuffleNetV2_x1_0_swish(): 282 | model = ShuffleNetV2_swish(scale=1.0) 283 | return model 284 | 285 | 286 | def ShuffleNetV2_x1_5_swish(): 287 | model = ShuffleNetV2_swish(scale=1.5) 288 | return model 289 | 290 | 291 | def ShuffleNetV2_x2_0_swish(): 292 | model = ShuffleNetV2_swish(scale=2.0) 293 | return model 294 | -------------------------------------------------------------------------------- /src/models/shufflenet_v2.py: -------------------------------------------------------------------------------- 1 | #copyright (c) 2019 PaddlePaddle Authors. All Rights Reserve. 2 | # 3 | #Licensed under the Apache License, Version 2.0 (the "License"); 4 | #you may not use this file except in compliance with the License. 5 | #You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | #Unless required by applicable law or agreed to in writing, software 10 | #distributed under the License is distributed on an "AS IS" BASIS, 11 | #WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | #See the License for the specific language governing permissions and 13 | #limitations under the License. 14 | 15 | from __future__ import absolute_import 16 | from __future__ import division 17 | from __future__ import print_function 18 | 19 | import math 20 | 21 | import paddle.fluid as fluid 22 | from paddle.fluid.initializer import MSRA 23 | from paddle.fluid.param_attr import ParamAttr 24 | 25 | __all__ = [ 26 | 'ShuffleNetV2_x0_25', 'ShuffleNetV2_x0_33', 'ShuffleNetV2_x0_5', 27 | 'ShuffleNetV2_x1_0', 'ShuffleNetV2_x1_5', 'ShuffleNetV2_x2_0', 28 | 'ShuffleNetV2' 29 | ] 30 | 31 | 32 | class ShuffleNetV2(): 33 | def __init__(self, scale=1.0): 34 | self.scale = scale 35 | 36 | def net(self, input, class_dim=1000): 37 | scale = self.scale 38 | stage_repeats = [4, 8, 4] 39 | 40 | if scale == 0.25: 41 | stage_out_channels = [-1, 24, 24, 48, 96, 512] 42 | elif scale == 0.33: 43 | stage_out_channels = [-1, 24, 32, 64, 128, 512] 44 | elif scale == 0.5: 45 | stage_out_channels = [-1, 24, 48, 96, 192, 1024] 46 | elif scale == 1.0: 47 | stage_out_channels = [-1, 24, 116, 232, 464, 1024] 48 | elif scale == 1.5: 49 | stage_out_channels = [-1, 24, 176, 352, 704, 1024] 50 | elif scale == 2.0: 51 | stage_out_channels = [-1, 24, 224, 488, 976, 2048] 52 | else: 53 | raise NotImplementedError("This scale size:[" + str(scale) + 54 | "] is not implemented!") 55 | #conv1 56 | 57 | input_channel = stage_out_channels[1] 58 | conv1 = self.conv_bn_layer( 59 | input=input, 60 | filter_size=3, 61 | num_filters=input_channel, 62 | padding=1, 63 | stride=2, 64 | name='stage1_conv') 65 | pool1 = fluid.layers.pool2d( 66 | input=conv1, 67 | pool_size=3, 68 | pool_stride=2, 69 | pool_padding=1, 70 | pool_type='max') 71 | conv = pool1 72 | # bottleneck sequences 73 | for idxstage in range(len(stage_repeats)): 74 | numrepeat = stage_repeats[idxstage] 75 | output_channel = stage_out_channels[idxstage + 2] 76 | for i in range(numrepeat): 77 | if i == 0: 78 | conv = self.inverted_residual_unit( 79 | input=conv, 80 | num_filters=output_channel, 81 | stride=2, 82 | benchmodel=2, 83 | name=str(idxstage + 2) + '_' + str(i + 1)) 84 | else: 85 | conv = self.inverted_residual_unit( 86 | input=conv, 87 | num_filters=output_channel, 88 | stride=1, 89 | benchmodel=1, 90 | name=str(idxstage + 2) + '_' + str(i + 1)) 91 | 92 | conv_last = self.conv_bn_layer( 93 | input=conv, 94 | filter_size=1, 95 | num_filters=stage_out_channels[-1], 96 | padding=0, 97 | stride=1, 98 | name='conv5') 99 | pool_last = fluid.layers.pool2d( 100 | input=conv_last, 101 | pool_size=7, 102 | pool_stride=1, 103 | pool_padding=0, 104 | pool_type='avg') 105 | 106 | output = fluid.layers.fc(input=pool_last, 107 | size=class_dim, 108 | param_attr=ParamAttr( 109 | initializer=MSRA(), name='fc6_weights'), 110 | bias_attr=ParamAttr(name='fc6_offset')) 111 | return output 112 | 113 | def conv_bn_layer(self, 114 | input, 115 | filter_size, 116 | num_filters, 117 | stride, 118 | padding, 119 | num_groups=1, 120 | use_cudnn=True, 121 | if_act=True, 122 | name=None): 123 | conv = fluid.layers.conv2d( 124 | input=input, 125 | num_filters=num_filters, 126 | filter_size=filter_size, 127 | stride=stride, 128 | padding=padding, 129 | groups=num_groups, 130 | act=None, 131 | use_cudnn=use_cudnn, 132 | param_attr=ParamAttr( 133 | initializer=MSRA(), name=name + '_weights'), 134 | bias_attr=False) 135 | out = int((input.shape[2] - 1) / float(stride) + 1) 136 | bn_name = name + '_bn' 137 | if if_act: 138 | return fluid.layers.batch_norm( 139 | input=conv, 140 | act='relu', 141 | param_attr=ParamAttr(name=bn_name + "_scale"), 142 | bias_attr=ParamAttr(name=bn_name + "_offset"), 143 | moving_mean_name=bn_name + '_mean', 144 | moving_variance_name=bn_name + '_variance') 145 | else: 146 | return fluid.layers.batch_norm( 147 | input=conv, 148 | param_attr=ParamAttr(name=bn_name + "_scale"), 149 | bias_attr=ParamAttr(name=bn_name + "_offset"), 150 | moving_mean_name=bn_name + '_mean', 151 | moving_variance_name=bn_name + '_variance') 152 | 153 | def channel_shuffle(self, x, groups): 154 | batchsize, num_channels, height, width = x.shape[0], x.shape[ 155 | 1], x.shape[2], x.shape[3] 156 | channels_per_group = num_channels // groups 157 | 158 | # reshape 159 | x = fluid.layers.reshape( 160 | x=x, shape=[batchsize, groups, channels_per_group, height, width]) 161 | 162 | x = fluid.layers.transpose(x=x, perm=[0, 2, 1, 3, 4]) 163 | 164 | # flatten 165 | x = fluid.layers.reshape( 166 | x=x, shape=[batchsize, num_channels, height, width]) 167 | 168 | return x 169 | 170 | def inverted_residual_unit(self, 171 | input, 172 | num_filters, 173 | stride, 174 | benchmodel, 175 | name=None): 176 | assert stride in [1, 2], \ 177 | "supported stride are {} but your stride is {}".format([1,2], stride) 178 | 179 | oup_inc = num_filters // 2 180 | inp = input.shape[1] 181 | 182 | if benchmodel == 1: 183 | x1, x2 = fluid.layers.split( 184 | input, 185 | num_or_sections=[input.shape[1] // 2, input.shape[1] // 2], 186 | dim=1) 187 | 188 | conv_pw = self.conv_bn_layer( 189 | input=x2, 190 | num_filters=oup_inc, 191 | filter_size=1, 192 | stride=1, 193 | padding=0, 194 | num_groups=1, 195 | if_act=True, 196 | name='stage_' + name + '_conv1') 197 | 198 | conv_dw = self.conv_bn_layer( 199 | input=conv_pw, 200 | num_filters=oup_inc, 201 | filter_size=3, 202 | stride=stride, 203 | padding=1, 204 | num_groups=oup_inc, 205 | if_act=False, 206 | use_cudnn=False, 207 | name='stage_' + name + '_conv2') 208 | 209 | conv_linear = self.conv_bn_layer( 210 | input=conv_dw, 211 | num_filters=oup_inc, 212 | filter_size=1, 213 | stride=1, 214 | padding=0, 215 | num_groups=1, 216 | if_act=True, 217 | name='stage_' + name + '_conv3') 218 | 219 | out = fluid.layers.concat([x1, conv_linear], axis=1) 220 | 221 | else: 222 | #branch1 223 | conv_dw_1 = self.conv_bn_layer( 224 | input=input, 225 | num_filters=inp, 226 | filter_size=3, 227 | stride=stride, 228 | padding=1, 229 | num_groups=inp, 230 | if_act=False, 231 | use_cudnn=False, 232 | name='stage_' + name + '_conv4') 233 | 234 | conv_linear_1 = self.conv_bn_layer( 235 | input=conv_dw_1, 236 | num_filters=oup_inc, 237 | filter_size=1, 238 | stride=1, 239 | padding=0, 240 | num_groups=1, 241 | if_act=True, 242 | name='stage_' + name + '_conv5') 243 | 244 | #branch2 245 | conv_pw_2 = self.conv_bn_layer( 246 | input=input, 247 | num_filters=oup_inc, 248 | filter_size=1, 249 | stride=1, 250 | padding=0, 251 | num_groups=1, 252 | if_act=True, 253 | name='stage_' + name + '_conv1') 254 | 255 | conv_dw_2 = self.conv_bn_layer( 256 | input=conv_pw_2, 257 | num_filters=oup_inc, 258 | filter_size=3, 259 | stride=stride, 260 | padding=1, 261 | num_groups=oup_inc, 262 | if_act=False, 263 | use_cudnn=False, 264 | name='stage_' + name + '_conv2') 265 | 266 | conv_linear_2 = self.conv_bn_layer( 267 | input=conv_dw_2, 268 | num_filters=oup_inc, 269 | filter_size=1, 270 | stride=1, 271 | padding=0, 272 | num_groups=1, 273 | if_act=True, 274 | name='stage_' + name + '_conv3') 275 | out = fluid.layers.concat([conv_linear_1, conv_linear_2], axis=1) 276 | 277 | return self.channel_shuffle(out, 2) 278 | 279 | 280 | def ShuffleNetV2_x0_25(): 281 | model = ShuffleNetV2(scale=0.25) 282 | return model 283 | 284 | 285 | def ShuffleNetV2_x0_33(): 286 | model = ShuffleNetV2(scale=0.33) 287 | return model 288 | 289 | 290 | def ShuffleNetV2_x0_5(): 291 | model = ShuffleNetV2(scale=0.5) 292 | return model 293 | 294 | 295 | def ShuffleNetV2_x1_0(): 296 | model = ShuffleNetV2(scale=1.0) 297 | return model 298 | 299 | 300 | def ShuffleNetV2_x1_5(): 301 | model = ShuffleNetV2(scale=1.5) 302 | return model 303 | 304 | 305 | def ShuffleNetV2_x2_0(): 306 | model = ShuffleNetV2(scale=2.0) 307 | return model 308 | --------------------------------------------------------------------------------