类激活热力图(CAM,class activation map)

这篇博客介绍了如何利用Grad-CAM技术对VGG16模型进行可视化,展示了如何不改变网络结构就能得到类激活图。文章通过实例代码演示了从图像预处理到Grad-CAM热力图生成的全过程,揭示了模型对图像特征的关注区域。同时,讨论了Grad-CAM相对于CAM的改进及其在分类问题上的应用,但对于回归问题的效果则未予详述。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

CAM,class activation map来自于论文《Learning Deep Features for Discriminative Localization》。通过based model+CAM之后,我们可以得到如下图所示的热度图,在对最后结果影响比较大的地方生成的热度就比较高

这项技术非常有用但是存在一些缺陷的。首先我们必须改变网络结构,例如把全连接层改成全局平均池化层,这不利于训练。第二是这是基于分类问题的一种可视化技术,帮助我们更好的理解模型内部的学习情况。但是该方法用于回归问题可能就没有这么好的效果。

为了解决第一个问题,2017年出现了一种改进的技术叫Grad-CAM,Grad-CAM可以不改变网络结构进行可视化,详见这篇论文《Grad-CAM: Visual Explanations from Deep Networks via Gradient-based Localization》 (2017 ICCV)。

以下的代码主要来自于博文,但是原作者的代码很零散,不能直接运行。我前者基础上进行整合:

import numpy as np
import tensorflow as tf
import cv2

VGG16_model = tf.keras.applications.VGG16(include_top=True)
VGG16_model.summary()

from tensorflow.keras.applications.vgg16 import preprocess_input, decode_predictions
def prepocess(x):
    x = tf.io.read_file(x)
    x = tf.image.decode_jpeg(x, channels=3)
    x = tf.image.resize(x, [224,224])
    x =tf.expand_dims(x, 0) # 扩维
    x = preprocess_input(x)
    return x

img_path='cat.jpg'
img=prepocess(img_path)

Predictions = VGG16_model.predict(img, steps=1)
print('Predicted:', decode_predictions(Predictions, top=3)[0])

# 应用Grad-CAM 算法
# 构建一个同时输出最后一层的卷积层和类别预测结果的网络
from tensorflow.keras import models
last_conv_layer = VGG16_model.get_layer('block5_conv3')
heatmap_model =models.Model([VGG16_model.inputs], [last_conv_layer.output, VGG16_model.output])
# Grad-CAM 算法实现
import tensorflow.keras.backend as K
with tf.GradientTape() as gtape:
    conv_output, Predictions = heatmap_model(img)
    prob = Predictions[:, np.argmax(Predictions[0])] # 最大可能性类别的预测概率
    grads = gtape.gradient(prob, conv_output)  # 类别与卷积层的梯度 (1,14,14,512)
    pooled_grads = K.mean(grads, axis=(0,1,2)) # 特征层梯度的全局平均代表每个特征层权重
heatmap = tf.reduce_mean(tf.multiply(pooled_grads, conv_output), axis=-1) #权重与特征层相乘,512层求和平均
with tf.Session() as sess:
    init = tf.initialize_all_variables()
    sess.run(init)
    Predictions,heatmap = sess.run([Predictions, heatmap])
# 绘制激活热力图
heatmap = np.maximum(heatmap, 0)
max_heat = np.max(heatmap)
if max_heat == 0:
    max_heat = 1e-10
heatmap /= max_heat
# plt.matshow(heatmap, cmap='viridis')

original_img=cv2.imread('cat.jpg')
heatmap1 = cv2.resize(heatmap[0], (original_img.shape[1], original_img.shape[0]), interpolation=cv2.INTER_CUBIC)
heatmap1 = np.uint8(255*heatmap1)
heatmap1 = cv2.applyColorMap(heatmap1, cv2.COLORMAP_JET)
frame_out=cv2.addWeighted(original_img,0.5,heatmap1,0.5,0)
cv2.imwrite('Egyptian_cat.jpg', frame_out)
cv2.imwrite("heatmap.jpg", heatmap1)


# 前三类结果比较
# 首先使用如下代买对预测的最大值进行修改,得到第二和第三可能性的预测结果
Predictions3=Predictions
Predictions3[0][np.argmax(Predictions3[0])]=np.min(Predictions3)
Predictions3[0][np.argmax(Predictions3[0])]=np.min(Predictions3)

### Class Activation Map (CAM) 力图生成方法 Class Activation Map (CAM) 是一种用于解释卷积神经网络决策过程的技术,能够显示输入图像中哪些区域对于特定分结果最为重要[^1]。 #### CAM 的工作原理 CAM 方法依赖于全局平均池化层(Global Average Pooling, GAP),该层位于最后一个卷积层之后。GAP 层的作用是对每个特征通道计算空间维度上的均值,从而获得固定长度的向量表示。这些向量随后被传递给全连接层以预测别概率。由于这种结构特性,可以反推出各个位置的重要性权重,进而构建力图[^2]。 #### 实现步骤 为了实现 CAM 并生成相应的力图,通常遵循以下流程: 1. **加载预训练模型** 需要一个已经训练好的 CNN 模型作为基础架构。例如,可以从 Keras 中导入 ImageNet 上预先训练过的 VGG16 或 ResNet50 模型。 ```python from tensorflow.keras.applications import vgg16 model = vgg16.VGG16(weights='imagenet', include_top=True) ``` 2. **获取目标别的索引** 3. **提取最后一层卷积层输出** 4. **执行前向传播并保存中间结果** 5. **计算加权求和得到力图矩阵** 6. **将力图与原始图片叠加展示** 下面是一个简单的 Python 代码片段来说明如何创建 CAM 图像: ```python import numpy as np import cv2 from matplotlib import pyplot as plt def generate_cam(image_path, model, last_conv_layer_name="block5_conv3"): img = preprocess_image(image_path) preds = model.predict(img) top_pred_index = np.argmax(preds[0]) grad_model = tf.keras.models.Model( [model.inputs], [model.get_layer(last_conv_layer_name).output, model.output] ) with tf.GradientTape() as tape: conv_outputs, predictions = grad_model(img) loss = predictions[:, top_pred_index] grads = tape.gradient(loss, conv_outputs) pooled_grads = tf.reduce_mean(grads, axis=(0, 1, 2)).numpy() heatmap = np.dot(conv_outputs.numpy()[0], pooled_grads[..., np.newaxis]) # For visualization purpose we normalize the heatmap between 0 and 1. heatmap = np.maximum(heatmap, 0) max_heat = np.max(heatmap) if max_heat == 0: max_heat = 1e-10 heatmap /= max_heat original_img = load_original_image(image_path) cam_result = overlay_heatmap(original_img, heatmap) return cam_result plt.imshow(generate_cam('path_to_your_image.jpg')) plt.show() ``` 此函数接收一张图片路径以及之前定义好的 `model` 对象作为参数,并返回带有覆盖在其上颜色编码强度映射的结果图像。 #### 应用场景 - **医学影像诊断辅助**: 帮助医生理解 AI 辅助工具做出判断的原因所在; - **自动驾驶汽车安全验证**: 解释车辆感知系统为何会识别某些物体而忽略其他对象; - **零售业商品推荐优化**: 提升个性化服务的质量,使顾客更容易找到感兴趣的商品;
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值