Main Content

このページの翻訳は最新ではありません。ここをクリックして、英語の最新版を参照してください。

Grad-CAM を使用したセマンティック セグメンテーション ネットワークの調査

この例では、Grad-CAM を使用してセマンティック セグメンテーション ネットワークの予測を調査する方法を説明します。

セマンティック セグメンテーション ネットワークはイメージ内のすべてのピクセルを分類して、クラスごとにセグメント化されたイメージを作成します。深層学習の可視化手法である Grad-CAM を使用することで、ピクセル分類判定にとってイメージのどの領域が重要かを確認できます。

データセットの読み込み

この例では、学習用に Cambridge University の CamVid データ セット [1] を使用します。このデータセットは、運転中に得られた路上レベルでのビューが含まれるイメージ コレクションです。このデータ セットは、車、歩行者、道路を含む 32 個のセマンティック クラスに関するピクセルレベルのラベルを提供します。

CamVid データセットのダウンロード

CamVid データ セットをダウンロードします。

rng("default")

imageURL = "http://web4.cs.ucl.ac.uk/staff/g.brostow/MotionSegRecData/files/701_StillsRaw_full.zip";
labelURL = "http://web4.cs.ucl.ac.uk/staff/g.brostow/MotionSegRecData/data/LabeledApproved_full.zip";

outputFolder = fullfile(tempdir,"CamVid"); 
labelsZip = fullfile(outputFolder,"labels.zip");
imagesZip = fullfile(outputFolder,"images.zip");

if ~exist(labelsZip,"file") || ~exist(imagesZip,"file")   
    mkdir(outputFolder)
       
    disp("Downloading 16 MB CamVid data set labels..."); 
    websave(labelsZip, labelURL);
    unzip(labelsZip, fullfile(outputFolder,"labels"));
    
    disp("Downloading 557 MB CamVid data set images...");  
    websave(imagesZip, imageURL);       
    unzip(imagesZip, fullfile(outputFolder,"images"));    
end
Downloading 16 MB CamVid data set labels...
Downloading 557 MB CamVid data set images...

CamVid イメージの読み込み

imageDatastore を使用して CamVid イメージを読み込みます。imageDatastore は、ディスク上の大規模なイメージ コレクションを効率的に読み込むことができます。

imgDir = fullfile(outputFolder,"images","701_StillsRaw_full");
imds = imageDatastore(imgDir);

このデータ セットには 32 個のクラスが含まれています。学習を容易にするために、元のデータ セットに含まれる複数のクラスをグループ化してクラスの数を 11 個に減らします。たとえば、元のデータ セットに含まれる "Car"、"SUVPickupTruck"、"Truck_Bus"、"Train"、および "OtherMoving" というクラスをまとめて "Car" というクラスを作成します。この例の最後にリストされているサポート関数 camvidPixelLabelIDs を使用することで、グループ化されたラベル ID が返されます。

classes = [
    "Sky"
    "Building"
    "Pole"
    "Road"
    "Pavement"
    "Tree"
    "SignSymbol"
    "Fence"
    "Car"
    "Pedestrian"
    "Bicyclist"
    ];

labelIDs = camvidPixelLabelIDs;

クラスとラベル ID を使用して pixelLabelDatastore を作成します。

labelDir = fullfile(outputFolder,"labels");
pxds = pixelLabelDatastore(labelDir,classes,labelIDs);

事前学習済みのセマンティック セグメンテーション ネットワークの読み込み

事前学習済みのセマンティック セグメンテーション ネットワークを読み込みます。事前学習済みのモデルを使用することで、学習の完了を待つことなく例全体を実行することができます。この例では、重みが初期化された学習済みの Deeplab v3+ ネットワークを、事前学習済みの ResNet-18 ネットワークから読み込みます。事前学習済みの ResNet-18 を入手するには、resnet18をインストールします。セマンティック セグメンテーション ネットワークの構築と学習の詳細については、深層学習を使用したセマンティック セグメンテーションを参照してください。

pretrainedURL = "https://www.mathworks.com/supportfiles/vision/data/deeplabv3plusResnet18CamVid.mat";
pretrainedFolder = fullfile(tempdir,"pretrainedNetwork");
pretrainedNetwork = fullfile(pretrainedFolder,"deeplabv3plusResnet18CamVid.mat");

