在前面配置好開發環境和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;
語句,然後將基類從更改MonoBehaviour
爲Agent
。
(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 Type
和Space 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,敬請期待!!!