diff --git a/make_patch.py b/make_patch.py index 58e40cf..0273023 100755 --- a/make_patch.py +++ b/make_patch.py @@ -2,6 +2,7 @@ import os import random import numpy as np +import warnings import torch import torch.nn as nn @@ -21,31 +22,45 @@ from utils import * parser = argparse.ArgumentParser() -parser.add_argument('--workers', type=int, help='number of data loading workers', default=2) -parser.add_argument('--epochs', type=int, default=20, help='number of epochs to train for') +parser.add_argument('--workers', type=int, + help='number of data loading workers', default=2) +parser.add_argument('--epochs', type=int, default=20, + help='number of epochs to train for') parser.add_argument('--cuda', action='store_true', help='enables cuda') -parser.add_argument('--target', type=int, default=859, help='The target class: 859 == toaster') -parser.add_argument('--conf_target', type=float, default=0.9, help='Stop attack on image when target classifier reaches this value for target class') +parser.add_argument('--target', type=int, default=859, + help='The target class: 859 == toaster') +parser.add_argument('--conf_target', type=float, default=0.9, + help='Stop attack on image when target classifier reaches this value for target class') -parser.add_argument('--max_count', type=int, default=1000, help='max number of iterations to find adversarial example') -parser.add_argument('--patch_type', type=str, default='circle', help='patch type: circle or square') -parser.add_argument('--patch_size', type=float, default=0.05, help='patch size. E.g. 0.05 ~= 5% of image ') +parser.add_argument('--max_count', type=int, default=1000, + help='max number of iterations to find adversarial example') +parser.add_argument('--patch_type', type=str, default='circle', + help='patch type: circle or square') +parser.add_argument('--patch_size', type=float, default=0.05, + help='patch size. E.g. 0.05 ~= 5% of image ') -parser.add_argument('--train_size', type=int, default=2000, help='Number of training images') -parser.add_argument('--test_size', type=int, default=2000, help='Number of test images') +parser.add_argument('--train_size', type=int, default=2000, + help='Number of training images') +parser.add_argument('--test_size', type=int, default=2000, + help='Number of test images') -parser.add_argument('--image_size', type=int, default=299, help='the height / width of the input image to network') +parser.add_argument('--image_size', type=int, default=299, + help='the height / width of the input image to network') -parser.add_argument('--plot_all', type=int, default=1, help='1 == plot all successful adversarial images') +parser.add_argument('--plot_all', type=int, default=1, + help='1 == plot all successful adversarial images') -parser.add_argument('--netClassifier', default='inceptionv3', help="The target classifier") +parser.add_argument('--netClassifier', default='inceptionv3', + help="The target classifier") -parser.add_argument('--outf', default='./logs', help='folder to output images and model checkpoints') +parser.add_argument('--outf', default='./logs', + help='folder to output images and model checkpoints') parser.add_argument('--manualSeed', type=int, default=1338, help='manual seed') opt = parser.parse_args() print(opt) +warnings.simplefilter("ignore") try: os.makedirs(opt.outf) @@ -58,8 +73,10 @@ random.seed(opt.manualSeed) np.random.seed(opt.manualSeed) torch.manual_seed(opt.manualSeed) -if opt.cuda: - torch.cuda.manual_seed_all(opt.manualSeed) +device = torch.device('mps') + +# if opt.cuda: +# torch.cuda.manual_seed_all(opt.manualSeed) cudnn.benchmark = True @@ -74,14 +91,17 @@ image_size = opt.image_size train_size = opt.train_size test_size = opt.test_size -plot_all = opt.plot_all +plot_all = opt.plot_all -assert train_size + test_size <= 50000, "Traing set size + Test set size > Total dataset size" +assert train_size + \ + test_size <= 50000, "Traing set size + Test set size > Total dataset size" print("=> creating model ") -netClassifier = pretrainedmodels.__dict__[opt.netClassifier](num_classes=1000, pretrained='imagenet') +netClassifier = pretrainedmodels.__dict__[opt.netClassifier]( + num_classes=1000, pretrained='imagenet') if opt.cuda: - netClassifier.cuda() + netClassifier.to(device) + # netClassifier.cuda() print('==> Preparing data..') @@ -90,35 +110,36 @@ idx = np.arange(50000) np.random.shuffle(idx) training_idx = idx[:train_size] -test_idx = idx[train_size:test_size] +test_idx = idx[train_size:(test_size+train_size)] train_loader = torch.utils.data.DataLoader( dset.ImageFolder('./imagenetdata/val', transforms.Compose([ - transforms.Scale(round(max(netClassifier.input_size)*1.050)), + transforms.Resize(round(max(netClassifier.input_size)*1.050)), transforms.CenterCrop(max(netClassifier.input_size)), transforms.ToTensor(), - ToSpaceBGR(netClassifier.input_space=='BGR'), - ToRange255(max(netClassifier.input_range)==255), + ToSpaceBGR(netClassifier.input_space == 'BGR'), + ToRange255(max(netClassifier.input_range) == 255), normalize, ])), batch_size=1, shuffle=False, sampler=SubsetRandomSampler(training_idx), num_workers=opt.workers, pin_memory=True) - + test_loader = torch.utils.data.DataLoader( dset.ImageFolder('./imagenetdata/val', transforms.Compose([ - transforms.Scale(round(max(netClassifier.input_size)*1.050)), + transforms.Resize(round(max(netClassifier.input_size)*1.050)), transforms.CenterCrop(max(netClassifier.input_size)), transforms.ToTensor(), - ToSpaceBGR(netClassifier.input_space=='BGR'), - ToRange255(max(netClassifier.input_range)==255), + ToSpaceBGR(netClassifier.input_space == 'BGR'), + ToRange255(max(netClassifier.input_range) == 255), normalize, ])), batch_size=1, shuffle=False, sampler=SubsetRandomSampler(test_idx), num_workers=opt.workers, pin_memory=True) min_in, max_in = netClassifier.input_range[0], netClassifier.input_range[1] -min_in, max_in = np.array([min_in, min_in, min_in]), np.array([max_in, max_in, max_in]) -mean, std = np.array(netClassifier.mean), np.array(netClassifier.std) +min_in, max_in = np.array([min_in, min_in, min_in] + ), np.array([max_in, max_in, max_in]) +mean, std = np.array(netClassifier.mean), np.array(netClassifier.std) min_out, max_out = np.min((min_in-mean)/std), np.max((max_in-mean)/std) @@ -127,6 +148,10 @@ def train(epoch, patch, patch_shape): success = 0 total = 0 recover_time = 0 + try: + os.makedirs(f'{opt.outf}/train/{epoch}') + except OSError: + pass for batch_idx, (data, labels) in enumerate(train_loader): if opt.cuda: data = data.cuda() @@ -134,102 +159,125 @@ def train(epoch, patch, patch_shape): data, labels = Variable(data), Variable(labels) prediction = netClassifier(data) - - # only computer adversarial examples on examples that are originally classified correctly + + # only computer adversarial examples on examples that are originally classified correctly if prediction.data.max(1)[1][0] != labels.data[0]: continue - + total += 1 - + # transform path data_shape = data.data.cpu().numpy().shape if patch_type == 'circle': - patch, mask, patch_shape = circle_transform(patch, data_shape, patch_shape, image_size) + patch, mask, patch_shape = circle_transform( + patch, data_shape, patch_shape, image_size) elif patch_type == 'square': - patch, mask = square_transform(patch, data_shape, patch_shape, image_size) + patch, mask = square_transform( + patch, data_shape, patch_shape, image_size) patch, mask = torch.FloatTensor(patch), torch.FloatTensor(mask) if opt.cuda: - patch, mask = patch.cuda(), mask.cuda() + patch, mask = patch.to(device), mask.to(device) + #patch, mask = patch.cuda(), mask.cuda() patch, mask = Variable(patch), Variable(mask) - + adv_x, mask, patch = attack(data, patch, mask) - + adv_label = netClassifier(adv_x).data.max(1)[1][0] ori_label = labels.data[0] - + if adv_label == target: success += 1 - - if plot_all == 1: + + if plot_all == 1: # plot source image - vutils.save_image(data.data, "./%s/%d_%d_original.png" %(opt.outf, batch_idx, ori_label), normalize=True) - + vutils.save_image(data.data, "./%s/train/%d/%d_%d_original.png" % + (opt.outf, epoch, batch_idx, ori_label), normalize=True) + # plot adversarial image - vutils.save_image(adv_x.data, "./%s/%d_%d_adversarial.png" %(opt.outf, batch_idx, adv_label), normalize=True) - + vutils.save_image(adv_x.data, "./%s/train/%d/%d_%d_adversarial.png" % + (opt.outf, epoch, batch_idx, adv_label), normalize=True) + masked_patch = torch.mul(mask, patch) patch = masked_patch.data.cpu().numpy() new_patch = np.zeros(patch_shape) - for i in range(new_patch.shape[0]): - for j in range(new_patch.shape[1]): + for i in range(new_patch.shape[0]): + for j in range(new_patch.shape[1]): new_patch[i][j] = submatrix(patch[i][j]) - + patch = new_patch - # log to file - progress_bar(batch_idx, len(train_loader), "Train Patch Success: {:.3f}".format(success/total)) + # log to file + progress_bar(batch_idx, len(train_loader), + "Train Patch Success: {:.3f}".format(success/total)) return patch + def test(epoch, patch, patch_shape): netClassifier.eval() success = 0 total = 0 + try: + os.makedirs(f'{opt.outf}/test/{epoch}') + except OSError: + pass for batch_idx, (data, labels) in enumerate(test_loader): if opt.cuda: - data = data.cuda() - labels = labels.cuda() + data = data.to(device) + labels = labels.to(device) + #data = data.cuda() + #labels = labels.cuda() data, labels = Variable(data), Variable(labels) prediction = netClassifier(data) - # only computer adversarial examples on examples that are originally classified correctly + # only computer adversarial examples on examples that are originally classified correctly if prediction.data.max(1)[1][0] != labels.data[0]: continue - - total += 1 - + + total += 1 + # transform path data_shape = data.data.cpu().numpy().shape if patch_type == 'circle': - patch, mask, patch_shape = circle_transform(patch, data_shape, patch_shape, image_size) + patch, mask, patch_shape = circle_transform( + patch, data_shape, patch_shape, image_size) elif patch_type == 'square': - patch, mask = square_transform(patch, data_shape, patch_shape, image_size) + patch, mask = square_transform( + patch, data_shape, patch_shape, image_size) patch, mask = torch.FloatTensor(patch), torch.FloatTensor(mask) if opt.cuda: - patch, mask = patch.cuda(), mask.cuda() + patch, mask = patch.to(device), mask.to(device) + #patch, mask = patch.cuda(), mask.cuda() patch, mask = Variable(patch), Variable(mask) - - adv_x = torch.mul((1-mask),data) + torch.mul(mask,patch) + + adv_x = torch.mul((1-mask), data) + torch.mul(mask, patch) adv_x = torch.clamp(adv_x, min_out, max_out) - + adv_label = netClassifier(adv_x).data.max(1)[1][0] ori_label = labels.data[0] - + if adv_label == target: success += 1 - + + vutils.save_image(data.data, "./%s/test/%d/%d_%d_original.png" % + (opt.outf, epoch, batch_idx, ori_label), normalize=True) + vutils.save_image(adv_x.data, "./%s/test/%d/%d_%d_adversarial.png" % + (opt.outf, epoch, batch_idx, adv_label), normalize=True) + masked_patch = torch.mul(mask, patch) patch = masked_patch.data.cpu().numpy() new_patch = np.zeros(patch_shape) - for i in range(new_patch.shape[0]): - for j in range(new_patch.shape[1]): + for i in range(new_patch.shape[0]): + for j in range(new_patch.shape[1]): new_patch[i][j] = submatrix(patch[i][j]) - + patch = new_patch - # log to file - progress_bar(batch_idx, len(test_loader), "Test Success: {:.3f}".format(success/total)) + # log to file + progress_bar(batch_idx, len(test_loader), + "Test Success: {:.3f}".format(success/total)) + def attack(x, patch, mask): netClassifier.eval() @@ -237,50 +285,49 @@ def attack(x, patch, mask): x_out = F.softmax(netClassifier(x)) target_prob = x_out.data[0][target] - adv_x = torch.mul((1-mask),x) + torch.mul(mask,patch) - - count = 0 - + adv_x = torch.mul((1-mask), x) + torch.mul(mask, patch) + + count = 0 + while conf_target > target_prob: count += 1 adv_x = Variable(adv_x.data, requires_grad=True) adv_out = F.log_softmax(netClassifier(adv_x)) - + adv_out_probs, adv_out_labels = adv_out.max(1) - + Loss = -adv_out[0][target] Loss.backward() - + adv_grad = adv_x.grad.clone() - + adv_x.grad.data.zero_() - - patch -= adv_grad - - adv_x = torch.mul((1-mask),x) + torch.mul(mask,patch) + + patch -= adv_grad + + adv_x = torch.mul((1-mask), x) + torch.mul(mask, patch) adv_x = torch.clamp(adv_x, min_out, max_out) - + out = F.softmax(netClassifier(adv_x)) target_prob = out.data[0][target] #y_argmax_prob = out.data.max(1)[0][0] - - #print(count, conf_target, target_prob, y_argmax_prob) + + #print(count, conf_target, target_prob, y_argmax_prob) if count >= opt.max_count: break - - return adv_x, mask, patch + return adv_x, mask, patch if __name__ == '__main__': if patch_type == 'circle': - patch, patch_shape = init_patch_circle(image_size, patch_size) + patch, patch_shape = init_patch_circle(image_size, patch_size) elif patch_type == 'square': - patch, patch_shape = init_patch_square(image_size, patch_size) + patch, patch_shape = init_patch_square(image_size, patch_size) else: sys.exit("Please choose a square or circle patch") - + for epoch in range(1, opt.epochs + 1): patch = train(epoch, patch, patch_shape) test(epoch, patch, patch_shape) diff --git a/make_patch_multi.py b/make_patch_multi.py new file mode 100644 index 0000000..fee5c6e --- /dev/null +++ b/make_patch_multi.py @@ -0,0 +1,364 @@ +import argparse +from operator import le +import os +import random +import numpy as np +import warnings + +import torch +import torch.nn as nn +import torch.nn.parallel +import torch.backends.cudnn as cudnn +import torch.optim as optim +import torch.utils.data +import torch.nn.functional as F +import torchvision.datasets as dset +import torchvision.transforms as transforms +import torchvision.utils as vutils +from torch.autograd import Variable +from torch.utils.data.sampler import SubsetRandomSampler + +from pretrained_models_pytorch import pretrainedmodels + +from utils import * + +parser = argparse.ArgumentParser() +parser.add_argument('--workers', type=int, + help='number of data loading workers', default=2) +parser.add_argument('--epochs', type=int, default=20, + help='number of epochs to train for') +parser.add_argument('--cuda', action='store_true', help='enables cuda') + +parser.add_argument('--target', type=int, default=859, + help='The target class: 859 == toaster') +parser.add_argument('--conf_target', type=float, default=0.9, + help='Stop attack on image when target classifier reaches this value for target class') + +parser.add_argument('--max_count', type=int, default=1000, + help='max number of iterations to find adversarial example') +parser.add_argument('--patch_type', type=str, default='circle', + help='patch type: circle or square') +parser.add_argument('--patch_size', type=float, default=0.05, + help='patch size. E.g. 0.05 ~= 5% of image ') + +parser.add_argument('--train_size', type=int, default=2000, + help='Number of training images') +parser.add_argument('--test_size', type=int, default=2000, + help='Number of test images') + +parser.add_argument('--image_size', type=int, default=299, + help='the height / width of the input image to network') + +parser.add_argument('--plot_all', type=int, default=1, + help='1 == plot all successful adversarial images') + +parser.add_argument('--netClassifier', default='inceptionv3', + help="The target classifier") + +parser.add_argument('--outf', default='./logs', + help='folder to output images and model checkpoints') +parser.add_argument('--manualSeed', type=int, default=1338, help='manual seed') + +opt = parser.parse_args() +print(opt) +warnings.simplefilter("ignore") + +try: + os.makedirs(opt.outf) +except OSError: + pass + +try: + os.makedirs(f'{opt.outf}/train') +except OSError: + pass + +try: + os.makedirs(f'{opt.outf}/test') +except OSError: + pass + +if opt.manualSeed is None: + opt.manualSeed = random.randint(1, 10000) +print("Random Seed: ", opt.manualSeed) +random.seed(opt.manualSeed) +np.random.seed(opt.manualSeed) +torch.manual_seed(opt.manualSeed) +device = torch.device('mps') + +# if opt.cuda: +# torch.cuda.manual_seed_all(opt.manualSeed) + +cudnn.benchmark = True + +if torch.cuda.is_available() and not opt.cuda: + print("WARNING: You have a CUDA device, so you should probably run with --cuda") + +target = opt.target +conf_target = opt.conf_target +max_count = opt.max_count +patch_type = opt.patch_type +patch_size = opt.patch_size +image_size = opt.image_size +train_size = opt.train_size +test_size = opt.test_size +plot_all = opt.plot_all + +assert train_size + \ + test_size <= 50000, "Traing set size + Test set size > Total dataset size" + +print("=> creating model ") +netClassifier = pretrainedmodels.__dict__[opt.netClassifier]( + num_classes=1000, pretrained='imagenet') + +netClassifiers_names = ['inceptionv3', 'resnet50', 'vgg16', 'vgg19'] + +netClassifiers = [pretrainedmodels.__dict__[name]( + num_classes=1000, pretrained='imagenet') for name in netClassifiers_names] + +if opt.cuda: + netClassifier.to(device) + # netClassifier.cuda() + + +print('==> Preparing data..') +normalize = transforms.Normalize(mean=netClassifier.mean, + std=netClassifier.std) +idx = np.arange(50000) +np.random.shuffle(idx) +training_idx = idx[:train_size] +test_idx = idx[train_size:(test_size+train_size)] + +train_loader = torch.utils.data.DataLoader( + dset.ImageFolder('./imagenetdata/val', transforms.Compose([ + transforms.Resize(round(max(netClassifier.input_size)*1.050)), + transforms.CenterCrop(max(netClassifier.input_size)), + transforms.ToTensor(), + ToSpaceBGR(netClassifier.input_space == 'BGR'), + ToRange255(max(netClassifier.input_range) == 255), + normalize, + ])), + batch_size=1, shuffle=False, sampler=SubsetRandomSampler(training_idx), + num_workers=opt.workers, pin_memory=True) + +test_loader = torch.utils.data.DataLoader( + dset.ImageFolder('./imagenetdata/val', transforms.Compose([ + transforms.Resize(round(max(netClassifier.input_size)*1.050)), + transforms.CenterCrop(max(netClassifier.input_size)), + transforms.ToTensor(), + ToSpaceBGR(netClassifier.input_space == 'BGR'), + ToRange255(max(netClassifier.input_range) == 255), + normalize, + ])), + batch_size=1, shuffle=False, sampler=SubsetRandomSampler(test_idx), + num_workers=opt.workers, pin_memory=True) + +min_in, max_in = netClassifier.input_range[0], netClassifier.input_range[1] +min_in, max_in = np.array([min_in, min_in, min_in] + ), np.array([max_in, max_in, max_in]) +mean, std = np.array(netClassifier.mean), np.array(netClassifier.std) +min_out, max_out = np.min((min_in-mean)/std), np.max((max_in-mean)/std) + + +def train(epoch, patch, patch_shape): + for i in range(len(netClassifiers)): + netClassifiers[i].eval() + success = 0 + total = 0 + recover_time = 0 + try: + os.makedirs(f'{opt.outf}/train/{epoch}') + except OSError: + pass + for batch_idx, (data, labels) in enumerate(train_loader): + for i, classifier in enumerate(netClassifiers): + if opt.cuda: + data = data.cuda() + labels = labels.cuda() + data, labels = Variable(data), Variable(labels) + + prediction = classifier(data) + + # only computer adversarial examples on examples that are originally classified correctly + if prediction.data.max(1)[1][0] != labels.data[0]: + print( + f'{netClassifiers_names[i]} predicted incorectly {prediction.data.max(1)[1][0]} != {labels.data[0]}') + continue + + total += 1 + + # transform path + data_shape = data.data.cpu().numpy().shape + if patch_type == 'circle': + patch, mask, patch_shape = circle_transform( + patch, data_shape, patch_shape, image_size) + elif patch_type == 'square': + patch, mask = square_transform( + patch, data_shape, patch_shape, image_size) + patch, mask = torch.FloatTensor(patch), torch.FloatTensor(mask) + if opt.cuda: + patch, mask = patch.to(device), mask.to(device) + #patch, mask = patch.cuda(), mask.cuda() + patch, mask = Variable(patch), Variable(mask) + + adv_x, mask, patch = attack(data, patch, mask, classifier, i) + + adv_label = classifier(adv_x).data.max(1)[1][0] + ori_label = labels.data[0] + + if adv_label == target: + success += 1 + + if plot_all == 1: + # plot source image + vutils.save_image(data.data, "./%s/train/%d/%d_%d_original_%s.png" % + (opt.outf, epoch, batch_idx, ori_label, netClassifiers_names[i]), normalize=True) + + # plot adversarial image + vutils.save_image(adv_x.data, "./%s/train/%d/%d_%d_adversarial_%s.png" % + (opt.outf, epoch, batch_idx, adv_label, netClassifiers_names[i]), normalize=True) + + masked_patch = torch.mul(mask, patch) + patch = masked_patch.data.cpu().numpy() + new_patch = np.zeros(patch_shape) + for i in range(new_patch.shape[0]): + for j in range(new_patch.shape[1]): + new_patch[i][j] = submatrix(patch[i][j]) + + patch = new_patch + + # log to file + keeper = False + if total == 0: + keeper = True + total = 1 + progress_bar(batch_idx, len(train_loader), + "Train Patch Success: {:.3f}".format(success/total)) + if keeper: + total = 0 + + return patch + + +def test(epoch, patch, patch_shape): + for i in range(len(netClassifiers)): + netClassifiers[i].eval() + success = 0 + total = 0 + try: + os.makedirs(f'{opt.outf}/test/{epoch}') + except OSError: + pass + for batch_idx, (data, labels) in enumerate(test_loader): + for i, classifier in enumerate(netClassifiers): + if opt.cuda: + data = data.to(device) + labels = labels.to(device) + #data = data.cuda() + #labels = labels.cuda() + data, labels = Variable(data), Variable(labels) + + prediction = classifier(data) + + # only computer adversarial examples on examples that are originally classified correctly + if prediction.data.max(1)[1][0] != labels.data[0]: + continue + + total += 1 + + # transform path + data_shape = data.data.cpu().numpy().shape + if patch_type == 'circle': + patch, mask, patch_shape = circle_transform( + patch, data_shape, patch_shape, image_size) + elif patch_type == 'square': + patch, mask = square_transform( + patch, data_shape, patch_shape, image_size) + patch, mask = torch.FloatTensor(patch), torch.FloatTensor(mask) + if opt.cuda: + patch, mask = patch.to(device), mask.to(device) + #patch, mask = patch.cuda(), mask.cuda() + patch, mask = Variable(patch), Variable(mask) + + adv_x = torch.mul((1-mask), data) + torch.mul(mask, patch) + adv_x = torch.clamp(adv_x, min_out, max_out) + + adv_label = classifier(adv_x).data.max(1)[1][0] + ori_label = labels.data[0] + + if adv_label == target: + success += 1 + + vutils.save_image(data.data, "./%s/test/%d/%d_%d_original_%s.png" % + (opt.outf, epoch, batch_idx, ori_label, netClassifiers_names[i]), normalize=True) + vutils.save_image(adv_x.data, "./%s/test/%d/%d_%d_adversarial_%s.png" % + (opt.outf, epoch, batch_idx, adv_label, netClassifiers_names[i]), normalize=True) + + masked_patch = torch.mul(mask, patch) + patch = masked_patch.data.cpu().numpy() + new_patch = np.zeros(patch_shape) + for i in range(new_patch.shape[0]): + for j in range(new_patch.shape[1]): + new_patch[i][j] = submatrix(patch[i][j]) + + patch = new_patch + + # log to file + progress_bar(batch_idx, len(test_loader), + "Test Success: {:.3f}".format(success/total)) + + +def attack(x, patch, mask, classifier, i): + classifier.eval() + + x_out = F.softmax(classifier(x)) + target_prob = x_out.data[0][target] + + adv_x = torch.mul((1-mask), x) + torch.mul(mask, patch) + + count = 0 + + while conf_target > target_prob: + count += 1 + adv_x = Variable(adv_x.data, requires_grad=True) + adv_out = F.log_softmax(classifier(adv_x)) + + adv_out_probs, adv_out_labels = adv_out.max(1) + + Loss = -adv_out[0][target] + Loss.backward() + + adv_grad = adv_x.grad.clone() + + adv_x.grad.data.zero_() + + patch -= adv_grad + + adv_x = torch.mul((1-mask), x) + torch.mul(mask, patch) + adv_x = torch.clamp(adv_x, min_out, max_out) + + out = F.softmax(classifier(adv_x)) + target_prob = out.data[0][target] + #y_argmax_prob = out.data.max(1)[0][0] + + #print(count, conf_target, target_prob, y_argmax_prob) + + if count >= opt.max_count: + print( + f'{netClassifiers_names[i]} over max count') + break + + return adv_x, mask, patch + + +if __name__ == '__main__': + if patch_type == 'circle': + patch, patch_shape = init_patch_circle(image_size, patch_size) + elif patch_type == 'square': + patch, patch_shape = init_patch_square(image_size, patch_size) + else: + sys.exit("Please choose a square or circle patch") + + for epoch in range(1, opt.epochs + 1): + patch = train(epoch, patch, patch_shape) + test(epoch, patch, patch_shape) diff --git a/pretrained_models_pytorch/.DS_Store b/pretrained_models_pytorch/.DS_Store new file mode 100644 index 0000000..c2048f8 Binary files /dev/null and b/pretrained_models_pytorch/.DS_Store differ diff --git a/pretrained_models_pytorch/pretrainedmodels/__pycache__/__init__.cpython-310.pyc b/pretrained_models_pytorch/pretrainedmodels/__pycache__/__init__.cpython-310.pyc new file mode 100644 index 0000000..d230d45 Binary files /dev/null and b/pretrained_models_pytorch/pretrainedmodels/__pycache__/__init__.cpython-310.pyc differ diff --git a/pretrained_models_pytorch/pretrainedmodels/__pycache__/bninception.cpython-310.pyc b/pretrained_models_pytorch/pretrainedmodels/__pycache__/bninception.cpython-310.pyc new file mode 100644 index 0000000..92513db Binary files /dev/null and b/pretrained_models_pytorch/pretrainedmodels/__pycache__/bninception.cpython-310.pyc differ diff --git a/pretrained_models_pytorch/pretrainedmodels/__pycache__/fbresnet.cpython-310.pyc b/pretrained_models_pytorch/pretrainedmodels/__pycache__/fbresnet.cpython-310.pyc new file mode 100644 index 0000000..b81c927 Binary files /dev/null and b/pretrained_models_pytorch/pretrainedmodels/__pycache__/fbresnet.cpython-310.pyc differ diff --git a/pretrained_models_pytorch/pretrainedmodels/__pycache__/inceptionresnetv2.cpython-310.pyc b/pretrained_models_pytorch/pretrainedmodels/__pycache__/inceptionresnetv2.cpython-310.pyc new file mode 100644 index 0000000..f28baca Binary files /dev/null and b/pretrained_models_pytorch/pretrainedmodels/__pycache__/inceptionresnetv2.cpython-310.pyc differ diff --git a/pretrained_models_pytorch/pretrainedmodels/__pycache__/inceptionv4.cpython-310.pyc b/pretrained_models_pytorch/pretrainedmodels/__pycache__/inceptionv4.cpython-310.pyc new file mode 100644 index 0000000..bcc8eb8 Binary files /dev/null and b/pretrained_models_pytorch/pretrainedmodels/__pycache__/inceptionv4.cpython-310.pyc differ diff --git a/pretrained_models_pytorch/pretrainedmodels/__pycache__/nasnet.cpython-310.pyc b/pretrained_models_pytorch/pretrainedmodels/__pycache__/nasnet.cpython-310.pyc new file mode 100644 index 0000000..08416f0 Binary files /dev/null and b/pretrained_models_pytorch/pretrainedmodels/__pycache__/nasnet.cpython-310.pyc differ diff --git a/pretrained_models_pytorch/pretrainedmodels/__pycache__/resnext.cpython-310.pyc b/pretrained_models_pytorch/pretrainedmodels/__pycache__/resnext.cpython-310.pyc new file mode 100644 index 0000000..64c60b1 Binary files /dev/null and b/pretrained_models_pytorch/pretrainedmodels/__pycache__/resnext.cpython-310.pyc differ diff --git a/pretrained_models_pytorch/pretrainedmodels/__pycache__/torchvision.cpython-310.pyc b/pretrained_models_pytorch/pretrainedmodels/__pycache__/torchvision.cpython-310.pyc new file mode 100644 index 0000000..1e8b3d4 Binary files /dev/null and b/pretrained_models_pytorch/pretrainedmodels/__pycache__/torchvision.cpython-310.pyc differ diff --git a/pretrained_models_pytorch/pretrainedmodels/resnext_features/__pycache__/__init__.cpython-310.pyc b/pretrained_models_pytorch/pretrainedmodels/resnext_features/__pycache__/__init__.cpython-310.pyc new file mode 100644 index 0000000..59d2831 Binary files /dev/null and b/pretrained_models_pytorch/pretrainedmodels/resnext_features/__pycache__/__init__.cpython-310.pyc differ diff --git a/pretrained_models_pytorch/pretrainedmodels/resnext_features/__pycache__/resnext101_32x4d_features.cpython-310.pyc b/pretrained_models_pytorch/pretrainedmodels/resnext_features/__pycache__/resnext101_32x4d_features.cpython-310.pyc new file mode 100644 index 0000000..8479b9f Binary files /dev/null and b/pretrained_models_pytorch/pretrainedmodels/resnext_features/__pycache__/resnext101_32x4d_features.cpython-310.pyc differ diff --git a/pretrained_models_pytorch/pretrainedmodels/resnext_features/__pycache__/resnext101_64x4d_features.cpython-310.pyc b/pretrained_models_pytorch/pretrainedmodels/resnext_features/__pycache__/resnext101_64x4d_features.cpython-310.pyc new file mode 100644 index 0000000..f44911d Binary files /dev/null and b/pretrained_models_pytorch/pretrainedmodels/resnext_features/__pycache__/resnext101_64x4d_features.cpython-310.pyc differ diff --git a/pretrained_models_pytorch/pretrainedmodels/torchvision.py b/pretrained_models_pytorch/pretrainedmodels/torchvision.py index eb48d84..3084b38 100644 --- a/pretrained_models_pytorch/pretrainedmodels/torchvision.py +++ b/pretrained_models_pytorch/pretrainedmodels/torchvision.py @@ -16,7 +16,7 @@ 'densenet121': 'https://download.pytorch.org/models/densenet121-241335ed.pth', 'densenet169': 'https://download.pytorch.org/models/densenet169-6f0f7f60.pth', 'densenet201': 'https://download.pytorch.org/models/densenet201-4c113574.pth', - 'densenet161': 'https://download.pytorch.org/models/densenet161-17b70270.pth', + 'densenet161': 'https://download.pytorch.org/models/densenet161-17b70270.pth', 'inceptionv3': 'https://download.pytorch.org/models/inception_v3_google-1a9a5a14.pth', 'resnet18': 'https://download.pytorch.org/models/resnet18-5c106cde.pth', 'resnet34': 'https://download.pytorch.org/models/resnet34-333f7ec4.pth', @@ -77,9 +77,11 @@ # 'num_classes': 1000 # } + def load_pretrained(model, num_classes, settings): assert num_classes == settings['num_classes'], \ - "num_classes should be {}, but is {}".format(settings['num_classes'], num_classes) + "num_classes should be {}, but is {}".format( + settings['num_classes'], num_classes) model.load_state_dict(model_zoo.load_url(settings['url'])) model.input_space = settings['input_space'] model.input_size = settings['input_size'] @@ -164,6 +166,7 @@ def resnet18(num_classes=1000, pretrained='imagenet'): model = load_pretrained(model, num_classes, settings) return model + def resnet34(num_classes=1000, pretrained='imagenet'): """Constructs a ResNet-34 model. """ @@ -173,6 +176,7 @@ def resnet34(num_classes=1000, pretrained='imagenet'): model = load_pretrained(model, num_classes, settings) return model + def resnet50(num_classes=1000, pretrained='imagenet'): """Constructs a ResNet-50 model. """ @@ -182,6 +186,7 @@ def resnet50(num_classes=1000, pretrained='imagenet'): model = load_pretrained(model, num_classes, settings) return model + def resnet101(num_classes=1000, pretrained='imagenet'): """Constructs a ResNet-101 model. """ @@ -191,6 +196,7 @@ def resnet101(num_classes=1000, pretrained='imagenet'): model = load_pretrained(model, num_classes, settings) return model + def resnet152(num_classes=1000, pretrained='imagenet'): """Constructs a ResNet-152 model. """ @@ -212,6 +218,7 @@ def squeezenet1_0(num_classes=1000, pretrained='imagenet'): model = load_pretrained(model, num_classes, settings) return model + def squeezenet1_1(num_classes=1000, pretrained='imagenet'): r"""SqueezeNet 1.1 model from the `official SqueezeNet repo `_. diff --git a/test_patch.py b/test_patch.py new file mode 100644 index 0000000..dc28388 --- /dev/null +++ b/test_patch.py @@ -0,0 +1,134 @@ +import argparse +import os +import random +import numpy as np +import warnings + +import torch +import torch.nn as nn +import torch.nn.parallel +import torch.backends.cudnn as cudnn +import torch.optim as optim +import torch.utils.data +import torch.nn.functional as F +import torchvision.datasets as dset +import torchvision.transforms as transforms +import torchvision.utils as vutils +from torch.autograd import Variable +from torch.utils.data.sampler import SubsetRandomSampler + +from pretrained_models_pytorch import pretrainedmodels + +from utils import * + +parser = argparse.ArgumentParser() +parser.add_argument('--workers', type=int, + help='number of data loading workers', default=2) +parser.add_argument('--epochs', type=int, default=20, + help='number of epochs to train for') +parser.add_argument('--cuda', action='store_true', help='enables cuda') + +parser.add_argument('--target', type=int, default=859, + help='The target class: 859 == toaster') +parser.add_argument('--conf_target', type=float, default=0.9, + help='Stop attack on image when target classifier reaches this value for target class') + +parser.add_argument('--max_count', type=int, default=1000, + help='max number of iterations to find adversarial example') +parser.add_argument('--patch_type', type=str, default='circle', + help='patch type: circle or square') +parser.add_argument('--patch_size', type=float, default=0.05, + help='patch size. E.g. 0.05 ~= 5% of image ') + +parser.add_argument('--train_size', type=int, default=2000, + help='Number of training images') +parser.add_argument('--test_size', type=int, default=2000, + help='Number of test images') + +parser.add_argument('--image_size', type=int, default=299, + help='the height / width of the input image to network') + +parser.add_argument('--plot_all', type=int, default=1, + help='1 == plot all successful adversarial images') + +parser.add_argument('--netClassifier', default='inceptionv3', + help="The target classifier") + +parser.add_argument('--outf', default='./logs', + help='folder to output images and model checkpoints') +parser.add_argument('--manualSeed', type=int, default=1338, help='manual seed') + +opt = parser.parse_args() +print(opt) +warnings.simplefilter("ignore") + +try: + os.makedirs(opt.outf) +except OSError: + pass + +if opt.manualSeed is None: + opt.manualSeed = random.randint(1, 10000) +print("Random Seed: ", opt.manualSeed) +random.seed(opt.manualSeed) +np.random.seed(opt.manualSeed) +torch.manual_seed(opt.manualSeed) +device = torch.device('mps') + +# if opt.cuda: +# torch.cuda.manual_seed_all(opt.manualSeed) + +cudnn.benchmark = True + +if torch.cuda.is_available() and not opt.cuda: + print("WARNING: You have a CUDA device, so you should probably run with --cuda") + +target = opt.target +conf_target = opt.conf_target +max_count = opt.max_count +patch_type = opt.patch_type +patch_size = opt.patch_size +image_size = opt.image_size +train_size = opt.train_size +test_size = opt.test_size +plot_all = opt.plot_all + +assert train_size + \ + test_size <= 50000, "Traing set size + Test set size > Total dataset size" + +print("=> creating model ") +netClassifier = pretrainedmodels.__dict__[opt.netClassifier]( + num_classes=1000, pretrained='imagenet') +if opt.cuda: + netClassifier.to(device) + # netClassifier.cuda() + + +print('==> Preparing data..') +normalize = transforms.Normalize(mean=netClassifier.mean, + std=netClassifier.std) +idx = np.arange(50000) +np.random.shuffle(idx) +training_idx = idx[:train_size] +test_idx = idx[train_size:(test_size+train_size)] + + +test_loader = torch.utils.data.DataLoader( + dset.ImageFolder('./log_8', transforms.Compose([ + transforms.Resize(round(max(netClassifier.input_size)*1.050)), + transforms.CenterCrop(max(netClassifier.input_size)), + transforms.ToTensor(), + ToSpaceBGR(netClassifier.input_space == 'BGR'), + ToRange255(max(netClassifier.input_range) == 255), + normalize, + ])), + batch_size=1, shuffle=False, sampler=SubsetRandomSampler(test_idx), + num_workers=opt.workers, pin_memory=True) + +if __name__ == '__main__': + for batch_idx, (data, labels) in enumerate(test_loader): + data, labels = Variable(data), Variable(labels) + prediction = netClassifier(data) + print(prediction.data.max(1)[1][0]) + if batch_idx == 0: + break