【Unity】三目ならべのディープラーニング(ML-Agents v0.8.1)

07/29/2019

三目ならべ

三目ならべをやってみました。ちなみに英語では「Ticktacktoe」と呼ぶようです。
Unity2018.4.4
Ml-Agentsv0.8.1
で取り組みしました。
ご存じだと思いますが、ルールは先に3×3のマス目に同じマークが3つ並べば勝ちとなるルールです。
ゲーム的には先手有利ですが、必ず引き分けにすることができるためそのあたりをちゃんと学習するのか?後手の学習上手にできれば成功だと思います。

構成のイメージ

構成ですが、1つのBrainに2つのAgentを利用しました。〇担当するAgentと×担当するAgentです。1戦毎に先行後攻を入れ替えていきます。

Brainに与える情報について

ブレインに与えた情報は以下の通り、詳しくはコメントを読んでください。

//Stateの取得
        public override void CollectObservations()
        {
            //Agentの担当を与えています。〇=0 ×=1
            if (manager.player_O == PLAYER.AI_O)
            {
                AddVectorObs(0);
            }
            else
            {
                AddVectorObs(1);
            }
	  //ターン数 0~8 
            AddVectorObs(manager.turn);
       //前のターンで相手が出した答え 1~9  
            AddVectorObs(manager.anser);

            //現在のCELLの値
            for (int i = 0; i < 9; i++)
            {
                int cellValue = -1;

                if (manager.cell[i] >= CELL.none)
                {
                    cellValue = (manager.cell[i] == (CELL)agentId) ? 1 : 0;
                }
                AddVectorObs(cellValue);
            }
	  //入力済みのセルは誤入力できないようにMASKをかけた。 
            if (maskActions)
            {
                SetMask();
            }
        }
        private void SetMask()
        {
            //MASKをセットする
            for (int i = 0; i < 9; i++)
            {

                if (agentId == (manager.turn + (int)manager.playMode) % 2)
                {
		  //MASKをセット
                    if (manager.cell[i] != CELL.none)
                    {
                        SetActionMask(i + 1);
                    }
                }
                else
                {
                    //ALLマスク(このコードは無意味ですよ)
                    SetActionMask(i + 1);
                }
            }
        }

上記でのポイントは、2つ。マスク処理で無駄な学習時間させてないこと。前のターンでの答えを教えること。
2つ目は意外に重要です。効率が革新的に上がりました。

Agent動作について

最終的にAgentは交互に動作するようにしました。同時に動くようにしたりしましたが制御が難しくて断念しました。

交互に動作させるためには、OnDemandDecisionsをONにします。そのうえで、呼びたいAgentにRequestDecision()を使います。FixedUpdate() から下記を呼びます。

//AIの処理
        private void WaitTimeInference()
        {
            //
            if (!academy.GetIsInference())
            {
                //学習中
                //Debug.Log("CALL Agent GetIsInference =" + academy.GetIsInference());
                agent[(turn + (int)playMode) % 2].RequestDecision();
            }
            else
            {
                //対戦モード timeBetweenDecisionsAtInference まで待機
                if (timeSinceDecision >= timeBetweenDecisionsAtInference)
                {
                    //Debug.Log("CALL Time TimeSinceDecision =" + (turn + (int)playMode) % 2 );
                    timeSinceDecision = 0f;
                    agent[(turn + (int)playMode) % 2].RequestDecision();
                }
                else
                {
                    timeSinceDecision += Time.fixedDeltaTime;
                }
            }
        }

academy.GetIsInference()は機械学習中trueになりますので、対戦PLAYと機械学習で切り分けに使います。

報酬について

引き分けの数字を+0.8にしています。勝ち+1.0 負け-1.0です。
引分けを0.5~0.8 先手後手で数字を変えたりしましたが、あまり変わらないです。

学習結果について

5万STEP学習程度では、まだまだバカです。先行の場合は負けないですが、後攻ではあっさり負けます。
10万STEP学習させた結果、まぁまぁ強くなりました。しかし、まだ100%引き分けに持ち込ませることは無理です。先手では負けないですが勝てません。後手も、負けが少なくなりましたが、まったく勝利を取るような手配はできませんww
30万STEP学習させてもどうなのかなぁと思っています。

トレーニング設定ファイル

今回はProximal Policy Optimization(PPO)と呼ばれる強化学習手法を使用しています。Ml-Agentは、模倣学習用のBehavioral Cloning (BC)も可能です。
PPOとは、ニューラルネットワークを使用して、観察結果を考慮してエージェントが常に最善の行動をするように学習していく方法です。ML-AgentsのPPOアルゴリズムはTensorFlowに実装されており、独立したPythonプロセス(ソケットを介して実行中のUnityアプリケーションと通信する)で実行されます。
最善の行動をした場合に、きちんと学習していくためには、トレーニング設定ファイルを設定する必要があります。
しかしながら、どこをどのようにすれば強くなるのか? 現状はまったくわかりません。

現在は、下記のようにしています。

default:
    trainer: ppo
    batch_size: 1024
    beta: 5.0e-3
    buffer_size: 10240
    epsilon: 0.2
    gamma: 0.99
    hidden_units: 128
    lambd: 0.95
    learning_rate: 3.0e-4
    max_steps: 5.0e4
    memory_size: 256
    normalize: false
    num_epoch: 3
    num_layers: 2
    time_horizon: 64
    sequence_length: 64
    summary_freq: 1000
    use_recurrent: false
    use_curiosity: false
    curiosity_strength: 0.01
    curiosity_enc_size: 128

TictactoeLearningBrain:
    batch_size: 512
    normalize: false
    num_layers: 1
    hidden_units: 128
    beta: 1.0e-3
    gamma: 0.9
    buffer_size: 10240
    max_steps: 10.0e5
    summary_freq: 1000
    time_horizon: 64

もっと強くなるためには・・・よくわからないんだよなぁ。

最後に

このまま、30万STEP~50万STEPと学習させても学ぶべきことが少ないような気がします。
なので次のゲームにチャレンジしようと思います。
今回の結果は、ストア買ったアセットを使っているため、Qiitaに上げられないのですが、興味のある方は、連絡いただければ個人的に送ります。アセット利用しないようにするのが面倒w

10万Stepの結果です。
〇が自分 ×がAIです。

以下の画像は学習中。やってる感満点なのが好きwwww

スポンサーリンク