田舎の大学生

都会の社会人になりたい

Unityで自作環境での強化学習のやり方

1.はじめに

実行環境
ml-agent:0.13.1
Unity:2019.3.13f1


www.youtube.comhttps://www.youtube.com/watch?v=DoDtGx3B-b8




Unityで初めて強化学習を行う人に対して記述していこうと思います!
参考にした記事はこちらです!
qiita.com



この記事はml-agent:0.11.0だったので、私と同じバージョンの人は少し変更点があります。

ちなみに私の学習結果です↓

www.youtube.com


2.強化学習とは

強化学習機械学習の手法の一つです。
教師あり学習とは違いエージェント(制御対象)が自分で制御側を獲得するものです。
エージェントが状態を取得して、行動を選択します。簡単に言えば人間の脳に似ています。

Unityでは「Academy」「Brain」「Agent」が大事になってきます。



f:id:fumiblogtan:20200509150843p:plain



「Academy」:環境
「Brain」:行動の選択
「Agent」:制御対象

といった感じです。


Unityのネイティブプログラミング言語C#(あってますか?)なのですが強化学習では最終的にpythonで動かします。(Tensorflowを使いたいから?)



3.インストールするもの

Unity:2019.3.13f1
ML-Agents v0.13.1
AnacondaPythonは3.6以降)



4.セッティング

1.Unityを立ち上げプロジェクトを作成
2.「ml-agents-0.13.1\UnitySDK\Agents」内にある「ML-Agents」フォルダを「プロジェクト名\Assets」にコピー
3.「ml-agents-0.13.1」内にある「config」「ml-agents」「ml-agents-envs」プロジェクト名フォルダー内にコピー


5.環境作成

5.1床の作成(Floor)

「Hierarchy」「+」マークから「3Dオブジェクト」>「Plane」を選択し平面を出す
「Inspector」から、「名前」「Transform」を変更
・色を変更したいときは「Inspector」>「Mesh Renderer」>「Element」から選択

f:id:fumiblogtan:20200509152803p:plain



5.2箱の作成(Target)

「Hierarchy」「+」マークから「3Dオブジェクト」>「Cube」を選択し立方体を出す
「Inspector」から、「名前」「Transform」を変更

f:id:fumiblogtan:20200509152907p:plain



5.3球の作成(RollerAgent)

「Hierarchy」の「+」マークから「3Dオブジェクト」>「Sphere」を選択し球を出す
「Inspector」から、「名前」「Transform」を変更
「Inspector」の一番下にある「Add Comporment」>「RigidBody」を追加


f:id:fumiblogtan:20200509153136p:plain


「RigidBody」を追加することでゲームオブジェクトに物理特性によって制御可能になります!

詳しくはこちら
Rigidbody - Unity マニュアル



5.4Academyの作成

「Hierarchy」「+」マークから「Create Export」>名前を「Academy」に変更

f:id:fumiblogtan:20200509153636p:plain












6.Academyの実装

「Hierarchy」「Academy」を選択し、「Add Comporment」>「New Script」「RollerAcademy.cs」を作成
「RollerAcademy.cs」を以下に変更

using MLAgents;

public class RollerAcademy : Academy{}

7.Agentの実装

「Hierarchy」「RollerAgent」を選択し、「Add Comporment」>「New Script」「RollerAgent.cs」を作成
「RollerAgent.cs」を以下に変更(詳しいプログラム説明は参考にした記事を見てください!ただしバージョンが違うのでところどころ変わっています)

using UnityEngine;
using MLAgents;

public class RollerAgent : Agent
{
    Rigidbody rBody;
    void Start()
    {
        rBody = GetComponent<Rigidbody>();
    }

    public Transform Target;
    public override void AgentReset()
    {
        if (this.transform.position.y < 0)
        {
            //回転加速度と加速度のリセット
            this.rBody.angularVelocity = Vector3.zero;
            this.rBody.velocity = Vector3.zero;
            //エージェントを初期位置に戻す
            this.transform.position = new Vector3(0, 0.5f, 0);
        }
        //ターゲット再配置
        Target.position = new Vector3(Random.value * 8 - 4, 0.5f,
                                      Random.value * 8 - 4);
    }

    public override void CollectObservations()
    {
        // ターゲットとエージェントの位置
        AddVectorObs(Target.position);
        AddVectorObs(this.transform.position);

        //エージェントの速度
        AddVectorObs(rBody.velocity.x);
        AddVectorObs(rBody.velocity.z);
    }

    public float speed = 10;
    public override void AgentAction(float[] vectorAction)
    {
        //行動
        Vector3 controlSignal = Vector3.zero;
        controlSignal.x = vectorAction[0];
        controlSignal.z = vectorAction[1];
        rBody.AddForce(controlSignal * speed);


        //報酬
        //ボール(エージェント)が動いた距離から箱(ターゲット)への距離を取得
        float distanceToTarget = Vector3.Distance(this.transform.position,
                                                 Target.position);

        //箱(ターゲット)に到達した場合
        if (distanceToTarget < 1.42f)
        {
            //報酬を与え完了
            SetReward(1.0f);
            Done();
        }

        //床から落ちた場合
        if (this.transform.position.y < 0)
        {
            Done();
        }
    }

    public override float[] Heuristic()
    {
        var action = new float[2];
        action[0] = Input.GetAxis("Horizontal");
        action[1] = Input.GetAxis("Vertical");
        return action;
    }

}

8.パラメータ調節

「Hierarchy」「RollerAgent(Script)」の項目を変更

f:id:fumiblogtan:20200509154459p:plain


「Add compornent」「Behavior Parameters(Script)」を追加、項目を変更

f:id:fumiblogtan:20200509154614p:plain


「プロジェクト名>config」内にある「trainer_config.yamlに以下を付け足す(新しいファイルを作成してもよい)

RollerBall:
    trainer: ppo
    batch_size: 10
    beta: 5.0e-3
    buffer_size: 100
    epsilon: 0.2
    hidden_units: 128
    lambd: 0.95
    learning_rate: 3.0e-4
    learning_rate_schedule: linear
    max_steps: 10.0e4
    normalize: false
    num_epoch: 3
    num_layers: 2
    time_horizon: 64
    summary_freq: 10000
    use_recurrent: false
    reward_signals:
       extrinsic:
            strength: 1.0
            gamma: 0.99

9.実行

ターミナルでプロジェクト名までいき、「mlagents-learn config/書き込んだファイル名 --run-id=id名 --train」で実行

f:id:fumiblogtan:20200509154942p:plain





さいごにUnity画面に戻ってPlayを押してみましょう!

学習が終わったら「tensorboard --logdir=summaries --port=6006」と打ち込むと推移グラフをブラウザで見れます!