Logo elodees  elodees

A caring AI for a better world













Only alphabetic characters accented or not as well as the space are accepted

Logo IA




Saliency map





No account yet ?

Sign up to access all content




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

License: MITLicenseMIT  Copyright (c) 2020 Ibrahim Sobh


GitHub



Free image provided by pexel.com

Free image provided by pexel.com
Free image provided by pexel.com








CAM Visualization

Free image provided by pexel.com


Guided Backpropagation Visualization

Free image provided by pexel.com


Keras-CNNVisualization

License: MITLicenseMIT  Copyright (c) 2018 YoungJin Kim


GitHub









Visualizing CNNs

Free image provided by pexel.com

Free image provided by pexel.com


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

License: MITLicenseMIT  Copyright (c) 2020 Jacob Gildenblat


GitHub



Free image provided by pexel.com

Free image provided by pexel.com
Free image provided by pexel.com
Free image provided by pexel.com








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



Free image provided by pexel.com

Free image provided by pexel.com

Free image provided by pexel.com

Free image provided by pexel.com

Free image provided by pexel.com










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