本記事のUnity ML-Agentsバージョンは0.4.0となります。
バージョン0.5.0がリリースされましたが、一部コマンドやディレクトリ構成に変更があったため、バージョン0.5.0の場合、動作しない可能性があります。
絶賛記事更新作業中です(2018/09/13)
概要
Unity ML-Agents(以下 ML-Agents)をクラウド上で動作させるのに適切な環境を探しています。
そのなかで、Google Cloud Machine Learning Engine(以下 Cloud ML)上で動作するものなのか、検証してみました。
ML-AgentsはTensorflowを利用した強化学習ができるライブラリです。
なので、Tensorflowなどの機械学習実行エンジンであるCloud MLで動かないわけがない。(はず)
Google Cloud Machine Learning Engineとは
Google Cloud Machine Learning Engine は”エンジン”であって開発環境ではない ~制約に気を付けよう~
https://www.gixo.jp/blog/10960/
ML Engine を一言で説明するなら「機械学習を実行するためのクラウドサービス」です。そのため、DataRobotなどの他のクラウドサービスのようにサービス上で開発は行えません。
Unity ML-Agents
Unity Machine Learning Agentsベータ版
https://unity3d.com/jp/machine-learning
Unity ML-Agentsは、新世代のロボット、ゲームをはじめさまざまな分野において、迅速かつ効率的に新しいAIアルゴリズムの開発を行い、テストする柔軟な方法を提供します。
手順
前提条件
Cloud MLやUnity、ML-Agentsの環境構築が済んでいる前提です。
まだ環境がないという方は下記をご参考ください。
MacでCloud Machine Learning Engineを利用してみる
https://qiita.com/kai_kou/items/0952c9b28efe19f2f680
Macでhomebrewを使ってUnityをインストールする(Unity Hub、日本語化対応)
https://qiita.com/kai_kou/items/445e614fb71f2204e033
MacでUnity ML-Agentsの環境を構築する
https://qiita.com/kai_kou/items/6478fa686ce1af5939d8
Unityでアプリをビルドする
ML-Agentsでは実際にUnityアプリを動作させつつ強化学習がすすみます。
MacであればMac用、WindowsであればWindows用にアプリをビルドするわけですが、今回はCloud ML上で動作させる必要があるので、Linux用のビルドとなります。
アプリはML-Agentsに含まれる[3DBall]アプリを利用します。
手順は下記記事のDockerに関する手順以外をすすめてビルドします。
MacでUnity ML-AgentsをDockerで動作させる
https://qiita.com/kai_kou/items/df3f3518a5a27b66f617
unity-volume
フォルダに以下ファイルとフォルダが用意できたと思います。
> ll ml-agents/unity-volume/
3DBall.x86_64
3DBall_Data
Cloud ML上で実行するための準備
Cloud MLで実行するための下準備です。
変数設定
Cloud Storageのバケット名やCloud MLを利用するリージョンなどを変数に設定します。
BUCKET_NAME
とJOB_NAME
は任意で指定してください。
> set -x BUCKET_NAME 任意のバケット名
> set -x REGION us-central1
> set -x JOB_NAME gcp_ml_cloud_run_01
> export BUCKET_NAME=任意のバケット名
> export REGION=us-central1
> export JOB_NAME=gcp_ml_cloud_run_01
ハイパーパラメータの指定
今回は動作確認が目的となりますので、学習のステップを少なくします。
ML-Agentsライブラリにtrainer_config.yaml
というハイパーパラメータを指定するYAMLがあるので、そちらでmax_steps
の指定をして5,000ステップ実行して終了するようにします。
> cd 任意のディレクトリ/ml-agents
> vi python/trainer_config.yaml
Ball3DBrain:
normalize: true
batch_size: 64
buffer_size: 12000
summary_freq: 1000
time_horizon: 1000
lambd: 0.99
gamma: 0.995
beta: 0.001
+ max_steps: 5000
アプリとハイパーパラメータファイルのアップロード
Cloud MLでは学習に利用するファイルなどをCloud Storageに置いて利用することになります。
今回はUnityアプリのファイル・フォルダとハイパーパラメータ設定ファイルをCloud Storageにコピーしておきます。
また、Linux用ビルドはDataフォルダがないとアプリが起動しません。
フォルダのままだと取り回しが面倒なので、ZIPファイルに圧縮しておきます。
> cd 任意のディレクトリ/ml-agents
# Dataフォルダの圧縮
> zip -r 3DBall_Data.zip unity-volume/3DBall_Data/
# Cloud Storageのバケットにコピー
# Unityアプリファイル
> gsutil cp unity-volume/3DBall.x86_64 gs://$BUCKET_NAME/data/3DBall.x86_64
> gsutil cp unity-volume/3DBall_Data.zip gs://$BUCKET_NAME/data/3DBall_Data.zip
# ハイパーパラメータ設定ファイル
> gsutil cp python/trainer_config.yaml gs://$BUCKET_NAME/data/trainer_config.yaml
学習実行ファイルの準備
ML-Agentsに含まれているpython/learn.py
が学習を開始するためのファイルになりますが、これをCloud MLで動作できるように以下の準備をします。
- Pythonのパッケージ化
- Cloud Storage連携実装追加
Pythonのパッケージ化
Cloud MLにPythonでパッケージ化されたファイルをアップして実行するので、その準備をします。
# Pythonフォルダのsetup.pyがCloud MLで動作するようにファイルを追加
> touch python/MANIFEST.in
> vi python/MANIFEST.in
+include requirements.txt
# learn.py実行用のパッケージ作成
> mkdir python/tasks
> touch python/tasks/__init__.py
> cp python/learn.py python/tasks/learn.py
learn.pyのカスタマイズ
learn.py
にCloud Storageからファイルを取得、学習結果をCloud Storageへ保存する実装を追加します。
今回、ファイル名を固定していますが、とりあえず動作検証のためなので、あしからず。
Cloud Storageからのファイル取得・アップにgsutil
コマンドを利用していますが、ここはPythonで実装してもOKです。
手抜きできるところは徹底的に^^
> vi python/tasks/learn.py
# import追加
import shlex
import subprocess
import zipfile
# import追加ここまで
(略)
# General parameters
(略)
fast_simulation = not bool(options['--slow'])
no_graphics = options['--no-graphics']
# ここから追加
# Stackdriver Loggingでログ確認できるようにする
logging.basicConfig(level=logging.INFO)
# Cloud Storageのパス指定
trainer_config_file = 'gs://任意のバケット名/data/trainer_config.yaml'
app_file = 'gs://任意のバケット名/data/3DBall.x86_64'
app_data_file = 'gs://任意のバケット名/data/3DBall_Data.zip'
# 実行環境のに保存する際のパスを指定
file_name = env_path.strip().replace('.x86_64', '')
cwd = os.getcwd() + '/'
app_data_local_dir = os.path.join(cwd, file_name + '_Data')
app_local_file = os.path.join(cwd, file_name + '.x86_64')
app_data_local_file = app_data_local_dir + '.zip'
# Cloud Storageからコピー、Cloud ML環境だとgsutilが利用できて楽
logger.info(subprocess.call(['gsutil', 'cp', trainer_config_file, cwd]))
logger.info(subprocess.call(['gsutil', 'cp', app_file, cwd]))
logger.info(subprocess.call(['gsutil', 'cp', app_data_file, cwd]))
# Unityアプリ動作用にDataファイルを展開する
with zipfile.ZipFile(app_data_local_file) as existing_zip:
existing_zip.extractall(cwd)
# Unityアプリが実行できるように権限を付与する
logger.info(subprocess.call(shlex.split('chmod u+x ' + app_local_file)))
# ここまで追加
(略)
tc.start_learning()
# ここから追加
# モデルファイルをCloud Storageへアップ
# TODO: 圧縮する
models_local_path = './models/{run_id}'.format(run_id=run_id)
models_storage_path = 'gs://任意のバケット名/{run_id}/models'.format(run_id=run_id)
logger.info(subprocess.call(['gsutil', 'cp', '-r', models_local_path, models_storage_path]))
# ここまで追加
パッケージ作成
Cloud MLの操作に利用するgcloud
コマンドにはパッケージを自動作成する機能もありますが、ここでは手動でパッケージングします。
> cd python
> python setup.py sdist
(略)
Writing unityagents-0.4.0/setup.cfg
Creating tar archive
removing 'unityagents-0.4.0' (and everything under it)
> ll dist
total 96
-rw-r--r-- 1 user users 45K 8 6 11:14 unityagents-0.4.0.tar.gz
Cloud MLで実行してみる
さて、下準備が完了しましたので、Cloud MLへジョブ登録して学習を実行してみましょう。
パラメータ指定に--
がありますが、これ以降のパラメータが--module-name
で指定したlearn.py
にパラメータとして渡されるので、取ってはいけません。(1敗)
> cd 任意のディレクトリ/ml-agents
> gcloud ml-engine jobs submit training $JOB_NAME \
--python-version=3.5 \
--runtime-version 1.8 \
--module-name tasks.learn \
--packages python/dist/unityagents-0.4.0.tar.gz \
--region $REGION \
--staging-bucket gs://$BUCKET_NAME \
-- \
3DBall \
--run-id $JOB_NAME \
--train
Job [gcp_ml_cloud_run_01] submitted successfully.
Your job is still active. You may view the status of your job with the command
$ gcloud ml-engine jobs describe gcp_ml_cloud_run_01
or continue streaming the logs with the command
$ gcloud ml-engine jobs stream-logs gcp_ml_cloud_run_01
jobId: gcp_ml_cloud_run_01
state: QUEUED
Updates are available for some Cloud SDK components. To install them,
please run:
$ gcloud components update
はい。
ジョブが登録されたか確認しましょう。
> gcloud ml-engine jobs describe $JOB_NAME
createTime: '2018-08-06T02:20:53Z'
etag: sm-_r3BqJBo=
jobId: gcp_ml_cloud_run_01
startTime: '2018-08-06T02:21:24Z'
state: RUNNING
trainingInput:
args:
- 3DBall
- --run-id
- gcp_ml_cloud_run_01
- --train
packageUris:
- gs://任意のバケット名/gcp_ml_cloud_run_01/xxxx/unityagents-0.4.0.tar.gz
pythonModule: tasks.learn
pythonVersion: '3.5'
region: us-central1
runtimeVersion: '1.8'
trainingOutput:
consumedMLUnits: 0.01
ジョブ実行されたかログを見てみましょう。
> gcloud ml-engine jobs stream-logs $JOB_NAME
(略)
INFO 2018-08-06 11:22:50 +0900 master-replica-0 List of nodes to export :
INFO 2018-08-06 11:22:50 +0900 master-replica-0 action
INFO 2018-08-06 11:22:50 +0900 master-replica-0 value_estimate
INFO 2018-08-06 11:22:50 +0900 master-replica-0 action_probs
INFO 2018-08-06 11:22:51 +0900 master-replica-0 Restoring parameters from ./models/gcp_ml_cloud_run_01/model-5001.cptk
INFO 2018-08-06 11:22:51 +0900 master-replica-0 Froze 16 variables.
(略)
INFO 2018-08-06 11:22:54 +0900 master-replica-0 Module completed; cleaning up.
INFO 2018-08-06 11:22:54 +0900 master-replica-0 Clean up finished.
INFO 2018-08-06 11:22:54 +0900 master-replica-0 Task completed successfully.
INFO 2018-08-06 11:27:32 +0900 service Job completed successfully.
はい。
これで、ML-AgentsがCloud ML上で実行されて、models
フォルダに結果ファイルが出力されているはずです。
learn.py
でmodels
フォルダをCloud Storageにコピーしてるので、フォルダをローカルにコピーして、Unityアプリにbytesファイルを組み込んで動作させることができます。
> gsutil ls gs://任意のバケット名/$JOB_NAME/models
gs://任意のバケット名/gcp_ml_cloud_run_01/models/3DBall_gcp_ml_cloud_run_01.bytes
gs://任意のバケット名/gcp_ml_cloud_run_01/models/checkpoint
gs://任意のバケット名/gcp_ml_cloud_run_01/models/model-5001.cptk.data-00000-of-00001
gs://任意のバケット名/gcp_ml_cloud_run_01/models/model-5001.cptk.index
gs://任意のバケット名/gcp_ml_cloud_run_01/models/model-5001.cptk.meta
gs://任意のバケット名/gcp_ml_cloud_run_01/models/raw_graph_def.pb
tensorboardでも結果が確認できます。
> gsutil cp -r gs://任意のバケット名/$JOB_NAME/models ローカルの任意のフォルダ/
> tensorboard --logdir=ローカルの任意のフォルダ/models
実行できることが確認できました。やったぜ^^
あとは、learn.py
をもう少し実用的に改修したり、Cloud Pub/Subや、Cloud Functionsなどを利用すれば、Cloud StorageにUnityアプリをアップすれば、自動的に強化学習が実行される素敵環境が構築できそうです^^
参考
Google Cloud Machine Learning Engine は”エンジン”であって開発環境ではない ~制約に気を付けよう~
https://www.gixo.jp/blog/10960/
Unity Machine Learning Agentsベータ版
https://unity3d.com/jp/machine-learning
MacでCloud Machine Learning Engineを利用してみる
https://qiita.com/kai_kou/items/0952c9b28efe19f2f680
Macでhomebrewを使ってUnityをインストールする(Unity Hub、日本語化対応)
https://qiita.com/kai_kou/items/445e614fb71f2204e033
MacでUnity ML-Agentsの環境を構築する
https://qiita.com/kai_kou/items/6478fa686ce1af5939d8
MacでUnity ML-AgentsをDockerで動作させる
https://qiita.com/kai_kou/items/df3f3518a5a27b66f617
トレーニング アプリケーションのパッケージング
https://cloud.google.com/ml-engine/docs/tensorflow/packaging-trainer?hl=ja
【mac】zipファイル操作コマンド
https://qiita.com/griffin3104/items/948e38aab62bbb0d0610
Linuxの権限確認と変更(超初心者向け)
https://qiita.com/shisama/items/5f4c4fa768642aad9e06
17.5.1. subprocess モジュールを使う
https://docs.python.jp/3/library/subprocess.html
CloudMLからgoogle cloud storageのファイルにアクセスする
https://qiita.com/mikebird28/items/543581ef04476a76d3e0
Google Cloud ML Engine 上でPythonを実行する時のコツ
https://rooter.jp/ml/google-cloud-ml-engine-python-tips/
Pythonでzipファイルを圧縮・解凍するzipfile
https://note.nkmk.me/python-zipfile/
gsutilコマンド全部試したので解説する(part1)
https://www.apps-gcp.com/gsutil-command-explanation-part1/