No account yet ?
A salience map is an image that highlights the region on which people's gaze is focused.
Tested in Anaconda and Python 3.7
import tensorflow as tf print("TensorFlow version: {}".format(tf.__version__)) print("Eager execution: {}".format(tf.executing_eagerly())) from keras.preprocessing import image from keras import applications from keras.applications.vgg16 import preprocess_input, decode_predictions from keras import backend as K import numpy as np import matplotlib.pyplot as plt import cv2 # build the VGG16 network model = applications.VGG16(include_top=True, weights='imagenet') # get the symbolic outputs of each "key" layer layer_dict = dict([(layer.name, layer) for layer in model.layers]) for layer in model.layers: print(layer.name) img_path = 'Chien-01.jpg' img = image.load_img(img_path, target_size=(224, 224)) x = image.img_to_array(img) print('image.img_to_array: ', x.shape, np.max(x), np.min(x)) x = np.expand_dims(x, axis=0) print('expand_dims: ', x.shape, np.max(x), np.min(x)) x = preprocess_input(x) print('preprocess_input: ', x.shape, np.max(x), np.min(x)) # util function to convert a tensor into a valid image def tensor2image(x): x -= x.mean() x /= (x.std() + 1e-5) x *= 0.2 # clip to [0, 1] x += 0.5 x = np.clip(x, 0, 1) # convert to RGB array x *= 255 x = np.clip(x, 0, 255).astype('uint8') return x preds = model.predict(x) # Get results into a list of tuples (class, description, probability) print('Predicted:', decode_predictions(preds, top=3)[0]) model_out = K.mean(layer_dict['fc2'].output) # compute the gradient of the input picture wrt this loss grads = K.gradients(model_out, model.input)[0] # Normalize the gradient grads /= K.std(grads) + 1e-8 # function: returns the loss and grads given the input picture model_predictor = K.function([model.input], [model_out, grads]) # feed the image to the network model_outputs, grads_values = model_predictor([x]) # get the grads that have the same shape as the input image abs_grads_values = np.abs(grads_values) sm = tensor2image(abs_grads_values[0]) print(sm.shape) # let's see the grads as an image gs = sm[:,:,0] + sm[:,:,1] + sm[:,:,2] gs[gs<150] = 0 plt.figure(figsize=(6,6)) plt.imshow(gs) plt.axis('off') plt.colorbar() x1 = image.img_to_array(img).astype('uint8') concan = np.concatenate((x1, sm), axis=0) plt.figure(figsize=(12,12)) plt.axis('off') plt.imshow(concan)
see-inside-cnn
Copyright (c) 2020 Ibrahim Sobh
CAM Visualization
Guided Backpropagation Visualization
Keras-CNNVisualization
Copyright (c) 2018 YoungJin Kim
Visualizing CNNs
Visualizing-CNNs - GitHub
GradCam pytorch
Tested in Anaconda and Python 3.7
import argparse import cv2 import numpy as np import torch from torch.autograd import Function from torchvision import models class FeatureExtractor(): """ Class for extracting activations and registering gradients from targetted intermediate layers """ def __init__(self, model, target_layers): self.model = model self.target_layers = target_layers self.gradients = [] def save_gradient(self, grad): self.gradients.append(grad) def __call__(self, x): outputs = [] self.gradients = [] for name, module in self.model._modules.items(): x = module(x) if name in self.target_layers: x.register_hook(self.save_gradient) outputs += [x] return outputs, x class ModelOutputs(): """ Class for making a forward pass, and getting: 1. The network output. 2. Activations from intermeddiate targetted layers. 3. Gradients from intermeddiate targetted layers. """ def __init__(self, model, feature_module, target_layers): self.model = model self.feature_module = feature_module self.feature_extractor = FeatureExtractor(self.feature_module, target_layers) def get_gradients(self): return self.feature_extractor.gradients def __call__(self, x): target_activations = [] for name, module in self.model._modules.items(): if module == self.feature_module: target_activations, x = self.feature_extractor(x) elif "avgpool" in name.lower(): x = module(x) x = x.view(x.size(0), -1) else: x = module(x) return target_activations, x def preprocess_image(img): means = [0.485, 0.456, 0.406] stds = [0.229, 0.224, 0.225] preprocessed_img = img.copy()[:, :, ::-1] for i in range(3): preprocessed_img[:, :, i] = preprocessed_img[:, :, i] - means[i] preprocessed_img[:, :, i] = preprocessed_img[:, :, i] / stds[i] preprocessed_img = \ np.ascontiguousarray(np.transpose(preprocessed_img, (2, 0, 1))) preprocessed_img = torch.from_numpy(preprocessed_img) preprocessed_img.unsqueeze_(0) input = preprocessed_img.requires_grad_(True) return input def show_cam_on_image(img, mask): heatmap = cv2.applyColorMap(np.uint8(255 * mask), cv2.COLORMAP_JET) heatmap = np.float32(heatmap) / 255 cam = heatmap + np.float32(img) cam = cam / np.max(cam) cv2.imwrite("cam.jpg", np.uint8(255 * cam)) class GradCam: def __init__(self, model, feature_module, target_layer_names, use_cuda): self.model = model self.feature_module = feature_module self.model.eval() self.cuda = use_cuda if self.cuda: self.model = model.cuda() self.extractor = ModelOutputs(self.model, self.feature_module, target_layer_names) def forward(self, input): return self.model(input) def __call__(self, input, index=None): if self.cuda: features, output = self.extractor(input.cuda()) else: features, output = self.extractor(input) if index is None: index = np.argmax(output.cpu().data.numpy()) one_hot = torch.zeros_like(output) one_hot[0][index] = 1 if self.cuda: one_hot = torch.sum(one_hot.cuda() * output) else: one_hot = torch.sum(one_hot * output) self.feature_module.zero_grad() self.model.zero_grad() one_hot.backward(retain_graph=True) grads_val = self.extractor.get_gradients()[-1].cpu().data.numpy() target = features[-1] target = target.cpu().data.numpy()[0, :] weights = np.mean(grads_val, axis=(2, 3))[0, :] cam = np.zeros(target.shape[1:], dtype=np.float32) for i, w in enumerate(weights): cam += w * target[i, :, :] cam = np.maximum(cam, 0) cam = cv2.resize(cam, input.shape[2:]) cam = cam - np.min(cam) cam = cam / np.max(cam) return cam class GuidedBackpropReLU(Function): @staticmethod def forward(self, input): positive_mask = (input > 0).type_as(input) output = torch.addcmul(torch.zeros(input.size()).type_as(input), input, positive_mask) self.save_for_backward(input, output) return output @staticmethod def backward(self, grad_output): input, output = self.saved_tensors grad_input = None positive_mask_1 = (input > 0).type_as(grad_output) positive_mask_2 = (grad_output > 0).type_as(grad_output) grad_input = torch.addcmul(torch.zeros(input.size()).type_as(input), torch.addcmul(torch.zeros(input.size()).type_as(input), grad_output, positive_mask_1), positive_mask_2) return grad_input class GuidedBackpropReLUModel: def __init__(self, model, use_cuda): self.model = model self.model.eval() self.cuda = use_cuda if self.cuda: self.model = model.cuda() def recursive_relu_apply(module_top): for idx, module in module_top._modules.items(): recursive_relu_apply(module) if module.__class__.__name__ == 'ReLU': module_top._modules[idx] = GuidedBackpropReLU.apply # replace ReLU with GuidedBackpropReLU recursive_relu_apply(self.model) def forward(self, input): return self.model(input) def __call__(self, input, index=None): if self.cuda: output = self.forward(input.cuda()) else: output = self.forward(input) if index == None: index = np.argmax(output.cpu().data.numpy()) one_hot = torch.zeros_like(output) one_hot[0][index] = 1 if self.cuda: one_hot = torch.sum(one_hot.cuda() * output) else: one_hot = torch.sum(one_hot * output) # self.model.features.zero_grad() # self.model.classifier.zero_grad() one_hot.backward(retain_graph=True) output = input.grad.cpu().data.numpy() output = output[0, :, :, :] return output def get_args(): parser = argparse.ArgumentParser() parser.add_argument('--use-cuda', action='store_true', default=False, help='Use NVIDIA GPU acceleration') parser.add_argument('--image-path', type=str, default='./examples/both.png', help='Input image path') args = parser.parse_args() args.use_cuda = args.use_cuda and torch.cuda.is_available() if args.use_cuda: print("Using GPU for acceleration") else: print("Using CPU for computation") return args def deprocess_image(img): """ see https://github.com/jacobgil/keras-grad-cam/blob/master/grad-cam.py#L65 """ img = img - np.mean(img) img = img / (np.std(img) + 1e-5) img = img * 0.1 img = img + 0.5 img = np.clip(img, 0, 1) return np.uint8(img * 255) def image2tensor(frame): img = torch.from_numpy(frame).float() img = img.div(255.0) img = img.unsqueeze(0) img = img.permute(0, 3, 1, 2) return img if __name__ == '__main__': """ python grad_cam.py <path_to_image> 1. Loads an image with opencv. 2. Preprocesses it for VGG19 and converts to a pytorch variable. 3. Makes a forward pass to find the category index with the highest score, and computes intermediate activations. Makes the visualization. """ args = get_args() # 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. model = models.vgg16(pretrained=True) print(model) grad_cam = GradCam(model=model, feature_module=model.features, \ target_layer_names=["30"], use_cuda=args.use_cuda) img = cv2.imread(args.image_path, 1) img = np.float32(cv2.resize(img, (224, 224))) / 255 input = preprocess_image(img) # If None, returns the map for the highest scoring category. # Otherwise, targets the requested index. target_index = None print(input.shape) mask = grad_cam(input, target_index) show_cam_on_image(img, mask) gb_model = GuidedBackpropReLUModel(model=model, use_cuda=args.use_cuda) print(model._modules.items()) gb = gb_model(input, index=target_index) gb = gb.transpose((1, 2, 0)) cam_mask = cv2.merge([mask, mask, mask]) cam_gb = deprocess_image(cam_mask * gb) gb = deprocess_image(gb) cv2.imwrite('gb.jpg', gb) cv2.imwrite('cam_gb.jpg', cam_gb)
GradCam_pytorch
Copyright (c) 2020 Jacob Gildenblat
Vanilla gradient - Guided backpropagation - Integrated gradient
Tested in Anaconda and Python 3.7
from keras.applications.vgg16 import VGG16 import numpy as np from keras.applications.resnet50 import decode_predictions import PIL.Image from matplotlib import pylab as plt def show_image(image, grayscale = True, ax=None, title=''): if ax is None: plt.figure() plt.axis('off') if len(image.shape) == 2 or grayscale == True: if len(image.shape) == 3: image = np.sum(np.abs(image), axis=2) vmax = np.percentile(image, 99) vmin = np.min(image) plt.imshow(image, cmap=plt.cm.gray, vmin=vmin, vmax=vmax) plt.title(title) else: image = image + 127.5 image = image.astype('uint8') plt.imshow(image) plt.title(title) def load_image(file_path): im = PIL.Image.open(file_path) im = np.asarray(im) return im - 127.5 # Load and compile the model model = VGG16(weights='imagenet') model.compile(loss='mean_squared_error', optimizer='adam') # Load an image and make the prediction img_path = 'images/doberman.png' img = load_image(img_path) show_image(img, grayscale=False) plt.show() x = np.expand_dims(img, axis=0) preds = model.predict(x) label = np.argmax(preds) print ('Predicted : ', decode_predictions(preds, top=1)[0], label) # Vanilla gradient from saliency import GradientSaliency vanilla = GradientSaliency(model) mask = vanilla.get_mask(img) show_image(mask, ax=plt.subplot('121'), title='vanilla gradient') mask = vanilla.get_smoothed_mask(img) show_image(mask, ax=plt.subplot('122'), title='smoothed vanilla gradient') plt.show() # Guided backpropagation from guided_backprop import GuidedBackprop guided_bprop = GuidedBackprop(model) # A very expensive operation, which hackingly creates 2 new temp models mask = guided_bprop.get_mask(img) show_image(mask, ax=plt.subplot('121'), title='guided backprop') mask = guided_bprop.get_smoothed_mask(x[0]) show_image(mask, ax=plt.subplot('122'), title='smoothed guided backprop') plt.show() # Integrated gradient from integrated_gradients import IntegratedGradients inter_grad = IntegratedGradients(model) mask = inter_grad.get_mask(x[0]) show_image(mask, ax=plt.subplot('121'), title='integrated grad') mask = inter_grad.get_smoothed_mask(x[0]) show_image(mask, ax=plt.subplot('122'), title='smoothed integrated grad') plt.show() # Cross comparision plt.figure(figsize=(20,8)) # Plot non-smoothed versions show_image(img, grayscale=False, ax=plt.subplot(251)) mask = vanilla.get_mask(img) show_image(mask, ax=plt.subplot(252), title='vanilla gradient') mask = guided_bprop.get_mask(img) show_image(mask, ax=plt.subplot(253), title='guided backprop') mask = inter_grad.get_mask(x[0]) show_image(mask, ax=plt.subplot(254), title='integrated grad') # Plot smoothed versions show_image(img, grayscale=False, ax=plt.subplot(256)) mask = vanilla.get_smoothed_mask(img) show_image(mask, ax=plt.subplot(257), title='smoothed vanilla gradient') mask = guided_bprop.get_smoothed_mask(img) show_image(mask, ax=plt.subplot(258), title='smoothed guided backprop') mask = inter_grad.get_smoothed_mask(x[0]) show_image(mask, ax=plt.subplot(259), title='smoothed integrated grad')
vis-cnn - GitHub
Welcome, my name is Eric Soupet and I am the administrator of the site elodees.com. elodees.com is a state of the art of Artificial Intelligence and aims to be collaborative, you can now offer content such as articles, events, tutorials, ... so don't hesitate !
Platform images credit : Pixabay - Pixabay License | Pexels - Pexels License