前一週忙着公司的考試,都沒有怎麼學新的,今天補上~
以後的記錄,我準備先只研究官方的示例,主要是把研究過程當中的疑惑和想法記下來。首先我先補充一下如何利用GPU進行訓練,結合(一)中的安裝方法,須要CUDA v10.0,cuDNN v7.6.5 for CUDA v10.0,對應Tensorflow的版本是2.0.1。c#
前置工做在文章(一)中都有,原先的環境能夠保留。如今能夠拉一個新的ml-agents源碼,而後修改ml-agents
文件下的setup.py
中以下圖:數組
原來是"tensorflow>=1.7,<2.1"
,如今修改成"tensorflow-gpu>=1.7,<2.1"
,而後再在Anaconda中新建一個環境,以下:dom
建好後在命令行中從新安裝環境(別忘記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
,以下圖:翻譯
配置好後,在Unity對應的Agent腳本上,也須要將Inference Device
勾選爲GPU
,而後按之前的方法開始訓練,就能夠了。3d
官方示例中,3Dball是一個比較簡單的例子,主要運用了reinforcement learning(強化學習)。就是小球在平臺上,萌版平臺要控制本身繞x、z軸旋轉,從而保持小球在本身頭上不掉下來。code
現根據官方文檔翻譯一下:orm
設置:一個平衡球任務,agent須要保持小球在其腦殼上的平衡
目標:Agent必須儘量長時間地保持球在頭頂的平衡
Agent設置:環境中包含12個想同類型的agent,所有使用一樣的行爲參數
Agent獎勵設置:
小球每一步保持在方塊頭頂上就獎勵+0.1
若是小球掉落,懲罰-0.1
行爲參數
Continuous
,Size
爲2,分別控制繞x軸旋轉、繞z軸旋轉Float屬性:三個
基準平均獎勵:100
OK,上面是借鑑官方文檔,隨意翻譯了一下,大概能夠了解3DBall主要用途和一些主要參數,裏面的Float屬性我這裏不是很明白,在代碼中是用在Agent.InitializeAgent()
中的SetResetParameters()
,這個方法顧名思義應該是對Agent進行初始化的操做。也許在這裏,咱們能夠任意修改小球的比例、質量、重力加速度來改變小球在不一樣的狀況下,訓練的效果如何吧。
看到目前爲止,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的區別就在於這裏少了小球剛體速度的收集,從而致使前者在其餘設置都相同的狀況下,訓練效果不佳,以下圖。
能夠看到平臺的抖動很大,就是由於沒有考慮到小球的速度影響而致使訓練結果天差地別,所以在用ML-Agents的時候,須要嚴謹的考慮環境的觀測項,可能因爲一個觀測項的增長或刪除,就致使最終學習結果的好壞,這裏我也是慢慢才學習,這就是我爲何要先研究官方的示例,到時候最壞也能夠照貓畫虎。
這裏是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。
紅色的是不加if條件的,藍色的是官方加if的。其實從數據來看,大的趨勢都差很少,不過我從訓練現象來看,確實官方加if以後訓練過程比較穩定。
後面的獎勵代碼中,有三個條件判斷小球應該受到懲罰。
(ball.transform.position.y - gameObject.transform.position.y) < -2f
小球與平臺y方向上的差值小於2,以下圖:
這裏能夠看出是小球掉落到平臺下邊,其實大多數狀況是其餘兩種狀況。
Mathf.Abs(ball.transform.position.x - gameObject.transform.position.x) > 3f
和Mathf.Abs(ball.transform.position.z - gameObject.transform.position.z) > 3f
這兩種放一塊兒將,先來看看小球的位置:
此時小球的x,z值都是3,能夠看出小球恰好在x軸方向或者z方向滾出了平臺邊緣。
因此,上面三種狀況只要發生一種就對小球Agent作出-1懲罰,同時調用Done()
。
復位就比較簡單了,來看代碼:
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(); }
這裏的代碼比較簡單,註釋能看明白便可。
這裏主要是當訓練模式爲Heuristic Only
時調用,具體設置以下:
代碼以下:
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.對於不遵照此聲明或者其餘違法使用本文內容者,本人依法保留追究權等。