基本的な流れは、Matlabの無料教材の下記を参照しています。
https://jp.mathworks.com/learn/tutorials/deep-learning-onramp.html
(1) プロジェクト設定
今回の作業フォルダを「deep01」としておきます。その中にLive Scriptファイル「deep01.mlx」を作成します。さらに学習用・テスト用画像フォルダ「image」を作っておきます。
(2) 画像データの用意
imageフォルダの中に、画像データを入れておきます。今回は12個の献立を分類するので、その献立毎12個のフォルダを作成して、フォルダ名は献立名にしておきます。
それぞれの献立フォルダの中に、それぞれ80枚程度の画像を入れておきます。
注意:jpegファイルでCMYK形式のファイルは、今回の読み込みでエラーになるので省いておきます。
(3) 画像の取り込み
今回はalexnetを転移学習して利用するため、入力の画像データが227 x 227 x 3になります。データストアを作成するときに、画像を加工しておく関数を用意します。
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
function img = imageread(file) | |
img = imread(file); | |
img = imresize(img,[227 227]); | |
end |
読み込みスクリプト
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
%学習イメージの取得 | |
food_ds = imageDatastore('/Users/mizuno/Documents/MATLAB/deep01/image','IncludeSubfolders',true,'LabelSource','foldernames','ReadFcn',@imageread); | |
[trainImgs,testImgs] = splitEachLabel(food_ds,0.8); | |
numClasses = numel(categories(food_ds.Labels)); |
サブフォルダの読み込み、フォルダ名をラベル名にする、読み込み時にimageread関数を適用する、を指定しています。学習用ファイルとテスト用ファイルを4:1にしています。分類をいくつするかを、numClassesに入れています。
ここまで実行するとWorkspaceに読み込まれます。
関数:numel 配列の要素数を返す
https://jp.mathworks.com/help/matlab/ref/numel.html
montage(food_ds)
としてみると、画像一覧が見られます。
時間がかかるコードは、必要に応じてセクションの区切りを入れておきます。
(4) 学習ネットワークの作成
今回は学習済みモデル「alexnet」を転移学習していきます。
alexnetを読み込み、レイヤーを見てみると25層あることがわかります。
第1層:Image Input では入力が、227x227x3であることがわかります。
第23層:1000個の出力クラスに紐づいています。
第25層:出力層です
ここでは、23層を全結合層:分類数12、25層を分類出力層と指定します。
fullyConnectedLayer :https://jp.mathworks.com/help/deeplearning/ref/nnet.cnn.layer.fullyconnectedlayer.html
classificationLayer:https://jp.mathworks.com/help/deeplearning/ref/classificationlayer.html
(5) 学習の実行
まず、学習アルゴリズムを指定します。
%学習アルゴリズム オプションの設定
options = trainingOptions('sgdm','InitialLearnRate', 0.001);
sgdm : ネットワーク学習ソルバー (sgdm, rmsprop, adamから選択) モーメンタム項付き確率的勾配降下法 (SGDM)
InitialLearnRate : 初期学習率を指定、今回は0.001(sgdmの初期学習率は0.01)
https://jp.mathworks.com/help/deeplearning/ref/trainingoptions.html
%学習の実行
[foodnet,info] = trainNetwork(trainImgs, layers, options);
時間がかかります。
精度が100%になっても、損失が下がるまで続きます。
学習損失のプロット:info の TrainingLoss フィールドに格納
(6) 学習済みネットワークを用いた分類
学習したネットワークを用いて、テストデータを分類してみます。
testpreds = classify(foodnet,testImgs);
%関数 nnz と等号演算子 (==) を使用して、正しい分類と一致している予測された分類の数をカウント
numCorrect = nnz(foodpreds == testImgs.Labels)
精度を確認
foodCorrect = numCorrect / numel(foodpreds)
混同行列の作成
[foodconf, foodnames] = confusionmat(testImgs.Labels, foodpreds)
confusionchartの作成
confusionchart(testImgs.Labels, foodpreds)
ヒートマップの作成
heatmap(foodnames, foodnames, foodconf)
これをみると、全体で77%
ほうれん草のおひたし:OK(間違え:0)
味噌汁:ほぼOK(間違え:1)
カレー:肉じゃがと間違えられる(間違え:3)
コロッケ:ソーセージと唐揚げに間違えられる(間違え:3)
ソーセージ:精度低い(間違え:6)
ハンバーグ:コロッケに間違えられる(間違え:4)
パン:ぼちぼち(間違え:2)
唐揚げ:精度低い(間違え:8)
卵焼き:餃子と間違えられる(間違え:3)
肉じゃが:唐揚げと間違えられる(間違え:1)
餃子:精度低い(間違え:4)
魚の照り焼き:カレーに間違えられる(間違え:6)
ソーセージ、唐揚げ、魚の照り焼きに間違えが多い。唐揚げに間違えられるのも多い。
関数 nnz : 行列中で等しい要素数を返す
https://jp.mathworks.com/help/matlab/ref/nnz.html
confusionmat : 分類問題用の混同行列の計算
https://jp.mathworks.com/help/stats/confusionmat.html
https://github.com/smzn/deep01/blob/master/deep01.mlx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
%学習イメージの取得 | |
food_ds = imageDatastore('/Users/mizuno/Documents/MATLAB/deep01/image','IncludeSubfolders',true,'LabelSource','foldernames','ReadFcn',@imageread); | |
[trainImgs,testImgs] = splitEachLabel(food_ds,0.8); | |
numClasses = numel(categories(food_ds.Labels)); | |
%montage(food_ds) | |
%AlexNet の変更によるネットワークの作成 | |
net = alexnet; | |
layers = net.Layers; | |
layers(end-2) = fullyConnectedLayer(numClasses); | |
layers(end) = classificationLayer; | |
%学習アルゴリズム オプションの設定 | |
options = trainingOptions('sgdm','InitialLearnRate', 0.001); | |
%学習の実行 | |
[foodnet,info] = trainNetwork(trainImgs, layers, options); | |
%info の TrainingLoss フィールドに格納されている学習損失をプロットしてください。 | |
plot(info.TrainingLoss) | |
%学習済みネットワークを使用したテスト イメージの分類 | |
foodpreds = classify(foodnet,testImgs); | |
%関数 nnz と等号演算子 (==) を使用して、正しい分類と一致している予測された分類の数をカウント | |
numCorrect = nnz(foodpreds == testImgs.Labels) | |
foodCorrect = numCorrect / numel(foodpreds) | |
[foodconf, foodnames] = confusionmat(testImgs.Labels, foodpreds) | |
confusionchart(testImgs.Labels, foodpreds) | |
heatmap(foodnames, foodnames, foodconf) | |
function img = imageread(file) | |
img = imread(file); | |
img = imresize(img,[227 227]); | |
end |
参考として
MABLABでは、JPEGでもCMYK形式の画像を受け付けていません。CMYK形式の画像を見つける方法としては、
ImageMagickをインストール
https://imagemagick.org/
環境変数の登録
例:C:\Program Files\ImageMagick-7.0.8-Q16
CMYKファイルのみカラーデータ表示させる
windows
magick identify -verbose *.jpg | ( findstr "Colorspace Image:" | findstr "CMYK Image:")