使用pytorch查看中间层特征矩阵以及卷积核参数

这里是记录如何查看网络结构和特征图信息 的笔记,是一个学习记录

内容来自于B站视频:霹雳吧啦Wz

根据up本次讲的内容,主要包括如下4个部分
其中:
AlexNet.pth 是训练5种花分类数据集的权重文件,这里是和模型相对应的,因为模型是自己搭建的,从官网下载的是不能用的
alexnet_model.py 是自己搭建的alexnet的实现过程
analyze_feature_map.py 是查看网络前向传播过程中的特征图部分代码
analyze_kernel_weight.py 是查看网络搭建过程中的核参数部分代码
打印模型的网络结构 :打印出来的模型结构和搭建的模型结构保持一致

这里有两个层结构features和classifier

定义的这两个层结构都是通过nn.Sequential这个类打包一系列结构实现

打印出来的结构和搭建的网络对比如下,都是一一对应:

但是,搭建出来的网络和以前搭建出来的网络,唯一不同的地方就是正向传播过程,因为需要得到中间层输出的特征矩阵,不同之处和具体的意义如下:

可以设置断点打印,查看是不是和想的一样,如下:

这里可以看出每遍历一个,都会输出相应的结果,执行的每一步都和代码结构对应的上

需要注意的是:Debug功能中,打上断点单步运行,调试的程序应该是有入口的程序,而不是调试函数,因为函数没有调用的话,就是调试也没有结果!(重要)

再次设置断点,今天调试,看看输出的结果:

这里的结果是刚刚说到的**(0,3,6)这个列表!返回了第1个,第3个,第6层**,也就是前3个卷积层!

python 复制代码
# alexnet_model部分代码
import torch.nn as nn
import torch


class AlexNet(nn.Module):
    def __init__(self, num_classes=1000, init_weights=False):
        super(AlexNet, self).__init__()
        self.features = nn.Sequential(
            nn.Conv2d(3, 48, kernel_size=11, stride=4, padding=2),  # input[3, 224, 224]  output[48, 55, 55]
            nn.ReLU(inplace=True),
            nn.MaxPool2d(kernel_size=3, stride=2),                  # output[48, 27, 27]
            nn.Conv2d(48, 128, kernel_size=5, padding=2),           # output[128, 27, 27]
            nn.ReLU(inplace=True),
            nn.MaxPool2d(kernel_size=3, stride=2),                  # output[128, 13, 13]
            nn.Conv2d(128, 192, kernel_size=3, padding=1),          # output[192, 13, 13]
            nn.ReLU(inplace=True),
            nn.Conv2d(192, 192, kernel_size=3, padding=1),          # output[192, 13, 13]
            nn.ReLU(inplace=True),
            nn.Conv2d(192, 128, kernel_size=3, padding=1),          # output[128, 13, 13]
            nn.ReLU(inplace=True),
            nn.MaxPool2d(kernel_size=3, stride=2),                  # output[128, 6, 6]
        )
        self.classifier = nn.Sequential(
            nn.Dropout(p=0.5),
            nn.Linear(128 * 6 * 6, 2048),
            nn.ReLU(inplace=True),
            nn.Dropout(p=0.5),
            nn.Linear(2048, 2048),
            nn.ReLU(inplace=True),
            nn.Linear(2048, num_classes),
        )
        if init_weights:
            self._initialize_weights()

    def forward(self, x): #和原来搭建的alexnet不一样,需要得到中间输出的特征矩阵
        outputs = []
        for name, module in self.features.named_children(): #遍历搭建的features层结构,包括层名称和层结构两个部分
            x = module(x)
            if name in ["0", "3", "6"]:#这里是判断层名称是不是第1个,第2个和第3个
                outputs.append(x) #对于满足的层,都添加到output这个输出列表当中

        return outputs #返回output这个列表

    def _initialize_weights(self):
        for m in self.modules():
            if isinstance(m, nn.Conv2d):
                nn.init.kaiming_normal_(m.weight, mode='fan_out', nonlinearity='relu')
                if m.bias is not None:
                    nn.init.constant_(m.bias, 0)
            elif isinstance(m, nn.Linear):
                nn.init.normal_(m.weight, 0, 0.01)
                nn.init.constant_(m.bias, 0)
