神经网络可视化《Grad-CAM:Visual Explanations from Deep Networks via Gradient-based Localization》
神经网络已经在很多场景下表现出了很好的识别能力,但是缺乏解释性一直所为人诟病。《Grad-CAM:Visual Explanations from Deep Networks via Gradient-based Localization》这篇论文基于梯度为其可解释性做了一些工作,它可以显著描述哪块图片区域对识别起了至关重要的作用,以热度图的方式可视化神经网络的注意力。本博客主要是基于pytorch的简单工程复现。原文见这里,本代码基于这里。
1 import torch
2 import torchvision
3 from torchvision import models
4 from torchvision import transforms
5 from PIL import Image
6 import pylab as plt
7 import numpy as np
8 import cv2
9
10
11 class Extractor():
12 """
13 pytorch在设计时,中间层的梯度完成回传后就释放了
14 这里用hook工具在保存中间参数的梯度
15 """
16 def __init__(self, model, target_layer):
17 self.model = model
18 self.target_layer = target_layer
19 self.gradient = None
20
21 def save_gradient(self, grad):
22 self.gradient=grad
23
24 def __call__(self, x):
25 outputs = []
26 self.gradients = []
27 for name,module in self.model.features._modules.items():
28 x = module(x)
29 if name == self.target_layer:
30 x.register_hook(self.save_gradient)
31 target_activation=x
32 x=x.view(1,-1)
33 for name,module in self.model.classifier._modules.items():
34 x = module(x)
35 # 维度为(1,c, h, w) , (1,class_num)
36 return target_activation, x
37
38
39 def preprocess_image(path):
40 means=[0.485, 0.456, 0.406]
41 stds=[0.229, 0.224, 0.225]
42 m_transform=transforms.Compose([transforms.ToTensor(),transforms.Normalize(means,stds)])
43 img=Image.open(path)
44 return m_transform(img).reshape(1,3,224,224)
45
46
47 class GradCam():
48 def __init__(self, model, target_layer_name, use_cuda):
49 self.model = model
50 self.model.eval()
51 self.cuda = use_cuda
52 if self.cuda:
53 self.model = model.cuda()
54
55 self.extractor = Extractor(self.model, target_layer_name)
56
57
58 def __call__(self, input, index = None):
59 if self.cuda:
60 target_activation, output = self.extractor(input.cuda())
61 else:
62 target_activation, output = self.extractor(input)
63
64 # index是想要查看的类别,未指定时选择网络做出的预测类
65 if index == None:
66 index = np.argmax(output.cpu().data.numpy())
67
68 # batch维为1(我们默认输入的是单张图)
69 one_hot = np.zeros((1, output.size()[-1]), dtype = np.float32)
70 one_hot[0][index] = 1.0
71 one_hot = torch.tensor(one_hot)
72 if self.cuda:
73 one_hot = torch.sum(one_hot.cuda() * output)
74 else:
75 one_hot = torch.sum(one_hot * output)
76
77 self.model.zero_grad()
78 one_hot.backward(retain_graph=True)
79
80 grads_val = self.extractor.gradient.cpu().data.numpy()
81 # 维度为(c, h, w)
82 target = target_activation.cpu().data.numpy()[0]
83 # 维度为(c,)
84 weights = np.mean(grads_val, axis = (2, 3))[0, :]
85 # cam要与target一样大
86 cam = np.zeros(target.shape[1 : ], dtype = np.float32)
87 for i, w in enumerate(weights):
88 cam += w * target[i, :, :]
89
90 # 每个位置选择c个通道上最大的最为输出
91 cam = np.maximum(cam, 0)
92 cam = cv2.resize(cam, (224, 224))
93 cam = cam - np.min(cam)
94 cam = cam / np.max(cam)
95 return cam
96
97
98 def show_cam_on_image(img, mask):
99 heatmap = cv2.applyColorMap(np.uint8(255*mask), cv2.COLORMAP_JET)
100 heatmap = np.float32(heatmap) / 255
101 cam = heatmap + np.float32(img)
102 cam = cam / np.max(cam)
103 cv2.imwrite("cam2.jpg", np.uint8(255 * cam))
104
105
106 #target_layer 越靠近分类层效果越好
107 grad_cam = GradCam(model = models.vgg19(pretrained=True), target_layer_name = "35", use_cuda=True)
108 input = preprocess_image("both.png")
109 mask = grad_cam(input, None)
110 img = cv2.imread("both.png", 1)
111 #热度图是直接resize加到输入图上的
112 img = np.float32(cv2.resize(img, (224, 224))) / 255
113 show_cam_on_image(img, mask)
原图:

可视化图:

