CNTKによる画像認識のサンプルをAzure DSVM上で動かしてみる(その2)

# はじめに
今回は、[前回](https://qiita.com/masa_sato/items/5936660931d44f661136)使った冷蔵庫画像のFast R-CNNサンプルプログラムについて、(CNTK設定情報が記載されている)BrainScriptの中身を見てみます。
また、BrainScript内の情報を変更し、CNTKをCPUとGPUで利用した場合の処理速度を比較してみます。

# 今回の概要
1. BrainScriptの設定情報を読んでみる。
2. BrainScriptでGPU/CPUの設定を変更し、処理時間を比較してみる。

## BrainScriptとは
BrainScriptは、CNTK実行のための設定・構成情報が記載されたファイルです。
前回のサンプルではpythonプログラム(A2_RunWithBSModel.py)内から呼び出されていましたが、単独で利用する場合は、`cntk configFile = xxxxxx.cntk`といったコマンドで実行されます。
(参考)：https://docs.microsoft.com/en-us/cognitive-toolkit/brainscript-config-file-overview

# 1.BrainScriptの設定情報を読んでみる


[前回](https://qiita.com/masa_sato/items/5936660931d44f661136)のサンプルプログラムに含まれている、fastrcnn.cntkをエディタ等で開き、内容を確認してみます。
前半部分には、CNTKを呼び出す際の各種設定が、後半部分には学習・適用の処理内容が記載されています。

[前半部分]
前半部分は、処理内容の指定やCPU/GPUの利用選択、ディレクトリの指定やROIの設定等が記載されています。
設定できる主なパラメータは下記の通りです。

| パラメータ |  概要  | 
| ---- | :--- | 
| deviceId   |  CPU/GPUの利用対象を指定できます。<br>"auto" : 利用可能なGPUのうち、その時点で負荷が少なく最速のものを選択します。利用可能なGPUが無い場合はCPUを利用します。<br>"cpu"もしくは -1 ：全ての計算にCPUを利用します。<br>0 : GPUを利用します。複数ある場合は最初のものを使用します。<br>任意の正の整数:その値で識別されるGPUを利用して計算を実行します。| 
|  precision | 浮動小数点精度(float[32ビット]もしくはdouble[64ビット])を選択します。 <br>GPU利用時はおおよそ"float"が推奨されるようです。|
|  traceLevel |  trace情報の出力量の選択 |
|  stderr   |  CNTKの実行ログをファイルに出力します。<br>(通常は標準エラー出力としてコンソール画面に表示されます。) |

参考：https://docs.microsoft.com/en-us/cognitive-toolkit/BrainScript-Top-level-configurations

```
#makeMode = false
command = Train:WriteTest:WriteTrain
deviceId = "Auto"
precision = "float"
parallelTrain = "false"
traceLevel = 1

rootDir = "." 
dataDir = "$rootDir$/data/"
outputDir = "$rootDir$/Output"

modelPath = "$outputDir$/Fast-RCNN.model"
#stderr = "$outputDir$/Fast-RCNN.log"

(中略)

TrainROIDim = 800               # $NumTrainROIs$ * 4 
TrainROILabelDim = 4400         # $NumTrainROIs$ * $NumLabels$
TestROIDim = 4000               # $NumTestROIs$ * 4
TestROILabelDim = 22000         # $NumTestROIs$ * $NumLabels$

```

[後半部分]
後半部分は、学習・適用の実際の処理内容が記載されています。
(今回は詳しく触れません。)

```
Train = {
    action = "train"
    
    BrainScriptNetworkBuilder = {
        network     = BS.Network.Load ("../../../../../PretrainedModels/AlexNet.model")
        convLayers  = BS.Network.CloneFunction(network.features, network.conv5_y, parameters = "constant")
        fcLayers    = BS.Network.CloneFunction(network.pool3, network.h2_d)

        model (features, rois) = {
    ・・・(中略)
        }.z


}

# Write network output for entire test data set
WriteTest = {
    ・・・(中略)
}

# Write network output for entire train data set
WriteTrain = {
    ・・・(中略)
    }
}

WriteTestModify = {
    ・・・(中略)
}

```


# 2.CPU/GPUの切り替えを試してみる
今回は、BrainScript内に記載された設定を変更し、CPU利用とGPU利用での処理速度の差をみてみます。
(今回は、Azure VMのNC6 [6vCPU, 56GiB memory, GPU:K80 × 1]インスタンスを利用しています。)

[設定箇所]
上記fastrcnn.cntk内の`deviceId = "Auto"`の箇所で、GPU利用の有無を設定しています。

・`deviceId = -1` もしくは`deviceId = "CPU"`の場合 ：　CPUのみ利用
・`deviceId = "Auto"` の場合 ： GPUが利用可能であればGPUを利用して処理を実行(利用するGPUは利用状況に応じて自動選択。GPUが利用できない、もしくはGPUが無い環境の場合はCPUを利用。)

それぞれについて、前回プログラムの学習部分(`A2_RunWithBSModel.py`)を3回ずつ実行してみました。

|    |  平均所要時間  | 
| ---- | ---: | 
|  CPU  |  394秒  | 
|  GPU  |  151秒 |  
※CPU利用は`deviceId = -1`、GPU利用は`deviceId = "Auto"`で設定。

各回±10秒前後のブレはありますが、平均するとざっくり2.5倍以上の速度差が出ました。





# 次回
次回は、上記環境とサンプルプログラムを元に、自前の画像データで画像認識を試してみます。