独自で作成した学習モデルを用いたGrad-CAM
Show older comments
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
Kenta
on 26 Jun 2020
こんにちは、classification.matと対象画像を添付いただけると考えやすいのですが、添付いただくことは可能でしょうか。ご検討宜しくお願い致します。
Takuma Hashimoto
on 29 Jun 2020
Kenta
on 29 Jun 2020
上のコードで、もともとのresnet101と、サンプル画像でやってみましたが、こちらではエラーは返さず、うまく走りました。おそらく、そちらのネットワーク固有の問題なのではと思います。ちなみに、dlfeval(@gradcam...
の直前まで実行してから
lgraph.Layers(19, 1).TrainedVariance
と打つとどのような値がでますか?エラー文ではこの値におそらく0が含まれているとあります。
Takuma Hashimoto
on 30 Jun 2020
Edited: Takuma Hashimoto
on 30 Jun 2020
Kenta
on 30 Jun 2020
詳細をありがとうございます。resnet用にリサイズ(224×224など)した画像を添付してもらえることは可能ですか?
Takuma Hashimoto
on 1 Jul 2020
Kenta
on 2 Jul 2020
わかりました。教えていただきありがとうございます。
resnet101以外で行ってみてはいかがでしょうか。もしかしたらネットワークを変更したらうまく走るかもしれません。
Kenta
on 2 Jul 2020
あと少し思い出したことがあるのですが、gradcam関数の中のpredictをforwardとsoftmax関数で書き直すと良いかもしれません。こちらの勘違いかもしれませんが、カスタムループ形式の深層学習のときにpredict関数のかわりに、上のように書き直すとうまくいった経験があります。
Takuma Hashimoto
on 2 Jul 2020
Accepted Answer
More Answers (0)
Categories
Find more on Deep Learning Toolbox in Help Center and File Exchange
Products
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!