├── __init__.py ├── config ├── __init__.py ├── _ctoy.yaml ├── _cifar10_VGG.yaml ├── _cifar100_VGG.yaml ├── _cifar10_WRN.yaml ├── _cifar100_WRN.yaml ├── _cifar10.yaml ├── _cifar100.yaml ├── _cifar10_rs.yaml ├── _cifar100_rs.yaml ├── _mini_imagenet_WRN.yaml ├── _mini_imagenet.yaml ├── _cifar10_bpfc.yaml ├── _mini_imagenet_rs.yaml ├── _cifar100_bpfc.yaml ├── _ctoy_ciiv.yaml ├── _cifar10_ciiv_VGG.yaml ├── _cifar100_ciiv.yaml ├── _cifar100_ciiv_VGG.yaml ├── _cifar10_ciiv.yaml ├── _cifar10_ciiv_rc.yaml ├── _cifar100_ciiv_rc.yaml ├── _cifar10_ciiv_WRN.yaml ├── _cifar100_ciiv_WRN.yaml ├── _cifar10_ciiv_mixup.yaml ├── _cifar100_ciiv_mixup.yaml ├── _mini_imagenet_bpfc.yaml ├── _mini_imagenet_ciiv.yaml ├── _mini_imagenet_ciiv_rc.yaml ├── _mini_imagenet_ciiv_mixup.yaml └── attacker_config.yaml ├── data ├── __init__.py ├── preprocessing.py ├── dataloader.py ├── mini-ImageNet │ └── preprocessing.py ├── dt_toy.py ├── dt_cifar.py └── dt_mini_imagenet.py ├── models ├── __init__.py ├── Base_Model.py ├── VGG.py └── WideResNet.py ├── utils ├── __init__.py ├── logger_utils.py ├── test_utils.py ├── train_utils.py ├── checkpoint_utils.py └── general_utils.py ├── attacker ├── attacks │ ├── __init__.py │ ├── autoattack.py │ ├── gn.py │ ├── un.py │ ├── bfs.py │ ├── spsa.py │ ├── eot.py │ ├── fgsm.py │ ├── ffgsm.py │ ├── adaptive_pgd.py │ ├── pgd_feat.py │ ├── pgd.py │ ├── bpdapgd.py │ ├── pgdl2.py │ └── cw.py ├── __init__.py └── attacker.py ├── README.md ├── old_file ├── old_config │ ├── prototype.yaml │ ├── toy.yaml │ ├── mnist.yaml │ ├── cifar10.yaml │ ├── mnist_rs.yaml │ ├── cifar10_rs.yaml │ ├── mini_imagenet_rs.yaml │ ├── mini_imagenet.yaml │ ├── toy_ciiv.yaml │ ├── mnist_ciiv.yaml │ ├── cifar10_ciiv.yaml │ ├── mini_imagenet_ciiv.yaml │ └── attacker_config.yaml ├── old_data │ └── dt_mnist.py └── old_model │ ├── VGG.py │ └── VGG_RS.py ├── visualization └── visualize_pth.py ├── test_baseline.py ├── test_ciiv.py ├── train_baseline.py └── main.py /__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /config/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /data/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /models/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /utils/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /attacker/attacks/__init__.py: -------------------------------------------------------------------------------- 1 | from .pgd import PGD 2 | from .pgdl2 import PGDL2 3 | from .fgsm import FGSM 4 | from .ffgsm import FFGSM 5 | from .gn import GN 6 | from .un import UN 7 | from .eot import EOT 8 | from .bpdapgd import BPDAPGD 9 | from .cw import CW 10 | from .bfs import BFS 11 | from .spsa import SPSA 12 | from .adaptive_pgd import ADAPTIVE 13 | from .pgd_feat import PGD_Feat -------------------------------------------------------------------------------- /attacker/__init__.py: -------------------------------------------------------------------------------- 1 | from .attacks.pgd import PGD 2 | from .attacks.pgdl2 import PGDL2 3 | from .attacks.fgsm import FGSM 4 | from .attacks.ffgsm import FFGSM 5 | from .attacks.gn import GN 6 | from .attacks.un import UN 7 | from .attacks.eot import EOT 8 | from .attacks.bpdapgd import BPDAPGD 9 | from .attacks.cw import CW 10 | from .attacks.bfs import BFS 11 | from .attacks.spsa import SPSA 12 | from .attacks.adaptive_pgd import ADAPTIVE 13 | from .attacks.autoattack import AA 14 | from .attacks.pgd_feat import PGD_Feat -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Codes for "Adversarial Visual Robustness by Causal Intervention" 2 | 3 | ### Baseline for CIFAR-10 4 | Baseline models 5 | ``` 6 | CUDA_VISIBLE_DEVICES=0 python main.py --cfg config/_cifar10.yaml --output_dir checkpoints/cifar10_resnet_baseline --require_eval --phase train 7 | ``` 8 | 9 | ### CiiV for CIFAR-10 10 | ``` 11 | CUDA_VISIBLE_DEVICES=0 python main.py --cfg config/_cifar10_ciiv.yaml --output_dir checkpoints/cifar10_resnet_ciiv --require_eval --phase train 12 | ``` 13 | 14 | ### Evaluation 15 | Examples for evaluation 16 | ``` 17 | CUDA_VISIBLE_DEVICES=0 python main.py --cfg config/_cifar10_ciiv.yaml --output_dir checkpoints/cifar10_resnet_ciiv --require_eval --phase test --load_dir checkpoints/cifar10_resnet_ciiv/epoch_XXX.pth --adv_test --adv_type TYPE_ADV_TYPE_HERE --adv_setting TYPE_DIFFERENT_SETTING_HERE 18 | `` -------------------------------------------------------------------------------- /models/Base_Model.py: -------------------------------------------------------------------------------- 1 | import torch 2 | import torch.nn as nn 3 | import torch.nn.functional as F 4 | 5 | 6 | class Base_Model(nn.Module): 7 | """ 8 | base model used for adversarial attack and defense 9 | """ 10 | def __init__(self): 11 | super(Base_Model, self).__init__() 12 | # attacking mode, i.e., generating attacking images 13 | self.attacking = False 14 | 15 | def set_attack(self): 16 | self.attacking = True 17 | # recursive set all modules to attack 18 | for m in self.modules(): 19 | if isinstance(m, Base_Model) and (not m.is_attack()): 20 | m.set_attack() 21 | 22 | def set_unattack(self): 23 | self.attacking = False 24 | # recursive set all modules to unattack 25 | for m in self.modules(): 26 | if isinstance(m, Base_Model) and m.is_attack(): 27 | m.set_unattack() 28 | 29 | def is_attack(self): 30 | return self.attacking 31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /data/preprocessing.py: -------------------------------------------------------------------------------- 1 | import json 2 | import torch 3 | import torch.nn.functional as F 4 | import h5py 5 | import os 6 | import xml 7 | 8 | 9 | 10 | 11 | ###################################### 12 | # Generate Validation data 13 | ###################################### 14 | 15 | 16 | datalist = os.listdir('/data4/imagenet/ILSVRC/Annotations/CLS-LOC/val/') 17 | 18 | name_to_label = {} 19 | for item in datalist: 20 | if item.split('.')[1] != 'xml': 21 | continue 22 | file_path = os.path.join('/data4/imagenet/ILSVRC/Annotations/CLS-LOC/val/', item) 23 | file = xml.dom.minidom.parse(file_path) 24 | labels = [] 25 | for obj in file.getElementsByTagName('object'): 26 | assert len(obj.getElementsByTagName('name')) == 1 27 | labels.append(obj.getElementsByTagName('name')[0].firstChild.data) 28 | label = list(set(labels)) 29 | assert len(label) == 1 30 | name = item.split('.')[0] 31 | name_to_label[name] = label[0] 32 | 33 | with open('./data/ImageNet/val_info.json', 'w') as f: 34 | json.dump(name_to_label, f) -------------------------------------------------------------------------------- /attacker/attacks/autoattack.py: -------------------------------------------------------------------------------- 1 | ############################################################################## 2 | # Modified from https://github.com/Harry24k/adversarial-attacks-pytorch 3 | ############################################################################## 4 | 5 | import torch 6 | import torch.nn as nn 7 | 8 | from ..attacker import Attacker 9 | import utils.general_utils as utils 10 | 11 | from autoattack import AutoAttack 12 | 13 | class AA(Attacker): 14 | """ 15 | Auto-Attack 16 | installing AutoAttack by: pip install git+https://github.com/fra31/auto-attack 17 | """ 18 | def __init__(self, model, logger, config, eps=16.0, norm='Linf'): 19 | super(AA, self).__init__("AA", model, logger, config) 20 | self.eps = eps / 255.0 21 | self.attacker = AutoAttack(model, norm=norm, eps=self.eps, version='standard') 22 | 23 | logger.info('Create Attacker Auto-Attack with eps: {}'.format(eps)) 24 | 25 | def forward(self, images, labels, random_start=False, targeted=False): 26 | 27 | images, labels = images.cuda(), labels.cuda() 28 | batch_size = images.shape[0] 29 | 30 | adv_images = self.attacker.run_standard_evaluation(images, labels, bs=batch_size) 31 | 32 | return adv_images -------------------------------------------------------------------------------- /utils/logger_utils.py: -------------------------------------------------------------------------------- 1 | import os 2 | from datetime import datetime 3 | 4 | class custom_logger(): 5 | def __init__(self, output_path, name='logger.txt'): 6 | now = datetime.now() 7 | logger_name = str(now.strftime("20%y_%h_%d_")) + name 8 | self.logger_path = os.path.join(output_path, logger_name) 9 | # init logger file 10 | f = open(self.logger_path, "w+") 11 | f.write(self.get_local_time() + 'Start Logging \n') 12 | f.close() 13 | 14 | def get_local_time(self): 15 | now = datetime.now() 16 | return str(now.strftime("%y_%h_%d %H:%M:%S : ")) 17 | 18 | def info(self, log_str): 19 | print(str(log_str)) 20 | with open(self.logger_path, "a") as f: 21 | f.write(self.get_local_time() + str(log_str) + '\n') 22 | 23 | def raise_error(self, error): 24 | prototype = '************* Error: {} *************'.format(str(error)) 25 | self.info(prototype) 26 | raise ValueError(str(error)) 27 | 28 | def info_iter(self, epoch, batch, total_batch, info_dict, print_iter): 29 | if batch % print_iter != 0: 30 | pass 31 | else: 32 | acc_log = 'Epoch {:5d}, Batch {:6d}/{},'.format(epoch, batch, total_batch) 33 | for key, val in info_dict.items(): 34 | acc_log += ' {}: {:9.3f},'.format(str(key), float(val)) 35 | self.info(acc_log) -------------------------------------------------------------------------------- /old_file/old_config/prototype.yaml: -------------------------------------------------------------------------------- 1 | # default num_head = 2 2 | criterions: 3 | PerformanceLoss: 4 | def_file: ./loss/SoftmaxLoss.py 5 | loss_params: {} 6 | optim_params: null 7 | weight: 1.0 8 | last: false 9 | # apply incremental pca to remove main components 10 | apply_ipca: false 11 | num_components: 512 12 | model_dir: null 13 | tuning_memory: false 14 | networks: 15 | classifier: 16 | def_file: ./models/CausalNormClassifier.py 17 | optim_params: {lr: 0.2, momentum: 0.9, weight_decay: 0.0005} 18 | scheduler_params: {coslr: true, endlr: 0.0, gamma: 0.1, step_size: 30} 19 | params: {dataset: CIFAR10_LT, feat_dim: 2048, num_classes: 10, stage1_weights: false} 20 | feat_model: 21 | def_file: ./models/ResNext50Feature.py 22 | fix: false 23 | optim_params: {lr: 0.2, momentum: 0.9, weight_decay: 0.0005} 24 | scheduler_params: {coslr: true, endlr: 0.0, gamma: 0.1, step_size: 30} 25 | params: {dataset: CIFAR10_LT, dropout: null, stage1_weights: false, use_fc: false} 26 | shuffle: false 27 | training_opt: 28 | backbone: resnext50 29 | batch_size: 512 30 | dataset: CIFAR10_LT 31 | display_step: 10 32 | display_grad: False 33 | display_grad_step: 10 34 | feature_dim: 2048 35 | log_dir: ./logs/CIFAR10_LT/models/resnext50_e90_causal_norm_ratio100_head2_scale16_norm32 36 | log_root: /logs/CIFAR10_LT 37 | num_classes: 10 38 | cifar_imb_ratio: 0.01 # 0.01, 0.02, 0.1 for 100, 50, 10 39 | num_epochs: 90 40 | num_workers: 12 41 | open_threshold: 0.1 42 | sampler: null 43 | sub_dir: models 44 | -------------------------------------------------------------------------------- /config/_ctoy.yaml: -------------------------------------------------------------------------------- 1 | output_dir: null 2 | 3 | dataset: 4 | name: TOYData 5 | num_classes: 3 6 | img_size: 64 7 | 8 | networks: 9 | def_file: ./models/ResNet.py 10 | params: {m_type: 'resnet18', cls_type: 'fc', num_classes: 3} 11 | 12 | strategy: 13 | train_type: 'baseline' # baseline / mixup / simsiam 14 | test_type: 'baseline' 15 | 16 | attacker_opt: 17 | adv_val: false # Adversarial attack during inference 18 | adv_train: false # Adversarial training 19 | attack_type: 'FGSM' # Adversarial attack algorithm type, candidates: 'PGD', 'PGDL2', 'FGSM', 'FFGSM', 'GN', 'UN' 20 | attack_set: 'setting1' # attack setting is under attacker_config.yaml 21 | eot_iter: 1 # EOT version of attacker is applied when eot_iter > 1 22 | 23 | 24 | training_opt: 25 | num_epochs: 7 26 | batch_size: 128 27 | data_workers: 4 28 | optimizer: 'SGD' # 'Adam' / 'SGD' 29 | optim_params: {lr: 0.1, momentum: 0.9, weight_decay: 0.0005} 30 | scheduler: 'step' # 'cosine' / 'step' 31 | scheduler_params: {endlr: 0.0, gamma: 0.1, milestones: [10, 100, 105]} 32 | 33 | test_opt: 34 | save_data: true # for val 35 | file_name: 'adv_images.pth' # for val 36 | save_length: 10 # only save first 10 batch for efficiency 37 | 38 | 39 | logger_opt: 40 | print_grad: false 41 | print_iter: 100 42 | 43 | checkpoint_opt: 44 | save_best: true # only save the model that better than previous epoches (except the last epoch) 45 | checkpoint_step: 1 46 | checkpoint_name: 'test_model.pth' -------------------------------------------------------------------------------- /config/_cifar10_VGG.yaml: -------------------------------------------------------------------------------- 1 | output_dir: null 2 | 3 | dataset: 4 | name: cifar10 5 | data_path: ./data/CIFAR10 6 | img_size: 32 7 | rand_aug: false 8 | 9 | networks: 10 | def_file: ./models/VGG.py 11 | params: {m_type: 'vgg13', num_classes: 10} 12 | 13 | strategy: 14 | train_type: 'baseline' # baseline / mixup / simsiam 15 | test_type: 'baseline' 16 | 17 | attacker_opt: 18 | adv_val: false # Adversarial attack during inference 19 | adv_train: false # Adversarial training 20 | attack_type: 'FGSM' # Adversarial attack algorithm type, candidates: 'PGD', 'PGDL2', 'FGSM', 'FFGSM', 'GN', 'UN' 21 | attack_set: 'setting1' # attack setting is under attacker_config.yaml 22 | eot_iter: 1 # EOT version of attacker is applied when eot_iter > 1 23 | 24 | 25 | training_opt: 26 | num_epochs: 110 27 | batch_size: 128 28 | data_workers: 4 29 | optimizer: 'SGD' # 'Adam' / 'SGD' 30 | optim_params: {lr: 0.01, momentum: 0.9, weight_decay: 0.0005} 31 | scheduler: 'step' # 'cosine' / 'step' 32 | scheduler_params: {endlr: 0.0, gamma: 0.1, milestones: [10, 100, 105]} 33 | 34 | test_opt: 35 | save_data: false # for val 36 | file_name: 'adv_images.pth' # for val 37 | save_length: 5 # only save first 10 batch for efficiency 38 | 39 | 40 | logger_opt: 41 | print_grad: false 42 | print_iter: 100 43 | 44 | checkpoint_opt: 45 | save_best: true # only save the model that better than previous epoches (except the last epoch) 46 | checkpoint_step: 10 47 | checkpoint_name: 'test_model.pth' -------------------------------------------------------------------------------- /config/_cifar100_VGG.yaml: -------------------------------------------------------------------------------- 1 | output_dir: null 2 | 3 | dataset: 4 | name: cifar100 5 | data_path: ./data/CIFAR100 6 | img_size: 32 7 | rand_aug: false 8 | 9 | networks: 10 | def_file: ./models/VGG.py 11 | params: {m_type: 'vgg13', num_classes: 100} 12 | 13 | strategy: 14 | train_type: 'baseline' # baseline / mixup / simsiam 15 | test_type: 'baseline' 16 | 17 | attacker_opt: 18 | adv_val: false # Adversarial attack during inference 19 | adv_train: false # Adversarial training 20 | attack_type: 'FGSM' # Adversarial attack algorithm type, candidates: 'PGD', 'PGDL2', 'FGSM', 'FFGSM', 'GN', 'UN' 21 | attack_set: 'setting1' # attack setting is under attacker_config.yaml 22 | eot_iter: 1 # EOT version of attacker is applied when eot_iter > 1 23 | 24 | 25 | training_opt: 26 | num_epochs: 110 27 | batch_size: 128 28 | data_workers: 4 29 | optimizer: 'SGD' # 'Adam' / 'SGD' 30 | optim_params: {lr: 0.01, momentum: 0.9, weight_decay: 0.0005} 31 | scheduler: 'step' # 'cosine' / 'step' 32 | scheduler_params: {endlr: 0.0, gamma: 0.1, milestones: [10, 100, 105]} 33 | 34 | test_opt: 35 | save_data: false # for val 36 | file_name: 'adv_images.pth' # for val 37 | save_length: 5 # only save first 10 batch for efficiency 38 | 39 | 40 | logger_opt: 41 | print_grad: false 42 | print_iter: 100 43 | 44 | checkpoint_opt: 45 | save_best: true # only save the model that better than previous epoches (except the last epoch) 46 | checkpoint_step: 10 47 | checkpoint_name: 'test_model.pth' -------------------------------------------------------------------------------- /config/_cifar10_WRN.yaml: -------------------------------------------------------------------------------- 1 | output_dir: null 2 | 3 | dataset: 4 | name: cifar10 5 | data_path: ./data/CIFAR10 6 | img_size: 32 7 | rand_aug: false 8 | 9 | networks: 10 | def_file: ./models/WideResNet.py 11 | params: {m_type: 'WRN34-10', num_classes: 10} 12 | 13 | strategy: 14 | train_type: 'baseline' # baseline / mixup / simsiam 15 | test_type: 'baseline' 16 | 17 | attacker_opt: 18 | adv_val: false # Adversarial attack during inference 19 | adv_train: false # Adversarial training 20 | attack_type: 'FGSM' # Adversarial attack algorithm type, candidates: 'PGD', 'PGDL2', 'FGSM', 'FFGSM', 'GN', 'UN' 21 | attack_set: 'setting1' # attack setting is under attacker_config.yaml 22 | eot_iter: 1 # EOT version of attacker is applied when eot_iter > 1 23 | 24 | 25 | training_opt: 26 | num_epochs: 110 27 | batch_size: 128 28 | data_workers: 4 29 | optimizer: 'SGD' # 'Adam' / 'SGD' 30 | optim_params: {lr: 0.1, momentum: 0.9, weight_decay: 0.0005} 31 | scheduler: 'step' # 'cosine' / 'step' 32 | scheduler_params: {endlr: 0.0, gamma: 0.1, milestones: [10, 100, 105]} 33 | 34 | test_opt: 35 | save_data: false # for val 36 | file_name: 'adv_images.pth' # for val 37 | save_length: 5 # only save first 10 batch for efficiency 38 | 39 | 40 | logger_opt: 41 | print_grad: false 42 | print_iter: 100 43 | 44 | checkpoint_opt: 45 | save_best: true # only save the model that better than previous epoches (except the last epoch) 46 | checkpoint_step: 10 47 | checkpoint_name: 'test_model.pth' -------------------------------------------------------------------------------- /config/_cifar100_WRN.yaml: -------------------------------------------------------------------------------- 1 | output_dir: null 2 | 3 | dataset: 4 | name: cifar100 5 | data_path: ./data/CIFAR100 6 | img_size: 32 7 | rand_aug: false 8 | 9 | networks: 10 | def_file: ./models/WideResNet.py 11 | params: {m_type: 'WRN34-10', num_classes: 100} 12 | 13 | strategy: 14 | train_type: 'baseline' # baseline / mixup / simsiam 15 | test_type: 'baseline' 16 | 17 | attacker_opt: 18 | adv_val: false # Adversarial attack during inference 19 | adv_train: false # Adversarial training 20 | attack_type: 'FGSM' # Adversarial attack algorithm type, candidates: 'PGD', 'PGDL2', 'FGSM', 'FFGSM', 'GN', 'UN' 21 | attack_set: 'setting1' # attack setting is under attacker_config.yaml 22 | eot_iter: 1 # EOT version of attacker is applied when eot_iter > 1 23 | 24 | 25 | training_opt: 26 | num_epochs: 110 27 | batch_size: 128 28 | data_workers: 4 29 | optimizer: 'SGD' # 'Adam' / 'SGD' 30 | optim_params: {lr: 0.1, momentum: 0.9, weight_decay: 0.0005} 31 | scheduler: 'step' # 'cosine' / 'step' 32 | scheduler_params: {endlr: 0.0, gamma: 0.1, milestones: [10, 100, 105]} 33 | 34 | test_opt: 35 | save_data: false # for val 36 | file_name: 'adv_images.pth' # for val 37 | save_length: 5 # only save first 10 batch for efficiency 38 | 39 | 40 | logger_opt: 41 | print_grad: false 42 | print_iter: 100 43 | 44 | checkpoint_opt: 45 | save_best: true # only save the model that better than previous epoches (except the last epoch) 46 | checkpoint_step: 10 47 | checkpoint_name: 'test_model.pth' -------------------------------------------------------------------------------- /config/_cifar10.yaml: -------------------------------------------------------------------------------- 1 | output_dir: null 2 | 3 | dataset: 4 | name: cifar10 5 | data_path: ./data/CIFAR10 6 | img_size: 32 7 | rand_aug: false 8 | 9 | networks: 10 | def_file: ./models/ResNet.py 11 | params: {m_type: 'resnet18', cls_type: 'fc', num_classes: 10} 12 | 13 | strategy: 14 | train_type: 'baseline' # baseline / mixup / simsiam 15 | test_type: 'baseline' 16 | 17 | attacker_opt: 18 | adv_val: false # Adversarial attack during inference 19 | adv_train: false # Adversarial training 20 | attack_type: 'FGSM' # Adversarial attack algorithm type, candidates: 'PGD', 'PGDL2', 'FGSM', 'FFGSM', 'GN', 'UN' 21 | attack_set: 'setting1' # attack setting is under attacker_config.yaml 22 | eot_iter: 1 # EOT version of attacker is applied when eot_iter > 1 23 | 24 | 25 | training_opt: 26 | num_epochs: 110 27 | batch_size: 128 28 | data_workers: 4 29 | optimizer: 'SGD' # 'Adam' / 'SGD' 30 | optim_params: {lr: 0.1, momentum: 0.9, weight_decay: 0.0005} 31 | scheduler: 'step' # 'cosine' / 'step' 32 | scheduler_params: {endlr: 0.0, gamma: 0.1, milestones: [10, 100, 105]} 33 | 34 | test_opt: 35 | save_data: false # for val 36 | file_name: 'adv_images.pth' # for val 37 | save_length: 5 # only save first 10 batch for efficiency 38 | 39 | 40 | logger_opt: 41 | print_grad: false 42 | print_iter: 100 43 | 44 | checkpoint_opt: 45 | save_best: true # only save the model that better than previous epoches (except the last epoch) 46 | checkpoint_step: 10 47 | checkpoint_name: 'test_model.pth' -------------------------------------------------------------------------------- /config/_cifar100.yaml: -------------------------------------------------------------------------------- 1 | output_dir: null 2 | 3 | dataset: 4 | name: cifar100 5 | data_path: ./data/CIFAR100 6 | img_size: 32 7 | rand_aug: false 8 | 9 | networks: 10 | def_file: ./models/ResNet.py 11 | params: {m_type: 'resnet18', cls_type: 'fc', num_classes: 100} 12 | 13 | strategy: 14 | train_type: 'baseline' # baseline / mixup / simsiam 15 | test_type: 'baseline' 16 | 17 | attacker_opt: 18 | adv_val: false # Adversarial attack during inference 19 | adv_train: false # Adversarial training 20 | attack_type: 'FGSM' # Adversarial attack algorithm type, candidates: 'PGD', 'PGDL2', 'FGSM', 'FFGSM', 'GN', 'UN' 21 | attack_set: 'setting1' # attack setting is under attacker_config.yaml 22 | eot_iter: 1 # EOT version of attacker is applied when eot_iter > 1 23 | 24 | 25 | training_opt: 26 | num_epochs: 110 27 | batch_size: 128 28 | data_workers: 4 29 | optimizer: 'SGD' # 'Adam' / 'SGD' 30 | optim_params: {lr: 0.1, momentum: 0.9, weight_decay: 0.0005} 31 | scheduler: 'step' # 'cosine' / 'step' 32 | scheduler_params: {endlr: 0.0, gamma: 0.1, milestones: [10, 100, 105]} 33 | 34 | test_opt: 35 | save_data: false # for val 36 | file_name: 'adv_images.pth' # for val 37 | save_length: 5 # only save first 10 batch for efficiency 38 | 39 | 40 | logger_opt: 41 | print_grad: false 42 | print_iter: 100 43 | 44 | checkpoint_opt: 45 | save_best: true # only save the model that better than previous epoches (except the last epoch) 46 | checkpoint_step: 10 47 | checkpoint_name: 'test_model.pth' -------------------------------------------------------------------------------- /config/_cifar10_rs.yaml: -------------------------------------------------------------------------------- 1 | output_dir: null 2 | 3 | dataset: 4 | name: cifar10 5 | data_path: ./data/CIFAR10 6 | img_size: 32 7 | rand_aug: false 8 | 9 | networks: 10 | def_file: ./models/ResNet_RS.py 11 | params: {m_type: 'resnet18', cls_type: 'fc', num_classes: 10, num_trial: 10, sigma: 0.25} 12 | 13 | strategy: 14 | train_type: 'baseline' # baseline / mixup / simsiam 15 | test_type: 'baseline' 16 | 17 | attacker_opt: 18 | adv_val: false # Adversarial attack during inference 19 | adv_train: false # Adversarial training 20 | attack_type: 'FGSM' # Adversarial attack algorithm type, candidates: 'PGD', 'PGDL2', 'FGSM', 'FFGSM', 'GN', 'UN' 21 | attack_set: 'setting1' # attack setting is under attacker_config.yaml 22 | eot_iter: 1 # EOT version of attacker is applied when eot_iter > 1 23 | 24 | 25 | training_opt: 26 | num_epochs: 110 27 | batch_size: 128 28 | data_workers: 4 29 | optimizer: 'SGD' # 'Adam' / 'SGD' 30 | optim_params: {lr: 0.1, momentum: 0.9, weight_decay: 0.0005} 31 | scheduler: 'step' # 'cosine' / 'step' 32 | scheduler_params: {endlr: 0.0, gamma: 0.1, milestones: [10, 100, 105]} 33 | 34 | test_opt: 35 | save_data: false # for val 36 | file_name: 'adv_images.pth' # for val 37 | save_length: 5 # only save first 10 batch for efficiency 38 | 39 | 40 | logger_opt: 41 | print_grad: false 42 | print_iter: 100 43 | 44 | checkpoint_opt: 45 | save_best: true # only save the model that better than previous epoches (except the last epoch) 46 | checkpoint_step: 10 47 | checkpoint_name: 'test_model.pth' -------------------------------------------------------------------------------- /visualization/visualize_pth.py: -------------------------------------------------------------------------------- 1 | import math 2 | import torch 3 | import numpy as np 4 | from PIL import Image 5 | 6 | saved_data = torch.load('/home/username/checkpoints/cifar10_decouple_lv_hv/adv_images.pth') 7 | 8 | index = 10 9 | 10 | # show org image 11 | img = (saved_data['org_images'][index]*255).permute(1,2,0).numpy().astype('uint8') 12 | Image.fromarray(img).resize((128, 128)) 13 | 14 | # show adv image 15 | adv = (saved_data['adv_images'][index]*255).permute(1,2,0).numpy().astype('uint8') 16 | Image.fromarray(adv).resize((128, 128)) 17 | 18 | def get_bit_image(image, bit=1): 19 | p_val = math.pow(2, bit) 20 | image = torch.round(image * 255) 21 | image = torch.remainder(image, p_val * 2) 22 | image = (image - torch.remainder(image, p_val)) 23 | image = image / 255 24 | return image 25 | 26 | def show_img(image): 27 | image = image * 255 28 | image = image.permute(1,2,0).numpy().astype('uint8') 29 | return Image.fromarray(image).resize((128, 128)) 30 | 31 | def multi_bit_image(image, bits): 32 | images = [get_bit_image(image, i) for i in bits] 33 | return sum(images) 34 | 35 | def differentiable_remainder(x, divider): 36 | return x - (torch.floor_divide(x, divider) * divider).clone().detach() 37 | 38 | index1 = 10 39 | index2 = 20 40 | 41 | org_image1 = saved_data['org_images'][index1] 42 | adv_image1 = saved_data['adv_images'][index1] 43 | org_image2 = saved_data['org_images'][index2] 44 | adv_image2 = saved_data['adv_images'][index2] 45 | 46 | show_img(org_image1) 47 | 48 | show_img(org_image2) 49 | 50 | show_img(multi_bit_image(org_image2, [1,2,3,4,5]) + multi_bit_image(org_image1, [6,7])) 51 | -------------------------------------------------------------------------------- /config/_cifar100_rs.yaml: -------------------------------------------------------------------------------- 1 | output_dir: null 2 | 3 | dataset: 4 | name: cifar100 5 | data_path: ./data/CIFAR100 6 | img_size: 32 7 | rand_aug: false 8 | 9 | networks: 10 | def_file: ./models/ResNet_RS.py 11 | params: {m_type: 'resnet18', cls_type: 'fc', num_classes: 100, num_trial: 10, sigma: 0.25} 12 | 13 | strategy: 14 | train_type: 'baseline' # baseline / mixup / simsiam 15 | test_type: 'baseline' 16 | 17 | attacker_opt: 18 | adv_val: false # Adversarial attack during inference 19 | adv_train: false # Adversarial training 20 | attack_type: 'FGSM' # Adversarial attack algorithm type, candidates: 'PGD', 'PGDL2', 'FGSM', 'FFGSM', 'GN', 'UN' 21 | attack_set: 'setting1' # attack setting is under attacker_config.yaml 22 | eot_iter: 1 # EOT version of attacker is applied when eot_iter > 1 23 | 24 | 25 | training_opt: 26 | num_epochs: 110 27 | batch_size: 128 28 | data_workers: 4 29 | optimizer: 'SGD' # 'Adam' / 'SGD' 30 | optim_params: {lr: 0.1, momentum: 0.9, weight_decay: 0.0005} 31 | scheduler: 'step' # 'cosine' / 'step' 32 | scheduler_params: {endlr: 0.0, gamma: 0.1, milestones: [10, 100, 105]} 33 | 34 | test_opt: 35 | save_data: false # for val 36 | file_name: 'adv_images.pth' # for val 37 | save_length: 5 # only save first 10 batch for efficiency 38 | 39 | 40 | logger_opt: 41 | print_grad: false 42 | print_iter: 100 43 | 44 | checkpoint_opt: 45 | save_best: true # only save the model that better than previous epoches (except the last epoch) 46 | checkpoint_step: 10 47 | checkpoint_name: 'test_model.pth' -------------------------------------------------------------------------------- /utils/test_utils.py: -------------------------------------------------------------------------------- 1 | import torch 2 | import torch.nn as nn 3 | 4 | import random 5 | import attacker 6 | 7 | from test_baseline import test_baseline 8 | from test_ciiv import test_ciiv 9 | 10 | def get_test_func(config): 11 | # choosing test strategy 12 | if config['strategy']['test_type'] == 'baseline': 13 | test_func = test_baseline 14 | elif config['strategy']['test_type'] == 'ciiv': 15 | test_func = test_ciiv 16 | else: 17 | raise ValueError('Wrong Test Strategy') 18 | return test_func 19 | 20 | 21 | 22 | def get_adv_target(target_type, model, inputs, gt_label): 23 | with torch.no_grad(): 24 | preds = model(inputs).softmax(-1) 25 | num_batch, num_class = preds.shape 26 | 27 | if target_type == 'random': 28 | adv_targets = torch.randint(0, num_class, (num_batch,)).to(gt_label.device) 29 | # validation check 30 | adv_targets = adv_target_update(gt_label, adv_targets, num_batch, num_class) 31 | elif target_type == 'most': 32 | idxs = torch.arange(num_batch).to(inputs.device) 33 | preds[idxs, gt_label] = -1 34 | adv_targets = preds.max(-1)[1] 35 | elif target_type == 'least': 36 | idxs = torch.arange(num_batch).to(inputs.device) 37 | preds[idxs, gt_label] = 100.0 38 | adv_targets = preds.min(-1)[1] 39 | else: 40 | raise ValueError('Wrong Targeted Attack Type') 41 | 42 | assert (adv_targets == gt_label).long().sum().item() == 0 43 | return adv_targets 44 | 45 | def adv_target_update(gt_label, adv_target, num_batch, num_class): 46 | for i in range(num_batch): 47 | if int(gt_label[i]) == int(adv_target[i]): 48 | adv_target[i] = (int(adv_target[i]) + random.randint(0, num_class-1)) % num_class 49 | return adv_target -------------------------------------------------------------------------------- /attacker/attacks/gn.py: -------------------------------------------------------------------------------- 1 | ############################################################################## 2 | # Modified from https://github.com/Harry24k/adversarial-attacks-pytorch 3 | ############################################################################## 4 | 5 | import torch 6 | import torch.nn as nn 7 | 8 | from ..attacker import Attacker 9 | import utils.general_utils as utils 10 | 11 | class GN(Attacker): 12 | r""" 13 | Add Gaussian Noise. 14 | Arguments: 15 | model (nn.Module): model to attack. 16 | sigma (nn.Module): sigma (DEFAULT: 0.1). 17 | 18 | Shape: 19 | - images: :math:`(N, C, H, W)` where `N = number of batches`, `C = number of channels`, `H = height` and `W = width`. It must have a range [0, 1]. 20 | - labels: :math:`(N)` where each value :math:`y_i` is :math:`0 \leq y_i \leq` `number of labels`. 21 | - output: :math:`(N, C, H, W)`. 22 | 23 | Examples:: 24 | >>> attack = torchattacks.GN(model) 25 | >>> adv_images = attack(images, labels) 26 | 27 | """ 28 | def __init__(self, model, logger, config, sigma=0.1, eps=16): 29 | super(GN, self).__init__("GN", model, logger, config) 30 | self.sigma = sigma 31 | self.eps = eps / 255.0 32 | self.loss = nn.CrossEntropyLoss() 33 | 34 | logger.info('Create Attacker Gaussian Noise with sigma: {}, eps: {}'.format(sigma, eps)) 35 | 36 | def forward(self, images, labels, random_start=False, targeted=False): 37 | """ 38 | Overridden. 39 | """ 40 | images = images.cuda() 41 | adv_images = images + torch.clamp(self.sigma * torch.randn_like(images), min=-self.eps, max=self.eps).detach() 42 | adv_images = torch.clamp(adv_images, min=0, max=1).detach() 43 | 44 | return adv_images 45 | -------------------------------------------------------------------------------- /attacker/attacks/un.py: -------------------------------------------------------------------------------- 1 | ############################################################################## 2 | # Modified from https://github.com/Harry24k/adversarial-attacks-pytorch 3 | ############################################################################## 4 | 5 | import torch 6 | import torch.nn as nn 7 | 8 | from ..attacker import Attacker 9 | import utils.general_utils as utils 10 | 11 | class UN(Attacker): 12 | r""" 13 | Add Uniform Noise. 14 | Arguments: 15 | model (nn.Module): model to attack. 16 | sigma (nn.Module): sigma (DEFAULT: 0.1). 17 | 18 | Shape: 19 | - images: :math:`(N, C, H, W)` where `N = number of batches`, `C = number of channels`, `H = height` and `W = width`. It must have a range [0, 1]. 20 | - labels: :math:`(N)` where each value :math:`y_i` is :math:`0 \leq y_i \leq` `number of labels`. 21 | - output: :math:`(N, C, H, W)`. 22 | 23 | Examples:: 24 | >>> attack = torchattacks.UN(model) 25 | >>> adv_images = attack(images, labels) 26 | 27 | """ 28 | def __init__(self, model, logger, config, sigma=0.1, eps=16): 29 | super(UN, self).__init__("UN", model, logger, config) 30 | self.sigma = sigma 31 | self.eps = eps / 255.0 32 | self.loss = nn.CrossEntropyLoss() 33 | 34 | logger.info('Create Attacker Uniform Noise with sigma: {}'.format(sigma)) 35 | 36 | def forward(self, images, labels, random_start=False, targeted=False): 37 | """ 38 | Overridden. 39 | """ 40 | images = images.cuda() 41 | adv_images = images + torch.clamp(self.sigma * torch.randn_like(images).uniform_(-1,1), min=-self.eps, max=self.eps).detach() 42 | adv_images = torch.clamp(adv_images, min=0, max=1).detach() 43 | 44 | return adv_images 45 | -------------------------------------------------------------------------------- /old_file/old_config/toy.yaml: -------------------------------------------------------------------------------- 1 | output_dir: null 2 | 3 | dataset: 4 | name: TOYData 5 | num_classes: 3 6 | img_size: 64 7 | 8 | networks: 9 | def_file: ./models/ResNet.py 10 | params: {m_type: 'resnet18', num_classes: 10, first_conv_size: 7} 11 | 12 | blackbox_save: false 13 | blackbox_test: false 14 | blackbox_name: 'blackbox_{}_{}.pth' 15 | 16 | training_opt: 17 | num_epochs: 100 18 | batch_size: 128 19 | data_workers: 4 20 | optimizer: 'SGD' # 'Adam' / 'SGD' 21 | optim_params: {lr: 0.1, momentum: 0.9, weight_decay: 0.0005} 22 | scheduler: 'step' # 'cosine' / 'step' 23 | scheduler_params: {endlr: 0.0, gamma: 0.2, milestones: [25, 50, 75]} 24 | 25 | mixup_on: false 26 | 27 | bpfc_opt: 28 | bpfc_on: false # turn on BPFC training 29 | p_val: 7 # (k in paper) 5,6,7 for cifar10, FMNIST, MNIST 30 | w_ce: 1 # cross entropy loss weight 31 | w_reg: 1 # regression loss weight 32 | mul_ru: 9 # regression weight multiplier 33 | milestones: [25,50,75] # update w_reg by mul_ru at K-th epoch 34 | 35 | attacker_opt: 36 | attack_type: 'FGSM' # Adversarial attack algorithm type, candidates: 'PGD', 'PGDL2', 'FGSM', 'FFGSM', 'GN', 'UN' 37 | attack_set: 'setting1' # attack setting is under attacker_config.yaml 38 | eot_iter: 1 # EOT version of attacker is applied when eot_iter > 1 39 | 40 | adv_train: false # Adversarial training 41 | adv_val: false # Adversarial attack during inference 42 | 43 | save_test: # for val 44 | save_data: true # for val 45 | file_name: 'adv_images.pth' # for val 46 | save_length: 10 # only save first 10 batch for efficiency 47 | 48 | logger_opt: 49 | print_grad: false 50 | print_iter: 100 51 | 52 | checkpoint_opt: 53 | checkpoint_step: 10 54 | checkpoint_name: 'test_model.pth' -------------------------------------------------------------------------------- /old_file/old_config/mnist.yaml: -------------------------------------------------------------------------------- 1 | output_dir: null 2 | 3 | dataset: 4 | name: mnist 5 | data_path: ./data/MNIST 6 | img_size: 32 7 | 8 | networks: 9 | def_file: ./models/ResNet.py 10 | params: {m_type: 'resnet18', num_classes: 10, first_conv_size: 7} 11 | 12 | blackbox_save: false 13 | blackbox_test: false 14 | blackbox_name: 'blackbox_{}_{}.pth' 15 | 16 | training_opt: 17 | num_epochs: 100 18 | batch_size: 128 19 | data_workers: 4 20 | optimizer: 'SGD' # 'Adam' / 'SGD' 21 | optim_params: {lr: 0.1, momentum: 0.9, weight_decay: 0.0005} 22 | scheduler: 'step' # 'cosine' / 'step' 23 | scheduler_params: {endlr: 0.0, gamma: 0.2, milestones: [25, 50, 75]} 24 | 25 | mixup_on: false 26 | 27 | bpfc_opt: 28 | bpfc_on: false # turn on BPFC training 29 | p_val: 7 # (k in paper) 5,6,7 for cifar10, FMNIST, MNIST 30 | w_ce: 1 # cross entropy loss weight 31 | w_reg: 1 # regression loss weight 32 | mul_ru: 9 # regression weight multiplier 33 | milestones: [25,50,75] # update w_reg by mul_ru at K-th epoch 34 | 35 | attacker_opt: 36 | attack_type: 'FGSM' # Adversarial attack algorithm type, candidates: 'PGD', 'PGDL2', 'FGSM', 'FFGSM', 'GN', 'UN' 37 | attack_set: 'setting1' # attack setting is under attacker_config.yaml 38 | eot_iter: 1 # EOT version of attacker is applied when eot_iter > 1 39 | 40 | adv_train: false # Adversarial training 41 | adv_val: false # Adversarial attack during inference 42 | 43 | save_test: # for val 44 | save_data: false # for val 45 | file_name: 'adv_images.pth' # for val 46 | save_length: 5 # only save first 10 batch for efficiency 47 | 48 | logger_opt: 49 | print_grad: false 50 | print_iter: 100 51 | 52 | checkpoint_opt: 53 | checkpoint_step: 10 54 | checkpoint_name: 'test_model.pth' -------------------------------------------------------------------------------- /config/_mini_imagenet_WRN.yaml: -------------------------------------------------------------------------------- 1 | output_dir: null 2 | 3 | dataset: 4 | name: mini-imagenet 5 | data_path: /gruntdata3/kaihua/datasets/imagenet/ILSVRC/Data/CLS-LOC 6 | category_path: ./data/mini-ImageNet/category_frame.csv 7 | train_path: ./data/mini-ImageNet/train_frame.csv 8 | test_path: ./data/mini-ImageNet/test_frame.csv 9 | val_path: ./data/mini-ImageNet/val_frame.csv 10 | num_classes: 100 11 | img_size: 64 12 | rand_aug: false 13 | 14 | networks: 15 | def_file: ./models/WideResNet.py 16 | params: {m_type: 'WRN34-10', num_classes: 100} 17 | 18 | strategy: 19 | train_type: 'baseline' # baseline / mixup / simsiam 20 | test_type: 'baseline' 21 | 22 | attacker_opt: 23 | adv_val: false # Adversarial attack during inference 24 | adv_train: false # Adversarial training 25 | attack_type: 'FGSM' # Adversarial attack algorithm type, candidates: 'PGD', 'PGDL2', 'FGSM', 'FFGSM', 'GN', 'UN' 26 | attack_set: 'setting1' # attack setting is under attacker_config.yaml 27 | eot_iter: 1 # EOT version of attacker is applied when eot_iter > 1 28 | 29 | 30 | training_opt: 31 | num_epochs: 110 32 | batch_size: 128 33 | data_workers: 4 34 | optimizer: 'SGD' # 'Adam' / 'SGD' 35 | optim_params: {lr: 0.1, momentum: 0.9, weight_decay: 0.0005} 36 | scheduler: 'step' # 'cosine' / 'step' 37 | scheduler_params: {endlr: 0.0, gamma: 0.1, milestones: [10, 100, 105]} 38 | 39 | test_opt: 40 | save_data: false # for val 41 | file_name: 'adv_images.pth' # for val 42 | save_length: 5 # only save first 10 batch for efficiency 43 | 44 | 45 | logger_opt: 46 | print_grad: false 47 | print_iter: 100 48 | 49 | checkpoint_opt: 50 | save_best: true # only save the model that better than previous epoches (except the last epoch) 51 | checkpoint_step: 10 52 | checkpoint_name: 'test_model.pth' -------------------------------------------------------------------------------- /old_file/old_config/cifar10.yaml: -------------------------------------------------------------------------------- 1 | output_dir: null 2 | 3 | dataset: 4 | name: cifar10 5 | data_path: ./data/CIFAR10 6 | img_size: 32 7 | 8 | networks: 9 | def_file: ./models/ResNet.py 10 | params: {m_type: 'resnet18', num_classes: 10, first_conv_size: 7} 11 | 12 | blackbox_save: false 13 | blackbox_test: false 14 | blackbox_name: 'blackbox_{}_{}.pth' 15 | 16 | training_opt: 17 | num_epochs: 100 18 | batch_size: 128 19 | data_workers: 4 20 | optimizer: 'SGD' # 'Adam' / 'SGD' 21 | optim_params: {lr: 0.1, momentum: 0.9, weight_decay: 0.0005} 22 | scheduler: 'step' # 'cosine' / 'step' 23 | scheduler_params: {endlr: 0.0, gamma: 0.2, milestones: [25, 50, 75]} 24 | 25 | mixup_on: false 26 | 27 | bpfc_opt: 28 | bpfc_on: false # turn on BPFC training 29 | p_val: 5 # (k in paper) 5,6,7 for cifar10, FMNIST, MNIST 30 | w_ce: 1 # cross entropy loss weight 31 | w_reg: 1 # regression loss weight 32 | mul_ru: 9 # regression weight multiplier 33 | milestones: [25,50,75] # update w_reg by mul_ru at K-th epoch 34 | 35 | attacker_opt: 36 | attack_type: 'FGSM' # Adversarial attack algorithm type, candidates: 'PGD', 'PGDL2', 'FGSM', 'FFGSM', 'GN', 'UN' 37 | attack_set: 'setting1' # attack setting is under attacker_config.yaml 38 | eot_iter: 1 # EOT version of attacker is applied when eot_iter > 1 39 | 40 | adv_train: false # Adversarial training 41 | adv_val: false # Adversarial attack during inference 42 | 43 | save_test: # for val 44 | save_data: false # for val 45 | file_name: 'adv_images.pth' # for val 46 | save_length: 5 # only save first 10 batch for efficiency 47 | 48 | logger_opt: 49 | print_grad: false 50 | print_iter: 100 51 | 52 | checkpoint_opt: 53 | checkpoint_step: 10 54 | checkpoint_name: 'test_model.pth' -------------------------------------------------------------------------------- /old_file/old_config/mnist_rs.yaml: -------------------------------------------------------------------------------- 1 | output_dir: null 2 | 3 | dataset: 4 | name: mnist 5 | data_path: ./data/MNIST 6 | img_size: 32 7 | 8 | networks: 9 | def_file: ./models/ResNet_RS.py 10 | params: {m_type: 'resnet18', num_classes: 10, first_conv_size: 7, num_trial: 10, sigma: 0.25} 11 | 12 | blackbox_save: false 13 | blackbox_test: false 14 | blackbox_name: 'blackbox_{}_{}.pth' 15 | 16 | training_opt: 17 | num_epochs: 100 18 | batch_size: 128 19 | data_workers: 4 20 | optimizer: 'SGD' # 'Adam' / 'SGD' 21 | optim_params: {lr: 0.1, momentum: 0.9, weight_decay: 0.0005} 22 | scheduler: 'step' # 'cosine' / 'step' 23 | scheduler_params: {endlr: 0.0, gamma: 0.2, milestones: [25, 50, 75]} 24 | 25 | bpfc_opt: 26 | bpfc_on: false # turn on BPFC training 27 | p_val: 7 # (k in paper) 5,6,7 for cifar10, FMNIST, MNIST 28 | w_ce: 1 # cross entropy loss weight 29 | w_reg: 1 # regression loss weight 30 | mul_ru: 9 # regression weight multiplier 31 | milestones: [25,50,75] # update w_reg by mul_ru at K-th epoch 32 | 33 | attacker_opt: 34 | attack_type: 'FGSM' # Adversarial attack algorithm type, candidates: 'PGD', 'PGDL2', 'FGSM', 'FFGSM', 'GN', 'UN' 35 | attack_set: 'setting1' # attack setting is under attacker_config.yaml 36 | eot_iter: 1 # EOT version of attacker is applied when eot_iter > 1 37 | 38 | adv_train: false # Adversarial training 39 | adv_val: false # Adversarial attack during inference 40 | 41 | save_test: # for val 42 | save_data: false # for val 43 | file_name: 'adv_images.pth' # for val 44 | save_length: 5 # only save first 10 batch for efficiency 45 | 46 | logger_opt: 47 | print_grad: false 48 | print_iter: 100 49 | 50 | checkpoint_opt: 51 | checkpoint_step: 10 52 | checkpoint_name: 'test_model.pth' -------------------------------------------------------------------------------- /config/_mini_imagenet.yaml: -------------------------------------------------------------------------------- 1 | output_dir: null 2 | 3 | dataset: 4 | name: mini-imagenet 5 | data_path: /gruntdata3/kaihua/datasets/imagenet/ILSVRC/Data/CLS-LOC 6 | category_path: ./data/mini-ImageNet/category_frame.csv 7 | train_path: ./data/mini-ImageNet/train_frame.csv 8 | test_path: ./data/mini-ImageNet/test_frame.csv 9 | val_path: ./data/mini-ImageNet/val_frame.csv 10 | num_classes: 100 11 | img_size: 64 12 | rand_aug: false 13 | 14 | networks: 15 | def_file: ./models/ResNet.py 16 | params: {m_type: 'resnet18', cls_type: 'fc', num_classes: 100} 17 | 18 | strategy: 19 | train_type: 'baseline' # baseline / mixup / simsiam 20 | test_type: 'baseline' 21 | 22 | attacker_opt: 23 | adv_val: false # Adversarial attack during inference 24 | adv_train: false # Adversarial training 25 | attack_type: 'FGSM' # Adversarial attack algorithm type, candidates: 'PGD', 'PGDL2', 'FGSM', 'FFGSM', 'GN', 'UN' 26 | attack_set: 'setting1' # attack setting is under attacker_config.yaml 27 | eot_iter: 1 # EOT version of attacker is applied when eot_iter > 1 28 | 29 | 30 | training_opt: 31 | num_epochs: 110 32 | batch_size: 128 33 | data_workers: 4 34 | optimizer: 'SGD' # 'Adam' / 'SGD' 35 | optim_params: {lr: 0.1, momentum: 0.9, weight_decay: 0.0005} 36 | scheduler: 'step' # 'cosine' / 'step' 37 | scheduler_params: {endlr: 0.0, gamma: 0.1, milestones: [10, 100, 105]} 38 | 39 | test_opt: 40 | save_data: false # for val 41 | file_name: 'adv_images.pth' # for val 42 | save_length: 5 # only save first 10 batch for efficiency 43 | 44 | 45 | logger_opt: 46 | print_grad: false 47 | print_iter: 100 48 | 49 | checkpoint_opt: 50 | save_best: true # only save the model that better than previous epoches (except the last epoch) 51 | checkpoint_step: 10 52 | checkpoint_name: 'test_model.pth' -------------------------------------------------------------------------------- /old_file/old_config/cifar10_rs.yaml: -------------------------------------------------------------------------------- 1 | output_dir: null 2 | 3 | dataset: 4 | name: cifar10 5 | data_path: ./data/CIFAR10 6 | img_size: 32 7 | 8 | networks: 9 | def_file: ./models/ResNet_RS.py 10 | params: {m_type: 'resnet18', num_classes: 10, first_conv_size: 7, num_trial: 10, sigma: 0.25} 11 | 12 | blackbox_save: false 13 | blackbox_test: false 14 | blackbox_name: 'blackbox_{}_{}.pth' 15 | 16 | training_opt: 17 | num_epochs: 100 18 | batch_size: 128 19 | data_workers: 4 20 | optimizer: 'SGD' # 'Adam' / 'SGD' 21 | optim_params: {lr: 0.1, momentum: 0.9, weight_decay: 0.0005} 22 | scheduler: 'step' # 'cosine' / 'step' 23 | scheduler_params: {endlr: 0.0, gamma: 0.2, milestones: [25, 50, 75]} 24 | 25 | bpfc_opt: 26 | bpfc_on: false # turn on BPFC training 27 | p_val: 5 # (k in paper) 5,6,7 for cifar10, FMNIST, MNIST 28 | w_ce: 1 # cross entropy loss weight 29 | w_reg: 1 # regression loss weight 30 | mul_ru: 9 # regression weight multiplier 31 | milestones: [25,50,75] # update w_reg by mul_ru at K-th epoch 32 | 33 | attacker_opt: 34 | attack_type: 'FGSM' # Adversarial attack algorithm type, candidates: 'PGD', 'PGDL2', 'FGSM', 'FFGSM', 'GN', 'UN' 35 | attack_set: 'setting1' # attack setting is under attacker_config.yaml 36 | eot_iter: 1 # EOT version of attacker is applied when eot_iter > 1 37 | 38 | adv_train: false # Adversarial training 39 | adv_val: false # Adversarial attack during inference 40 | 41 | save_test: # for val 42 | save_data: false # for val 43 | file_name: 'adv_images.pth' # for val 44 | save_length: 5 # only save first 10 batch for efficiency 45 | 46 | logger_opt: 47 | print_grad: false 48 | print_iter: 100 49 | 50 | checkpoint_opt: 51 | checkpoint_step: 10 52 | checkpoint_name: 'test_model.pth' -------------------------------------------------------------------------------- /config/_cifar10_bpfc.yaml: -------------------------------------------------------------------------------- 1 | output_dir: null 2 | 3 | dataset: 4 | name: cifar10 5 | data_path: ./data/CIFAR10 6 | img_size: 32 7 | rand_aug: false 8 | 9 | networks: 10 | def_file: ./models/ResNet.py 11 | params: {m_type: 'resnet18', cls_type: 'fc', num_classes: 10} 12 | 13 | strategy: 14 | train_type: 'bpfc' # baseline / mixup / bpfc 15 | test_type: 'baseline' 16 | 17 | attacker_opt: 18 | adv_val: false # Adversarial attack during inference 19 | adv_train: false # Adversarial training 20 | attack_type: 'FGSM' # Adversarial attack algorithm type, candidates: 'PGD', 'PGDL2', 'FGSM', 'FFGSM', 'GN', 'UN' 21 | attack_set: 'setting1' # attack setting is under attacker_config.yaml 22 | eot_iter: 1 # EOT version of attacker is applied when eot_iter > 1 23 | 24 | training_opt: 25 | num_epochs: 110 26 | batch_size: 128 27 | data_workers: 4 28 | optimizer: 'SGD' # 'Adam' / 'SGD' 29 | optim_params: {lr: 0.1, momentum: 0.9, weight_decay: 0.0005} 30 | scheduler: 'step' # 'cosine' / 'step' 31 | scheduler_params: {endlr: 0.0, gamma: 0.1, milestones: [10, 100, 105]} 32 | 33 | bpfc_opt: 34 | p_val: 5 # (k in paper) 5,6,7 for cifar10, FMNIST, MNIST 35 | w_ce: 1 # cross entropy loss weight 36 | w_reg: 1 # regression loss weight 37 | mul_ru: 9 # regression weight multiplier 38 | milestones: [25,50,75] # update w_reg by mul_ru at K-th epoch 39 | 40 | test_opt: 41 | save_data: false # for val 42 | file_name: 'adv_images.pth' # for val 43 | save_length: 5 # only save first 10 batch for efficiency 44 | 45 | 46 | logger_opt: 47 | print_grad: false 48 | print_iter: 100 49 | 50 | checkpoint_opt: 51 | save_best: true # only save the model that better than previous epoches (except the last epoch) 52 | checkpoint_step: 10 53 | checkpoint_name: 'test_model.pth' -------------------------------------------------------------------------------- /config/_mini_imagenet_rs.yaml: -------------------------------------------------------------------------------- 1 | output_dir: null 2 | 3 | dataset: 4 | name: mini-imagenet 5 | data_path: /gruntdata3/kaihua/datasets/imagenet/ILSVRC/Data/CLS-LOC 6 | category_path: ./data/mini-ImageNet/category_frame.csv 7 | train_path: ./data/mini-ImageNet/train_frame.csv 8 | test_path: ./data/mini-ImageNet/test_frame.csv 9 | val_path: ./data/mini-ImageNet/val_frame.csv 10 | num_classes: 100 11 | img_size: 64 12 | rand_aug: false 13 | 14 | networks: 15 | def_file: ./models/ResNet_RS.py 16 | params: {m_type: 'resnet18', cls_type: 'fc', num_classes: 100, num_trial: 10, sigma: 0.25} 17 | 18 | strategy: 19 | train_type: 'baseline' # baseline / mixup / simsiam 20 | test_type: 'baseline' 21 | 22 | attacker_opt: 23 | adv_val: false # Adversarial attack during inference 24 | adv_train: false # Adversarial training 25 | attack_type: 'FGSM' # Adversarial attack algorithm type, candidates: 'PGD', 'PGDL2', 'FGSM', 'FFGSM', 'GN', 'UN' 26 | attack_set: 'setting1' # attack setting is under attacker_config.yaml 27 | eot_iter: 1 # EOT version of attacker is applied when eot_iter > 1 28 | 29 | 30 | training_opt: 31 | num_epochs: 110 32 | batch_size: 128 33 | data_workers: 4 34 | optimizer: 'SGD' # 'Adam' / 'SGD' 35 | optim_params: {lr: 0.1, momentum: 0.9, weight_decay: 0.0005} 36 | scheduler: 'step' # 'cosine' / 'step' 37 | scheduler_params: {endlr: 0.0, gamma: 0.1, milestones: [10, 100, 105]} 38 | 39 | test_opt: 40 | save_data: false # for val 41 | file_name: 'adv_images.pth' # for val 42 | save_length: 5 # only save first 10 batch for efficiency 43 | 44 | 45 | logger_opt: 46 | print_grad: false 47 | print_iter: 100 48 | 49 | checkpoint_opt: 50 | save_best: true # only save the model that better than previous epoches (except the last epoch) 51 | checkpoint_step: 10 52 | checkpoint_name: 'test_model.pth' -------------------------------------------------------------------------------- /attacker/attacks/bfs.py: -------------------------------------------------------------------------------- 1 | ############################################################################## 2 | # Modified from https://github.com/Harry24k/adversarial-attacks-pytorch 3 | ############################################################################## 4 | 5 | import torch 6 | import torch.nn as nn 7 | 8 | from ..attacker import Attacker 9 | import utils.general_utils as utils 10 | 11 | class BFS(Attacker): 12 | ''' 13 | Brute-Fore Search 14 | ''' 15 | def __init__(self, model, logger, config, sigma=0.1, eps=16, steps=100, eot_iter=100): 16 | super(BFS, self).__init__("BFS", model, logger, config) 17 | self.sigma = sigma 18 | self.eps = eps / 255.0 19 | self.steps = steps 20 | self.loss = nn.CrossEntropyLoss() 21 | 22 | logger.info('Create Attacker BFS with sigma: {}, eps: {}, steps: {}'.format(sigma, eps, steps)) 23 | 24 | def forward(self, images, labels, random_start=False, targeted=False): 25 | """ 26 | Overridden. 27 | Note: BFS doesn't contain random_start 28 | """ 29 | 30 | images, labels = images.cuda(), labels.cuda() 31 | 32 | final_images = images.clone() 33 | 34 | # EOT is applied when eot_iter > 1 35 | for _ in range(self.steps): 36 | noise = torch.clamp(self.sigma * torch.randn_like(images), min=-self.eps, max=self.eps).detach() 37 | adv_images = torch.clamp(images + noise, min=0, max=1).detach() 38 | 39 | outputs = self.model(adv_images) 40 | if isinstance(outputs, tuple): 41 | outputs = outputs[0] 42 | 43 | success = (labels != outputs.max(-1)[-1]).float().unsqueeze(-1).unsqueeze(-1).unsqueeze(-1) 44 | # update successed attack 45 | final_images = success * adv_images + (1.0 - success) * final_images 46 | 47 | return final_images 48 | -------------------------------------------------------------------------------- /config/_cifar100_bpfc.yaml: -------------------------------------------------------------------------------- 1 | output_dir: null 2 | 3 | dataset: 4 | name: cifar100 5 | data_path: ./data/CIFAR100 6 | img_size: 32 7 | rand_aug: false 8 | 9 | networks: 10 | def_file: ./models/ResNet.py 11 | params: {m_type: 'resnet18', cls_type: 'fc', num_classes: 100} 12 | 13 | strategy: 14 | train_type: 'bpfc' # baseline / mixup / bpfc 15 | test_type: 'baseline' 16 | 17 | attacker_opt: 18 | adv_val: false # Adversarial attack during inference 19 | adv_train: false # Adversarial training 20 | attack_type: 'FGSM' # Adversarial attack algorithm type, candidates: 'PGD', 'PGDL2', 'FGSM', 'FFGSM', 'GN', 'UN' 21 | attack_set: 'setting1' # attack setting is under attacker_config.yaml 22 | eot_iter: 1 # EOT version of attacker is applied when eot_iter > 1 23 | 24 | training_opt: 25 | num_epochs: 110 26 | batch_size: 128 27 | data_workers: 4 28 | optimizer: 'SGD' # 'Adam' / 'SGD' 29 | optim_params: {lr: 0.1, momentum: 0.9, weight_decay: 0.0005} 30 | scheduler: 'step' # 'cosine' / 'step' 31 | scheduler_params: {endlr: 0.0, gamma: 0.1, milestones: [10, 100, 105]} 32 | 33 | bpfc_opt: 34 | p_val: 5 # (k in paper) 5,6,7 for cifar10, FMNIST, MNIST 35 | w_ce: 1 # cross entropy loss weight 36 | w_reg: 1 # regression loss weight 37 | mul_ru: 9 # regression weight multiplier 38 | milestones: [25,50,75] # update w_reg by mul_ru at K-th epoch 39 | 40 | test_opt: 41 | save_data: false # for val 42 | file_name: 'adv_images.pth' # for val 43 | save_length: 5 # only save first 10 batch for efficiency 44 | 45 | 46 | logger_opt: 47 | print_grad: false 48 | print_iter: 100 49 | 50 | checkpoint_opt: 51 | save_best: true # only save the model that better than previous epoches (except the last epoch) 52 | checkpoint_step: 10 53 | checkpoint_name: 'test_model.pth' -------------------------------------------------------------------------------- /config/_ctoy_ciiv.yaml: -------------------------------------------------------------------------------- 1 | output_dir: null 2 | 3 | dataset: 4 | name: TOYData 5 | num_classes: 3 6 | img_size: 64 7 | 8 | networks: 9 | def_file: ./models/ResNet_CiiV.py 10 | params: {m_type: 'resnet18', num_classes: 3, num_sample: 3, aug_weight: 0.8, mask_center: [20, 32, 44]} 11 | 12 | strategy: 13 | train_type: 'ciiv' 14 | test_type: 'ciiv' 15 | 16 | attacker_opt: 17 | adv_val: false # Adversarial attack during inference 18 | adv_train: false # Adversarial training 19 | attack_type: 'FGSM' # Adversarial attack algorithm type, candidates: 'PGD', 'PGDL2', 'FGSM', 'FFGSM', 'GN', 'UN' 20 | attack_set: 'setting1' # attack setting is under attacker_config.yaml 21 | eot_iter: 1 # EOT version of attacker is applied when eot_iter > 1 22 | 23 | training_opt: 24 | num_epochs: 7 25 | batch_size: 128 26 | data_workers: 4 27 | optimizer: 'SGD' # 'Adam' / 'SGD' 28 | optim_params: {lr: 0.1, momentum: 0.9, weight_decay: 0.0005} 29 | scheduler: 'step' # 'cosine' / 'step' 30 | scheduler_params: {endlr: 0.0, gamma: 0.1, milestones: [10, 100, 105]} 31 | 32 | inst_sample: 33 | w_ce: 1 # cross entropy loss weight 34 | w_reg: 0.1 # regression loss weight 35 | mul_ru: 10 # regression weight multiplier 36 | milestones: [5, 7, 9] # update w_reg by mul_ru at K-th epoch 37 | num_loop: 9 # number of consistent loops 38 | reg_loss: 'L1' # L1 or L2 39 | ce_smooth: false # use z_score to smooth the ce loss 40 | 41 | 42 | test_opt: 43 | save_data: true # for val 44 | file_name: 'adv_images.pth' # for val 45 | save_length: 10 # only save first 10 batch for efficiency 46 | 47 | 48 | logger_opt: 49 | print_grad: false 50 | print_iter: 100 51 | 52 | checkpoint_opt: 53 | save_best: true # only save the model that better than previous epoches (except the last epoch) 54 | checkpoint_step: 1 55 | checkpoint_name: 'test_model.pth' -------------------------------------------------------------------------------- /config/_cifar10_ciiv_VGG.yaml: -------------------------------------------------------------------------------- 1 | output_dir: null 2 | 3 | dataset: 4 | name: cifar10 5 | data_path: ./data/CIFAR10 6 | img_size: 32 7 | rand_aug: false 8 | 9 | networks: 10 | def_file: ./models/VGG_CiiV.py 11 | params: {m_type: 'vgg13', num_classes: 10, num_sample: 3, aug_weight: 0.9, mask_center: [16, 5, 27]} 12 | 13 | strategy: 14 | train_type: 'ciiv' 15 | test_type: 'ciiv' 16 | 17 | attacker_opt: 18 | adv_val: false # Adversarial attack during inference 19 | adv_train: false # Adversarial training 20 | attack_type: 'FGSM' # Adversarial attack algorithm type, candidates: 'PGD', 'PGDL2', 'FGSM', 'FFGSM', 'GN', 'UN' 21 | attack_set: 'setting1' # attack setting is under attacker_config.yaml 22 | eot_iter: 1 # EOT version of attacker is applied when eot_iter > 1 23 | 24 | training_opt: 25 | num_epochs: 110 26 | batch_size: 128 27 | data_workers: 4 28 | optimizer: 'SGD' # 'Adam' / 'SGD' 29 | optim_params: {lr: 0.01, momentum: 0.9, weight_decay: 0.0005} 30 | scheduler: 'step' # 'cosine' / 'step' 31 | scheduler_params: {endlr: 0.0, gamma: 0.1, milestones: [10, 100, 105]} 32 | 33 | inst_sample: 34 | w_ce: 1 # cross entropy loss weight 35 | w_reg: 0.01 # regression loss weight 36 | mul_ru: 10 # regression weight multiplier 37 | milestones: [25,50,75] # update w_reg by mul_ru at K-th epoch 38 | num_loop: 9 # number of consistent loops 39 | reg_loss: 'L1' # L1 or L2 40 | ce_smooth: false # use z_score to smooth the ce loss 41 | 42 | 43 | test_opt: 44 | save_data: false # for val 45 | file_name: 'adv_images.pth' # for val 46 | save_length: 5 # only save first 10 batch for efficiency 47 | 48 | 49 | logger_opt: 50 | print_grad: false 51 | print_iter: 100 52 | 53 | checkpoint_opt: 54 | save_best: true # only save the model that better than previous epoches (except the last epoch) 55 | checkpoint_step: 10 56 | checkpoint_name: 'test_model.pth' -------------------------------------------------------------------------------- /config/_cifar100_ciiv.yaml: -------------------------------------------------------------------------------- 1 | output_dir: null 2 | 3 | dataset: 4 | name: cifar100 5 | data_path: ./data/CIFAR100 6 | img_size: 32 7 | rand_aug: false 8 | 9 | networks: 10 | def_file: ./models/ResNet_CiiV.py 11 | params: {m_type: 'resnet18', num_classes: 100, num_sample: 3, aug_weight: 0.9, mask_center: [16, 5, 27]} 12 | 13 | strategy: 14 | train_type: 'ciiv' 15 | test_type: 'ciiv' 16 | 17 | attacker_opt: 18 | adv_val: false # Adversarial attack during inference 19 | adv_train: false # Adversarial training 20 | attack_type: 'FGSM' # Adversarial attack algorithm type, candidates: 'PGD', 'PGDL2', 'FGSM', 'FFGSM', 'GN', 'UN' 21 | attack_set: 'setting1' # attack setting is under attacker_config.yaml 22 | eot_iter: 1 # EOT version of attacker is applied when eot_iter > 1 23 | 24 | training_opt: 25 | num_epochs: 110 26 | batch_size: 128 27 | data_workers: 4 28 | optimizer: 'SGD' # 'Adam' / 'SGD' 29 | optim_params: {lr: 0.1, momentum: 0.9, weight_decay: 0.0005} 30 | scheduler: 'step' # 'cosine' / 'step' 31 | scheduler_params: {endlr: 0.0, gamma: 0.1, milestones: [10, 100, 105]} 32 | 33 | inst_sample: 34 | w_ce: 1 # cross entropy loss weight 35 | w_reg: 0.1 # regression loss weight 36 | mul_ru: 10 # regression weight multiplier 37 | milestones: [25,50,75] # update w_reg by mul_ru at K-th epoch 38 | num_loop: 9 # number of consistent loops 39 | reg_loss: 'L1' # L1 or L2 40 | ce_smooth: false # use z_score to smooth the ce loss 41 | 42 | 43 | test_opt: 44 | save_data: false # for val 45 | file_name: 'adv_images.pth' # for val 46 | save_length: 5 # only save first 10 batch for efficiency 47 | 48 | 49 | logger_opt: 50 | print_grad: false 51 | print_iter: 100 52 | 53 | checkpoint_opt: 54 | save_best: true # only save the model that better than previous epoches (except the last epoch) 55 | checkpoint_step: 10 56 | checkpoint_name: 'test_model.pth' -------------------------------------------------------------------------------- /config/_cifar100_ciiv_VGG.yaml: -------------------------------------------------------------------------------- 1 | output_dir: null 2 | 3 | dataset: 4 | name: cifar100 5 | data_path: ./data/CIFAR100 6 | img_size: 32 7 | rand_aug: false 8 | 9 | networks: 10 | def_file: ./models/VGG_CiiV.py 11 | params: {m_type: 'vgg13', num_classes: 100, num_sample: 3, aug_weight: 0.9, mask_center: [16, 5, 27]} 12 | 13 | strategy: 14 | train_type: 'ciiv' 15 | test_type: 'ciiv' 16 | 17 | attacker_opt: 18 | adv_val: false # Adversarial attack during inference 19 | adv_train: false # Adversarial training 20 | attack_type: 'FGSM' # Adversarial attack algorithm type, candidates: 'PGD', 'PGDL2', 'FGSM', 'FFGSM', 'GN', 'UN' 21 | attack_set: 'setting1' # attack setting is under attacker_config.yaml 22 | eot_iter: 1 # EOT version of attacker is applied when eot_iter > 1 23 | 24 | training_opt: 25 | num_epochs: 110 26 | batch_size: 128 27 | data_workers: 4 28 | optimizer: 'SGD' # 'Adam' / 'SGD' 29 | optim_params: {lr: 0.01, momentum: 0.9, weight_decay: 0.0005} 30 | scheduler: 'step' # 'cosine' / 'step' 31 | scheduler_params: {endlr: 0.0, gamma: 0.1, milestones: [10, 100, 105]} 32 | 33 | inst_sample: 34 | w_ce: 1 # cross entropy loss weight 35 | w_reg: 0.005 # regression loss weight 36 | mul_ru: 10 # regression weight multiplier 37 | milestones: [25,50,75] # update w_reg by mul_ru at K-th epoch 38 | num_loop: 9 # number of consistent loops 39 | reg_loss: 'L1' # L1 or L2 40 | ce_smooth: false # use z_score to smooth the ce loss 41 | 42 | 43 | test_opt: 44 | save_data: false # for val 45 | file_name: 'adv_images.pth' # for val 46 | save_length: 5 # only save first 10 batch for efficiency 47 | 48 | 49 | logger_opt: 50 | print_grad: false 51 | print_iter: 100 52 | 53 | checkpoint_opt: 54 | save_best: true # only save the model that better than previous epoches (except the last epoch) 55 | checkpoint_step: 10 56 | checkpoint_name: 'test_model.pth' -------------------------------------------------------------------------------- /config/_cifar10_ciiv.yaml: -------------------------------------------------------------------------------- 1 | output_dir: null 2 | 3 | dataset: 4 | name: cifar10 5 | data_path: ./data/CIFAR10 6 | img_size: 32 7 | rand_aug: false 8 | 9 | networks: 10 | def_file: ./models/ResNet_CiiV.py 11 | params: {m_type: 'resnet18', num_classes: 10, num_sample: 3, aug_weight: 0.9, mask_center: [16, 5, 27]} 12 | 13 | strategy: 14 | train_type: 'ciiv' 15 | test_type: 'ciiv' 16 | 17 | attacker_opt: 18 | adv_val: false # Adversarial attack during inference 19 | adv_train: false # Adversarial training 20 | attack_type: 'FGSM' # Adversarial attack algorithm type, candidates: 'PGD', 'PGDL2', 'FGSM', 'FFGSM', 'GN', 'UN' 21 | attack_set: 'setting1' # attack setting is under attacker_config.yaml 22 | eot_iter: 1 # EOT version of attacker is applied when eot_iter > 1 23 | 24 | training_opt: 25 | num_epochs: 110 26 | batch_size: 128 27 | data_workers: 4 28 | optimizer: 'SGD' # 'Adam' / 'SGD' 29 | optim_params: {lr: 0.1, momentum: 0.9, weight_decay: 0.0005} 30 | scheduler: 'step' # 'cosine' / 'step' 31 | scheduler_params: {endlr: 0.0, gamma: 0.1, milestones: [10, 100, 105]} 32 | 33 | inst_sample: 34 | w_ce: 1 # cross entropy loss weight 35 | w_reg: 0.1 # regression loss weight 36 | mul_ru: 10 # regression weight multiplier 37 | milestones: [25,50,75] # update w_reg by mul_ru at K-th epoch 38 | num_loop: 9 # number of consistent loops 39 | reg_loss: 'L1' # L1 or L2 40 | ce_smooth: false # use z_score to smooth the ce loss 41 | 42 | 43 | test_opt: 44 | save_data: false # for val 45 | file_name: 'adv_images.pth' # for val 46 | save_length: 5 # only save first 10 batch for efficiency 47 | 48 | 49 | logger_opt: 50 | print_grad: false 51 | print_iter: 100 52 | 53 | checkpoint_opt: 54 | save_best: true # only save the model that better than previous epoches (except the last epoch) 55 | checkpoint_step: 10 56 | checkpoint_name: 'test_model.pth' -------------------------------------------------------------------------------- /config/_cifar10_ciiv_rc.yaml: -------------------------------------------------------------------------------- 1 | output_dir: null 2 | 3 | dataset: 4 | name: cifar10 5 | data_path: ./data/CIFAR10 6 | img_size: 32 7 | rand_aug: false 8 | 9 | networks: 10 | def_file: ./models/ResNet_CiiV_RC.py 11 | params: {m_type: 'resnet18', num_classes: 10, num_sample: 3, aug_weight: 0.9, mask_center: [5, 27]} 12 | 13 | strategy: 14 | train_type: 'ciiv' 15 | test_type: 'ciiv' 16 | 17 | attacker_opt: 18 | adv_val: false # Adversarial attack during inference 19 | adv_train: false # Adversarial training 20 | attack_type: 'FGSM' # Adversarial attack algorithm type, candidates: 'PGD', 'PGDL2', 'FGSM', 'FFGSM', 'GN', 'UN' 21 | attack_set: 'setting1' # attack setting is under attacker_config.yaml 22 | eot_iter: 1 # EOT version of attacker is applied when eot_iter > 1 23 | 24 | training_opt: 25 | num_epochs: 110 26 | batch_size: 128 27 | data_workers: 4 28 | optimizer: 'SGD' # 'Adam' / 'SGD' 29 | optim_params: {lr: 0.1, momentum: 0.9, weight_decay: 0.0005} 30 | scheduler: 'step' # 'cosine' / 'step' 31 | scheduler_params: {endlr: 0.0, gamma: 0.1, milestones: [10, 100, 105]} 32 | 33 | inst_sample: 34 | w_ce: 1 # cross entropy loss weight 35 | w_reg: 0.1 # regression loss weight 36 | mul_ru: 10 # regression weight multiplier 37 | milestones: [25,50,75] # update w_reg by mul_ru at K-th epoch 38 | num_loop: 9 # number of consistent loops 39 | reg_loss: 'L1' # L1 or L2 40 | ce_smooth: false # use z_score to smooth the ce loss 41 | 42 | 43 | test_opt: 44 | save_data: false # for val 45 | file_name: 'adv_images.pth' # for val 46 | save_length: 5 # only save first 10 batch for efficiency 47 | 48 | 49 | logger_opt: 50 | print_grad: false 51 | print_iter: 100 52 | 53 | checkpoint_opt: 54 | save_best: true # only save the model that better than previous epoches (except the last epoch) 55 | checkpoint_step: 10 56 | checkpoint_name: 'test_model.pth' -------------------------------------------------------------------------------- /config/_cifar100_ciiv_rc.yaml: -------------------------------------------------------------------------------- 1 | output_dir: null 2 | 3 | dataset: 4 | name: cifar100 5 | data_path: ./data/CIFAR100 6 | img_size: 32 7 | rand_aug: false 8 | 9 | networks: 10 | def_file: ./models/ResNet_CiiV_RC.py 11 | params: {m_type: 'resnet18', num_classes: 100, num_sample: 3, aug_weight: 0.9, mask_center: [5, 27]} 12 | 13 | strategy: 14 | train_type: 'ciiv' 15 | test_type: 'ciiv' 16 | 17 | attacker_opt: 18 | adv_val: false # Adversarial attack during inference 19 | adv_train: false # Adversarial training 20 | attack_type: 'FGSM' # Adversarial attack algorithm type, candidates: 'PGD', 'PGDL2', 'FGSM', 'FFGSM', 'GN', 'UN' 21 | attack_set: 'setting1' # attack setting is under attacker_config.yaml 22 | eot_iter: 1 # EOT version of attacker is applied when eot_iter > 1 23 | 24 | training_opt: 25 | num_epochs: 110 26 | batch_size: 128 27 | data_workers: 4 28 | optimizer: 'SGD' # 'Adam' / 'SGD' 29 | optim_params: {lr: 0.1, momentum: 0.9, weight_decay: 0.0005} 30 | scheduler: 'step' # 'cosine' / 'step' 31 | scheduler_params: {endlr: 0.0, gamma: 0.1, milestones: [10, 100, 105]} 32 | 33 | inst_sample: 34 | w_ce: 1 # cross entropy loss weight 35 | w_reg: 0.1 # regression loss weight 36 | mul_ru: 10 # regression weight multiplier 37 | milestones: [25,50,75] # update w_reg by mul_ru at K-th epoch 38 | num_loop: 9 # number of consistent loops 39 | reg_loss: 'L1' # L1 or L2 40 | ce_smooth: false # use z_score to smooth the ce loss 41 | 42 | 43 | test_opt: 44 | save_data: false # for val 45 | file_name: 'adv_images.pth' # for val 46 | save_length: 5 # only save first 10 batch for efficiency 47 | 48 | 49 | logger_opt: 50 | print_grad: false 51 | print_iter: 100 52 | 53 | checkpoint_opt: 54 | save_best: true # only save the model that better than previous epoches (except the last epoch) 55 | checkpoint_step: 10 56 | checkpoint_name: 'test_model.pth' -------------------------------------------------------------------------------- /config/_cifar10_ciiv_WRN.yaml: -------------------------------------------------------------------------------- 1 | output_dir: null 2 | 3 | dataset: 4 | name: cifar10 5 | data_path: ./data/CIFAR10 6 | img_size: 32 7 | rand_aug: false 8 | 9 | networks: 10 | def_file: ./models/WideResNet_CiiV.py 11 | params: {m_type: 'WRN34-10', num_classes: 10, num_sample: 3, aug_weight: 0.9, mask_center: [16, 5, 27]} 12 | 13 | strategy: 14 | train_type: 'ciiv' 15 | test_type: 'ciiv' 16 | 17 | attacker_opt: 18 | adv_val: false # Adversarial attack during inference 19 | adv_train: false # Adversarial training 20 | attack_type: 'FGSM' # Adversarial attack algorithm type, candidates: 'PGD', 'PGDL2', 'FGSM', 'FFGSM', 'GN', 'UN' 21 | attack_set: 'setting1' # attack setting is under attacker_config.yaml 22 | eot_iter: 1 # EOT version of attacker is applied when eot_iter > 1 23 | 24 | training_opt: 25 | num_epochs: 110 26 | batch_size: 128 27 | data_workers: 4 28 | optimizer: 'SGD' # 'Adam' / 'SGD' 29 | optim_params: {lr: 0.1, momentum: 0.9, weight_decay: 0.0005} 30 | scheduler: 'step' # 'cosine' / 'step' 31 | scheduler_params: {endlr: 0.0, gamma: 0.1, milestones: [10, 100, 105]} 32 | 33 | inst_sample: 34 | w_ce: 1 # cross entropy loss weight 35 | w_reg: 0.1 # regression loss weight 36 | mul_ru: 10 # regression weight multiplier 37 | milestones: [25,50,75] # update w_reg by mul_ru at K-th epoch 38 | num_loop: 9 # number of consistent loops 39 | reg_loss: 'L1' # L1 or L2 40 | ce_smooth: false # use z_score to smooth the ce loss 41 | 42 | 43 | test_opt: 44 | save_data: false # for val 45 | file_name: 'adv_images.pth' # for val 46 | save_length: 5 # only save first 10 batch for efficiency 47 | 48 | 49 | logger_opt: 50 | print_grad: false 51 | print_iter: 100 52 | 53 | checkpoint_opt: 54 | save_best: true # only save the model that better than previous epoches (except the last epoch) 55 | checkpoint_step: 10 56 | checkpoint_name: 'test_model.pth' -------------------------------------------------------------------------------- /config/_cifar100_ciiv_WRN.yaml: -------------------------------------------------------------------------------- 1 | output_dir: null 2 | 3 | dataset: 4 | name: cifar100 5 | data_path: ./data/CIFAR100 6 | img_size: 32 7 | rand_aug: false 8 | 9 | networks: 10 | def_file: ./models/WideResNet_CiiV.py 11 | params: {m_type: 'WRN34-10', num_classes: 100, num_sample: 3, aug_weight: 0.9, mask_center: [16, 5, 27]} 12 | 13 | strategy: 14 | train_type: 'ciiv' 15 | test_type: 'ciiv' 16 | 17 | attacker_opt: 18 | adv_val: false # Adversarial attack during inference 19 | adv_train: false # Adversarial training 20 | attack_type: 'FGSM' # Adversarial attack algorithm type, candidates: 'PGD', 'PGDL2', 'FGSM', 'FFGSM', 'GN', 'UN' 21 | attack_set: 'setting1' # attack setting is under attacker_config.yaml 22 | eot_iter: 1 # EOT version of attacker is applied when eot_iter > 1 23 | 24 | training_opt: 25 | num_epochs: 110 26 | batch_size: 128 27 | data_workers: 4 28 | optimizer: 'SGD' # 'Adam' / 'SGD' 29 | optim_params: {lr: 0.1, momentum: 0.9, weight_decay: 0.0005} 30 | scheduler: 'step' # 'cosine' / 'step' 31 | scheduler_params: {endlr: 0.0, gamma: 0.1, milestones: [10, 100, 105]} 32 | 33 | inst_sample: 34 | w_ce: 1 # cross entropy loss weight 35 | w_reg: 0.1 # regression loss weight 36 | mul_ru: 10 # regression weight multiplier 37 | milestones: [25,50,75] # update w_reg by mul_ru at K-th epoch 38 | num_loop: 9 # number of consistent loops 39 | reg_loss: 'L1' # L1 or L2 40 | ce_smooth: false # use z_score to smooth the ce loss 41 | 42 | 43 | test_opt: 44 | save_data: false # for val 45 | file_name: 'adv_images.pth' # for val 46 | save_length: 5 # only save first 10 batch for efficiency 47 | 48 | 49 | logger_opt: 50 | print_grad: false 51 | print_iter: 100 52 | 53 | checkpoint_opt: 54 | save_best: true # only save the model that better than previous epoches (except the last epoch) 55 | checkpoint_step: 10 56 | checkpoint_name: 'test_model.pth' -------------------------------------------------------------------------------- /config/_cifar10_ciiv_mixup.yaml: -------------------------------------------------------------------------------- 1 | output_dir: null 2 | 3 | dataset: 4 | name: cifar10 5 | data_path: ./data/CIFAR10 6 | img_size: 32 7 | rand_aug: false 8 | 9 | networks: 10 | def_file: ./models/ResNet_CiiV.py 11 | params: {m_type: 'resnet18', num_classes: 10, num_sample: 3, aug_weight: 0.9, mask_center: [16, 5, 27]} 12 | 13 | strategy: 14 | train_type: 'ciiv_mixup' 15 | test_type: 'ciiv' 16 | 17 | attacker_opt: 18 | adv_val: false # Adversarial attack during inference 19 | adv_train: false # Adversarial training 20 | attack_type: 'FGSM' # Adversarial attack algorithm type, candidates: 'PGD', 'PGDL2', 'FGSM', 'FFGSM', 'GN', 'UN' 21 | attack_set: 'setting1' # attack setting is under attacker_config.yaml 22 | eot_iter: 1 # EOT version of attacker is applied when eot_iter > 1 23 | 24 | training_opt: 25 | num_epochs: 110 26 | batch_size: 128 27 | data_workers: 4 28 | optimizer: 'SGD' # 'Adam' / 'SGD' 29 | optim_params: {lr: 0.1, momentum: 0.9, weight_decay: 0.0005} 30 | scheduler: 'step' # 'cosine' / 'step' 31 | scheduler_params: {endlr: 0.0, gamma: 0.1, milestones: [10, 100, 105]} 32 | 33 | inst_sample: 34 | w_ce: 1 # cross entropy loss weight 35 | w_reg: 0.1 # regression loss weight 36 | mul_ru: 10 # regression weight multiplier 37 | milestones: [25,50,75] # update w_reg by mul_ru at K-th epoch 38 | num_loop: 9 # number of consistent loops 39 | reg_loss: 'L1' # L1 or L2 40 | ce_smooth: false # use z_score to smooth the ce loss 41 | 42 | 43 | test_opt: 44 | save_data: false # for val 45 | file_name: 'adv_images.pth' # for val 46 | save_length: 5 # only save first 10 batch for efficiency 47 | 48 | 49 | logger_opt: 50 | print_grad: false 51 | print_iter: 100 52 | 53 | checkpoint_opt: 54 | save_best: true # only save the model that better than previous epoches (except the last epoch) 55 | checkpoint_step: 10 56 | checkpoint_name: 'test_model.pth' -------------------------------------------------------------------------------- /utils/train_utils.py: -------------------------------------------------------------------------------- 1 | import torch 2 | import torch.nn as nn 3 | 4 | import random 5 | import attacker 6 | 7 | from train_baseline import train_baseline 8 | from train_mixup import train_mixup 9 | from train_ciiv import train_ciiv 10 | from train_ciiv_img import train_ciiv_img 11 | from train_ciiv_mixup import train_ciiv_mixup 12 | from train_bpfc import train_bpfc 13 | 14 | 15 | def get_train_func(config): 16 | # choosing training strategy 17 | if config['strategy']['train_type'] == 'baseline': 18 | training_func = train_baseline 19 | elif config['strategy']['train_type'] == 'mixup': 20 | training_func = train_mixup 21 | elif config['strategy']['train_type'] == 'ciiv': 22 | training_func = train_ciiv 23 | elif config['strategy']['train_type'] == 'ciiv_img': 24 | training_func = train_ciiv_img 25 | elif config['strategy']['train_type'] == 'ciiv_mixup': 26 | training_func = train_ciiv_mixup 27 | elif config['strategy']['train_type'] == 'bpfc': 28 | training_func = train_bpfc 29 | else: 30 | raise ValueError('Wrong Training Strategy') 31 | return training_func 32 | 33 | def rgb_norm(images, config): 34 | # set mean, std for different dataset 35 | if config['dataset']['name'] == 'cifar10': 36 | mean = [0.4914, 0.4822, 0.4465] 37 | std = [0.2471, 0.2435, 0.2616] 38 | elif config['dataset']['name'] == 'cifar100': 39 | mean = [0.5071, 0.4867, 0.4408] 40 | std = [0.2673, 0.2564, 0.2762] 41 | elif config['dataset']['name'] == 'mini-imagenet': 42 | mean = [0.485, 0.456, 0.406] 43 | std = [0.229, 0.224, 0.225] 44 | elif config['dataset']['name'] == 'TOYData': 45 | mean = [0.0, 0.0, 0.0] 46 | std = [1.0, 1.0, 1.0] 47 | else: 48 | raise ValueError('Wrong Dataset ({}) for RGB normalization.'.format(config['dataset']['name'])) 49 | # apply normalization 50 | mean = torch.tensor(mean).view(1,3,1,1).to(images.device) 51 | std = torch.tensor(std).view(1,3,1,1).to(images.device) 52 | images = (images - mean) / std 53 | return images -------------------------------------------------------------------------------- /config/_cifar100_ciiv_mixup.yaml: -------------------------------------------------------------------------------- 1 | output_dir: null 2 | 3 | dataset: 4 | name: cifar100 5 | data_path: ./data/CIFAR100 6 | img_size: 32 7 | rand_aug: false 8 | 9 | networks: 10 | def_file: ./models/ResNet_CiiV.py 11 | params: {m_type: 'resnet18', num_classes: 100, num_sample: 3, aug_weight: 0.9, mask_center: [16, 5, 27]} 12 | 13 | strategy: 14 | train_type: 'ciiv_mixup' 15 | test_type: 'ciiv' 16 | 17 | attacker_opt: 18 | adv_val: false # Adversarial attack during inference 19 | adv_train: false # Adversarial training 20 | attack_type: 'FGSM' # Adversarial attack algorithm type, candidates: 'PGD', 'PGDL2', 'FGSM', 'FFGSM', 'GN', 'UN' 21 | attack_set: 'setting1' # attack setting is under attacker_config.yaml 22 | eot_iter: 1 # EOT version of attacker is applied when eot_iter > 1 23 | 24 | training_opt: 25 | num_epochs: 110 26 | batch_size: 128 27 | data_workers: 4 28 | optimizer: 'SGD' # 'Adam' / 'SGD' 29 | optim_params: {lr: 0.1, momentum: 0.9, weight_decay: 0.0005} 30 | scheduler: 'step' # 'cosine' / 'step' 31 | scheduler_params: {endlr: 0.0, gamma: 0.1, milestones: [10, 100, 105]} 32 | 33 | inst_sample: 34 | w_ce: 1 # cross entropy loss weight 35 | w_reg: 0.1 # regression loss weight 36 | mul_ru: 10 # regression weight multiplier 37 | milestones: [25,50,75] # update w_reg by mul_ru at K-th epoch 38 | num_loop: 9 # number of consistent loops 39 | reg_loss: 'L1' # L1 or L2 40 | ce_smooth: false # use z_score to smooth the ce loss 41 | 42 | 43 | test_opt: 44 | save_data: false # for val 45 | file_name: 'adv_images.pth' # for val 46 | save_length: 5 # only save first 10 batch for efficiency 47 | 48 | 49 | logger_opt: 50 | print_grad: false 51 | print_iter: 100 52 | 53 | checkpoint_opt: 54 | save_best: true # only save the model that better than previous epoches (except the last epoch) 55 | checkpoint_step: 10 56 | checkpoint_name: 'test_model.pth' -------------------------------------------------------------------------------- /old_file/old_config/mini_imagenet_rs.yaml: -------------------------------------------------------------------------------- 1 | output_dir: null 2 | 3 | dataset: 4 | name: mini-imagenet 5 | data_path: /data4/imagenet/ILSVRC/Data/CLS-LOC 6 | category_path: ./data/mini-ImageNet/category_frame.csv 7 | train_path: ./data/mini-ImageNet/train_frame.csv 8 | test_path: ./data/mini-ImageNet/test_frame.csv 9 | val_path: ./data/mini-ImageNet/val_frame.csv 10 | num_classes: 100 11 | img_size: 84 12 | 13 | networks: 14 | def_file: ./models/ResNet_RS.py 15 | params: {m_type: 'resnet18', num_classes: 100, first_conv_size: 7, num_trial: 10, sigma: 0.25} 16 | 17 | training_opt: 18 | num_epochs: 100 19 | batch_size: 128 20 | data_workers: 4 21 | optimizer: 'SGD' # 'Adam' / 'SGD' 22 | optim_params: {lr: 0.1, momentum: 0.9, weight_decay: 0.0005} 23 | scheduler: 'step' # 'cosine' / 'step' 24 | scheduler_params: {endlr: 0.0, gamma: 0.2, milestones: [25, 50, 75]} 25 | 26 | mixup_on: false 27 | 28 | bpfc_opt: 29 | bpfc_on: false # turn on BPFC training 30 | p_val: 5 # (k in paper) 5,6,7 for cifar10, FMNIST, MNIST 31 | w_ce: 1 # cross entropy loss weight 32 | w_reg: 1 # regression loss weight 33 | mul_ru: 9 # regression weight multiplier 34 | milestones: [25,50,75] # update w_reg by mul_ru at K-th epoch 35 | 36 | attacker_opt: 37 | attack_type: 'FGSM' # Adversarial attack algorithm type, candidates: 'PGD', 'PGDL2', 'FGSM', 'FFGSM', 'GN', 'UN' 38 | attack_set: 'setting1' # attack setting is under attacker_config.yaml 39 | eot_iter: 1 # EOT version of attacker is applied when eot_iter > 1 40 | 41 | adv_train: false # Adversarial training 42 | adv_val: false # Adversarial attack during inference 43 | 44 | save_test: # for val 45 | save_data: false # for val 46 | file_name: 'adv_images.pth' # for val 47 | save_length: 5 # only save first 10 batch for efficiency 48 | 49 | logger_opt: 50 | print_grad: false 51 | print_iter: 100 52 | 53 | checkpoint_opt: 54 | checkpoint_step: 10 55 | checkpoint_name: 'test_model.pth' -------------------------------------------------------------------------------- /old_file/old_config/mini_imagenet.yaml: -------------------------------------------------------------------------------- 1 | output_dir: null 2 | 3 | dataset: 4 | name: mini-imagenet 5 | data_path: /data4/imagenet/ILSVRC/Data/CLS-LOC 6 | category_path: ./data/mini-ImageNet/category_frame.csv 7 | train_path: ./data/mini-ImageNet/train_frame.csv 8 | test_path: ./data/mini-ImageNet/test_frame.csv 9 | val_path: ./data/mini-ImageNet/val_frame.csv 10 | num_classes: 100 11 | img_size: 84 12 | 13 | networks: 14 | def_file: ./models/ResNet.py 15 | params: {m_type: 'resnet18', num_classes: 100, first_conv_size: 7} 16 | 17 | blackbox_save: false 18 | blackbox_test: false 19 | blackbox_name: 'blackbox_{}_{}.pth' 20 | 21 | training_opt: 22 | num_epochs: 100 23 | batch_size: 128 24 | data_workers: 4 25 | optimizer: 'SGD' # 'Adam' / 'SGD' 26 | optim_params: {lr: 0.1, momentum: 0.9, weight_decay: 0.0005} 27 | scheduler: 'step' # 'cosine' / 'step' 28 | scheduler_params: {endlr: 0.0, gamma: 0.2, milestones: [25, 50, 75]} 29 | 30 | mixup_on: false 31 | 32 | bpfc_opt: 33 | bpfc_on: false # turn on BPFC training 34 | p_val: 5 # (k in paper) 5,6,7 for cifar10, FMNIST, MNIST 35 | w_ce: 1 # cross entropy loss weight 36 | w_reg: 1 # regression loss weight 37 | mul_ru: 9 # regression weight multiplier 38 | milestones: [25,50,75] # update w_reg by mul_ru at K-th epoch 39 | 40 | attacker_opt: 41 | attack_type: 'FGSM' # Adversarial attack algorithm type, candidates: 'PGD', 'PGDL2', 'FGSM', 'FFGSM', 'GN', 'UN' 42 | attack_set: 'setting1' # attack setting is under attacker_config.yaml 43 | eot_iter: 1 # EOT version of attacker is applied when eot_iter > 1 44 | 45 | adv_train: false # Adversarial training 46 | adv_val: false # Adversarial attack during inference 47 | 48 | save_test: # for val 49 | save_data: false # for val 50 | file_name: 'adv_images.pth' # for val 51 | save_length: 5 # only save first 10 batch for efficiency 52 | 53 | logger_opt: 54 | print_grad: false 55 | print_iter: 100 56 | 57 | checkpoint_opt: 58 | checkpoint_step: 10 59 | checkpoint_name: 'test_model.pth' -------------------------------------------------------------------------------- /config/_mini_imagenet_bpfc.yaml: -------------------------------------------------------------------------------- 1 | output_dir: null 2 | 3 | dataset: 4 | name: mini-imagenet 5 | data_path: /gruntdata3/kaihua/datasets/imagenet/ILSVRC/Data/CLS-LOC 6 | category_path: ./data/mini-ImageNet/category_frame.csv 7 | train_path: ./data/mini-ImageNet/train_frame.csv 8 | test_path: ./data/mini-ImageNet/test_frame.csv 9 | val_path: ./data/mini-ImageNet/val_frame.csv 10 | num_classes: 100 11 | img_size: 64 12 | rand_aug: false 13 | 14 | networks: 15 | def_file: ./models/ResNet.py 16 | params: {m_type: 'resnet18', cls_type: 'fc', num_classes: 100} 17 | 18 | strategy: 19 | train_type: 'bpfc' # baseline / mixup / bpfc 20 | test_type: 'baseline' 21 | 22 | attacker_opt: 23 | adv_val: false # Adversarial attack during inference 24 | adv_train: false # Adversarial training 25 | attack_type: 'FGSM' # Adversarial attack algorithm type, candidates: 'PGD', 'PGDL2', 'FGSM', 'FFGSM', 'GN', 'UN' 26 | attack_set: 'setting1' # attack setting is under attacker_config.yaml 27 | eot_iter: 1 # EOT version of attacker is applied when eot_iter > 1 28 | 29 | training_opt: 30 | num_epochs: 110 31 | batch_size: 128 32 | data_workers: 4 33 | optimizer: 'SGD' # 'Adam' / 'SGD' 34 | optim_params: {lr: 0.1, momentum: 0.9, weight_decay: 0.0005} 35 | scheduler: 'step' # 'cosine' / 'step' 36 | scheduler_params: {endlr: 0.0, gamma: 0.1, milestones: [10, 100, 105]} 37 | 38 | bpfc_opt: 39 | p_val: 5 # (k in paper) 5,6,7 for cifar10, FMNIST, MNIST 40 | w_ce: 1 # cross entropy loss weight 41 | w_reg: 1 # regression loss weight 42 | mul_ru: 9 # regression weight multiplier 43 | milestones: [25,50,75] # update w_reg by mul_ru at K-th epoch 44 | 45 | test_opt: 46 | save_data: false # for val 47 | file_name: 'adv_images.pth' # for val 48 | save_length: 5 # only save first 10 batch for efficiency 49 | 50 | 51 | logger_opt: 52 | print_grad: false 53 | print_iter: 100 54 | 55 | checkpoint_opt: 56 | save_best: true # only save the model that better than previous epoches (except the last epoch) 57 | checkpoint_step: 10 58 | checkpoint_name: 'test_model.pth' -------------------------------------------------------------------------------- /attacker/attacker.py: -------------------------------------------------------------------------------- 1 | ############################################################################## 2 | # Modified from https://github.com/Harry24k/adversarial-attacks-pytorch 3 | ############################################################################## 4 | 5 | import torch 6 | import torch.nn as nn 7 | 8 | class Attacker(): 9 | """ 10 | Base class for all attackers. 11 | note:: 12 | It automatically set device to the device where given model is. 13 | It temporarily changes the original model's `training mode` to `test` 14 | by `.eval()` only during an attack process. 15 | """ 16 | def __init__(self, name, model, logger, config): 17 | self.attacker = name 18 | self.model = model 19 | self.logger = logger 20 | self.config = config 21 | 22 | 23 | def forward(self, *input): 24 | """ 25 | It defines the computation performed at every call. 26 | Should be overridden by all subclasses. 27 | """ 28 | raise NotImplementedError 29 | 30 | 31 | def get_adv_images(self, images, labels, random_start=False, targeted=False): 32 | adv_images = self.attack(images, labels, random_start, targeted) 33 | return adv_images.detach() 34 | 35 | 36 | def __str__(self): 37 | # Whole structure of the model will be NOT displayed for print pretty. 38 | return '(Attacker Model : {})'.format(self.attacker) 39 | 40 | def attack(self, *input, **kwargs): 41 | # eval model before attack 42 | self.model.eval() 43 | # set model to attack mode 44 | if isinstance(self.model, nn.DataParallel): 45 | self.model.module.set_attack() 46 | else: 47 | self.model.set_attack() 48 | 49 | # generate attack images 50 | images = self.forward(*input, **kwargs) 51 | 52 | # set back to the training phase 53 | self.model.train() 54 | # set model to unattack mode 55 | if isinstance(self.model, nn.DataParallel): 56 | self.model.module.set_unattack() 57 | else: 58 | self.model.set_unattack() 59 | 60 | return images 61 | -------------------------------------------------------------------------------- /config/_mini_imagenet_ciiv.yaml: -------------------------------------------------------------------------------- 1 | output_dir: null 2 | 3 | dataset: 4 | name: mini-imagenet 5 | data_path: /gruntdata3/kaihua/datasets/imagenet/ILSVRC/Data/CLS-LOC 6 | category_path: ./data/mini-ImageNet/category_frame.csv 7 | train_path: ./data/mini-ImageNet/train_frame.csv 8 | test_path: ./data/mini-ImageNet/test_frame.csv 9 | val_path: ./data/mini-ImageNet/val_frame.csv 10 | num_classes: 100 11 | img_size: 64 12 | rand_aug: false 13 | 14 | networks: 15 | def_file: ./models/ResNet_CiiV.py 16 | params: {m_type: 'resnet18', num_classes: 100, num_sample: 3, aug_weight: 0.8, mask_center: [32, 11, 53]} 17 | 18 | strategy: 19 | train_type: 'ciiv' 20 | test_type: 'ciiv' 21 | 22 | attacker_opt: 23 | adv_val: false # Adversarial attack during inference 24 | adv_train: false # Adversarial training 25 | attack_type: 'FGSM' # Adversarial attack algorithm type, candidates: 'PGD', 'PGDL2', 'FGSM', 'FFGSM', 'GN', 'UN' 26 | attack_set: 'setting1' # attack setting is under attacker_config.yaml 27 | eot_iter: 1 # EOT version of attacker is applied when eot_iter > 1 28 | 29 | training_opt: 30 | num_epochs: 110 31 | batch_size: 128 32 | data_workers: 4 33 | optimizer: 'SGD' # 'Adam' / 'SGD' 34 | optim_params: {lr: 0.1, momentum: 0.9, weight_decay: 0.0005} 35 | scheduler: 'step' # 'cosine' / 'step' 36 | scheduler_params: {endlr: 0.0, gamma: 0.1, milestones: [10, 100, 105]} 37 | 38 | inst_sample: 39 | w_ce: 1 # cross entropy loss weight 40 | w_reg: 0.1 # regression loss weight 41 | mul_ru: 10 # regression weight multiplier 42 | milestones: [25,50,75] # update w_reg by mul_ru at K-th epoch 43 | num_loop: 9 # number of consistent loops 44 | reg_loss: 'L1' # L1 or L2 45 | ce_smooth: false # use z_score to smooth the ce loss 46 | 47 | 48 | test_opt: 49 | save_data: false # for val 50 | file_name: 'adv_images.pth' # for val 51 | save_length: 5 # only save first 10 batch for efficiency 52 | 53 | 54 | logger_opt: 55 | print_grad: false 56 | print_iter: 100 57 | 58 | checkpoint_opt: 59 | save_best: true # only save the model that better than previous epoches (except the last epoch) 60 | checkpoint_step: 10 61 | checkpoint_name: 'test_model.pth' -------------------------------------------------------------------------------- /config/_mini_imagenet_ciiv_rc.yaml: -------------------------------------------------------------------------------- 1 | output_dir: null 2 | 3 | dataset: 4 | name: mini-imagenet 5 | data_path: /gruntdata3/kaihua/datasets/imagenet/ILSVRC/Data/CLS-LOC 6 | category_path: ./data/mini-ImageNet/category_frame.csv 7 | train_path: ./data/mini-ImageNet/train_frame.csv 8 | test_path: ./data/mini-ImageNet/test_frame.csv 9 | val_path: ./data/mini-ImageNet/val_frame.csv 10 | num_classes: 100 11 | img_size: 64 12 | rand_aug: false 13 | 14 | networks: 15 | def_file: ./models/ResNet_CiiV_RC.py 16 | params: {m_type: 'resnet18', num_classes: 100, num_sample: 3, aug_weight: 0.8, mask_center: [11, 53]} 17 | 18 | strategy: 19 | train_type: 'ciiv' 20 | test_type: 'ciiv' 21 | 22 | attacker_opt: 23 | adv_val: false # Adversarial attack during inference 24 | adv_train: false # Adversarial training 25 | attack_type: 'FGSM' # Adversarial attack algorithm type, candidates: 'PGD', 'PGDL2', 'FGSM', 'FFGSM', 'GN', 'UN' 26 | attack_set: 'setting1' # attack setting is under attacker_config.yaml 27 | eot_iter: 1 # EOT version of attacker is applied when eot_iter > 1 28 | 29 | training_opt: 30 | num_epochs: 110 31 | batch_size: 128 32 | data_workers: 4 33 | optimizer: 'SGD' # 'Adam' / 'SGD' 34 | optim_params: {lr: 0.1, momentum: 0.9, weight_decay: 0.0005} 35 | scheduler: 'step' # 'cosine' / 'step' 36 | scheduler_params: {endlr: 0.0, gamma: 0.1, milestones: [10, 100, 105]} 37 | 38 | inst_sample: 39 | w_ce: 1 # cross entropy loss weight 40 | w_reg: 0.1 # regression loss weight 41 | mul_ru: 10 # regression weight multiplier 42 | milestones: [25,50,75] # update w_reg by mul_ru at K-th epoch 43 | num_loop: 9 # number of consistent loops 44 | reg_loss: 'L1' # L1 or L2 45 | ce_smooth: false # use z_score to smooth the ce loss 46 | 47 | 48 | test_opt: 49 | save_data: false # for val 50 | file_name: 'adv_images.pth' # for val 51 | save_length: 5 # only save first 10 batch for efficiency 52 | 53 | 54 | logger_opt: 55 | print_grad: false 56 | print_iter: 100 57 | 58 | checkpoint_opt: 59 | save_best: true # only save the model that better than previous epoches (except the last epoch) 60 | checkpoint_step: 10 61 | checkpoint_name: 'test_model.pth' -------------------------------------------------------------------------------- /config/_mini_imagenet_ciiv_mixup.yaml: -------------------------------------------------------------------------------- 1 | output_dir: null 2 | 3 | dataset: 4 | name: mini-imagenet 5 | data_path: /gruntdata3/kaihua/datasets/imagenet/ILSVRC/Data/CLS-LOC 6 | category_path: ./data/mini-ImageNet/category_frame.csv 7 | train_path: ./data/mini-ImageNet/train_frame.csv 8 | test_path: ./data/mini-ImageNet/test_frame.csv 9 | val_path: ./data/mini-ImageNet/val_frame.csv 10 | num_classes: 100 11 | img_size: 64 12 | rand_aug: false 13 | 14 | networks: 15 | def_file: ./models/ResNet_CiiV.py 16 | params: {m_type: 'resnet18', num_classes: 100, num_sample: 3, aug_weight: 0.8, mask_center: [32, 11, 53]} 17 | 18 | strategy: 19 | train_type: 'ciiv_mixup' 20 | test_type: 'ciiv' 21 | 22 | attacker_opt: 23 | adv_val: false # Adversarial attack during inference 24 | adv_train: false # Adversarial training 25 | attack_type: 'FGSM' # Adversarial attack algorithm type, candidates: 'PGD', 'PGDL2', 'FGSM', 'FFGSM', 'GN', 'UN' 26 | attack_set: 'setting1' # attack setting is under attacker_config.yaml 27 | eot_iter: 1 # EOT version of attacker is applied when eot_iter > 1 28 | 29 | training_opt: 30 | num_epochs: 110 31 | batch_size: 128 32 | data_workers: 4 33 | optimizer: 'SGD' # 'Adam' / 'SGD' 34 | optim_params: {lr: 0.1, momentum: 0.9, weight_decay: 0.0005} 35 | scheduler: 'step' # 'cosine' / 'step' 36 | scheduler_params: {endlr: 0.0, gamma: 0.1, milestones: [10, 100, 105]} 37 | 38 | inst_sample: 39 | w_ce: 1 # cross entropy loss weight 40 | w_reg: 0.1 # regression loss weight 41 | mul_ru: 10 # regression weight multiplier 42 | milestones: [25,50,75] # update w_reg by mul_ru at K-th epoch 43 | num_loop: 9 # number of consistent loops 44 | reg_loss: 'L1' # L1 or L2 45 | ce_smooth: false # use z_score to smooth the ce loss 46 | 47 | 48 | test_opt: 49 | save_data: false # for val 50 | file_name: 'adv_images.pth' # for val 51 | save_length: 5 # only save first 10 batch for efficiency 52 | 53 | 54 | logger_opt: 55 | print_grad: false 56 | print_iter: 100 57 | 58 | checkpoint_opt: 59 | save_best: true # only save the model that better than previous epoches (except the last epoch) 60 | checkpoint_step: 10 61 | checkpoint_name: 'test_model.pth' -------------------------------------------------------------------------------- /old_file/old_config/toy_ciiv.yaml: -------------------------------------------------------------------------------- 1 | output_dir: null 2 | 3 | dataset: 4 | name: TOYData 5 | num_classes: 3 6 | img_size: 64 7 | 8 | networks: 9 | def_file: ./models/ResNet_Final_Time.py 10 | params: {m_type: 'resnet18', num_classes: 10, first_conv_size: 7, num_sample: 3, mask_aug: true, samp_aug: false, aug_weight: 0.8, mask_center: [20, 32, 44]} 11 | 12 | blackbox_save: false 13 | blackbox_test: false 14 | blackbox_name: 'blackbox_{}_{}.pth' 15 | 16 | training_opt: 17 | num_epochs: 100 18 | batch_size: 128 19 | data_workers: 4 20 | optimizer: 'SGD' # 'Adam' / 'SGD' 21 | optim_params: {lr: 0.1, momentum: 0.9, weight_decay: 0.0005} 22 | scheduler: 'step' # 'cosine' / 'step' 23 | scheduler_params: {endlr: 0.0, gamma: 0.2, milestones: [25, 50, 75]} 24 | 25 | inst_sample: 26 | inst_on: true # turn on instrumental variable sample 27 | inst_half: false # merge sampled feature in the middle of the network 28 | w_ce: 1 # cross entropy loss weight 29 | w_reg: 0.1 # regression loss weight 30 | mul_ru: 10 # regression weight multiplier 31 | milestones: [25,50,75] # update w_reg by mul_ru at K-th epoch 32 | num_loop: 20 # number of consistent loops 33 | accumulate_grad: false # use accumulated grad to implement loop 34 | reg_loss: 'L1' # L1 or L2 35 | reg_type: 'regmean' # 'neighbour', 'regmean', 'none' 36 | 37 | attacker_opt: 38 | attack_type: 'FGSM' # Adversarial attack algorithm type, candidates: 'PGD', 'PGDL2', 'FGSM', 'FFGSM', 'GN', 'UN' 39 | attack_set: 'setting1' # attack setting is under attacker_config.yaml 40 | eot_iter: 1 # EOT version of attacker is applied when eot_iter > 1 41 | 42 | adv_train: false # Adversarial training 43 | adv_val: false # Adversarial attack during inference 44 | 45 | targeted_on: false # report success rate (for evaluating targeted attacks) 46 | targeted_type: 'type1' # type1: untargeted, type2: random targeted, type3: least likely targeted, type4: most likely targeted 47 | 48 | save_test: # for val 49 | save_data: true # for val 50 | file_name: 'adv_images.pth' # for val 51 | save_length: 10 # only save first 10 batch for efficiency 52 | 53 | logger_opt: 54 | print_grad: false 55 | print_iter: 100 56 | 57 | checkpoint_opt: 58 | checkpoint_step: 10 59 | checkpoint_name: 'test_model.pth' -------------------------------------------------------------------------------- /old_file/old_config/mnist_ciiv.yaml: -------------------------------------------------------------------------------- 1 | output_dir: null 2 | 3 | dataset: 4 | name: mnist 5 | data_path: ./data/MNIST 6 | img_size: 32 7 | 8 | networks: 9 | def_file: ./models/ResNet_Final_Time.py 10 | params: {m_type: 'resnet18', num_classes: 10, first_conv_size: 7, num_sample: 3, mask_aug: true, samp_aug: false, aug_weight: 0.8, mask_center: [5, 16, 27]} 11 | 12 | blackbox_save: false 13 | blackbox_test: false 14 | blackbox_name: 'blackbox_{}_{}.pth' 15 | 16 | training_opt: 17 | num_epochs: 100 18 | batch_size: 128 19 | data_workers: 4 20 | optimizer: 'SGD' # 'Adam' / 'SGD' 21 | optim_params: {lr: 0.1, momentum: 0.9, weight_decay: 0.0005} 22 | scheduler: 'step' # 'cosine' / 'step' 23 | scheduler_params: {endlr: 0.0, gamma: 0.2, milestones: [25, 50, 75]} 24 | 25 | inst_sample: 26 | inst_on: true # turn on instrumental variable sample 27 | inst_half: false # merge sampled feature in the middle of the network 28 | w_ce: 1 # cross entropy loss weight 29 | w_reg: 0.1 # regression loss weight 30 | mul_ru: 10 # regression weight multiplier 31 | milestones: [25,50,75] # update w_reg by mul_ru at K-th epoch 32 | num_loop: 20 # number of consistent loops 33 | accumulate_grad: false # use accumulated grad to implement loop 34 | reg_loss: 'L1' # L1 or L2 35 | reg_type: 'regmean' # 'neighbour', 'regmean', 'none' 36 | 37 | attacker_opt: 38 | attack_type: 'FGSM' # Adversarial attack algorithm type, candidates: 'PGD', 'PGDL2', 'FGSM', 'FFGSM', 'GN', 'UN' 39 | attack_set: 'setting1' # attack setting is under attacker_config.yaml 40 | eot_iter: 1 # EOT version of attacker is applied when eot_iter > 1 41 | 42 | adv_train: false # Adversarial training 43 | adv_val: false # Adversarial attack during inference 44 | 45 | targeted_on: false # report success rate (for evaluating targeted attacks) 46 | targeted_type: 'type1' # type1: untargeted, type2: random targeted, type3: least likely targeted, type4: most likely targeted 47 | 48 | save_test: # for val 49 | save_data: false # for val 50 | file_name: 'adv_images.pth' # for val 51 | save_length: 5 # only save first 10 batch for efficiency 52 | 53 | logger_opt: 54 | print_grad: false 55 | print_iter: 100 56 | 57 | checkpoint_opt: 58 | checkpoint_step: 10 59 | checkpoint_name: 'test_model.pth' -------------------------------------------------------------------------------- /old_file/old_config/cifar10_ciiv.yaml: -------------------------------------------------------------------------------- 1 | output_dir: null 2 | 3 | dataset: 4 | name: cifar10 5 | data_path: ./data/CIFAR10 6 | img_size: 32 7 | 8 | networks: 9 | def_file: ./models/ResNet_Final_Time.py 10 | params: {m_type: 'resnet18', num_classes: 10, first_conv_size: 7, num_sample: 3, mask_aug: true, samp_aug: false, aug_weight: 0.9, mask_center: [5, 16, 27]} 11 | 12 | blackbox_save: false 13 | blackbox_test: false 14 | blackbox_name: 'blackbox_{}_{}.pth' 15 | 16 | training_opt: 17 | num_epochs: 100 18 | batch_size: 128 19 | data_workers: 4 20 | optimizer: 'SGD' # 'Adam' / 'SGD' 21 | optim_params: {lr: 0.1, momentum: 0.9, weight_decay: 0.0005} 22 | scheduler: 'step' # 'cosine' / 'step' 23 | scheduler_params: {endlr: 0.0, gamma: 0.2, milestones: [25, 50, 75]} 24 | 25 | inst_sample: 26 | inst_on: true # turn on instrumental variable sample 27 | inst_half: false # merge sampled feature in the middle of the network 28 | w_ce: 1 # cross entropy loss weight 29 | w_reg: 0.1 # regression loss weight 30 | mul_ru: 10 # regression weight multiplier 31 | milestones: [25,50,75] # update w_reg by mul_ru at K-th epoch 32 | num_loop: 15 # number of consistent loops 33 | accumulate_grad: false # use accumulated grad to implement loop 34 | reg_loss: 'L1' # L1 or L2 35 | reg_type: 'regmean' # 'neighbour', 'regmean', 'none' 36 | 37 | attacker_opt: 38 | attack_type: 'FGSM' # Adversarial attack algorithm type, candidates: 'PGD', 'PGDL2', 'FGSM', 'FFGSM', 'GN', 'UN' 39 | attack_set: 'setting1' # attack setting is under attacker_config.yaml 40 | eot_iter: 1 # EOT version of attacker is applied when eot_iter > 1 41 | 42 | adv_train: false # Adversarial training 43 | adv_val: false # Adversarial attack during inference 44 | 45 | targeted_on: false # report success rate (for evaluating targeted attacks) 46 | targeted_type: 'type1' # type1: untargeted, type2: random targeted, type3: least likely targeted, type4: most likely targeted 47 | 48 | save_test: # for val 49 | save_data: false # for val 50 | file_name: 'adv_images.pth' # for val 51 | save_length: 5 # only save first 10 batch for efficiency 52 | 53 | logger_opt: 54 | print_grad: false 55 | print_iter: 100 56 | 57 | checkpoint_opt: 58 | checkpoint_step: 10 59 | checkpoint_name: 'test_model.pth' -------------------------------------------------------------------------------- /old_file/old_config/mini_imagenet_ciiv.yaml: -------------------------------------------------------------------------------- 1 | output_dir: null 2 | 3 | dataset: 4 | name: mini-imagenet 5 | data_path: /data4/imagenet/ILSVRC/Data/CLS-LOC 6 | category_path: ./data/mini-ImageNet/category_frame.csv 7 | train_path: ./data/mini-ImageNet/train_frame.csv 8 | test_path: ./data/mini-ImageNet/test_frame.csv 9 | val_path: ./data/mini-ImageNet/val_frame.csv 10 | num_classes: 100 11 | img_size: 84 12 | 13 | networks: 14 | def_file: ./models/ResNet_Final_Time.py 15 | params: {m_type: 'resnet18', num_classes: 100, first_conv_size: 7, num_sample: 3, mask_aug: true, samp_aug: false, aug_weight: 0.8, mask_center: [14, 42, 70]} 16 | 17 | blackbox_save: false 18 | blackbox_test: false 19 | blackbox_name: 'blackbox_{}_{}.pth' 20 | 21 | training_opt: 22 | num_epochs: 100 23 | batch_size: 128 24 | data_workers: 4 25 | optimizer: 'SGD' # 'Adam' / 'SGD' 26 | optim_params: {lr: 0.1, momentum: 0.9, weight_decay: 0.0005} 27 | scheduler: 'step' # 'cosine' / 'step' 28 | scheduler_params: {endlr: 0.0, gamma: 0.2, milestones: [25, 50, 75]} 29 | 30 | inst_sample: 31 | inst_on: true # turn on instrumental variable sample 32 | inst_half: false # merge sampled feature in the middle of the network 33 | w_ce: 1 # cross entropy loss weight 34 | w_reg: 0.1 # regression loss weight 35 | mul_ru: 10 # regression weight multiplier 36 | milestones: [25,50,75] # update w_reg by mul_ru at K-th epoch 37 | num_loop: 10 # number of consistent loops 38 | accumulate_grad: false # use accumulated grad to implement loop 39 | reg_loss: 'L1' # L1 or L2 40 | reg_type: 'regmean' # 'neighbour', 'regmean', 'none' 41 | 42 | attacker_opt: 43 | attack_type: 'FGSM' # Adversarial attack algorithm type, candidates: 'PGD', 'PGDL2', 'FGSM', 'FFGSM', 'GN', 'UN' 44 | attack_set: 'setting1' # attack setting is under attacker_config.yaml 45 | eot_iter: 1 # EOT version of attacker is applied when eot_iter > 1 46 | 47 | adv_train: false # Adversarial training 48 | adv_val: false # Adversarial attack during inference 49 | 50 | save_test: # for val 51 | save_data: false # for val 52 | file_name: 'adv_images.pth' # for val 53 | save_length: 5 # only save first 10 batch for efficiency 54 | 55 | logger_opt: 56 | print_grad: false 57 | print_iter: 100 58 | 59 | checkpoint_opt: 60 | checkpoint_step: 10 61 | checkpoint_name: 'test_model.pth' -------------------------------------------------------------------------------- /attacker/attacks/spsa.py: -------------------------------------------------------------------------------- 1 | ############################################################################## 2 | # Modified from https://github.com/BorealisAI/advertorch/ 3 | ############################################################################## 4 | 5 | import torch 6 | import torch.nn as nn 7 | import torch.optim as optim 8 | import torch.nn.functional as F 9 | 10 | from ..attacker import Attacker 11 | import utils.general_utils as utils 12 | 13 | class SPSA(Attacker): 14 | r""" 15 | SPSA in the paper 'Adversarial Risk and the Dangers of Evaluating Against Weak Attacks' 16 | [https://arxiv.org/abs/1802.05666] 17 | """ 18 | def __init__(self, model, logger, config, delta=0.1, eps=16, batch_size=128, steps=5, lr=0.01): 19 | super(SPSA, self).__init__("SPSA", model, logger, config) 20 | self.batch_size = batch_size 21 | self.delta = delta 22 | self.eps = eps / 255.0 23 | self.steps = steps 24 | self.lr = lr 25 | 26 | logger.info('Create Attacker SPSA with delta: {}, eps: {}, steps: {}, lr: {}, batch_size: {}'.format(delta, eps, steps, lr, batch_size)) 27 | 28 | def forward(self, images, labels, random_start=False, targeted=False): 29 | 30 | images, labels = images.cuda(), labels.cuda() 31 | 32 | dx = torch.zeros_like(images) 33 | dx.grad = torch.zeros_like(dx) 34 | optimizer = optim.Adam([dx], lr=self.lr) 35 | for _ in range(self.steps): 36 | optimizer.zero_grad() 37 | dx.grad = self.spsa_grad(images + dx, labels) 38 | optimizer.step() 39 | adv_images = torch.clamp(images + dx , min=0, max=1) 40 | dx = torch.clamp(adv_images - images, min=-self.eps, max=self.eps) 41 | adv_images = images + dx 42 | 43 | return adv_images 44 | 45 | def f(self, x, y): 46 | pred = self.model(x) 47 | if isinstance(pred, tuple): 48 | pred = pred[0] 49 | return F.cross_entropy(pred, y) 50 | 51 | def spsa_grad(self, x, y): 52 | b, c, w, h = x.shape 53 | x = x.unsqueeze(0) 54 | y = y.unsqueeze(0) 55 | x = x.repeat(self.batch_size, 1, 1, 1, 1).contiguous().view(self.batch_size*b,c,w,h) 56 | y = y.repeat(self.batch_size, 1).contiguous().view(-1) 57 | 58 | v = torch.zeros_like(x).bernoulli_().mul_(2.0).sub_(1.0) 59 | df = self.f(x + self.delta * v, y) - self.f(x - self.delta * v, y) 60 | grad = df / (2. * self.delta * v) 61 | grad = grad.view(self.batch_size,b,c,w,h).mean(dim=0) 62 | return grad -------------------------------------------------------------------------------- /data/dataloader.py: -------------------------------------------------------------------------------- 1 | import os 2 | import json 3 | 4 | import torch 5 | import torch.utils.data as data 6 | import torchvision.transforms as transforms 7 | import numpy as np 8 | from PIL import Image 9 | 10 | from .dt_mini_imagenet import miniImageNetData 11 | from .dt_cifar import CIFAR10Data, CIFAR100Data 12 | from .dt_toy import TOYData 13 | 14 | ################################## 15 | # return a dataloader 16 | ################################## 17 | def get_loader(config, phase, logger): 18 | dataset = config['dataset']['name'] 19 | if dataset == 'mini-imagenet': 20 | split = miniImageNetData(phase=phase, 21 | data_path=config['dataset']['data_path'], 22 | category_path=config['dataset']['category_path'], 23 | train_path=config['dataset']['train_path'], 24 | test_path=config['dataset']['test_path'], 25 | val_path=config['dataset']['val_path'], 26 | output_path=config['output_dir'], 27 | num_classes=config['dataset']['num_classes'], 28 | rand_aug=config['dataset']['rand_aug'], 29 | logger=logger) 30 | elif dataset == 'cifar10': 31 | split = CIFAR10Data(phase=phase, 32 | data_path=config['dataset']['data_path'], 33 | output_path=config['output_dir'], 34 | rand_aug=config['dataset']['rand_aug'], 35 | logger=logger) 36 | elif dataset == 'cifar100': 37 | split = CIFAR100Data(phase=phase, 38 | data_path=config['dataset']['data_path'], 39 | output_path=config['output_dir'], 40 | rand_aug=config['dataset']['rand_aug'], 41 | logger=logger) 42 | elif dataset == 'TOYData': 43 | split = TOYData(phase=phase, 44 | output_path=config['output_dir'], 45 | num_classes=config['dataset']['num_classes'], 46 | logger=logger) 47 | else: 48 | logger.info('********** ERROR: unidentified dataset **********') 49 | 50 | loader = data.DataLoader( 51 | split, 52 | batch_size=config['training_opt']['batch_size'], 53 | shuffle=True if phase == 'train' else False, 54 | pin_memory=True, 55 | num_workers=config['training_opt']['data_workers'], 56 | ) 57 | 58 | return loader 59 | 60 | 61 | -------------------------------------------------------------------------------- /data/mini-ImageNet/preprocessing.py: -------------------------------------------------------------------------------- 1 | # Transfer the mini-imagenet from meta-learning to classification 2 | # link: https://github.com/yaoyao-liu/mini-imagenet-tools/tree/main/csv_files 3 | 4 | 5 | import os 6 | import pandas as pd 7 | from PIL import Image 8 | 9 | trainval_data = pd.read_csv("/home/username/projects/Causal_Adversarial.private/BPFC_mine/data/mini-ImageNet/trainval.csv") 10 | test_data = pd.read_csv("/home/username/projects/Causal_Adversarial.private/BPFC_mine/data/mini-ImageNet/test.csv") 11 | frames = [trainval_data, test_data] 12 | all_data = pd.concat(frames) 13 | 14 | def generate_data(all_data): 15 | images = [] 16 | labels = [] 17 | for item in all_data.values: 18 | name = item[0] 19 | label = item[1] 20 | image = 'train/' + label + '/' + name 21 | images.append(image) 22 | labels.append(label) 23 | return images, labels 24 | 25 | def generate_split(images, labels): 26 | category = list(set(labels)) 27 | data_dict = {} 28 | for image, label in zip(images, labels): 29 | if label in data_dict: 30 | data_dict[label].append(image) 31 | else: 32 | data_dict[label] = [image,] 33 | train_split = [] 34 | test_split = [] 35 | val_split = [] 36 | for label in category: 37 | train = data_dict[label][:420] 38 | test = data_dict[label][420:540] 39 | val = data_dict[label][540:] 40 | for item in train: 41 | train_split.append([item, label]) 42 | for item in test: 43 | test_split.append([item, label]) 44 | for item in val: 45 | val_split.append([item, label]) 46 | return train_split, test_split, val_split, category 47 | 48 | 49 | images, labels = generate_data(all_data) 50 | train_split, test_split, val_split, category = generate_split(images, labels) 51 | 52 | train_frame = {'image': [item[0] for item in train_split], 53 | 'label': [item[1] for item in train_split],} 54 | test_frame = {'image': [item[0] for item in test_split], 55 | 'label': [item[1] for item in test_split],} 56 | val_frame = {'image': [item[0] for item in val_split], 57 | 'label': [item[1] for item in val_split],} 58 | category_frame = {'category': category,} 59 | 60 | category_frame = pd.DataFrame(data=category_frame) 61 | train_frame = pd.DataFrame(data=train_frame) 62 | test_frame = pd.DataFrame(data=test_frame) 63 | val_frame = pd.DataFrame(data=val_frame) 64 | 65 | category_frame.to_csv('/home/username/projects/Causal_Adversarial.private/BPFC_mine/data/mini-ImageNet/category_frame.csv') 66 | train_frame.to_csv('/home/username/projects/Causal_Adversarial.private/BPFC_mine/data/mini-ImageNet/train_frame.csv') 67 | test_frame.to_csv('/home/username/projects/Causal_Adversarial.private/BPFC_mine/data/mini-ImageNet/test_frame.csv') 68 | val_frame.to_csv('/home/username/projects/Causal_Adversarial.private/BPFC_mine/data/mini-ImageNet/val_frame.csv') 69 | -------------------------------------------------------------------------------- /attacker/attacks/eot.py: -------------------------------------------------------------------------------- 1 | ############################################################################## 2 | # Modified from https://github.com/Harry24k/adversarial-attacks-pytorch 3 | ############################################################################## 4 | 5 | import torch 6 | import torch.nn as nn 7 | 8 | from ..attacker import Attacker 9 | import utils.general_utils as utils 10 | 11 | class EOT(Attacker): 12 | """ 13 | EOT(Linf) attack in the paper 'Obfuscated Gradients Give a False Sense of Security: Circumventing Defenses to Adversarial Examples' 14 | [https://arxiv.org/abs/1802.00420] 15 | 16 | """ 17 | def __init__(self, model, logger, config, eps=16.0, learning_rate=0.1, steps=100, eot_iter=30): 18 | super(EOT, self).__init__("EOT", model, logger, config) 19 | self.eps = eps / 255.0 20 | self.learning_rate = learning_rate 21 | self.steps = steps 22 | self.eot_iter = eot_iter 23 | self.loss = nn.CrossEntropyLoss() 24 | 25 | logger.info('Create Attacker EOT with eps: {}, learning_rate: {}, steps: {}, eot: {}'.format(eps, learning_rate, steps, eot_iter)) 26 | 27 | def forward(self, images, labels, random_start=False, targeted=False): 28 | """ 29 | Overridden. 30 | """ 31 | if targeted: 32 | self.sign = -1 33 | else: 34 | self.sign = 1 35 | 36 | images, labels = images.cuda(), labels.cuda() 37 | 38 | org_images = images.detach() 39 | adv_images = images.clone().detach() 40 | 41 | for _ in range(self.steps): 42 | adv_images = adv_images.detach() 43 | adv_images.requires_grad = True 44 | 45 | # apply EOT to the attacker 46 | eot_grads = [] 47 | # EOT is applied when eot_iter > 1 48 | for _ in range(self.eot_iter): 49 | if adv_images.grad: 50 | adv_images.grad.zero_() 51 | outputs = self.model(adv_images) 52 | if isinstance(outputs, tuple): 53 | outputs = outputs[0] 54 | cost = self.sign * self.loss(outputs, labels) 55 | grad = torch.autograd.grad(cost, adv_images, create_graph=True)[0] 56 | eot_grads.append(grad.detach().clone()) 57 | grad = sum(eot_grads) 58 | 59 | # adv image update, image is NOT normalized 60 | adv_images = self.adv_image_update(adv_images, org_images, grad) 61 | 62 | return adv_images 63 | 64 | def adv_image_update(self, adv_images, org_images, grad): 65 | # for the original EOT implemented in https://github.com/anishathalye/obfuscated-gradients/blob/72e24bc4f4669c01a4f2987a2c4a01d2ba363687/randomization/robustml_attack.py 66 | # instead of grad.sign(), the grad is directly used 67 | adv_images = adv_images.detach() + self.learning_rate * grad 68 | delta = torch.clamp(adv_images - org_images, min=-self.eps, max=self.eps) 69 | adv_images = torch.clamp(org_images + delta, min=0, max=1) 70 | return adv_images.detach() 71 | -------------------------------------------------------------------------------- /old_file/old_data/dt_mnist.py: -------------------------------------------------------------------------------- 1 | import os 2 | import json 3 | 4 | import torch 5 | import torch.utils.data as data 6 | import torchvision 7 | import torchvision.transforms as transforms 8 | import numpy as np 9 | from PIL import Image 10 | 11 | from randaugment import RandAugment 12 | 13 | class MNISTData(torchvision.datasets.MNIST): 14 | def __init__(self, phase, data_path, output_path, logger): 15 | if not os.path.exists(data_path): 16 | os.mkdir(data_path) 17 | train = True if phase == 'train' else False 18 | super(MNISTData, self).__init__(data_path, train, transform=None, target_transform=None, download=True) 19 | valid_phase = ['train', 'val', 'test'] 20 | assert phase in valid_phase 21 | 22 | self.dataset_info = {} 23 | self.phase = phase 24 | self.transform = self.get_data_transform(phase) 25 | 26 | # get dataset info 27 | self.get_dataset_info() 28 | # save dataset info 29 | logger.info('=====> Save dataset info') 30 | self.save_dataset_info(output_path) 31 | 32 | 33 | def __len__(self): 34 | return len(self.targets) 35 | 36 | 37 | def __getitem__(self, index): 38 | img, label = self.data[index], self.targets[index] 39 | img = img.unsqueeze(0) 40 | if self.transform is not None: 41 | img = self.transform(img) 42 | return img, label, index 43 | 44 | 45 | ####################################### 46 | # get dataset info 47 | ####################################### 48 | def get_dataset_info(self): 49 | self.id2class = {i:_class for i, _class in enumerate(self.classes)} 50 | self.dataset_info['id2class'] = self.id2class 51 | 52 | 53 | ####################################### 54 | # transform 55 | ####################################### 56 | def get_data_transform(self, phase): 57 | transform_info = {} 58 | 59 | if phase == 'train': 60 | trans = transforms.Compose([ 61 | transforms.ToPILImage(), 62 | transforms.RandomResizedCrop(32, scale=(0.8, 1.0), ratio=(0.8, 1.2)), 63 | transforms.ToTensor(), 64 | ]) 65 | transform_info['operations'] = ['ToPILImage()', 'transforms.RandomResizedCrop(32, scale=(0.8, 1.0), ratio=(0.8, 1.2)),', 'ToTensor()'] 66 | else: 67 | trans = transforms.Compose([ 68 | transforms.ToPILImage(), 69 | transforms.Resize(32), 70 | transforms.ToTensor(), 71 | ]) 72 | transform_info['operations'] = ['ToPILImage()', 'Resize(32)', 'ToTensor()'] 73 | 74 | # save dataset info 75 | self.dataset_info['transform_info'] = transform_info 76 | 77 | return trans 78 | 79 | ####################################### 80 | # Save dataset info 81 | ####################################### 82 | def save_dataset_info(self, output_path): 83 | 84 | with open(os.path.join(output_path, 'dataset_info_{}.json'.format(self.phase)), 'w') as f: 85 | json.dump(self.dataset_info, f) 86 | 87 | del self.dataset_info 88 | 89 | -------------------------------------------------------------------------------- /attacker/attacks/fgsm.py: -------------------------------------------------------------------------------- 1 | ############################################################################## 2 | # Modified from https://github.com/Harry24k/adversarial-attacks-pytorch 3 | ############################################################################## 4 | 5 | import torch 6 | import torch.nn as nn 7 | 8 | from ..attacker import Attacker 9 | import utils.general_utils as utils 10 | 11 | class FGSM(Attacker): 12 | r""" 13 | FGSM in the paper 'Explaining and harnessing adversarial examples' 14 | [https://arxiv.org/abs/1412.6572] 15 | 16 | Distance Measure : Linf 17 | Arguments: 18 | model (nn.Module): model to attack. 19 | eps (float): maximum perturbation. (DEFALUT: 0.007) 20 | 21 | Shape: 22 | - images: :math:`(N, C, H, W)` where `N = number of batches`, `C = number of channels`, `H = height` and `W = width`. It must have a range [0, 1]. 23 | - labels: :math:`(N)` where each value :math:`y_i` is :math:`0 \leq y_i \leq` `number of labels`. 24 | - output: :math:`(N, C, H, W)`. 25 | 26 | Examples:: 27 | >>> attack = torchattacks.FGSM(model, eps=0.007) 28 | >>> adv_images = attack(images, labels) 29 | 30 | """ 31 | def __init__(self, model, logger, config, eps=16.0, eot_iter=1): 32 | super(FGSM, self).__init__("FGSM", model, logger, config) 33 | self.eps = eps / 255.0 34 | self.eot_iter = eot_iter 35 | self.loss = nn.CrossEntropyLoss() 36 | 37 | logger.info('Create Attacker FGSM with eps: {}, eot: {}'.format(eps, eot_iter)) 38 | 39 | def forward(self, images, labels, random_start=False, targeted=False): 40 | """ 41 | Overridden. 42 | Note: FGSM doesn't contain random_start 43 | """ 44 | if targeted: 45 | self.sign = -1 46 | else: 47 | self.sign = 1 48 | 49 | images, labels = images.cuda(), labels.cuda() 50 | 51 | org_images = images.detach() 52 | 53 | if random_start: 54 | adv_images = images.clone().detach() + torch.randn_like(images).uniform_(-self.eps, self.eps) 55 | adv_images = torch.clamp(adv_images, min=0, max=1).detach() 56 | else: 57 | adv_images = images.clone().detach() 58 | 59 | adv_images.requires_grad = True 60 | 61 | # apply EOT to the attacker 62 | eot_grads = [] 63 | # EOT is applied when eot_iter > 1 64 | for _ in range(self.eot_iter): 65 | if adv_images.grad: 66 | adv_images.grad.zero_() 67 | outputs = self.model(adv_images) 68 | if isinstance(outputs, tuple): 69 | outputs = outputs[0] 70 | cost = self.sign * self.loss(outputs, labels) 71 | grad = torch.autograd.grad(cost, adv_images, create_graph=True)[0] 72 | eot_grads.append(grad.detach().clone()) 73 | grad = sum(eot_grads) / self.eot_iter 74 | 75 | # adv image update, image is NOT normalized 76 | adv_images = org_images.detach() + self.eps * grad.sign() 77 | adv_images = torch.clamp(adv_images, min=0, max=1).detach() 78 | return adv_images.detach() 79 | -------------------------------------------------------------------------------- /attacker/attacks/ffgsm.py: -------------------------------------------------------------------------------- 1 | ############################################################################## 2 | # Modified from https://github.com/Harry24k/adversarial-attacks-pytorch 3 | ############################################################################## 4 | 5 | import torch 6 | import torch.nn as nn 7 | 8 | from ..attacker import Attacker 9 | import utils.general_utils as utils 10 | 11 | class FFGSM(Attacker): 12 | r""" 13 | New FGSM proposed in 'Fast is better than free: Revisiting adversarial training' 14 | [https://arxiv.org/abs/2001.03994] 15 | 16 | Distance Measure : Linf 17 | Arguments: 18 | model (nn.Module): model to attack. 19 | eps (float): maximum perturbation. (DEFALUT: 8/255) 20 | alpha (float): step size. (DEFALUT: 10/255) 21 | 22 | Shape: 23 | - images: :math:`(N, C, H, W)` where `N = number of batches`, `C = number of channels`, `H = height` and `W = width`. It must have a range [0, 1]. 24 | - labels: :math:`(N)` where each value :math:`y_i` is :math:`0 \leq y_i \leq` `number of labels`. 25 | - output: :math:`(N, C, H, W)`. 26 | 27 | Examples:: 28 | >>> attack = torchattacks.FFGSM(model, eps=8/255, alpha=10/255) 29 | >>> adv_images = attack(images, labels) 30 | """ 31 | def __init__(self, model, logger, config, eps=8.0, alpha=10.0, eot_iter=1): 32 | super(FFGSM, self).__init__("FFGSM", model, logger, config) 33 | self.eps = eps / 255.0 34 | self.alpha = alpha / 255.0 35 | self.eot_iter = eot_iter 36 | self.loss = nn.CrossEntropyLoss() 37 | 38 | logger.info('Create Attacker FFGSM with eps: {}, alpha: {}, eot: {}'.format(eps, alpha, eot_iter)) 39 | 40 | def forward(self, images, labels, random_start=False, targeted=False): 41 | """ 42 | Overridden. 43 | Note: FFGSM always apply random_start 44 | """ 45 | if targeted: 46 | self.sign = -1 47 | else: 48 | self.sign = 1 49 | 50 | images, labels = images.cuda(), labels.cuda() 51 | 52 | org_images = images.detach() 53 | adv_images = images.clone().detach() + torch.randn_like(images).uniform_(-self.eps, self.eps) 54 | adv_images = torch.clamp(adv_images, min=0, max=1).detach() 55 | adv_images.requires_grad = True 56 | 57 | # apply EOT to the attacker 58 | eot_grads = [] 59 | # EOT is applied when eot_iter > 1 60 | for _ in range(self.eot_iter): 61 | if adv_images.grad: 62 | adv_images.grad.zero_() 63 | outputs = self.model(adv_images) 64 | if isinstance(outputs, tuple): 65 | outputs = outputs[0] 66 | cost = self.sign * self.loss(outputs, labels) 67 | grad = torch.autograd.grad(cost, adv_images, create_graph=True)[0] 68 | eot_grads.append(grad.detach().clone()) 69 | grad = sum(eot_grads) / self.eot_iter 70 | 71 | # adv image update, image is NOT normalized 72 | adv_images = adv_images.detach() + self.alpha * grad.sign() 73 | delta = torch.clamp(adv_images - org_images, min=-self.eps, max=self.eps) 74 | adv_images = torch.clamp(org_images + delta, min=0, max=1).detach() 75 | return adv_images.detach() 76 | -------------------------------------------------------------------------------- /utils/checkpoint_utils.py: -------------------------------------------------------------------------------- 1 | import os 2 | import json 3 | import torch 4 | import numpy as np 5 | 6 | class Checkpoint(): 7 | def __init__(self, config): 8 | self.config = config 9 | self.save_best = config['checkpoint_opt']['save_best'] 10 | self.best_epoch = -1 11 | self.best_performance = -1 12 | self.best_model_path = None 13 | 14 | 15 | def save(self, model, epoch, logger, acc): 16 | # update best model 17 | model_name = 'epoch_{}_'.format(epoch) + self.config['checkpoint_opt']['checkpoint_name'] 18 | model_path = os.path.join(self.config['output_dir'], model_name) 19 | if acc is not None: 20 | if float(acc) > self.best_performance: 21 | self.best_epoch = epoch 22 | self.best_performance = float(acc) 23 | self.best_model_path = model_path 24 | self.save_current = True 25 | logger.info('Best model is updated at epoch {} with accuracy {:9.3f} (Path: {})'.format(self.best_epoch, self.best_performance, self.best_model_path)) 26 | else: 27 | self.save_current = False 28 | else: 29 | # if acc is None, the newest is always the best 30 | self.best_epoch = epoch 31 | self.best_model_path = model_path 32 | 33 | # only save the best model or the last model 34 | best_saving = (self.save_best and self.save_current) 35 | # only save at certain steps, best epoch or the last epoch 36 | if (not best_saving) and (epoch % self.config['checkpoint_opt']['checkpoint_step'] != 0) and (epoch < (self.config['training_opt']['num_epochs'] - 1)): 37 | return 38 | 39 | output = { 40 | 'state_dict': model.state_dict(), 41 | 'epoch': epoch, 42 | } 43 | 44 | logger.info('Model at epoch {} is saved to {}'.format(epoch, model_path)) 45 | torch.save(output, model_path) 46 | logger.info('Best model is at epoch {} with accuracy {:9.3f}'.format(self.best_epoch, self.best_performance)) 47 | self.save_best_model(logger) 48 | 49 | 50 | def save_best_model(self, logger): 51 | logger.info('Best model is at epoch {} with accuracy {:9.3f} (Path: {})'.format(self.best_epoch, self.best_performance, self.best_model_path)) 52 | with open(os.path.join(self.config['output_dir'], 'best_checkpoint'), 'w+') as f: 53 | f.write(self.best_model_path + ' ' + str(self.best_epoch) + ' ' + str(self.best_performance) + '\n') 54 | 55 | def load(self, model, path, logger): 56 | if path.split('.')[-1] != 'pth': 57 | with open(os.path.join(path, 'best_checkpoint')) as f: 58 | path = f[0].split(' ')[0] 59 | 60 | checkpoint = torch.load(path, map_location='cpu') 61 | logger.info('Loading checkpoint pretrained with epoch {}.'.format(checkpoint['epoch'])) 62 | model_state = checkpoint['state_dict'] 63 | 64 | x = model.state_dict() 65 | for key, _ in x.items(): 66 | if key in model_state: 67 | x[key] = model_state[key] 68 | logger.info('Load {:>50} from checkpoint.'.format(key)) 69 | elif 'module.' + key in model_state: 70 | x[key] = model_state['module.' + key] 71 | logger.info('Load {:>50} from checkpoint (rematch with module.).'.format(key)) 72 | else: 73 | logger.info('WARNING: Key {} is missing in the checkpoint.'.format(key)) 74 | 75 | model.load_state_dict(x) 76 | pass 77 | 78 | 79 | -------------------------------------------------------------------------------- /old_file/old_model/VGG.py: -------------------------------------------------------------------------------- 1 | import torch 2 | import torch.nn as nn 3 | import torchvision.models as models 4 | 5 | from models.Base_Model import Base_Model 6 | 7 | class VGG(Base_Model): 8 | def __init__(self, features, num_classes=1000, init_weights=True): 9 | super(VGG, self).__init__() 10 | self.features = features 11 | self.avgpool = nn.AdaptiveAvgPool2d((7, 7)) 12 | self.classifier = nn.Sequential( 13 | nn.Linear(512 * 7 * 7, 4096), 14 | nn.ReLU(True), 15 | nn.Dropout(), 16 | nn.Linear(4096, 4096), 17 | nn.ReLU(True), 18 | nn.Dropout(), 19 | nn.Linear(4096, num_classes), 20 | ) 21 | if init_weights: 22 | self._initialize_weights() 23 | 24 | def forward(self, x): 25 | if x.shape[1] == 1: 26 | x = x.repeat(1, 3, 1, 1) 27 | x = self.features(x) 28 | x = self.avgpool(x) 29 | x = torch.flatten(x, 1) 30 | x = self.classifier(x) 31 | return x 32 | 33 | def _initialize_weights(self): 34 | for m in self.modules(): 35 | if isinstance(m, nn.Conv2d): 36 | nn.init.kaiming_normal_(m.weight, mode='fan_out', nonlinearity='relu') 37 | if m.bias is not None: 38 | nn.init.constant_(m.bias, 0) 39 | elif isinstance(m, nn.BatchNorm2d): 40 | nn.init.constant_(m.weight, 1) 41 | nn.init.constant_(m.bias, 0) 42 | elif isinstance(m, nn.Linear): 43 | nn.init.normal_(m.weight, 0, 0.01) 44 | nn.init.constant_(m.bias, 0) 45 | 46 | 47 | def make_layers(cfg, batch_norm=False): 48 | layers = [] 49 | in_channels = 3 50 | for v in cfg: 51 | if v == 'M': 52 | layers += [nn.MaxPool2d(kernel_size=2, stride=2)] 53 | else: 54 | conv2d = nn.Conv2d(in_channels, v, kernel_size=3, padding=1) 55 | if batch_norm: 56 | layers += [conv2d, nn.BatchNorm2d(v), nn.ReLU(inplace=True)] 57 | else: 58 | layers += [conv2d, nn.ReLU(inplace=True)] 59 | in_channels = v 60 | return nn.Sequential(*layers) 61 | 62 | 63 | cfgs = { 64 | 'A': [64, 'M', 128, 'M', 256, 256, 'M', 512, 512, 'M', 512, 512, 'M'], 65 | 'B': [64, 64, 'M', 128, 128, 'M', 256, 256, 'M', 512, 512, 'M', 512, 512, 'M'], 66 | 'D': [64, 64, 'M', 128, 128, 'M', 256, 256, 256, 'M', 512, 512, 512, 'M', 512, 512, 512, 'M'], 67 | 'E': [64, 64, 'M', 128, 128, 'M', 256, 256, 256, 256, 'M', 512, 512, 512, 512, 'M', 512, 512, 512, 512, 'M'], 68 | } 69 | 70 | 71 | def _vgg(arch, cfg, batch_norm, **kwargs): 72 | model = VGG(make_layers(cfgs[cfg], batch_norm=batch_norm), **kwargs) 73 | return model 74 | 75 | 76 | def vgg11(**kwargs): 77 | return _vgg('vgg11', 'A', False, **kwargs) 78 | 79 | def vgg11_bn(**kwargs): 80 | return _vgg('vgg11_bn', 'A', True, **kwargs) 81 | 82 | def vgg13(**kwargs): 83 | return _vgg('vgg13', 'B', False, **kwargs) 84 | 85 | def vgg13_bn(**kwargs): 86 | return _vgg('vgg13_bn', 'B', True, **kwargs) 87 | 88 | def vgg16(**kwargs): 89 | return _vgg('vgg16', 'D', False, **kwargs) 90 | 91 | def vgg16_bn(**kwargs): 92 | return _vgg('vgg16_bn', 'D', True, **kwargs) 93 | 94 | def vgg19(**kwargs): 95 | return _vgg('vgg19', 'E', False, **kwargs) 96 | 97 | def vgg19_bn(**kwargs): 98 | return _vgg('vgg19_bn', 'E', True, **kwargs) 99 | 100 | 101 | def create_model(m_type='vgg16', num_classes=1000, first_conv_size=7): 102 | # create various resnet models 103 | if m_type == 'vgg16': 104 | model = vgg16(num_classes=num_classes) 105 | 106 | return model -------------------------------------------------------------------------------- /attacker/attacks/adaptive_pgd.py: -------------------------------------------------------------------------------- 1 | ############################################################################## 2 | # Modified from https://github.com/Harry24k/adversarial-attacks-pytorch 3 | ############################################################################## 4 | 5 | import torch 6 | import torch.nn as nn 7 | import torch.nn.functional as F 8 | 9 | from ..attacker import Attacker 10 | import utils.general_utils as utils 11 | 12 | class ADAPTIVE(Attacker): 13 | def __init__(self, model, logger, config, eps=16.0, alpha=1.0, steps=30, weight=10.0, eot_iter=1): 14 | super(ADAPTIVE, self).__init__("ADAPTIVE", model, logger, config) 15 | self.eps = eps / 255.0 16 | self.alpha = alpha / 255.0 17 | self.weight = weight 18 | self.steps = steps 19 | self.eot_iter = eot_iter 20 | self.loss = nn.CrossEntropyLoss() 21 | 22 | logger.info('Create Attacker ADAPTIVE with eps: {}, alpha: {}, steps: {}, eot: {}, weight: {}'.format(eps, alpha, steps, eot_iter, weight)) 23 | 24 | def forward(self, images, labels, random_start=False, targeted=False): 25 | """ 26 | Overridden. 27 | """ 28 | if targeted: 29 | self.sign = -1 30 | else: 31 | self.sign = 1 32 | 33 | images, labels = images.cuda(), labels.cuda() 34 | 35 | org_images = images.detach() 36 | adv_images = images.clone().detach() 37 | 38 | if random_start: 39 | # Starting at a uniformly random point 40 | adv_images = adv_images + torch.empty_like(adv_images).uniform_(-self.eps, self.eps) 41 | adv_images = torch.clamp(adv_images, min=0, max=1) 42 | 43 | for _ in range(self.steps): 44 | adv_images = adv_images.detach() 45 | adv_images.requires_grad = True 46 | 47 | # apply EOT to the attacker 48 | eot_grads = [] 49 | # EOT is applied when eot_iter > 1 50 | for _ in range(self.eot_iter): 51 | if adv_images.grad: 52 | adv_images.grad.zero_() 53 | all_ces = [] 54 | all_regs = [] 55 | preds, other_feats, other_logits = self.model(adv_images, loop=5) 56 | for i, logits in enumerate(other_logits): 57 | ce_loss = F.cross_entropy(logits, labels) 58 | all_ces.append(ce_loss) 59 | mean_feat = sum(other_feats) / len(other_feats) 60 | for i in range(len(other_feats)): 61 | reg_loss = self.smooth_l1_loss(other_feats[i], mean_feat) 62 | all_regs.append(reg_loss) 63 | loss = sum(all_ces) + self.weight * sum(all_regs) 64 | cost = self.sign * loss 65 | grad = torch.autograd.grad(cost, adv_images, create_graph=True)[0] 66 | eot_grads.append(grad.detach().clone()) 67 | grad = sum(eot_grads) / self.eot_iter 68 | 69 | # adv image update, image is NOT normalized 70 | adv_images = self.adv_image_update(adv_images, org_images, grad) 71 | 72 | return adv_images 73 | 74 | def smooth_l1_loss(self, x, y): 75 | diff = F.smooth_l1_loss(x, y, reduction='none') 76 | diff = diff.sum(1) 77 | diff = diff.mean(0) 78 | return diff 79 | 80 | def adv_image_update(self, adv_images, org_images, grad): 81 | # image is NOT normalized 82 | adv_images = adv_images.detach() + self.alpha * grad.sign() 83 | delta = torch.clamp(adv_images - org_images, min=-self.eps, max=self.eps) 84 | adv_images = torch.clamp(org_images + delta, min=0, max=1) 85 | return adv_images 86 | 87 | -------------------------------------------------------------------------------- /data/dt_toy.py: -------------------------------------------------------------------------------- 1 | import os 2 | import json 3 | 4 | import torch 5 | import torch.utils.data as data 6 | import torchvision.transforms as transforms 7 | import numpy as np 8 | import pandas as pd 9 | from PIL import Image 10 | 11 | 12 | class TOYData(data.Dataset): 13 | def __init__(self, phase, output_path, num_classes, logger): 14 | super(TOYData, self).__init__() 15 | valid_phase = ['train', 'val', 'test'] 16 | assert phase in valid_phase 17 | 18 | if phase == 'train': 19 | self.num_data = 10000 20 | elif phase == 'val': 21 | self.num_data = 1000 22 | elif phase == 'test': 23 | self.num_data = 1000 24 | 25 | self.num_classes = num_classes 26 | self.dataset_info = {} 27 | self.phase = phase 28 | self.generate_data() 29 | 30 | # save dataset info 31 | logger.info('=====> Save dataset info') 32 | self.save_dataset_info(output_path) 33 | 34 | 35 | def __len__(self): 36 | return len(self.labels) 37 | 38 | def generate_data(self): 39 | assert self.num_classes == 3 40 | self.images = [] 41 | self.labels = torch.randint(0, self.num_classes, (self.num_data,)).tolist() 42 | 43 | for i in range(self.num_data): 44 | tp = str(self.labels[i]) 45 | self.images.append(self.generate_patterns(tp=tp)) 46 | 47 | def __getitem__(self, index): 48 | image = self.images[index] 49 | label = self.labels[index] 50 | 51 | return image, label, index 52 | 53 | def generate_patterns(self, tp='1', noise=True): 54 | if noise: 55 | tps = {'0':{'r':0.8, 'g':0.1, 'b':0.1}, '1':{'r':0.1, 'g':0.8, 'b':0.1}, '2':{'r':0.1, 'g':0.1, 'b':0.8}} 56 | r = torch.zeros(1, 16, 1, 16, 1).uniform_(0,tps[tp]['r']).repeat(1,1,4,1,4).contiguous().view(1,64,64) 57 | g = torch.zeros(1, 16, 1, 16, 1).uniform_(0,tps[tp]['g']).repeat(1,1,4,1,4).contiguous().view(1,64,64) 58 | b = torch.zeros(1, 16, 1, 16, 1).uniform_(0,tps[tp]['b']).repeat(1,1,4,1,4).contiguous().view(1,64,64) 59 | img = torch.cat([r,g,b], dim=0) 60 | img = img.contiguous().view(3, 64*64).contiguous().permute(1,0).max(-1)[1] 61 | img = torch.nn.functional.one_hot(img, 3).permute(1,0).contiguous().view(3,64,64).float() 62 | img = img * 0.2 + 0.8 63 | else: 64 | img = torch.zeros(3, 64, 64) 65 | 66 | radius = torch.zeros(1).float().uniform_(15, 25).item() 67 | if tp == '0': 68 | w = torch.arange(64).view(1,64).repeat(64,1).float() 69 | h = torch.arange(64).view(64,1).repeat(1,64).float() 70 | mask = ((w - 31.5)**2 + (h - 31.5)**2) ** 0.5 71 | mask = (mask < radius).float().view(1,64,64) 72 | elif tp == '1': 73 | w = torch.arange(64).view(1,64).repeat(64,1).float() 74 | h = torch.arange(64).view(64,1).repeat(1,64).float() 75 | mask = ((w - 31.5).abs() < radius).float() + ((h - 31.5).abs() < radius).float() 76 | mask = (mask >= 2.0).float().view(1,64,64) 77 | elif tp == '2': 78 | w = torch.arange(64).view(1,64).repeat(64,1).float() 79 | h = torch.arange(64).view(64,1).repeat(1,64).float() 80 | r1 = (h < (25+radius)).float() 81 | r2 = (w+h > (64-radius/2)).float() 82 | r3 = ((h-w) > -radius/2).float() 83 | mask = ((r1+r2+r3) >= 3.0).float().view(1,64,64) 84 | 85 | img = torch.clamp(img - mask, 0, 1) 86 | return img 87 | 88 | 89 | 90 | ####################################### 91 | # Save dataset info 92 | ####################################### 93 | def save_dataset_info(self, output_path): 94 | 95 | with open(os.path.join(output_path, 'dataset_info_{}.json'.format(self.phase)), 'w') as f: 96 | json.dump(self.dataset_info, f) 97 | 98 | del self.dataset_info -------------------------------------------------------------------------------- /test_baseline.py: -------------------------------------------------------------------------------- 1 | import torch 2 | import torch.nn as nn 3 | import torch.nn.functional as F 4 | 5 | from data.dataloader import get_loader 6 | 7 | import os 8 | import time 9 | import random 10 | import attacker 11 | 12 | from utils.attack_utils import * 13 | 14 | class test_baseline(): 15 | def __init__(self, args, config, logger, model, val=False): 16 | self.config = config 17 | self.logger = logger 18 | self.model = model 19 | 20 | # initialize attacker 21 | self.adv_test = self.config['attacker_opt']['adv_val'] 22 | if self.adv_test: 23 | self.attacker = create_adversarial_attacker(config, model, logger) 24 | 25 | # save test 26 | self.test_save = True if config['test_opt']['save_data'] else False 27 | 28 | # get dataloader 29 | if val: 30 | self.phase = 'val' 31 | self.loader = get_loader(config, 'val', logger) 32 | else: 33 | self.phase = 'test' 34 | self.loader = get_loader(config, 'test', logger) 35 | 36 | def run_val(self, epoch): 37 | self.logger.info('------------- Start Validation at Epoch {} -----------'.format(epoch)) 38 | total_acc = [] 39 | 40 | # set model to evaluation 41 | self.model.eval() 42 | 43 | # save test 44 | if self.test_save: 45 | org_list = [] 46 | adv_list = [] 47 | gt_list = [] 48 | pred_list = [] 49 | 50 | # run batch 51 | for i, (inputs, labels, indexes) in enumerate(self.loader): 52 | inputs, labels = inputs.cuda(), labels.cuda() 53 | batch_size = inputs.shape[0] 54 | # print test time 55 | # trigger adversarial attack or not 56 | if self.adv_test: 57 | if self.config['targeted_attack']: 58 | adv_targets = get_adv_target(self.config['targeted_type'], self.model, inputs, labels) 59 | adv_inputs = self.attacker.get_adv_images(inputs, adv_targets, random_start=rand_adv_init(self.config), targeted=True) 60 | else: 61 | adv_inputs = self.attacker.get_adv_images(inputs, labels, random_start=rand_adv_init(self.config)) 62 | self.model.eval() 63 | final_inputs = adv_inputs 64 | else: 65 | final_inputs = inputs 66 | 67 | # run model 68 | with torch.no_grad(): 69 | predictions = self.model(final_inputs) 70 | 71 | if isinstance(predictions, tuple): 72 | predictions = predictions[0] 73 | 74 | total_acc.append((predictions.max(1)[1] == labels).view(-1, 1)) 75 | 76 | # save adversarial images 77 | if self.test_save and i < self.config['test_opt']['save_length']: 78 | org_list.append(inputs.cpu()) 79 | gt_list.append(labels.cpu()) 80 | pred_list.append(predictions.max(1)[1].cpu()) 81 | if self.adv_test: 82 | adv_list.append(adv_inputs.cpu()) 83 | 84 | all_acc = torch.cat(total_acc, dim=0).float() 85 | avg_acc = all_acc.mean().item() 86 | self.logger.info('Epoch {:5d} Evaluation Complete ==> Total Accuracy : {:9.4f}, Number Samples : {:9d}'.format(epoch, avg_acc, all_acc.shape[0])) 87 | 88 | # set back to training mode again 89 | self.model.train() 90 | 91 | # save adversarial images 92 | if self.test_save: 93 | file_name = os.path.join(self.config['output_dir'], self.config['test_opt']['file_name']) 94 | adv_output = { 95 | 'org_images' : torch.cat(org_list, 0), 96 | 'gt_labels' : torch.cat(gt_list, 0), 97 | 'adv_images' : torch.cat(adv_list, 0) if self.adv_test else 0, 98 | 'pred_labels': torch.cat(pred_list, 0), 99 | } 100 | torch.save(adv_output, file_name) 101 | self.logger.info('=====> Complete! Adversarial images have been saved to {}'.format(file_name)) 102 | 103 | return avg_acc -------------------------------------------------------------------------------- /attacker/attacks/pgd_feat.py: -------------------------------------------------------------------------------- 1 | ############################################################################## 2 | # Modified from https://github.com/Harry24k/adversarial-attacks-pytorch 3 | ############################################################################## 4 | 5 | import torch 6 | import torch.nn as nn 7 | 8 | from ..attacker import Attacker 9 | import utils.general_utils as utils 10 | 11 | class PGD_Feat(Attacker): 12 | """ 13 | PGD(Linf) attack in the paper 'Towards Deep Learning Models Resistant to Adversarial Attacks' 14 | [https://arxiv.org/abs/1706.06083] 15 | 16 | Arguments: 17 | model (nn.Module): model to attack. 18 | eps (float): strength of the attack or maximum perturbation. (DEFALUT : 16(max 255)) 19 | alpha (float): step size. (DEFALUT : 1(max 255)) 20 | steps (int): number of steps. (DEFALUT : 30) 21 | random_start (bool): using random initialization of delta. (DEFAULT : False) 22 | targeted (bool): using targeted attack with input labels as targeted labels. (DEFAULT : False) 23 | 24 | Shape: 25 | - images: :math:`(N, C, H, W)` where `N = number of batches`, `C = number of channels`, `H = height` and `W = width`. It must have a range [0, 1]. 26 | - labels: :math:`(N)` where each value :math:`y_i` is :math:`0 \leq y_i \leq` `number of labels`. 27 | - output: :math:`(N, C, H, W)`. 28 | 29 | Examples:: 30 | >>> attack = torchattacks.PGD(model, eps = 4, alpha = 1, steps=40, random_start=False) 31 | >>> adv_images = attack(images, labels) 32 | 33 | """ 34 | def __init__(self, model, logger, config, eps=16.0, alpha=1.0, steps=30, eot_iter=1): 35 | super(PGD_Feat, self).__init__("PGD_Feat", model, logger, config) 36 | self.eps = eps / 255.0 37 | self.alpha = alpha / 255.0 38 | self.steps = steps 39 | self.eot_iter = eot_iter 40 | self.loss = nn.MSELoss() 41 | 42 | logger.info('Create Attacker PGD_Feat with eps: {}, alpha: {}, steps: {}, eot: {}'.format(eps, alpha, steps, eot_iter)) 43 | 44 | 45 | def clamp(self, X, lower_limit, upper_limit): 46 | return torch.max(torch.min(X, upper_limit), lower_limit) 47 | 48 | def forward(self, images, target_feat, random_start=False, targeted=False): 49 | """ 50 | Overridden. 51 | """ 52 | if targeted: 53 | self.sign = -1 54 | else: 55 | self.sign = 1 56 | 57 | images, target_feat = images.cuda(), target_feat.cuda() 58 | 59 | org_images = images.detach() 60 | delta = torch.zeros_like(org_images).cuda() 61 | 62 | if random_start: 63 | # Starting at a uniformly random point 64 | delta.uniform_(-self.eps, self.eps) 65 | delta = self.clamp(delta, 0.0-org_images, 1.0-org_images) 66 | 67 | for _ in range(self.steps): 68 | delta = delta.detach() 69 | delta.requires_grad = True 70 | 71 | # apply EOT to the attacker 72 | eot_grads = [] 73 | # EOT is applied when eot_iter > 1 74 | for _ in range(self.eot_iter): 75 | if delta.grad: 76 | delta.grad.zero_() 77 | _, feats = self.model(org_images + delta) 78 | cost = self.sign * self.loss(feats, target_feat.detach()) 79 | grad = torch.autograd.grad(cost, delta, create_graph=True)[0] 80 | #cost.backward() 81 | #grad = delta.grad.detach() 82 | eot_grads.append(grad.detach().clone()) 83 | grad = sum(eot_grads) / self.eot_iter 84 | 85 | # adv image update, image is NOT normalized 86 | delta = self.adv_image_update(delta, org_images, grad) 87 | 88 | return (org_images + delta).detach() 89 | 90 | 91 | def adv_image_update(self, delta, org_images, grad): 92 | # image is NOT normalized 93 | delta = torch.clamp(delta + self.alpha * grad.sign(), min=-self.eps, max=self.eps) 94 | delta = self.clamp(delta, 0.0-org_images, 1.0-org_images) 95 | return delta 96 | 97 | -------------------------------------------------------------------------------- /attacker/attacks/pgd.py: -------------------------------------------------------------------------------- 1 | ############################################################################## 2 | # Modified from https://github.com/Harry24k/adversarial-attacks-pytorch 3 | ############################################################################## 4 | 5 | import torch 6 | import torch.nn as nn 7 | 8 | from ..attacker import Attacker 9 | import utils.general_utils as utils 10 | 11 | class PGD(Attacker): 12 | """ 13 | PGD(Linf) attack in the paper 'Towards Deep Learning Models Resistant to Adversarial Attacks' 14 | [https://arxiv.org/abs/1706.06083] 15 | 16 | Arguments: 17 | model (nn.Module): model to attack. 18 | eps (float): strength of the attack or maximum perturbation. (DEFALUT : 16(max 255)) 19 | alpha (float): step size. (DEFALUT : 1(max 255)) 20 | steps (int): number of steps. (DEFALUT : 30) 21 | random_start (bool): using random initialization of delta. (DEFAULT : False) 22 | targeted (bool): using targeted attack with input labels as targeted labels. (DEFAULT : False) 23 | 24 | Shape: 25 | - images: :math:`(N, C, H, W)` where `N = number of batches`, `C = number of channels`, `H = height` and `W = width`. It must have a range [0, 1]. 26 | - labels: :math:`(N)` where each value :math:`y_i` is :math:`0 \leq y_i \leq` `number of labels`. 27 | - output: :math:`(N, C, H, W)`. 28 | 29 | Examples:: 30 | >>> attack = torchattacks.PGD(model, eps = 4, alpha = 1, steps=40, random_start=False) 31 | >>> adv_images = attack(images, labels) 32 | 33 | """ 34 | def __init__(self, model, logger, config, eps=16.0, alpha=1.0, steps=30, eot_iter=1): 35 | super(PGD, self).__init__("PGD", model, logger, config) 36 | self.eps = eps / 255.0 37 | self.alpha = alpha / 255.0 38 | self.steps = steps 39 | self.eot_iter = eot_iter 40 | self.loss = nn.CrossEntropyLoss() 41 | 42 | logger.info('Create Attacker PGD with eps: {}, alpha: {}, steps: {}, eot: {}'.format(eps, alpha, steps, eot_iter)) 43 | 44 | 45 | def clamp(self, X, lower_limit, upper_limit): 46 | return torch.max(torch.min(X, upper_limit), lower_limit) 47 | 48 | def forward(self, images, labels, random_start=False, targeted=False): 49 | """ 50 | Overridden. 51 | """ 52 | if targeted: 53 | self.sign = -1 54 | else: 55 | self.sign = 1 56 | 57 | images, labels = images.cuda(), labels.cuda() 58 | 59 | org_images = images.detach() 60 | delta = torch.zeros_like(org_images).cuda() 61 | 62 | if random_start: 63 | # Starting at a uniformly random point 64 | delta.uniform_(-self.eps, self.eps) 65 | delta = self.clamp(delta, 0.0-org_images, 1.0-org_images) 66 | 67 | for _ in range(self.steps): 68 | delta = delta.detach() 69 | delta.requires_grad = True 70 | 71 | # apply EOT to the attacker 72 | eot_grads = [] 73 | # EOT is applied when eot_iter > 1 74 | for _ in range(self.eot_iter): 75 | if delta.grad: 76 | delta.grad.zero_() 77 | outputs = self.model(org_images + delta) 78 | if isinstance(outputs, tuple): 79 | outputs = outputs[0] 80 | cost = self.sign * self.loss(outputs, labels) 81 | grad = torch.autograd.grad(cost, delta, create_graph=True)[0] 82 | #cost.backward() 83 | #grad = delta.grad.detach() 84 | eot_grads.append(grad.detach().clone()) 85 | grad = sum(eot_grads) / self.eot_iter 86 | 87 | # adv image update, image is NOT normalized 88 | delta = self.adv_image_update(delta, org_images, grad) 89 | 90 | return (org_images + delta).detach() 91 | 92 | 93 | def adv_image_update(self, delta, org_images, grad): 94 | # image is NOT normalized 95 | delta = torch.clamp(delta + self.alpha * grad.sign(), min=-self.eps, max=self.eps) 96 | delta = self.clamp(delta, 0.0-org_images, 1.0-org_images) 97 | return delta 98 | 99 | -------------------------------------------------------------------------------- /models/VGG.py: -------------------------------------------------------------------------------- 1 | import torch 2 | import torch.nn as nn 3 | import torch.nn.functional as F 4 | import torchvision.models as models 5 | from typing import Union, List, Dict, Any, cast 6 | 7 | import math 8 | 9 | '''Pre-activation ResNet in PyTorch. 10 | Reference: 11 | [1] Kaiming He, Xiangyu Zhang, Shaoqing Ren, Jian Sun 12 | Identity Mappings in Deep Residual Networks. arXiv:1603.05027 13 | ''' 14 | 15 | from models.Base_Model import Base_Model 16 | 17 | from utils.train_utils import * 18 | 19 | __all__ = [ 20 | 'VGG', 'vgg11', 'vgg11_bn', 'vgg13', 'vgg13_bn', 'vgg16', 'vgg16_bn', 21 | 'vgg19_bn', 'vgg19', 22 | ] 23 | 24 | class VGG(Base_Model): 25 | 26 | def __init__( 27 | self, 28 | features: nn.Module, 29 | num_classes: int = 1000, 30 | init_weights: bool = True 31 | ) -> None: 32 | super(VGG, self).__init__() 33 | self.features = features 34 | self.mlp = nn.Sequential( 35 | nn.Linear(512, 4096), 36 | nn.ReLU(True), 37 | nn.Dropout(), 38 | nn.Linear(4096, 4096), 39 | nn.ReLU(True), 40 | nn.Dropout(), 41 | ) 42 | self.classifier = nn.Linear(4096, num_classes) 43 | if init_weights: 44 | self._initialize_weights() 45 | 46 | def forward(self, x: torch.Tensor) -> torch.Tensor: 47 | x = self.features(x) 48 | size = x.shape[-1] 49 | x = F.avg_pool2d(x, size) 50 | x = x.view(x.size(0), -1) 51 | x = self.mlp(x) 52 | x = self.classifier(x) 53 | return x 54 | 55 | def _initialize_weights(self) -> None: 56 | for m in self.modules(): 57 | if isinstance(m, nn.Conv2d): 58 | nn.init.kaiming_normal_(m.weight, mode='fan_out', nonlinearity='relu') 59 | if m.bias is not None: 60 | nn.init.constant_(m.bias, 0) 61 | elif isinstance(m, nn.BatchNorm2d): 62 | nn.init.constant_(m.weight, 1) 63 | nn.init.constant_(m.bias, 0) 64 | elif isinstance(m, nn.Linear): 65 | nn.init.normal_(m.weight, 0, 0.01) 66 | nn.init.constant_(m.bias, 0) 67 | 68 | 69 | def make_layers(cfg: List[Union[str, int]], batch_norm: bool = False) -> nn.Sequential: 70 | layers: List[nn.Module] = [] 71 | in_channels = 3 72 | for v in cfg: 73 | if v == 'M': 74 | layers += [nn.MaxPool2d(kernel_size=2, stride=2)] 75 | else: 76 | v = cast(int, v) 77 | conv2d = nn.Conv2d(in_channels, v, kernel_size=3, padding=1) 78 | if batch_norm: 79 | layers += [conv2d, nn.BatchNorm2d(v), nn.ReLU(inplace=True)] 80 | else: 81 | layers += [conv2d, nn.ReLU(inplace=True)] 82 | in_channels = v 83 | return nn.Sequential(*layers) 84 | 85 | 86 | cfgs: Dict[str, List[Union[str, int]]] = { 87 | 'A': [64, 'M', 128, 'M', 256, 256, 'M', 512, 512, 'M', 512, 512, 'M'], 88 | 'B': [64, 64, 'M', 128, 128, 'M', 256, 256, 'M', 512, 512, 'M', 512, 512, 'M'], 89 | 'D': [64, 64, 'M', 128, 128, 'M', 256, 256, 256, 'M', 512, 512, 512, 'M', 512, 512, 512, 'M'], 90 | 'E': [64, 64, 'M', 128, 128, 'M', 256, 256, 256, 256, 'M', 512, 512, 512, 512, 'M', 512, 512, 512, 512, 'M'], 91 | } 92 | 93 | 94 | def _vgg(arch: str, cfg: str, batch_norm: bool, **kwargs: Any) -> VGG: 95 | model = VGG(make_layers(cfgs[cfg], batch_norm=batch_norm), **kwargs) 96 | return model 97 | 98 | 99 | def vgg11(**kwargs: Any) -> VGG: 100 | return _vgg('vgg11', 'A', True, **kwargs) 101 | 102 | 103 | def vgg13(**kwargs: Any) -> VGG: 104 | return _vgg('vgg13', 'B', True, **kwargs) 105 | 106 | 107 | def vgg16(**kwargs: Any) -> VGG: 108 | return _vgg('vgg16', 'D', True, **kwargs) 109 | 110 | 111 | def create_model(m_type='vgg11', num_classes=1000): 112 | # create various resnet models 113 | if m_type == 'vgg11': 114 | model = vgg11(num_classes=num_classes) 115 | elif m_type == 'vgg13': 116 | model = vgg13(num_classes=num_classes) 117 | elif m_type == 'vgg16': 118 | model = vgg16(num_classes=num_classes) 119 | else: 120 | raise ValueError('Wrong Model Type') 121 | return model -------------------------------------------------------------------------------- /attacker/attacks/bpdapgd.py: -------------------------------------------------------------------------------- 1 | ############################################################################## 2 | # Modified from https://github.com/Harry24k/adversarial-attacks-pytorch 3 | ############################################################################## 4 | 5 | import torch 6 | import torch.nn as nn 7 | 8 | from ..attacker import Attacker 9 | import utils.general_utils as utils 10 | 11 | class BPDAPGD(Attacker): 12 | """ 13 | PGD(Linf) attack in the paper 'Towards Deep Learning Models Resistant to Adversarial Attacks' 14 | [https://arxiv.org/abs/1706.06083] 15 | BPDA attack in the paper 'Obfuscated Gradients Give a False Sense of Security: Circumventing Defenses to Adversarial Examples' 16 | [https://arxiv.org/abs/1802.00420] 17 | 18 | Arguments: 19 | model (nn.Module): model to attack. 20 | eps (float): strength of the attack or maximum perturbation. (DEFALUT : 16(max 255)) 21 | alpha (float): step size. (DEFALUT : 1(max 255)) 22 | steps (int): number of steps. (DEFALUT : 30) 23 | random_start (bool): using random initialization of delta. (DEFAULT : False) 24 | targeted (bool): using targeted attack with input labels as targeted labels. (DEFAULT : False) 25 | 26 | Shape: 27 | - images: :math:`(N, C, H, W)` where `N = number of batches`, `C = number of channels`, `H = height` and `W = width`. It must have a range [0, 1]. 28 | - labels: :math:`(N)` where each value :math:`y_i` is :math:`0 \leq y_i \leq` `number of labels`. 29 | - output: :math:`(N, C, H, W)`. 30 | 31 | Examples:: 32 | >>> attack = torchattacks.BPDAPGD(model, eps = 4, alpha = 1, steps=40, random_start=False) 33 | >>> adv_images = attack(images, labels) 34 | 35 | """ 36 | def __init__(self, model, logger, config, eps=16.0, alpha=1.0, steps=30, eot_iter=1): 37 | super(BPDAPGD, self).__init__("BPDAPGD", model, logger, config) 38 | self.eps = eps / 255.0 39 | self.alpha = alpha / 255.0 40 | self.steps = steps 41 | self.eot_iter = eot_iter 42 | self.loss = nn.CrossEntropyLoss() 43 | 44 | logger.info('Create Attacker BPDAPGD with eps: {}, alpha: {}, steps: {}, eot: {}'.format(eps, alpha, steps, eot_iter)) 45 | 46 | def forward(self, images, labels, random_start=False, targeted=False): 47 | """ 48 | Overridden. 49 | """ 50 | if targeted: 51 | self.sign = -1 52 | else: 53 | self.sign = 1 54 | 55 | images, labels = images.cuda(), labels.cuda() 56 | 57 | org_images = images.detach() 58 | adv_images = images.clone().detach() 59 | 60 | if random_start: 61 | # Starting at a uniformly random point 62 | adv_images = adv_images + torch.empty_like(adv_images).uniform_(-self.eps, self.eps) 63 | adv_images = torch.clamp(adv_images, min=0, max=1) 64 | 65 | for _ in range(self.steps): 66 | adv_images = adv_images.detach() 67 | adv_images.requires_grad = True 68 | 69 | # apply EOT to the attacker 70 | eot_grads = [] 71 | # EOT is applied when eot_iter > 1 72 | for _ in range(self.eot_iter): 73 | if adv_images.grad: 74 | adv_images.grad.zero_() 75 | outputs = self.model(adv_images, bpda=True) 76 | if isinstance(outputs, tuple): 77 | outputs = outputs[0] 78 | cost = self.sign * self.loss(outputs, labels) 79 | grad = torch.autograd.grad(cost, adv_images, create_graph=True)[0] 80 | eot_grads.append(grad.detach().clone()) 81 | grad = sum(eot_grads) / self.eot_iter 82 | 83 | # adv image update, image is NOT normalized 84 | adv_images = self.adv_image_update(adv_images, org_images, grad) 85 | 86 | return adv_images 87 | 88 | def adv_image_update(self, adv_images, org_images, grad): 89 | # image is NOT normalized 90 | adv_images = adv_images.detach() + self.alpha * grad.sign() 91 | delta = torch.clamp(adv_images - org_images, min=-self.eps, max=self.eps) 92 | adv_images = torch.clamp(org_images + delta, min=0, max=1) 93 | return adv_images.detach() 94 | 95 | -------------------------------------------------------------------------------- /data/dt_cifar.py: -------------------------------------------------------------------------------- 1 | import os 2 | import json 3 | 4 | import torch 5 | import torch.utils.data as data 6 | import torchvision 7 | import torchvision.transforms as transforms 8 | import numpy as np 9 | from PIL import Image 10 | 11 | from randaugment import RandAugment 12 | 13 | class CIFAR10Data(torchvision.datasets.CIFAR10): 14 | def __init__(self, phase, data_path, output_path, rand_aug, logger): 15 | if not os.path.exists(data_path): 16 | os.mkdir(data_path) 17 | train = True if phase == 'train' else False 18 | super(CIFAR10Data, self).__init__(data_path, train, transform=None, target_transform=None, download=True) 19 | valid_phase = ['train', 'val', 'test'] 20 | assert phase in valid_phase 21 | self.rand_aug = rand_aug 22 | 23 | self.dataset_info = {} 24 | self.phase = phase 25 | self.transform = self.get_data_transform(phase) 26 | 27 | # get dataset info 28 | self.get_dataset_info() 29 | # save dataset info 30 | logger.info('=====> Save dataset info') 31 | self.save_dataset_info(output_path) 32 | 33 | 34 | def __len__(self): 35 | return len(self.targets) 36 | 37 | 38 | def __getitem__(self, index): 39 | img, label = self.data[index], self.targets[index] 40 | 41 | # doing this so that it is consistent with all other datasets 42 | # to return a PIL Image 43 | img = Image.fromarray(img) 44 | 45 | if self.transform is not None: 46 | img = self.transform(img) 47 | 48 | return img, label, index 49 | 50 | 51 | ####################################### 52 | # get dataset info 53 | ####################################### 54 | def get_dataset_info(self): 55 | self.id2class = {i:_class for i, _class in enumerate(self.classes)} 56 | self.dataset_info['id2class'] = self.id2class 57 | 58 | 59 | ####################################### 60 | # Save dataset info 61 | ####################################### 62 | def save_dataset_info(self, output_path): 63 | 64 | with open(os.path.join(output_path, 'dataset_info_{}.json'.format(self.phase)), 'w') as f: 65 | json.dump(self.dataset_info, f) 66 | 67 | del self.dataset_info 68 | 69 | 70 | ####################################### 71 | # transform 72 | ####################################### 73 | def get_data_transform(self, phase): 74 | transform_info = {} 75 | 76 | if phase == 'train': 77 | if self.rand_aug: 78 | base_trans = [transforms.RandomCrop(32, padding=4, padding_mode='reflect'), 79 | RandAugment(), 80 | transforms.RandomHorizontalFlip(), 81 | transforms.ToTensor(),] 82 | transform_info['operations'] = ['transforms.RandomCrop(32, padding=4, padding_mode=reflect)', 'RandAugment()', 'RandomHorizontalFlip()', 'ToTensor()'] 83 | else: 84 | base_trans = [transforms.RandomCrop(32, padding=4, padding_mode='reflect'), 85 | transforms.RandomHorizontalFlip(), 86 | transforms.ToTensor(),] 87 | transform_info['operations'] = ['transforms.RandomCrop(32, padding=4, padding_mode=reflect)', 'RandomHorizontalFlip()', 'ToTensor()'] 88 | trans = transforms.Compose(base_trans) 89 | 90 | else: 91 | base_trans = [transforms.ToTensor(),] 92 | transform_info['operations'] = ['ToTensor()'] 93 | trans = transforms.Compose(base_trans) 94 | 95 | # save dataset info 96 | self.dataset_info['transform_info'] = transform_info 97 | 98 | return trans 99 | 100 | 101 | 102 | class CIFAR100Data(CIFAR10Data): 103 | """`CIFAR100 `_ Dataset. 104 | This is a subclass of the `CIFAR10` Dataset. 105 | """ 106 | cls_num = 100 107 | base_folder = 'cifar-100-python' 108 | url = "https://www.cs.toronto.edu/~kriz/cifar-100-python.tar.gz" 109 | filename = "cifar-100-python.tar.gz" 110 | tgz_md5 = 'eb9058c3a382ffc7106e4002c42a8d85' 111 | train_list = [ 112 | ['train', '16019d7e3df5f24257cddd939b257f8d'], 113 | ] 114 | 115 | test_list = [ 116 | ['test', 'f0ef6b0ae62326f3e7ffdfab6717acfc'], 117 | ] 118 | meta = { 119 | 'filename': 'meta', 120 | 'key': 'fine_label_names', 121 | 'md5': '7973b15100ade9c7d40fb424638fde48', 122 | } -------------------------------------------------------------------------------- /test_ciiv.py: -------------------------------------------------------------------------------- 1 | import torch 2 | import torch.nn as nn 3 | import torch.nn.functional as F 4 | 5 | from data.dataloader import get_loader 6 | 7 | import os 8 | import time 9 | import random 10 | import attacker 11 | 12 | from utils.attack_utils import * 13 | 14 | class test_ciiv(): 15 | def __init__(self, args, config, logger, model, val=False): 16 | self.config = config 17 | self.logger = logger 18 | self.model = model 19 | 20 | # init inst setting 21 | self.init_inst_sample() 22 | 23 | # initialize attacker 24 | self.adv_test = self.config['attacker_opt']['adv_val'] 25 | if self.adv_test: 26 | self.attacker = create_adversarial_attacker(config, model, logger) 27 | 28 | # save test 29 | self.test_save = True if config['test_opt']['save_data'] else False 30 | 31 | # get dataloader 32 | if val: 33 | self.phase = 'val' 34 | self.loader = get_loader(config, 'val', logger) 35 | else: 36 | self.phase = 'test' 37 | self.loader = get_loader(config, 'test', logger) 38 | 39 | def init_inst_sample(self): 40 | self.logger.info('=====> Init Instrumental Sampling') 41 | self.w_ce = self.config['inst_sample']['w_ce'] 42 | self.w_reg = self.config['inst_sample']['w_reg'] 43 | self.mul_ru = self.config['inst_sample']['mul_ru'] 44 | self.num_loop = self.config['inst_sample']['num_loop'] 45 | 46 | 47 | def run_val(self, epoch): 48 | self.logger.info('------------- Start Validation at Epoch {} -----------'.format(epoch)) 49 | total_acc = [] 50 | 51 | # set model to evaluation 52 | self.model.eval() 53 | 54 | # save test 55 | if self.test_save: 56 | org_list = [] 57 | adv_list = [] 58 | gt_list = [] 59 | pred_list = [] 60 | 61 | # run batch 62 | for i, (inputs, labels, indexes) in enumerate(self.loader): 63 | inputs, labels = inputs.cuda(), labels.cuda() 64 | batch_size = inputs.shape[0] 65 | # print test time 66 | # trigger adversarial attack or not 67 | if self.adv_test: 68 | if self.config['targeted_attack']: 69 | adv_targets = get_adv_target(self.config['targeted_type'], self.model, inputs, labels) 70 | adv_inputs = self.attacker.get_adv_images(inputs, adv_targets, random_start=rand_adv_init(self.config), targeted=True) 71 | else: 72 | adv_inputs = self.attacker.get_adv_images(inputs, labels, random_start=rand_adv_init(self.config)) 73 | self.model.eval() 74 | final_inputs = adv_inputs 75 | else: 76 | final_inputs = inputs 77 | 78 | # run model 79 | with torch.no_grad(): 80 | predictions = self.model(final_inputs, loop=self.num_loop) 81 | 82 | if isinstance(predictions, tuple): 83 | predictions = predictions[0] 84 | 85 | total_acc.append((predictions.max(1)[1] == labels).view(-1, 1)) 86 | 87 | # save adversarial images 88 | if self.test_save and i < self.config['test_opt']['save_length']: 89 | org_list.append(inputs.cpu()) 90 | gt_list.append(labels.cpu()) 91 | pred_list.append(predictions.max(1)[1].cpu()) 92 | if self.adv_test: 93 | adv_list.append(adv_inputs.cpu()) 94 | 95 | all_acc = torch.cat(total_acc, dim=0).float() 96 | avg_acc = all_acc.mean().item() 97 | self.logger.info('Epoch {:5d} Evaluation Complete ==> Total Accuracy : {:9.4f}, Number Samples : {:9d}'.format(epoch, avg_acc, all_acc.shape[0])) 98 | 99 | # set back to training mode again 100 | self.model.train() 101 | 102 | # save adversarial images 103 | if self.test_save: 104 | file_name = os.path.join(self.config['output_dir'], self.config['test_opt']['file_name']) 105 | adv_output = { 106 | 'org_images' : torch.cat(org_list, 0), 107 | 'gt_labels' : torch.cat(gt_list, 0), 108 | 'adv_images' : torch.cat(adv_list, 0) if self.adv_test else 0, 109 | 'pred_labels': torch.cat(pred_list, 0), 110 | } 111 | torch.save(adv_output, file_name) 112 | self.logger.info('=====> Complete! Adversarial images have been saved to {}'.format(file_name)) 113 | 114 | return avg_acc -------------------------------------------------------------------------------- /attacker/attacks/pgdl2.py: -------------------------------------------------------------------------------- 1 | ############################################################################## 2 | # Modified from https://github.com/Harry24k/adversarial-attacks-pytorch 3 | ############################################################################## 4 | 5 | import torch 6 | import torch.nn as nn 7 | 8 | from ..attacker import Attacker 9 | import utils.general_utils as utils 10 | 11 | class PGDL2(Attacker): 12 | r""" 13 | PGD in the paper 'Towards Deep Learning Models Resistant to Adversarial Attacks' 14 | [https://arxiv.org/abs/1706.06083] 15 | 16 | Distance Measure : L2 17 | Arguments: 18 | model (nn.Module): model to attack. 19 | eps (float): maximum perturbation. (DEFALUT: 1.0) 20 | alpha (float): step size. (DEFALUT: 0.2) 21 | steps (int): number of steps. (DEFALUT: 40) 22 | random_start (bool): using random initialization of delta. (DEFAULT: False) 23 | 24 | Shape: 25 | - images: :math:`(N, C, H, W)` where `N = number of batches`, `C = number of channels`, `H = height` and `W = width`. It must have a range [0, 1]. 26 | - labels: :math:`(N)` where each value :math:`y_i` is :math:`0 \leq y_i \leq` `number of labels`. 27 | - output: :math:`(N, C, H, W)`. 28 | 29 | Examples:: 30 | >>> attack = torchattacks.PGDL2(model, eps=1.0, alpha=0.2, steps=40, random_start=False) 31 | >>> adv_images = attack(images, labels) 32 | 33 | """ 34 | def __init__(self, model, logger, config, eps=16.0, alpha=1.0, steps=30, eot_iter=1, eps_for_division=1e-10): 35 | super(PGDL2, self).__init__("PGDL2", model, logger, config) 36 | self.eps = eps / 255.0 37 | self.alpha = alpha / 255.0 38 | self.steps = steps 39 | self.eot_iter = eot_iter 40 | self.loss = nn.CrossEntropyLoss() 41 | self.eps_for_division = eps_for_division 42 | 43 | logger.info('Create Attacker PGD-L2 with eps: {}, alpha: {}, steps: {}, eot: {}'.format(eps, alpha, steps, eot_iter)) 44 | 45 | def forward(self, images, labels, random_start=False, targeted=False): 46 | """ 47 | Overridden. 48 | """ 49 | if targeted: 50 | self.sign = -1 51 | else: 52 | self.sign = 1 53 | 54 | images, labels = images.cuda(), labels.cuda() 55 | batch_size = images.shape[0] 56 | 57 | org_images = images.detach() 58 | adv_images = images.clone().detach() 59 | 60 | if random_start: 61 | # Starting at a uniformly random point 62 | delta = torch.zeros_like(adv_images).to(adv_images.device) 63 | d_flat = delta.view(delta.size(0),-1) 64 | n = d_flat.norm(p=2,dim=1).view(delta.size(0),1,1,1) 65 | r = torch.zeros_like(n).uniform_(0, 1) 66 | delta = delta / n * r * self.eps 67 | adv_images = adv_images + delta 68 | adv_images = torch.clamp(adv_images, min=0, max=1) 69 | 70 | for _ in range(self.steps): 71 | adv_images = adv_images.detach() 72 | adv_images.requires_grad = True 73 | 74 | # apply EOT to the attacker 75 | eot_grads = [] 76 | # EOT is applied when eot_iter > 1 77 | for _ in range(self.eot_iter): 78 | if adv_images.grad: 79 | adv_images.grad.zero_() 80 | outputs = self.model(adv_images) 81 | if isinstance(outputs, tuple): 82 | outputs = outputs[0] 83 | cost = self.sign * self.loss(outputs, labels) 84 | grad = torch.autograd.grad(cost, adv_images, create_graph=True)[0] 85 | eot_grads.append(grad.detach().clone()) 86 | grad = sum(eot_grads) / self.eot_iter 87 | 88 | grad_norms = torch.norm(grad.view(batch_size, -1), p=2, dim=1) + self.eps_for_division 89 | grad = grad / grad_norms.view(batch_size, 1, 1, 1) 90 | 91 | # adv image update, image is NOT normalized 92 | adv_images = self.adv_image_update(adv_images, org_images, grad, batch_size) 93 | 94 | return adv_images 95 | 96 | def adv_image_update(self, adv_images, org_images, grad, batch_size): 97 | delta = adv_images - org_images 98 | g_norm = torch.norm(grad.view(grad.shape[0],-1),dim=1).view(-1,1,1,1) 99 | scaled_g = grad/(g_norm + 1e-10) 100 | delta = (delta + scaled_g*self.alpha).view(delta.size(0),-1).renorm(p=2,dim=0,maxnorm=self.eps).view_as(delta) 101 | adv_images = torch.clamp(org_images + delta, min=0, max=1).detach() 102 | return adv_images.detach() 103 | 104 | -------------------------------------------------------------------------------- /old_file/old_model/VGG_RS.py: -------------------------------------------------------------------------------- 1 | import torch 2 | import torch.nn as nn 3 | import torch.nn.functional as F 4 | import torchvision.models as models 5 | 6 | from models.Base_Model import Base_Model 7 | 8 | class VGG(Base_Model): 9 | def __init__(self, features, num_classes=1000, init_weights=True, num_trial=10, sigma=0.25): 10 | super(VGG, self).__init__() 11 | self.num_trial = num_trial 12 | self.sigma = sigma 13 | self.num_classes = num_classes 14 | self.features = features 15 | self.avgpool = nn.AdaptiveAvgPool2d((7, 7)) 16 | self.classifier = nn.Sequential( 17 | nn.Linear(512 * 7 * 7, 4096), 18 | nn.ReLU(True), 19 | nn.Dropout(), 20 | nn.Linear(4096, 4096), 21 | nn.ReLU(True), 22 | nn.Dropout(), 23 | nn.Linear(4096, num_classes), 24 | ) 25 | if init_weights: 26 | self._initialize_weights() 27 | 28 | def forward(self, x, bpda=False): 29 | if x.shape[1] == 1: 30 | x = x.repeat(1, 3, 1, 1) 31 | if self.training or self.is_attack(): 32 | if not bpda: 33 | x = self.sample_noise(x) 34 | x = self.features(x) 35 | x = self.avgpool(x) 36 | x = torch.flatten(x, 1) 37 | x = self.classifier(x) 38 | return x 39 | # Randomized Smoothing Inference 40 | # original https://github.com/locuslab/smoothing/blob/master/code/core.py#L61 will return ABSTAIN if the output 41 | # doesn't pass the binom_test. However, we will always return the prediction 42 | else: 43 | counts = [] 44 | for _ in range(self.num_trial): 45 | if not bpda: 46 | x_t = self.sample_noise(x) 47 | x_t = self.features(x_t) 48 | x_t = self.avgpool(x_t) 49 | x_t = torch.flatten(x_t, 1) 50 | x_t = self.classifier(x_t) 51 | pred = x_t.max(-1)[1] 52 | counts.append(F.one_hot(pred, self.num_classes)) 53 | return sum(counts) 54 | 55 | def sample_noise(self, x): 56 | noise_x = x + self.sigma * torch.randn_like(x).to(x.device) 57 | noise_x = torch.clamp(noise_x, min=0, max=1) 58 | return noise_x 59 | 60 | def _initialize_weights(self): 61 | for m in self.modules(): 62 | if isinstance(m, nn.Conv2d): 63 | nn.init.kaiming_normal_(m.weight, mode='fan_out', nonlinearity='relu') 64 | if m.bias is not None: 65 | nn.init.constant_(m.bias, 0) 66 | elif isinstance(m, nn.BatchNorm2d): 67 | nn.init.constant_(m.weight, 1) 68 | nn.init.constant_(m.bias, 0) 69 | elif isinstance(m, nn.Linear): 70 | nn.init.normal_(m.weight, 0, 0.01) 71 | nn.init.constant_(m.bias, 0) 72 | 73 | 74 | def make_layers(cfg, batch_norm=False): 75 | layers = [] 76 | in_channels = 3 77 | for v in cfg: 78 | if v == 'M': 79 | layers += [nn.MaxPool2d(kernel_size=2, stride=2)] 80 | else: 81 | conv2d = nn.Conv2d(in_channels, v, kernel_size=3, padding=1) 82 | if batch_norm: 83 | layers += [conv2d, nn.BatchNorm2d(v), nn.ReLU(inplace=True)] 84 | else: 85 | layers += [conv2d, nn.ReLU(inplace=True)] 86 | in_channels = v 87 | return nn.Sequential(*layers) 88 | 89 | 90 | cfgs = { 91 | 'A': [64, 'M', 128, 'M', 256, 256, 'M', 512, 512, 'M', 512, 512, 'M'], 92 | 'B': [64, 64, 'M', 128, 128, 'M', 256, 256, 'M', 512, 512, 'M', 512, 512, 'M'], 93 | 'D': [64, 64, 'M', 128, 128, 'M', 256, 256, 256, 'M', 512, 512, 512, 'M', 512, 512, 512, 'M'], 94 | 'E': [64, 64, 'M', 128, 128, 'M', 256, 256, 256, 256, 'M', 512, 512, 512, 512, 'M', 512, 512, 512, 512, 'M'], 95 | } 96 | 97 | 98 | def _vgg(arch, cfg, batch_norm, **kwargs): 99 | model = VGG(make_layers(cfgs[cfg], batch_norm=batch_norm), **kwargs) 100 | return model 101 | 102 | 103 | def vgg11(**kwargs): 104 | return _vgg('vgg11', 'A', False, **kwargs) 105 | 106 | def vgg11_bn(**kwargs): 107 | return _vgg('vgg11_bn', 'A', True, **kwargs) 108 | 109 | def vgg13(**kwargs): 110 | return _vgg('vgg13', 'B', False, **kwargs) 111 | 112 | def vgg13_bn(**kwargs): 113 | return _vgg('vgg13_bn', 'B', True, **kwargs) 114 | 115 | def vgg16(**kwargs): 116 | return _vgg('vgg16', 'D', False, **kwargs) 117 | 118 | def vgg16_bn(**kwargs): 119 | return _vgg('vgg16_bn', 'D', True, **kwargs) 120 | 121 | def vgg19(**kwargs): 122 | return _vgg('vgg19', 'E', False, **kwargs) 123 | 124 | def vgg19_bn(**kwargs): 125 | return _vgg('vgg19_bn', 'E', True, **kwargs) 126 | 127 | 128 | def create_model(m_type='vgg16', num_classes=1000, first_conv_size=7, num_trial=10, sigma=0.25): 129 | # create various resnet models 130 | if m_type == 'vgg16': 131 | model = vgg16(num_classes=num_classes, num_trial=num_trial, sigma=sigma) 132 | 133 | return model -------------------------------------------------------------------------------- /config/attacker_config.yaml: -------------------------------------------------------------------------------- 1 | 2 | # attacker settings for each dataset 3 | 4 | TOYData: 5 | FGSM: 6 | setting1: {attack_eps: 128, attack_rand_ini: 1.0} 7 | PGD: 8 | setting1: {attack_eps: 128, attack_alpha: 8, attack_step: 20, attack_rand_ini: 1.0} 9 | 10 | 11 | cifar10: 12 | AutoAttack: 13 | setting1: {attack_eps: 8, attack_norm: 'Linf', attack_rand_ini: 1.0} 14 | setting2: {attack_eps: 128, attack_norm: 'L2', attack_rand_ini: 1.0} 15 | FGSM: 16 | setting1: {attack_eps: 8, attack_rand_ini: 1.0} 17 | setting2: {attack_eps: 16, attack_rand_ini: 1.0} 18 | setting3: {attack_eps: 24, attack_rand_ini: 1.0} 19 | setting4: {attack_eps: 32, attack_rand_ini: 1.0} 20 | setting5: {attack_eps: 40, attack_rand_ini: 1.0} 21 | setting6: {attack_eps: 48, attack_rand_ini: 1.0} 22 | setting7: {attack_eps: 56, attack_rand_ini: 1.0} 23 | setting8: {attack_eps: 64, attack_rand_ini: 1.0} 24 | setting9: {attack_eps: 72, attack_rand_ini: 1.0} 25 | setting10: {attack_eps: 80, attack_rand_ini: 1.0} 26 | setting11: {attack_eps: 88, attack_rand_ini: 1.0} 27 | setting12: {attack_eps: 96, attack_rand_ini: 1.0} 28 | PGD: 29 | setting1: {attack_eps: 8, attack_alpha: 2, attack_step: 10, attack_rand_ini: 1.0} 30 | setting2: {attack_eps: 8, attack_alpha: 2, attack_step: 20, attack_rand_ini: 1.0} 31 | setting3: {attack_eps: 8, attack_alpha: 2, attack_step: 30, attack_rand_ini: 1.0} 32 | setting4: {attack_eps: 8, attack_alpha: 2, attack_step: 40, attack_rand_ini: 1.0} 33 | setting5: {attack_eps: 8, attack_alpha: 2, attack_step: 50, attack_rand_ini: 1.0} 34 | setting6: {attack_eps: 8, attack_alpha: 2, attack_step: 60, attack_rand_ini: 1.0} 35 | setting7: {attack_eps: 8, attack_alpha: 2, attack_step: 70, attack_rand_ini: 1.0} 36 | setting8: {attack_eps: 8, attack_alpha: 2, attack_step: 80, attack_rand_ini: 1.0} 37 | setting9: {attack_eps: 8, attack_alpha: 2, attack_step: 90, attack_rand_ini: 1.0} 38 | setting10: {attack_eps: 8, attack_alpha: 2, attack_step: 100, attack_rand_ini: 1.0} 39 | setting20: {attack_eps: 8, attack_alpha: 2, attack_step: 200, attack_rand_ini: 1.0} 40 | 41 | #setting2: {attack_eps: 16, attack_alpha: 4, attack_step: 10, attack_rand_ini: 1.0} 42 | #setting3: {attack_eps: 24, attack_alpha: 6, attack_step: 10, attack_rand_ini: 1.0} 43 | #setting4: {attack_eps: 32, attack_alpha: 8, attack_step: 10, attack_rand_ini: 1.0} 44 | #setting5: {attack_eps: 40, attack_alpha: 10, attack_step: 10, attack_rand_ini: 1.0} 45 | #setting6: {attack_eps: 48, attack_alpha: 12, attack_step: 10, attack_rand_ini: 1.0} 46 | #setting7: {attack_eps: 56, attack_alpha: 14, attack_step: 10, attack_rand_ini: 1.0} 47 | #setting8: {attack_eps: 64, attack_alpha: 16, attack_step: 10, attack_rand_ini: 1.0} 48 | #setting9: {attack_eps: 72, attack_alpha: 18, attack_step: 10, attack_rand_ini: 1.0} 49 | #setting10: {attack_eps: 80, attack_alpha: 20, attack_step: 10, attack_rand_ini: 1.0} 50 | #setting11: {attack_eps: 88, attack_alpha: 22, attack_step: 10, attack_rand_ini: 1.0} 51 | #setting12: {attack_eps: 96, attack_alpha: 24, attack_step: 10, attack_rand_ini: 1.0} 52 | GN: 53 | setting1: {gn_sigma: 0.1, attack_eps: 16, attack_rand_ini: 0.0} 54 | UN: 55 | setting1: {un_sigma: 0.1, attack_eps: 16, attack_rand_ini: 0.0} 56 | BFS: 57 | setting1: {sigma: 0.1, attack_eps: 16, steps: 100, attack_rand_ini: 0.0} 58 | SPSA: 59 | setting1: {attack_eps: 16, delta: 0.1, batch_size: 16, steps: 20, lr: 0.1, attack_rand_ini: 1.0} 60 | 61 | 62 | cifar100: 63 | AutoAttack: 64 | setting1: {attack_eps: 8, attack_norm: 'Linf', attack_rand_ini: 1.0} 65 | setting2: {attack_eps: 128, attack_norm: 'L2', attack_rand_ini: 1.0} 66 | FGSM: 67 | setting1: {attack_eps: 8, attack_rand_ini: 1.0} 68 | PGD: 69 | setting1: {attack_eps: 8, attack_alpha: 2, attack_step: 10, attack_rand_ini: 1.0} 70 | setting2: {attack_eps: 8, attack_alpha: 2, attack_step: 20, attack_rand_ini: 1.0} 71 | GN: 72 | setting1: {gn_sigma: 0.1, attack_eps: 16, attack_rand_ini: 0.0} 73 | UN: 74 | setting1: {un_sigma: 0.1, attack_eps: 16, attack_rand_ini: 0.0} 75 | BFS: 76 | setting1: {sigma: 0.1, attack_eps: 16, steps: 100, attack_rand_ini: 0.0} 77 | SPSA: 78 | setting1: {attack_eps: 16, delta: 0.1, batch_size: 16, steps: 20, lr: 0.1, attack_rand_ini: 1.0} 79 | 80 | 81 | mini-imagenet: 82 | AutoAttack: 83 | setting1: {attack_eps: 8, attack_norm: 'Linf', attack_rand_ini: 1.0} 84 | setting2: {attack_eps: 128, attack_norm: 'L2', attack_rand_ini: 1.0} 85 | FGSM: 86 | setting1: {attack_eps: 8, attack_rand_ini: 1.0} 87 | PGD: 88 | setting1: {attack_eps: 8, attack_alpha: 2, attack_step: 10, attack_rand_ini: 1.0} 89 | setting2: {attack_eps: 8, attack_alpha: 2, attack_step: 20, attack_rand_ini: 1.0} 90 | GN: 91 | setting1: {gn_sigma: 0.1, attack_eps: 16, attack_rand_ini: 0.0} 92 | UN: 93 | setting1: {un_sigma: 0.1, attack_eps: 16, attack_rand_ini: 0.0} 94 | BFS: 95 | setting1: {sigma: 0.1, attack_eps: 16, steps: 100, attack_rand_ini: 0.0} 96 | SPSA: 97 | setting1: {attack_eps: 16, delta: 0.1, batch_size: 16, steps: 20, lr: 0.1, attack_rand_ini: 1.0} -------------------------------------------------------------------------------- /utils/general_utils.py: -------------------------------------------------------------------------------- 1 | import torch 2 | import importlib 3 | 4 | 5 | def update_attacker_info(config, attack_config, dataset_name, attacker_type, attacker_set): 6 | print('==================== Attacker {} ================='.format(attacker_type)) 7 | config['attacker_opt']['attack_type'] = attacker_type 8 | config['attacker_opt']['attack_set'] = attacker_set 9 | config['attacker_opt'].update(attack_config[dataset_name][attacker_type][attacker_set]) 10 | 11 | def RepresentsInt(s): 12 | try: 13 | int(s) 14 | return True 15 | except ValueError: 16 | return False 17 | 18 | def RepresentsFloat(s): 19 | try: 20 | float(s) 21 | return True 22 | except ValueError: 23 | return False 24 | 25 | def int_to_others(val): 26 | if val == 'true' or val == 'True': 27 | return True 28 | elif val == 'false' or val == 'False': 29 | return False 30 | elif RepresentsInt(val): 31 | return int(val) 32 | elif RepresentsFloat(val): 33 | return float(val) 34 | else: 35 | return val 36 | 37 | def update_config_key(update_dict, key, new_val): 38 | names = key.split('.') 39 | while(len(names) > 1): 40 | item_key = names.pop(0) 41 | update_dict = update_dict[item_key] 42 | old_val = update_dict[names[-1]] 43 | update_dict[names[-1]] = int_to_others(new_val) 44 | return old_val 45 | 46 | def update(config, args, logger): 47 | if args.output_dir is not None: 48 | config['output_dir'] = args.output_dir 49 | logger.info('======= Update Config: output_dir is set to : ' + str(config['output_dir'])) 50 | if args.train_type is not None: 51 | config['strategy']['train_type'] = args.train_type 52 | logger.info('======= Update Config: training type is set to: '.format(args.train_type)) 53 | if args.test_type is not None: 54 | config['strategy']['test_type'] = args.test_type 55 | logger.info('======= Update Config: test type is set to: '.format(args.test_type)) 56 | if args.adv_train: 57 | config['attacker_opt']['adv_train'] = args.adv_train 58 | if args.adv_test: 59 | config['attacker_opt']['adv_val'] = args.adv_test 60 | if args.adv_type is not None: 61 | config['attacker_opt']['attack_type'] = args.adv_type 62 | if args.adv_setting is not None: 63 | config['attacker_opt']['attack_set'] = args.adv_setting 64 | if args.rand_aug: 65 | config['dataset']['rand_aug'] = True 66 | logger.info('===================> Using Random Augmentation') 67 | 68 | if args.target_type: 69 | config['targeted_attack'] = True 70 | config['targeted_type'] = args.target_type 71 | else: 72 | config['targeted_attack'] = False 73 | 74 | # update config from command 75 | if len(args.opts) > 0 and (len(args.opts) % 2) == 0: 76 | for i in range(len(args.opts)//2): 77 | key = args.opts[2*i] 78 | val = args.opts[2*i+1] 79 | old_val = update_config_key(config, key, val) 80 | logger.info('=====> {}: {} (old key) => {} (new key)'.format(key, old_val, val)) 81 | return config 82 | 83 | def source_import(file_path): 84 | """This function imports python module directly from source code using importlib""" 85 | spec = importlib.util.spec_from_file_location('', file_path) 86 | module = importlib.util.module_from_spec(spec) 87 | spec.loader.exec_module(module) 88 | return module 89 | 90 | def print_grad(named_parameters): 91 | """ show grads """ 92 | total_norm = 0 93 | param_to_norm = {} 94 | param_to_shape = {} 95 | for n, p in named_parameters: 96 | if p.grad is not None: 97 | param_norm = p.grad.data.norm(2) 98 | total_norm += param_norm ** 2 99 | param_to_norm[n] = param_norm 100 | param_to_shape[n] = p.size() 101 | total_norm = total_norm ** (1. / 2) 102 | print('---Total norm {:.3f} -----------------'.format(total_norm)) 103 | for name, norm in sorted(param_to_norm.items(), key=lambda x: -x[1]): 104 | print("{:<50s}: {:.3f}, ({})".format(name, norm, param_to_shape[name])) 105 | print('-------------------------------', flush=True) 106 | return total_norm 107 | 108 | def print_config(config, logger, head=''): 109 | for key, val in config.items(): 110 | if isinstance(val, dict): 111 | logger.info(head + str(key)) 112 | print_config(val, logger, head=head + ' ') 113 | else: 114 | logger.info(head + '{} : {}'.format(str(key), str(val))) 115 | 116 | class TriggerAction(): 117 | def __init__(self, name): 118 | self.name = name 119 | self.action = {} 120 | 121 | def add_action(self, name, func): 122 | assert str(name) not in self.action 123 | self.action[str(name)] = func 124 | 125 | def remove_action(self, name): 126 | assert str(name) in self.action 127 | del self.action[str(name)] 128 | assert str(name) not in self.action 129 | 130 | def run_all(self, logger=None): 131 | for key, func in self.action.items(): 132 | if logger: 133 | logger.info('trigger {}'.format(key)) 134 | func() -------------------------------------------------------------------------------- /train_baseline.py: -------------------------------------------------------------------------------- 1 | import torch 2 | import torch.nn as nn 3 | import torch.optim as optim 4 | import torch.optim.lr_scheduler as lr_scheduler 5 | import torch.nn.functional as F 6 | 7 | import utils.general_utils as utils 8 | from data.dataloader import get_loader 9 | from utils.checkpoint_utils import Checkpoint 10 | 11 | import time 12 | import math 13 | import random 14 | import attacker 15 | import numpy as np 16 | 17 | from utils.attack_utils import * 18 | from utils.train_utils import * 19 | from utils.test_utils import * 20 | 21 | 22 | class train_baseline(): 23 | def __init__(self, args, config, logger, model, eval=False): 24 | self.config = config 25 | self.logger = logger 26 | self.model = model 27 | self.training_opt = config['training_opt'] 28 | self.checkpoint = Checkpoint(config) 29 | self.logger.info('============= Training Strategy: Baseline Training ============') 30 | 31 | # get dataloader 32 | self.logger.info('=====> Get train dataloader') 33 | self.train_loader = get_loader(config, 'train', logger) 34 | 35 | # create optimizer 36 | self.create_optimizer() 37 | 38 | # create scheduler 39 | self.create_scheduler() 40 | 41 | # adversarial train 42 | self.adv_train = self.config['attacker_opt']['adv_train'] 43 | if self.adv_train: 44 | self.attacker = create_adversarial_attacker(config, model, logger) 45 | 46 | # set eval 47 | if eval: 48 | # choosing test strategy 49 | test_func = get_test_func(config) 50 | # start testing 51 | self.testing = test_func(args, config, logger, model, val=True) 52 | 53 | 54 | def create_optimizer(self): 55 | self.logger.info('=====> Create optimizer') 56 | optim_params = self.training_opt['optim_params'] 57 | optim_params_dict = {'params': self.model.parameters(), 58 | 'lr': optim_params['lr'], 59 | 'momentum': optim_params['momentum'], 60 | 'weight_decay': optim_params['weight_decay'] 61 | } 62 | 63 | if self.training_opt['optimizer'] == 'Adam': 64 | self.optimizer = optim.Adam([optim_params_dict, ]) 65 | elif self.training_opt['optimizer'] == 'SGD': 66 | self.optimizer = optim.SGD([optim_params_dict, ]) 67 | else: 68 | self.logger.info('********** ERROR: unidentified optimizer **********') 69 | 70 | 71 | def create_scheduler(self): 72 | self.logger.info('=====> Create Scheduler') 73 | scheduler_params = self.training_opt['scheduler_params'] 74 | if self.training_opt['scheduler'] == 'cosine': 75 | self.scheduler = optim.lr_scheduler.CosineAnnealingLR(self.optimizer, self.training_opt['num_epochs'], eta_min=scheduler_params['endlr']) 76 | elif self.training_opt['scheduler'] == 'step': 77 | self.scheduler = optim.lr_scheduler.MultiStepLR(self.optimizer, gamma=scheduler_params['gamma'], milestones=scheduler_params['milestones']) 78 | else: 79 | self.logger.info('********** ERROR: unidentified optimizer **********') 80 | 81 | 82 | def run(self): 83 | # Start Training 84 | self.logger.info('=====> Start Naive Training') 85 | 86 | # run epoch 87 | for epoch in range(self.training_opt['num_epochs']): 88 | self.logger.info('------------ Start Epoch {} -----------'.format(epoch)) 89 | self.model.train() 90 | 91 | # run batch 92 | total_batch = len(self.train_loader) 93 | for step, (inputs, labels, indexes) in enumerate(self.train_loader): 94 | # naive training 95 | inputs, labels = inputs.cuda(), labels.cuda() 96 | if self.adv_train: 97 | final_inputs = self.attacker.get_adv_images(inputs, labels) 98 | else: 99 | final_inputs = inputs 100 | 101 | preds = self.model(final_inputs) 102 | loss = F.cross_entropy(preds, labels) 103 | iter_info_print = {'ce_loss' : loss.sum().item(),} 104 | # backward 105 | self.optimizer.zero_grad() 106 | loss.backward() 107 | self.optimizer.step() 108 | # calculate accuracy 109 | accuracy = (preds.max(1)[1] == labels).sum().float() / preds.shape[0] 110 | 111 | # log information 112 | iter_info_print.update( {'Accuracy' : accuracy.item(), 'Loss' : loss.sum().item(), 'Poke LR' : float(self.optimizer.param_groups[0]['lr'])} ) 113 | self.logger.info_iter(epoch, step, total_batch, iter_info_print, self.config['logger_opt']['print_iter']) 114 | if self.config['logger_opt']['print_grad'] and step % 1000 == 0: 115 | utils.print_grad(self.model.named_parameters()) 116 | 117 | # evaluation on validation set 118 | self.optimizer.zero_grad() 119 | val_acc = self.testing.run_val(epoch) 120 | # checkpoint 121 | self.checkpoint.save(self.model, epoch, self.logger, acc=val_acc) 122 | # update scheduler 123 | self.scheduler.step() 124 | # save best model path 125 | self.checkpoint.save_best_model(self.logger) 126 | 127 | -------------------------------------------------------------------------------- /attacker/attacks/cw.py: -------------------------------------------------------------------------------- 1 | ############################################################################## 2 | # Modified from https://github.com/Harry24k/adversarial-attacks-pytorch 3 | ############################################################################## 4 | 5 | import torch 6 | import torch.nn as nn 7 | import torch.optim as optim 8 | 9 | from ..attacker import Attacker 10 | import utils.general_utils as utils 11 | 12 | class CW(Attacker): 13 | r""" 14 | CW in the paper 'Towards Evaluating the Robustness of Neural Networks' 15 | [https://arxiv.org/abs/1608.04644] 16 | Distance Measure : L2 17 | 18 | Arguments: 19 | model (nn.Module): model to attack. 20 | c (float): c in the paper. parameter for box-constraint. (DEFALUT: 1e-4) 21 | :math:`minimize \Vert\frac{1}{2}(tanh(w)+1)-x\Vert^2_2+c\cdot f(\frac{1}{2}(tanh(w)+1))` 22 | kappa (float): kappa (also written as 'confidence') in the paper. (DEFALUT: 0) 23 | :math:`f(x')=max(max\{Z(x')_i:i\neq t\} -Z(x')_t, - \kappa)` 24 | steps (int): number of steps. (DEFALUT: 1000) 25 | lr (float): learning rate of the Adam optimizer. (DEFALUT: 0.01) 26 | 27 | .. warning:: With default c, you can't easily get adversarial images. Set higher c like 1. 28 | 29 | Shape: 30 | - images: :math:`(N, C, H, W)` where `N = number of batches`, `C = number of channels`, `H = height` and `W = width`. It must have a range [0, 1]. 31 | - labels: :math:`(N)` where each value :math:`y_i` is :math:`0 \leq y_i \leq` `number of labels`. 32 | - output: :math:`(N, C, H, W)`. 33 | 34 | Examples:: 35 | >>> attack = torchattacks.CW(model, c=1e-4, kappa=0, steps=1000, lr=0.01) 36 | >>> adv_images = attack(images, labels) 37 | 38 | .. note:: NOT IMPLEMENTED methods in the paper due to time consuming. 39 | 40 | (1) Binary search for c. 41 | """ 42 | def __init__(self, model, logger, config, c=1e-4, kappa=0, steps=1000, lr=0.01): 43 | super(CW, self).__init__("CW", model, logger, config) 44 | self.c = c 45 | self.kappa = kappa 46 | self.steps = steps 47 | self.lr = lr 48 | 49 | logger.info('Create Attacker CW with c: {}, kappa: {}, steps: {}, lr: {}'.format(c, kappa, steps, lr)) 50 | 51 | def forward(self, images, labels, random_start=False, targeted=False): 52 | r""" 53 | Overridden. 54 | """ 55 | if targeted: 56 | self.sign = -1 57 | else: 58 | self.sign = 1 59 | 60 | images, labels = images.cuda(), labels.cuda() 61 | 62 | # w = torch.zeros_like(images).detach() # Requires 2x times 63 | w = self.inverse_tanh_space(images).detach() 64 | w.requires_grad = True 65 | 66 | best_adv_images = images.clone().detach() 67 | best_L2 = 1e10*torch.ones((len(images))).to(images.device) 68 | prev_cost = 1e10 69 | dim = len(images.shape) 70 | 71 | MSELoss = nn.MSELoss(reduction='none') 72 | Flatten = nn.Flatten() 73 | 74 | optimizer = optim.Adam([w], lr=self.lr) 75 | 76 | for step in range(self.steps): 77 | # Get Adversarial Images 78 | adv_images = self.tanh_space(w) 79 | 80 | current_L2 = MSELoss(Flatten(adv_images), 81 | Flatten(images)).sum(dim=1) 82 | L2_loss = current_L2.sum() 83 | 84 | outputs = self.model(adv_images) 85 | if isinstance(outputs, tuple): 86 | outputs = outputs[0] 87 | f_Loss = self.f(outputs, labels).sum() 88 | 89 | cost = L2_loss + self.c*f_Loss 90 | 91 | optimizer.zero_grad() 92 | cost.backward() 93 | optimizer.step() 94 | 95 | # Update Adversarial Images 96 | _, pre = torch.max(outputs.detach(), 1) 97 | correct = (pre == labels).float() 98 | 99 | mask = (1-correct)*(best_L2 > current_L2.detach()) 100 | best_L2 = mask*current_L2.detach() + (1-mask)*best_L2 101 | 102 | mask = mask.view([-1]+[1]*(dim-1)) 103 | best_adv_images = mask*adv_images.detach() + (1-mask)*best_adv_images 104 | 105 | # Early Stop when loss does not converge. 106 | if step % (self.steps//10) == 0: 107 | if cost.item() > prev_cost: 108 | return best_adv_images 109 | prev_cost = cost.item() 110 | 111 | return best_adv_images 112 | 113 | def tanh_space(self, x): 114 | return 1/2*(torch.tanh(x) + 1) 115 | 116 | def inverse_tanh_space(self, x): 117 | # torch.atanh is only for torch >= 1.7.0 118 | return self.atanh(x*2-1) 119 | 120 | def atanh(self, x): 121 | return 0.5*torch.log((1+x)/(1-x+1e-9)) 122 | 123 | # f-function in the paper 124 | def f(self, outputs, labels): 125 | one_hot_labels = torch.eye(len(outputs[0]))[labels].to(outputs.device) 126 | 127 | i, _ = torch.max((1-one_hot_labels)*outputs, dim=1) 128 | j = torch.masked_select(outputs, one_hot_labels.bool()) 129 | 130 | return torch.clamp(self.sign*(j-i), min=-self.kappa) 131 | -------------------------------------------------------------------------------- /main.py: -------------------------------------------------------------------------------- 1 | import json 2 | import yaml 3 | import os 4 | import argparse 5 | import torch 6 | import torch.nn as nn 7 | import random 8 | import utils.general_utils as utils 9 | from utils.logger_utils import custom_logger 10 | from data.dataloader import get_loader 11 | from utils.checkpoint_utils import Checkpoint 12 | 13 | from utils.train_utils import * 14 | from utils.test_utils import * 15 | 16 | # ============================================================================ 17 | # argument parser 18 | parser = argparse.ArgumentParser() 19 | parser.add_argument('--cfg', default=None, type=str, help='Indicate the config file used for the training.') 20 | parser.add_argument('--seed', default=25, type=int, help='Fix the random seed for reproduction. Default is 25.') 21 | parser.add_argument('--phase', default='train', type=str, help='Indicate train/val/test/val_all phase.') 22 | parser.add_argument('--output_dir', default=None, type=str, help='Output directory that saves everything.') 23 | parser.add_argument('--load_dir', default=None, type=str, help='Load model from this directory for testing') 24 | parser.add_argument('--require_eval', action='store_true', help='Require evaluation on val set during training.') 25 | parser.add_argument('--logger_name', default='logger_eval', type=str, help='Name of TXT output for the logger.') 26 | parser.add_argument("opts", help="Modify config options using the command-line", default=None, nargs=argparse.REMAINDER,) 27 | # ============================================================================ 28 | # other important parameters 29 | parser.add_argument('--train_type', default=None, type=str, help='Type of training strategy.') 30 | parser.add_argument('--test_type', default=None, type=str, help='Type of test strategy.') 31 | parser.add_argument('--adv_train', action='store_true', help='Adversarial Training.') 32 | parser.add_argument('--adv_test', action='store_true', help='Adversarial Attacked Testing.') 33 | parser.add_argument('--adv_type', default=None, type=str, help='Adversarial Attack Type.') 34 | parser.add_argument('--adv_setting', default=None, type=str, help='Adversarial Attack Setting.') 35 | parser.add_argument('--rand_aug', action='store_true', help='Use Random Augmentation.') 36 | parser.add_argument('--target_type', default=None, type=str, help='The using of targeted attack and types. random / most (likely) / least (likely)') 37 | 38 | args = parser.parse_args() 39 | 40 | # ============================================================================ 41 | # init logger 42 | if args.output_dir is None: 43 | print('Please specify output directory') 44 | if not os.path.exists(args.output_dir): 45 | os.mkdir(args.output_dir) 46 | if args.phase != 'train': 47 | logger = custom_logger(args.output_dir, name='{}.txt'.format(args.logger_name)) 48 | else: 49 | logger = custom_logger(args.output_dir) 50 | logger.info('========================= Start Main =========================') 51 | 52 | 53 | # ============================================================================ 54 | # fix random seed 55 | logger.info('=====> Using fixed random seed: ' + str(args.seed)) 56 | random.seed(args.seed) 57 | torch.manual_seed(args.seed) 58 | torch.cuda.manual_seed(args.seed) 59 | torch.cuda.manual_seed_all(args.seed) 60 | 61 | 62 | # ============================================================================ 63 | # load config 64 | logger.info('=====> Load config from yaml: ' + str(args.cfg)) 65 | with open(args.cfg) as f: 66 | config = yaml.load(f) 67 | 68 | # load attacker config 69 | logger.info('=====> Load attacker config from yaml: config/attacker_config.yaml') 70 | with open('config/attacker_config.yaml') as f: 71 | attack_config = yaml.load(f) 72 | 73 | # merge second for details attack settings 74 | logger.info('=====> Merge arguments from command') 75 | config = utils.update(config, args, logger) 76 | 77 | # change attack type 78 | dataset_name = config['dataset']['name'] 79 | attacker_type = config['attacker_opt']['attack_type'] 80 | attacker_set = config['attacker_opt']['attack_set'] 81 | utils.update_attacker_info(config, attack_config, dataset_name, attacker_type, attacker_set) 82 | 83 | # save config file 84 | logger.info('=====> Save config as config.json') 85 | with open(os.path.join(args.output_dir, 'config.json'), 'w') as f: 86 | json.dump(config, f) 87 | utils.print_config(config, logger) 88 | 89 | # ============================================================================ 90 | # create model 91 | logger.info('=====> Model construction from: ' + str(config['networks']['def_file'])) 92 | model_file = config['networks']['def_file'] 93 | model_args = config['networks']['params'] 94 | model = utils.source_import(model_file).create_model(**model_args) 95 | model.config = config 96 | model = nn.DataParallel(model).cuda() 97 | 98 | # ============================================================================ 99 | # training 100 | if args.phase == 'train': 101 | training_func = get_train_func(config) 102 | # start training 103 | training = training_func(args, config, logger, model, eval=args.require_eval) 104 | training.run() 105 | # normal test 106 | else: 107 | checkpoint = Checkpoint(config) 108 | checkpoint.load(model, args.load_dir, logger) 109 | # start testing 110 | test_func = get_test_func(config) 111 | if args.phase == 'val': 112 | testing = test_func(args, config, logger, model, val=True) 113 | testing.run_val(epoch=-1) 114 | elif args.phase == 'test': 115 | testing = test_func(args, config, logger, model, val=False) 116 | testing.run_val(epoch=-1) 117 | else: 118 | raise ValueError('Wrong Phase') 119 | 120 | logger.info('========================= Complete =========================') 121 | -------------------------------------------------------------------------------- /data/dt_mini_imagenet.py: -------------------------------------------------------------------------------- 1 | import os 2 | import json 3 | 4 | import torch 5 | import torch.utils.data as data 6 | import torchvision.transforms as transforms 7 | import numpy as np 8 | import pandas as pd 9 | from PIL import Image 10 | 11 | from randaugment import RandAugment 12 | 13 | class miniImageNetData(data.Dataset): 14 | def __init__(self, phase, data_path, category_path, train_path, test_path, val_path, output_path, num_classes, rand_aug, logger): 15 | super(miniImageNetData, self).__init__() 16 | valid_phase = ['train', 'val', 'test'] 17 | assert phase in valid_phase 18 | 19 | self.num_classes = num_classes 20 | self.dataset_info = {} 21 | self.phase = phase 22 | self.data_path = data_path 23 | self.train_path = train_path 24 | self.test_path = test_path 25 | self.val_path = val_path 26 | self.rand_aug = rand_aug 27 | 28 | self.transform = self.get_data_transform(phase) 29 | 30 | # load dataset category info 31 | logger.info('=====> Load dataset category info') 32 | self.id2label, self.label2id = self.load_data_info(category_path) 33 | 34 | # load all image info 35 | if phase == 'train': 36 | logger.info('=====> Load train image info') 37 | self.img_paths, self.labels = self.load_img_info(self.train_path) 38 | elif phase == 'val': 39 | logger.info('=====> Load val image info') 40 | self.img_paths, self.labels = self.load_img_info(self.val_path) 41 | else: 42 | logger.info('=====> Load test image info') 43 | self.img_paths, self.labels = self.load_img_info(self.test_path) 44 | 45 | # save dataset info 46 | logger.info('=====> Save dataset info') 47 | self.save_dataset_info(output_path) 48 | 49 | 50 | def __len__(self): 51 | return len(self.labels) 52 | 53 | 54 | def __getitem__(self, index): 55 | path = self.img_paths[index] 56 | label = self.labels[index] 57 | 58 | with open(path, 'rb') as f: 59 | sample = Image.open(f).convert('RGB') 60 | 61 | if self.transform is not None: 62 | sample = self.transform(sample) 63 | 64 | return sample, label, index 65 | 66 | 67 | ####################################### 68 | # Load image info 69 | ####################################### 70 | def load_img_info(self, path): 71 | data_file = pd.read_csv(path).values 72 | 73 | labels = [] 74 | img_paths = [] 75 | 76 | for item in data_file: 77 | name = item[1] 78 | label = self.label2id[item[2]] 79 | img_path = os.path.join(self.data_path, name) 80 | labels.append(label) 81 | img_paths.append(img_path) 82 | 83 | # save dataset info 84 | self.dataset_info['labels'] = labels 85 | self.dataset_info['img_paths'] = img_paths 86 | 87 | return img_paths, labels 88 | 89 | 90 | ####################################### 91 | # Load dataset category info 92 | ####################################### 93 | def load_data_info(self, path): 94 | id2label = {} # id to label, e.g., n02119789 95 | label2id = {} 96 | 97 | category_list = pd.read_csv(path).values 98 | 99 | for item in category_list: 100 | id = int(item[0]) 101 | label = str(item[1]) 102 | id2label[id] = label 103 | label2id[label] = id 104 | 105 | # save dataset info 106 | self.dataset_info['id2label'] = id2label 107 | self.dataset_info['label2id'] = label2id 108 | assert len(id2label) == self.num_classes 109 | assert len(label2id) == self.num_classes 110 | 111 | return id2label, label2id 112 | 113 | 114 | ####################################### 115 | # Save dataset info 116 | ####################################### 117 | def save_dataset_info(self, output_path): 118 | 119 | with open(os.path.join(output_path, 'dataset_info_{}.json'.format(self.phase)), 'w') as f: 120 | json.dump(self.dataset_info, f) 121 | 122 | del self.dataset_info 123 | 124 | 125 | ####################################### 126 | # transform 127 | ####################################### 128 | def get_data_transform(self, phase): 129 | transform_info = {} 130 | 131 | if phase == 'train': 132 | if self.rand_aug: 133 | trans = transforms.Compose([ 134 | transforms.Resize(64), 135 | transforms.RandomCrop(64, padding=8, padding_mode='reflect'), 136 | RandAugment(), 137 | transforms.RandomHorizontalFlip(), 138 | transforms.ToTensor(), 139 | ]) 140 | transform_info['operations'] = ['Resize(64)', 'RandomCrop(64)', 'RandAugment()', 'RandomHorizontalFlip()', 'ToTensor()',] 141 | else: 142 | trans = transforms.Compose([ 143 | transforms.Resize(64), 144 | transforms.RandomCrop(64, padding=8, padding_mode='reflect'), 145 | transforms.RandomHorizontalFlip(), 146 | transforms.ToTensor(), 147 | ]) 148 | transform_info['operations'] = ['Resize(64)', 'RandomCrop(64)', 'RandomHorizontalFlip()', 'ToTensor()',] 149 | else: 150 | trans = transforms.Compose([ 151 | transforms.Resize(72), 152 | transforms.CenterCrop(64), 153 | transforms.ToTensor(), 154 | ]) 155 | transform_info['operations'] = ['Resize(72)', 'CenterCrop(64)', 'ToTensor()',] 156 | 157 | # save dataset info 158 | self.dataset_info['transform_info'] = transform_info 159 | 160 | return trans -------------------------------------------------------------------------------- /old_file/old_config/attacker_config.yaml: -------------------------------------------------------------------------------- 1 | 2 | # attacker settings for each dataset 3 | 4 | TOYData: 5 | FGSM: 6 | setting1: {attack_eps: 128, attack_rand_ini: 0.0} 7 | PGD: 8 | setting1: {attack_eps: 128, attack_alpha: 8, attack_step: 20, attack_rand_ini: 1.0} 9 | 10 | mnist: 11 | AutoAttack: 12 | setting1: {attack_eps: 32, attack_norm: 'Linf', attack_rand_ini: 0.0} 13 | setting2: {attack_eps: 128, attack_norm: 'L2', attack_rand_ini: 0.0} 14 | FGSM: 15 | setting1: {attack_eps: 32, attack_rand_ini: 0.0} 16 | setting2: {attack_eps: 64, attack_rand_ini: 0.0} 17 | BFS: 18 | setting1: {sigma: 0.25, eps: 32, steps: 100, attack_rand_ini: 0.0} 19 | FFGSM: 20 | setting1: {attack_eps: 32, attack_alpha: 10, attack_rand_ini: 1.0} 21 | setting2: {attack_eps: 64, attack_alpha: 20, attack_rand_ini: 1.0} 22 | PGD: 23 | setting1: {attack_eps: 32, attack_alpha: 2, attack_step: 20, attack_rand_ini: 1.0} 24 | setting2: {attack_eps: 64, attack_alpha: 2, attack_step: 20, attack_rand_ini: 1.0} 25 | ADAPTIVE: 26 | setting1: {attack_eps: 32, attack_alpha: 2, attack_step: 20, weight: 10.0, attack_rand_ini: 1.0} 27 | setting2: {attack_eps: 64, attack_alpha: 2, attack_step: 20, weight: 10.0, attack_rand_ini: 1.0} 28 | PGDL2: 29 | setting1: {attack_eps: 128, attack_alpha: 20, attack_step: 20, attack_rand_ini: 1.0} 30 | setting2: {attack_eps: 255, attack_alpha: 20, attack_step: 20, attack_rand_ini: 1.0} 31 | GN: 32 | setting1: {sigma: 0.25, eps: 32, attack_rand_ini: 0.0} 33 | UN: 34 | setting1: {un_sigma: 0.25, attack_rand_ini: 0.0} 35 | BPDAPGD: 36 | setting1: {attack_eps: 32, attack_alpha: 2, attack_step: 20, attack_rand_ini: 1.0} 37 | EOT: 38 | setting1: {attack_eps: 32, attack_lr: 100.0, attack_step: 100, attack_rand_ini: 1.0, eot_iter: 10} 39 | CW: 40 | setting1: {c: 0.0001, kappa: 0, steps: 1000, lr: 0.1, attack_rand_ini: 1.0} 41 | SPSA: 42 | setting1: {delta: 0.1, batch_size: 16, steps: 20, lr: 0.1, attack_rand_ini: 1.0} 43 | 44 | cifar10: 45 | AutoAttack: 46 | setting1: {attack_eps: 8, attack_norm: 'Linf', attack_rand_ini: 0.0} 47 | setting2: {attack_eps: 128, attack_norm: 'L2', attack_rand_ini: 0.0} 48 | FGSM: 49 | setting1: {attack_eps: 8, attack_rand_ini: 0.0} 50 | setting2: {attack_eps: 16, attack_rand_ini: 0.0} 51 | BFS: 52 | setting1: {sigma: 0.1, eps: 8, steps: 100, attack_rand_ini: 0.0} 53 | FFGSM: 54 | setting1: {attack_eps: 8, attack_alpha: 10, attack_rand_ini: 1.0} 55 | setting2: {attack_eps: 16, attack_alpha: 20, attack_rand_ini: 1.0} 56 | PGD: 57 | setting1: {attack_eps: 8, attack_alpha: 2, attack_step: 20, attack_rand_ini: 1.0} 58 | setting2: {attack_eps: 16, attack_alpha: 2, attack_step: 20, attack_rand_ini: 1.0} 59 | setting3: {attack_eps: 8, attack_alpha: 2, attack_step: 10, attack_rand_ini: 1.0} 60 | ADAPTIVE: 61 | setting1: {attack_eps: 8, attack_alpha: 2, attack_step: 20, weight: 10.0, attack_rand_ini: 1.0} 62 | setting2: {attack_eps: 16, attack_alpha: 2, attack_step: 20, weight: 10.0, attack_rand_ini: 1.0} 63 | PGDL2: 64 | setting1: {attack_eps: 128, attack_alpha: 20, attack_step: 20, attack_rand_ini: 1.0} 65 | setting2: {attack_eps: 255, attack_alpha: 20, attack_step: 20, attack_rand_ini: 1.0} 66 | GN: 67 | setting1: {sigma: 0.1, eps: 8, attack_rand_ini: 0.0} 68 | UN: 69 | setting1: {un_sigma: 0.1, attack_rand_ini: 0.0} 70 | BPDAPGD: 71 | setting1: {attack_eps: 8, attack_alpha: 2, attack_step: 20, attack_rand_ini: 1.0} 72 | EOT: 73 | setting1: {attack_eps: 8, attack_lr: 100.0, attack_step: 100, attack_rand_ini: 1.0, eot_iter: 10} 74 | CW: 75 | setting1: {c: 0.0001, kappa: 0, steps: 1000, lr: 0.1, attack_rand_ini: 1.0} 76 | SPSA: 77 | setting1: {delta: 0.1, batch_size: 16, steps: 20, lr: 0.1, attack_rand_ini: 1.0} 78 | 79 | imagenet: 80 | FGSM: 81 | setting1: {attack_eps: 8, attack_rand_ini: 0.0} 82 | setting2: {attack_eps: 16, attack_rand_ini: 0.0} 83 | FFGSM: 84 | setting1: {attack_eps: 8, attack_alpha: 10, attack_rand_ini: 1.0} 85 | setting2: {attack_eps: 16, attack_alpha: 20, attack_rand_ini: 1.0} 86 | PGD: 87 | setting1: {attack_eps: 8, attack_alpha: 2, attack_step: 20, attack_rand_ini: 1.0} 88 | setting2: {attack_eps: 16, attack_alpha: 2, attack_step: 20, attack_rand_ini: 1.0} 89 | PGDL2: 90 | setting1: {attack_eps: 128, attack_alpha: 20, attack_step: 20, attack_rand_ini: 1.0} 91 | setting2: {attack_eps: 255, attack_alpha: 20, attack_step: 20, attack_rand_ini: 1.0} 92 | GN: 93 | setting1: {gn_sigma: 0.25, attack_rand_ini: 0.0} 94 | UN: 95 | setting1: {un_sigma: 0.25, attack_rand_ini: 0.0} 96 | BPDAPGD: 97 | setting1: {attack_eps: 8, attack_alpha: 2, attack_step: 20, attack_rand_ini: 1.0} 98 | EOT: 99 | setting1: {attack_eps: 8, attack_lr: 100.0, attack_step: 100, attack_rand_ini: 1.0, eot_iter: 10} 100 | CW: 101 | setting1: {c: 0.0001, kappa: 0, steps: 1000, lr: 0.1, attack_rand_ini: 1.0} 102 | 103 | 104 | mini-imagenet: 105 | FGSM: 106 | setting1: {attack_eps: 8, attack_rand_ini: 0.0} 107 | setting2: {attack_eps: 16, attack_rand_ini: 0.0} 108 | FFGSM: 109 | setting1: {attack_eps: 8, attack_alpha: 10, attack_rand_ini: 1.0} 110 | setting2: {attack_eps: 16, attack_alpha: 20, attack_rand_ini: 1.0} 111 | PGD: 112 | setting1: {attack_eps: 8, attack_alpha: 2, attack_step: 20, attack_rand_ini: 1.0} 113 | setting2: {attack_eps: 16, attack_alpha: 2, attack_step: 20, attack_rand_ini: 1.0} 114 | PGDL2: 115 | setting1: {attack_eps: 128, attack_alpha: 20, attack_step: 20, attack_rand_ini: 1.0} 116 | setting2: {attack_eps: 255, attack_alpha: 20, attack_step: 20, attack_rand_ini: 1.0} 117 | GN: 118 | setting1: {gn_sigma: 0.25, attack_rand_ini: 0.0} 119 | UN: 120 | setting1: {un_sigma: 0.25, attack_rand_ini: 0.0} 121 | BPDAPGD: 122 | setting1: {attack_eps: 8, attack_alpha: 2, attack_step: 20, attack_rand_ini: 1.0} 123 | EOT: 124 | setting1: {attack_eps: 8, attack_lr: 100.0, attack_step: 100, attack_rand_ini: 1.0, eot_iter: 10} 125 | CW: 126 | setting1: {c: 0.0001, kappa: 0, steps: 1000, lr: 0.1, attack_rand_ini: 1.0} 127 | -------------------------------------------------------------------------------- /models/WideResNet.py: -------------------------------------------------------------------------------- 1 | import math 2 | import torch 3 | import torch.nn as nn 4 | import torch.nn.functional as F 5 | 6 | from models.Base_Model import Base_Model 7 | from utils.train_utils import * 8 | 9 | class BasicBlock(Base_Model): 10 | def __init__(self, in_planes, out_planes, stride, dropRate=0.0, activation='ReLU', softplus_beta=1): 11 | super(BasicBlock, self).__init__() 12 | self.bn1 = nn.BatchNorm2d(in_planes) 13 | self.conv1 = nn.Conv2d(in_planes, out_planes, kernel_size=3, stride=stride, 14 | padding=1, bias=False) 15 | self.bn2 = nn.BatchNorm2d(out_planes) 16 | self.conv2 = nn.Conv2d(out_planes, out_planes, kernel_size=3, stride=1, 17 | padding=1, bias=False) 18 | if activation == 'ReLU': 19 | self.relu1 = nn.ReLU(inplace=True) 20 | self.relu2 = nn.ReLU(inplace=True) 21 | print('R') 22 | elif activation == 'Softplus': 23 | self.relu1 = nn.Softplus(beta=softplus_beta, threshold=20) 24 | self.relu2 = nn.Softplus(beta=softplus_beta, threshold=20) 25 | print('S') 26 | elif activation == 'GELU': 27 | self.relu1 = nn.GELU() 28 | self.relu2 = nn.GELU() 29 | print('G') 30 | elif activation == 'ELU': 31 | self.relu1 = nn.ELU(alpha=1.0, inplace=True) 32 | self.relu2 = nn.ELU(alpha=1.0, inplace=True) 33 | print('E') 34 | 35 | self.droprate = dropRate 36 | self.equalInOut = (in_planes == out_planes) 37 | self.convShortcut = (not self.equalInOut) and nn.Conv2d(in_planes, out_planes, kernel_size=1, stride=stride, 38 | padding=0, bias=False) or None 39 | 40 | def forward(self, x): 41 | if not self.equalInOut: 42 | x = self.relu1(self.bn1(x)) 43 | else: 44 | out = self.relu1(self.bn1(x)) 45 | out = self.relu2(self.bn2(self.conv1(out if self.equalInOut else x))) 46 | if self.droprate > 0: 47 | out = F.dropout(out, p=self.droprate, training=self.training) 48 | out = self.conv2(out) 49 | return torch.add(x if self.equalInOut else self.convShortcut(x), out) 50 | 51 | 52 | class NetworkBlock(Base_Model): 53 | def __init__(self, nb_layers, in_planes, out_planes, block, stride, dropRate=0.0, activation='ReLU', softplus_beta=1): 54 | super(NetworkBlock, self).__init__() 55 | self.activation = activation 56 | self.softplus_beta = softplus_beta 57 | self.layer = self._make_layer(block, in_planes, out_planes, nb_layers, stride, dropRate) 58 | 59 | def _make_layer(self, block, in_planes, out_planes, nb_layers, stride, dropRate): 60 | layers = [] 61 | for i in range(int(nb_layers)): 62 | layers.append(block(i == 0 and in_planes or out_planes, out_planes, i == 0 and stride or 1, dropRate, 63 | self.activation, self.softplus_beta)) 64 | return nn.Sequential(*layers) 65 | 66 | def forward(self, x): 67 | return self.layer(x) 68 | 69 | 70 | class WideResNet(Base_Model): 71 | def __init__(self, depth=34, num_classes=10, widen_factor=10, dropRate=0.0, activation='ReLU', softplus_beta=1): 72 | super(WideResNet, self).__init__() 73 | nChannels = [16, 16 * widen_factor, 32 * widen_factor, 64 * widen_factor] 74 | assert ((depth - 4) % 6 == 0) 75 | n = (depth - 4) / 6 76 | block = BasicBlock 77 | #self.scale = scale 78 | # 1st conv before any network block 79 | self.conv1 = nn.Conv2d(3, nChannels[0], kernel_size=3, stride=1, 80 | padding=1, bias=False) 81 | # 1st block 82 | self.block1 = NetworkBlock(n, nChannels[0], nChannels[1], block, 1, dropRate, activation=activation, softplus_beta=softplus_beta) 83 | # 1st sub-block 84 | self.sub_block1 = NetworkBlock(n, nChannels[0], nChannels[1], block, 1, dropRate, activation=activation, softplus_beta=softplus_beta) 85 | # 2nd block 86 | self.block2 = NetworkBlock(n, nChannels[1], nChannels[2], block, 2, dropRate, activation=activation, softplus_beta=softplus_beta) 87 | # 3rd block 88 | self.block3 = NetworkBlock(n, nChannels[2], nChannels[3], block, 2, dropRate, activation=activation, softplus_beta=softplus_beta) 89 | # global average pooling and classifier 90 | self.bn1 = nn.BatchNorm2d(nChannels[3]) 91 | 92 | if activation == 'ReLU': 93 | self.relu = nn.ReLU(inplace=True) 94 | elif activation == 'Softplus': 95 | self.relu = nn.Softplus(beta=softplus_beta, threshold=20) 96 | elif activation == 'GELU': 97 | self.relu = nn.GELU() 98 | elif activation == 'ELU': 99 | self.relu = nn.ELU(alpha=1.0, inplace=True) 100 | print('Use activation of ' + activation) 101 | 102 | self.fc = nn.Linear(nChannels[3], num_classes) 103 | self.nChannels = nChannels[3] 104 | 105 | for m in self.modules(): 106 | if isinstance(m, nn.Conv2d): 107 | n = m.kernel_size[0] * m.kernel_size[1] * m.out_channels 108 | m.weight.data.normal_(0, math.sqrt(2. / n)) 109 | elif isinstance(m, nn.BatchNorm2d): 110 | m.weight.data.fill_(1) 111 | m.bias.data.zero_() 112 | elif isinstance(m, nn.Linear): 113 | m.bias.data.zero_() 114 | 115 | def forward(self, x): 116 | out = self.conv1(x) 117 | out = self.block1(out) 118 | out = self.block2(out) 119 | out = self.block3(out) 120 | out = self.relu(self.bn1(out)) 121 | out = F.avg_pool2d(out, 8) 122 | out = out.view(-1, self.nChannels) 123 | return self.fc(out) 124 | 125 | 126 | def create_model(m_type='WRN34-10', num_classes=1000, activation='ReLU', softplus_beta=1.0): 127 | if m_type == 'WRN34-10': 128 | model = WideResNet(34, num_classes, widen_factor=10, dropRate=0.0, activation=activation, softplus_beta=softplus_beta) 129 | else: 130 | raise ValueError('Wrong Model Type') 131 | return model --------------------------------------------------------------------------------