文章目录
- 前言
- 一般过程:
- 一、代码示例
- 二、卷积核和输入图片相乘可视化
- 总结
前言
卷积核可视化是一种用于理解卷积神经网络 (CNN) 中卷积层的工作原理和特征提取能力的方法。通过可视化卷积核,我们可以观察卷积层学习到的特征模式,帮助我们理解网络如何对输入进行处理。
本文给出了一个具体的pytorch实现的例子。
本文还给了一个用权重核和直接卷积图像的例子。
一般过程:
导入必要的库和模型:首先,你需要导入相关的库,如 PyTorch、NumPy 和 Matplotlib,并加载已经训练好的 CNN 模型。
获取卷积层权重:从模型中获取卷积层的权重。这些权重通常存储在模型的卷积层参数中。
可视化卷积核:对于每个卷积层,获取对应的权重,并以图像形式展示。可以使用 Matplotlib 或其他图像处理库来显示卷积核。
可选:对于多通道的卷积核,你可以将每个通道的权重分别可视化,以更好地理解卷积核的组成。
一、代码示例
以resnet50为例进行第一层可视化
import os
import numpy as np
import torch
from PIL import Image
import matplotlib.pyplot as plt
from torchvision import models
from torchvision import transformsdef visualize_conv_filters():# 设置GPU设备torch.cuda.set_device(0) # 没有GPU可以删除model = models.resnet50(pretrained=True)model = model.cuda() # 将模型移动到GPU上 # 没有GPU可以删除# 获取第一个卷积层的权重conv1_weights = model.conv1.weight.data.cpu().numpy()# 调整权重形状,从 [out_channels, in_channels, kernel_size, kernel_size] 变为 [out_channels, kernel_size, kernel_size, in_channels]conv1_weights = np.transpose(conv1_weights, (0, 2, 3, 1))# 可视化卷积核fig, axes = plt.subplots(nrows=8, ncols=8, figsize=(12, 12))for i, ax in enumerate(axes.flat):ax.imshow(conv1_weights[i])ax.axis('off')plt.show()if __name__ == '__main__':visualize_conv_filters()
获得图像:
二、卷积核和输入图片相乘可视化
把卷积核(作为权重)和图片进行卷积操作
import os
import numpy as np
import torch
from PIL import Image
import matplotlib.pyplot as plt
from torchvision import models
from torchvision import transformsdef visualize_conv_filters(model_conv, img_file):# 设置GPU设备# torch.cuda.set_device(gpu_number)# model = models.resnet50(pretrained=True)# model = model.cuda() # 将模型移动到GPU2上# 获取第一个卷积层的权重conv1_weights = model_conv.weight.data.cpu().numpy()# 调整权重形状,从 [out_channels, in_channels, kernel_size, kernel_size] 变为 [out_channels, kernel_size, kernel_size, in_channels]conv1_weights = np.transpose(conv1_weights, (0, 2, 3, 1))# 读入图像image = Image.open(img_file)image = transforms.ToTensor()(image)image = image.unsqueeze(0) # 添加批次维度并将图像移动到GPU上# 对每个卷积核进行卷积操作并绘制图像fig, axes = plt.subplots(nrows=8, ncols=4, figsize=(12, 6),dpi=100)al_list = range(conv1_weights.shape[0])for i, ax in zip(al_list, axes.flat):conv1_weight = conv1_weights[i]conv1_weight = torch.from_numpy(conv1_weight).permute(2, 0, 1).cuda() # 将当前卷积核移动到GPU上# 对图像的每个通道进行卷积操作output_channels = []for channel in range(conv1_weight.size(0)):conv1_weight_ = torch.unsqueeze(conv1_weight, 0)## 重点代码,卷积操作output_channel = torch.nn.functional.conv2d(image[:,channel:channel+1,:,:],conv1_weight_[:,channel:channel+1,:,:],stride=(1, 1), padding=0)output_channels.append(output_channel)# 合并卷积后的通道output = torch.cat(output_channels, dim=1)# 转换为NumPy数组并绘制图像output = output.squeeze(0).cpu().detach().numpy() # 移除批次维度,并将结果移动到CPU上output = np.transpose(output, (1, 2, 0)) # 调整形状为 [height, width, channels]ax.imshow(output)ax.axis('off')# input('>>')if not os.path.exists('./img/'):os.mkdir('./img/')plt.savefig('./img/abc.png')if __name__ == '__main__':model = models.resnet50(pretrained=True)torch.cuda.set_device(0)img_file = 'img_1.png'visualize_conv_filters(model.conv1, img_file)
原图:
乘以卷积核之后的可视化结果:
总结
以上就是今天要讲的内容,本文仅仅简单介绍了卷积核可视化的计算