[Project Bonsai] Bonsaiのシミュレータを触ってみる


はじめに

Project Bonsaiについて調べてみましたの3回目です。
過去の内容はこちら。
1回目は「Bonsaiを触ってみる」
2回目は「Bonsaiをいじってみる」

前回は、教育カリキュラムをいじってみたので、今回はシミュレータを触ってみたいと思います。

Bonsaiって何?

Microsoftが提供している自律システム向け機械教示サービスです。(現在はPublic Preview)
産業制御システムに焦点を当てた汎用ディープ強化学習プラットフォームのようです

Bonsaiのシミュレータ

Cartpoleのチュートリアルは、すでにシミュレータも用意されていますが、基本的には自分で用意する必要があります。

サポートされているソフトウェア

  • MATLAB Simulink
  • AnyLogic
  • VP Link
  • Docker でコンテナー化されたカスタムのコンテナー

APIによるPythonやRESTのサポートもあるようですが、一からの作成だとなかなかお手軽にできる感じではありません。

実は、Cartpoleのシミュレータのソースコードは、公開されています。

今回は、このソースコードを、ローカル上で動かすアンマネージシミュレータを試してみたいと思います。

ローカル環境でシミュレータを動かす

今回チェックをした環境及び、使用したソフトは以下の通りです。

  • Windows10 Pro 21H1
  • Visual Studio Community 2019 version 16.9.6

BonsaiのIDとキーの取得する

BonsaiのWorkspcaeIDと、AccessKeyを取得します。
BosnsaiのWebページの右上にあるアカウント情報をクリックし、メニューから、「Workspace info」を選択します。

Workspace Infoが表示されたら、WorkspaceIDをメモします。
AccessKeyは、右下にある「+ New access key」をクリックすると画面上に表示されます。
セキュリティ上、AccessKeyは、一度だけしか表示されません。もしキーを紛失した場合は、再度発行処理を行ってください。

シミュレータのソースコードを取得する

BosnsaiAPIのGitHubページからソースコードを取得します。
CSharpやJava、Pythonなどのサンプルがありますが、今回はCSharpを使用します。

BonsaiのIDとキーを設定する

取得してきたソースコードの中にある「Microsoft.Bonsai.Api.Samples.Cartpole.sln」ファイルをVisual Studioで開きます。

メニューより、プロジェクトのプロパティを開き、環境変数の項目に以下を追加します。

名前
SIM_WORKSPACE Bonsaiで取得したWorkspcaeID
SIM_ACCESS_KEY Bonsaiで取得したAccess key

ここまで出来たら準備万端です。
「F5」を押すか、メニューから「デバッグの開始」を選択します。
実行すると「コマンドプロンプト」が表示され、Bonsaiからの指示待ち状態になります。

※赤線の部分は、Bonsaiのシミュレータ画面の名称の一部として表示されます。

Cartpole学習の準備をする

ローカルシミュレータの連携確認

プロジェクトを実行すると、BonsaiのSimulatorsの一覧に「Cartpole-CSharp-Unmanaged」 が追加されます。
赤線の部分は、「コマンドプロンプト」の起動時に表示されたものと同じ内容が表示されます。
もし、表示されていない場合は、WorkspcaeIDや、AccessKeyが間違っていないか確認してください。

教育カリキュラムを作る

ローカルシミュレータを使用するCartpole用教育カリキュラム作成します。
「+ Create Brain」を選択し、チュートリアル用のCartpoleを追加します。
作り方は「Bonsaiを触ってみる」を参照ください
今回は、「Cartpole Trial Unmanaged」という名前で作成しています。

シミュレータの変更

そのまま使うと、チュートリアルのシミュレータと連携するので、ローカルのシミュレータに接続できるように教育カリキュラムを修正します。

変更前
source simulator (Action: SimAction): SimState {
    package "Cartpole"
}
変更後
source simulator (Action: SimAction): SimState {
}

使用するシミュレータのpackageを削除します。
削除することで、学習開始時にシミュレータを選択することが可能になります。

学習を開始する

「Train」をクリックすると、シミュレータを選択するポップアップが表示されるので、「Unmanaged simulators Cartpole-CShape」をクリックします。

選択すると、学習が開始されます。
この後は、基本的にチュートリアルの学習時度の動作と同じです。

チュートリアルと大きく違うのは、実行速度です。
ローカルで実行しているためシミュレータ数が1個になります。
実行速度も1秒間に5回程度となり、かなり遅いです。
※チュートリアルだと、35インスタンスで、1秒間に300回程度実行されていました。

同じ結果になるか、気長に待つとします。

まさかのエラー

なんかエラーでました。。(通信エラー・・?)

