交差検証を用いた画像の判別について
3 views (last 30 days)
Show older comments
交差検証を用いた画像の判別を行っています。まず,2種類の画像を100枚ずつ,合計200枚を以下のコードで交差検証を行い,誤分類率を出します。以下は,データを10分割して,交差検証を行った結果です。
imds = imageDatastore('train_data', ...
'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([28 28 1],'Name','input')
convolution2dLayer(3,8,'Padding','same','Name','conv1')
batchNormalizationLayer('Name','BN1')
reluLayer('Name','relu1')
crossChannelNormalizationLayer(5)
maxPooling2dLayer(2,'Stride',2,'Name','pool1')
convolution2dLayer(3,16,'Padding','same','Name','conv2')
batchNormalizationLayer('Name','BN2')
reluLayer('Name','relu2')
crossChannelNormalizationLayer(5)
maxPooling2dLayer(2,'Stride',2,'Name','pool2')
convolution2dLayer(3,32,'Padding','same','Name','conv3')
batchNormalizationLayer('Name','BN3')
reluLayer('Name','relu3')
dropoutLayer('probability',0.5,'Name','drop6')
fullyConnectedLayer(2,'Name','fc')
softmaxLayer('Name','softmax')
classificationLayer('Name','classoutput')];
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
それを,net10に保存すると,net10.matというmatファイルができます。これを使用して,以下のコードを使って,交差検証に使用していない画像を判別し,ヒートマップで,判別要因をみようとしています。
load net10
%% 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 = 'relu3'; % MAPを適用するレイヤを指定
%% 画像の読み込み
labeltbl = {'4test';'9test'};
colortbl = [255 255 102; 73 6 248];
img = imread(fullfile('test_data','4test','5796.jpg'));% 画像の取り込み
img = imresize(img,[28 28]); % ネットワークと同じサイズに変更
[class,score] = classify(net10,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, [28 28], 'Method', 'bicubic'); % 画像サイズに合わせる
HeatMap = map2jpg(gradcam, [], 'jet'); % ヒートマップ表示の画像データに変換する
HeatMap = uint8((im2double(img)*0.3+HeatMap*0.5)*255); % 元画像と重ね合わせる
out2 = [img HeatMap]; % 元画像と結果を横方向に結合する
imshow(out2);shg
%%
function [conv_output,gradients] = Gradient_function(net10,I2,softmaxlayer,activationlayer,class)
[scores,conv_output] = predict(net10, 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._
しかし,以下のようなエラーが出ました。
エラー: horzcat
連結する配列の次元が一致しません。
エラー: kasika (line 28)
out2 = [img HeatMap]; % 元画像と結果を横方向に結合する。
以前,別の画像を判別したときは,うまくいったので,同じものを使用してみましたが,このようなエラーがでてしまいました。
どこがおかしいか教えていただけますでしょうか。よろしくお願い致します。
0 Comments
Accepted Answer
More Answers (0)
See Also
Categories
Find more on Modify Image Colors in Help Center and File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!