スマホアプリで学習状況を監視するHyperdash入門

WebアプリやiOS/Androidアプリで機械学習の学習状況を見ることができるHyperdashの使い方をまとめてみます。

インストールとユーザ登録
はじめにインストールとユーザ登録を行います。
インストールは、pipで簡単に行えます。
$ pip install hyperdash
ユーザ登録は、メールアドレスでの登録とGithubアカウントでの認証の2種類があります。
$ hyperdash signup --email
$ hyperdash signup --github
Githubアカウントで認証の場合、ブラウザでGithubの認証ページが開かれるので、そこで承認します。
また、pipでインストールすると、hyperdashというコマンドの他にhdがエイリアスとしてインストールされています。
$ hd signup
iOS/Androidのアプリは以下のリンクよりインストールできます。
- iOS: Hyperdash - Machine Learning on the App Store
- Android: https://play.google.com/store/apps/details?id=com.hyperdash
Webアプリは以下のリンクより使うことができます。
- Web: Hyperdash
インストールしたら、登録したアカウントでログインします。iPhoneで使ってみます。

ログの表示
どんなコードでも実行できますが、KerasのExampleを使ってみます。
$ hd run -n "MNIST" python mnist_mlp.py
-nオプションはアプリ側で識別するための名前です。同じ名前にしておくとまとめられます(#1, #2, …といったサフィックスがつきます)
実行させると、アプリで状況を見ることができます。これだけだと、標準出力がLogsに表示されるだけで、MetricsやParametersにはなにも表示されませんが、既存のコードでもすぐに実行することができます。


パイプによる実行もできます。
$ python mnist_mlp.py | hd pipe -n "MNIST"
コードに少しの修正を加えることでも同じように実行できます。Experiment()の引数が、-nオプションと同じくアプリに表示させる名前になります。
from hyperdash import Experiment
exp = Experiment("MNIST")
# 学習コード
# ...
exp.end()
コードを修正した場合はの実行は、
$ python mnist_mlp.py
とするだけです。
また、途中終了や完了して終了すると通知がきます。

パラメータやスコアをトラッキング
パラメータやスコアを表示させるには、先程のコードを修正する方法に、さらに修正を加えます。
パラメータを表示させるには、exp.param()を使います。スコアの表示は、exp.metric()です。どちらも、(名前, 値)を引数とします。
# sample.py
from hyperdash import Experiment
import numpy as np
from time import sleep
exp = Experiment('SAMPLE')
n_iters = exp.param('n_iters', 100)
for _ in range(n_iters):
exp.metric('acc', np.random.rand())
sleep(1)
exp.end()
$ python sample.py


標準出力でも表示されます。
{ n_iters: 100 }
| acc: 0.305129 |
| acc: 0.693012 |
...
This run of SAMPLE ran for 0:01:40 and logs are available locally at: ~/.hyperdash/logs/sample/sample_2017-12-27t19-37-15-923598.log
また、paramはユニークである必要があり、更新ができません。なので、学習率のように途中で変化させる値を表示したい場合は、metricに設定するしかありませが、metricはグラフ表示で軸が一つなので、スケールの異なる複数のパラメータを表示させるのには向いていません。
それでは、いくつかのフレームワークで実際に使ってみたいと思います。
Chainer
Chainerの場合、TrainerのExtensionを自作することでLossの値などを取得できます。chainer.training.extension.Extensionを継承してクラスをつくります。PrintReportのコードを参考に実装しました。
from chainer.training import extension
from chainer.training.extensions import log_report as log_report_module
class Hyperdash(extension.Extension):
def __init__(self, entries, exp, log_report='LogReport'):
self._entries = entries
self._exp = exp
self._log_report = log_report
self._log_len = 0
def __call__(self, trainer):
log_report = self._log_report
if isinstance(log_report, str):
log_report = trainer.get_extension(log_report)
elif isinstance(log_report, log_report_module.LogReport):
log_report(trainer)
else:
raise TypeError('log report has a wrong type %s' %
type(log_report))
log = log_report.log
log_len = self._log_len
while len(log) > log_len:
for entrie in self._entries:
self._exp.metric(entrie, log[log_len][entrie])
log_len += 1
self._log_len = log_len
PrintReportを同じように使うことができます。
from hyperdash import Experiment
exp = Experiment('Chainer MNIST')
# モデル定義やTrainerの準備など
# ...
trainer.extend(Hyperdash(
['main/loss', 'validation/main/loss'], exp),
trigger=(1, 'epoch'))
trainer.run()
exp.end()
Keras
Kerasの場合は、Callbackを継承してクラスを作成します。以下の記事を参考にしました。
from keras.callbacks import Callback
class Hyperdash(Callback):
def __init__(self, entries, exp):
super(Hyperdash, self).__init__()
self.entries = entries
self.exp = exp
def on_epoch_end(self, epoch, logs=None):
for entrie in self.entries:
log = logs.get(entrie)
if log is not None:
self.exp.metric(entrie, log)
fit()の引数に作成したcallbackを指定します。
from hyperdash import Experiment
exp = Experiment('Keras MNIST')
# モデル定義やデータの準備など
# ...
hd_callback = Hyperdash(['val_acc', 'val_loss'], exp)
history = model.fit(x_train, y_train,
batch_size=batch_size,
epochs=epochs,
verbose=1,
validation_data=(x_test, y_test),
callbacks=[hd_callback])
exp.end()
XGBoost
XGBoostの場合は、callback関数を作成します。
def hyperdash(entries, exp):
def callback(env):
result_dict = {r[0]: r[1] for r in env.evaluation_result_list}
for entrie in entries:
exp.metric(entrie, result_dict[entrie])
return callback
from hyperdash import Experiment
import xgboost as xgb
exp = Experiment('XGBoost')
# データやパラメータの準備など
# ...
d_train = xgb.DMatrix(X_train, label=y_train)
d_valid = xgb.DMatrix(X_valid, label=y_valid)
watchlist = [(d_train, 'train'), (d_valid, 'valid')]
hd_callback = hyperdash(['train-rmse', 'valid-rmse'], exp)
xgb.train(params, d_train,
evals=watchlist,
callbacks=[hd_callback])
exp.end()
まとめ
Chainer/Keras/XGboostの学習状況をHyperdashを使って、スマホアプリでを見る方法について説明しました。今回、紹介しませんでしたが、Jupyterからも使えるそうです。
DeepLearningの学習は時間がかかることが多く、手軽にスマホやWebで見れるととても便利です。高度なことはできませんが、どのプラットフォームからでも使えるのも良い点です。