1. octa-gon

    Posted

    octa-gon
Changes in title
+自作シンプル物理演算ゲームを強化学習で攻略させる【Unity ML-Agents v3.0】
Changes in tags
Changes in body
Source | HTML | Preview
@@ -0,0 +1,135 @@
+【Unity ML-Agents v3.0】自作シンプルゲームをAIに攻略させる
+
+以前から機械学習などに興味があったものの、難しそうでためらっていたのですが、Unityで強化学習ができるML-Agentsというものがあると知り、なんだかいけそうだと思って試してみました。
+
+<img width="572" alt="スクリーンショット 2018-04-25 23.17.07.png" src="https://qiita-image-store.s3.amazonaws.com/0/223765/9ab97616-ae93-5561-0412-36aa5a091930.png">
+
+まずは[公式サンプルゲーム](https://github.com/Unity-Technologies/ml-agents)を動かしてみたのですが、何か自作ゲームを学習させてみないと理解が進まないと思い、なるべくシンプルで最小限の構成になるようなゲームを考えました。そして、せっかくUnityを使うので物理演算も入れたい。
+
+![bounce-player.mov.gif](https://qiita-image-store.s3.amazonaws.com/0/223765/4aa58df9-7947-b285-427e-54968c6969ee.gif)
+
+そこで考えたのが、上から降ってくる物体をヘディングのようにバウンドさせるゲームです。人間がプレイするとこんな感じになります。これを強化学習させて攻略させてみました。
+
+ここから先の記事はML-Agentsの公式サンプルを動かすところまで出来る方が対象です。Qiitaにも他の方が書いた記事があるので参考にして下さい。
+
+#ゲームを作る
+
+<img width="1073" alt="スクリーンショット 2018-04-25 10.18.07.png" src="https://qiita-image-store.s3.amazonaws.com/0/223765/228184a8-79ba-6934-0099-877a155a4622.png">
+
+上からボールが降ってきて、下の大きいボール(Player)で跳ね返します。操作は左右キーのみです。ボールを下に落とすとリセットされます。
+
+```c#:BounceAgent.cs
+using System.Collections;
+using System.Collections.Generic;
+using UnityEngine;
+
+public class BounceAgent : Agent {
+
+ public float speed;
+ public GameObject ball;
+
+ public override void CollectObservations()
+ {
+ AddVectorObs(ball.transform.position.x - gameObject.transform.position.x);
+
+ //状態数は少なくても上手くいったため、削除
+ // AddVectorObs(gameObject.transform.position);
+ // AddVectorObs(ball.transform.GetComponent<Rigidbody>().velocity);
+ }
+
+ void OnCollisionEnter(Collision col)
+ {
+ if (col.gameObject.tag == "ball")
+ {
+ //衝突する度に報酬を与える
+ SetReward(1f);
+ }
+ }
+ public override void AgentAction(float[] vectorAction, string textAction)
+ {
+ MoveAgent(vectorAction);
+
+ //以下のような報酬の与え方でもよいが、単に衝突時に報酬を与えてもうまくいくため削除
+ // if (Mathf.Abs(ball.transform.position.x - gameObject.transform.position.x) < 0.2f)
+ // {
+ // SetReward(0.1f);
+ // }
+ // else{
+ // SetReward(-0.1f);
+ // }
+
+ if ((ball.transform.position.y - gameObject.transform.position.y) < 0)
+ {
+ //ゲームオーバー時に報酬を引く方法だとうまくいかなかった
+ // SetReward(-10f);
+ Done();
+ }
+
+ Monitor.Log ("Reward", reward);
+ }
+
+ public override void AgentReset()
+ {
+ ball.transform.position = new Vector3(Random.Range(-0.2f,0.2f),1.5f,0) + gameObject.transform.position;
+ ball.GetComponent<Rigidbody>().velocity = new Vector3(0f, 0f, 0f);
+ }
+
+ public void MoveAgent(float[] act)
+ {
+ int action = Mathf.FloorToInt(act[0]);
+
+ //アクション
+ if (action == 1)
+ {
+ transform.Translate(-speed, 0, 0);
+ // AddReward(-0.01f);
+ }
+ if (action == 2)
+ {
+ transform.Translate(speed, 0, 0);
+ // AddReward(-0.01f);
+ }
+
+ //移動制限
+ if (transform.localPosition.x < -1.5f)
+ {
+ transform.localPosition = new Vector3(-1.5f, 0, 0);
+ }
+ if (1.5f < transform.localPosition.x)
+ {
+ transform.localPosition = new Vector3(1.5f, 0, 0);
+ }
+ }
+}
+```
+
+状態数は1つだけ。ボールとPlayerのx座標の相対位置を取得します。
+報酬はボールを跳ね返したら1点追加します。
+ボールを落とした場合に報酬を減らす方法も試しましたが、うまくいきませんでした。
+
+#学習結果
+
+<img width="862" alt="スクリーンショット 2018-04-25 8.56.12.png" src="https://qiita-image-store.s3.amazonaws.com/0/223765/343b4d2b-6cfe-6e9e-aa88-2cb99a1bb937.png">
+
+10万回学習させたところ、7回ぐらい跳ね返せるようになりました。
+
+<img width="822" alt="スクリーンショット 2018-04-25 8.57.02.png" src="https://qiita-image-store.s3.amazonaws.com/0/223765/87d67b15-3a7b-b17d-dd86-fcfec4331ea9.png">
+
+その他の値はこのようになっています。
+ただ、これらが何を意味しているのかよくわかっていないので、分かる方はぜひ教えてください。
+
+#改良点と課題
+
+今回の学習結果では、ボールのx座標に追従するような動きになっています。このような動きは、わざわざ強化学習でなく、コードを書くだけでも似たような動きが実現できると思います。
+
+より人間的な動きとしては、落下地点を予測してあらかじめ移動しておくものになるはずです。そのために、状態数や報酬の与え方を工夫する必要が有る、ということを実感できました。
+
+また、今回WebGL版をビルドしようとしましたが、エラーが出てビルドできませんでした。これについても詳しい方、コメント頂けると幸いです。
+
+#制作物
+macでとりあえず動きを見たい人用のappです。
+[http://mixsandwich.info/Bounce.zip](http://mixsandwich.info/Bounce.zip)
+
+ソースコードです。スクリプト見たり、ビルド&学習させたい時用。
+[https://github.com/mixsandwich/Bounce](https://github.com/mixsandwich/Bounce)
+