if ~exist(pretrainedNetwork,"file")
    mkdir(pretrainedFolder);
    disp("Downloading pretrained network (58 MB)...");
    websave(pretrainedNetwork,pretrainedURL);
end
pretrainedNet = load(pretrainedNetwork); 
net = pretrainedNet.net;

ネットワークのテスト

この学習済みのセマンティック セグメンテーション ネットワークは、イメージに含まれるピクセルごとにラベルを予測します。イメージのピクセル ラベルを予測することで、ネットワークをテストできます。

テスト イメージを読み込みます。

figure
img = readimage(imds,615);
imshow(img,InitialMagnification=35)

関数 semanticseg を使用して、学習済みのセマンティック セグメンテーション ネットワークでイメージのピクセル ラベルを予測します。

predLabels = semanticseg(img,net);

結果を表示します。

cmap = camvidColorMap;
segImg = labeloverlay(img,predLabels,Colormap=cmap,Transparency=0.4);
figure
imshow(segImg,InitialMagnification=40)

pixelLabelColorbar(cmap,classes)

このネットワークはイメージの各部をかなり正確にラベル付けしていることがわかります。一部の領域は、このネットワークによって間違って分類されています。たとえば、交差点の左側に延びる道路の一部が歩道として誤分類されています。

ネットワークの予測の調査

深層ネットワークは複雑であるため、ネットワークがどのようにして特定の予測に至るかを理解するのは困難です。Grad-CAM を使用することで、セマンティック セグメンテーション ネットワークがテスト イメージのどの領域を使用してピクセルを分類したかを確認できます。

Grad-CAM は、選択した層に含まれる畳み込みの特徴について、クラスのスコアなどの微分可能な出力の勾配を計算します。Grad-CAM は、通常、イメージ分類タスク [2] に使用されますが、セマンティック セグメンテーションの問題 [3] に拡張できます。

セマンティック セグメンテーション タスクでは、ネットワークのソフトマックス層が元のイメージに含まれるすべてのピクセルに対する各クラスのスコアを出力します。これは、通常のイメージ分類問題とは対照的です。通常のイメージ分類問題では、ソフトマックス層はイメージ全体に対する各クラスのスコアを出力します。クラス c の Grad-CAM マップは次のようになります。

Mc=ReLU(kαckAk)、ここで αck=1/Ni,jdycdAi,jk

N はピクセルの数、Ak は対象の特徴マップであり、yc はスカラーのクラスのスコアに対応します。シンプルなイメージ分類問題では、yc は対象のクラスに関するソフトマックス スコアです。セマンティック セグメンテーションでは、対象のクラスに対するピクセル単位のクラス スコアをスカラーに変換することで、yc が得られます。たとえば、ソフトマックス層の空間次元を次のように加算します。yc=(i,j)Pyi,jc。ここで、P は、セマンティック セグメンテーション ネットワーク [3] の出力層に含まれるピクセルです。この例では、出力層はピクセル分類層の前にあるソフトマックス層です。マップ Mc は、クラス c の判定に影響を与える領域を強調表示します。イメージ内で値が高い領域は、ピクセル分類判定にとって重要であることを表します。

Grad-CAM を使用するには、特徴マップを抽出する特徴層と、出力活性化を抽出するリダクション層を選択する必要があります。analyzeNetwork を使用して、Grad-CAM を使う層を見つけます。

analyzeNetwork(net)

特徴層を指定します。通常、これは、ネットワークの最後にある畳み込み層の出力を受け取る ReLU 層です。

featureLayer = "dec_relu4";

リダクション層を指定します。関数 gradCAM は、指定したクラスについてリダクション層の空間次元を加算し、スカラー値を生成します。その後、このスカラー値は特徴層の各特徴に対して微分されます。セマンティック セグメンテーションの問題では、通常、リダクション層はソフトマックス層です。

reductionLayer = "softmax-out";

道路と歩道のクラスに関する Grad-CAM マップを計算します。

classes = ["Road" "Pavement"];

gradCAMMap = gradCAM(net,img,classes, ...
    ReductionLayer=reductionLayer, ...
    FeatureLayer=featureLayer);

この 2 つのクラスに関する Grad-CAM マップを、セマンティック セグメンテーション マップと比較します。

