【Pytorch】 特征图的可视化

这篇具有很好参考价值的文章主要介绍了【Pytorch】 特征图的可视化。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。


前言

Pytroch中间层的特征图可视化,网上已经有很多教程,比如用hook钩子函数,但是代码都写得不是很清楚,所以还是自己去摸索一下。


更新一下


目前这种方法有很大的缺陷,最近看一篇国外的blog时,发现了Pytorch官方文档有一个Torch FX,基于这个实现了特征提取,更新一下Pytorch官方实现的特征图提取,参考我新写的记录:六行代码实现:特征图提取与特征图可视化


一、torchvision.models._utils.IntermediateLayerGetter

IntermediateLayerGetter这个函数是在看DETR源码时发现的,它的作用很简单,记录我们想要的中间层的输出。看个官方给出的例子:

import torch
import torchvision
import torch.nn as nn
import torchvision.transforms as transforms
import torchvision.models as models
from matplotlib import pyplot as plt

model = torchvision.models.resnet18(weights=models.ResNet18_Weights.DEFAULT)
new_model = torchvision.models._utils.IntermediateLayerGetter(model, {'layer1': 'feat1', 'layer3': 'feat2'})
out = new_model(torch.rand(1, 3, 224, 224))

print([(k, v.shape) for k, v in out.items()])  # 其中v是对应层的输出,也就是我们要得到的特征图Tensor

#输出
"[('feat1', torch.Size([1, 64, 56, 56])), ('feat2', torch.Size([1, 256, 14, 14]))]"

注意:torcvision的最新版本0.13,已经取消了pretrained=True这个参数,并且打算在0.15版正式移除,如果用pretrained这个参数会出现warring警告。现在加载与训练权重的参数改成了weights,这样可以加载不同版本的预训练权重,比如models.ResNet18_Weights.DEFAULT,就加载默认最新的ResNet18权重文件,还有其他参数形式,具体参考官网

这里详细说一下

#首先定义一个模型,这里直接加载models里的预训练模型
model = torchvision.models.resnet18(weights=models.ResNet18_Weights.DEFAULT)
#查看模型的各个层,
for name in model.named_children():
    print(name[0])
#输出,相当于把ResNet的分成了10个层
"""
conv1
bn1
relu
maxpool
layer1
layer2
layer3
layer4
avgpool
fc"""

可以看到ResNet18的结构被分为了10个部分,和下图的网络结构是一一对应的,conv1、bn1、relu、maxpool这四个对应第一层的卷积conv1,layer1对应图中的conv2_x,也就是一个残差结构,同理layer2对应conv3_x,以此类推。

【Pytorch】 特征图的可视化
比如,我想要layer1(conv2_x)和layer2(conv3_x)的输出,那么只需要构建一个字典,{‘layer1’: ‘feat1’, ‘layer2’: ‘feat2’},feat1、feat2是我们的重命名,可以随意输入自己想要的名字。

#现在我们把model传进IntermediateLayerGetter
new_model = torchvision.models._utils.IntermediateLayerGetter(model, {'layer1': 'feat1', 'layer2': 'feat2'})
out = new_model(torch.rand(1, 3, 224, 224))
print([(k,v.shape) for  k,v in out.items()])

#输出
"""
[('feat1', torch.Size([1, 64, 56, 56])), ('feat2', torch.Size([1, 128, 28, 28]))]
"""

二、示例

1.ResNet50特征图可视化

代码如下:

# 返回输出结果
import cv2
import torchvision
import torch
from matplotlib import pyplot as plt
import numpy as np


#定义函数,随机从0-end的一个序列中抽取size个不同的数
def random_num(size,end):
    range_ls=[i for i in range(end)]
    num_ls=[]
    for i in range(size):
        num=random.choice(range_ls)
        range_ls.remove(num)
        num_ls.append(num)
    return num_ls
    


path = "test.jpg"
transformss = transforms.Compose(
    [transforms.ToTensor(),
     transforms.Resize((224, 224)),
     transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225])])

#注意如果有中文路径需要先解码,最好不要用中文
img = cv2.imread(path)
img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)

#转换维度
img = transformss(img).unsqueeze(0)

model = torchvision.models.resnet50(weights=models.ResNet50_Weights.DEFAULT)
new_model = torchvision.models._utils.IntermediateLayerGetter(model, {'layer1': '1', 'layer2': '2',"layer3":"3"})
out = new_model(img)

tensor_ls=[(k,v) for  k,v in out.items()]

#这里选取layer2的输出画特征图
v=tensor_ls[1][1]

