主要内容

使用类激活映射研究网络预测

这个例子展示了如何使用类激活映射(CAM)来研究和解释用于图像分类的深度卷积神经网络的预测。

深度学习网络通常被认为是“黑盒”,无法确定网络学到了什么,也无法确定网络输入的哪一部分负责网络的预测。当这些模型失败并给出不正确的预测时,它们往往会在没有任何警告或解释的情况下轰然失败。类激活映射[1]是一种可以用来获得卷积神经网络预测的可视化解释的技术。不正确的,看似不合理的预测往往有合理的解释。使用类激活映射,您可以检查输入图像的特定部分是否“混淆”了网络,并导致它做出错误的预测。

您可以使用类激活映射来识别训练集中的偏差并提高模型的准确性。如果你发现网络的预测基于错误的特征,那么你可以通过收集更好的数据来使网络更加健壮。例如,假设你训练一个网络来区分猫和狗的图像。该网络在训练集上具有很高的准确性,但在真实世界的示例上表现不佳。通过在训练示例上使用类激活映射,您会发现网络的预测不是基于图像中的猫和狗,而是基于背景。然后你意识到你所有的猫的照片都是红色的背景,你所有的狗的照片都是绿色的背景,这是网络在训练中学习到的背景颜色。然后,您可以收集没有这种偏差的新数据。

这个示例类激活映射显示了输入图像的哪些区域对预测类的贡献最大鼠标.红色区域贡献最大。

加载预训练网络和网络摄像头

加载预先训练好的卷积神经网络进行图像分类。SqueezeNet、GoogLeNet、ResNet-18和MobileNet-v2是相对较快的网络。SqueezeNet是最快的网络,它的类激活地图比其他网络的地图分辨率高4倍。不能对在网络末端有多个完全连接层的网络使用类激活映射,例如AlexNet、VGG-16和VGG-19。

网络=“squeezenet”;net = eval(netName);

创建一个网络摄像头对象并连接到您的网络摄像头。

摄像头=网络摄像头;

提取图像的输入大小和网络的输出类别。的activationLayerNameHelper函数,在本例的末尾定义,返回要从中提取激活的层的名称。这一层是ReLU层,它跟随网络的最后一个卷积层。

inputSize = net.Layers(1).InputSize(1:2);classes = net.Layers(end).Classes;layerName = activationLayerName(netName);

显示职业激活地图

在循环中创建图形并执行类激活映射。若要终止循环执行,请关闭该图。

H =数字(“单位”“归一化”“位置”,[0.05 0.05 0.9 0.8],“可见”“上”);ishandle (h)

用网络摄像头拍一张快照。调整图像的大小,使其最短边的长度(在本例中为图像高度)等于网络的图像输入大小。在调整大小时,保留图像的纵横比。还可以将图像调整为更大或更小的大小。使图像变大会增加最终类激活映射的分辨率,但可能导致整体预测不太准确。

计算在网络的最后一个卷积层之后的ReLU层中调整大小的图像的激活。

Im =快照(相机);imresize = imresize(im,[inputSize(1), NaN]);imageActivations =激活(net,imResized,layerName);

特定类的类激活映射是在最终卷积层之后的ReLU层的激活映射,由每个激活对该类的最终分数的贡献进行加权。这些权重等于该类网络的最终全连接层的权重。SqueezeNet没有最终的全连接层。相反,在最后一个卷积层之后的ReLU层的输出已经是类激活映射。

您可以为任何输出类生成类激活映射。例如,如果网络做出了错误的分类,您可以比较真实类和预测类的类激活映射。对于本例,为预测得分最高的班级生成班级激活图。

scores = squeeze(mean(imageactivation,[1 2]));如果网络~ =“squeezenet”fcWeights = net.Layers(end-2).Weights;fcBias = net.Layers(end-2).Bias;分数= fcWeights*分数+ fcBias;[~,classIds] = maxk(scores,3);weightVector = shiftdim(fcWeights(classIds(1),:),-1);classActivationMap = sum(imageactivation .*weightVector,3);其他的[~,classIds] = maxk(scores,3);classActivationMap = imageActivations(:,:,classIds(1));结束

计算顶级班级标签和最终标准化班级分数。

Scores = exp(Scores)/sum(exp(Scores));maxScores = scores(classIds);标签=类(classIds);

绘制类激活映射。在第一个子图中显示原始图像。在第二个子图中,使用CAMshowHelper函数,在本例的末尾定义,用于在原始图像的暗灰色版本之上显示类激活映射。显示前三个预测标签及其预测分数。

subplot(1,2,1) imshow(im) subplot(1,2,2) CAMshow(im,classActivationMap) title(字符串(标签)+”、“+字符串(maxScores));drawnow结束

清除网络摄像头对象。

清晰的相机

例子地图

网络正确地将图像中的物体识别为乐福鞋(一种鞋)。右边图像中的类激活映射显示了输入图像的每个区域对预测类的贡献游手好闲的人.红色区域贡献最大。该网络基于整只鞋进行分类,但最强的输入来自红色区域——也就是鞋尖和鞋口。

网络将这张图片归类为鼠标。正如类激活图所示,预测不仅基于图像中的鼠标,还基于键盘。因为训练集可能有许多键盘旁边的老鼠图像,网络预测包含键盘的图像更有可能包含老鼠。

该网络将这张咖啡杯的图片归类为扣环。正如类激活映射所示,网络错误地分类了图像,因为图像包含太多混淆对象。该网络检测并集中在手表表带上,而不是咖啡杯。

辅助函数

CAMshow (im,凸轮)覆盖类激活映射凸轮在一个暗的,灰度版本的图像上即时通讯.函数将类激活映射的大小调整为即时通讯,将其规范化,从下面开始设置阈值,并使用飞机colormap。

函数CAMshow(im,CAM) imSize = size(im);CAM = imresize(CAM,imSize(1:2));CAM = normalizeImage(CAM);凸轮(凸轮<0.2)= 0;Cmap = jet(255).*linspace(0,1,255)';CAM = ind2rgb(uint8(CAM*255),cmap)*255;combinedImage = double(rgb2gray(im))/2 + CAM;combinedImage = normalizeImage(combinedImage)*255;imshow (uint8 (combinedImage));结束函数N = normalizeImage(I) minimum = min(I(:));最大值=最大值(I(:));N = (I-minimum)/(maximum-minimum);结束函数layerName = activationLayerName(netName)如果网络= =“squeezenet”layerName =“relu_conv10”elseif网络= =“googlenet”layerName =“inception_5b-output”elseif网络= =“resnet18”layerName =“res5b_relu”elseif网络= =“mobilenetv2”layerName =“out_relu”结束结束

参考文献

[1] Zhou, Bolei, Aditya Khosla, Agata Lapedriza, Aude Oliva和Antonio Torralba。“学习深度特征进行判别定位。”在IEEE计算机视觉与模式识别会议论文集, 2921-2929页。2016.

另请参阅

||||

相关的话题