ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

CNN卷积特征可视化

2021-10-03 19:32:53  阅读:202  来源: 互联网

标签:img 卷积 outputs 可视化 CNN output save


CNN卷积特征可视化

可视化准备工作:
我们将要进行的工作包括:
创建CNN特征提取器,本文使用PyTorch自带的resnet34
创建一个保存hook内容的对象
为每个卷积层创建hook
导入需要使用的库

对以下图片进行可视化
在这里插入图片描述

用到的python库

import numpy as np

import torch
import torchvision
from PIL import Image
from torchvision import transforms as T

import matplotlib.pyplot as plt

创建CNN特征提取器

import torch
import torchvision

feature_extractor = torchvision.models.resnet34(pretrained=True)
if torch.cuda.is_available():
	feature_extractor.cuda()

device = torch.device('cuda') if torch.cuda.is_available() else torch.device('cpu')

创建保存hook内容的对象

class SaveOutput:
	def __init__(self):
		self.outputs = []
	def __call__(self, module, module_in, module_out):
		self.outputs.append(module_out)
	def clear(self):
		self.outputs=[]
		
save_output = SaveOutput()

为卷积层注册hook

hook_handles = []

for layer in feature_extractor.modules():
	if isinstance(layer, torch.nn.Conv2d):
		handle = layer.register_forward_hook(save_output)
		hook_handles.append(handle)

读取图像并进行特征提取

from PIL import Image
from torchvision import transforms as T

image = Image.open('cat.jpg')
transform = T.Compose([T.Resize((224, 224)), T.ToTensor()])
X = transform(image).unsqueeze(dim=0).to(device)

out = feature_extractor(X)

查看卷积层特征提取效果

在这里插入图片描述
卷积层共有1+6+(42+1)+(62+1)+(32+1)=36个,对conv3_x层有42+1卷积层的原因是(1)四个basicblock本身有4*2个卷积层(2)其中一个basicblock进行了downsample,又多了一个卷积层

可视化哪些卷积层

对于resnet34来说,我们计划可视化其第1、2、15、28个卷积层

第一个卷积层是conv1_x的输出,图片轮廓较为清楚
第二、七个卷积层是conv2_x首个和末尾卷积层的输出,我们将其与第一个卷积层输出对比可以得到特征逐渐高层化的结论
第十五个卷积层是conv3_x的输出
第二十八个卷积层是conv4_x的输出

为何不可视化最后一个卷积层?

对于最后一个卷积层,其每个通道的像素仅仅为7x7,可视化也看不出什么东西。或者说我们可视化第二十八个卷积层后,就发现继续可视化没有必要了。

提取计划可视化的卷积层结果

每个卷积层的结果都通过hook保存到了save_output.outputs里面,我们查看是否为36个结果
我们创建一个拼接卷积结果的函数。对每个卷积层来说,其结果都是由许多单通道图片组成(比如第一个卷积层的通道为64,因此有64张单通道图片),因此我们首先需要将这些单通道图片进行拼接一张单通道大图。

临时查看

我们查看是否为36个结果并查看计划可视化的层的shape

print(len(save_output.outputs))
a_list = [0, 1, 6, 15, 28, 35]
for i in a_list:
    print(save_output.outputs[i].cpu().detach().squeeze(0).shape)

在这里插入图片描述

拼接函数

def grid_gray_image(imgs, each_row: int):
    '''
    imgs shape: batch * size (e.g., 64x32x32, 64 is the number of the gray images, and (32, 32) is the size of each gray image)
    '''
    row_num = imgs.shape[0]//each_row
    for i in range(row_num):
        img = imgs[i*each_row]
        img = (img - img.min()) / (img.max() - img.min())
        for j in range(1, each_row):
            tmp_img = imgs[i*each_row+j]
            tmp_img = (tmp_img - tmp_img.min()) / (tmp_img.max() - tmp_img.min())
            img = np.hstack((img, tmp_img))
        if i == 0:
            ans = img
        else:
            ans = np.vstack((ans, img))
    return ans

提取计划可视化的卷积层结果

img0 = save_output.outputs[0].cpu().detach().squeeze(0)
img0 = grid_gray_image(img0.numpy(), 8)
img1 = save_output.outputs[1].cpu().detach().squeeze(0)
img1 = grid_gray_image(img1.numpy(), 8)
img6 = save_output.outputs[6].cpu().detach().squeeze(0)
img6 = grid_gray_image(img6.numpy(), 8)
img15 = save_output.outputs[15].cpu().detach().squeeze(0)
img15 = grid_gray_image(img15.numpy(), 16)
img29 = save_output.outputs[28].cpu().detach().squeeze(0)
img29 = grid_gray_image(img29.numpy(), 16)

对第1层进行可视化

plt.figure(figsize=(15, 15))
plt.imshow(img1, cmap='gray')

在这里插入图片描述

对第29层进行可视化

plt.figure(figsize=(15, 15))
plt.imshow(img29, cmap='gray')

在这里插入图片描述

标签:img,卷积,outputs,可视化,CNN,output,save
来源: https://blog.csdn.net/Viraha_/article/details/120597339

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有