【Unity強化学習】チュートリアルで遊んでみる

[Introducing: Unity Machine Learning Agents](https://blogs.unity3d.com/jp/2017/09/19/introducing-unity-machine-learning-agents/)
Unity ML-Agentsを使えば、Unity環境で強化学習を行うことができます。
チュートリアルは簡単に試すことができるのでまずはやってみましょう。

![TypicalRL.png](https://qiita-image-store.s3.amazonaws.com/0/225485/216088cc-64c0-9ba5-fcbb-da9678f13748.png)


#まず動かしてみる

Unityを起動して適当な名前でプロジェクトを作ります。

[公式GitHub](https://github.com/Unity-Technologies/ml-agents/blob/master/docs/Making-a-new-Unity-Environment.md)からML-Agents package with TensorflowSharpをダウンロード。実行して環境をインポートします。

<img width="563" alt="SnapCrab_NoName_2018-2-28_9-54-47_No-00.png" src="https://qiita-image-store.s3.amazonaws.com/0/225485/03282d6d-0fe7-c53d-74c5-88771cf7bfbb.png">

Examples > Areaの中にあるWallSceneをやってみましょう。

<img width="802" alt="SnapCrab_NoName_2018-2-28_10-6-22_No-00.png" src="https://qiita-image-store.s3.amazonaws.com/0/225485/8f129665-687d-8d65-efc1-2ad1dd893383.png">

HierarchyのAcademy > Brainを選択。BrainTypeがPlayerになっていることを確認して実行してみましょう。

<img width="256" alt="SnapCrab_NoName_2018-2-28_10-8-1_No-00.png" src="https://qiita-image-store.s3.amazonaws.com/0/225485/6a5e2988-1ef9-857f-6959-5398dda8447b.png">

![Wall_Play.gif](https://qiita-image-store.s3.amazonaws.com/0/225485/ffbbc0c6-555d-33b5-6611-88ed8f5df126.gif)


キーボードのWASDで移動、スペースでジャンプ。
壁の向こうにある緑色のところに行けばゴールです。しかし、ただジャンプするだけでは壁は越えられないので、オレンジの箱を利用しなければいけません。

#学習済みデータを利用する

このチュートリアルには学習済みのデータが付属しています。これを使ってみましょう。同じフォルダのTFModelsに入っているファイルがそれです。

<img width="318" alt="SnapCrab_NoName_2018-2-28_10-16-11_No-00.png" src="https://qiita-image-store.s3.amazonaws.com/0/225485/4f2de14c-a114-4735-e275-a32f2c6cc791.png">

まず、Edit > Project Settings > PlayerからOtherSettingsタブを開き、
Scripting Runtime Version を Experimental(.NET 4.6 Equivalent)
Scripting Define Symbols を ENABLE_TENSORFLOW
にします

<img width="230" alt="SnapCrab_NoName_2018-2-25_22-17-39_No-00.png" src="https://qiita-image-store.s3.amazonaws.com/0/225485/ea314905-9ca3-ec3b-46d4-a87bda346545.png">

今度は先ほどと違って、BrainTypeをInternalにします。

<img width="255" alt="SnapCrab_NoName_2018-2-28_10-23-41_No-00.png" src="https://qiita-image-store.s3.amazonaws.com/0/225485/4e30d98f-dafb-7968-ab14-06aff7a276d5.png">

Graph Modelに強化学習のデータが入ります。デフォルトですでに入っていると思います。これがさっきのTFModelsに入っていたデータですね。

これで実行してみましょう。

![Wall_Internal.gif](https://qiita-image-store.s3.amazonaws.com/0/225485/747e5a2e-bc96-1e24-e79b-63b22958c17b.gif)


強化学習されたモデルによって自動で動くと思います。
同様の手順でほかのサンプルも動かすことができます。

#サンプル紹介

**3DBall**

![3DBall.gif](https://qiita-image-store.s3.amazonaws.com/0/225485/f46ac3c7-e63d-da03-7758-948cbc786dcf.gif)

**Reacher**

![Reacher.gif](https://qiita-image-store.s3.amazonaws.com/0/225485/4a633f87-0bc3-b1d5-5ba4-aa4015d292a1.gif)

**Tennis**

![Tennis.gif](https://qiita-image-store.s3.amazonaws.com/0/225485/f09d3b19-6bcc-b137-08cb-13e3bee3e305.gif)


#Unity ML-Agentsの仕組み

![Learning Environment.png](https://qiita-image-store.s3.amazonaws.com/0/225485/49391ed7-0530-a85f-1741-2a685bc25139.png)

移動したり、ジャンプしたりするAgentsはBrainとAcademyによって動作が制御されています。
BrainTypeがPlayerのときは人間が動かすことができ、Internalのときは学習済みモデルによって自動で動きました。
ExternalにするとPython APIを使用して、オープンソケットを介して通信することで、外部から行動を制御できます。
これを使って、強化学習を実際にやってみましょう。

#ビルドして強化学習

WallSceneの隣にあるPushSceneを使います

<img width="433" alt="SnapCrab_NoName_2018-2-28_11-31-7_No-00.png" src="https://qiita-image-store.s3.amazonaws.com/0/225485/a3159508-21e6-338a-39ac-71c942aac5b4.png">

Pushの場合はオレンジの箱を緑のところに持っていけばゴールです。

[GitHub](https://github.com/Unity-Technologies/ml-agents)のリポジトリをダウンロード。その中のPythonフォルダをいまのプロジェクトにコピーします。(Assetsの外)

<img width="335" alt="SnapCrab_NoName_2018-2-28_11-35-11_No-00.png" src="https://qiita-image-store.s3.amazonaws.com/0/225485/5f7ba3e5-5255-17ec-40ad-eb1f047662b4.png">

次にBrainTypeがExternalになっていることを確認

<img width="259" alt="SnapCrab_NoName_2018-2-28_11-33-19_No-00.png" src="https://qiita-image-store.s3.amazonaws.com/0/225485/b4cff314-6d85-6269-14d2-027be33b7820.png">

Edit > Project Settings > Player からResolution and Presentationタブを開く。
Run In BackGround にチェック
Display Resolution Dialog をDisabled
にする

<img width="235" alt="SnapCrab_NoName_2018-2-28_11-38-10_No-00.png" src="https://qiita-image-store.s3.amazonaws.com/0/225485/fa2393bd-9538-0aca-6112-712b6eb53187.png">

その後、設定を確認してビルド。保存先は先ほどのPythonフォルダ。名前はAreaPushにしておきましょう。

PythonフォルダでAnacondaプロンプトを開きます。

```python
python ppo.py AreaPush --train
```

これで学習が開始します。

<img width="539" alt="SnapCrab_NoName_2018-2-28_11-54-18_No-00.png" src="https://qiita-image-store.s3.amazonaws.com/0/225485/aa829faa-357c-2f0a-7b0c-fb4c9e36d272.png">

オプションで`--max-steps=1e5`といった感じで学習回数を決められます。デフォルトでは1e6(100万回)
`--load`などで途中から学習を再開できます。
詳しくはppo.pyを見てみてください。

学習が完了するとmodelsというフォルダが作成され、その中のppo
フォルダにAreaPush.bytesファイルが生成されていると思います。

<img width="281" alt="SnapCrab_NoName_2018-2-28_12-12-54_No-00.png" src="https://qiita-image-store.s3.amazonaws.com/0/225485/eb4a1bbb-441d-57d4-5161-5cb9673f4a9e.png">

これをUnityのArea > TFModelsフォルダにコピーしましょう
前のときと同様BrainTypeをInternalにし、Graph ModelにAreaPushファイルをセット

<img width="255" alt="SnapCrab_NoName_2018-2-28_12-15-54_No-00.png" src="https://qiita-image-store.s3.amazonaws.com/0/225485/abdb3b02-3710-9656-bb0a-3a29cef294cc.png">

#結果

**10万回学習**

![Push_Internal_100k.gif](https://qiita-image-store.s3.amazonaws.com/0/225485/1181009f-2f2e-afa9-f082-a546a20babac.gif)

緑のところがゴールということは理解してますが、オレンジの箱がどう関係しているかはわかっていない様子。

**50万回学習**

![Push_Internal_500k.gif](https://qiita-image-store.s3.amazonaws.com/0/225485/1e48aec3-6277-5453-550c-f43cfce56f95.gif)

オレンジの箱をゴールに持っていくのを理解した模様

Unityは無料で使え、誰でもクオリティの高いゲームを作ることができるソフトです。
チュートリアル以外にも自分でゲームを作ったり、ほかの人が作ったゲームで強化学習を行うこともできます。

[【Unity強化学習】自作ゲームで強化学習](https://qiita.com/God_KonaBanana/items/7aebdb411c99b059cc6f)

#参考

[Introducing: Unity Machine Learning Agents](https://blogs.unity3d.com/jp/2017/09/19/introducing-unity-machine-learning-agents/)