こんにちは,DSOC 研究開発部 インターン生の内田です.先日プチ卒業旅行として伊豆の温泉旅館に行ってきました.伊豆といえば バナナワニ園 ですよね,異論は認めません.バナナワニ園のワニたちは基本的に動かないので思わず「休日の俺じゃん」って呟いてしまいました.
さて,今回はCVとは直接関係ないですが,多くの人が頭を悩ませている実験管理に関する話題です.
機械学習と実験管理
機械学習,特に深層学習を用いたプロジェクトにおいては,精度を引き出すためにハイパーパラメータが非常に重要です.一口にハイパーパラメータといっても,モデルサイズや学習率,バッチサイズなど挙げるとキリがありません.
最適なハイパーパラメータを定めるには,Grid Searchなりでパラメータを探索し,精度などと共にロギングする必要があります.バナナワニ園のワニのように怠惰な私にとって,パラメータや結果をマメに記録しておくことは簡単なことではありません.現状では表示可能な項目はなるべくTensorBoardに集約して,TensorBoardのログディレクトリにその他の結果を全部吐かせるようにしています.これなら後からでも漏れなく参照できるので安心ですが,TensorBoardに表示できない項目の検索・比較は面倒です.
上記の背景から,もう少し高機能な実験管理ツールを使ってみたい気持ちが常々あります.ただし,導入にあたってはいくつか条件があります.パッと思い当たるのは次のような感じです.
移行コストが低いこと
ロガーに値を手動で報告する場合,ツールを変えれば当然プログラムの書き換えが生じます.一気に書き換えるのも手ですが,バックアップとしてローカルのログも残しておきたかったりもするので,ロガーの命令をキャッチしてよしなにやってくれると嬉しいです.モデル管理機能
学習済みモデルと実験を紐づけてUI上で管理できると嬉しいです.社内サーバでのホスティング
最近 Comet.ml や Neptune.ai のようなクラウド上で実験管理を行えるSaaSが出てきていているのですが,業務で扱うデータの性質上,外部のサーバにデータを送信するのはご法度です.とはいえ個々人のインスタンスに閉じているのもスケールしなさそうなので,社内サーバにデプロイして共有できる程度が望ましいです.
Trains
上記の条件に概ね合致しているツールとしてTrainsがあります.Trainsは,Allegro AI社が提供する実験管理ツールであり,OSSとしてGitHubに公開されています.
Trainsそのものはコード内から結果・モデルを報告するPythonパッケージであって,pip install trains
でインストールできます.学習曲線やハイパーパラメータはもちろんのこと,モデルのスナップショットやコミットIDなども自動でロギングしてくれます.2行プログラムを追加するだけでTensorBoardの命令をキャッチして自動でロギングしてくれるので,移行コストが非常に低いのも特徴です.
また,Trainsから報告された結果は,実験管理UIを提供するTrains Server上でホスティングされます.社内サーバにTrains Serverをデプロイしておけば,複数プロジェクトを1つのUI上で管理することが可能になります.
半年くらい前にTwitter上でちょっと話題になっていて気になってはいたのですが,あまり使うタイミングがないままだったので,今回はドキュメントを読みながらTrains Serverの導入からTrainsの使い方についてまとめたいと思います.
実行環境
本エントリでは以下の環境を想定しています.
- OS: Ubuntu 16.04 LTS
- Docker: 19.03.0
- Docker Compose: 1.24.1
- Python: 3.7.4
- Trains / Trains Server: 0.14
Trains Serverの導入
Trains Serverはビルド済みイメージが配布されているため簡単に導入できます.以下ではDockerを利用しますが,他にもEC2 AMIが利用できたり,k8sクラスタ上にも導入できます.Trains Serverのシステム概略図は次のようになります.直近のリリースではこれに加えてredisのコンテナも動いているようで,日々改善されている感があります.
導入手順は以下です.
TRAINS ServerではElasticSearchを利用するため,メモリマップ数の上限を引き上げます.
echo "vm.max_map_count=262144" > /tmp/99-trains.conf
sudo mv /tmp/99-trains.conf /etc/sysctl.d/99-trains.conf
sudo sysctl -w vm.max_map_count=262144
sudo service docker restartデータベース・ストレージ用のディレクトリを作成します.
sudo mkdir -p /opt/trains/data/elastic
sudo mkdir -p /opt/trains/data/mongo/db
sudo mkdir -p /opt/trains/data/mongo/configdb
sudo mkdir -p /opt/trains/data/redis
sudo mkdir -p /opt/trains/logs
sudo mkdir -p /opt/trains/config
sudo mkdir -p /opt/trains/data/fileserver作成したディレクトリ群へのアクセス権をDockerに付与します.
sudo chown -R 1000:1000 /opt/trains
GitHubから
docker-compose.yml
をダウンロードします.cd /opt/trains
curl https://raw.githubusercontent.com/allegroai/trains-server/0.14.0/docker-compose.yml -o docker-compose.ymlDocker Compose でサーバを起動します.
sudo docker-compose -f docker-compose.yml up
以上でTrains Serverのデプロイは完了で,下記のポートが利用可能となります.
8080
: Webサーバ8008
: APIサーバ8081
: ファイルサーバ
localhost:8080 にアクセスし,次のようなダッシュボードが表示されれば成功です.
Trains Serverへの送信設定
PythonコードからTrains Serverへデータを送信するには,認証情報の登録を行う必要があります *2.
ダッシュボード左下のメニューからPROFILEを選択し,Create new credentials
をクリックすると次のような画面になります.
アクセスキーとシークレットキーが生成されているので,Copy to clipboard
をクリックして認証情報を取得します.コンソールからtrains-init
コマンドを実行すると認証情報を聞かれるので,クリップボードの情報を貼り付けて設定完了です.設定項目は~/trains.conf
に保存されているので,二回目以降は~/trains.conf
を直に編集すれば設定を変更できます.
Trainsによる実験管理
以下では,PyTorch Lightningを用いてニューラルネットワークを学習し,Trainsによって実験管理を行います.PyTorch LightningはデフォルトでTensorBoardによるロギングを行うため,最小限のコード追加でTrainsによる自動ロギングが可能です.
実験では次のコードを用います.
import argparse import os import pytorch_lightning as pl from models import CoolModel # Trains関係の追加部分は次の2行のみ import trains task = trains.Task.init(project_name="trains-demo", task_name="mnist") def app(): parser = argparse.ArgumentParser() parser.add_argument('--n_filters', type=int, required=True) args = parser.parse_args() trainer = pl.Trainer(max_epochs=10) model = CoolModel(args) trainer.fit(model) if __name__ == "__main__": app()
CoolModel
は3層ニューラルネットワークによりMNISTを学習するモデルクラスであり,コマンドラインから隠れ層のフィルタ数をハイパーパラメータとして受け取ります.Trainsに関連する部分はコメント以下2行のみです.上記のコードを5種類のフィルタ数に対して実行すると,ダッシュボードは次のように変化します.trains.Task.init()
で指定したように,trains-demo
というプロジェクトが出現し,プロジェクト下にmnist
という実験が5つ生成されているのが確認できます.
各実験の詳細は,プロジェクトに入りポチポチすることで確認できます.各実験はユニークなIDで管理されており,IDボタンをクリックすると取得できます.
各タブには次のような項目が記録されています.
大項目 | 小項目 | 内容 |
---|---|---|
EXECUTION | - | コミットID,依存パッケージ等の再現性に関する情報 |
HYPER PARAMETERS | - | ハイパーパラメータ |
ARTIFACTS | - | モデルファイルなどの入出力ファイル |
INFO | - | 実験時間等のメタデータ |
RESULTS | LOG | 標準入出力 |
RESULTS | SCALARS | 学習曲線やマシンリソースモニタリング |
RESULTS | PLOTS | MatplotlibやSeabornで作成した図 |
RESULTS | DEBUG IMAGES | 画像ロギング |
また,各実験のチェックボックスを複数選択することで,実験間でハイパーパラメータや学習曲線を比較できます.ベースの実験との差分をハイライトしてくれるため,比較が容易です.
Trainsによるモデル管理
Trainsはモデル管理機能も提供しています.実験管理と同様に,モデルファイルの保存を自動的にキャッチして記録を取ってくれます.例えば次のコード*3を実行すると,プロジェクトのモデルタブに出力モデルが記録されます.
ここで Task.init(..., output_uri="s3://<BUCKET>")
みたいに指定しておくと,クラウドストレージにモデルを転送することもできます *4.
import torch from torchvision.models import alexnet from trains import Task task = Task.init(project_name='trains-demo', task_name='model_saving') model = alexnet() torch.save(model.state_dict(), 'model.pth')
モデル管理画面は次のようになります.実験とモデルの紐付けはCREATING EXPERIMENTから確認できます.
実験と同様,モデルはユニークIDで管理されるため,IDボタンをクリックしてモデルIDを取得できます. モデルIDから保存先のパスを取得するには,次のように記述します. 保存先がクラウドストレージである場合,バケットからモデルファイルがtempディレクトリにダウンロードされ,ダウンロード先のパスが返ってきます.
from trains import InputModel model_path = InputModel('model_id').get_weights()
ファイルの保存先にかかわらずモデルIDのみで読み出せるので,コードの簡素化も期待できますね.
まとめ
実験管理ツール Trains を紹介し,実験管理からモデル管理までの流れを実際に試してみました. UIが非常に良くできていますし,自動ロギングやクラウドストレージとの連携がスムーズだったので実用性があると感じました. 特に,今までテストの際にモデルファイルのパスを手打ちしていたことを考えると,モデルIDをUIから取得すればいいのはとても嬉しく感じました.
また今回紹介できませんでしたが,「既存の実験をクローン→ハイパーパラメータを修正→再実行」というフローを実現するTrains Agentというツールも存在します. 発展著しいツールですので,普及に期待したいと思います.
▼本連載のほかの記事
buildersbox.corp-sansan.com
*1:https://allegro.ai/docs/concepts_arch/concepts_arch/ より引用
*2:ここで設定を行わない場合,データはデモサーバに送られ,誰でも見れる状態に置かれます.
*3:Lightningのモデル保存方法が特殊でうまくキャッチしてくれなかったため変更しています.
*4:アクセスキーを trains.conf に設定しておく必要があります.