本文将使用一种称为“深度特征分解(Deep Feature Factorizations)”的方法来创建关于模型在图像中看到的内容的深刻可视化。pytorch-gradcam包提供了该方法的实现和一些附加功能,使其成为一个非常有用的工具。通常,可解释性方法会回答诸如“模型在图像中哪里看到了猫”之类的问题。在这里,将更详细地了解模型,并让它展示在图像中发现的所有不同概念,以及它们是如何分类的。话不多说,直接看效果图吧!
|
|
|
目录
大多数可解释性方法,如Grad-CAM,都是寻找与目标函数相对应的解释。在分类的情况下,目标函数通常是其中一个类别的分数。热图的计算方式与网络输出相连接,目的是在属性中获得更高值的像素,将与目标函数中的更高输出相对应。如果告诉可解释性方法:“想获得与猫类别对应的模型内部激活的热图”,会得到如下的图。
那么,模型发现的内部概念是什么?网络只看猫头和身体在一起吗?或者它把它们当作不同的概念来检测?神经网络能够识别耳朵、眼睛、脸和腿等高级特征。但无法在模型解释中看到这一点。有没有可能猫的身体也会把输出拉向其他类别?仅仅因为它有助于一个类别的更高产出,并不意味着它对其他类别也没有贡献。例如,有许多不同类型的猫。为了在解释热图时考虑到这一点,必须仔细查看所有的热图并跟踪它们。
如何将这些概念与网络的输出联系起来?
使用最后一层CNN是创建模型解释的最常用方法。可以为每个概念分配不同的颜色,并根据热图调节强度。然后,因为有独特的颜色,可以把所有的masks组合成一个单一的图像。但是有一个问题“同一个像素可以有来自不同概念的非零值”。在这里使用的策略是保留在标准化热图中得到更高值的概念,这意味着它对它更重要。对于每个概念,还将显示一个图例,其中包含该概念的信息属性:得分最高的类别。
1 安装pytorch-gradcam
pip install grad-cam==1.4.8 -i https://pypi.tuna.tsinghua.edu.cn/simple
2 实践
① 代码
import warnings
import numpy as np
import requests
import cv2
import matplotlib.pyplot as plt
import torch
from pytorch_grad_cam import DeepFeatureFactorization
from pytorch_grad_cam.utils.image import show_cam_on_image, preprocess_image, deprocess_image
from torchvision.models import resnet50
from pytorch_grad_cam.utils.image import show_factorization_on_image
import os
warnings.filterwarnings('ignore')
# 这部分根据自己的实际路径去对应
os.environ['QT_QPA_PLATFORM_PLUGIN_PATH'] = '/home/test/anaconda3/envs/yolov11/lib/python3.9/site-packages/PyQt5/Qt5/plugins'
def create_labels(concept_scores, top_k=2):
""" Create a list with the image-net category names of the top scoring categories"""
imagenet_categories_url = "https://gist.githubusercontent.com/yrevar/942d3a0ac09ec9e5eb3a/raw/238f720ff059c1f82f368259d1ca4ffa5dd8f9f5/imagenet1000_clsidx_to_labels.txt"
labels = eval(requests.get(imagenet_categories_url).text)
concept_categories = np.argsort(concept_scores, axis=1)[:, ::-1][:, :top_k]
concept_labels_topk = []
for concept_index in range(concept_categories.shape[0]):
categories = concept_categories[concept_index, :]
concept_labels = []
for category in categories:
score = concept_scores[concept_index, category]
label = f"{labels[category].split(',')[0]}:{score:.2f}"
concept_labels.append(label)
concept_labels_topk.append("\n".join(concept_labels))
return concept_labels_topk
def visualize_image(model, img, rgb_img_float, input_tensor, n_components=5, top_k=2):
classifier = model.fc
dff = DeepFeatureFactorization(model=model, target_layer=model.layer4, computation_on_concepts=classifier)
concepts, batch_explanations, concept_outputs = dff(input_tensor, n_components)
concept_outputs = torch.softmax(torch.from_numpy(concept_outputs), axis=-1).numpy()
concept_label_strings = create_labels(concept_outputs, top_k=top_k)
visualization = show_factorization_on_image(rgb_img_float,
batch_explanations[0],
image_weight=0.3,
concept_labels=concept_label_strings)
result = np.hstack((img, visualization))
#if result.shape[0] > 500:
#result = cv2.resize(result, (result.shape[1] // 4, result.shape[0] // 4))
return result
def RUN(img_path, n_components):
img = cv2.imread(img_path)
image = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
rgb_img_float = np.float32(image) / 255
input_tensor = preprocess_image(rgb_img_float, mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
model = resnet50(pretrained=True)
model.eval()
print("Loaded model")
result = visualize_image(model, image, rgb_img_float, input_tensor, n_components=n_components)
plt.imshow(result)
plt.savefig("result.jpg")
plt.show()
if __name__ == '__main__':
RUN("adata/dogs.jpeg", 10)
pass
② 效果图
至此,本文分享的内容就结束啦。