ML-Agents(三)3DBall例子

ML-Agents(三)3DBall例子

前一週忙着公司的考試,都沒有怎麼學新的,今天補上~
以後的記錄,我準備先只研究官方的示例,主要是把研究過程當中的疑惑和想法記下來。首先我先補充一下如何利用GPU進行訓練,結合(一)中的安裝方法,須要CUDA v10.0,cuDNN v7.6.5 for CUDA v10.0,對應Tensorflow的版本是2.0.1。c#

1、利用GPU進行訓練

前置工做在文章(一)中都有,原先的環境能夠保留。如今能夠拉一個新的ml-agents源碼,而後修改ml-agents文件下的setup.py中以下圖:數組

image-20200319233335183

原來是"tensorflow>=1.7,<2.1",如今修改成"tensorflow-gpu>=1.7,<2.1",而後再在Anaconda中新建一個環境,以下:dom

image-20200319234037666

建好後在命令行中從新安裝環境(別忘記cd到新的ml-agents源碼),分別輸入:ide

pip install -e ml-agents-envs -i http://pypi.douban.com/simple/ --trusted-host pypi.douban.com學習

pip install -e ml-agents -i http://pypi.douban.com/simple/ --trusted-host pypi.douban.com命令行

就是分別安裝兩個環境,能夠發現他會自動下載tensorflow_gpu-2.0.1,以下圖:翻譯

GPU

配置好後,在Unity對應的Agent腳本上,也須要將Inference Device勾選爲GPU,而後按之前的方法開始訓練,就能夠了。3d

image-20200319233940196

2、3DBall

官方示例中,3Dball是一個比較簡單的例子,主要運用了reinforcement learning(強化學習)。就是小球在平臺上,萌版平臺要控制本身繞x、z軸旋轉,從而保持小球在本身頭上不掉下來。code

3dBall

現根據官方文檔翻譯一下:orm

  • 設置:一個平衡球任務,agent須要保持小球在其腦殼上的平衡

  • 目標:Agent必須儘量長時間地保持球在頭頂的平衡

  • Agent設置:環境中包含12個想同類型的agent,所有使用一樣的行爲參數

  • Agent獎勵設置:

    • 小球每一步保持在方塊頭頂上就獎勵+0.1

    • 若是小球掉落,懲罰-0.1

  • 行爲參數

    • 矢量觀察空間:8個變量,包括agent方塊的旋轉角度(兩個值,x、z軸方向),球和方塊之間的相對位置關係(Vector3),球上剛體的速度(Vector3)
    • 矢量動做空間:類型爲ContinuousSize爲2,分別控制繞x軸旋轉、繞z軸旋轉
  • Float屬性:三個

    • scale(比例):小球的比例,默認爲1,推薦最小值爲0.2,最大值爲5
    • gravity(重力):重力加速度,默認爲9.81,推薦最小值4,最大值爲105
    • mass(質量):小球的質量,默認爲1,推薦最小值爲0.1,最大值爲20
  • 基準平均獎勵:100

OK,上面是借鑑官方文檔,隨意翻譯了一下,大概能夠了解3DBall主要用途和一些主要參數,裏面的Float屬性我這裏不是很明白,在代碼中是用在Agent.InitializeAgent()中的SetResetParameters(),這個方法顧名思義應該是對Agent進行初始化的操做。也許在這裏,咱們能夠任意修改小球的比例、質量、重力加速度來改變小球在不一樣的狀況下,訓練的效果如何吧。

3DBall代碼分析

看到目前爲止,ml-agents其中的精華就在agent的腳本如何設置了,咱們下面來分析一下Ball3DAgent代碼。

初始化

public class Ball3DAgent : Agent
{
    [Header("Specific to Ball3D")]
    public GameObject ball;
    Rigidbody m_BallRb;
    IFloatProperties m_ResetParams;

    public override void InitializeAgent()
    {
        m_BallRb = ball.GetComponent<Rigidbody>();
        m_ResetParams = Academy.Instance.FloatProperties;
        SetResetParameters();
    }

