[Project Bonsai/Moab]Bonsai育成記 (1)Moabバランス

# はじめに
ここではMicrosoftの[Project Bonsai](https://azure.microsoft.com/ja-jp/services/project-bonsai/)および[Project Moab](https://microsoft.github.io/moab/)のチュートリアルを紹介します。
実際に手を動かす部分にフォーカスするので概念的な説明は[Docs](https://docs.microsoft.com/en-us/bonsai/product/)にお任せしてここではほぼ触れません。
チュートリアルもDocsも公式サイトには記事執筆時点で日本語がありませんがご了承ください。
なお、Elasticsearchの[bonsai.io](https://bonsai.io/)は関係ありません。
盆栽も出てきません。

## Bonsaiとは
Microsoftが提供するローコードプラットフォームです。Webブラウザ上で動作します。
強化学習を利用する産業機械をターゲットに提供されています。
計算リソースはAzureを利用します。

## Moabとは
ボールのバランシング課題用シミュレータです。
実物はこんなのです。本稿ではこれをシミュレートします。
![moab.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/94824/cebbd966-c902-e1e9-e179-a3a2cd57ef70.gif)
参考：https://www.freshconsulting.com/portfolio/moab/
3Dモデルは[こちら](https://sketchfab.com/3d-models/project-moab-m2-540ca7b7751344928d11a1eea66f252f)。ハードウェアは記事執筆時点では市販されてはいないようです。

# 前提
- Microsoftのアカウント取得済み　→未取得の場合は[こちら](https://account.microsoft.com/)
- Azureのサブスクリプションを導入済み　→未取得の場合は[こちら](https://azure.microsoft.com/ja-jp/free/)
- Bonsaiは記事執筆時点でPreview版です。

# 事前準備 ワークスペースの作成
参考：[Microsoft account setup for Bonsai](https://docs.microsoft.com/en-us/bonsai/guides/account-setup)
BonsaiのワークスペースをAzure上に作成します。
Azure Portalの「Create a resource」から「Bonsai」と検索して出てきた盆栽アイコンのリソースを選択して「Create」します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/94824/01660e9e-f855-40b7-c6e0-8c0042a3ebd1.png)

次にリソース情報を入力していきます。リソースグループがない場合は新規作成します。
名前は任意で。ここでは「BonsaiWS-Tutorial-wus2」としました。
リージョンは今は選択肢が少ないです。West USかWest US2しか選べないと思います。とりあえずデフォルトの「West US 2」の選択のまま「Review + create」→次の画面も「create」を押します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/94824/64d03850-efe5-6c08-9d3c-94413cd66131.png)

ワークスペース作成の手順は以上です。
作成されたワークスペースを確認しましょう。
Bonsaiはワークスペースとは別に、Azure管理下にあるリソースグループとその配下にStorageとLogAnalyticsが自動生成されます。Bonsaiの使用量に応じてこの部分が課金されますのでご注意ください。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/94824/c8d6787a-d036-ebb8-c2e9-5c4cf33b0ac0.png)
# チュートリアル1 バランスをとる 
参考：[Quickstart: Balance a ball with AI (Moab)](https://docs.microsoft.com/en-us/bonsai/quickstart/moab/)
参考：[MOAB TUTORIAL 1: TRAIN AI TO BALANCE A BALL]
(https://microsoft.github.io/moab/tutorials/1-balance/index.html)
前置きが長くなりましたが、ようやく本題のチュートリアルです。早速Bonsaiのサイトに入ってみます。
https://preview.bons.ai/accounts/signin
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/94824/103b2b76-0b6a-8feb-8a51-01c62bb41990.png)
Microsoftアカウントでログインし、先ほど作成したワークスペースを指定して「Get started」を押します。
ログインすると開始するアセットを選べます。ここでは「Moab」を選択して進めていきます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/94824/62772922-4482-e114-df43-f84978835782.png)
AIモデルであるBrainの表示名を入力します。「Moab Tutorial 1」とします。
Brain表示名を入力したら「Create brain」で作成します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/94824/3d39d6cc-d774-c39e-8984-3eda401d00cb.png)

## BonsaiのWebUI
BonsaiのUIです。3領域に分かれています。
* ナビゲーションサイドパネル：作成されたBrainとシミュレータ（ここではMoab）が表示されます。
* Inkling コードエディター：独自言語Inklingのコードエディター。
* グラフパネル：コードエディターで定義されたState, Goal, Actionなどをグラフ表示します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/94824/fdb71983-cfd1-2e50-9576-a0f4c9838400.png)

本来のステップで言えばシミュレート対象の機械があり、ここに適切なパラメータ設定と訓練カリキュラムを設定した上でカリキュラム通りの訓練を何万回と繰り返し、結果訓練されたモデルである「Brain」を最終的な出力とすることを目標とします。
チュートリアルではこの時点でシミュレータのMoab、訓練カリキュラムのInklingコード、Azure上の訓練用エンジンとリソースがすでに用意されている状態です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/94824/26d4d9c5-1840-0d1d-ab2e-979ded61f77a.png)
参考：https://docs.microsoft.com/en-us/bonsai/product/

## チュートリアルの目標
詳しいコードの中身やグラフの見方は後程簡単に説明しますが、押さえておきたいポイントが１つ。「Goal」です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/94824/988b6e41-2e8d-15e1-fb7a-5fea7ff08b0e.png)
Goalはその名の通りシミュレーションに対する目標を設定します。現在は「ボールをプレートから落とさないこと」「ボールをプレートの中央に移動させること」の２点をGoalに設定しています。グラフパネルにはGoalで設定された２つが表示されていることが分かります。この後のBrainの訓練ではこのGoalがどの程度達成されているかが表示されます。

