news 2026/6/10 19:44:21

Day 50 注意力热图可视化

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Day 50 注意力热图可视化

@浙大疏锦行

一、核心概念

注意力热图的本质是注意力权重矩阵的可视化映射

  • 权重值越高 → 热图颜色越深(如红色),代表模型越关注该部分输入
  • 权重值越低 → 热图颜色越浅(如蓝色),代表模型对该部分关注度低

在深度学习中,注意力热图主要分为两类:

  1. NLP 领域:基于 Transformer 的自注意力热图,展示 token 之间的关联权重
  2. CV 领域:基于 CAM/Grad-CAM 的特征注意力热图,展示图像区域对分类结果的贡献

二、CV - Grad-CAM 注意力热图可视化

在计算机视觉中,Grad-CAM 通过梯度加权激活图展示图像中对分类结果关键的区域,适用于 CNN 模型(如 ResNet、ViT)。

核心原理

  1. 计算目标类别对模型最后一个卷积层特征图的梯度
  2. 用梯度权重对特征图进行加权求和
  3. 将加权后的特征图上采样至原图尺寸,得到注意力热图

简化代码示例

import torch import torch.nn.functional as F import matplotlib.pyplot as plt from PIL import Image from torchvision import models, transforms # 1. 加载模型和图像预处理 model = models.resnet50(pretrained=True) model.eval() # 预处理:图像→张量 preprocess = transforms.Compose([ transforms.Resize((224, 224)), transforms.ToTensor(), transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]) ]) # 2. 加载并预处理图像 img = Image.open("cat.jpg").convert("RGB") img_tensor = preprocess(img).unsqueeze(0) # (1, 3, 224, 224) # 3. 注册钩子获取特征图和梯度 feature_maps = [] grads = [] def forward_hook(module, input, output): feature_maps.append(output) def backward_hook(module, grad_in, grad_out): grads.append(grad_out[0]) # 注册到最后一个卷积层 target_layer = model.layer4[-1] forward_handle = target_layer.register_forward_hook(forward_hook) backward_handle = target_layer.register_full_backward_hook(backward_hook) # 4. 前向传播+反向传播 preds = model(img_tensor) pred_class = preds.argmax(dim=1).item() model.zero_grad() preds[:, pred_class].backward() # 5. 计算Grad-CAM权重 fm = feature_maps[0].squeeze() # (2048, 7, 7) grad = grads[0].squeeze() # (2048, 7, 7) weights = F.adaptive_avg_pool2d(grad, (1, 1)).squeeze() # (2048,) cam = torch.sum(weights[:, None, None] * fm, dim=0) # (7, 7) cam = F.relu(cam) # 只保留正贡献 cam = F.interpolate( cam.unsqueeze(0).unsqueeze(0), size=img.size[::-1], mode="bilinear", align_corners=False ).squeeze() cam = cam / cam.max() # 归一化 # 6. 绘制热图叠加原图 plt.figure(figsize=(10, 10)) plt.imshow(img) plt.imshow(cam.numpy(), alpha=0.5, cmap="jet") plt.axis("off") plt.title(f"Grad-CAM Attention (Class: {pred_class})") plt.show() # 移除钩子 forward_handle.remove() backward_handle.remove()

三、步骤总结

步骤 1:准备工作(模型 + 图像预处理)

核心目的:搭建可提取梯度和特征图的模型环境,将原始图像转为模型可处理的张量

  1. 选择并加载 CNN 模型:优先选择包含卷积层 + 全连接层的模型(预训练 / 自定义均可),关键是保留最后一层卷积层(高层特征包含语义信息,可视化有意义;低层仅边缘纹理,无分类参考价值)。
  2. 图像预处理:严格遵循模型输入规范(尺寸、归一化参数),转为张量并增加批次维度(模型要求批量输入)。
  3. 模型设置:设为eval()模式(关闭 Dropout、BatchNorm 等训练层),但不使用torch.no_grad()(因为需要计算梯度,no_grad()会禁用梯度传播)。

步骤 2:捕获最后一层卷积层的「特征图」和「梯度」(核心:Hook 函数)

核心目的:通过 Hook 函数获取两个关键数据 —— 最后卷积层的输出(特征图)、目标类别对该特征图的梯度(反映通道重要性)。这是 Grad-CAM 的核心基础,因为后续所有计算都依赖这两个数据,具体操作:

  1. 定义两个 Hook 函数:前向 Hook 捕获特征图,反向 Hook 捕获梯度;
  2. 定位最后一层卷积层:以 ResNet18 为例,最后一层卷积层是model.layer4[-1].conv2
  3. 注册 Hook 并保存句柄:后续需移除 Hook,避免内存泄漏。

步骤 3:前向传播,获取目标类别

核心目的:通过前向传播得到模型的预测结果,确定要可视化的「目标类别」(可选择模型预测类别,也可自定义类别)

  1. 执行前向传播,得到模型对输入图像的预测输出;
  2. 提取预测类别(argmax获取概率最大的类别),作为后续反向传播的目标。

步骤 4:反向传播,计算目标类别的梯度

核心目的:针对目标类别执行反向传播,触发反向 Hook 函数,捕获该类别对最后卷积层特征图的梯度。关键细节:

  1. 清零现有梯度:用model.zero_grad()避免梯度累积;
  2. 仅对目标类别的输出值反向传播:不是对整个损失函数反向传播,而是直接对pred_output[0, target_class]反向传播,这样得到的梯度仅反映该类别对特征图的贡献;
  3. 反向传播后,gradient变量会被 Hook 函数填充,得到目标类别对应的梯度。