predLabels = semanticseg(img,net);
segMap = labeloverlay(img,predLabels,Colormap=cmap,Transparency=0.4);

figure;
subplot(2,2,1)
imshow(img)
title("Test Image")
subplot(2,2,2)
imshow(segMap)
title("Semantic Segmentation")
subplot(2,2,3)
imshow(img)
hold on
imagesc(gradCAMMap(:,:,1),AlphaData=0.5)
title("Grad-CAM: " + classes(1))
colormap jet
subplot(2,2,4)
imshow(img)
hold on
imagesc(gradCAMMap(:,:,2),AlphaData=0.5)
title("Grad-CAM: " + classes(2))
colormap jet

Grad-CAM マップとセマンティック セグメンテーション マップのどちらも同じように強調表示されています。いずれのマップも、交差点の左側に延びる道路を識別できていません。これは、セマンティック セグメンテーション マップでは歩道としてラベル付けされています。歩道クラスの Grad-CAM マップを見ると、ネットワークの分類判定では歩道の中央よりも歩道の縁部が重要であることがわかります。このネットワークは、歩道の縁部が鮮明でないために、交差点の左側に延びる道路を誤分類した可能性があります。

中間層の調査

ネットワークの最後に近い層を使用して計算すると、Grad-CAM マップとセマンティック セグメンテーション マップは同じような結果になります。Grad-CAM を使用すると、学習済みのネットワークに含まれる中間層を調査することもできます。最初の方の層では、ネットワークの最後にある層と比べて、受容野のサイズが小さく、学習する特徴は小さく低レベルになります。

ネットワーク内の連続的な深い層について、Grad-CAM マップを計算します。

layers = ["res5b_relu","catAspp","dec_relu1"];
numLayers = length(layers);

res5b_relu 層はネットワークの中間に位置します。一方、dec_relu1 はネットワークの最後の方に位置します。

車、道路、および歩道のクラスについて、ネットワークの分類判定を調査します。各層とクラスについて、Grad-CAM マップを計算します。

classes = ["Car" "Road" "Pavement"];
numClasses = length(classes);

gradCAMMaps = [];
for i = 1:numLayers
    gradCAMMaps(:,:,:,i) = gradCAM(net,img,classes, ...
        ReductionLayer=reductionLayer, ...
        FeatureLayer=layers(i));
end

各層とクラスの Grad-CAM マップを表示します。行は各層のマップを表し、ネットワーク内で最初の方にある層から最後にある層の順に並んでいます。

figure;
idx = 1;
for i=1:numLayers
    for j=1:numClasses
        subplot(numLayers,numClasses,idx)
        imshow(img)
        hold on
        imagesc(gradCAMMaps(:,:,j,i),AlphaData=0.5)
        title(sprintf("%s (%s)",classes(j),layers(i)), ...
            Interpreter="none")
        colormap jet
        idx = idx + 1;
    end
end

最後の方にある層は、セグメンテーション マップと非常に似ているマップを生成します。一方で、ネットワーク内の最初の方にある層は、抽象的な結果となります。これらの層では、一般に、セマンティック クラスがほとんど認識されず、縁部などの低レベルの特徴の方が関係します。たとえば、最初の方にある層のマップを見ると、車と道路のどちらのクラスについても信号機が強調表示されていることがわかります。これは、最初の方にある層では、イメージ内でそのクラスに関係する領域に焦点を当てるものの、その領域が必ずしもそのクラスに属しているとは限らないことを示しています。たとえば、信号機は道路の近くにあることが多いため、ネットワークはこの情報を使用してどのピクセルが道路であるかを予測すると考えられます。また、歩道クラスについて見ると、最初の方にある層は縁部を非常に重視しています。これは、どのピクセルが歩道クラスに属するのかを判断する際に、この特徴がネットワークにとって重要であることを示しています。

参考文献

[1] Brostow, Gabriel J., Julien Fauqueur, and Roberto Cipolla.“Semantic Object Classes in Video: A High-Definition Ground Truth Database.” Pattern Recognition Letters 30, no. 2 (January 2009): 88–97. https://doi.org/10.1016/j.patrec.2008.04.005.

[2] Selvaraju, R. R., M. Cogswell, A. Das, R. Vedantam, D. Parikh, and D. Batra."Grad-CAM:Visual Explanations from Deep Networks via Gradient-Based Localization."In IEEE International Conference on Computer Vision (ICCV), 2017, pp. 618–626. Available at Grad-CAM on the Computer Vision Foundation Open Access website.

