2019年4月30日火曜日

Matlab : Deep Learningの基礎

MatlabでDeep Learningをやるときの方法です。今回は献立を分類してみます。
基本的な流れは、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になります。データストアを作成するときに、画像を加工しておく関数を用意します。

読み込みスクリプト

サブフォルダの読み込み、フォルダ名をラベル名にする、読み込み時に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



参考として
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:")