0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

CAM与Grad-CAM++可视化CNN方式的代码实现和对比

冬至子 来源:Tanishq Sardana 作者:Tanishq Sardana 2023-06-09 16:53 次阅读

当使用神经网络时,我们可以通过它的准确性来评估模型的性能,但是当涉及到计算机视觉问题时,不仅要有最好的准确性,还要有可解释性和对哪些特征/数据点有助于做出决策的理解。模型专注于正确的特征比模型的准确性更重要。

理解CNN的方法主要有类激活图(Class Activation Maps, CAM)、梯度加权类激活图(Gradient Weighted Class Activation Mapping, Grad-CAM)和优化的 Grad-CAM( Grad-CAM++)。它们的思想都是一样的:如果我们取最后一个卷积层的输出特征映射并对它们施加权重,就可以得到一个热图,可以表明输入图像中哪些部分的权重高(代表了整个图的特征)。

Class Activation Maps

CAM是一种将CNN所看到或关注的内容可视化并为我们生成类输出的方法。

通过将图像传递给CNN,我们获得了相同图像的低分辨率特征图。

CAM的思想是,删除那些完全连接的神经网络,并用全局平均池化层代替它们,特征图中所有像素的平均值就是它的全局平均值。通过将GAP应用于所有特征映射将获得它们的标量值。

对于这些标量值,我们应用表明每个特征映射对特定类重要性的权重,权重是通过训练一个线性模型来学习的。

激活图将是所有这些特征图的加权组合。

defgenerate_cam(input_model, image, layer_name='block5_conv3', H=224, W=224):
     
     cls=np.argmax(input_model.predict(image)) # Obtain the predicted class
     conv_output=input_model.get_layer(layer_name).output#Get the weights of the last output layer
     
     last_conv_layer_model=keras.Model(input_model.inputs, conv_output) #Create a model with the last output layer    
     class_weights=input_model.get_layer(layer_name).get_weights()[0] # Get the weights of the output layer\\
     class_weights=class_weights[0,:,:,:]
     class_weights=np.mean(class_weights, axis=(0, 1))
     
     
     last_conv_output=last_conv_layer_model.predict(image) #The feature map output from last output layer
     last_conv_output=last_conv_output[0, :]
     cam=np.dot(last_conv_output, class_weights)
     
     
     cam=zoom(cam, H/cam.shape[0]) #Spatial Interpolation/zooming to image size
     cam=cam/np.max(cam) #Normalizing the gradcam
     
     returncam

但是CAM有一个最大的缺点就是必须重新训练模型才能得到全局平均池化后得到的权重。对于每一类必须学习一个线性模型。也就是说将有n个权重(等于最后一层的过滤器)* n个线性模型(等于类)。并且还必须修改网络架构来创建CAM这对于现有的模型来说改动太大,所以Grad-CAM解决了这些缺点。

Grad-CAM( Gradient Weighted Class Activation Mapping)

Grad-CAM背后的思想是,依赖于最后一个卷积层的特征映射中使用的梯度,而不是使用网络权重。这些梯度是通过反向传播得到的。

这不仅解决了再训练问题,还解决了网络架构修改问题,因为只使用梯度而不使用GAP层。

我们只要在最后一个卷积层中计算用于顶部预测类的特征映射的梯度。然后我们对这些权重应用全局平均。权重与最后一层得到的特征映射的点积就是Grad-CAM输出。然后通过在其上应用ReLU,识别图像中仅对我们的图像有积极贡献的部分。

最后就是将Grad-CAM调整为图像大小并规范化,以便它可以叠加在图像上。

defgrad_cam(input_model, image, layer_name='block5_conv3',H=224,W=224):
     
     cls=np.argmax(input_model.predict(image)) #Get the predicted class
     y_c=input_model.output[0, cls] #Probability Score
     conv_output=input_model.get_layer(layer_name).output#Tensor of the last layer of cnn
     grads=K.gradients(y_c, conv_output)[0] #Gradients of the predicted class wrt conv_output layer
     
     get_output=K.function([input_model.input], [conv_output, grads]) 
     output, grads_val=get_output([image]) #Gives output of image till conv_output layer and the gradient values at that level
     output, grads_val=output[0, :], grads_val[0, :, :, :]
     
     
     weights=np.mean(grads_val, axis=(0, 1)) #Mean of gradients which acts as our weights
     cam=np.dot(output, weights) #Grad-CAM output
     
     cam=np.maximum(cam, 0) #Applying Relu
     cam=zoom(cam,H/cam.shape[0]) #Spatial Interpolation/zooming to image size
     cam=cam/cam.max() #Normalizing the gradcam
     
     returncam