## 学習実行
さて、コメントは日本語に直してみましたが、この時点でコード自体は何も修正はしていないです。
Moabを動かせるのでとりあえず動かしてみます。「Train」ボタンを押してみます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/94824/334bcd96-cef8-d05a-a692-86d09312069c.png)
Trainボタンを押すと中央のパネルのタブがTrainタブへ切り替わります。このパネル上でMoabのシミュレーションを見ることができます。
Moabの場合はTrainタブで見れるセクションは大きく３つです。

1. トレーニングパフォーマンスプロット：訓練回数に対する目標達成度のグラフ。各Goalの達成度とその平均値がプロットされます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/94824/0829a39f-32f2-8ec2-0f2f-0a120701bdd9.png)

2. シミュレータノード：グラフパネルに達成度が表示されます。シミュレーターにはインスタンス数と訓練速度が表示されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/94824/d8a4e824-5e1a-f63b-f751-d3bfcc91b29a.png)

3. Moabデバイスの視覚化：リアルタイムにデバイスモデルのシミュレーションが見れます。
![moab_train1.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/94824/55c378b3-6dd1-20bb-2a9e-a1b561bacd1d.gif)
最初はボール落としてばかりですが、徐々に上手になっていくはずです！

## ソースコード
訓練完了までは時間がかかるのでその間コードを眺めてみようと思います。
ソースコードはInklingという独自言語で記述されています。グラフパネルのいずれかのノードをクリックすると対応するコードにジャンプすることもできます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/94824/c8ad458f-a8d1-d8b0-9d7a-67a9c9958a55.png)