"""
如果要选layer3的输出特征图只需把第一个索引值改为2,即:
v=tensor_ls[2][1]
只需把第一个索引更换为需要输出的特征层对应的位置索引即可
"""
#取消Tensor的梯度并转成三维tensor,否则无法绘图
v=v.data.squeeze(0)

print(v.shape)  # torch.Size([512, 28, 28])


#随机选取25个通道的特征图
channel_num = random_num(25,v.shape[0])
plt.figure(figsize=(10, 10))
for index, channel in enumerate(channel_num):
    ax = plt.subplot(5, 5, index+1,)
    plt.imshow(v[channel, :, :])
plt.savefig("feature.jpg",dpi=300)

原图

【Pytorch】 特征图的可视化

特征图

从特征图中可以看到,layer2确实已经学习到了某些特征,比如第二行第二列的特征图已经把狗的形状勾勒出来了,说明这个卷积核学习的可能是狗的颜色。

【Pytorch】 特征图的可视化
这里再展示一下ResNet第一部分(conv1)卷积层的特征图(灰度图):
【Pytorch】 特征图的可视化

2.AlexNet可视化

上面的ResNet用的是预训练模型,这里我们自己构建AlexNet。
代码如下:

class AlexNet(nn.Module):
    def __init__(self):
        super(AlexNet, self).__init__()

        self.conv1 = nn.Sequential(nn.Conv2d(3, 96, 11, 4, 2),
                                   nn.ReLU(),
                                   nn.MaxPool2d(3, 2),
                                   )

        self.conv2 = nn.Sequential(nn.Conv2d(96, 256, 5, 1, 2),
                                   nn.ReLU(),
                                   nn.MaxPool2d(3, 2),
                                   )

        self.conv3 = nn.Sequential(nn.Conv2d(256, 384, 3, 1, 1),
                                   nn.ReLU(),
                                   nn.Conv2d(384, 384, 3, 1, 1),
                                   nn.ReLU(),
                                   nn.Conv2d(384, 256, 3, 1, 1),
                                   nn.ReLU(),
                                   nn.MaxPool2d(3, 2))


        self.fc=nn.Sequential(nn.Linear(256*6*6, 4096),
                                nn.ReLU(),
                                nn.Dropout(0.5),
                                nn.Linear(4096, 4096),
                                nn.ReLU(),
                                nn.Dropout(0.5),
                                nn.Linear(4096, 100),
                                )

    def forward(self, x):
        x=self.conv1(x)
        x=self.conv2(x)
        x=self.conv3(x)
        output=self.fc(x.view(-1, 256*6*6))
        return output

model=AlexNet()
for name in model.named_children():
    print(name[0])
#同理先看网络结构
#输出
"""
conv1
conv2
conv3
fc
"""


    
path = "test.jpg"
transformss = transforms.Compose(
    [transforms.ToTensor(),
     transforms.Resize((224, 224)),
     transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225])])

#注意如果有中文路径需要先解码,最好不要用中文
img = cv2.imread(path)
img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)

#转换维度
img = transformss(img).unsqueeze(0)

model = AlexNet()


## 修改这里传入的字典即可

new_model = torchvision.models._utils.IntermediateLayerGetter(model, {"conv1":1,"conv2":2,"conv3":3})
out = new_model(img)

tensor_ls=[(k,v) for  k,v in out.items()]

#选取conv2的输出
v=tensor_ls[1][1]

#取消Tensor的梯度并转成三维tensor,否则无法绘图
v=v.data.squeeze(0)

print(v.shape)  # torch.Size([512, 28, 28])


#随机选取25个通道的特征图
channel_num = random_num(25,v.shape[0])
plt.figure(figsize=(10, 10))
for index, channel in enumerate(channel_num):
    ax = plt.subplot(5, 5, index+1,)
    plt.imshow(v[channel, :, :])  # 灰度图参数cmap="gray"
plt.savefig("feature.jpg",dpi=300)


也就是说AlexNet这里分为了4部分,三个卷积和一个全连接(其实就是我们自己定义的foward前向传播),我们想要哪层的输出改个字典就好了,new_model = torchvision.models._utils.IntermediateLayerGetter(model, {“conv1”:1,“conv2”:2,“conv3”:3}),得到的特征图如下。

【Pytorch】 特征图的可视化
plt.imshow(v[channel, :, :],cmap="gray") 加上cmap参数就可以显示灰度图
【Pytorch】 特征图的可视化


总结

