-
Notifications
You must be signed in to change notification settings - Fork 20
/
Copy pathcollect_gradients.py
executable file
·165 lines (146 loc) · 9.87 KB
/
collect_gradients.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
collect_gradients.py
Front end for collecting maximum gradient norm samples
Copyright (C) 2017-2018, IBM Corp.
Copyright (C) 2017, Lily Weng <[email protected]>
and Huan Zhang <[email protected]>
This program is licenced under the Apache 2.0 licence,
contained in the LICENCE file in this directory.
"""
from __future__ import division
import numpy as np
import scipy.io as sio
import random
import time
import sys
import os
from functools import partial
from estimate_gradient_norm import EstimateLipschitz
from utils import generate_data
if __name__ == "__main__":
import argparse
parser = argparse.ArgumentParser(description = "Collect gradient norm samples for calculating CLEVER score",
formatter_class=argparse.ArgumentDefaultsHelpFormatter)
parser.add_argument("-d", "--dataset", choices=["mnist", "cifar", "imagenet"], default="mnist", help = "choose dataset")
parser.add_argument("-m", "--model_name", default="normal",
help = "Select model. For MNIST and CIFAR, options are: 2-layer (MLP), normal (7-layer CNN), distilled (7-layer CNN with defensive distillation), brelu (7-layer CNN with Bounded ReLU). For ImageNet, available options are: resnet_v2_50, resnet_v2_101, resnet_v2_152, inception_v1, inception_v2, inception_v3, inception_v4, inception_resnet_v2, vgg_16, vgg_19, mobilenet_v1_025, mobilenet_v1_050, mobilenet_v1_100, alexnet, nasnet_large, densenet121_k32, densenet169_k32, densenet161_k48")
parser.add_argument("--activation", type=str, choices=["relu", "tanh", "sigmoid", "elu", "softplus", "hard_sigmoid", "arctan"], help = "activation functions", default="relu")
parser.add_argument("-N", "--Nsamps", type=int, default=1024, help = "number of samples per iterations")
parser.add_argument("-i", "--Niters", type=int, default=500, help = "number of iterations. NITERS maximum gradient norms will be collected. A larger value will give a more accurate estimate")
parser.add_argument("-n", "--numimg", type=int, default=1, help = "number of test images to load from dataset")
parser.add_argument("--ids", default = "", help = "use a filelist of image IDs in CSV file for attack (UNSUPPORTED)")
parser.add_argument("--target_type", type=int, default=0b01111, help = "Binary mask for selecting targeted attack classes. bit0: top-2, bit1: random, bit2: least likely, bit3: use --ids override (UNSUPPORTED), bit4: use all labels (for untargeted)")
parser.add_argument("-f", "--firstimg", type=int, default=0, help = "start from which image in dataset")
parser.add_argument("--transform", default="", help = "input transformation function (defend_reduce, defend_jpeg, defend_png)")
parser.add_argument("--order", type = int, default=1, choices=[1,2], help = "1: first order bound, 2: second order bound for twice differentiable activations")
parser.add_argument("--compute_slope", action='store_true', help = "collect slope estimate")
parser.add_argument("--sample_norm", type=str, choices=["l2", "li", "l1"], help = "norm of sampling ball (l2, l1 or li)", default="l2")
parser.add_argument("--fix_dirty_bug", action='store_true', help = "do not use (UNSUPPORTED)")
parser.add_argument("-b", "--batch_size", type=int, default=0, help = "batch size to run model. 0: use default batch size")
parser.add_argument("--nthreads", type=int, default=0, help = "number of threads for generating random samples in sphere")
parser.add_argument("-s", "--save", default="./lipschitz_mat", help = "results output path")
parser.add_argument("--seed", type=int, default = 1215, help = "random seed")
args = vars(parser.parse_args())
print(args)
seed = args['seed']
Nsamp = args['Nsamps'];
Niters = args['Niters'];
dataset = args['dataset']
model_name = args['model_name']
start = args['firstimg']
numimg = args['numimg']
save_path = args['save']
total = 0
random.seed(seed)
np.random.seed(seed)
# create output directory
os.system("mkdir -p {}/{}_{}".format(save_path, dataset, model_name))
# create a Lipschitz estimator class (initial it early to save multiprocessing memory)
clever_estimator = EstimateLipschitz(sess=None, nthreads=args['nthreads'])
# import the ID lists
if args['ids']:
import pandas as pd
df = pd.read_csv(args['ids'], sep = "\t")
# don't use this
if args['fix_dirty_bug']:
df = df[df['new_class'] != df['target']]
ids = list(df['id'])
target_type = args['target_type']
# use the target classes override
if target_type & 0b1000 != 0:
target_classes = [[t] for t in list(df['target'])]
else:
# use generated classes
target_classes = None
else:
ids = None
target_classes = None
target_type = args['target_type']
import tensorflow as tf
from setup_cifar import CIFAR
from setup_mnist import MNIST
from setup_imagenet import ImageNet
tf.set_random_seed(seed)
config = tf.ConfigProto()
config.gpu_options.allow_growth=True
with tf.Session(config=config) as sess:
clever_estimator.sess = sess
# returns the input tensor and output prediction vector
img, output = clever_estimator.load_model(dataset, model_name, activation = args['activation'], batch_size = args['batch_size'], compute_slope = args['compute_slope'], order = args['order'])
# load dataset
datasets_loader = {"mnist": MNIST, "cifar": CIFAR, "imagenet": partial(ImageNet, clever_estimator.model.image_size)}
data = datasets_loader[dataset]()
# for prediction
predictor = lambda x: np.squeeze(sess.run(output, feed_dict = {img: x}))
# generate target images
inputs, targets, true_labels, true_ids, img_info = generate_data(data, samples=numimg, targeted=True,
start=start, predictor=predictor,
random_and_least_likely = True,
ids = ids, target_classes = target_classes, target_type = target_type,
imagenet="imagenet" in dataset,
remove_background_class="imagenet" in dataset and
("vgg" in model_name or "densenet" in model_name or "alexnet" in model_name))
timestart = time.time()
print("got {} images".format(inputs.shape))
for i, input_img in enumerate(inputs):
# original_predict = np.squeeze(sess.run(output, feed_dict = {img: [input_img]}))
print("processing image {}".format(i))
original_predict = predictor([input_img])
true_label = np.argmax(true_labels[i])
predicted_label = np.argmax(original_predict)
least_likely_label = np.argmin(original_predict)
original_prob = np.sort(original_predict)
original_class = np.argsort(original_predict)
print("Top-10 classifications:", original_class[-1:-11:-1])
print("True label:", true_label)
print("Top-10 probabilities/logits:", original_prob[-1:-11:-1])
print("Most unlikely classifications:", original_class[:10])
print("Most unlikely probabilities/logits:", original_prob[:10])
if true_label != predicted_label:
print("[WARNING] This image is classfied wrongly by the classifier! Skipping!")
continue
total += 1
# set target class
target_label = np.argmax(targets[i]);
print('Target class: ', target_label)
sys.stdout.flush()
if args['order'] == 1:
[L2_max,L1_max,Li_max,G2_max,G1_max,Gi_max,g_x0,pred] = clever_estimator.estimate(input_img, true_label, target_label, Nsamp, Niters, args['sample_norm'], args['transform'], args['order'])
print("[STATS][L1] total = {}, seq = {}, id = {}, time = {:.3f}, true_class = {}, target_class = {}, info = {}".format(total, i, true_ids[i], time.time() - timestart, true_label, target_label, img_info[i]))
# save to sampling results to matlab ;)
mat_path = "{}/{}_{}/{}_{}_{}_{}_{}_{}_{}_order{}.mat".format(save_path, dataset, model_name, Nsamp, Niters, true_ids[i], true_label, target_label, img_info[i], args['activation'], args['order'])
save_dict = {'L2_max': L2_max, 'L1_max': L1_max, 'Li_max': Li_max, 'G2_max': G2_max, 'G1_max': G1_max, 'Gi_max': Gi_max, 'pred': pred, 'g_x0': g_x0, 'id': true_ids[i], 'true_label': true_label, 'target_label': target_label, 'info':img_info[i], 'args': args, 'path': mat_path}
sio.savemat(mat_path, save_dict)
print('saved to', mat_path)
sys.stdout.flush()
elif args['order'] == 2:
[H2_max,g_x0,g_x0_grad_2_norm,g_x0_grad_1_norm,g_x0_grad_inf_norm,pred] = clever_estimator.estimate(input_img, true_label, target_label, Nsamp, Niters, args['sample_norm'], args['transform'], args['order'])
print("[STATS][L1] total = {}, seq = {}, id = {}, time = {:.3f}, true_class = {}, target_class = {}, info = {}".format(total, i, true_ids[i], time.time() - timestart, true_label, target_label, img_info[i]))
# save to sampling results to matlab ;)
mat_path = "{}/{}_{}/{}_{}_{}_{}_{}_{}_{}_order{}.mat".format(save_path, dataset, model_name, Nsamp, Niters, true_ids[i], true_label, target_label, img_info[i], args['activation'], args['order'])
save_dict = {'H2_max': H2_max, 'pred': pred, 'g_x0': g_x0, 'id': true_ids[i], 'true_label': true_label, 'target_label': target_label, 'info':img_info[i], 'args': args, 'path': mat_path, 'g_x0_grad_2_norm': g_x0_grad_2_norm}
sio.savemat(mat_path, save_dict)
print('saved to', mat_path)
sys.stdout.flush()