<jupyter_start><jupyter_text>By [<NAME>](https://www.linkedin.com/in/ibrahim-sobh-phd-8681757/)  CAM **Class Activation Map (CAM)** visualization techniques produce heatmaps of 2D class activation over input images, showing how important each location is for  considered class.  Grad-CAMIn the paper [Grad-CAM: Why did you say that? Visual Explanations from Deep Networks via Gradient-based Localization](https://arxiv.org/abs/1610.02391), the visualization is conducted by taking the output feature map of a convolution layer (given an input image), and then weighing every channel (feature map) by the gradient of the output class wrt the feature map.![Grad-Cam](https://www.mathworks.com/help/examples/nnet/win64/GradCAMRevealsTheWhyBehindDeepLearningDecisionsExample_02.png)<jupyter_code>from keras.applications.vgg16 import VGG16
from keras.applications.vgg16 import preprocess_input, decode_predictions
from keras.preprocessing import image
import numpy as np
import keras.backend as K
import matplotlib.pyplot as plt
import cv2
from google.colab.patches import cv2_imshow
# load the model
model = VGG16(weights='imagenet')
# download an image
#!wget -nv https://i.pinimg.com/736x/18/86/a8/1886a88d9d7af5dafd5b8b175185dafd.jpg -O ex01.jpg
#!wget -nv https://proudfootcreams.files.wordpress.com/2013/05/img_8799.jpg -O ex01.jpg
!wget -nv https://image.freepik.com/free-photo/asian-man-with-dog-golden-retriever-park_1286-769.jpg -O ex01.jpg
# image load and resize
img_path = 'ex01.jpg'
img = image.load_img(img_path, target_size=(224, 224))
plt.imshow(img)
# image preprocess
x = image.img_to_array(img)
x = np.expand_dims(x, axis=0)
x = preprocess_input(x)
# predict (just fo sainty)
preds = model.predict(x)
print(decode_predictions(preds, top=3)[0])
cls_id = np.argmax(preds[0])
print(cls_id) # the output index
output_point = model.output[:, cls_id]

# Select the last conv layer
feature_maps = model.get_layer('block5_conv3')

# grads of the output wrt the conv layer
grads = K.gradients(output_point, feature_maps.output)[0]

# grads has the same shape as the selected conv layer
# the weight of each feature map is simple the mean of the grads
mean_grads = K.mean(grads, axis=(0, 1, 2))

# the function
iterate = K.function([model.input], [mean_grads, feature_maps.output[0]])

mean_grads_value, feature_maps_value = iterate([x])
# sample feature mapnumber 200 
feature_map = feature_maps_value[:, :, 200].copy()
feature_map -= feature_map.mean()
feature_map /= feature_map.std()
feature_map *= 64
feature_map += 128
feature_map = np.clip(feature_map, 0, 255).astype('uint8')
plt.imshow(feature_map)
# mean of all feature maps (without weighting)
plt.imshow(np.mean(feature_maps_value, axis=-1))
# weight each feature map by its mean gradinet
for i in range(512):
    feature_maps_value[:, :, i] *= mean_grads_value[i]

# The heatmap the mean of all weighted maps
heatmap = np.mean(feature_maps_value, axis=-1)
heatmap = np.maximum(heatmap, 0)
heatmap /= np.max(heatmap)
plt.matshow(heatmap)
# overlay 
img = cv2.imread(img_path)
heatmap = cv2.resize(heatmap, (img.shape[1], img.shape[0]))
heatmap = np.uint8(255 * heatmap)
heatmap = cv2.applyColorMap(heatmap, cv2.COLORMAP_JET)
superimposed_img = heatmap * 0.4 + img
cv2_imshow(superimposed_img)<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.1143204621465491, 'fraction_numerical': 0.040437823046518696, 'mean_word_length': 5.67342799188641, 'pattern_counts': {'":': 0, '<': 6, '<?xml version=': 0, '>': 6, 'https://': 6, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 1, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '1', 'dir': 'jupyter-structured-clean-dedup', 'id': '559624', 'license': 'MIT', 'n_tokens_mistral': 1249, 'n_tokens_neox': 1144, 'n_words': 304, 'path': '06_grad_cam.ipynb', 'repo_name': 'IbrahimSobh/see-inside-cnn', 'size': '3295'}