ABEJA Platformで新しいローカル学習(train-local)を試してみる

## 概要
#### 今回はABEJA Platformで新しくなったローカル学習 (train-local) を紹介します。

## ABEJA Platformのローカル学習のメリットって？
ABEJA Platformは、機械学習における作業パイプラインをサポートしているサービスです。例えば、開発をABEJA Platform のJupyter Notebook・学習・デプロイをABEJA Platform上で行うことも可能です。今回は、すでに機械学習環境(GPUマシンなど)を保有しているユーザが、既存のオンプレミス環境を活用し、効率よくパイプラインを実施するための利用方法を紹介します。

- メリット
    - 既存のリソース(GPUマシンなど)を有効活用できる
    - ローカル環境での学習だと、トライアンドエラーが効率よく実施できる
    - 学習履歴やログ・モデルなどの管理・API提供などはABEJA Platformで実施可能

#### 公式ドキュメント
[ABEJA Platform ローカル学習](https://developers.abeja.io/function/training/train-local/)

![01-train-local_ja.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/14014/b5b632d1-aa14-b985-418f-662d8a210e07.png)


## 新しいローカル学習でできるようになったこと

- チームでの学習状況の確認や、モデルのやり取りがしやすくなりました
    - ローカルでの学習の進捗がコンソールで確認可能に
    - ローカル学習のログがコンソールで確認可能に
    - 学習結果が ABEJA Platform 上に保存されるため、簡単にmodel 提供も可能に


## 実施すること
サンプルコード (KerasでVGG16を利用した画像分類判別) を利用し、モデル作成をローカルで実施していきましょう。

## 早速やってみる
### 前準備
ローカル学習(train-local)では、ABEJA Platform CLIを利用します。
ABEJA Platform CLIの導入については、こちらをご参考ください。

- [ABEJA Platform CLI](https://developers.abeja.io/cli/overview/)

##### ※注意
* ABEJA Platform CLIはPython3.5以降が対応しています。
* Windowsには一部対応しているのですが、動作保証対象外となっていますので、ご注意ください。
* ローカル学習にはDockerが必要になりますので、事前にDockerを起動しておきます。

## ローカル学習(train-local)の実施
### training.yamlの作成
ABEJA Platformのローカル学習では、まずは学習をするための設定ファイル「traning.yaml」を用意します。

以下のコマンドで「trainig.yaml」を作成します。

```bash
$ abeja training init trainig-local-demo #学習ジョブ名を入力
```

コマンドを実行後、ディレクトリ上に training.yaml が作成されます。training.yamlの記載方法は[こちら](https://developers.abeja.io/function/training/training-yaml/)を参考に設定します。

```yaml
name: train-local-demo # 学習ジョブ名
handler: train:handler # 学習コードのHandler指定
image: abeja-inc/all-cpu:18.10 # 学習イメージ指定
params: # 環境変数
  NUM_EPOCHS: '5'
```
### 学習ジョブ定義バージョンの作成
学習ジョブのバージョンを以下のコマンドで指定します。 ( `training.yaml` が必須です)

```bash
$ abeja training create-version
```
実行後、以下のような出力が出れば、バージョンの作成が完了です。

```
{
    "archived": null,
    "created_at": "2019-07-19T14:49:40.609351Z",
    "datasets": {},
    "description": null,
    "handler": "train:handler",
    "image": "abeja-inc/all-cpu:18.10",
    "job_definition_id": "1234567890123",
    "job_definition_version": 1,
    "modified_at": "2019-07-19T14:49:40.712602Z",
    "user_parameters": {}
}
```

### ローカル学習 (train-local)の実行
ローカル学習実行までの準備が整いましたので、ついにローカル学習( train-local )を実行してみましょう。
コマンドのリファレンスは[こちら](https://developers.abeja.io/reference/cli/training-command/training-train-local/)
####コマンド例
```bash
$ abeja training train-local
```
##### ※コマンド実行するディレクトリにtraining.yamlが存在する場合、 training.yaml に定義されている値が優先されて使用されます。

### ■サンプル① (ABEJA Platform上のデータセットを利用する場合)
###### サンプル : 「環境変数(epochs)を5に指定、ABEJA Platformデータセット(dataset_1)を利用する場合)
```bash
$ abeja training train-local \
    --version 1 \
    --environment epochs:5 \
    --datasets dataset_1:1000000000
```

- `--organization_id` ：ABEJA Platform組織ID。組織IDの確認方法は[こちら](https://developers.abeja.io/cli/configuration-command/init/)
- `--version` ：学習ジョブ定義のバージョン
- `--enviroment`環境変数の指定 (ハイパーパラメータなどの設定などに使用)
- `--datasets` ：使用するデータセットを次のフォーマットにて指定。` {dataset_name}:{dataset_id}`
( 例えば、ABEJA Platform上にあるデータセット `demo-dataset` (データセット名：demo-dataset、データセットID：1000000000) を上記のmain.pyを使って呼び出す場合、データセット名`dataset_name`、データセットID `1000000000`を指定

### ■サンプル② (ローカル上のデータセットを利用する場合)
###### サンプル : 「環境変数(epochs)を5に指定、ローカルデータセット (/同一フォルダ内/data) を利用する場合)
```bash
$ abeja training train-local \
    --version 1 \
    --environment epochs:5 \
    --volume `pwd`:/data
```

- `--version` ：学習ジョブ定義のバージョン
- `--enviroment`環境変数の指定 (ハイパーパラメータなどの設定などに使用)
- `--volume` ：ローカル内のデータセットが格納されているパスを指定

他に以下のようなオプションも選択可能です。

- `--runtime`：docker run コマンドの --runtime オプションに相当。例えば、「nvidia-docker」など。
- `--config` ：training.yaml以外の学習設定ファイルの指定。デフォルトはtrainig.yaml

### 実行
今回はタイトルの通りKerasでVGG16を利用し、画像分類判定を実施します。
サンプルコードは[こちら](https://github.com/abeja-inc/Platform_handson/tree/work/keras_vgg_sample/keras_vgg_sample)です。

ローカルで学習を実施したい端末にコードを配置します。
今回は`train.py`のhandlerを呼び出し、ローカルで学習させます。
すでにPlatform上で作成したデータセットも利用します。



コードを配置したフォルダ上で、以下のコマンドを実行します。

```bash
$ abeja training train-local \
   --version 1 \
   --environment epochs:5 \
   --datasets train:XXXXXXXXXXXXXX    # データセットIDを入力してください
```

すると、以下のような実行状況(infoログ)が出力されてきます。 ( `--quit`で出力を抑制することも可能です。)

```bash
[info] preparing ...
Pulling from abeja/all-cpu
Pulling fs layer
Extracting [=========================================>         ]  669.6MB/806.4MB
Extracting [=========================================>         ]  670.1MB/806.4MB
Extracting [=========================================>         ]  671.8MB/806.4MB
Extracting [=========================================>         ]  673.5MB/806.4MB
Extracting [=========================================>         ]  674.6MB/806.4MB
Pull complete
Digest: sha256:11e379115705056cd4b1d6f08ab7be96e7471ac5c00ba6119848b2c4bb7d05f8
Status: Downloaded newer image for abeja/all-cpu:18.10
[info] start training job
{"log_id": "2b224d22-2f3d-457e-ae0e-88db226e5ad2", "log_level": "INFO", "timestamp": "2019-07-19T15:46:03.500551+00:00", "source": "model:run.download_training_source_code.80", "requester_id": "-", "message": "downloading training source code", "exc_info": null}
{"log_id": "89456823-2f19-4655-8c9a-b84820592122", "log_level": "INFO", "timestamp": "2019-07-19T15:46:03.762592+00:00", "source": "model:run.download_training_source_code.89", "requester_id": "-", "message": "successfully downloaded training source code", "exc_info": null}
INFO: start installing packages from requirements.txt
```

学習が開始されたので、管理画面上にその状況が反映されているか見てみましょう。

ABEJA Platformの管理画面上のモデル定義より「ジョブ」を見てみると、`PENDING`の状態で学習ジョブが作成されていることがわかります。
<img width="1462" alt="2.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/14014/729018b5-4391-a15b-b4b6-a2b75dfb0dc6.png">

少し待つと、`RUNNNING`に変わり、学習が開始されました。管理画面上でも学習が実施されていることがわかります。
<img width="1466" alt="1.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/14014/6cc11427-4f3c-f8d1-e74d-8dc8ae8cf8b6.png">


例えば、この状態で学習の停止やエラーで学習が止まった場合もステータスが管理画面上でも見えるようになります。
<img width="1440" alt="3.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/14014/7472dcda-7ea3-1b46-00be-3468aa1ffe53.png">

少し待つと、ローカル側の学習が完了したので、管理画面上でも結果を確認してみましょう。

```bash
2816/2959 [===========================>..] - ETA: 5s - loss: 0.6505 - acc: 0.6257
2848/2959 [===========================>..] - ETA: 4s - loss: 0.6497 - acc: 0.6264
2880/2959 [============================>.] - ETA: 3s - loss: 0.6493 - acc: 0.6264
2912/2959 [============================>.] - ETA: 1s - loss: 0.6485 - acc: 0.6253
2944/2959 [============================>.] - ETA: 0s - loss: 0.6486 - acc: 0.6250
2959/2959 [==============================] - 141s 48ms/step - loss: 0.6496 - acc: 0.6249 - val_loss: 0.8135 - val_acc: 0.5067
Test loss: 0.8134503923973011
Test accuracy: 0.50669818783107
```

無事、 `SUCCESS`と表示されており、学習が完了していることがわかります。
<img width="1491" alt="4.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/14014/12e9f797-2d24-8a6f-fe76-579a1c56bcfc.png">
今回は、結果としてAccuracy(学習) 62.5%とAccuracy(バリデーション) 50.7%とあまり良くない結果でしたが、、このローカル学習を利用すれば、すぐに修正して学習を開始できるため、作業効率があがるのと、自動的に進捗と結果が管理画面でも参照できるので、よりチーム内の作業も効率化されるのではないかなと思います！

### モデルのダウンロード
今回の学習で生成されたモデルは学習を実行したローカル環境でも生成されているかと思いますが、ABEJA Platform上の管理画面からも参照可能です！そして、学習したモデルは管理画面上からダウンロードできるので、学習ジョブにおけるモデル管理も便利になりますね！モデルのダウンロードはこちらから実施できます。

<img width="1491" alt="5.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/14014/f09459c4-df6e-3ea7-3e33-183faa3b7233.png">

<img width="608" alt="6.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/14014/706cb7c8-1471-01dd-4a93-9c67a01eea23.png">

このモデルファイルを利用し、ABEJA Platform上でデプロイを実施することで、HTTPサービスや、トリガーに利用することも可能ですので、ぜひ、お試しください。

## まとめ

今回はローカル学習(train-local)を利用し、ローカル環境で学習・モデルファイルを作成、管理画面での確認までを実施してみました。オンプレミス環境などですでにあるマシンを有効活用するだけでなく、ABEJA Platformでは並行して学習管理することができるので、学習をより高速化して、再現性の担保やチーム内でのコラボレーションが捗りそうですね！この機能はぜひ、試してみてください！


## 最後に
ABEJA Platformは、トライアルも提供しています。気になられた方は、是非、お気軽にお問い合わせください！また、フォーラムもありますので、是非、ご活用ください。

**ABEJA Platformに関するお問い合わせ**
https://abejainc.com/platform/ja/contact/

**ABEJA Platform Forums**
https://forums.abeja.io/