    public void SetBall()
    {
        //從Academy中獲取小球的屬性(質量、比例)
        m_BallRb.mass = m_ResetParams.GetPropertyWithDefault("mass", 1.0f);
        var scale = m_ResetParams.GetPropertyWithDefault("scale", 1.0f);
        ball.transform.localScale = new Vector3(scale, scale, scale);
    }

    public void SetResetParameters()
    {
        SetBall();
    }
}

這裏初始化應用了InitializeAgent()方法,這裏獲取了小球的剛體,而且利用SetBall()來設置了小球的質量和比例,這裏的的m_ResetParams變量是Academy的FloatProperties變量,這裏的變量好像是會做爲環境參數傳遞給Python,具體的用途我也還沒研究清楚,姑且先看作是初始化小球的屬性。

環境觀察值

直接上源碼。

public override void CollectObservations(VectorSensor sensor)
{
    //平臺繞Z軸旋轉值
    sensor.AddObservation(gameObject.transform.rotation.z);
    //平臺繞X軸旋轉值
    sensor.AddObservation(gameObject.transform.rotation.x);
    //小球與平臺的相對位置
    sensor.AddObservation(ball.transform.position -gameObject.transform.position);
    //小球剛體的速度
    sensor.AddObservation(m_BallRb.velocity);
}

以上一共運用了8個觀察值,注意Vector3類型的變量算是3個觀察值(x,y,z)。

Ball3DHardAgent項目裏,與Ball3DAgent的區別就在於這裏少了小球剛體速度的收集,從而致使前者在其餘設置都相同的狀況下,訓練效果不佳,以下圖。

3dHardBall

能夠看到平臺的抖動很大,就是由於沒有考慮到小球的速度影響而致使訓練結果天差地別,所以在用ML-Agents的時候,須要嚴謹的考慮環境的觀測項,可能因爲一個觀測項的增長或刪除,就致使最終學習結果的好壞,這裏我也是慢慢才學習,這就是我爲何要先研究官方的示例,到時候最壞也能夠照貓畫虎。

Agent動做反饋

這裏是Agent的核心實現,觀測值經過Agent收集到Brain處,Brain再經過外部Python訓練環境反饋動做,再沿相同的路線返回到Agent的AgentAction(float[] vectorAction)上(這裏不知道個人想法對不對),具體的代碼以下。

public override void AgentAction(float[] vectorAction)
{
    //控制平臺繞Z軸、X軸旋轉的值
    //用Mathf.Clamp()將響應的動做值限制到-2到2
    var actionZ = 2f * Mathf.Clamp(vectorAction[0], -1f, 1f);
    var actionX = 2f * Mathf.Clamp(vectorAction[1], -1f, 1f);

    //平臺繞Z軸旋轉響應
    if ((gameObject.transform.rotation.z < 0.25f && actionZ > 0f) ||
            (gameObject.transform.rotation.z > -0.25f && actionZ < 0f))
    {
        gameObject.transform.Rotate(new Vector3(0, 0, 1), actionZ);
    }
	//平臺繞X軸旋轉響應
	if ((gameObject.transform.rotation.x < 0.25f && actionX > 0f) ||
            (gameObject.transform.rotation.x > -0.25f && actionX < 0f))
    {
        gameObject.transform.Rotate(new Vector3(1, 0, 0), actionX);
    }
    //gameObject.transform.Rotate(new Vector3(0, 0, 1), actionZ);
    //gameObject.transform.Rotate(new Vector3(1, 0, 0), actionX);
    
    //當小球在平臺上,掉落或飛出平臺,分別進行獎勵或懲罰
    if ((ball.transform.position.y - gameObject.transform.position.y) < -2f ||
        Mathf.Abs(ball.transform.position.x - gameObject.transform.position.x) > 3f ||
        Mathf.Abs(ball.transform.position.z - gameObject.transform.position.z) > 3f)
    {
        SetReward(-1f);//懲罰1
        Done();//這次訓練結束並從新開始,會調用AgentReset()
    }
    else
    {
        SetReward(0.1f);//在平臺上的時候,每次動做都獎勵0.1
    }
}

