CAM,PradCAM,layer CAM(可解释性分析方法)

本文介绍了计算机视觉中的几种解释性模型,包括CAM(ClassActivationMapping)、GradCAM、ScoreCAM和layerCAM,探讨了它们的作用、应用实例、特点、区别以及各自的优缺点,特别强调了可解释性分析的重要性。文章还提到如何解决模型偏见和局限性问题,如多目标对象的识别和梯度处理方法。
摘要由CSDN通过智能技术生成

目录

1.CAM

1.1作用

1.2应用实例

1.3CAM的特点

1.4CAM的思路

1.5CAM的缺点

2.GradCAM

2.1和GAM的区别及思路

2.2应用面

2.3一个延深(解决模型偏见)

2.4缺点

3.Grad CAM++

4.Score CAM

5.layer CAM

参考文献


导读

尽管CAM在计算机视觉领域起到了解释性的作用,但同时也要注意到,CAM只能关注模型得到结果依据的特征是什么,它依然不能从根本上解释神经网络在做什么。真正意义上的可解释性分析,应该有一个通用模型,而不是一个计算模型,一个解释模型,因为这两个模型还是不同的,这样的解释模型也无法百分之百保证对计算模型的解释是正确的。

1.CAM

1.1作用

CAM不不光可以分类还可以定位:从下图理解,识别palace时热力图定位了模型认为它是palace的特征,同样对dome等识别时也用热力图定位了相应特征,也就是定位了palace和dome的位置。

1.2应用实例

从热力图可以看出,识别福建土楼依据的特征是洞状结构,识别吊脚楼依据的是棍状结构,识别故宫依据的是沿状结构

1.3CAM的特点

      1.实现了深度学习的可解释性分析

      2.可拓展性强,后续研发出一系列基于CAM的算法

      3.在每张图片,每个类别都能生成CAM热力图

      4.若监督模型:用图像分类模型解决定位问题

      5.潜在的注意力机制:比方说,识别不同的鸟时(属于细粒度分类) ,人类可以根据模型识别鸟的不同种类所依据的特征的热力图,去理解和学习如何对鸟进行分类,这也属于用人工智能理解世界的方式,带人类去认识这个世界。

      6.使得Machine Teaching成为可能:就是,现在模型不仅可以人类一个问题的答案,还可以给出解决这个问题的思路,这不就可以实现真曾意义上的利用人工智能学习嘛

1.4CAM的思路

如下图所示,正常来说对于图像分类问题,最后一层卷积层之后通常链接全连接层,但这里用GAP(全局平均池化)替代了全连接层,具体操作为,假设最后一层为14×14×512,可以理解为该层有512个特征图然后对每个特征图进行平均池化操作,我们得到每一个特征图对应的值(标量,每一个值代表了原来的特征图),最终得到512个值,再乘以512个w(权重)得到每一个类别的得分,再进行softmax操作,得到对应的概率值。这个方法的特点就在于GAP的w值,对某个类别评分越高,说明这512个特征图某一部分占的比重越大,w也就越大,然后这些特征图还包含位置信息,如第Class Activation Mapping下的图所示,w1*(14×14的特征图)+w2*(14×14的特征图)+......w512*(14×14的特征图)中,我们看到w1对应特征图原图中的位置,w2对应特征图原图中的位置,w3对应特征图原图中的位置,从结果看我们得到的类别是狗,w1对应的特征图和狗毫无关系,所以输出时比重很低,在最终的识别图根本看不到这个特征图,而w2和w3对应的特征图包含狗,我们会发现,最终的识别图中有这两张特征图的身影。

注意到没有池化层:因为池化层会丢失长宽信息,这是CAM无法接受的

1.5CAM的缺点

      1.必须要有GAP层,否则无法得到热力图,基于此有了gradCAM

      2.只能分析最后一层卷积输出,无法分析中间层的特征图

      3.仅限图像分类任务

2.GradCAM

2.1和GAM的区别及思路

区别:在CAM中用GAP替代了全连接层,在GradCAM中,保留了全连接层