python 复制代码
# analyze_feature_map部分代码
import torch
from alexnet_model import AlexNet
from resnet_model import resnet34
import matplotlib.pyplot as plt
import numpy as np
from PIL import Image
from torchvision import transforms

# 这里是图像预处理过程,这个训练过程要和训练过程的图像预处理过程一致(重要)
data_transform = transforms.Compose(
    [transforms.Resize((224, 224)),
     transforms.ToTensor(),
     transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))])

# data_transform = transforms.Compose(
#     [transforms.Resize(256),
#      transforms.CenterCrop(224),
#      transforms.ToTensor(),
#      transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225])])

# create model
model = AlexNet(num_classes=5)  #实例化AlexNet模型,这里使用的是AlexNet这个模型
# model = resnet34(num_classes=5)
# load model weights

#这是训练出来的权重参数,注意,这个要和那个模型保持一致,必须是那个模型训练出来的,自己训练出来的权重文件,否则可能报错(权重与模型一致)!
model_weight_path = "./AlexNet.pth"  # "./resNet34.pth"
model.load_state_dict(torch.load(model_weight_path))  #载入预训练好的模型参数
print(model) #打印这个模型的结构

# load image
img = Image.open("../tulip.jpg") #载入一张图片
# [N, C, H, W]
img = data_transform(img)  #对载入的图片进行预处理
# expand batch dimension
img = torch.unsqueeze(img, dim=0) #增加一个batch维度

# forward
out_put = model(img) #把图片输入到这个模型,进行正向传播
for feature_map in out_put:
    # [N, C, H, W] -> [C, H, W]
    im = np.squeeze(feature_map.detach().numpy()) #将特征图转化为numpy格式,方便后续的分析 #就传入了一张图片,N维度是没有意义的,就把这一层给压缩掉
    # [C, H, W] -> [H, W, C]
    im = np.transpose(im, [1, 2, 0]) #将特征矩阵的排列方式进行改变

    # show top 12 feature maps 打印12张特征图
    plt.figure()
    for i in range(12):
        ax = plt.subplot(3, 4, i+1) #3行4列
        # [H, W, C]
        plt.imshow(im[:, :, i], cmap='gray')
    plt.show()

运动结果: 这里每一张图都是经过这个通道学习到的特征
第1个卷积层后

第2个卷积层后:

第3个卷积层后:

注意:

1.前面的层提取的是低层次特征,越往后的层提取的信息越高层次,也就越抽象

2.特征图中白色的部分代表的是,网络所关注的部分,也就是学习到的特征

3.全黑色的图说明卷积核并没有起到太多的作用,没有学到有用的信息

卷积核参数部分待补充...

相关推荐
勾股导航1 小时前
大模型Skill
人工智能·python·机器学习
卷福同学3 小时前
【养虾日记】Openclaw操作浏览器自动化发文
人工智能·后端·算法
春日见4 小时前
如何入门端到端自动驾驶?
linux·人工智能·算法·机器学习·自动驾驶
光锥智能4 小时前
从自动驾驶到 AI 能力体系,元戎启行 GTC 发布基座模型新进展
人工智能
luoganttcc4 小时前
自动驾驶 世界模型 有哪些
人工智能·机器学习·自动驾驶
潘高4 小时前
10分钟教你手撸一个小龙虾(OpenClaw)
人工智能
禁默4 小时前
光学与机器视觉:解锁“机器之眼”的核心密码-《第五届光学与机器视觉国际学术会议(ICOMV 2026)》
人工智能·计算机视觉·光学
深小乐4 小时前
不是DeepSeek V4!这两个神秘的 Hunter 模型竟然来自小米
人工智能
laozhao4324 小时前
科大讯飞中标教育管理应用升级开发项目
大数据·人工智能
rainbow7242444 小时前
AI人才简历评估选型:技术面试、代码评审与项目复盘的综合运用方案
人工智能·面试·职场和发展