Visualizing CNN decisions(2)

はじめに

以前Grad-CAMについて書いた。
今回はCAMについて。
github.com
上記サイトを参考にさせて頂いた。

環境

Windows10 Pro
Python 3.7.5
GPUなし
certifi==2019.9.11
chardet==3.0.4
cycler==0.10.0
gluoncv==0.5.0
graphviz==0.8.4
idna==2.6
kiwisolver==1.1.0
matplotlib==3.1.1
mxnet==1.6.0b20191004
numpy==1.16.5
opencv-python==4.1.1.26
Pillow==6.2.0
pyparsing==2.4.2
python-dateutil==2.8.0
requests==2.18.4
scipy==1.3.1
six==1.12.0
tqdm==4.36.1
urllib3==1.22

コード

import numpy as np
import mxnet as mx
from mxnet import image
from gluoncv import utils
from gluoncv.model_zoo import get_model
from mxnet.gluon.data.vision import transforms
import cv2

url = 'https://raw.githubusercontent.com/dmlc/web-data/master/gluoncv/segmentation/voc_examples/1.jpg'
filename = 'example.jpg'
utils.download(url, filename)

#net = get_model('resnet18_v1', pretrained=True)
net = get_model('resnet18_v2', pretrained=True)

params_list = list(net.collect_params())
weight_softmax = net.collect_params()[params_list[-2]].data().asnumpy()

def returnCAM(feature_conv, weight_softmax, idx):
    # generate the class activation maps upsample to 256x256
    size_upsample = (256, 256)
    bz, nc, h, w = feature_conv.shape
    cam = weight_softmax[idx].dot(feature_conv.reshape((nc, h*w)))
    cam = cam.reshape(h, w)
    cam = cam - np.min(cam)
    cam_img = cam / np.max(cam)
    cam_img = np.uint8(255 * cam_img)
    return cv2.resize(cam_img, size_upsample)
    
transform = transforms.Compose([
    transforms.Resize((224,224)),
    transforms.ToTensor(),
    transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225])
])

img = image.imread(filename)
img = transform(img)
img = img.expand_dims(0)

output = net(img)

classes = net.classes

idx = mx.nd.argmax(output).asscalar().astype('int32')
#probs = mx.nd.softmax(output)[0,idx].asscalar()

features_blob = net.features[:-4](img).asnumpy()

CAMs = returnCAM(features_blob, weight_softmax, idx)

print('output CAM.jpg for the top1 prediction: %s'%classes[idx])
img = cv2.imread(filename)
height, width, _ = img.shape
heatmap = cv2.applyColorMap(cv2.resize(CAMs,(width, height)), cv2.COLORMAP_JET)
result = heatmap * 0.3 + img * 0.5
cv2.imwrite('CAM.jpg', result)

結果

f:id:touch-sp:20191101184639j:plain