步骤 5:计算梯度权重(全局平均池化 GAP)

核心目的:将每个通道的梯度压缩为一个标量权重,反映该通道对目标类别的「重要性」。为什么用全局平均池化(GAP)?因为最后卷积层的梯度形状是(1, C, H, W)(C = 通道数,H/W = 特征图尺寸),每个通道对应一个特征图,我们需要用一个标量来代表该通道的重要性,GAP 可以将每个通道的(H, W)梯度值平均为一个标量,具体操作:

  1. 对梯度在「空间维度」(H、W)上执行平均池化,保留通道维度;
  2. 得到的权重形状为(1, C, 1, 1),每个值对应一个通道的重要性。

步骤 6:加权求和生成原始 CAM 图,ReLU 激活过滤负贡献

核心目的:用通道权重对特征图进行加权求和,生成原始 CAM 图,并过滤负贡献(仅保留对分类有帮助的区域)。具体操作:

  1. 加权求和:将通道权重与对应的特征图通道相乘,然后沿通道维度求和,消除通道维度,得到原始 CAM 图;
  2. ReLU 激活:Grad-CAM 的核心创新之一,只保留正贡献(值 > 0),负贡献对目标类别分类无帮助,直接过滤,避免干扰可视化结果;
  3. 原始 CAM 图的形状与最后卷积层特征图一致(如(7, 7)),尺寸较小,需后续上采样。

步骤 7:上采样至原图尺寸,归一化处理

核心目的:将小尺寸的原始 CAM 图放大至与输入图像一致的尺寸,方便叠加可视化,并归一化到 0-1 区间,避免颜色失真。具体操作:

  1. 上采样:使用双线性插值(bilinear),效果优于最近邻插值,能保持热图的平滑性;
  2. 归一化:将 CAM 图的值压缩到 0-1 区间,消除数值范围差异对可视化的影响。

步骤 8:热图可视化,叠加原图展示结果

核心目的:将 CAM 图转换为彩色热图,并与原始图像叠加,直观展示模型的注意力区域。具体操作:

  1. 将 CAM 图转换为彩色热图:使用 OpenCV 的applyColorMap,常用COLORMAP_JET(红 = 高权重,蓝 = 低权重);
  2. 格式转换与归一化:将 OpenCV 的 BGR 格式转为 RGB 格式,与原始图像格式对齐;
  3. 叠加原图:设置透明度(如原图 0.7,热图 0.3),平衡原图和热图的可见性;
  4. 移除 Hook 句柄:释放内存,避免后续干扰。
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/6/10 3:06:29

基于TensorRT的实时翻译系统性能优化案例

基于TensorRT的实时翻译系统性能优化案例 在一场国际线上会议中,发言者刚说完一句话,参会者的耳机里几乎立刻响起了流畅的母语翻译——没有卡顿、没有延迟,仿佛有人在背后实时同声传译。这种“即时可懂”的体验背后,是自然语言处理…

作者头像 李华
网站建设 2026/6/10 12:50:25

深度探索.NET 中 IAsyncEnumerable:异步迭代的底层奥秘与高效实践

深度探索.NET 中 IAsyncEnumerable&#xff1a;异步迭代的底层奥秘与高效实践 在.NET 开发中&#xff0c;处理大量数据或执行异步操作时&#xff0c;异步迭代成为提升性能和响应性的关键技术。IAsyncEnumerable<T> 接口为此提供了强大支持&#xff0c;它允许以异步方式逐…

作者头像 李华
网站建设 2026/6/10 12:52:26

对比测评:TensorRT vs TorchScript vs OpenVINO推理表现

推理引擎三巨头&#xff1a;TensorRT、TorchScript 与 OpenVINO 深度对比 在当前 AI 模型从实验室走向产线的过程中&#xff0c;推理效率已成为决定系统成败的关键瓶颈。一个在训练时表现优异的模型&#xff0c;若无法在实际场景中实现低延迟、高吞吐的稳定推理&#xff0c;其商…

作者头像 李华
网站建设 2026/6/10 3:12:52

机器学习数据集完全指南:从公开资源到Sklearn实战

机器学习数据集完全指南&#xff1a;从公开资源到Sklearn实战1. 引言&#xff1a;为什么数据集如此重要&#xff1f;2. 机器学习公开数据集大全2.1 综合型数据集平台2.2 领域特定数据集3. Sklearn内置数据集详解3.1 小型玩具数据集3.2 大型真实世界数据集3.3 完整列表4. Sklear…

作者头像 李华
网站建设 2026/6/10 12:51:45

避免踩坑:TensorRT模型转换常见错误及解决方案

避免踩坑&#xff1a;TensorRT模型转换常见错误及解决方案 在如今的AI部署场景中&#xff0c;训练一个高精度模型只是第一步。真正决定产品成败的&#xff0c;往往是推理阶段的表现——延迟是否足够低&#xff1f;吞吐量能否支撑业务高峰&#xff1f;功耗是否适合边缘设备&…

作者头像 李华
网站建设 2026/6/10 12:53:18

数据建模如何助力企业大数据战略落地?

数据建模:企业大数据战略落地的底层逻辑与实践指南 一、引言:为什么说数据建模是大数据战略的“地基”? 你是否遇到过这样的场景? 企业花了大价钱搭建了大数据平台,却发现数据分散在各个系统(ERP、CRM、线下POS、线上电商),像“数据孤岛”一样,无法整合分析; 业务部…

作者头像 李华