思路:如下图所示,简单理解全连接层对类别打分之后,再对其求导重新得到输入全连接层之前的卷积层,14×14×512(这个和原来不完全一样,这里面是梯度值,但能表示卷积层原来的特征图),再进行GAP操作。

优势:对CAM,当我们只想进行图像分类任务时,我们只用一个分类模型就行了,但如果我们想进行性可解释性分析,就需要将全连接层改为GAP重新训练。对GradCAM,当我们想进行可解释性分析时,直接载原模型上加入GAP就可以使用了。

2.2应用面

这样就导致GradCAM应用面很广,只要最后一层结果可导,不管是用什么忘了,RNN还是LSTM,不管是图像还是文本任务等,都可以用其解决。在强化学习中,比方说玩超级马里奥,我们就可以知道,模型执行上下左右的某一个操作,是基于什么,是为了金币,躲避伤害还是其他什么原因

 在文字描述生成任务中:就是说根据一张图生成文字描述,如下图所示,使用GradCAM,不仅可以生成文字,还有生成该文字所依赖的特征。

2.3一个延深(解决模型偏见)

做一个可视化分析的延深,可以用于纠正模型偏见:比方说我们通常会认为医生男性多,护士女性多,那么在建立数据集时,我们可能会在图片中,医生男性占比较多,护士女性占比较多,这就可能导致,模型基于男女分别医生还是护士,但这显然是不对的,在黑箱模型中,知道模型有问题,但可能很难找出问题在哪,需要做大量的实验尝试,有了可视化分析,就可以直接找出问题所在,改进模型。

2.4缺点

      1.图像上有多个同类物体时,只能画出一块热力图,比方说图中有三值猫,但只能画出一只猫,

      2.不同位置的梯度,GAP平局之后,影响相同,但一般来讲图片边缘的影响应该小于图像中心。

      3.梯度饱和、梯度消失、梯度噪声

      4.权重大的channel,不一定对类别预测分数贡献大

      5.只考虑从后往前的反向传播梯度,没考虑前向预测的影响

      6.深层生成的粗粒度热力图和浅层生成的细粒度热力图都不够精确

      7.CAM中只能分析最后一层,GradCAM可以分析中间层,但发现在浅层中,分析效果很差,基于这个有了layer CAM

3.Grad CAM++

解决Grad CAM两个问题

      1.图像上有多个同类物体时,只能画出一块热力图,比方说图中有三值猫,但只能画出一只猫,

      2.不同位置的梯度,GAP平局之后,影响相同,但一般来讲图片边缘的影响应该小于图像中心。

对于第一个问题简单理解:从下图看假设intput image输入的图片包含三个猫(分别对应灰色区域),经过卷积之后,这三个区域分别出现在不同的特征图之中,经过Grad CAM处理之后只能激活其中一个猫的特征图,在Grad CAM++中, 可以同时激活三个猫的特征图。

对于第二个问题简单理解:就是对梯度加了权重,来区别不同位置梯度的影响。

4.Score CAM

解决Grad CAM三个问题

      3.梯度饱和、梯度消失、梯度噪声

      4.权重大的channel,不一定对类别预测分数贡献大

      5.只考虑从后往前的反向传播梯度,没考虑前向预测的影响

做个对比:如下图所示,明显Score CAM热力图对应的位置更加聚焦。

思路

 首先用Phase1(第一个网络),经过Upsampling之后得到14×14×256个特征图,将这些特征图和原图input的小狗分别相乘我们会得到,将每个特征图在原图中对应的位置高亮显示,进一步得到每一个特征图对应他权重,最后Phase2输出这些权重和Phase1中对应的每一个特征图相乘得到Score CAM的结果。

5.layer CAM

解决Grad CAM2个问题

      6.深层生成的粗粒度热力图和浅层生成的细粒度热力图都不够精确

      7.CAM中只能分析最后一层,GradCAM可以分析中间层,但发现在浅层中,分析效果很差,基于这个有了layer CAM

应用:工业检测很合适。

