卷积核可视化是一种用于理解卷积神经网络 (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 transforms
def 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 transforms
def 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)
以上就是今天要讲的内容,本文仅仅简单介绍了卷积核可视化的计算