def get_top_prediction(model_name, img): if isinstance(model_name, str): model, classes, layer = get_model_info(model_name) else: model = model_name logits = model(img) probs = F.softmax(logits, dim=1) prediction = probs.topk(1) return classes[prediction[1][0].detach().cpu().numpy()[0]]
def gen_grounding_lime_batch(imgs, model='resnet18', label_name='explanation', from_saved=True, target_index=1, layer='layer4', device=0, topk=True, classes=get_imagenet_classes(), save=True, save_path='./results/gradcam_examples/', show=True): #CUDA_VISIBLE_DEVICES=str(device) # Create result directory if it doesn't exist; all explanations should # be stored in a folder that is the predicted class if not os.path.exists(save_path): os.makedirs(save_path) if save: print('result path: {0}'.format(save_path)) if isinstance(model, str): model_name = model model, classes, target_layer = get_model_info(model, device=device) else: model_name = 'custom' # Generate the explanations masks = generate_lime_explanation_batch(imgs, model, pred_rank=1, positive_only=True, show=show, device='cuda:' + str(device)) cams = [] for mask, img in zip(masks, imgs): cams += [get_cam(img, mask)] if save: for i in range(len(imgs)): res_path = save_path + str(target_index[i].cpu().numpy()) + '/' if not os.path.exists(res_path): os.makedirs(res_path) #print("saving explanation mask....\n") cv2.imwrite(res_path + 'original_img.png', get_displ_img(imgs[i])) np.save(res_path + "lime_mask.npy", masks[i]) #just in case torch.cuda.empty_cache() return masks
def get_model_layer(model_name): return get_model_info(model_name)[2]
def get_model(model_name): return get_model_info(model_name)[0]
def gen_grounding_bp_batch(imgs, model='resnet18', label_name='explanation', from_saved=True, target_index=1, layer='layer4', device=0, topk=True, classes=get_imagenet_classes(), save=True, save_path='./results/gradcam_examples/', show=True): #CUDA_VISIBLE_DEVICES=str(device) # Create result directory if it doesn't exist; all explanations should # be stored in a folder that is the predicted class dateTimeObj = datetime.now() timestampStr = dateTimeObj.strftime("%d-%b-%Y_%H") if not os.path.exists(save_path): os.makedirs(save_path) if save: print('result path: {0}'.format(save_path)) if isinstance(model, str): model_name = model model, classes, target_layer = get_model_info(model, device=device) else: model_name = 'custom' # Generate the explanations if topk: masks = gen_bp(imgs, model, target_index=target_index, target_layer=layer, device=device, single=False, prep=False, classes=classes) else: masks = gen_bp_target(imgs, model, target_index=target_index, device=device, single=False, prep=False, classes=classes) cams = [] for mask, img in zip(masks, imgs): cams += [get_cam(img, mask)] if show: #plot heatmaps fig = plt.figure(figsize=(10, 10)) grid = ImageGrid( fig, 111, # similar to subplot(111) nrows_ncols=(2, 2), axes_pad=0.35, # pad between axes in inch. ) for ax, im in zip(grid, cams[:4]): ax.axis('off') # Iterating over the grid returns the Axes. ax.imshow(im) if save: for i in range(len(imgs)): res_path = save_path + str(target_index[i].cpu().numpy()) + '/' if not os.path.exists(res_path): os.makedirs(res_path) #print("saving explanation mask....\n") cv2.imwrite(res_path + 'original_img.png', get_displ_img(imgs[i])) cv2.imwrite(res_path + "bp_mask.png", np.uint8(cams[i] * 255)) np.save(res_path + "bp_mask.npy", masks[i]) #just in case torch.cuda.empty_cache() return masks
def gen_grounding(img, technique, model='resnet18', show=False, layer='layer4', save_path='./results/explanation', target_index=1, save=True, device=0, index=False): # Create result directory if it doesn't exist; all explanations should # be stored in a folder that is the predicted class if save_path[-1] != '/': save_path += '/' if save: if not os.path.exists(save_path): os.makedirs(save_path) print('result path: {0}'.format(save_path)) # convert image if needed if np.max(img) < 2: img = np.uint8(img * 255) if isinstance(model, str): model_name = model model, classes, layer = get_model_info(model, device=device) else: model_name = 'custom' model.eval() device = 'cuda:' + str(device) if not torch.cuda.is_available(): device = 'cpu' # Generate the explanations if technique == 'lime' or technique == 'LIME': if not index: mask = generate_lime_explanation(img, model, pred_rank=target_index, positive_only=True, device=device) else: mask = generate_lime_explanation(img, model, pred_rank=target_index, target_index=target_index, positive_only=True, device=device) elif technique == 'gradcam' or technique == 'GradCam' or technique == 'gcam': if not index: mask = gen_gcam([img], model, target_index=target_index, target_layer=layer) else: mask = gen_gcam_target([img], model, target_index=[target_index], target_layer=layer) elif technique == 'backprop' or technique == 'bp': if not index: mask = gen_bp([img], model, target_index=target_index) else: mask = gen_bp_target([img], model, target_index=[target_index]) elif technique == 'guided_backprop' or technique == 'gbp': if not index: mask = gen_gbp([img], model, target_index=target_index) else: mask = gen_gbp_target([img], model, target_index=[target_index]) elif technique == 'deconv' or technique == 'deconvolution': if not index: mask = gen_deconv([img], model, target_index=target_index) else: mask = gen_deconv_target([img], model, target_index=[target_index]) elif technique == 'ig' or technique == 'integrated-gradients': if not index: mask = generate_ig(img, model, cuda=device) else: mask = generate_ig(img, model, target_index=target_index, cuda=device) elif technique == 'rise' or technique == 'RISE': mask = gen_rise_grounding(img, model, index=target_index, device=device) else: print('ERROR: invalid explainability technique {0}'.format(technique)) return # For visualization, zero out bottom 90% of values if technique in ['bp', 'gbp', 'deconv', 'ig']: displ_mask = mask displ_mask[displ_mask < np.percentile(displ_mask, 90)] = 0 else: displ_mask = mask cam = get_cam(img, displ_mask) if show: plt.axis('off') cam = cv2.resize(cam, (224, 224)) plt.imshow(cam) if save: print("saving explanation mask....\n") np.save(os.path.join(save_path + 'original_img'), img) cv2.imwrite(os.path.join(save_path + 'original_img.png'), img) np.save(os.path.join(save_path + technique + '-' + model_name), mask) if not cv2.imwrite( os.path.join(save_path + technique + '-' + str(model_name) + ".png"), cam * 255): print('error saving explanation') print('saved to {0}'.format( os.path.join(save_path + technique + '-' + model_name))) return mask
def gen_grounding(img, technique, label_name='explanation', model='resnet18', show=False, reg=False, layer='layer4', save_path='./results/master_examples/', target_index=1, unique_id=None, patch=False, save=True, device=5, index=False): # Create result directory if it doesn't exist; all explanations should # be stored in a folder that is the predicted class save_path += label_name + '/' if not os.path.exists(save_path): os.makedirs(save_path) if patch: save_path = os.path.join(save_path + 'patch/') if not os.path.exists(save_path): os.makedirs(save_path) if save: print('result path: {0}'.format(save_path)) # convert image if needed if np.max(img) < 2: img = np.uint8(img * 255) if isinstance(model, str): model_name = model model, classes, layer = get_model_info(model, device=device) else: model_name = 'custom' model.eval() device = 'cuda:' + str(device) if not torch.cuda.is_available(): device = 'cpu' # Generate the explanations if technique == 'lime' or technique == 'LIME': if not index: mask = generate_lime_explanation(img, model, pred_rank=target_index, positive_only=True, device=device) else: mask = generate_lime_explanation(img, model, pred_rank=target_index, target_index=target_index, positive_only=True, device=device) elif technique == 'gradcam' or technique == 'GradCam' or technique == 'gcam': if not index: mask = gen_gcam([img], model, target_index=target_index, show_labels=True, target_layer=layer) else: mask = gen_gcam_target([img], model, target_index=[target_index], target_layer=layer) elif technique == 'backprop' or technique == 'bp': if not index: mask = gen_bp([img], model, target_index=target_index, show_labels=True, target_layer=layer) else: mask = gen_bp_target([img], model, target_index=[target_index]) elif technique == 'guided_backprop' or technique == 'gbp': if not index: mask = gen_gbp([img], model, target_index=target_index, show_labels=True, target_layer=layer) else: mask = gen_gbp_target([img], model, target_index=[target_index]) elif technique == 'ig' or technique == 'integrated-gradients': if not index: mask = generate_ig(img, model, cuda=device) else: mask = generate_ig(img, model, target_index=target_index, cuda=device) elif technique == 'rise' or technique == 'RISE': mask = gen_rise_grounding(img, model, index=target_index, device=device) else: print('ERROR: invalid explainability technique {0}'.format(technique)) return print('after ', mask.shape) cam = get_cam(img, mask) if show: plt.axis('off') cam = cv2.resize(cam, (224, 224)) plt.imshow(cam) if save: print("saving explanation mask....\n") np.save(os.path.join(save_path + 'original_img'), img) cv2.imwrite(os.path.join(save_path + 'original_img.png'), img) np.save(os.path.join(save_path + technique + '-' + model_name), mask) if not cv2.imwrite( os.path.join(save_path + technique + '-' + str(model_name) + ".png"), cam * 255): print('error saving explanation') print('saved to {0}'.format( os.path.join(save_path + technique + '-' + model_name))) return mask
def gen_adversarial_patch(img, model_name, label_name, save_path='./results/patch_imagenet/', show=True, save=True, device='cuda'): # Create result directory if it doesn't exist; all explanations sshould # be stored in a folder that is the predicted class save_path = save_path + str(label_name) + '/patch/' if not os.path.exists(save_path): os.makedirs(save_path) # Setting the seed for reproducibility for demo # Comment the below 4 lines for the target category to be random across runs #np.random.seed(1) #torch.manual_seed(1) #torch.backends.cudnn.deterministic = True #torch.backends.cudnn.benchmark = False # Can work with any model, but it assumes that the model has a feature method, # and a classifier method, as in the VGG models in torchvision pretrained_net, classes, net_layer = get_model_info(model_name) #gradcam_attack = GradCamAttack(model=pretrained_net, target_layer_names=[net_layer]) gradcam_reg_patch_attack = GradCamRegPatchAttack( model=pretrained_net, target_layer_names=[net_layer], device=device) #gradcam = GradCam(model=pretrained_net, target_layer_names=[net_layer]) pretrained_net = pretrained_net.to(device) pretrained_net = pretrained_net.eval() # Create result directory if it doesn't exist if save: if not os.path.exists(save_path): os.makedirs(save_path) # Read the input image and preprocess to a tensor #img = cv2.imread(args.image_path, 1) #img = np.float32(cv2.resize(img, (224, 224))) / 255 preprocessed_img = preprocess_image(img, device=device) # Get the original prediction index and the corresponding probability orig_index, orig_prob = forward_inference(pretrained_net, preprocessed_img) # Pick a random target from the remaining 999 categories excluding the original prediction list_of_idx = np.delete(np.arange(1000), orig_index) rand_idx = np.random.randint(999) target_index = list_of_idx[rand_idx] preprocess = transforms.Compose([ lambda x: Image.fromarray(x.astype('uint8'), 'RGB'), transforms.Resize((224, 224)), transforms.ToTensor(), # Normalization for ImageNet transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]), ]) # Compute the regular adv patch attack image and the corresponding GradCAM reg_patch_adv_img, reg_patch_adv_tensor = gradcam_reg_patch_attack( preprocessed_img, orig_index, target_index) test_img = np.uint8((reg_patch_adv_img / np.max(reg_patch_adv_img)) * 255) reg_patch_pred_index, reg_patch_pred_prob = forward_inference( pretrained_net, preprocess_image(preprocess(test_img[:, :, ::-1]), device=device)) print("original index: {0} adv index: {1}".format( orig_index, reg_patch_pred_index)) # save adversarial image if save: #cv2.imwrite(os.path.join(save_path + 'patch_image-%s.png'%datetime.now().strftime('%Y-%m-%d-%H-%M')), # np.uint8(255 * np.clip(reg_patch_adv_img[:, :, ::-1], 0, 1))) np.save( os.path.join(save_path + 'patch_image-%s.png' % datetime.now().strftime('%Y-%m-%d-%H-%M')), reg_patch_adv_img) # Generate the GradCAM heatmap for the target category using the regular patch adversarial image # reg_patch_adv_mask = gradcam(reg_patch_adv_tensor, target_index) #gcam_expl, reg_patch_adv_mask = gen_grounding(reg_patch_adv_img, 'vgg19_bn', 'gcam', label_name, show=True) if show: plt.imshow(reg_patch_adv_img) print('finished generating adveersarial patch') return reg_patch_adv_img, orig_index, target_index