相关文章推荐
曾经爱过的帽子  ·  From Dagger & Hilt ...·  1 年前    · 
坏坏的麦片  ·  SqlParameter.Value ...·  4 分钟前    · 
爱旅游的铁链  ·  Uses of Class ...·  4 分钟前    · 
独立的红豆  ·  SqlParameter ...·  4 分钟前    · 
聪明伶俐的课本  ·  SpringBoot ...·  1小时前    · 
爱看球的牙膏  ·  IDEA ...·  1小时前    · 

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

理解CNN的方法主要有类激活图(Class Ac ti vation Maps, CAM)、梯度加权类激活图(Gradient Weigh te d Class Activation Map pi ng, 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更好的捕捉到了错误的原因。

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容图片侵权或者其他问题,请联系本站作侵删。 可视化芯片设计软件(国产EDA)-北京革新创展科技有限公司
可视化的跨平台EDA设计工具,具有超级简化的设计流程,最新可视化的分层设计理念,透明开放的模型库以及非常友好的用户界面。Robei软件将芯片设计高度抽象,并精简到
发表于 07-27 10:24 单片机可视化编程
可视化编程是不是指在环境下避开复杂的指令编写而通过图形的方式产生指令代码?-在可视化的条件下是否可以观察到仿真的结果?是的。不过仿真的结果不能够直接观察到,而要通过将生成的代码装载到仿真器工具中才能看到。
发表于 07-08 16:56 数据可视化大屏和一般的数据可视化报表有什么区别?
可视化工具上采用拖拉拽、点击的操作来实现,都可以自由运用数据可视化图表、智能数据分析功能,从海量数据中精准匹配数据,执行
发表于 08-10 11:49 基于VSCode的嵌入式开发的可视化代码调试方法分享
方式进行排查的问题,并且加打印排查的方式较为低效,使得调试过程极为痛苦。可视化调试效率一直比命令行调试要方便和快捷很多,而嵌入式开发由于目标程序在开发板上,而不在编写代码本身的环境中,这样的程序运行环境和编译环境分离的情况,导致普通的集成开发环境并不能满足
发表于 12-14 07:54 如何在Ubuntu下实现可视化代码跟踪调试
实现可视化代码跟踪调试1.1 安装VSCode1.2 配置调试和编译文件一、在Ubuntu下实现可视化代码跟踪调试1.1 安装VSCode在Ubuntu的应用商店下搜索
发表于 12-14 07:02 卷积神经网络表征可视化研究综述(1)
方式CNN内部表征和输出决策进行解释. 表征可视化尝试解释CNN内部特征的表示形式、输入–内部特征–输出三者之间的关系、促使网络做出当前预测的输入等问题。与其他方法相比, 表征可视化方法
发表于 08-09 10:53 基于模板的通用文件对话框的可视化定制
可视化定制通用文件对话框的实现方法。关键词: 定制;通用文件对话框;模板;预览在我们开发的CAD/CAM系统及其它应用软件中,经常需要用户进行一些
发表于 08-21 10:08 14次下载
基于 Grad-CAM 与KL损失的SSD目标检测算法
Grad-CAM 与KL损失的SSD目标检测算法 来源:《电子学报》,作者侯庆山等 摘 要: 鉴于Single Shot Multibox Detector (SSD)算法对中小目标检测
发表于 01-21 08:40 615 次阅读
 
推荐文章