深度学习模型特征可视化(以yolov4为例)

一般来说,深度学习模型中的特征可视化分为两种:GAM/Grad_GAM、特征图可视化。

一、GAM/Grad_GAM可视化

GAM/Grad_GAM即为热力图,可以很直观的看到模型关注的重点区域,如图所示。这种可视化方法有很多帖子可参考,因此不再赘述,放上大佬改好的开源代码链接https://github.com/IDayday/YOLOv4_CAM
这里为特征图不同感受野对应的CAM热力图,由于我需要检测的物体是二轮车,可以看到模型的注意力集中在二轮车区域附近
对于YOLOv4的GAM可视化作者源码,同学在使用过程中出现了一些BUG,现在进行一下说明,帮助大家避坑。
源码使用方法如下:
1、在yolo_cam.py里面将model_path、classes_path、path改为自己的训练好的模型权重、目标类别、输入图片路径(相对位置)
2、直接运行或调试yolo_cam.py
同学在使用过程中出现的报错如下:
在这里插入图片描述
这是因为对张量f进行reshape操作时出现了维度不匹配的情况。让我们从第221行代码进行分析,首先通过赋值过的path读取图片,将图片存入image中,然后调用detect_image()函数,将图片输入进行检测后,将检测结果返回到output_list这个张量中,output_list是一个存了3个tensor的列表,其shape为[[1,507,6],[1,2028,6],[1,8112,6]]。报错的第223行代码通过枚举函数和for语句将output_list中的tensor和对应索引依次取出,进行reshape后加入ret列表中。这里取出第一个tensor处理时就出现了报错,其shape为[1,507,6],总的维度数量为1x507x6=3042。而此时reshape函数中的参数为(1,3,13,13,10),总的维度数量为1x3x13x13x10=5070,总的维度数量不等,所以报错。
解决方案: 将224行ret.append(f.reshape(1,3,stride[i],stride[i],10))中的10改为6,将156行def show_CAM(image_path, feature_maps, class_id, all_ids=10, show_one_layer=True):函数定义处的 all_ids改为6。最后将230行show_CAM(path, ret, 1)中的1改为想要可视化类别的索引即可,但是要注意这里的索引值从0开始,并且不能超过classes.txt的维度大小。比如classes.txt中只有1个类别,索引设为了1,必然报错(应设置为0)。

二、特征图可视化

特征图可视化需要对特征图进行通道分离,将tensor展开后以图片的形式保存。为直观展示效果,从YOLOv4主干网络CSPdarknet53中分别提取shape为(416,416,32)、(208,208,64)、(104,104,128)的特征进行可视化。在CSPDarkNet类中的forward(self, x)函数进行修改,调用模型即可,使用前要先在项目目录下分别创建名为“new_feature_picture0”、“new_feature_picture1”、“new_feature_picture2”的文件夹,代码如下:

def forward(self, x):
    x = self.conv1(x)
    out0 = x
    x = self.stages[0](x)
    out1 = x
    x = self.stages[1](x)
    out2 = x
    out3 = self.stages[2](x)
    out4 = self.stages[3](out3)
    out5 = self.stages[4](out4)
    #-----------------------------------特征可视化---------------------------------#
    image0s = out0
    image1s = out1
    image2s = out2
    #--------通道分离tensor,并可视化每个维度的特征图-------#
    #先清空文件夹中的内容
    shutil.rmtree('new_feature_picture0/')
    os.mkdir('new_feature_picture0/')

    image0s=torch.split(image0s,1,dim=0)   #dim=0是通道的索引,代表image0的第一个通道。'1'表示分离成单个维度,此处分离后image0为装有单通道tensor的元组。  
    k=0
    for image0 in image0s:   
        q=0
        image0=torch.split(image0,1,dim=1)
        for i in image0:
            t='backbone-32-416-416-picture'+str(k)+'-channel-'+str(q)+'.jpg'
            save_image(i,os.path.join('new_feature_picture0',t))
            q=q+1

            # feature_map_sum = sum(ele for ele in image0)
            # save_image(feature_map_sum,os.path.join('new_feature_picture0','feature_map_sum'+'_'+str(k)+'.png'))
        k=k+1        

    #--------通道分离tensor,并可视化每个维度的特征图-------#
    #先清空文件夹中的内容
    shutil.rmtree('new_feature_picture1/')
    os.mkdir('new_feature_picture1/')   

    image1s=torch.split(image1s,1,dim=0)   #dim=0是通道的索引,代表image0的第一个通道。'1'表示分离成单个维度,此处分离后image0为装有单通道tensor的元组。  
    k=0
    for image1 in image1s:   
        q=0
        image1=torch.split(image1,1,dim=1)
        for i in image1:
            t='backbone-64-208-208-picture'+str(k)+'-channel-'+str(q)+'.jpg'
            save_image(i,os.path.join('new_feature_picture1',t))
            q=q+1

            # feature_map_sum = sum(ele for ele in image1)
            # save_image(feature_map_sum,os.path.join('new_feature_picture1','feature_map_sum'+'_'+str(k)+'.png'))
        k=k+1

    #--------通道分离tensor,并可视化每个维度的特征图-------#
    #先清空文件夹中的内容
    shutil.rmtree('new_feature_picture2/')
    os.mkdir('new_feature_picture2/')     
        
    image2s=torch.split(image2s,1,dim=0)   #dim=0是通道的索引,代表image0的第一个通道。'1'表示分离成单个维度,此处分离后image0为装有单通道tensor的元组。  
    k=0
    for image2 in image2s:   
        q=0
        image2=torch.split(image2,1,dim=1)
        for i in image2:
            t='backbone-128-104-104-picture'+str(k)+'-channel-'+str(q)+'.jpg'
            save_image(i,os.path.join('new_feature_picture2',t))
            q=q+1

            # feature_map_sum = sum(ele for ele in image2)
            # save_image(feature_map_sum,os.path.join('new_feature_picture2','feature_map_sum'+'_'+str(k)+'.png'))
        k=k+1
    return out3, out4, out5

