Main Content

gradCAM

Grad-CAM を使用したネットワーク予測の説明

R2021a 以降

    説明

    scoreMap = gradCAM(net,X,classIdx) は、classIdx によって与えられたクラスのクラス スコアをネットワーク net が評価するときの、入力 X の分類スコアの変化に関する勾配加重クラス活性化マッピング (Grad-CAM) のマップを返します。この関数を使用して、ネットワーク予測を説明し、ネットワークがデータの正しい部分に焦点を当てていることを確認します。

    Grad-CAM 解釈可能性手法では、最終的な畳み込み特徴マップに対する分類スコアの勾配を使用します。観測結果において Grad-CAM マップの値が大きい部分は、そのクラスのネットワーク スコアに最も影響を与えている部分です。

    分類タスクの Grad-CAM マップを計算するには、この構文を使用します。

    scoreMap = gradCAM(net,X,label) は、クラス ラベル label で指定されたクラスを使用して Grad-CAM マップを返します。

    scoreMap = gradCAM(net,X,reductionFcn) は、リダクション関数を使用して Grad-CAM 重要度マップを返します。reductionFcn は、リダクション層の出力活性化をスカラー値に削減する関数ハンドルです。このスカラーは、分類タスクのクラス スコアの役目を果たし、Grad-CAM 手法を回帰などの非分類タスクに一般化します。

    関数 gradCAM は、削減されたリダクション層出力を特徴層の特徴に関して微分することで、Grad-CAM のマップを計算します。gradCAM は、マップの計算に使用するリダクション層と特徴層を自動的に選択します。これらの層を指定するには、名前と値の引数 'ReductionLayer' および 'FeatureLayer' を使用します。

    非分類タスクの Grad-CAM マップを計算するには、この構文を使用します。

    [scoreMap,featureLayer,reductionLayer] = gradCAM(___) は、Grad-CAM マップの計算で使用した特徴層とリダクション層の名前も返します。この構文では、前の構文の入力引数を自由に組み合わせて使用します。

    ___ = gradCAM(___,Name,Value) では、前の構文の入力引数に加えて、1 つ以上の名前と値の引数を使用してオプションを指定します。たとえば、ReductionLayer="prob" は、リダクション層を "prob" という名前の net 層に設定します。

    すべて折りたたむ

    gradCAM を使用して、ネットワークによる分類の判定にとってイメージのどの部分が重要かを可視化します。

    事前学習済みのネットワーク SqueezeNet をインポートします。

    [net,classes] = imagePretrainedNetwork("squeezenet");

    イメージをインポートし、ネットワークの入力サイズに合わせてサイズを変更します。

    X = imread("laika_grass.jpg");
    inputSize = net.Layers(1).InputSize(1:2);
    X = imresize(X,inputSize);

    イメージを表示します。

    imshow(X)

    イメージを分類してクラス ラベルを取得します。

    scores = predict(net,single(X));
    label = scores2label(scores,classes)
    label = categorical
         toy poodle 
    
    

    gradCAM を使用して、分類結果にとってイメージのどの部分が重要かを判定します。ネットワーク内のソフトマックス層をリダクション層として指定します。

    scoreMap = gradCAM(net,X,label,ReductionLayer="prob");

    結果を元のイメージの上に半透明でプロットし、イメージのどの領域が分類スコアに最も寄与しているかを確認します。

    figure
    imshow(X)
    hold on
    imagesc(scoreMap,AlphaData=0.5)
    colormap jet

    このネットワークは、主に犬の背中に焦点を当てて分類の判定を行っています。

    Grad-CAM を使用して、イメージ回帰ネットワークによる予測にとってイメージのどの部分が最も重要かを可視化します。

    事前学習済みのネットワーク digitsRegressionNet を読み込みます。このネットワークは、手書き数字の回転角度を予測する回帰畳み込みニューラル ネットワークです。

    load digitsRegressionNet

    ネットワーク層を表示します。ネットワークの出力層は回帰層です。

    layers = net.Layers
    layers = 
      17x1 Layer array with layers:
    
         1   'imageinput'    Image Input           28x28x1 images with 'zerocenter' normalization
         2   'conv_1'        2-D Convolution       8 3x3x1 convolutions with stride [1  1] and padding 'same'
         3   'batchnorm_1'   Batch Normalization   Batch normalization with 8 channels
         4   'relu_1'        ReLU                  ReLU
         5   'avgpool2d_1'   2-D Average Pooling   2x2 average pooling with stride [2  2] and padding [0  0  0  0]
         6   'conv_2'        2-D Convolution       16 3x3x8 convolutions with stride [1  1] and padding 'same'
         7   'batchnorm_2'   Batch Normalization   Batch normalization with 16 channels
         8   'relu_2'        ReLU                  ReLU
         9   'avgpool2d_2'   2-D Average Pooling   2x2 average pooling with stride [2  2] and padding [0  0  0  0]
        10   'conv_3'        2-D Convolution       32 3x3x16 convolutions with stride [1  1] and padding 'same'
        11   'batchnorm_3'   Batch Normalization   Batch normalization with 32 channels
        12   'relu_3'        ReLU                  ReLU
        13   'conv_4'        2-D Convolution       32 3x3x32 convolutions with stride [1  1] and padding 'same'
        14   'batchnorm_4'   Batch Normalization   Batch normalization with 32 channels
        15   'relu_4'        ReLU                  ReLU
        16   'dropout'       Dropout               20% dropout
        17   'fc'            Fully Connected       1 fully connected layer
    

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

    load DigitsDataTest

    テスト イメージでネットワーク性能を評価します。

    testIdx = 501;
    testDigit = XTest(:,:,:,testIdx);

    predict を使用して回転角度を予測し、予測した回転と実際の回転を比較します。

    predRotation = predict(net,testDigit)
    predRotation = single
        26.5635
    
    trueRotation = anglesTest(testIdx)
    trueRotation = 29
    

    gradCAM を使用して、ネットワークによる予測にとって最も重要なイメージの領域を可視化します。特徴層として ReLU 層を選択し、リダクション層として全結合層を選択します。

    featureLayer = 'relu_4';
    reductionLayer = 'fc';

    リダクション関数を定義します。リダクション関数は、リダクション層の出力をスカラー値に削減しなければなりません。Grad-CAM マップは、そのスカラー値に対するイメージの各部分の重要度を表示します。今回の回帰問題では、ネットワークによってイメージの回転角度が予測されます。したがって、全結合層の出力は既にスカラー値であり、リダクション層は単なる恒等関数です。

    reductionFcn = @(x)x;

    Grad-CAM マップを計算します。

    scoreMap = gradCAM(net,testDigit,reductionFcn, ...
        'ReductionLayer',reductionLayer, ...
        'FeatureLayer',featureLayer);

    テスト イメージの上に Grad-CAM マップを表示します。

    ax(1) = subplot(1,2,1);
    imshow(testDigit)
    title("True Rotation = " + trueRotation + newline + "Pred Rotation = " + round(predRotation,0))
    colormap(ax(1),'gray')
    
    ax(2) = subplot(1,2,2);
    imshow(testDigit)
    hold on
    imagesc(rescale(scoreMap))
    colormap(ax(2),'jet')
    title("Grad-CAM")
    hold off

    gradCAM を使用して、ネットワークによる分類の判定にとってシーケンスのどの部分も重要かを可視化します。

    事前学習済みのネットワーク JapaneseVowelsConvNet を読み込みます。このネットワークは、[1] および [2] で説明されているように Japanese Vowels データ セットで学習させた事前学習済みの 1 次元畳み込みニューラル ネットワーク ネットワークです。

    load JapaneseVowelsConvNet

    ネットワーク アーキテクチャを表示します。

    net.Layers
    ans = 
      10x1 Layer array with layers:
    
         1   'sequenceinput'     Sequence Input               Sequence input with 12 dimensions
         2   'conv1d_1'          1-D Convolution              32 3x12 convolutions with stride 1 and padding 'causal'
         3   'relu_1'            ReLU                         ReLU
         4   'layernorm_1'       Layer Normalization          Layer normalization with 32 channels
         5   'conv1d_2'          1-D Convolution              64 3x32 convolutions with stride 1 and padding 'causal'
         6   'relu_2'            ReLU                         ReLU
         7   'layernorm_2'       Layer Normalization          Layer normalization with 64 channels
         8   'globalavgpool1d'   1-D Global Average Pooling   1-D global average pooling
         9   'fc'                Fully Connected              9 fully connected layer
        10   'softmax'           Softmax                      softmax
    

    テスト データを読み込みます。XTest は、次元 12 の可変長のシーケンスが含まれる cell 配列です。TTest は、9 人の話者に対応するラベル "1"、"2"、...、"9" から成る categorical ベクトルです。

    load JapaneseVowelsTestData

    最初の時系列の観測値を選択します。このシーケンスには 19 個のタイム ステップが含まれています。

    testSequence = XTest{1};
    testSize = size(testSequence)
    testSize = 1×2
    
        12    19
    
    
    numFeatures = testSize(1);

    最初の時系列をプロットで可視化します。各ラインは特徴に対応しています。

    figure
    plot(testSequence')
    title("Test Observation 1")
    xlabel("Time Step")
    legend("Feature " + string(1:numFeatures),'Location','northeastoutside')

    テスト観測値を分類します。

    scores = predict(net,testSequence,InputDataFormats="CT");
    label = scores2label(scores,categories(TTest))
    label = categorical
         1 
    
    

    gradCAM を使用して、分類結果にとってシーケンスのどの部分が重要かを判定します。

    map = gradCAM(net,testSequence,label);

    map は、19 個の各タイム ステップに関する重要度の値を含む 1 行 19 列のベクトルです。

    結果をプロットし、どのタイム ステップが分類スコアに最も寄与しているかを確認します。

    figure
    
    subplot(2,1,1)
    plot(testSequence')
    xlabel("Time Step")
    
    subplot(2,1,2)
    plot(map)
    xlabel("Time Step")
    ylabel("Grad-CAM Importance")

    Grad-CAM マップは、ネットワークが後半のタイム ステップに焦点を当てて分類の判定を行っていることを示唆しています。

    入力引数

    すべて折りたたむ

    学習済みネットワーク。dlnetwork オブジェクトとして指定します。

    net には 1 つの入力と 1 つの出力がなければなりません。net の入力層は、imageInputLayerimage3dInputLayer、または sequenceInputLayer でなければなりません。sequenceInputLayer をもつネットワークの場合、InputSize プロパティはスカラーでなければなりません。

    入力データ。数値配列または形式を整えた dlarray オブジェクトとして指定します。

    • 2 次元イメージ データの場合、X は、h×w×c の配列でなければなりません。ここで、h、w、および c は、それぞれネットワーク入力層の高さ、幅、およびチャネル数です。

    • 3 次元イメージ データの場合、X は、h×w×d×c の配列でなければなりません。ここで、h、w、d、および c は、それぞれネットワーク入力層の高さ、幅、深さ、および数です。

    • ベクトル シーケンス データの場合、X は、c 行 t 列の配列でなければなりません。c はネットワーク net の入力サイズです。t はシーケンスに含まれるタイム ステップの数で、任意の正の整数を指定できます。

    データ型: single | double | int8 | int16 | int32 | int64 | uint8 | uint16 | uint32 | uint64

    クラス インデックス。数値スカラー、またはクラス インデックスの数値ベクトルとして指定します。

    classIdx をベクトルとして指定した場合、指定された各クラスの特徴量重要度マップは個別に計算されます。詳細については、scoreMap を参照してください。

    関数 gradCAM は、クラス classIdx についてリダクション層の空間次元と時間次元の和を計算します。そのため、セマンティック セグメンテーション タスクの関心クラスとして classIdx を指定できます。この場合、gradCAM は、各ピクセルの Grad-CAM 重要度を返します。

    例: [1 5]

    データ型: single | double | int8 | int16 | int32 | int64 | uint8 | uint16 | uint32 | uint64

    クラス ラベル。categorical スカラー、またはクラス ラベルの categorical ベクトルとして返されます。

    label をベクトルとして指定した場合、指定された各クラスの特徴量重要度マップは個別に計算されます。詳細については、scoreMap を参照してください。

    関数 gradCAM は、クラス label についてリダクション層の空間次元と時間次元の和を計算します。そのため、セマンティック セグメンテーション タスクの関心クラスとして label を指定できます。この場合、gradCAM は、各ピクセルの Grad-CAM 重要度を返します。

    データ型: categorical

    リダクション関数。関数ハンドルとして指定します。リダクション関数は、リダクション層の出力活性化を 1 つの値に削減します。これは、dlarray オブジェクトを dlarray スカラーに削減しなければなりません。このスカラーは、分類タスクの classIdx の役目を果たし、Grad-CAM 手法を回帰などの非分類タスクに一般化します。

    Grad-CAM は、リダクション層の削減された出力活性化を使用して、重要度マップの勾配を計算します。

    例: @x(x)

    データ型: function_handle

    名前と値の引数

    オプションの引数のペアを Name1=Value1,...,NameN=ValueN として指定します。ここで、Name は引数名で、Value は対応する値です。名前と値の引数は他の引数の後に指定しなければなりませんが、ペアの順序は重要ではありません。

    R2021a より前では、コンマを使用して名前と値をそれぞれ区切り、Name を引用符で囲みます。

    例: FeatureLayer="conv10",ReductionLayer="prob",OutputUpsampling="bicubic",ExecutionEnvironment="gpu" は、conv10 層と prob 層について Grad-CAM マップを計算し、GPU 上で計算を実行します。さらに、結果として得られたマップを、入力データと同じサイズになるように双三次内挿を使用してアップサンプリングします。

    Grad-CAM マップの計算時に特徴マップを抽出する特徴層の名前。string または文字ベクトルとして指定します。特徴層のデータ形式は、入力層と同じでなければなりません。データ形式の詳細については、InputDataFormats を参照してください。ほとんどのタスクでは、大きさが 1 でない空間次元または時間次元をもつ最後の ReLU 層、または ReLU 層の出力を収集する最後の層 (深さ連結層や加算層など) を使用します。ネットワークに ReLU 層が含まれていない場合、大きさが 1 でない空間次元または時間次元が出力に含まれている最後の畳み込み層の名前を指定します。

    既定値は、大きさが 1 でない空間次元または時間次元をもち、入力層とデータ形式が等しい最後の層です。ネットワークを調べて正しい層を選択するには、関数 analyzeNetwork を使用します。

    例: FeatureLayer="conv10"

    データ型: char | string

    Grad-CAM マップの計算時に出力活性化を抽出するリダクション層の名前。string または文字ベクトルとして指定します。

    既定値はネットワークの最後の層です。ネットワークを調べて正しい層を選択するには、関数 analyzeNetwork を使用します。

    例: ReductionLayer="prob"

    データ型: char | string

    入力データの各次元にラベルを割り当てる入力データ形式。文字ベクトルまたは string として指定します。この形式の各文字は、次のいずれかの次元ラベルでなければなりません。

    • S — 空間

    • C — チャネル

    • B — バッチ

    • T — 時間

    詳細については、dlarray を参照してください。

    関数 gradCAM は、大きさが 1 のバッチ次元を最大で 1 つサポートします。

    例: InputDataFormats="TC"

    データ型: char | string

    出力のアップサンプリング方法。以下として指定します。

    • "bicubic" — 双三次内挿を使用してスムーズなマップを生成します。

    • "nearest" — 最近傍内挿を使用してマップを拡張します。

    • "none" — アップサンプリングを使用しません。マップは入力データより小さく (または大きく) なる場合があります。

    OutputUpsampling"nearest" または "bicubic" の場合、Grad-CAM マップは入力の空間次元および時間次元と同じサイズになります。

    • 2 次元イメージ データの場合、マップのサイズは h×w になります。ここで、h および w は、それぞれイメージの高さと幅です。

    • 3 次元イメージ データの場合、マップのサイズは h×w×d になります。ここで、h、w、および d は、それぞれイメージの高さ、幅、深さです。

    • ベクトル シーケンス入力の場合、マップのサイズは 1×t になります。ここで、t はシーケンスのタイム ステップ数です。

    OutputUpsampling"nearest" または "bicubic" の場合、計算されたマップは、2 次元イメージ データおよびベクトル シーケンス データであれば関数 imresize、3 次元イメージ データであれば関数 imresize3 (Image Processing Toolbox) を使用してアップサンプリングされます。3 次元イメージ データの場合、"bicubic" オプションを指定すると、"cubic" の手法で imresize3 (Image Processing Toolbox) が使用されます。

    例: OutputUpsampling="bicubic"

    ハードウェア リソース。次のいずれかの値として指定します。

    • "auto" — 利用可能な場合、GPU を使用します。そうでない場合、CPU を使用します。

    • "gpu" — GPU を使用します。GPU を使用するには Parallel Computing Toolbox™ ライセンスとサポートされている GPU デバイスが必要です。サポートされているデバイスについては、GPU 計算の要件 (Parallel Computing Toolbox)を参照してください。Parallel Computing Toolbox または適切な GPU が利用できない場合、エラーが返されます。

    • "cpu" — CPU を使用します。

    出力引数

    すべて折りたたむ

    Grad-CAM 重要度マップ。行ベクトルまたは数値配列として返されます。マップ内で正の値が大きな領域は、予測に積極的に寄与している入力データの領域に対応します。

    • 分類タスクの場合、scoreMap は、特徴層に含まれる各特徴について算出された、指定したクラスに関する最終分類スコアの勾配です。

    • それ以外のタイプのタスクの場合、scoreMap は、特徴層に含まれる各特徴について算出された、リダクション層の削減された出力の勾配です。

    scoreMap のサイズは、データのタイプによって異なります。

    • 2 次元イメージ データの場合、scoreMap は行列です。scoreMap(i,j) は、空間位置 (i,j) における Grad-CAM 重要度に対応します。たとえば、classIdx をベクトルとして指定した場合、scoreMap(:,:,n)classIdx(n) のマップに対応します。

    • 3 次元イメージ データの場合、scoreMap は 3 次元配列です。scoreMap(i,j,k) は、空間位置 (i,j,k) における Grad-CAM 重要度に対応します。たとえば、classIdx をベクトルとして指定した場合、scoreMap(:,:,:,n)classIdx(n) のマップに対応します。

    • ベクトル シーケンス データの場合、scoreMap は行ベクトルです。scoreMap(:,i) は、タイム ステップ i における Grad-CAM 重要度に対応します。たとえば、classIdx をベクトルとして指定した場合、scoreMap(:,:,n)classIdx(n) のマップに対応します。

    Grad-CAM マップの計算時に特徴マップを抽出する特徴層の名前。string として返されます。

    既定では、Grad-CAM マップの計算に使用する特徴層が gradCAM によって選択されます。この層は、大きさが 1 でない空間次元または時間次元をもち、入力層とデータ形式が等しい最後の層です。名前と値の引数 FeatureLayer を使って、どの特徴層を使用するかを指定できます。名前と値の引数 FeatureLayer を指定した場合、featureLayer は同じ値を返します。

    Grad-CAM マップの計算時に出力活性化を抽出するリダクション層の名前。string として返されます。

    既定では、Grad-CAM マップの計算に使用するリダクション層が gradCAM によって選択されます。この層は、dlnetwork オブジェクトの最後の層です。名前と値の引数 ReductionLayer を使って、どのリダクション層を使用するかを指定することもできます。名前と値の引数 ReductionLayer を指定した場合、reductionLayer は同じ値を返します。

    詳細

    すべて折りたたむ

    Grad-CAM

    勾配加重クラス活性化マッピング (Grad-CAM) は、深層ニューラル ネットワークによって行われた予測を理解するのに役立つ説明可能性の技術です[3]。CAM 手法を一般化したものである Grad-CAM は、ディープ ネットワークを流れるターゲットの勾配を考慮して、ネットワークによる予測における各ニューロンの重要度を判定します。

    Grad-CAM は、選択した層に含まれる畳み込みの特徴について、クラスのスコアなどの微分可能な出力の勾配を計算します。この勾配が空間次元と時間次元にプールされ、ニューロンの重要度の重みが求められます。その後、この重みを使用して活性化マップが線形結合され、予測にとってどの特徴が最も重要かが判定されます。

    クラス c のスコアを表す出力 yc をもつ 2 次元イメージ分類ネットワークがあり、k 個の特徴マップ (チャネル) Aki,j をもつ畳み込み層の Grad-CAM マップを計算するとします。ここで、i,j はピクセルのインデックスです。ニューロンの重要度の重みは以下のとおりです。

    αkc=1NijycAi,jkGradientsviabackpropGlobal average pooling,

    ここで、N は特徴マップに含まれるピクセル数の合計です。このとき、Grad-CAM マップは、特徴マップの重み付き組み合わせに ReLU を適用したものになります。

    M=ReLU(kαkcAk).

    ReLU 活性化によって、関心クラスに積極的に寄与している特徴のみを得ることができます。これにより、特徴マップと同じサイズをもつ、指定したクラスのヒートマップが出力として得られます。その後、入力データのサイズに合わせて Grad-CAM がアップサンプリングされます。

    Grad-CAM は、一般に分類タスクで使用されますが、微分可能な任意の活性化について Grad-CAM マップを計算することができます。たとえば、セマンティック セグメンテーション タスクの場合、yc(i,j)Syijc に置き換えることで Grad-CAM マップを計算できます。ここで、S は関心ピクセルのセットです。また、yi,jc は、ピクセル (i,j) がクラス c であると予測された場合は 1 になり、そうでない場合は 0 になります[4]。リダクション層の出力活性化を 1 つの値に削減する適切なリダクション関数を指定し、ニューロンの重要度を求める重み方程式の yc をその関数に置き換えることで、関数 gradCAM を非分類タスクに使用できます。

    ヒント

    • 関数 reductionFcn は、リダクション層からの出力をトレースされた dlarray オブジェクトとして受け取ります。この関数は、この出力をスカラー dlarray に削減しなければなりません。gradCAM は、特徴層の活性化に関してこのスカラーを微分します。たとえば、ネットワークのソフトマックス活性化に含まれるチャネル 208 について Grad-CAM マップを計算する場合、リダクション関数は @(x)(x(208)) となります。この関数は、活性化を受け取って 208 番目のチャネルを抽出します。

    • 関数 gradCAM は、Grad-CAM マップの計算に使用するリダクション層と特徴層を自動的に選択します。ネットワークによっては、選択された層が適切でない場合があります。たとえば、特徴層として使用できる層がネットワークに複数含まれている場合、この関数はその層のいずれかを選択しますが、その選択が最適であるとは限りません。そのようなネットワークの場合、名前と値の引数 FeatureLayer を使用して、どの特徴層を使用するかを指定します。

    • グレースケール イメージの上に Grad-CAM マップを重ねて表示するには、まず、範囲が [0, 1] となるようにマップを再スケーリングしなければなりません。たとえば、scoreMapRescaled = rescale(scoreMap); のようにします。

    参照

    [1] Kudo, Mineichi, Jun Toyama, and Masaru Shimbo. “Multidimensional Curve Classification Using Passing-through Regions.” Pattern Recognition Letters 20, no. 11–13 (November 1999): 1103–11. https://doi.org/10.1016/S0167-8655(99)00077-X.

    [2] UCI Machine Learning Repository: Japanese Vowels Dataset. https://archive.ics.uci.edu/ml/datasets/Japanese+Vowels.

    [3] Selvaraju, Ramprasaath R., Michael Cogswell, Abhishek Das, Ramakrishna Vedantam, Devi Parikh, and Dhruv Batra. “Grad-CAM: Visual Explanations from Deep Networks via Gradient-Based Localization.” 2017 (October 2017): 618–626, https://doi.org/10.1109/ICCV.2017.74.

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

    拡張機能

    バージョン履歴

    R2021a で導入

    すべて展開する