https://zhuanlan.zhihu.com/p/269702192
CAM技术可以帮助我们理解CNN在图像中寻找目标对象的过程,并且可以用于可视化CNN的中间层特征,以及对图像分类结果的解释和可视化。CAM技术的实现比较简单,可以使用常用的深度学习框架如PyTorch和TensorFlow来实现。
CAM(Class Activation Map)是一种特征可视化技术,它可以帮助我们理解神经网络对图像分类的决策过程。CAM技术可以生成一个热力图,用来可视化输入图像中哪些区域对于神经网络的分类决策起到了重要作用。CAM技术主要适用于基于卷积神经网络的图像分类任务。
在CNN中,每个卷积层都会生成一组特征图,其中每个特征图对应一个卷积核。CAM技术利用全局平均池化(Global Average Pooling,GAP)操作来捕捉每个特征图中与目标类别相关的特征。然后,将这些特征映射到输入图像的空间位置上,从而生成对应于每个类别的类激活图(Class Activation Map)。
具体地说,CAM技术的步骤如下:
-
将图像输入到CNN中,并获得最后一个卷积层的输出特征图。
-
对于每个目标类别,计算其在卷积层输出特征图中的权重,即使用全局平均池化操作对该类别对应的特征图进行加权平均。
-
将这些权重与卷积层输出特征图相乘,并对结果进行求和,得到对应于该类别的类激活图(Class Activation Map)。
-
对类激活图进行归一化处理,从而得到可视化结果。
以下是一个简单的示例代码,它使用PyTorch和CAM技术来可视化图像中哪些区域对于神经网络的分类决策起到了重要作用:
import torch
import torch.nn as nn
import torchvision.transforms as transforms
import matplotlib.pyplot as plt
import numpy as np
# 加载预训练的ResNet50模型
model = torch.hub.load('pytorch/vision', 'resnet50', pretrained=True)
# 定义CAM模型
class CAM(nn.Module):
def __init__(self, feature_extractor, classifier):
super(CAM, self).__init__()
self.feature_extractor = feature_extractor
self.classifier = classifier
self.gradient = None
def gradients_hook(self, grad):
self.gradient = grad
def forward(self, x):
x = self.feature_extractor(x)
h = x.register_hook(self.gradients_hook)
x = self.classifier(x)
h.remove()
return x
# 定义CAM可视化函数
def visualize_CAM(image, model, target_class):
# 转换图像为张量
transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
])
image = transform(image).unsqueeze(0)
# 定义CAM模型
feature_extractor = nn.Sequential(*list(model.children())[:-2])
classifier = model.fc
cam_model = CAM(feature_extractor, classifier)
# 前向传播
output = cam_model(image)
target = torch.Tensor([target_class])
loss = nn.functional.binary_cross_entropy_with_logits(output, target)
# 反向传播
cam_model.zero_grad()
loss.backward()
# 计算CAM
features = cam_model.feature_extractor(image).detach().squeeze()
weights = cam_model.gradient.squeeze().mean(dim=(1, 2), keepdims=True)
cam = (weights * features).sum(dim=0)
cam = np.maximum(cam, 0)
cam = cam / cam.max()
# 可视化CAM
plt.imshow(image.squeeze().permute(1, 2, 0))
plt.imshow(cam, cmap='jet', alpha=0.5, interpolation='nearest')
plt.axis('off')
plt.show()
# 加载一张测试图像
image = plt.imread('test_image.jpg')
# 可视化CAM
visualize_CAM(image, model, target_class=0)
在上述代码中,我们首先加载了一个预训练的ResNet50模型,并定义了一个CAM模型。然后,我们定义了一个可视化CAM的函数,该函数接受一张图像、一个神经网络模型和一个目标类别,然后使用CAM技术生成一个热力图来可视化输入图像中哪些区域对于神经网络的分类决策起到了重要作用。最后,我们加载一张测试图像,并使用可视化CAM函数将其可视化。
请注意,这只是一个简单的示例代码,您可以根据需要进行修改来适应您的数据和可视化需求。