可视化完成后,如需要对特征图进行拼接,可参考我的上一篇博客https://blog.csdn.net/weixin_44944382/article/details/123829981?spm=1001.2014.3001.5501,最终效果如下:
原图
(416,416,32),32通道,所以一共由32张图片拼接而成。

(208,208,64)

(104,104,128)

  • 12
    点赞
  • 108
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 19
    评论
### 回答1: Grad-CAM是一种可视化技术,可以帮助我们理解深度学习模型的决策过程。在YOLOv5模型中,我们可以使用Grad-CAM来可视化模型对于不同目标的关注程度,从而更好地理解模型的预测结果。通过Grad-CAM,我们可以看到模型在预测时所关注的区域,这对于模型的调试和优化非常有帮助。 ### 回答2: GradCAM是一种可解释性方法,它允许机器学习模型生成图像中每个区域对预测结果的重要性得分。在对象检测中,这可以用来识别模型中关注哪些物体或区域来做出预测。在这篇学习笔记中,我们将介绍如何使用GradCAM可视化一个训练有素的Object Detection模型,以评估这个模型如何来预测不同的类别。 在本次中我们使用的是Yolov5模型,它是作为目标检测模型非常强大和常用的模型之一, 在实现中我们使用了PyTorch深度学习框架和OpenCV计算机视觉库。 GradCAM 原理: GradCAM是一种可视化技术,它可以帮助我们理解CNNs的预测结果。在通常的CNNs中,我们可以通常使用反向传播算法来计算梯度,通过梯度可以获得损失函数中每个权重和偏差的值。GradCAM使用类激活图(计算他们的方法会涉及到网络内物体检测的过程),用于确定CNNs特定级别包含了目标(或特征)的真实位置。 结果: GradCAM尝试告诉我们在CNNs中每层中哪些位置对预测起到了重要的作用,这有助于识别反常例行为或异常预测。在本次实验中,我们使用了Yolov5,使用我们的可视化技术来查看机器可能用来了解某些类别的对象的视觉问题作为预测的可靠性来源。 GradCAM在多个任务中都可以使用,也可以在多种环境下使用,可以用于分析分类、检查器、聚类、图像分割,可以确定CNNs中每个部分的影响,从而增强我们对CNNs的理解。 ### 回答3: Grad-CAM是一种可视化技术,可以显示神经网络如何对特定的输入做出决策。在物体识别任务中,Grad-CAM可以显示在预测过程中神经网络关注的输入图像的哪些部分。这些部分通常是神经网络识别物体的关键部分。 在YoloV5模型中,Grad-CAM技术可以帮助我们理解模型如何预测出物体。YoloV5模型是一种高效的目标检测模型,通过组合锚框、多尺度特征图和快速的非最大抑制算法完成了目标检测任务。 使用Grad-CAM技术,我们可以对YoloV5模型进行可视化,显示出模型表示出物体的关键部分。这个可视化更加直观,通俗易懂,即使对于没有深度学习经验的人也能理解。 在YoloV5模型中,Grad-CAM的实现需要两个步骤。首先,需要定义一个损失函数来反向传播位置权重。然后,使用这些位置权重对原始输入图像进行加权,以可视化神经网络关注的区域。 使用Grad-CAM技术的优点是它可以通过可视化方式帮助我们理解YoloV5模型。这使得模型的可解释性更加高,有助于我们优化模型,并更好地理解其内部工作原理。因此,Grad-CAM技术在深度学习领域中已经成为了一个非常重要的工具,可以帮助我们更好地了解神经网络。
评论 19
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

上交-威哥

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值