MATLAB Answers

独自で作成した学習モデルを用いたGrad-CAM

22 views (last 30 days)
resnet101を転移学習させたモデルを使って3クラス分類をしています。
その際に画像のどの部分に着目しているかを調べるためにGrad-CAMの実装を、
ドキュメンテーション(Grad-CAMでの深層学習による判定の理由を解明)を見ながら試みたのですが
以下のエラーが出てしまい原因がわかりません。
エラー: nnet.internal.cnn.dlnetwork/predict (line 198)
層 'bn2a_branch2a': 入力データが無効です。 'Variance' の値は無効です。 入力は正にする必要があります。
エラー: dlnetwork/predict (line 205)
[varargout{1:nargout}] = predict(net.PrivateNetwork, x, layerIndices, layerOutputIndices);
エラー: gradcam (line 2)
[scores,convMap] = predict(dlnet, dlImg, 'Outputs', {softmaxName, convLayerName});
エラー: deep.internal.dlfeval (line 18)
[varargout{1:nout}] = fun(x{:});
エラー: dlfeval (line 40)
[varargout{1:nout}] = deep.internal.dlfeval(fun,varargin{:});
エラー: G_CAM (line 34)
[convMap, dScoresdMap] = dlfeval(@gradcam, dlnet, dlImg, softmaxName, convLayerName, classfn);
最初のネットワークの読み込み部分と最終畳み込み層の名前を
ConvLayerName = 'res5c_relu'にした以外は基本的に変えていません。
6/29追記
lgraphとdlnetのプロパティを調べたところ、以下のようになりました。
lgraph =
LayerGraph のプロパティ:
Layers: [346×1 nnet.cnn.layer.Layer]
Connections: [378×2 table]
InputNames: {'data'}
OutputNames: {1×0 cell}
ーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーー
dlnet =
dlnetwork のプロパティ:
Layers: [346×1 nnet.cnn.layer.Layer]
Learnables: [418×3 table]
State: [208×3 table]
dlnetworkに変換したときにConnectionsとInputNamesとOutputNamesが消えていました。
これがエラーの原因になっているかはわかりませんが、
調べた感じではdlnetworkオブジェクトに変換しただけでこれらが消える事例はなかったので気になりました。
消えてしまう原因もわからずじまいで、手詰まりになっています。
%3クラス分類のネットワークの読み込み
net = load('classification.mat');
net = net.net
%イメージサイズの読み取り
inputSize = net.Layers(1).InputSize(1:2);
%画像の読み込み
img = imread("IMG_4257.JPG");
%画像サイズの変更
img = imresize(img,inputSize);
%イメージを分類して、分類結果及びスコアを表示
[classfn,score] = classify(net,img);
imshow(img);
title(sprintf("%s (%.2f)", classfn, score(classfn)));
type gradcam.m
analyzeNetwork(net)
%Grad-Camを使用するためにdlnetworkを作成する。ネットワークから層グラフを作成する。
lgraph = layerGraph(net);
%分類に使用されるデータにアクセスするため、最終分類層を削除
lgraph = removeLayers(lgraph, lgraph.Layers(end).Name);
%層グラフからdlnetworkを作成
dlnet = dlnetwork(lgraph);
%ソフトマックス層の名前を'prob'に指定。最終畳み込み層の名前を'res5c_relu'に指定
softmaxName = 'prob';
convLayerName = 'res5c_relu';
analyzeNetwork(lgraph)
%自動微分を使用するために、画像をdlarrayに変換
dlImg = dlarray(single(img),'SSC');
%関数gradcamでdlfevalを呼び出すことによって画像のGrad-CAM勾配を計算
[convMap, dScoresdMap] = dlfeval(@gradcam, dlnet, dlImg, softmaxName, convLayerName, classfn);
%
gradcamMap = sum(convMap .* sum(dScoresdMap, [1 2]), 3);
gradcamMap = extractdata(gradcamMap);
gradcamMap = rescale(gradcamMap);
gradcamMap = imresize(gradcamMap, inputSize, 'Method', 'bicubic');
%'AlphaData'の値として、0.5を使用して、イメージの上にGrad-CAMレベルを表示する。'jet'カラーマップでは、濃い青が最低値、濃い赤が最高値
imshow(img);
hold on;
imagesc(gradcamMap,'AlphaData', 0.5);
colormap jet
hold off;
title("Grad-CAM");

  9 Comments

Show 6 older comments
Kenta
Kenta on 2 Jul 2020
わかりました。教えていただきありがとうございます。
resnet101以外で行ってみてはいかがでしょうか。もしかしたらネットワークを変更したらうまく走るかもしれません。
Kenta
Kenta on 2 Jul 2020
あと少し思い出したことがあるのですが、gradcam関数の中のpredictをforwardとsoftmax関数で書き直すと良いかもしれません。こちらの勘違いかもしれませんが、カスタムループ形式の深層学習のときにpredict関数のかわりに、上のように書き直すとうまくいった経験があります。
Takuma Hashimoto
Takuma Hashimoto on 2 Jul 2020
ありがとうございます。
私の技術不足で恐縮ですが、どのように書き直せばよいか
具体的にコードを見せていただくことは可能でしょうか。

Sign in to comment.

Accepted Answer

Kenta
Kenta on 3 Jul 2020
[featureMap,scores]=forward(dlnet,dlImg,'Outputs',{convLayerName,'prob'});
こんにちは、コメントのほう、返信ありがとうございます。
predict関数ではなく、forward関数で行ってはいかがでしょうか。詳細は添付のファイルをご覧ください。

  1 Comment

Takuma Hashimoto
Takuma Hashimoto on 5 Jul 2020
動かせました!
ありがとうございます。

Sign in to comment.

More Answers (0)