ml-agent學習筆記(二),unity建立新場景訓練個人AI的基礎代碼操作

在前面配置好開發環境和Unity項目後,我們開始訓練自己的個人AI,分爲以下步驟,沒有看過前面章節的推薦看完後在繼續往下看

前一章節博客的鏈接如下:https://blog.csdn.net/qq_31157943/article/details/104163182

一,首先你需要把從Github上下載下來的ml-agents的文件包中的UnitySDK/Assets下的ML-Agents文件夾拖入unity項目的Assets文件下,這個文件下有有些官方的例子,感興趣的可以看看,然後設置好unity支持.Net4.x,然後再把下載下來的ml-agents文件包中的config文件下的trainer_config.yaml文件導入unity的Assets根目錄,這些都做完後,unity項目的文件列表應該像這樣。

                                                                      

 

二.上面都做完後且沒有問題後我們繼續,我們先來搭建一個簡單的場景 ,思路我們訓練一個簡單的小球自動尋找方塊的AI

1.首先建一個Plane的GameObject,改名叫Floor,座標,旋轉清零,縮放爲1

2.建一個Cube的GameObejct,改名叫Target,座標(3,0.5,3),旋轉清零,縮放爲1

3.建一個Sphere的GameObject,改名叫RollerAgent,座標(0,0.5,0),旋轉清零,縮放爲1,這個遊戲物體作爲掛載我們AI腳本的遊戲物體,並掛載Rigidbody

4.建一個空物體,名字叫TrainingArea,座標,旋轉清零,縮放爲1,作爲以上3個物體的服務體,把三面3個物體拖到它下面

 

三,基本環境搭建完成,下面我們開始講代碼部分。

1.新建一個叫RollerAgent的腳本,掛在RollerAgent的GameObject上。

2.編輯腳本

     (1)在編輯器中,添加using MLAgents;語句,然後將基類從更改MonoBehaviourAgent

     (2)刪除該Update()方法,但是我們將使用該Start()函數,因此暫時不要使用它。如圖所示

                                        

    (3) 初始化和重置代理,思路爲當Agent達到其目標時,它將標記爲已完成,並且其Agent重置功能會將目標移動到隨機位  置。此外,如果Agent從平臺上滑落,重置功能會將其放回地板上。代碼如下

using System.Collections.Generic;
using MLAgents;
using UnityEngine;

/// <summary>
/// 個人AI訓練測試1
/// </summary>
public class RollerAgent : Agent {
    
    Rigidbody rigidbody;
    
    void Start () {
        rigidbody = transform.GetComponent<Rigidbody>();
    }


    public Transform target;
    /// <summary>
    ///重構AI重置訓練時的方法
    /// </summary>
    public override void AgentReset()
    {   
        //重置AI的位置和剛體的速度
        if(transform.localPosition.y < 0)
        {
            rigidbody.angularVelocity = Vector3.zero;
            rigidbody.velocity = Vector3.zero;
            transform.localPosition = new Vector3(0f,0.5f,0f);
        }

        //隨機設置AI目標的位置
        target.localPosition = new Vector3(Random.value * 8 - 4,0.5f,Random.value * 8 -4);
    }
}

     (4)接下來,讓我們實現該Agent.CollectObservations()方法。重構這個方法的意義在於收集我們需要的數據來輔助AI訓練。在我們訓練的這個模型中需要收集以下重要信息:1.AI自己的位置  2.目標的位置,3.AI自己在XZ平面上的速度(x軸上的速度,z軸上的速度),代碼如下

    /// <summary>
    /// 收集AI訓練時的數據,用作訓練參考的數據
    /// </summary>
    public override void CollectObservations()
    {
        /*需收集以下參考量(基本)
        1.目標的位置
        2.自己的位置
        3.自己的剛體的角速度和速度
        */

        AddVectorObs(target.localPosition);
        AddVectorObs(transform.localPosition);

        AddVectorObs(rigidbody.velocity.x);
        AddVectorObs(rigidbody.velocity.z);


    }

      (5)最後一部分是實現AI的具體動作和獲得的相關獎勵,1.實現Agent.AgentAction()方法,該方法從AI接收決策並分配獎勵。 傳遞給AgentAction()函數的數組的形式出現 ,此數組中元素的數量由Vector Action Space TypeSpace Size設置確定,等下再具體講述,而我們要訓練的這個AI只需要兩個控制信號,所以Space Size = 2,第一個元素action[0]確定沿x軸施加的力;第二個元素確定沿z軸施加的力。action[1]確定沿z軸施加的力。(如果我們允許Agent在三個維度上移動,則需要設置Vector Action Size到3。),注意的是AI確實不知道數組中的值是什麼意思。訓練過程只是根據觀察輸入調整動作值,然後查看其結果是什麼樣的獎勵。2.實現獎勵,強化學習需要獎勵。在AgentAction() 功能中分配獎勵。學習算法使用在模擬和學習過程中分配給Agent的獎勵來確定它是否正在爲Agent提供最佳行動。獎勵完成分配的任務。在這種情況下,代理達到目標多維數據集可獲得1.0的獎勵。我們的AI計算距離以檢測到達目標的距離。完成後,代碼將調用Agent.SetReward()方法以分配1.0的報酬,並通過Done()在代理上調用方法將代理標記爲完成。代碼如下

    //設置給AI完成目標時的獎勵分配
    public float speed = 10f;
    public override void AgentAction(float[] vectorAction)
    { 
        Vector3 controlSingal = Vector3.zero;
        controlSingal.x = vectorAction[0];
        controlSingal.z = vectorAction[1];
        rigidbody.AddForce(controlSingal * speed);

        //獎勵
        float distanceToTarget = 
             Vector3.Distance(transform.localPosition,target.localPosition);

        //到達目標
        if(distanceToTarget < 1.42f)
        {
            //設置獎勵,標記方法完成
            SetReward(1.0f);
            Done();
        }

        //自己落下平臺,重置
        if(transform.localPosition.y < 0)
        {
            Done();
        }
    }

   四,代碼部分已經完成,那麼接下來先回到unity,我們需要在掛載AI腳本的GameObject上掛載  BehaviorParameters  腳本,搜索添加即可。然後按照如圖所示配置

                                                  

     五,環境測試,可以重載Heuristic方法來實現手動控制,代碼如下

        

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