Grad-CAM++

Grad-CAM++不仅包括gradcam技术,它增加了引导反向传播,只通过类别预测的正梯度进行反向传播。

Grad-CAM++这种优化的原因是因为Grad-CAM在识别和关注多次出现的对象或具有低空间占用的对象方面存在问题。

所以Grad-CAM++给予与预测类相关的梯度像素更多的重要性(正梯度),通过使用更大的因子而不是像Grad-CAM那样使用常数因子来缩放它们。这个比例因子在代码中用alpha表示。

defgrad_cam_plus(input_model, image, layer_name='block5_conv3',H=224,W=224):
     
     cls=np.argmax(input_model.predict(image))
     y_c=input_model.output[0, cls]
     conv_output=input_model.get_layer(layer_name).output
     grads=K.gradients(y_c, conv_output)[0]
     
     first=K.exp(y_c)*grads#Variables used to calculate first second and third gradients
     second=K.exp(y_c)*grads*grads
     third=K.exp(y_c)*grads*grads*grads
 
     #Gradient calculation
     get_output=K.function([input_model.input], [y_c,first,second,third, conv_output, grads])
     y_c, conv_first_grad, conv_second_grad,conv_third_grad, conv_output, grads_val=get_output([img])
     global_sum=np.sum(conv_output[0].reshape((-1,conv_first_grad[0].shape[2])), axis=0)
 
     #Used to calculate the alpha values for each spatial location
     alpha_num=conv_second_grad[0]
     alpha_denom=conv_second_grad[0]*2.0+conv_third_grad[0]*global_sum.reshape((1,1,conv_first_grad[0].shape[2]))
     alpha_denom=np.where(alpha_denom!=0.0, alpha_denom, np.ones(alpha_denom.shape))
     alphas=alpha_num/alpha_denom
     
     #Calculating the weights and alpha's which is the scale at which we multiply the weights with more importance
     weights=np.maximum(conv_first_grad[0], 0.0)
     alpha_normalization_constant=np.sum(np.sum(alphas, axis=0),axis=0)
     alphas/=alpha_normalization_constant.reshape((1,1,conv_first_grad[0].shape[2])) #Normalizing alpha
     
     #Weights with alpha multiplied to get spatial importance
     deep_linearization_weights=np.sum((weights*alphas).reshape((-1,conv_first_grad[0].shape[2])),axis=0)
     
     grad_CAM_map=np.sum(deep_linearization_weights*conv_output[0], axis=2) #Grad-CAM++ map
     cam=np.maximum(grad_CAM_map, 0)
     cam=zoom(cam,H/cam.shape[0])
     cam=cam/np.max(cam) 
     
     returncam

结果对比

这里我们使用VGG16,对一些图像进行了比较,下图中可以看到CAM、Grad-CAM和Grad-CAM++的看法有多么不同。虽然它们都主要集中在它的上半身,但Grad-CAM++能够将其整体视为重要部分,而CAM则将其某些部分视为非常重要的特征,而将一些部分视为其预测的辅助。而Grad-CAM只关注它的冠和翅膀作为决策的重要特征。

对于这张风筝的图像,CAM显示它关注的是除了风筝之外的所有东西(也就是天空),但是使用gradcam则看到到模型关注的是风筝,而gradcam ++通过增加重要的突出空间进一步加强了这一点。这里需要注意的是,模型错误地将其分类为降落伞,但风筝类紧随其后。也就是说,其实CAM更好的捕捉到了错误的原因。

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 神经网络
    +关注

    关注

    42

    文章

    4749

    浏览量

    100431
  • 过滤器
    +关注

    关注

    1

    文章

    427

    浏览量

    19526
  • 计算机视觉
    +关注

    关注

    8

    文章

    1694

    浏览量

    45905
  • GAP
    GAP
    +关注

    关注

    0

    文章

    15

    浏览量

    8294
