-
Notifications
You must be signed in to change notification settings - Fork 18
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
c361f2a
commit 23586d9
Showing
19 changed files
with
737 additions
and
0 deletions.
There are no files selected for viewing
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
import numpy as np | ||
|
||
def find_mask(x, p=2/32): | ||
sp=x.shape | ||
h=int(sp[0]*p) | ||
if h<1: h=1 | ||
tmp_x=x.copy() | ||
bg_x=x.copy() | ||
|
||
for iindex, _ in np.ndenumerate(x): | ||
i0=iindex[0] | ||
i1=iindex[1] | ||
region=tmp_x[ np.max([i0-h,0]) : np.min([i0+h, sp[0]]), np.max([i1-h,0]):np.min([i1+h,sp[1]])] | ||
v=np.min(region) | ||
for j in range(0, (sp[2])): | ||
#bg_x[i0][i1][j]=v | ||
bg_x[i0][i1][j]=np.mean(region[:,:,j]) | ||
|
||
return bg_x |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,138 @@ | ||
|
||
from keras.preprocessing import image | ||
from keras.applications import vgg16 | ||
from keras.applications.vgg16 import VGG16 | ||
from keras.applications import inception_v3, mobilenet, xception | ||
from keras.models import load_model | ||
import matplotlib.pyplot as plt | ||
|
||
import argparse | ||
import os | ||
import numpy as np | ||
|
||
from utils import * | ||
from to_explain import * | ||
|
||
def main(): | ||
parser=argparse.ArgumentParser(description='To explain neural network decisions' ) | ||
parser.add_argument( | ||
'--model', dest='model', default='-1', help='the input neural network model (.h5)') | ||
parser.add_argument("--inputs", dest="inputs", default="-1", | ||
help="the input test data directory", metavar="DIR") | ||
parser.add_argument("--outputs", dest="outputs", default="outs", | ||
help="the outputput test data directory", metavar="DIR") | ||
parser.add_argument("--measures", dest="measures", default=['tarantula', 'zoltar', 'ochiai', 'wong-ii'], | ||
help="the measures", metavar="zoltar, tarantula ...", nargs='+') | ||
parser.add_argument("--measure", dest="measure", default="None", | ||
help="the measure", metavar="zoltar, tarantula ...") | ||
parser.add_argument("--mnist-dataset", dest="mnist", help="MNIST dataset", action="store_true") | ||
parser.add_argument("--normalized-input", dest="normalized", help="To normalize the input", action="store_true") | ||
parser.add_argument("--cifar10-dataset", dest="cifar10", help="CIFAR-10 dataset", action="store_true") | ||
parser.add_argument("--grayscale", dest="grayscale", help="MNIST dataset", action="store_true") | ||
parser.add_argument("--vgg16-model", dest='vgg16', help="vgg16 model", action="store_true") | ||
parser.add_argument("--inception-v3-model", dest='inception_v3', help="inception v3 model", action="store_true") | ||
parser.add_argument("--xception-model", dest='xception', help="Xception model", action="store_true") | ||
parser.add_argument("--mobilenet-model", dest='mobilenet', help="mobilenet model", action="store_true") | ||
parser.add_argument("--attack", dest='attack', help="to atatck", action="store_true") | ||
parser.add_argument("--text-only", dest='text_only', help="for efficiency", action="store_true") | ||
parser.add_argument("--input-rows", dest="img_rows", default="224", | ||
help="input rows", metavar="INT") | ||
parser.add_argument("--input-cols", dest="img_cols", default="224", | ||
help="input cols", metavar="INT") | ||
parser.add_argument("--input-channels", dest="img_channels", default="3", | ||
help="input channels", metavar="INT") | ||
parser.add_argument("--top-classes", dest="top_classes", default="1", | ||
help="check the top-xx classifications", metavar="INT") | ||
parser.add_argument("--adversarial-ub", dest="adv_ub", default="1.", | ||
help="upper bound on the adversarial percentage (0, 1]", metavar="FLOAT") | ||
parser.add_argument("--adversarial-lb", dest="adv_lb", default="0.", | ||
help="lower bound on the adversarial percentage (0, 1]", metavar="FLOAT") | ||
parser.add_argument("--adversarial-value", dest="adv_value", default="234", | ||
help="adversarial value", metavar="FLOAT") | ||
parser.add_argument("--testgen-factor", dest="testgen_factor", default="0.2", | ||
help="test generation factor (0, 1]", metavar="FLOAT") | ||
parser.add_argument("--testgen-size", dest="testgen_size", default="2000", | ||
help="testgen size ", metavar="INT") | ||
parser.add_argument("--testgen-iterations", dest="testgen_iter", default="1", | ||
help="to control the testgen iteration", metavar="INT") | ||
|
||
args=parser.parse_args() | ||
|
||
img_rows, img_cols, img_channels = int(args.img_rows), int(args.img_cols), int(args.img_channels) | ||
|
||
## some common used datasets | ||
if args.mnist: | ||
img_rows, img_cols, img_channels = 28, 28, 1 | ||
elif args.cifar10: | ||
img_rows, img_cols, img_channels = 32, 32, 3 | ||
elif args.inception_v3 or args.xception: | ||
img_rows, img_cols, img_channels = 299, 299, 3 | ||
|
||
## to load the input DNN model | ||
if args.model!='-1': | ||
dnn=load_model(args.model) | ||
elif args.vgg16: | ||
print ('to load VGG16') | ||
dnn=VGG16() | ||
print ('done') | ||
elif args.mobilenet: | ||
dnn=mobilenet.MobileNet() | ||
elif args.inception_v3: | ||
dnn=inception_v3.InceptionV3() | ||
elif args.xception: | ||
dnn=xception.Xception() | ||
else: | ||
raise Exception ('A DNN model needs to be provided...') | ||
|
||
## to load the input data | ||
fnames=[] | ||
xs=[] | ||
if args.inputs!='-1': | ||
for path, subdirs, files in os.walk(args.inputs): | ||
for name in files: | ||
fname=(os.path.join(path, name)) | ||
if fname.endswith('.jpg') or fname.endswith('.png') or fname.endswith('.JPEG'): | ||
if args.grayscale is True or args.mnist: | ||
x=image.load_img(fname, target_size=(img_rows, img_cols), color_mode = "grayscale") | ||
x=np.expand_dims(x,axis=2) | ||
else: | ||
x=image.load_img(fname, target_size=(img_rows, img_cols)) | ||
x=np.expand_dims(x,axis=0) | ||
xs.append(x) | ||
fnames.append(fname) | ||
else: | ||
raise Exception ('What do you want me to do?') | ||
xs=np.vstack(xs) | ||
xs = xs.reshape(xs.shape[0], img_rows, img_cols, img_channels) | ||
print ('Total data loaded:', len(xs)) | ||
|
||
eobj=explain_objectt(dnn, xs) | ||
eobj.outputs=args.outputs | ||
eobj.top_classes=int(args.top_classes) | ||
eobj.adv_ub=float(args.adv_ub) | ||
eobj.adv_lb=float(args.adv_lb) | ||
eobj.adv_value=float(args.adv_value) | ||
eobj.testgen_factor=float(args.testgen_factor) | ||
eobj.testgen_size=int(args.testgen_size) | ||
eobj.testgen_iter=int(args.testgen_iter) | ||
eobj.vgg16=args.vgg16 | ||
eobj.mnist=args.mnist | ||
eobj.cifar10=args.cifar10 | ||
eobj.inception_v3=args.inception_v3 | ||
eobj.xception=args.xception | ||
eobj.mobilenet=args.mobilenet | ||
eobj.attack=args.attack | ||
eobj.text_only=args.text_only | ||
eobj.normalized=args.normalized | ||
eobj.fnames=fnames | ||
measures = [] | ||
if not args.measure=='None': | ||
measures.append(args.measure) | ||
else: measures = args.measures | ||
eobj.measures=measures | ||
|
||
to_explain(eobj) | ||
|
||
if __name__=="__main__": | ||
main() | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,138 @@ | ||
import numpy as np | ||
from utils import * | ||
|
||
def spectra_sym_gen(eobj, x, y, adv_value=1, testgen_factor=.2, testgen_size=0): | ||
|
||
|
||
v_type=type(adv_value) | ||
model=eobj.model | ||
failing=[] | ||
passing=[] | ||
|
||
#inputs=[] | ||
sp=x.shape | ||
x_flag=np.zeros(sp, dtype=bool) | ||
portion=int(sp[0]*testgen_factor) | ||
incr=1/6*portion | ||
if portion<1: portion=1 | ||
L0=np.array(np.arange(x.size)) | ||
L0=np.reshape(L0, sp) | ||
|
||
while (not np.all(x_flag)) or len(passing)+len(failing)<testgen_size: | ||
#print ('####', len(passing), len(failing)) | ||
t=x.copy() | ||
|
||
i0=np.random.randint(0,sp[0]) | ||
i1=np.random.randint(0,sp[1]) | ||
|
||
h=portion | ||
region=L0[ np.max([i0-h,0]) : np.min([i0+h, sp[0]]), np.max([i1-h,0]):np.min([i1+h,sp[1]])].flatten() | ||
|
||
L=region #L0[0:portion] | ||
if v_type==np.ndarray: | ||
np.put(t, L, adv_value.take(L)) | ||
else: | ||
np.put(t, L, adv_value) | ||
x_flag.flat[L]=True #np.put(x, L, True) | ||
new_y=np.argsort(model.predict(sbfl_preprocess(eobj, np.array([t]))))[0][-eobj.top_classes:] | ||
is_adv=(len(np.intersect1d(y, new_y))==0) | ||
|
||
if is_adv: | ||
failing.append(t) | ||
## to find a passing | ||
ite=h #testgen_factor | ||
while ite>1: #ite>0.01: | ||
t2=x.copy() | ||
#ite=ite-1#ite//2 #ite=(ite+0)/2 | ||
ite=int(ite-incr) | ||
if ite<1: break | ||
region=L0[ np.max([i0-ite,0]) : np.min([i0+ite, sp[0]]), np.max([i1-ite,0]):np.min([i1+ite,sp[1]])].flatten() | ||
|
||
L=region #L0[0:portion] | ||
if v_type==np.ndarray: | ||
np.put(t, L, adv_value.take(L)) | ||
else: | ||
np.put(t, L, adv_value) | ||
x_flag.flat[L]=True #np.put(x, L, True) | ||
new_y=np.argsort(model.predict(sbfl_preprocess(eobj, np.array([t]))))[0][-eobj.top_classes:] | ||
#is_adv=(len(np.intersect1d(y, new_y))==0) | ||
#ite-=0.01 | ||
#L2=L0[0:int(ite/testgen_factor*portion)] | ||
#if v_type==np.ndarray: | ||
# np.put(t2, L2, adv_value.take(L2)) | ||
#else: | ||
# np.put(t2, L2, adv_value) | ||
#new_y=np.argsort(model.predict(sbfl_preprocess(eobj, np.array([t2]))))[0][-eobj.top_classes:] | ||
##print (y, new_y) | ||
if (len(np.intersect1d(y, new_y))!=0): | ||
passing.append(t2) | ||
break | ||
|
||
else: | ||
passing.append(t) | ||
## to find a failing | ||
ite=h #testgen_factor | ||
while ite<sp[0]/2: #0.99: | ||
t2=x.copy() | ||
#ite=ite+1#ite*2 | ||
ite=int(ite+incr) | ||
if ite>sp[0]/2: break | ||
region=L0[ np.max([i0-ite,0]) : np.min([i0+ite, sp[0]]), np.max([i1-ite,0]):np.min([i1+ite,sp[1]])].flatten() | ||
|
||
L=region #L0[0:portion] | ||
if v_type==np.ndarray: | ||
np.put(t, L, adv_value.take(L)) | ||
else: | ||
np.put(t, L, adv_value) | ||
x_flag.flat[L]=True #np.put(x, L, True) | ||
new_y=np.argsort(model.predict(sbfl_preprocess(eobj, np.array([t]))))[0][-eobj.top_classes:] | ||
#t2=x.copy() | ||
#ite=(ite+1)/2 | ||
##ite+=0.01 | ||
#L2=L0[0:int(ite/testgen_factor*portion)] | ||
#if v_type==np.ndarray: | ||
# np.put(t2, L2, adv_value.take(L2)) | ||
#else: | ||
# np.put(t2, L2, adv_value) | ||
#new_y=np.argsort(model.predict(sbfl_preprocess(eobj, np.array([t2]))))[0][-eobj.top_classes:] | ||
if (len(np.intersect1d(y, new_y))==0): | ||
failing.append(t2) | ||
x_flag.flat[L]=True | ||
break | ||
|
||
return np.array(passing), np.array(failing) | ||
|
||
def spectra_gen(x, adv_value=1, testgen_factor=0.01, testgen_size=0): | ||
|
||
#print (adv_value, testgen_factor, testgen_size) | ||
v_type=type(adv_value) | ||
|
||
inputs=[] | ||
sp=x.shape | ||
x_flag=np.zeros(sp, dtype=bool) | ||
portion=int(x.size*testgen_factor) #int(x.size/sp[2]*testgen_factor) | ||
|
||
while (not np.all(x_flag)) or len(inputs)<testgen_size: | ||
t=x.copy() | ||
L=np.random.choice(x.size, portion) | ||
if v_type==np.ndarray: | ||
#t.flat[L]=adv_value.take(L) | ||
np.put(t, L, adv_value.take(L)) | ||
else: | ||
#t.flat[L]=adv_value | ||
np.put(t, L, adv_value) | ||
x_flag.flat[L]=True #np.put(x, L, True) | ||
#for pos in L: | ||
# ipos=np.unravel_index(pos,sp) | ||
# #if v_type==np.ndarray: | ||
# # t.flat[pos]=adv_value.flat[pos] | ||
# #else: t.flat[pos]=adv_value | ||
# #x_flag.flat[pos]=True #np.put(x, L, True) | ||
# for j in range(0, sp[2]): | ||
# if v_type==np.ndarray: | ||
# t[ipos[0]][ipos[1]][j]=adv_value[ipos[0]][ipos[1]][j] | ||
# else: | ||
# t[ipos[0]][ipos[1]][j]=adv_value | ||
# x_flag[ipos[0]][ipos[1]][j]=True | ||
inputs.append(t) | ||
return inputs |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
|
||
import numpy as np | ||
from utils import * | ||
from sbfl import * | ||
|
||
def to_attack(eobj, ind, origin_data, bg_v, init_step, step_incr): | ||
|
||
v_type=type(bg_v) | ||
|
||
top_classes=eobj.top_classes | ||
sp=origin_data.shape | ||
|
||
x=origin_data | ||
model=eobj.model | ||
y=np.argsort(model.predict(sbfl_preprocess(eobj,np.array([x]))))[0][-top_classes:] | ||
|
||
latest_step=ind.size | ||
|
||
#im=np.ones(sp) | ||
#im=np.multiply(im, bg_v) | ||
im=x.copy() | ||
im_flag=np.zeros(im.shape, dtype=bool) | ||
|
||
pos=ind.size-1 | ||
old_count=1 | ||
count=1 | ||
|
||
adv_v=0 | ||
|
||
while pos>=0: | ||
|
||
ipos=np.unravel_index(ind[pos], sp) | ||
if not im_flag[ipos]: | ||
for k in range(0,sp[2]): | ||
if type(bg_v)==np.ndarray: | ||
im[ipos[0]][ipos[1]][k]=bg_v[ipos[0]][ipos[1]][k] | ||
else: | ||
im[ipos[0]][ipos[1]][k]=bg_v | ||
im_flag[ipos[0]][ipos[1]][k]=True | ||
count+=1 | ||
|
||
pos-=1 | ||
|
||
if count<init_step: continue ## to start from a partial image | ||
|
||
if count>5000: break | ||
|
||
if count-old_count>=step_incr: | ||
old_count=count | ||
|
||
adv_v=model.predict(sbfl_preprocess(eobj, np.array([im]))) | ||
adv_y=np.argsort(adv_v)[0][-top_classes:] | ||
if len(np.intersect1d(y, adv_y))==0: | ||
#if np.sort(adv_v)[0][-top_classes:][0]>.5: | ||
return im, count, np.sort(adv_v)[0][-top_classes:] | ||
|
||
return x, x.size//sp[2], [None] | ||
|
Oops, something went wrong.