好了,現在我們已經完成基本代碼配置,全部代碼如下

using System.Collections.Generic;
using MLAgents;
using UnityEngine;

/// <summary>
/// 個人AI訓練測試1
/// </summary>
public class RollerAgent : Agent {
    
    Rigidbody rigidbody;
    
    void Start () {
        rigidbody = transform.GetComponent<Rigidbody>();
    }


    public Transform target;
    /// <summary>
    ///重構AI重置訓練時的方法
    /// </summary>
    public override void AgentReset()
    {   
        //重置AI的位置和剛體的速度
        if(transform.localPosition.y < 0)
        {
            rigidbody.angularVelocity = Vector3.zero;
            rigidbody.velocity = Vector3.zero;
            transform.localPosition = new Vector3(0f,0.5f,0f);
        }

        //隨機設置AI目標的位置
        target.localPosition = new Vector3(Random.value * 8 - 4,0.5f,Random.value * 8 -4);
    }

    /// <summary>
    /// 收集AI訓練時的數據,用作訓練參考的數據
    /// </summary>
    public override void CollectObservations()
    {
        /*需收集以下參考量(基本)
        1.目標的位置
        2.自己的位置
        3.自己的剛體的角速度和速度
        */

        AddVectorObs(target.localPosition);
        AddVectorObs(transform.localPosition);

        AddVectorObs(rigidbody.velocity.x);
        AddVectorObs(rigidbody.velocity.z);


    }

    //設置給AI完成目標時的獎勵分配
    public float speed = 10f;
    public override void AgentAction(float[] vectorAction)
    { 
        Vector3 controlSingal = Vector3.zero;
        controlSingal.x = vectorAction[0];
        controlSingal.z = vectorAction[1];
        rigidbody.AddForce(controlSingal * speed);

        //獎勵
        float distanceToTarget = Vector3.Distance(transform.localPosition,target.localPosition);

        //到達目標
        if(distanceToTarget < 1.42f)
        {
            //設置獎勵,標記方法完成
            SetReward(1.0f);
            Done();
        }

        //自己落下平臺,重置
        if(transform.localPosition.y < 0)
        {
            Done();
        }
    }


    // 手動操作方法
    public override float[] Heuristic()
    {
        var action = new float[2];
        action[0] = Input.GetAxis("Horizontal");
        action[1] = Input.GetAxis("Vertical");
        return action;
    }

}

  六,現在修改trainer_config.yaml配置文件裏的訓練的配置信息,你可以使用裏面原有的配置,複製下來修改下就行,不過需要注意以下 

用於訓練的超參數在傳遞給mlagents-learn程序的配置文件中指定。使用原始ml-agents/config/trainer_config.yaml文件中指定的默認設置,RollerAgent大約需要進行300,000步訓練。但是,您可以更改以下超參數以顯着加快訓練速度(達到20,000步以下):

batch_size:10 
buffer_size:100

由於此示例創建了一個非常簡單的訓練環境,僅包含少量輸入和輸出,因此使用較小的批處理和緩衝區大小可大大加快訓練速度。但是,如果您增加了環境的複雜性或更改了獎勵或觀察功能,則可能還會發現使用不同的超參數值可以更好地進行訓練。

 配置如下

RollerBallBrain:
    normalize: true
    batch_size: 10
    buffer_size: 100

    現在在控制檯裏輸入mlagents-learn trainer_config.yaml --run-id=RollerBall-1 --train,即可開始訓練,看到控制檯中的提示啓動unity的Play按鈕就可,當訓練完成時,控制檯中出現Saved Model的提示,表示模型訓練完成,你按Ctrl + C就可以中斷訓練,模型保存在models文件下,把自己的模型拖入腳本中就可以看到訓練的結果,如圖

                                                 

 

 七.批量訓練,先把前面的TrainingArea遊戲物體拖成預製體,然後複製多個後,控制檯輸入訓練命令後,再根據提示啓動unity就行了。

 

好了,以上就是目前的進度,後面會訓練更加複雜的AI,敬請期待!!!

 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章