美文网首页人工智能
特征可视化技术——CAM

特征可视化技术——CAM

作者: 星光下的胖子 | 来源:发表于2021-01-22 16:33 被阅读0次

前言

深度学习是一个“黑盒系统”,它通过“end-end”的方式来工作,图像数据作为输入,输出类别标签、回归值等信息,中间过程不可见。如何才能打开“黑盒”,一探究竟,让“黑盒”变成“灰盒”,甚至“白盒”?于是有了“深度学习可解释性”这一研究领域,而 CAM 技术就是其中之一,其利用“特征可视化”来探究深度卷积神经网络的工作机制和判断依据。

CAM的概念

CAM(Class Activation Mapping,类别激活映射图),亦称为类别热力图或显著性图。它的大小与原图一致,像素值表示原始图片的对应区域对预测输出的影响程度,值越大贡献越大。

像素值的取值范围从0到1,一般也用0~255的灰度图表示。示例:

cam_gray = np.uint8(255 * cam)  # 转换为0~255的灰度图

为了更直观的表达,可更进一步将灰度图转换为彩色图。示例:

cam_color = cv2.applyColorMap(cam_gray, cv2.COLORMAP_HSV)  # 转换成伪彩色图

一般用热力图和原图叠加的形式进行呈现,如下所示:

CAM 的作用

CAM 的作用:

  • 1)有助于理解和分析神经网络的工作原理及决策过程,进而更好地选择或设计网络。
    不同模型对同一张图的 CAM 是有差异的,同一个模型的不同训练过程的 CAM 也是有差异的。参考 CAM 我们可以对设计的网络提出更高的要求:不但关注预测准确率,还可关注网络是否提取到我们需要的特征。例如对于两个模型 A、B,若它们的 accuracy 一致,但从 CAM 上看到 A 相对 B 提取更多所需的特征(高亮区域更集中在目标附近),那么我们判断模型 A 更好一些。
  • 2)利用可视化的信息引导网络更好的学习。
    例如可利用 CAM 信息通过"擦除"或"裁剪"的方式对数据进行增强。
  • 3)利用 CAM 作为原始的种子,进行弱监督语义分割或弱监督定位。
    由于 CAM 能够覆盖到目标物体,因此仅利用分类标注也可用来完成语义分割或目标检测任务,这极大程度降低了标注的工作量。当然,对分类网络的 CAM 精度的要求很高,不然误差相对较大。

CAM 的获取步骤

总结 CAM 的获取步骤:

  • 1)提取需要可视化的特征图,例如尺寸为512*7*7的张量;
  • 2)获取该张量的每个 channel 的权重,即长度为512的向量;
  • 3)通过线性融合的方式,将该张量在 channel 维度上加权求和,获取尺寸为7*7的 map;
  • 4)对该 map 进行归一化,并通过插值的方式 resize 成和原图一样的尺寸。

利用 GAP 获取 CAM

GAP(Global Average Pooling,全局平均池化操作),可直接将 C*W*H 的特征图转换成 C*1*1。分别选用 resnet18、resnet50、densenet121 三种不同的模型,结合 hook 机制获取 CAM:

import numpy as np
from torchvision import models, transforms
import cv2
from PIL import Image
from torch.nn import functional as F

# 定义预训练模型: resnet18、resnet50、densenet121
resnet18 = models.resnet18(pretrained=True)
resnet50 = models.resnet50(pretrained=True)
densenet121 = models.densenet121(pretrained=True)
resnet18.eval()
resnet50.eval()
densenet121.eval()

# 图片数据转换
image_transform = transforms.Compose([
    # 将输入图片resize成统一尺寸
    transforms.Resize([224, 224]),
    # 将PIL Image或numpy.ndarray转换为tensor,并除255归一化到[0,1]之间
    transforms.ToTensor(),
    # 标准化处理-->转换为标准正太分布,使模型更容易收敛
    transforms.Normalize(
        mean=[0.485, 0.456, 0.406],
        std=[0.229, 0.224, 0.225]
    )
])

# =====注册hook start=====
feature_data = []


def feature_hook(model, input, output):
    feature_data.append(output.data.numpy())


resnet18._modules.get('layer4').register_forward_hook(feature_hook)
resnet50._modules.get('layer4').register_forward_hook(feature_hook)
densenet121._modules.get('features').register_forward_hook(feature_hook)
# =====注册hook end=====

# 获取fc层的权重
fc_weights_resnet18 = resnet18._modules.get('fc').weight.data.numpy()
fc_weights_resnet50 = resnet50._modules.get('fc').weight.data.numpy()
fc_weights_densenet121 = densenet121._modules.get('classifier').weight.data.numpy()

# 获取预测类别id
image = image_transform(Image.open("cat.jpg")).unsqueeze(0)
out_resnet18 = resnet18(image)
out_resnet50 = resnet50(image)
out_densenet121 = densenet121(image)
predict_classes_id_resnet18 = np.argmax(F.softmax(out_resnet18, dim=1).data.numpy())
predict_classes_id_resnet50 = np.argmax(F.softmax(out_resnet50, dim=1).data.numpy())
predict_classes_id_densenet121 = np.argmax(F.softmax(out_densenet121, dim=1).data.numpy())