首先是平臺對於旋轉的響應,我又將兩個if的條件去掉訓練了一下,發現平臺訓練過程當中比較不穩,抖動較大,由於只要一來值就讓平臺旋轉,可能這裏會形成平臺一直在調整姿態的過程當中,而源代碼中,以繞Z軸爲例,只有在平臺Z軸旋轉值<0.25f且actionZ>0、或平臺Z軸旋轉值>0.25f且actionZ<0時纔對平臺的姿態進行動做,這樣就至關於設置了一個緩衝區間,不會讓平臺不停調整姿態,而是根據小球狀況來適當調整姿態。

這裏附上兩次訓練的tensorboard。

image-20200329000940392

紅色的是不加if條件的,藍色的是官方加if的。其實從數據來看,大的趨勢都差很少,不過我從訓練現象來看,確實官方加if以後訓練過程比較穩定。

後面的獎勵代碼中,有三個條件判斷小球應該受到懲罰。

  • (ball.transform.position.y - gameObject.transform.position.y) < -2f

    小球與平臺y方向上的差值小於2,以下圖:

    image-20200329001534471

    這裏能夠看出是小球掉落到平臺下邊,其實大多數狀況是其餘兩種狀況。

  • Mathf.Abs(ball.transform.position.x - gameObject.transform.position.x) > 3f

    和Mathf.Abs(ball.transform.position.z - gameObject.transform.position.z) > 3f

    這兩種放一塊兒將,先來看看小球的位置:

    image-20200329001749169

    此時小球的x,z值都是3,能夠看出小球恰好在x軸方向或者z方向滾出了平臺邊緣。

因此,上面三種狀況只要發生一種就對小球Agent作出-1懲罰,同時調用Done()

Agent復位

復位就比較簡單了,來看代碼:

public override void AgentReset()
{
	//復位平臺旋轉角度
    gameObject.transform.rotation = new Quaternion(0f, 0f, 0f, 0f);
    //令平臺隨機繞x軸旋轉-10~10度
    gameObject.transform.Rotate(new Vector3(1, 0, 0), Random.Range(-10f, 10f));
    //令平臺隨機繞z軸旋轉-10~10度
    gameObject.transform.Rotate(new Vector3(0, 0, 1), Random.Range(-10f, 10f));
    //小球剛體速度變爲0
    m_BallRb.velocity = new Vector3(0f, 0f, 0f);
    //小球在y(相對平臺高度)爲4的地方,同時隨機x、z值出現
    ball.transform.position = new Vector3(Random.Range(-1.5f, 1.5f), 4f, Random.Range(-1.5f, 1.5f))
        + gameObject.transform.position;
    //Agent重置時,同時重置參數,這裏是指小球的質量和比例,其實我以爲這裏不必,估計以後別的項目有用
    SetResetParameters();
}

這裏的代碼比較簡單,註釋能看明白便可。

Agent手動設置

這裏主要是當訓練模式爲Heuristic Only時調用,具體設置以下:

image-20200329002653210

代碼以下:

public override float[] Heuristic()
{
    var action = new float[2];

    action[0] = -Input.GetAxis("Horizontal");
    action[1] = Input.GetAxis("Vertical");
    return action;
}

這裏的代碼至關於咱們輸入來控制動做向量空間的值,其實就是action[]數組,咱們令action[0]控制平臺繞x軸的旋轉,action[1]控制平臺繞z軸的旋轉。

能夠試一下,其實要保持小球在平臺上還有點難度。

至此第一個例子就研究到這,有什麼問題歡迎你們一塊兒探討。

寫文不易~所以作如下申明:

1.博客中標註原創的文章,版權歸原做者 煦陽(本博博主) 全部;

2.未經原做者容許不得轉載本文內容,不然將視爲侵權;

3.轉載或者引用本文內容請註明來源及原做者;

4.對於不遵照此聲明或者其餘違法使用本文內容者,本人依法保留追究權等。

相關文章
相關標籤/搜索