做个对比:如下图左所示,第一行为Grad CAM的特征结果,第二行为layer CAM的特征结果,很明显Grad CAM噪声过多。如下图右所示,即使在浅层中也能聚焦较好的特征。

 补充

参考文献

1.类别激活热力图可视化工具介绍

2.【机器学习】请停止做“有可解释性”机器学习(中英文字幕)_哔哩哔哩_bilibili 

  • 1
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Grad-CAM是一种可视化CNN模型中每个输出类别的重要性的方法,可以用于解释模型的预测结果。对于图像分割任务,可以使用3D Grad-CAM来可视化模型中每个像素点的重要性,以帮助理解模型在图像分割任务上的表现。 下面是使用3D Grad-CAM进行脑肿瘤图像分割的代码示例: ```python import numpy as np import torch from torch.autograd import Function from torch.nn.functional import interpolate from torchvision import models class GradCam3d(Function): def __init__(self, model, target_layer): super(GradCam3d, self).__init__() self.model = model self.target_layer = target_layer self.feature_maps = None self.gradient = None def forward(self, x): self.feature_maps = [] self.gradient = [] for module_pos, module in self.model.module.named_children(): x = module(x) if module_pos == self.target_layer: x.register_hook(self.save_gradient) self.feature_maps.append(x) return x def backward(self, grad_output): if grad_output.is_cuda: grad_output = grad_output.cpu() grad_output = grad_output.data.numpy()[0] self.feature_maps[-1].grad = torch.from_numpy(grad_output) for i in range(len(self.feature_maps) - 1, 0, -1): x = self.feature_maps[i] if x.grad is not None: continue x.retain_grad() y = self.feature_maps[i - 1] if y.grad is not None: continue y.retain_grad() x_size = x.size() y_size = y.size() if x_size[2] != y_size[2] or x_size[3] != y_size[3] or x_size[4] != y_size[4]: y = interpolate(y, size=(x_size[2], x_size[3], x_size[4]), mode='trilinear', align_corners=False) x.backward(retain_graph=True) grad = y.grad if grad is not None: grad = grad.data.numpy()[0] self.gradient.append(grad) return self.gradient def save_gradient(self, grad): if grad.is_cuda: grad = grad.cpu() self.gradient.append(grad.data.numpy()) def get_heatmap(gradient_maps): heatmap = np.sum(gradient_maps, axis=0) heatmap = np.where(heatmap > 0, heatmap, 0) heatmap_max = np.max(heatmap) if heatmap_max != 0: heatmap /= heatmap_max return heatmap def grad_cam_3d(model, x, target_layer): model.eval() grad_cam = GradCam3d(model, target_layer) output = model(x) output = output.cpu().data.numpy()[0] output_index = np.argmax(output) grad_maps = grad_cam(torch.FloatTensor(x)).backward(torch.FloatTensor([1.0])) heatmap = get_heatmap(grad_maps) return heatmap, output_index # 加载模型 model = models.resnet50(pretrained=True) model.fc = torch.nn.Sequential(torch.nn.Linear(2048, 2)) model.cuda() model.eval() # 加载数据 x = np.load('data.npy') x = torch.from_numpy(x).unsqueeze(0).float() x = x.cuda() # 进行Grad-CAM可视化 heatmap, output_index = grad_cam_3d(model, x, 'layer4') ``` 在上述代码中,GradCam3d类继承自Function类,用于计算梯度和特征图。`forward`函数用于计算前向传播,同时保存目标层的特征图并注册梯度保存的hook。`backward`函数用于计算反向传播,同时保存梯度并计算每一层的梯度。`save_gradient`函数用于保存梯度。 `get_heatmap`函数用于将每一层的梯度加权求和得到最终的热力图,并进行归一化处理。`grad_cam_3d`函数用于调用GradCam3d类,同时返回热力图和模型的预测类别。 最后,加载模型和数据后,调用grad_cam_3d函数即可得到热力图和预测结果,其中`target_layer`参数表示目标层的名称。在脑肿瘤图像分割任务中,可以使用输出层或者中间的卷积层作为目标层。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值