畳み込みニューラルネットワークを用いた画像判別について
2 次查看(过去 30 天)
显示 更早的评论
Kaneko
2020-1-24
MATLAB初心者です。畳み込みニューラルネットワークを使って学習データと評価データを使い、画像の判別を行い、その後、分割交差検証を使って、過学習を防ぐようにしたいです。また、その判別をしたモデルを使って、学習データと評価データで使った画像とは別の画像の判別を行いたいと考えています。
何かいい方法はないでしょうか。
よろしくお願いいたします。
2 个评论
Kaneko
2020-1-27
ありがとうございます。おかげさまで、分割交差検証を使って、誤分類率を出すことができました。
ちなみにですが、この交差検証を行ったものを使用して、学習データ、評価データとは別の画像を判別したいと考えているのですが、可能でしょうか。
また、grad-camに用いることは可能でしょうか。
よろしくお願いいたします。
采纳的回答
Kenta
2020-1-28
こんにちは、こちらで試したわけではないので不確かなのですが、たとえば、functionのなかで、netができたあとに
save net net
などで、そのネットワークを保存すればそのディレクトリにnetが保存される気がします。ただ、
n回するうちに上書きされるので、最後のnetが保存されることになると思います。
そして、畳み込みニューラルネットワークによる画像分類であれば基本的にgrad-camも可能であると思います。
10 个评论
Kaneko
2020-1-28
ありがとうございます。別の画像の判別はできましたが、以下のようなエラーが出て、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
2020-1-28
こんにちは、解決し、よかったです。
grad-camのほうですが、エラーは「層 'relu5' は存在しません」と書いていますね。
ということはお使いになられているCNNに、その名前をもつ層がないということではないでしょうか。
grad-camで参照したい特徴マップの直前のrelu層を取り出すと思いますが、それの名前を探してみてはいかがでしょうか。
analyzenetworkでネットワークを見れるので、あとは、変数netをクリックして調べたりすれば、ターゲットとなるrelu層が見つかると思います。その名前を指定すれば良いと思います。
ただ、お使いになられているCNNの構造を知りませんので、これを解決してもさらなるエラーがでるかもしれません。
Kaneko
2020-1-29
回答ありがとうございます。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
2020-1-29
こんにちは、
「ネットにあるサンプルコードを使っていった結果、alexnetを使ってないから、relu5が存在しません、と出てしまったと考えられます」はい、そうですね、私もそうだと思います。
コードも共有いただきありがとうございます。
自分で定義したCNNを使っていたんですね。はい、alexnetにもできます。
layers...のところを削除します。あらかじめ、load alexnetでロードしておき、
自分のクラス数にあうように適宜、レイヤーを入れ替えます。これはコードでもできますし、deepnetworkdesignerでもできます。
そして、functionの引数にalexnetも含めるようにして、つまり
function ypred = myCNNPredict(xtrain,ytrain,xtest,imds,layers)
とすれば動くと思います。「MATLAB初心者です」とのことですが、いきなりだと少し難しいかもしれませんね...
Kaneko
2020-1-30
回答ありがとうございます。上記のコードの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
2020-1-30
すみません、解決しました。deepnetworkdesignerを使わず、コードで、relu3など、層に名前を入れていったらできました。
いろいろと教えて頂き、ありがとうございました。
Kaneko
2020-1-31
编辑:Kaneko
2020-1-31
すみません、もう一つ質問よろしいでしょうか。以下のコードで誤分類率を出すことはできたのですが、保存した、net2をディープラーニング評価キットのD2_2_3_mygradcam_alexnet.mを使って、別の画像を判別してみたのですが、どの画像を判別しても、同じ方に判別されてしまい、ans = signal 1(100%)となってしまいます。また、ヒートマップも画像のように判別要因がでないというような状態です。
何度も質問してしまい、申し訳ございません。よろしくお願いいたします。
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._
Kenta
2020-1-31
毎度返信が遅くなり申し訳ございません。
前提条件などを明記したうえで新たに質問をされてはいかがでしょうか。その方がより多くの方からアドバイスを頂けると思いますし、今後似た問題がある方の参考にもなりそうです。
更多回答(0 个)
另请参阅
类别
在 Help Center 和 File Exchange 中查找有关 イメージを使用した深層学習 的更多信息
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!发生错误
由于页面发生更改,无法完成操作。请重新加载页面以查看其更新后的状态。
您也可以从以下列表中选择网站:
如何获得最佳网站性能
选择中国网站(中文或英文)以获得最佳网站性能。其他 MathWorks 国家/地区网站并未针对您所在位置的访问进行优化。
美洲
- América Latina (Español)
- Canada (English)
- United States (English)
欧洲
- 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)
亚太
- Australia (English)
- India (English)
- New Zealand (English)
- 中国
- 日本Japanese (日本語)
- 한국Korean (한국어)