前述の通り[goal](https://docs.microsoft.com/en-us/bonsai/inkling/keywords/goal?tabs=avoid)では学習における目標を設定します。goalを設定することにより、Bonsaiのエンジンが強化学習における報酬と早期終了条件を自動的に決定できるようにします。

```ruby
# トレーニングの目的は、2つのサブゴールを持つゴールとして表されます。
# - ボールをプレートから落下させないこと
# - ボールをプレートの中央に移動させること
goal (State: ObservableState) {
    avoid `Fall Off Plate`: Math.Hypot(State.ball_x, State.ball_y) in Goal.RangeAbove(RadiusOfPlate * 0.8)
    drive `Center Of Plate`: [State.ball_x, State.ball_y] in Goal.Sphere([0, 0], CloseEnough)
}
```

goalの引数には ```State: ObservableState``` が指定されています。これはSimulatorから出力された「状態」が渡されます。グラフパネルを見ると４つポチがありますが、これはそれぞれObservableState内で定義されている変数を表しています。

```ruby
# Stateは反復処理のたびにsimulatorから渡されます
type ObservableState {
    # ボールの X,Y 位置
    ball_x: number<-MaxDistancePerStep - RadiusOfPlate .. RadiusOfPlate + MaxDistancePerStep>,
    ball_y: number<-MaxDistancePerStep - RadiusOfPlate .. RadiusOfPlate + MaxDistancePerStep>,

    # ボールの X,Y 速度
    ball_vel_x: number<-MaxVelocity .. MaxVelocity>,
    ball_vel_y: number<-MaxVelocity .. MaxVelocity>,
}
```

座標系とPitch/Rollの概念は下図の通りです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/94824/2ee92fae-303b-f6bc-89de-9f8a8d14c330.png)
参考：https://microsoft.github.io/moab/tutorials/1-balance/index.html#step-1-define-the-problem

goalの評価結果、シミュレーションを継続する場合次の反復が開始されます。その際simulatorへ渡される情報として定義されるのがActionです。Brainの演算結果、プレートをどういう方向に動かせばいいのかはプレートの傾きであるpitchとrollで表現されます。

```ruby
# シミュレータのポリシーによって出力として提供され、シミュレータへの入力として送信されます
type SimAction {
    # -1から1の範囲は、ハードウェアでサポートされているプレートの回転範囲全体を表す値です。
    input_pitch: number<-1 .. 1>, # rotate about x-axis
    input_roll: number<-1 .. 1>, # rotate about y-axis
}
```

Moabデバイスの３本のアームはこのActionで受け取った値によってプレートを操作します。
なおコメントにあるポリシーとは（たぶんですが）提供されているMoabシミュレータで定義されているインターフェースを指します。ナビゲーションサイドパネルのSimulator部分にある「Moab」をクリックしてみます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/94824/a676afd4-4f05-33c9-fe44-1937343c6c9a.png)
ここではシミュレータが提供しているインターフェースとその詳細を見ることができます。
グラフパネルの「Moab」をクリックしても同じページに飛びます。

## 学習終了
これらのAction→Simlator→State→Goalの手順を繰り返すことにより学習をしていきます。
50万回の試行を繰り返すか、有意な改善が見られなくなったら自動的に訓練は終了します。
訓練時間はまちまちですが、今回は34分でした。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/94824/4f7fa12b-4352-e5b0-0497-a0a72e890298.png)

最終的にはこんな感じになりました。上手！
![moab_trainfinished.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/94824/a6d8b6ee-d92f-c1dc-4d55-507976e2b4a4.gif)

現在は物理デバイスが手元にないのでやりませんでしたが、作成されたAIモデルのBrainをExportして物理デバイスへデプロイすることも可能だそうです。
<iframe width="800" height="450" src="https://www.youtube.com/embed/iMDVCL7W9xs" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>

# 次のステップ
次のチュートリアルもできたら書いていきたいと思います。

チュートリアル2 ドメインランダム化
[MOAB TUTORIAL 2: ROBUST BALANCING VIA DOMAIN RANDOMIZATION](https://microsoft.github.io/moab/tutorials/2-robustness/index.html)

チュートリアル3 障害物を避ける
[MOAB TUTORIAL 3: BALANCE WITH A FIXED OBSTACLE](https://microsoft.github.io/moab/tutorials/3-fixed-obstacle/index.html)

サンプル（OpenAI Gym）
[bonsai-gym sample](https://github.com/microsoft/bonsai-gym/tree/main/samples)

# まとめ
MicrosoftのProject Bonsaiをチュートリアル通りなぞってみました。コードは一切修正せずに簡単に試すことができます。3Dモデルがあれば、よく見る物理演算＆強化学習とか結構簡単にできるのでは、と思いました。