神经网络可视化《Grad-CAM:Visual Explanations from Deep Networks via Gradient-based Localization》的更多相关文章
- Grad-CAM:Visual Explanations from Deep Networks via Gradient-based Localization
目录 Grad-CAM:Visual Explanations from Deep Networks via Gradient-based Localization 1.Abstract 2.Intr ...
- 【论文简读】 Deep web data extraction based on visual
<Deep web data extraction based on visual information processing>作者 J Liu 上海海事大学 2017 AIHC会议登载 ...
- 深度卷积神经网络用于图像缩放Image Scaling using Deep Convolutional Neural Networks
This past summer I interned at Flipboard in Palo Alto, California. I worked on machine learning base ...
- 论文笔记:SiamRPN++: Evolution of Siamese Visual Tracking with Very Deep Networks
SiamRPN++: Evolution of Siamese Visual Tracking with Very Deep Networks 2019-04-02 12:44:36 Paper:ht ...
- 论文笔记之:Action-Decision Networks for Visual Tracking with Deep Reinforcement Learning
论文笔记之:Action-Decision Networks for Visual Tracking with Deep Reinforcement Learning 2017-06-06 21: ...
- Distill详述「可微图像参数化」:神经网络可视化和风格迁移利器!
近日,期刊平台 Distill 发布了谷歌研究人员的一篇文章,介绍一个适用于神经网络可视化和风格迁移的强大工具:可微图像参数化.这篇文章从多个方面介绍了该工具. 图像分类神经网络拥有卓越的图像生成能力 ...
- WPF中的可视化对象(Visual)
原文:WPF中的可视化对象(Visual) 这是MSDN对Visual的解释:Visual class:Provides rendering support in WPF, which include ...
- TensorSpace:超酷炫3D神经网络可视化框架
TensorSpace:超酷炫3D神经网络可视化框架 TensorSpace - 一款 3D 模型可视化框架,支持多种模型,帮助你可视化层间输出,更直观地展示模型的输入输出,帮助理解模型结构和输出方法 ...
- Deep Learning 8_深度学习UFLDL教程:Stacked Autocoders and Implement deep networks for digit classification_Exercise(斯坦福大学深度学习教程)
前言 1.理论知识:UFLDL教程.Deep learning:十六(deep networks) 2.实验环境:win7, matlab2015b,16G内存,2T硬盘 3.实验内容:Exercis ...
随机推荐
- C++ 类成员指针
C++的类成员指针是一种奇葩的指针. 假设现在我们要表示一个三维的点,现在有两种定义方式: struct point1{ int x, y, z; }; struct point2{ int c[3] ...
- 我的树莓派 Raspberry Pi Zero 2W 折腾笔记,记录一些遇到的问题和解决办法
0x00 前言说明 最近买了一块Raspberry Pi Zero 2W来玩,目的是想搭建一台远程运行的个人服务器,上面放个博客.点个灯啥的.于是就有了这篇文章. 树莓派官网地址:https://ww ...
- Unity实现A*寻路算法学习1.0
一.A*寻路算法的原理 如果现在地图上存在两点A.B,这里设A为起点,B为目标点(终点) 这里为每一个地图节点定义了三个值 gCost:距离起点的Cost(距离) hCost:距离目标点的Cost(距 ...
- git-github远程仓库以及git的进阶使用
注意保存自己的笔记吧,看来这个typora还是有点bug,居然还被我碰到了,今天突然死机,重启电脑后,看我自动保存的里面居然没有后来连上网了又有了,这就不说了嘛,但是命名文件有几kb的大小,为什么我一 ...
- 批量安装Windows系统
今天我们利用Windows server 2019自带的Windows部署服务通过网络批量安装Win 10 一.Windows服务 1)WDS WDS(Windows Deployment Servi ...
- IIS方式部署项目发布上线
VS2019如何把项目部署和发布 这里演示:通过IIS文件publish的方式部署到Windows本地服务器上 第一步(安装IIS) 1.在自己电脑上搜索Windows功能里的[启用或关闭Window ...
- python写一个能变身电光耗子的贪吃蛇
python写一个不同的贪吃蛇 写这篇文章是因为最近课太多,没有精力去挖洞,记录一下学习中的收获,python那么好玩就写一个大一没有完成的贪吃蛇(主要还是跟课程有关o(╥﹏╥)o,课太多好烦) 第一 ...
- 手脱NsPacK壳
1.查壳 使用PEiD未能检测到壳信息,这时,我们更换其他工具 从图中可以看到壳的信息为[NsPacK(3.x)[-]] 2.百度壳信息 北斗程序压缩(Nspack)是一款压缩壳.主要的选项是:压缩资 ...
- 『忘了再学』Shell基础 — 16、位置参数变量
目录 1.位置参数变量$n 2.位置参数变量$*和$@ 3.位置参数变量$# 位置參数变量的作用主要用于脚本的传参. 位置參数变量的名称和作用都是确定不能改变的,但是该变量的内容是可以更改的,也就是变 ...
- Python趣味入门9:函数是你走过的套路,详解函数、调用、参数及返回值
1.概念 琼恩·雪诺当上守夜人的司令后,为训练士兵对付僵尸兵团,把成功斩杀僵尸的一系列动作编排成了"葵花宝典剑法",这就是函数.相似,在计算机世界,一系列前后连续的计算机语句组合在 ...