6時間近くシミュレータ動かしてたのに。。ひどすぎる。。
課金の額を見るのが怖いのに。。

シミュレータをデバッグする

コノヤロー!ってことで、終わってもよかったのですが、
原因が知りたいのでデバッグしてみます。
Bonsaiには、シミュレータをデバッグする仕組みが用意されているようなので、少し試してみます。

デバッグ画面は、Simulatorsから、Cartpole-CSharpを開き、Debuggerタブを選択することで表示されます。

デバッグ画面で使用するのは、4つです。

  • デバッグのタイムライン
  • タイムラインの操作パネル
  • シミュレータへの送信情報
  • シミュレータからの受信情報

デバッグのタイムライン

4つのEventTypeを組み合わせて、学習動作を再現します。
Startと、Finish、Unregisterの登録は必須です。
Unregisterは、Finish後の設定が一般的な様です。
Stepは、一回の学習を意味します。
補足)Unregisterは、無くても動作しています。Unregisterの実行後にローカルシミュレータとの接続がきれるので無いほうがデバッグしやすいかも。。

「+」ボタンを押すことで、タイムライン上に項目を追加し、EventTypeのラジオボタンを選択することで、種類を変更することができます。
今回は、「Start」「Step」「Finish」「Unregister」を登録します。
ちなみに削除したいときは、タイムラインの項目を選んで、Backspaceです。

タイムラインの操作パネル

タイムラインの実行や、ステップ実行、リセットなどの動きを操作することができます。

シミュレータへの送信情報

シミュレータへ送信するJSON形式の情報を設定することができます。
「Start」では、シミュレータのSimConfigにあたる設定、Stepでは、SimActionのあたる値の設定可能です。

今回は、Stepの項目を以下のように修正します。

変更前
{
    "type": "EpisodeStep",
    "episodeStep": {
        "action": {}
    }
}
変更後
{
    "type": "EpisodeStep",
    "episodeStep": {
        "action": {
            "command:"1 
        }
    }
}

「右にcommand:1で進めろ」という命令を設定しています。

シミュレータからの受信情報

Bonsai側からの操作に対するレスポンスの情報が表示されます。
Stepの場合は、シミュレータの実行結果になります。

デバッグを実行

準備ができたので、デバッグを開始します。
まず、ローカルのシミュレータと接続するために、「Start session」をクリックします。

接続ができた場合は、ボタンが「End session」に変わり、Simulator StatusがIdleに変わります。

次に、タイムライン上の「-R」を選択します。
選択すると、「Reset」や、「Step」、「Run」が選択可能になります。
「Step」は、タイムライン上の項目を一つずつ実行、「Run」は、連続で実行します。

「Run」ですべて実行してみます。

エラーが発生。。

エラーがでましたが、問題のエラーと違いますね。。
※前回は通信系のエラーだったけど、今回はParseに失敗してる系?

動作ログを見ると、EpisodeStepまでログが出てるので、Finishで失敗していることがわかります。

System.AggregateException: One or more errors occurred. (Unable to deserialize the response.)

Exceptionの内容を確認すると、Deserializeに失敗している事が見えます。

Exceptionログをもとに、Visual Studioでブレイクポイントを張って詳しくデバッグしていきます。
ローカルなので、細かくチェックできるのは便利です。

原因発覚

原因がわかりました。
タイムライン上で追加されるFinishのJSONの入力値が問題でした。

仕様を確認してみると、EpisodeFinishなんて無いじゃないですか。。

変更前
{
    "type": "EpisodeFinish",
    "episodeFinish": {
        "reason": "EpisodeComplete"
    }
}
変更後
{
    "type": "EpisodeFinish",
    "episodeFinish": {
        "reason": "LessonChanged"
    }
}

パラメータに説明がないので、とりあえずLessonChangedに変えます。

再度実行!

修正後、再度デバッグを実行しました。
今回は無事成功、コマンドプロンプトには各操作のログが表示され、エラーは出てないです。

ってことは、シミュレータの問題ではなくて、やっぱり通信が原因だったんでしょうか・・(ログ残してたらよかった・・)

まとめ

とりあえず、自分でシミュレータを用意して動かす&予想外のデバッグまで試してました。
学習時のエラー(たぶんタイムアウト系・・?)と、デバッグでのエラーは違うと思いますが、デバッグのやり方を理解できたのでよしとします。

再度動作の確認をしたいのですが、ちょっと時間とコストが割に合わないです・・。

今回は、Visual Studioから直接実行しましたがDockerのコンテナにすることで、スケーリング可能なマネージドのシミュレータとしてBonsaiに登録できるそうなので、それをしないと使い物にならないかなと思います。

最終は、今回のBonsaiのコストで締めたいと思います。