收藏 人收藏

    评论

    相关推荐

    单片机可视化编程

    单片机的可视化编程是不是指在环境下避开复杂的指令编写而通过图形的方式产生指令代码?-在可视化的条件下是否可以观察到仿真的结果?是的。不过仿真的结果不能够直接观察到,而要通过将生成的
    发表于 07-08 16:56

    可视化MES系统软件

    和客户都会造成损失,为了更好的满足客户需求、实现企业信息,目前企业制造过程中主要还存在以下需求:(1)数据可视化方面。MES系统软件之所以能有效的监控整个车间的生产过程,主要是通过对制造过程中
    发表于 11-30 19:55

    利用Keras实现四种卷积神经网络(CNN)可视化

    Keras实现卷积神经网络(CNN)可视化
    发表于 07-12 11:01

    python数据可视化的方法和代码

    Python数据可视化汇总
    发表于 10-14 14:59

    三维可视化的应用和优势

    的整体态势。  比如设备在偏僻区域(海下、深山、沙漠、分布全国各地等),可以实现无人检测,无需消耗人力物力进行检测,通过三维数据的分析可以直观的探测出设备状态和产能。  设备运行可视化:根据图像
    发表于 12-02 11:52

    基于VSCode的嵌入式开发的可视化代码调试方法分享

    ,经常会遇到问题不是那么明显,不方便通过加打印的方式进行排查的问题,并且加打印排查的方式较为低效,使得调试过程极为痛苦。可视化调试效率一直比命令行调试要方便和快捷很多,而嵌入式开发由于目标程序在开发板上,而不在编写
    发表于 12-14 07:54

    如何在Ubuntu下实现可视化代码跟踪调试

    目录一、在Ubuntu下实现可视化代码跟踪调试1.1 安装VSCode1.2 配置调试和编译文件一、在Ubuntu下实现可视化
    发表于 12-14 07:02

    Keras可视化神经网络架构的4种方法

    pip install graphviz然后我们创建一个模型,并用这4个包来进行可视化:在实际使用时我们希望的是通过可视化对比模型架构,所以这里定义三个具有不同超参数 CNN 模型
    发表于 11-02 14:55

    CAM工序自动说明

    CAM工序自动 虽然CAM系统在PCB业界中不断增加,但是为甚么还有很多厂商不愿意把工序自动
    发表于 01-28 23:40 0次下载

    基于模板的通用文件对话框的可视化定制

    本文介绍了利用模板可视化定制通用文件对话框的实现方法。关键词: 定制;通用文件对话框;模板;预览在我们开发的CAD/CAM系统及其它应用软件中,经常需要用户进行一些
    发表于 08-21 10:08 14次下载

    CAM工序自动

    CAM工序自动CAM工序自动CAM工序自动CAM
    发表于 02-24 11:02 0次下载

    管线可视化管理怎么实现呢?

    无论是城市管线还是社区,商场,大厦里的管线,想要实时检测到管线的情况怕是有难度。如何通过物联网和互联网技术实现管线可视化管理是解决问题的根本。 智慧电力可视化系统构建发电、输电、变电、配电、用电
    发表于 03-11 14:36 1331次阅读

    CNN的三种可视化方法介绍

    导读 对神经网络进行可视化分析不管是在学习上还是实际应用上都有很重要的意义,基于此,本文介绍了3种CNN可视化方法:可视化中间特征图,可视化
    的头像 发表于 12-29 11:49 2404次阅读

    3种CNN可视化方法

    上图为某CNN 5-8 层输出的某喵星人的特征图的可视化结果(一个卷积核对应一个小图片)。可以发现越是低的层,捕捉的底层次像素信息越多,特征图中猫的轮廓也越清晰。越到高层,图像越抽象,稀疏程度也越高。这符合我们一直强调的特征提取概念。
    的头像 发表于 01-07 14:36 1996次阅读

    基于Grad-CAM与KL损失的SSD目标检测算法

    基于Grad-CAM与KL损失的SSD目标检测算法 来源:《电子学报》,作者侯庆山等 摘 要: 鉴于Single Shot Multibox Detector (SSD)算法对中小目标检测
    发表于 01-21 08:40 947次阅读