PyTorch で Hyperdash を使ってみる 

# Hyperdash 
Deep Learning をはじめとする機械学習のモデル作成の際，training に結構時間が掛かることがあって，training 中は上手くいくことを祈りながら，別のことをやっていることが多いかと思います．その際に，途中結果が気になるけどサーバにログインして確認するのが面倒くさかったり，できる状態じゃないことがあるときに，スマートフォンや Web で途中結果をモニタリングできるのが，[Hyperdash](https://hyperdash.io/) です．Web で紹介されている通り，scikit-learn や Deeeeeeeep Learning 系のフレームワークで利用できますし，フレームワークに依存する部分はないので，モデル作成以外でも何かの処理の途中結果の確認に利用することができます．
Keras, Chainer で Hyperdash を利用する際は下記の記事が丁寧に説明されています．

[Kerasの学習過程をスマホで見る][*1]
[*1]:https://qiita.com/yakigac/items/f8158b9f65a479e55ed8
[スマホアプリで学習状況を監視するHyperdash入門][*2]
[*2]:http://www.kumilog.net/entry/hyperdash

ここでは，PyTorch での利用例を紹介します．

# PyTorch を利用する環境
nvidia-docker を利用して，PyTorch の実行環境を作ります．

```
git clone https://github.com/pytorch/pytorch
```
として，pytorch 下にある Dockerfile をビルドすれば PyTorch の実行環境を作成することが可能です．その際，Hyperdash を利用するので Hyperdash をインストールする必要があります．

# Hyperdash のインストール
上記の記事などで紹介されている通り

```
pip install hyperdash 
```
でインストールできるので，上記の Dockerfile に

```Dockerfile
RUN pip install hyperdash
```
を追記します．

# Hyperdash の API Key の利用
ユーザ登録は，email か github アカウントで行うことができます．

```
hyperdash signup --email
hyperdash signup --github
```

Docker 環境で利用するので API Key を用いて認証を実施する方法について説明します．
ユーザ登録を行うと，ホームディレクトリ下に .hyperdash とディレクトリができていて，その中に hyperdash.json というファイルがあり，この json ファイルの中に API Key の情報が入っています．
この API Key の情報を Docker コンテナ内で利用できるようにすればよいのですが，Dockerfile 内に，

```
ENV HYPERDASH_API_KEY=xxxxxxxx
```
と書くと key の情報が丸見えでカッコ悪いので，ホストの環境変数として key を登録して，Docker の実行時にこの環境変数をコンテナ内で参照できるようにします．
ホストが Ubuntu の場合だと .bashrc に，

```
HYPERDASH_API_KEY=xxxxxxxx
```

と追記して，nvidia-docker run 時に，-e オプションを利用して指定の環境変数を渡します．

```
-e HYPERDASH_API_KEY=$HYPERDASH_API_KEY
```

# ログの表示
ログを表示させるためのサンプルプログラムの例（一部）を示します．
前述の記事で紹介されている通り，Keras は，callback を定義，Chainer は，Trainer の Extension を自作するなどすれば良いかと思います．Pytorch には，Chainer の Trainer のような，Training 処理を抽象化してくれるようなものがないので，自分で学習処理のループを書いて，ループ中に直接モニタリングしたい文字列を渡しています．

```train.py
from hyperdash import Experiment

def get_api_key_from_env():
    key_str = os.environ.get('HYPERDASH_API_KEY')
    return key_str


"""
前処理やら諸々を書く．
"""

"""
学習処理のループ
"""
    exp = Experiment("TEST", api_key_getter=get_api_key_from_env)
    for epoch in tqdm(range(args.training_epoch)):

        training_result = training(train_loader, model, criterion,
                                             optimizer
                                             )
        val_result = validate(val_loader, model, criterion)

        result_str = 'epoch : {} / {}\
        main/loss : {:.3f}\
        main/acc : {:.3f}\
        val/loss : {:.3f}\
        val/acc : {:.3f}'.format(
            epoch,
            args.training_epoch,
            training_result['loss'],
            training_result['acc'],
            val_result['loss'],
            val_result['acc']
        )
        logger.info(result_str)
        exp.log(result_str)

        prec1 = val_result['acc']

        # remember best prec@1 and save checkpoint
        is_best = prec1 > best_prec
        best_prec = max(prec1, best_prec)
        if is_best:
            save_checkpoint(state={
                'epoch': epoch + 1,
                'state_dict': model.state_dict(),
                'best_prec': best_prec,
                'optimizer': optimizer.state_dict(),
            }, is_best=is_best, result_dir=result_dir)

        exp.metric('main/loss', training_result['loss'])
        exp.metric('val/loss', val_result['loss'])

    logger.info('> end training')
    exp.end()
```

上記のプログラムでは，epoch 数，training data の loss, accuracy, validation data のloss, accuracy を hyperdash でモニタリングしたいので，

```.py
exp.log("モニタリングしたい文字列")
```
として，モニタリングできるようにしています．print 文で標準出力するようにしても，モニタリングできます．また，`exp.metric()` で，グラフ表示する項目を設定することができます．詳細は，前述の記事で紹介されていますのでそちらをご参照下さい． 
また，API Key の情報を取得する関数 `get_api_key_from_env` を用意し，`Experiment(api_key_getter=get_api_key_from_env)` として，docker run 時に渡した API Key の情報を取得しています．

# やってみた
実行中
![training.jpg](https://qiita-image-store.s3.amazonaws.com/0/61425/594fbd0c-14f5-5d7f-dcd0-0640b379d42b.jpeg)

モニタリングしたいログ
![log.jpg](https://qiita-image-store.s3.amazonaws.com/0/61425/9ddb109e-9e80-e014-ac52-1d014e6f08c9.jpeg)

学習が終わったことの通知
![finish.jpg](https://qiita-image-store.s3.amazonaws.com/0/61425/51ed4809-c180-509a-4534-ae35bb24854b.jpeg)
異常終了した場合も教えてくれます．

loss のグラフ
![graph.jpg](https://qiita-image-store.s3.amazonaws.com/0/61425/fcb38ad2-8ced-7f21-4846-ce071f7f7178.jpeg)

グラフにしたい項目は自由に設定できますが，縦軸のスケールが合うような項目にしておかないと何のグラフかよくわからないことになると思います．

これで Web につながる状況であれば電車の中でも簡単にモニタリングできます．