# =====获取CAM start=====
def makeCAM(feature, weights, classes_id):
    print(feature.shape, weights.shape, classes_id)
    # batchsize, C, h, w
    bz, nc, h, w = feature.shape
    # (512,) @ (512, 7*7) = (49,)
    cam = weights[classes_id].dot(feature.reshape(nc, h * w))
    cam = cam.reshape(h, w)  # (7, 7)
    # 归一化到[0, 1]之间
    cam = (cam - cam.min()) / (cam.max() - cam.min())
    # 转换为0~255的灰度图
    cam_gray = np.uint8(255 * cam)
    # 最后,上采样操作,与网络输入的尺寸一致,并返回
    return cv2.resize(cam_gray, (224, 224))


cam_gray_resnet18 = makeCAM(feature_data[0], fc_weights_resnet18, predict_classes_id_resnet18)
cam_gray_resnet50 = makeCAM(feature_data[1], fc_weights_resnet50, predict_classes_id_resnet50)
cam_gray_densenet121 = makeCAM(feature_data[2], fc_weights_densenet121, predict_classes_id_densenet121)
# =====获取CAM start=====

# =====叠加CAM和原图,并保存图片=====
# 1)读取原图
src_image = cv2.imread("cat.jpg")
h, w, _ = src_image.shape
# 2)cam转换成与原图大小一致的彩色度(cv2.COLORMAP_HSV为彩色图的其中一种类型)
cam_color_resnet18 = cv2.applyColorMap(cv2.resize(cam_gray_resnet18, (w, h)),
                                       cv2.COLORMAP_HSV)
cam_color_resnet50 = cv2.applyColorMap(cv2.resize(cam_gray_resnet50, (w, h)),
                                       cv2.COLORMAP_HSV)
cam_color_densenet121 = cv2.applyColorMap(cv2.resize(cam_gray_densenet121, (w, h)),
                                          cv2.COLORMAP_HSV)
# 3)合并cam和原图,并保存
cam_resnet18 = src_image * 0.5 + cam_color_resnet18 * 0.5
cam_resnet50 = src_image * 0.5 + cam_color_resnet50 * 0.5
cam_densenet121 = src_image * 0.5 + cam_color_densenet121 * 0.5
cam_hstack = np.hstack((src_image, cam_resnet18, cam_resnet50, cam_densenet121))
cv2.imwrite("cam_hstack.jpg", cam_hstack)
# 可视化
Image.open("cam_hstack.jpg").show()

最终的可视化效果如下图所示(从左到右依次是原图、cam_resnet18、cam_resnet50、cam_densenet121):

可见,不同的模型得到的 CAM 效果不同,从覆盖区域来看,densenet121 的效果相对更好一些。

更通用的获取 CAM 的方法——Grad-CAM

利用 GAP 获取 CAM 的方式有它的局限性:

  • 1)要求模型必须有 GAP 层;
  • 2)只能提取最后一层特征图的热力图。

Grad-CAM 是为了克服上面的缺陷而提出的,Grad-CAM 可适用于非 GAP 的网络结构,并且可提取任意层的热力图。

相关文章

  • 特征可视化技术——CAM

    前言 深度学习是一个“黑盒系统”,它通过“end-end”的方式来工作,图像数据作为输入,输出类别标签、回归值等信...

  • 中间特征可视化

    中间特征可视化 参考: PyTorch | 提取神经网络中间层特征进行可视化 参考: pytorch模型中间层特...

  • 深度学习的可解释性|Class Activation Mappi

    CAM 特征图经过 GAP 处理后每一个特征图包含了不同类别的信息,其具体效果如上图的 Class Activat...

  • Lecture 12 可视化和理解CNN

    本课重点 特征可视化 DeepDream 风格迁移 1 特征可视化 之前一直把CNN当做黑盒子处理,那么其工作原理...

  • Visualizing the Resilience of De

    可视化深度卷积网络解释型的弹性 (1)跨数据集 (2)网络权重损毁 (3)用在遥感图像上,利用CAM,证明弹性 (...

  • 使用PHATE可视化单细胞数据

    在单细胞标准分析中,在两个地方使用了降维技术,特征提取和可视化。特征提取我们都知道用的是PCA,在数据分析领域是比...

  • 数控加时选择正确的走刀方式,让你的加工效率翻倍!

    随着现代制造加工技术的不断发展,数控加工设备和其配套的CAM 系统得到了广泛的应用和发展。CAM 系统生成的加工刀...

  • 异常处理

    异常值检测特征分为类别特征和数字特征 数字特征 相关性分析、查看特征的偏度和峰度、数字特征相互之间的关系可视化、多...

  • 网络安全态势可视化

    导语 网络态势可视化技术作为一项新技术,是网络安全态势感知与可视化技术的结合,将网络中蕴涵的态势状况通过可视化图形...

  • 2019年深圳国际凸轮分割器及减速机展览会

    2019深圳国际凸轮分割器及减速机技术应用展览会 2019 Shenzhen International Cam ...

网友评论

    本文标题:特征可视化技术——CAM

    本文链接:https://www.haomeiwen.com/subject/twfdzktx.html