栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Python

MindSpore 使用 GradCAM

Python 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

MindSpore 使用 GradCAM

定义:

GradCAM是一个典型及有效的梯度解释器

代码如下:


import mindspore as ms
from mindspore import Tensor
from mindspore_xai.explanation import GradCAM

# 通常指定最后一层的卷积层
grad_cam = GradCAM(net, layer="layer4")

# 5 是'boat'类的ID
saliency = grad_cam(boat_image, targets=5)

如果输入的是一个 1xCx224x224 的图片Tensor,那返回的saliency就是一个 1x1x224x224 的热力图Tensor。

批次解释

对于梯度解释器,批次解释通常较有效率,但其他解释器也可以使用:

代码如下:


from dataset import load_dataset

test_ds = load_dataset('xai_examples_data/test').batch(4)

for images, labels in test_ds:
    saliencies = grad_cam(images, targets=Tensor([5, 5, 5, 5], dtype=ms.int32))
    # 其他用户操作 ...

如果输入的是一个 4xCx224x224 的批次图片Tensor,那返回的saliency就是一个 4x1x224x224 的批次热力图Tensor。

使用其他解释器

使用其他解释器(RISEPlus 除外)的方法跟 GradCAM 的使用方法十分相似 。

使用 RISEPlus

RISEPlus是一个基于RISE的解释器,它引入了分布外侦测器,解决了RISE在遇到分布外(OoD)样本时产生的热力图劣化问题。

首先,我们要使用分类器的训练数据集去训练一个分布外侦测器(OoDNet):

代码如下:


# 必须先把当前目录切换到 xai/examples/
from mindspore import context, save_checkpoint, load_checkpoint, load_param_into_net
from mindspore.nn import Softmax, SoftmaxCrossEntropyWithLogits
from mindspore_xai.explanation import RISEPlus, OoDNet
from common.dataset import load_dataset, load_image_tensor
from common.resnet import resnet50

# 只支持 PYNATIVE_MODE
context.set_context(mode=context.PYNATIVE_MODE)

num_classes = 20

# 分类器的训练数据集
train_ds = load_dataset('xai_examples_data/train').batch(4)

# 加载训练好的分类器
net = resnet50(num_classes)
param_dict = load_checkpoint('xai_examples_data/ckpt/resnet50.ckpt')
load_param_into_net(net, param_dict)

ood_net = OoDNet(underlying=net, num_classes=num_classes)

# 如果分类器的激活函数是 Softmax,我们要使用 SoftmaxCrossEntropyWithLogits 作为损失函数,如果激活函数是 Sigmod 则使用
# BCEWithLogitsLoss 作为损失函数
ood_net.train(train_ds, loss_fn=SoftmaxCrossEntropyWithLogits())

save_checkpoint(ood_net, 'ood_net.ckpt')

下游分类器(underlying)的父类必须为nn.Cell,以及在__init()__函数内:

定义一个名为num_features的int成员,它代表了在特征层输出的特征值个数。

定义一个名为output_features的bool成员并使用False作为初始值,OoDNet会使用output_features来控制分类器是否在construct()输出特征Tensor

下面举LeNet5 的例子:

代码如下:


from mindspore import nn
from mindspore.common.initializer import Normal

class MyLeNet5(nn.Cell):

    def __init__(self, num_class, num_channel):
        super(MyLeNet5, self).__init__()

        # 必须定义以下两个成员
        self.num_features = 84 # 特征值个数, int
        self.output_features = False # 是否输出特征Tensor, bool

        self.conv1 = nn.Conv2d(num_channel, 6, 5, pad_mode='valid')
        self.conv2 = nn.Conv2d(6, 16, 5, pad_mode='valid')
        self.relu = nn.ReLU()
        self.max_pool2d = nn.MaxPool2d(kernel_size=2, stride=2)
        self.flatten = nn.Flatten()
        self.fc1 = nn.Dense(16 * 5 * 5, 120, weight_init=Normal(0.02))
        self.fc2 = nn.Dense(120, self.num_features, weight_init=Normal(0.02))
        self.fc3 = nn.Dense(self.num_features, num_class, weight_init=Normal(0.02))

    def construct(self, x):
        x = self.conv1(x)
        x = self.relu(x)
        x = self.max_pool2d(x)
        x = self.conv2(x)
        x = self.relu(x)
        x = self.max_pool2d(x)
        x = self.flatten(x)
        x = self.relu(self.fc1(x))
        x = self.relu(self.fc2(x))

        # 如果 output_features 是 True, 返回特征Tensor
        if self.output_features:
            return x

        x = self.fc3(x)
        return x

现在,我们可以使用训练好的OoDNet去构造RISEPlus解释器输出热力图:


# 如果是要从 checkpoint 文件读取 OoDNet 的权重,我们就要传入一个新构造的下游分类器对象
ood_net = OoDNet(underlying=resnet50(num_classes), num_classes=num_classes)
param_dict = load_checkpoint('ood_net.ckpt')
load_param_into_net(ood_net)

rise_plus = RISEPlus(ood_net=ood_net, network=net, activation_fn=Softmax())
boat_image = load_image_tensor("xai_examples_data/test/boat.jpg")
saliency = rise_plus(boat_image, targets=5)

如果输入的是一个 1xCx224x224 的图片Tensor,那返回的saliency就是一个 1x1x224x224 的热力图Tensor。

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/656199.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号