写在前面
类激活热力图:用于检查图像哪一部分对模型的最终输出有更大的贡献。具体某个类别对应到图片的那个区域响应最大,也就是对该类别的识别贡献最大
pytorch-grad-cam库代码GitHub代码
如果只想跑个图的话不用下!
作用:一是清晰直观的看看到底影响检测结果的特征;而是cv论文里出图真的很好看
本篇只是跑了代码给的猫狗图,下一篇要写如何可视化其他类别实战
先上跑完结果
使用的是resnet50,可以看出其关注度不仅仅只有狗,还有后面的背景,这会对以后的检测结果造成影响
实战
1.安装pytorch-grad-cam
在pycharm终端中输入
pip install grad-cam
我之前安装过了,页面如下
2.复制全部代码
'''
1)导入相关的包并加载模型
'''
from pytorch_grad_cam import GradCAM, ScoreCAM, GradCAMPlusPlus, AblationCAM, XGradCAM, EigenCAM
from pytorch_grad_cam.utils.image import show_cam_on_image, \
deprocess_image, \
preprocess_image
from torchvision.models import resnet50
import cv2
import numpy as np
import os
os.environ["KMP_DUPLICATE_LIB_OK"]="TRUE"
# 1.加载模型
model = resnet50(pretrained=True) #预先训练
# 2.选择目标层
# target_layer = model.layer4[-1]
target_layer = [model.layer4]
'''
Resnet18 and 50: model.layer4[-1]
VGG and densenet161: model.features[-1]
mnasnet1_0: model.layers[-1]
ViT: model.blocks[-1].norm1
'''
#------------------------------
'''
2)构建输入图像的Tensor形式,使其能传送到model里面去计算
'''
image_path = '../../examples/both.png'
rgb_img = cv2.imread(image_path, 1)[:, :, ::-1] # 1是读取rgb
#imread返回从指定路径加载的图像
rgb_img = cv2.imread(image_path, 1) #imread()读取的是BGR格式
rgb_img = np.float32(rgb_img) / 255
# preprocess_image作用:归一化图像,并转成tensor
input_tensor = preprocess_image(rgb_img, mean=[0.485, 0.456, 0.406],
std=[0.229, 0.224, 0.225]) # torch.Size([1, 3, 224, 224])
# Create an input tensor image for your model..
# Note: input_tensor can be a batch tensor with several images!
#----------------------------------------
'''
3)初始化CAM对象,包括模型,目标层以及是否使用cuda等
'''
# Construct the CAM object once, and then re-use it on many images:
cam = GradCAM(model=model, target_layers=target_layer, use_cuda=False)
'''
4)选定目标类别,如果不设置,则默认为分数最高的那一类
'''
# If target_category is None, the highest scoring category
# will be used for every image in the batch.
# target_category can also be an integer, or a list of different integers
# for every image in the batch.
target_category = None
#指定类:target_category = 281
'''
5)计算cam
'''
# You can also pass aug_smooth=True and eigen_smooth=True, to apply smoothing.
grayscale_cam = cam(input_tensor=input_tensor, target_category=target_category) # [batch, 224,224]
#----------------------------------
'''
6)展示热力图并保存
'''
# In this example grayscale_cam has only one image in the batch:
# 7.展示热力图并保存, grayscale_cam是一个batch的结果,只能选择一张进行展示
grayscale_cam = grayscale_cam[0]
visualization = show_cam_on_image(rgb_img, grayscale_cam) # (224, 224, 3)
cv2.imwrite(f'first_try.jpg', visualization)
> 步骤:先把博客中代码复制,然后按照本博客写的修改即可,也可以直接拉到下面复制我的代码,然后按照说明修改路径
3.自己使用代码需要修改的部分
1、图片路径
第34行,将单引号地址改为你要用的图片地址
image_path = '../../examples/both.png'
不会的请详细参看错误1内容,写的很清楚
注意:路径中不要有中文
2、结果图名称
第79行
cv2.imwrite(f'first_try.jpg', visualization)
将’'改为你希望的名字即可
4.查看结果图
其实就在代码当前路径的文件夹下
当然也可以复制图片名称first_try.jpg,在保存代码的文件夹里直接查找
点击结果图
运行代码所遇到的问题
错误1:TypeError: ‘NoneType’ object is not subscriptable
1、报错内容:
Traceback (most recent call last):
File “E:/CAM/pytorch-grad-cam/pytorch_grad_cam/utils/using_grad_cam.py”, line 32, in
rgb_img = cv2.imread(image_path, 1)[:, :, ::-1] # 1是读取rgb
TypeError: ‘NoneType’ object is not subscriptable
2、错误代码:
第2)构建输入图像的Tensor形式,使其能传送到model里面去计算,这一步
image_path = './examples/both.png'
rgb_img = cv2.imread(image_path, 1)[:, :, ::-1] # 1是读取rgb
rgb_img = np.float32(rgb_img) / 255
使用OpenCV读取图片时发生错误,一直显示图片类型是“nonetype”
3、修正:
发现是路径错误
image_path = './examples/both.png' #错误路径
修改后
image_path = '../../examples/both.png'
附上运行代码与读取的图片位置
关于路径如何正确表示可以看这篇文件路径./和…/
错误2:AttributeError: ‘GradCAM’ object has no attribute ‘activations_and_grads’
报错内容:
Traceback (most recent call last):
File “D:\anaconda\envs\pytorch\lib\site-packages\pytorch_grad_cam\base_cam.py”, line 192, in del
self.activations_and_grads.release()
AttributeError: ‘GradCAM’ object has no attribute ‘activations_and_grads’
错误3:TypeError: init() got an unexpected keyword argument ‘target_layer’
报错内容:
Traceback (most recent call last):
File “E:/CAM/pytorch-grad-cam/pytorch_grad_cam/utils/using_grad_cam.py”, line 60, in
cam = GradCAM(model=model, target_layer=target_layer, use_cuda=False)
TypeError: init() got an unexpected keyword argument ‘target_layer’
针对错误2与错误3的修改:
第一处:
target_layer = model.layer4[-1]
修改为 target_layer = [model.layer4]
第二处:
cam = GradCAM(model=model, target_layer=target_layer, use_cuda=False)
修改为
cam = GradCAM(model=model, target_layers=target_layer, use_cuda=False)
只想跑图出结果的不需要看,想大概熟悉代码与原理的可以看一看
使用pytorch实现grad-cam需了解hook机制,详细看 pytorch的autograd
pytorch的hook应用
个人理解:hook就是储存pytorch所释放的中间变量的“钩子”,哪里需要就钩在哪里 举例更好理解。
hook机制一定要理解,grad-cam中hook是重要代码基础差的看不懂基础代码,可以哪里不懂点哪里
1、*args
,**kargs
知识点讲解链接
2、Python自带模块argparse详细使用说明书 Python argparse命令行参数解析包的详细使用说明书例:采用LeNet-5演示backward_hook在grad-cam中应用,下面是代码过程(具体代码上面链接中有) 1、创建网络net
2、注册forward_hook函数用于提取最后一层特征图;
3、注册backward_hook函数用于提取类向量(one-hot)关于特征图的梯度; 4、对特征图的梯度进行求均值,并对特征图进行加权;
5、可视化heatmap
model._modules.items()
遍历输出每一层register_hook
的作用:即对x求导时,对x的导数进行操作,并且register_hook的参数只能以函数的形式传过去。(保护求导中中间值作用,不然pytorch将直接保存最后结果,中间结果不保存)详细解释文章来源:https://www.toymoban.com/news/detail-465206.html
本篇主要参考CAM(类激活映射),卷积可视化,神经网络可视化,一个库搞定,真的简单的不能再简单文章来源地址https://www.toymoban.com/news/detail-465206.html
到了这里,关于类别激活热力图grad-cam(pytorch)实战跑图的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!