IntermediateLayerGetter有一个不足就是它不能获取二级层的输出,比如ResNet的layer2,他不能获取layer2里面的卷积的输出。文章来源地址https://www.toymoban.com/news/detail-416929.html

到了这里,关于【Pytorch】 特征图的可视化的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 多模型图像特征可视化

            特征图可视化是指将网络中某一层的特征图可视化出来,以便观察网络在不同层次上学到的特征。卷积可视化可以帮助深度学习研究者更好地理解卷积的概念和原理,从而更好地设计和优化卷积神经网络。通过可视化,研究者可以更清晰地看到卷积运算中的每一个

    2024年01月17日
    浏览(33)
  • 特征可视化技术(CAM)

    https://zhuanlan.zhihu.com/p/269702192 CAM技术可以帮助我们理解CNN在图像中寻找目标对象的过程,并且可以用于可视化CNN的中间层特征,以及对图像分类结果的解释和可视化。CAM技术的实现比较简单,可以使用常用的深度学习框架如PyTorch和TensorFlow来实现。 CAM(Class Activation Map)是一

    2024年02月02日
    浏览(41)
  • 可视化CNN和特征图

    卷积神经网络(cnn)是一种神经网络,通常用于图像分类、目标检测和其他计算机视觉任务。CNN的关键组件之一是特征图,它是通过对图像应用卷积滤波器生成的输入图像的表示。 1、卷积操作 卷积的概念是CNN操作的核心。卷积是一种数学运算,它把两个函数结合起来产生第三

    2023年04月10日
    浏览(44)
  • Python可视化学习——使用JSON进行数据转换、pyecharts模块调用以及可视化案例的介绍(可视化案例数据暂无),柱状图及动态柱状图的构建

    可视化效果一:2020年印美日新冠累计确诊人数 2020年是新冠疫情爆发的一年,随着疫情的爆发,国内外确诊人数成了大家关心的热点,相信大家都有看过类似的疫情报告.本案例对印度美国日本三个国家确诊人数的进行了可视化处理,形成了可视化的疫情确诊人数报告.  可视

    2024年02月01日
    浏览(78)
  • 【Python】可视化:常见统计图的汇总(含源代码示例)

    Python有很多可视化库可以用于各类统计图的绘制,比如常用的matplotlib、seaborn、plotly、bokeh等。 下面简单介绍一些基本的统计图及其Python实现方法: 直方图(Histogram) 直方图是用于表示连续变量分布情况的一种统计图形。通常将连续变量按照一定的间隔分成若干个区间,然后

    2023年04月21日
    浏览(348)
  • 网络特征之PCA可视化-Python实现

    PCA也是对网络特征可视化的一种方法,目的是对特征进行降维,然后通过图片的形式来对网络的特征提供一种解释。 所以,本博客提供一个将网络特征进行PCA的可视化的代码,其原理为将C通道的特征降维到3通道,即图片的RGB通道,然后直接进行可视化。 关于PCA和t-SNE的差异

    2023年04月08日
    浏览(51)
  • Python数据可视化化第五节(子图的绘制及坐标轴共享)

    matplotlib可以将整个画布规划成等分布局的m n(行 列)的矩阵区域,并按照先行后列的·方式对每个区域进行编号(编号从1开始),之后在选中的某个区域或某些区域中绘制单个‘或多个子图。 使用pyplot的subplot()函数可以规划好的某个区域中绘制单个子图,subplot()函数的语法格

    2024年02月02日
    浏览(38)
  • CNNs:ZFNet之基于AlexNet特征可视化实验分析

    上一篇我们介绍了如何利用 Deconvnet 网络进行特征可视化操作,本篇我们将基于 Deconvnet 对文献中的相关实验进行分析,并验证一些结论。除此之外,我们还将针对实验现象对对 AlexNet 网络进行微调( ZFNet ),并对网络进行简单介绍。然后基于 ZFNet 进行实验分析。 实验条件:

    2024年02月07日
    浏览(33)
  • 3DSC特征描述符、对应关系可视化以及ICP配准

    pcl::NormalEstimationOMPpcl::PointXYZ, pcl::Normal n; : pcl::NormalEstimationOMP  是一个用于估计点云法线的类,它利用了 OpenMP 进行多线程加速。 pcl::PointXYZ, pcl::Normal  指定输入点云类型为  pcl::PointXYZ ,输出法线类型为  pcl::Normal 。 pcl::PointCloudpcl::Normal::Ptr normals(new pcl::PointCloudpcl::Normal);

    2024年02月19日
    浏览(35)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包