[3] Vinogradova, Kira, Alexandr Dibrov, and Gene Myers.“Towards Interpretable Semantic Segmentation via Gradient-Weighted Class Activation Mapping (Student Abstract).”Proceedings of the AAAI Conference on Artificial Intelligence 34, no. 10 (April 3, 2020):13943–44. https://doi.org/10.1609/aaai.v34i10.7244.

サポート関数

function labelIDs = camvidPixelLabelIDs()
% Return the label IDs corresponding to each class.
%
% The CamVid data set has 32 classes. Group them into 11 classes following
% the original SegNet training methodology [1].
%
% The 11 classes are:
%   "Sky", "Building", "Pole", "Road", "Pavement", "Tree", "SignSymbol",
%   "Fence", "Car", "Pedestrian",  and "Bicyclist".
%
% CamVid pixel label IDs are provided as RGB color values. Group them into
% 11 classes and return them as a cell array of M-by-3 matrices. The
% original CamVid class names are listed alongside each RGB value. Note
% that the Other/Void class are excluded below.
labelIDs = { ...
    
    % "Sky"
    [
    128 128 128; ... % "Sky"
    ]
    
    % "Building" 
    [
    000 128 064; ... % "Bridge"
    128 000 000; ... % "Building"
    064 192 000; ... % "Wall"
    064 000 064; ... % "Tunnel"
    192 000 128; ... % "Archway"
    ]
    
    % "Pole"
    [
    192 192 128; ... % "Column_Pole"
    000 000 064; ... % "TrafficCone"
    ]
    
    % Road
    [
    128 064 128; ... % "Road"
    128 000 192; ... % "LaneMkgsDriv"
    192 000 064; ... % "LaneMkgsNonDriv"
    ]
    
    % "Pavement"
    [
    000 000 192; ... % "Sidewalk" 
    064 192 128; ... % "ParkingBlock"
    128 128 192; ... % "RoadShoulder"
    ]
        
    % "Tree"
    [
    128 128 000; ... % "Tree"
    192 192 000; ... % "VegetationMisc"
    ]
    
    % "SignSymbol"
    [
    192 128 128; ... % "SignSymbol"
    128 128 064; ... % "Misc_Text"
    000 064 064; ... % "TrafficLight"
    ]
    
    % "Fence"
    [
    064 064 128; ... % "Fence"
    ]
    
    % "Car"
    [
    064 000 128; ... % "Car"
    064 128 192; ... % "SUVPickupTruck"
    192 128 192; ... % "Truck_Bus"
    192 064 128; ... % "Train"
    128 064 064; ... % "OtherMoving"
    ]
    
    % "Pedestrian"
    [
    064 064 000; ... % "Pedestrian"
    192 128 064; ... % "Child"
    064 000 192; ... % "CartLuggagePram"
    064 128 064; ... % "Animal"
    ]
    
    % "Bicyclist"
    [
    000 128 192; ... % "Bicyclist"
    192 000 192; ... % "MotorcycleScooter"
    ]
    
    };
end
function pixelLabelColorbar(cmap, classNames)
% Add a colorbar to the current axis. The colorbar is formatted
% to display the class names with the color.

colormap(gca,cmap)

% Add a colorbar to the current figure.
c = colorbar("peer",gca);

% Use class names for tick marks.
c.TickLabels = classNames;
numClasses = size(cmap,1);

% Center tick labels.
c.Ticks = 1/(numClasses*2):1/numClasses:1;

% Remove tick marks.
c.TickLength = 0;
end

function cmap = camvidColorMap
% Define the colormap used by the CamVid data set.

cmap = [
    128 128 128   % Sky
    128 0 0       % Building
    192 192 192   % Pole
    128 64 128    % Road
    60 40 222     % Pavement
    128 128 0     % Tree
    192 128 128   % SignSymbol
    64 64 128     % Fence
    64 0 128      % Car
    64 64 0       % Pedestrian
    0 128 192     % Bicyclist
    ];

% Normalize between [0 1].
cmap = cmap ./ 255;
end

参考

| (Computer Vision Toolbox) | (Computer Vision Toolbox)

関連するトピック