【Matlab】自分用忘備録 DeepLearning編

#前置き
このページはDeepLearning関連で自分がよく使いそうな関数等を纏めています。
表現に不備が多いかと思いますが，初心者なのでそこは見逃してください。。。
勉強元①→[MATLABおよびSimulinkトレーニング(DeepLearning入門編)](https://matlabacademy.mathworks.com/jp)


#学習用/テスト用データストアの作成

##**imageDatastore** : matlab用のデータストアを作成する

```matlab
%フォルダ内のfilexx.jpgを全てデータストアに格納 '*'はワイルドカード
imds = imageDatastore('file*.jpg') 
```

```matlab
%'Flowers'内の全てのサブフォルダ内の画像をデータストアに格納
flwrds = imageDatastore('Flowers','IncludeSubfolders',true) 
```

```matlab
%'Flowers'内のサブフォルダ名をラベルにしてデータストアを生成する
flwrds = imageDatastore('Flowers','IncludeSubfolders',true,'LabelSource','foldernames');
%ラベルの表示
flwrds.Labels % カテゴリカル配列として出力される
```

##**readimage** : データストア内の任意の画像を抽出する

```matlab
I = readimage(ds,n) %データストアdsに格納しているn番目の画像配列を抽出する
```
##**montage** : データストア内の画像を全て表示する

```matlab
imds = imageDatastore('file*.jpg')
montage(imds)
```
結果
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/610270/636a3338-d303-7b92-5cb1-a650adcf1de4.png)

##**splitEachLabel** : 既存のデータストアをTrain用とTest用に仕分けする
imds : ラベル付けされた画像データストア
p : traindataの割合(0~1の範囲)　残りはtestdataに割り当てられる
n : traindataに含まれる各ラベルのデータ数 (1以上)

```matlab
%各Labelの画像を一定の割合で順番通りに割り振りする場合
[traindata,testdata] = splitEachLabel(imds,p) 

%各Labelの画像を一定の割合で%ランダムに割り振りする場合
[traindata,testdata] = splitEachLabel(imds,p,'randomized')

%各Labelの画像を一定のデータ数で順番通りに割り振りする場合
[traindata,testdata] = splitEachLabel(imds,n) 
```



#画像の前処理
##**imresize** : 画像を任意のサイズに変更する
※この処理でCNNにInputする画像のサイズを整える

```matlab
%img: 1096x822x3の画像
img = imresize(img,[227 227]); %227(行)x227(列)に縦横リサイズされる.(RGBの3次元は省略可)
```
##**augmentedImageDatastore** : フォルダ内(データストア内)の画像を纏めて画像編集する

※例:画像サイズを変更する場合)
サイズ変更後の新しい画像は元フォルダ内の画像を基に生成されるが，生成された画像はPCに保存せず容量を圧迫しない為，大量なデータの前処理に有効。

```matlab
auds = augmentedImageDatastore([227 227],imds) %imdsはデータストア
net = alexnet
pred = classify(net,auds) %Alexnetでのクラス分類にも画像サイズ変更後のデータストアを使用可能
```
```matlab
%%画像サイズを変更&グレースケールからカラーに変更する場合
auds = augmentedImageDatastore([227 227],imds,'ColorPreprocessing','gray2rgb')
```

#転移学習用の処理
##①全結合層の出力ラベル数を調整する
```matlab
%使用する学習済みCNNを決める
anet = alexnet;
layers = anet.Layers

%n個の出力に対応した全結合層をfclayerに格納
fclayer = fullyConnectedLayer(n)

%Alexnetの最後の全結合層(layersに格納された23番目の層)を変更する
mylayers(23) = fclayer 
```
##②その他の層を調整する
①で全結合層のみラベル数を合わせたが，最終出力層は既存の学習モデルに合わせたパラメータのまま。
このまま使用するとエラーが生じる為，転移学習するラベル数に合わせて出力層も調整する。

```matlab
cl = classificationLayer('Name','RevisedOutput') %引数はなくてもOK。この場合は出力層の名前を付けている
layers(end) = cl
```

#学習開始準備
##trainingOptions : 学習オプションを設定する
学習用のオプションを設定します。詳細は[公式リファレンス](https://jp.mathworks.com/help/deeplearning/ref/trainingoptions.html;jsessionid=81c0552d987e0445805045aa6856)へ

```matlab
%学習アルゴリズム “モーメンタム項付き確率的勾配降下法” の既定のオプションを格納する
opts = trainingOptions('sgdm')
```
多くの場合、最初は、ほとんどのオプションを既定値のままにして学習を試す。
しかし、転移学習を実行する場合は、InitialLearnRate を既定の 0.01 よりも小さい値に設定して開始するのが一般的です。

学習率は、アルゴリズムでネットワークの重みを変えるときの振り幅を制御します。転移学習の目標は、既存のネットワークを微調整することです。そのため、通常、ゼロから学習をさせる場合よりも重みを変えるときの振り幅を小さくする必要があります。

```matlab
%既定の学習率'InitialLearnRate'の値を変更する
opts = trainingOptions('sgdm','InitialLearnRate',0.001)
```
**GPUの準備**
 GPU と Parallel Computing Toolbox を事前にインストールする


#学習開始
**エポックとミニバッチ**
全ての学習用データA個のうち，ミニバッチをB個とすると1イテレーションで1ミニバッチを学習する。
全ての学習用データを学習したら1エポックとなる。

##trainNetwork : 学習を開始する

```matlab
%学習には1:データストア,2:使用するネットワーク, 3:学習オプションを引数として入力する。
[flowernet,info] = trainNetwork(traindata, layers, opts); %flowernetは吐き出したCNNネットワーク, infoは学習情報
```

#学習結果の評価
##**info.TrainingLoss** : 学習損失を表示

```matlab
%学習損失をプロット表示する
plot(info.TrainingLoss)
```

##学習結果CNNを用いて画像分類→実際のラベルと比較して正答率を算出
```matlab
flwrPreds = classify(flowernet,testImags) %学習結果CNNを用いてテストデータを分類
numCorrect = nnz(flwrPreds == flwrActual) %nnz関数を用いて正当数をカウント
fracCorrect = numCorrect/numel(flwrPreds) %正答率算出

```
※nnz(X) 非ゼロ要素の数を返す

##不正解の分布を調べる

```matlab
confusionchart(testImgs.Labels,flwrPreds)
```
結果
対角要素が正解となる
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/610270/ed03bd2a-cd29-c788-f341-6c1afe1ee12e.png)