You are now following this question
- You will see updates in your followed content feed.
- You may receive emails, depending on your communication preferences.
畳み込みニューラルネットワークを用いた画像判別について
2 views (last 30 days)
Show older comments
MATLAB初心者です。畳み込みニューラルネットワークを使って学習データと評価データを使い、画像の判別を行い、その後、分割交差検証を使って、過学習を防ぐようにしたいです。また、その判別をしたモデルを使って、学習データと評価データで使った画像とは別の画像の判別を行いたいと考えています。
何かいい方法はないでしょうか。
よろしくお願いいたします。
Accepted Answer
Kenta
on 28 Jan 2020
こんにちは、こちらで試したわけではないので不確かなのですが、たとえば、functionのなかで、netができたあとに
save net net
などで、そのネットワークを保存すればそのディレクトリにnetが保存される気がします。ただ、
n回するうちに上書きされるので、最後のnetが保存されることになると思います。
そして、畳み込みニューラルネットワークによる画像分類であれば基本的にgrad-camも可能であると思います。
10 Comments
Kaneko
on 28 Jan 2020
ありがとうございます。別の画像の判別はできましたが、以下のようなエラーが出て、grad-camが実行されませんでした。
どこがいけないのか教えて頂けますでしょうか。
よろしくお願いいたします。
エラー:
nnet.internal.cnn.dlnetwork>iAssertLayerNameExist (line
453)
層 'relu5' は存在しません。
エラー: nnet.internal.cnn.dlnetwork>iGetOutputIndices
(line 431)
iAssertLayerNameExist(layerName, map);
エラー:
nnet.internal.cnn.dlnetwork>@(l)iGetOutputIndices(l,layerNameMap,layers)
(line 171)
[outputLayerIdx, outputLayerPortIdx] =
cellfun( @(l)iGetOutputIndices(l,
layerNameMap, layers), outputNames );
エラー:
nnet.internal.cnn.dlnetwork/getOutputLayersIndicesFromNames
(line 171)
[outputLayerIdx, outputLayerPortIdx] =
cellfun( @(l)iGetOutputIndices(l,
layerNameMap, layers), outputNames );
エラー: dlnetwork/parseForwardMethodsNameValuePairs
(line 246)
[layerIndices, layerOutputIndices] =
getOutputLayersIndicesFromNames(this.PrivateNetwork,
outputNames);
エラー: dlnetwork/predict (line 204)
[layerIndices, layerOutputIndices] =
net.parseForwardMethodsNameValuePairs(varargin{:});
エラー: kasika>Gradient_function (line 36)
[scores,conv_output] = predict(net0, I2, 'Outputs',
{softmaxlayer, activationlayer}); % 予測確率とMAPを作る層
までの出力を得る
エラー: deep.internal.dlfeval (line 18)
[varargout{1:nout}] = fun(x{:});
エラー: dlfeval (line 40)
[varargout{1:nout}] =
deep.internal.dlfeval(fun,varargin{:});
エラー: kasika (line 22)
[conv_output,gradients] = dlfeval(@Gradient_function,net0,img2,softmaxlayer,activationlayer,class);
load('net10.mat')
%% Autodiffにかけられるようにdlnetworkに変更
lgraph = layerGraph(net10.Layers); %
Outputlayer = lgraph.Layers(end);
newlgraph = removeLayers(lgraph,lgraph.Layers(end).Name); % calssificationの層だけ取る
net0 = dlnetwork(newlgraph); % dlnetworkに変更
softmaxlayer = 'softmax' ; % 予測確率が出てくる最後のレイヤを指定
activationlayer = 'relu5'; % MAPを適用するレイヤを指定
%% 画像の読み込み
labeltbl = {'sioaritest';'sionasitest'};
colortbl = [255 255 102; 73 6 248];
img = imread(fullfile('houdentestdata','sionasitest','houden_190807_0005 (35).jpg'));% 画像の取り込み
img = imresize(img,[150 200]); % ネットワークと同じサイズに変更
[class,score] = classify(net,img); % 推論
class
max(score)
img2 = dlarray(single(img),'SSC');
% 指定レイヤの出力とGradientをとる
[conv_output,gradients] = dlfeval(@Gradient_function,net0,img2,softmaxlayer,activationlayer,class);
% 得られた出力から演算でヒートマップを作製
gradcam = sum(conv_output .* mean(gradients, [1 2]), 3); % GradientのGlobal average poolingし出力とかけ和をとる
gradcam = extractdata(gradcam); % single型で取り出し。
gradcam = max(gradcam,0); % relu関数を適用
gradcam = imresize(gradcam, [150 200], 'Method', 'bicubic'); % 画像サイズに合わせる
HeatMap = map2jpg(gradcam, [150 200], 'jet'); % ヒートマップ表示の画像データに変換する
HeatMap = uint8((im2double(img)*0.3+HeatMap*0.5)*255); % 元画像と重ね合わせる
out2 = [img HeatMap]; % 元画像と結果を横方向に結合する
imshow(out2);shg
%%
function [conv_output,gradients] = Gradient_function(net0,I2,softmaxlayer,activationlayer,class)
[scores,conv_output] = predict(net0, I2, 'Outputs', {softmaxlayer, activationlayer}); % 予測確率とMAPを作る層までの出力を得る
loss = scores(class); % 指定したクラスのスコアをとる
gradients = dlgradient(loss,conv_output); % MAPを作る層でのgradientをとる
gradients = gradients / (sqrt(mean(gradients.^2,'all')) + 1e-5); % 正規化する
end
% ヒートマップに変換する関数
function img = map2jpg(imgmap, range, colorMap)
imgmap = double(imgmap);
if(~exist('range', 'var') || isempty(range))
range = [min(imgmap(:)) max(imgmap(:))];
end
heatmap_gray = mat2gray(imgmap, range);
heatmap_x = gray2ind(heatmap_gray, 256);
heatmap_x(isnan(imgmap)) = 0;
if(~exist('colorMap', 'var'))
img = ind2rgb(heatmap_x, jet(256));
else
img = ind2rgb(heatmap_x, eval([colorMap '(256)']));
end
end
%%
% _Copyright 2018-2019 The MathWorks, Inc._
Kenta
on 28 Jan 2020
こんにちは、解決し、よかったです。
grad-camのほうですが、エラーは「層 'relu5' は存在しません」と書いていますね。
ということはお使いになられているCNNに、その名前をもつ層がないということではないでしょうか。
grad-camで参照したい特徴マップの直前のrelu層を取り出すと思いますが、それの名前を探してみてはいかがでしょうか。
analyzenetworkでネットワークを見れるので、あとは、変数netをクリックして調べたりすれば、ターゲットとなるrelu層が見つかると思います。その名前を指定すれば良いと思います。
ただ、お使いになられているCNNの構造を知りませんので、これを解決してもさらなるエラーがでるかもしれません。
Kaneko
on 29 Jan 2020
回答ありがとうございます。relu5についてですが、学習済みネットワークであるalexnetのものでした。いろいろと、ネットにあるサンプルコードを使っていった結果、alexnetを使ってないから、relu5が存在しません、と出てしまったと考えられます。
交差検証のコードに、alexnetを使えば、この問題は解決すると思いますが、以下のコードに、alexnetを入れることは可能でしょうか。よろしくお願いいたします。
imds = imageDatastore('houdenmatlab1', ...
'IncludeSubfolders',true, ...
'LabelSource','foldernames');
figure;
perm = randperm(200,20);
for i = 1:20
subplot(4,5,i);
imshow(imds.Files{perm(i)});
end
labelCount = countEachLabel(imds)
img = readimage(imds,1);
size(img)
numTrainFiles = 80;
[imdsTrain,imdsValidation] = splitEachLabel(imds,numTrainFiles,'randomize');
%% ダミーのトレーニングインデックスを生成
X = (1:imds.numpartitions)';
y = imds.Labels;
%% 交差検定にCNNの予測ラベル関数のポインタを渡す
cp = cvpartition(y,'k',10); % Stratified cross-validation
mcr = crossval('mcr',X,y,'Predfun',@(xtrain,ytrain,xtest)myCNNPredict(xtrain,ytrain,xtest,imds),'partition',cp)
%% CNNを学習し、予測ラベルを出力する関数
function ypred = myCNNPredict(xtrain,ytrain,xtest,imds)
% 結果が一意になるように乱数シードをデフォルト値に設定
rng('default');
% ダミーの変数ベクトルを受けてimageDatastoreを学習用とテスト用に分割
imdsTrain = imageDatastore(imds.Files(xtrain));
imdsTrain.Labels = ytrain;
imdsValidation = imageDatastore(imds.Files(xtest));
layers = [
imageInputLayer([150 200 3])
convolution2dLayer(3,8,'Padding','same')
batchNormalizationLayer
reluLayer
maxPooling2dLayer(2,'Stride',2)
convolution2dLayer(3,16,'Padding','same')
batchNormalizationLayer
reluLayer
maxPooling2dLayer(2,'Stride',2)
convolution2dLayer(3,32,'Padding','same')
batchNormalizationLayer
reluLayer
fullyConnectedLayer(2)
softmaxLayer
classificationLayer];
options = trainingOptions('sgdm', ...
'InitialLearnRate',0.01, ...
'MaxEpochs',5, ...
'Shuffle','every-epoch', ...
'Verbose',false);
net10 = trainNetwork(imdsTrain,layers,options);
ypred = classify(net10,imdsValidation);
save net10
end
Kenta
on 29 Jan 2020
こんにちは、
「ネットにあるサンプルコードを使っていった結果、alexnetを使ってないから、relu5が存在しません、と出てしまったと考えられます」はい、そうですね、私もそうだと思います。
コードも共有いただきありがとうございます。
自分で定義したCNNを使っていたんですね。はい、alexnetにもできます。
layers...のところを削除します。あらかじめ、load alexnetでロードしておき、
自分のクラス数にあうように適宜、レイヤーを入れ替えます。これはコードでもできますし、deepnetworkdesignerでもできます。
そして、functionの引数にalexnetも含めるようにして、つまり
function ypred = myCNNPredict(xtrain,ytrain,xtest,imds,layers)
とすれば動くと思います。「MATLAB初心者です」とのことですが、いきなりだと少し難しいかもしれませんね...
Kaneko
on 30 Jan 2020
回答ありがとうございます。上記のコードのlayers...をdeepnetworkdesignerを使って、leyer_1として作成しました。以下のようにやってみたのですが、mcr = crossval('mcr',X,y,'Predfun',@(xtrain,ytrain,xtest)myCNNPredict(xtrain,ytrain,xtest,imds),'partition',cp)の部分で入力引数が不足しています。と出てしまいましたがどういう事か分かりません。
よろしくお願いいたします。
load layer_1
imds = imageDatastore('houdenmatlab1', ...
'IncludeSubfolders',true, ...
'LabelSource','foldernames');
figure;
perm = randperm(200,20);
for i = 1:20
subplot(4,5,i);
imshow(imds.Files{perm(i)});
end
labelCount = countEachLabel(imds)
img = readimage(imds,1);
size(img)
numTrainFiles = 80;
[imdsTrain,imdsValidation] = splitEachLabel(imds,numTrainFiles,'randomize');
%% ダミーのトレーニングインデックスを生成
X = (1:imds.numpartitions)';
y = imds.Labels;
%% 交差検定にCNNの予測ラベル関数のポインタを渡す
cp = cvpartition(y,'k',10); % Stratified cross-validation
mcr = crossval('mcr',X,y,'Predfun',@(xtrain,ytrain,xtest)myCNNPredict(xtrain,ytrain,xtest,imds),'partition',cp)
%% CNNを学習し、予測ラベルを出力する関数
function ypred = myCNNPredict(xtrain,ytrain,xtest,imds,layers)
% 結果が一意になるように乱数シードをデフォルト値に設定
rng('default');
% ダミーの変数ベクトルを受けてimageDatastoreを学習用とテスト用に分割
imdsTrain = imageDatastore(imds.Files(xtrain));
imdsTrain.Labels = ytrain;
imdsValidation = imageDatastore(imds.Files(xtest));
options = trainingOptions('sgdm', ...
'InitialLearnRate',0.01, ...
'MaxEpochs',5, ...
'Shuffle','every-epoch', ...
'Verbose',false);
net10 = trainNetwork(imdsTrain,layers,options);
ypred = classify(net10,imdsValidation);
save net10
end
Kaneko
on 31 Jan 2020
Edited: Kaneko
on 31 Jan 2020
すみません、もう一つ質問よろしいでしょうか。以下のコードで誤分類率を出すことはできたのですが、保存した、net2をディープラーニング評価キットのD2_2_3_mygradcam_alexnet.mを使って、別の画像を判別してみたのですが、どの画像を判別しても、同じ方に判別されてしまい、ans = signal 1(100%)となってしまいます。また、ヒートマップも画像のように判別要因がでないというような状態です。
何度も質問してしまい、申し訳ございません。よろしくお願いいたします。
![](https://www.mathworks.com/matlabcentral/answers/uploaded_files/269214/image.jpeg)
load net2
%% Autodiffにかけられるようにdlnetworkに変更
lgraph = layerGraph(net2.Layers); %
Outputlayer = lgraph.Layers(end);
newlgraph = removeLayers(lgraph,lgraph.Layers(end).Name); % calssificationの層だけ取る
net0 = dlnetwork(newlgraph); % dlnetworkに変更
softmaxlayer = 'softmax' ; % 予測確率が出てくる最後のレイヤを指定
activationlayer = 'relu3'; % MAPを適用するレイヤを指定
%% 画像の読み込み
labeltbl = {'sioaritest';'sionasitest'};
colortbl = [255 255 102; 73 6 248];
img = imread(fullfile('houdentestdata','sionasitest','houden_190807_0005 (1).jpg'));% 画像の取り込み
img = imresize(img,[150 200]); % ネットワークと同じサイズに変更
[class,score] = classify(net2,img); % 推論
class
max(score)
img2 = dlarray(single(img),'SSC');
% 指定レイヤの出力とGradientをとる
[conv_output,gradients] = dlfeval(@Gradient_function,net0,img2,softmaxlayer,activationlayer,class);
% 得られた出力から演算でヒートマップを作製
gradcam = sum(conv_output .* mean(gradients, [1 2]), 3); % GradientのGlobal average poolingし出力とかけ和をとる
gradcam = extractdata(gradcam); % single型で取り出し。
gradcam = max(gradcam,0); % relu関数を適用
gradcam = imresize(gradcam, [150 200], 'Method', 'bicubic'); % 画像サイズに合わせる
HeatMap = map2jpg(gradcam, [150 200], 'jet'); % ヒートマップ表示の画像データに変換する
HeatMap = uint8((im2double(img)*0.3+HeatMap*0.5)*255); % 元画像と重ね合わせる
out2 = [img HeatMap]; % 元画像と結果を横方向に結合する
imshow(out2);shg
%%
function [conv_output,gradients] = Gradient_function(net0,I2,softmaxlayer,activationlayer,class)
[scores,conv_output] = predict(net0, I2, 'Outputs', {softmaxlayer, activationlayer}); % 予測確率とMAPを作る層までの出力を得る
loss = scores(class); % 指定したクラスのスコアをとる
gradients = dlgradient(loss,conv_output); % MAPを作る層でのgradientをとる
gradients = gradients / (sqrt(mean(gradients.^2,'all')) + 1e-5); % 正規化する
end
% ヒートマップに変換する関数
function img = map2jpg(imgmap, range, colorMap)
imgmap = double(imgmap);
if(~exist('range', 'var') || isempty(range))
range = [min(imgmap(:)) max(imgmap(:))];
end
heatmap_gray = mat2gray(imgmap, range);
heatmap_x = gray2ind(heatmap_gray, 256);
heatmap_x(isnan(imgmap)) = 0;
if(~exist('colorMap', 'var'))
img = ind2rgb(heatmap_x, jet(256));
else
img = ind2rgb(heatmap_x, eval([colorMap '(256)']));
end
end
%%
% _Copyright 2018-2019 The MathWorks, Inc._
More Answers (0)
See Also
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!An Error Occurred
Unable to complete the action because of changes made to the page. Reload the page to see its updated state.
Select a Web Site
Choose a web site to get translated content where available and see local events and offers. Based on your location, we recommend that you select: .
You can also select a web site from the following list
How to Get Best Site Performance
Select the China site (in Chinese or English) for best site performance. Other MathWorks country sites are not optimized for visits from your location.
Americas
- América Latina (Español)
- Canada (English)
- United States (English)
Europe
- Belgium (English)
- Denmark (English)
- Deutschland (Deutsch)
- España (Español)
- Finland (English)
- France (Français)
- Ireland (English)
- Italia (Italiano)
- Luxembourg (English)
- Netherlands (English)
- Norway (English)
- Österreich (Deutsch)
- Portugal (English)
- Sweden (English)
- Switzerland
- United Kingdom (English)
Asia Pacific
- Australia (English)
- India (English)
- New Zealand (English)
- 中国
- 日本Japanese (日本語)
- 한국Korean (한국어)