戰(zhàn):從零構(gòu)建強(qiáng)化學(xué)習(xí)驅(qū)動的游戲AI)
1. 項(xiàng)目概述當(dāng)游戲角色開始“自學(xué)成才”如果你還在用一長串的if-else或者復(fù)雜的狀態(tài)機(jī)來驅(qū)動你的NPC是時候換個思路了。想象一下你設(shè)計(jì)的敵人不再只是按照預(yù)設(shè)的路徑巡邏而是會觀察你的走位預(yù)判你的攻擊甚至學(xué)會利用地形進(jìn)行伏擊你訓(xùn)練的寵物不再只會執(zhí)行幾個固定的指令而是能根據(jù)環(huán)境和你互動的歷史發(fā)展出獨(dú)特的“性格”和行為模式。這聽起來像是遙遠(yuǎn)的未來不這就是 Unity ML-Agents 工具箱正在讓開發(fā)者觸手可及的現(xiàn)實(shí)。ML-Agents 本質(zhì)上是一個橋梁它將游戲開發(fā)世界與機(jī)器學(xué)習(xí)特別是強(qiáng)化學(xué)習(xí)世界連接了起來。它把 Unity 編輯器變成了一個功能強(qiáng)大的“虛擬生物實(shí)驗(yàn)室”而你就是那個設(shè)定進(jìn)化規(guī)則的設(shè)計(jì)師。你不再需要手把手地教角色每一個動作而是通過定義“獎勵”和“懲罰”讓角色在虛擬環(huán)境中通過數(shù)百萬次的試錯自己找到達(dá)成目標(biāo)的最優(yōu)策略。這個過程我們稱之為“訓(xùn)練”。訓(xùn)練完成后你會得到一個神經(jīng)網(wǎng)絡(luò)模型一個.nn文件這就是角色的“大腦”。把這個大腦裝回你的游戲一個能自主“思考”的智能體就誕生了。這個工具箱的價值遠(yuǎn)不止于讓方塊學(xué)會走路。它適用于任何需要復(fù)雜決策、適應(yīng)性行為或玩家-like AI 的場景從 RTS 游戲中的單位微操到開放世界 NPC 的擬真反應(yīng)再到解謎游戲中能自適應(yīng)玩家策略的對手。它降低了機(jī)器學(xué)習(xí)的門檻讓你能用熟悉的 Unity 工作流創(chuàng)造出真正擁有“學(xué)習(xí)能力”的游戲內(nèi)容。2. 核心原理拆解獎勵驅(qū)動的試錯學(xué)習(xí)要玩轉(zhuǎn) ML-Agents你必須理解其核心——強(qiáng)化學(xué)習(xí)。你可以把它想象成訓(xùn)練一只小狗。小狗不知道“握手”是什么但你可以在它抬起爪子時給它一塊零食正向獎勵在其他時候不給或給予輕微懲罰。經(jīng)過多次重復(fù)小狗就把“抬爪”和“獲得零食”聯(lián)系了起來。ML-Agents 中的智能體Agent就是這只“小狗”而你就是那個手握零食的訓(xùn)練師。2.1 強(qiáng)化學(xué)習(xí)的關(guān)鍵要素在這個框架里有幾個核心概念構(gòu)成了智能體與環(huán)境的交互循環(huán)智能體 (Agent)你需要訓(xùn)練的對象即游戲中的角色。它身上掛載著繼承自Agent基類的腳本。環(huán)境 (Environment)你的 Unity 場景。它包含了地面、障礙物、目標(biāo)等一切外部元素。狀態(tài)/觀察 (State/Observation)智能體感知環(huán)境的方式。在 ML-Agents 中你通過CollectObservations方法將環(huán)境信息如自身位置、目標(biāo)位置、生命值、敵人距離等轉(zhuǎn)化為一組數(shù)字向量輸入給神經(jīng)網(wǎng)絡(luò)。這是智能體的“眼睛”和“耳朵”。動作 (Action)智能體可以做的事情。在OnActionReceived方法中你將神經(jīng)網(wǎng)絡(luò)輸出的數(shù)字例如一個代表“向前移動力”的 -1 到 1 的值轉(zhuǎn)化為實(shí)際的行為如給剛體施加一個力。動作可以是連續(xù)的如轉(zhuǎn)向角度也可以是離散的如跳躍、下蹲、開槍。獎勵 (Reward)驅(qū)動學(xué)習(xí)的核心。你需要在代碼中 strategically 地調(diào)用AddReward()函數(shù)。獎勵信號告訴智能體“剛才那一步做得好不好”。達(dá)成目標(biāo)給一個大額正獎勵10犯錯給一個懲罰-1甚至為了鼓勵效率每一步都可以給一個微小的負(fù)獎勵-0.001以激勵其盡快完成任務(wù)。策略 (Policy)即神經(jīng)網(wǎng)絡(luò)模型。它根據(jù)當(dāng)前的“觀察”決定采取哪個“動作”以最大化未來累積的獎勵期望。訓(xùn)練的過程就是不斷優(yōu)化這個策略的過程。2.2 訓(xùn)練流程PPO 算法與課程學(xué)習(xí)ML-Agents 默認(rèn)使用 PPO近端策略優(yōu)化算法這是一種非常穩(wěn)健的強(qiáng)化學(xué)習(xí)算法。你可以把它理解為一個既鼓勵探索嘗試新動作又防止“學(xué)壞”動作變得太隨機(jī)的教練。在后臺Unity 會啟動一個 Python 進(jìn)程運(yùn)行訓(xùn)練算法而你的 Unity 編輯器則作為“環(huán)境模擬器”在運(yùn)行。更強(qiáng)大的是課程學(xué)習(xí) (Curriculum Learning)功能。就像教小孩先學(xué)爬再學(xué)走一樣你可以把復(fù)雜任務(wù)分解成多個階段。在配置文件中你可以定義當(dāng)智能體在簡單環(huán)境如無障礙中的成功率超過 90% 后自動切換到更難的環(huán)境如加入移動障礙。這能極大地解決稀疏獎勵問題即智能體在成功前幾乎得不到任何有效反饋導(dǎo)致它無從學(xué)起是訓(xùn)練復(fù)雜行為的利器。注意獎勵函數(shù)的設(shè)計(jì)是整個項(xiàng)目成敗的關(guān)鍵也是最容易“踩坑”的地方。一個設(shè)計(jì)不當(dāng)?shù)莫剟詈瘮?shù)會導(dǎo)致智能體學(xué)會各種意想不到的“作弊”行為。例如如果你的懲罰是“每存活一秒扣 0.1 分”而“到達(dá)終點(diǎn)加 100 分”智能體可能會發(fā)現(xiàn)與其冒險沖向終點(diǎn)不如找個角落躲起來“茍活”因?yàn)榭鄯炙俣群苈?。這被稱為“獎勵黑客”。3. 環(huán)境搭建與項(xiàng)目初始化實(shí)戰(zhàn)理論說再多不如動手搭一個。我們從零開始構(gòu)建一個經(jīng)典案例訓(xùn)練一個立方體 Agent 找到場景中隨機(jī)位置的目標(biāo)球。3.1 基礎(chǔ)環(huán)境配置首先確保你有一個較新版本的 Unity Hub 和 Unity Editor推薦 2021 LTS 或更新版本。新建一個 3D 項(xiàng)目命名為MLAgents_Playground。安裝 ML-Agents 包是第一步。打開Window - Package Manager。點(diǎn)擊左上角的號選擇Add package from git URL...。輸入官方包地址com.unity.ml-agents。點(diǎn)擊AddUnity 會自動下載并安裝。這個過程可能會花費(fèi)幾分鐘取決于你的網(wǎng)絡(luò)。安裝完成后強(qiáng)烈建議導(dǎo)入示例項(xiàng)目。在 Package Manager 中找到已安裝的ML-Agents包在詳情頁切換到Samples選項(xiàng)卡點(diǎn)擊Import按鈕導(dǎo)入Getting Started示例。這里面包含了多個預(yù)制場景和腳本是極佳的學(xué)習(xí)參考能幫你省去大量搭建基礎(chǔ)組件的時間。3.2 構(gòu)建第一個訓(xùn)練場景現(xiàn)在讓我們搭建一個最簡單的訓(xùn)練場創(chuàng)建地面在 Hierarchy 窗口右鍵 -3D Object - Plane重命名為Ground縮放至合適大小如 Scale 設(shè)為 10, 1, 10。創(chuàng)建智能體右鍵 -3D Object - Cube重命名為Agent。將其 Y 軸位置設(shè)為 0.5使其剛好立在地面上。創(chuàng)建目標(biāo)右鍵 -3D Object - Sphere重命名為Target。將其放置在離 Agent 一段距離的位置如 X5, Y0.5, Z5。添加物理與標(biāo)簽選中Agent點(diǎn)擊Add Component添加Rigidbody剛體。為了簡化初期訓(xùn)練可以暫時取消勾選Use Gravity避免它因摔倒而增加學(xué)習(xí)難度。確保Agent有Box Collider。選中Target確保其有Sphere Collider并勾選Is Trigger這樣 Agent 可以穿過它并觸發(fā)事件。在Target的 Tag 下拉列表中點(diǎn)擊Add Tag...新建一個名為Target的標(biāo)簽并賦予給Target物體??蛇x創(chuàng)建訓(xùn)練邊界復(fù)制幾個Cube縮放成圍墻擺放在Ground邊緣防止 Agent 在訓(xùn)練初期跑出視野。為它們創(chuàng)建一個新 Tag如Wall。至此一個最基礎(chǔ)的訓(xùn)練環(huán)境就搭建好了。接下來我們要賦予 Agent “靈魂”。4. 編寫智能體腳本定義觀察、動作與獎勵在 Project 窗口右鍵 -Create - C# Script命名為MoveToTargetAgent。雙擊打開我們將逐步實(shí)現(xiàn)一個完整 Agent。4.1 腳本骨架與初始化using UnityEngine; using Unity.MLAgents; using Unity.MLAgents.Sensors; using Unity.MLAgents.Actuators; public class MoveToTargetAgent : Agent // 必須繼承自 Agent 類 { // 關(guān)鍵引用 public Transform targetTransform; // 在 Inspector 中拖拽賦值 private Rigidbody agentRigidbody; // 初始化類似于 Start() public override void Initialize() { agentRigidbody GetComponentRigidbody(); // 確保剛體存在如果忘記添加這里可以自動添加 if (agentRigidbody null) { agentRigidbody gameObject.AddComponentRigidbody(); agentRigidbody.useGravity false; // 按需設(shè)置 } } }4.2 定義觀察告訴大腦“世界是什么樣子”CollectObservations方法負(fù)責(zé)收集環(huán)境信息。我們決定讓 Agent 知道三件事自己在哪、目標(biāo)在哪、自己跑得多快。public override void CollectObservations(VectorSensor sensor) { // 觀察1: Agent自身的位置 (3個浮點(diǎn)數(shù): x, y, z) sensor.AddObservation(transform.localPosition); // 觀察2: 目標(biāo)點(diǎn)的位置 (3個浮點(diǎn)數(shù)) sensor.AddObservation(targetTransform.localPosition); // 觀察3: Agent當(dāng)前的速度 (3個浮點(diǎn)數(shù)) sensor.AddObservation(agentRigidbody.velocity); // 總觀察值數(shù)量 3 3 3 9 // 這個數(shù)字必須與 Behavior Parameters 組件中的 Vector Observation Space Size 嚴(yán)格一致 }為什么是這些觀察值位置信息是導(dǎo)航的基礎(chǔ)。速度信息則至關(guān)重要它讓 Agent 能感知自己的運(yùn)動狀態(tài)是靜止、加速還是減速沒有速度信息Agent 很難學(xué)會平穩(wěn)地啟動和停止容易產(chǎn)生振蕩。4.3 定義動作大腦決策后“該怎么做”O(jiān)nActionReceived是執(zhí)行指令的地方。我們假設(shè)大腦輸出兩個連續(xù)值分別控制 X 軸和 Z 軸的力。public override void OnActionReceived(ActionBuffers actions) { // 從大腦的輸出緩沖區(qū)獲取連續(xù)動作 float moveX actions.ContinuousActions[0]; // 范圍通常在 [-1, 1] float moveZ actions.ContinuousActions[1]; // 將輸出值轉(zhuǎn)換為力。系數(shù) 5f 需要根據(jù)你的 Agent 質(zhì)量和場景大小調(diào)整 Vector3 controlSignal new Vector3(moveX, 0, moveZ); Vector3 force controlSignal * 5f; // 使用 VelocityChange 力模式忽略質(zhì)量使控制更直接 agentRigidbody.AddForce(force, ForceMode.VelocityChange); // 基于距離的獎勵/懲罰設(shè)計(jì) float distanceToTarget Vector3.Distance(transform.localPosition, targetTransform.localPosition); // 核心獎勵1每一步的小懲罰鼓勵快速完成任務(wù)時間懲罰 AddReward(-0.001f); // 核心獎勵2越靠近目標(biāo)給予的即時獎勵越多稠密獎勵解決稀疏性問題 // 計(jì)算一個基于距離的獎勵距離越近獎勵越高 float proximityReward 0.01f * (1f / (distanceToTarget 1f)); // 防止除零 AddReward(proximityReward); }這里引入了“稠密獎勵”的概念。如果只在碰到目標(biāo)時給一個大獎勵稀疏獎勵A(yù)gent 在探索初期幾乎得不到任何正向反饋學(xué)習(xí)會非常緩慢甚至失敗。我們通過proximityReward提供了一個連續(xù)的、與距離成反比的獎勵信號像一塊磁鐵始終將 Agent 引向目標(biāo)大大加速了學(xué)習(xí)過程。4.4 處理回合與碰撞事件// 每個訓(xùn)練回合(Episode)開始時調(diào)用用于重置狀態(tài) public override void OnEpisodeBegin() { // 隨機(jī)重置Agent的位置增加訓(xùn)練的泛化能力 float randomX Random.Range(-4f, 4f); float randomZ Random.Range(-4f, 4f); transform.localPosition new Vector3(randomX, 0.5f, randomZ); // 重置物理狀態(tài) agentRigidbody.velocity Vector3.zero; agentRigidbody.angularVelocity Vector3.zero; transform.rotation Quaternion.identity; // 也可以隨機(jī)重置目標(biāo)的位置讓學(xué)習(xí)更具挑戰(zhàn)性 // targetTransform.localPosition new Vector3(Random.Range(-4f, 4f), 0.5f, Random.Range(-4f, 4f)); } // 碰撞檢測用于判斷成功或失敗 private void OnTriggerEnter(Collider other) { if (other.CompareTag(Target)) { // 成功抵達(dá)目標(biāo)給予巨額獎勵 AddReward(10.0f); // 可選播放成功音效或粒子效果 // Debug.Log(Target Reached!); EndEpisode(); // 結(jié)束本輪觸發(fā) OnEpisodeBegin } else if (other.CompareTag(Wall)) { // 撞墻了給予懲罰并結(jié)束本輪 AddReward(-2.0f); EndEpisode(); } }4.5 實(shí)現(xiàn)手動控制Heuristic用于調(diào)試這是一個極其重要但常被忽略的步驟。它讓你可以用鍵盤控制 Agent驗(yàn)證你的動作邏輯移動、轉(zhuǎn)向是否正常同時也是調(diào)試獎勵函數(shù)的絕佳工具。public override void Heuristic(in ActionBuffers actionsOut) { var continuousActions actionsOut.ContinuousActions; // 將鍵盤輸入映射到動作輸出 continuousActions[0] Input.GetAxis(Horizontal); // A/D 鍵對應(yīng) X 軸力 continuousActions[1] Input.GetAxis(Vertical); // W/S 鍵對應(yīng) Z 軸力 }5. 編輯器配置與訓(xùn)練啟動腳本寫好后回到 Unity 編輯器進(jìn)行配置。5.1 組件掛載與參數(shù)設(shè)置將MoveToTargetAgent腳本拖到Agent立方體上。在 Inspector 中將場景中的Target球體拖拽到腳本的Target Transform字段。為Agent添加Behavior Parameters組件。這是連接 Agent 腳本與 ML-Agents 訓(xùn)練后端的關(guān)鍵。Behavior Name: 填寫MoveToTarget。這個名字必須與后續(xù)配置文件中的行為名嚴(yán)格一致。Vector Observation Space Size: 填入9。這就是我們CollectObservations方法中AddObservation調(diào)用次數(shù)的總和。Actions Continuous Actions: 填入2。對應(yīng)OnActionReceived中我們期望的兩個連續(xù)動作值moveX, moveZ。Model: 暫時留空。訓(xùn)練完成后我們會把生成的.nn模型文件拖到這里。在Behavior Parameters組件下方確保Agent腳本的Use Heuristic在訓(xùn)練時是取消勾選的我們讓算法控制但在手動測試時可以勾選。5.2 編寫訓(xùn)練配置文件在項(xiàng)目根目錄與Assets同級下創(chuàng)建一個新文件夾config。在里面創(chuàng)建一個文本文件重命名為move_to_target.yaml。用文本編輯器如 VSCode打開輸入以下內(nèi)容behaviors: MoveToTarget: # 必須與 Behavior Name 完全一致 trainer_type: ppo # 使用PPO算法 hyperparameters: batch_size: 64 # 每次參數(shù)更新使用的經(jīng)驗(yàn)樣本數(shù) buffer_size: 1024 # 經(jīng)驗(yàn)回放緩沖區(qū)大小 learning_rate: 3.0e-4 # 學(xué)習(xí)率太大不穩(wěn)定太小學(xué)得慢 beta: 5.0e-4 # 熵系數(shù)鼓勵探索 epsilon: 0.2 # PPO裁剪參數(shù) lambd: 0.95 # GAE參數(shù)權(quán)衡偏差與方差 num_epoch: 3 # 每次更新時對數(shù)據(jù)進(jìn)行幾輪優(yōu)化 learning_rate_schedule: linear # 學(xué)習(xí)率隨訓(xùn)練步數(shù)線性衰減 network_settings: normalize: false # 是否歸一化輸入簡單任務(wù)可關(guān)閉 hidden_units: 128 # 神經(jīng)網(wǎng)絡(luò)隱藏層神經(jīng)元數(shù)量 num_layers: 2 # 神經(jīng)網(wǎng)絡(luò)隱藏層層數(shù) reward_signals: extrinsic: gamma: 0.99 # 折扣因子越接近1表示越重視遠(yuǎn)期獎勵 strength: 1.0 # 外部獎勵的權(quán)重 max_steps: 500000 # 最大訓(xùn)練步數(shù) time_horizon: 64 # 每個Agent收集多少步經(jīng)驗(yàn)后進(jìn)行一次更新 summary_freq: 10000 # 每多少步輸出一次訓(xùn)練摘要到TensorBoard5.3 啟動訓(xùn)練流程打開命令行終端Windows 的 CMD/PowerShellMac/Linux 的 Terminal。使用cd命令導(dǎo)航到你的 Unity 項(xiàng)目根目錄。輸入訓(xùn)練命令mlagents-learn config/move_to_target.yaml --run-idRun_01 --forcemlagents-learn: 訓(xùn)練命令。config/move_to_target.yaml: 你的配置文件路徑。--run-idRun_01: 為本次訓(xùn)練運(yùn)行指定一個名稱用于區(qū)分不同實(shí)驗(yàn)。--force: 如果同名 run-id 已存在則覆蓋。命令行會顯示Start training by pressing the Play button in the Unity Editor.。切回 Unity 編輯器點(diǎn)擊 Play 按鈕。此時場景中可能會出現(xiàn)多個 Agent 的副本取決于配置它們會同時開始探索。觀察命令行窗口你會看到獎勵Cumulative Reward等指標(biāo)在滾動。同時你可以直接在 Game 視圖中觀察 Agent 們從“無頭蒼蠅”到“精準(zhǔn)導(dǎo)航”的進(jìn)化過程。訓(xùn)練達(dá)到最大步數(shù)或你手動CtrlC停止后在項(xiàng)目根目錄下的results/Run_01文件夾中會找到生成的MoveToTarget.nn模型文件。將此.nn文件拖入 Unity 項(xiàng)目的Assets文件夾。然后選中Agent在Behavior Parameters組件的Model字段中拖入這個模型文件。取消勾選Agent腳本上的Use Heuristic再次點(diǎn)擊 Play?,F(xiàn)在你的立方體將使用訓(xùn)練好的 AI 大腦自主導(dǎo)航到目標(biāo)點(diǎn)6. 實(shí)戰(zhàn)進(jìn)階從走到跑解鎖復(fù)雜行為基礎(chǔ)移動只是開始。ML-Agents 的真正威力在于構(gòu)建復(fù)雜、智能的行為。6.1 添加視覺觀察讓 Agent “看見”世界除了向量觀察ML-Agents 支持基于攝像頭的視覺觀察。這適用于需要識別形狀、顏色或復(fù)雜空間關(guān)系的任務(wù)。給 Agent 添加一個子物體作為“眼睛”比如一個Camera。在 Agent 腳本中聲明一個CameraSensorComponent類型的公共變量并在 Inspector 中賦值。在CollectObservations中你不再需要手動添加目標(biāo)位置等神經(jīng)網(wǎng)絡(luò)會直接從攝像頭畫面中學(xué)習(xí)特征。但請注意視覺訓(xùn)練對算力要求高訓(xùn)練時間更長且需要更精細(xì)的獎勵設(shè)計(jì)。6.2 實(shí)現(xiàn)離散動作與組合動作很多游戲行為是離散的比如“跳躍”、“開槍”、“切換武器”。ML-Agents 支持離散動作空間。// 在 Behavior Parameters 中設(shè)置 Discrete Actions 分支例如定義兩個分支 // Branch 0: 3個動作 (0: 不動1: 左轉(zhuǎn)2: 右轉(zhuǎn)) // Branch 1: 2個動作 (0: 不跳1: 跳) public override void OnActionReceived(ActionBuffers actions) { // 處理離散動作 int turnAction actions.DiscreteActions[0]; // 取值 0, 1, 2 int jumpAction actions.DiscreteActions[1]; // 取值 0, 1 float turnStrength 0f; switch (turnAction) { case 1: turnStrength -1f; break; // 左轉(zhuǎn) case 2: turnStrength 1f; break; // 右轉(zhuǎn) } // 應(yīng)用轉(zhuǎn)向... if (jumpAction 1 IsGrounded()) { // 執(zhí)行跳躍 agentRigidbody.AddForce(Vector3.up * jumpForce, ForceMode.Impulse); } // 同時也可以處理連續(xù)動作如移動 float moveZ actions.ContinuousActions[0]; // ... 應(yīng)用移動 }6.3 多智能體與競爭/協(xié)作在同一個場景中放置多個具有相同Behavior Name的 Agent它們會共享同一個大腦進(jìn)行訓(xùn)練。你可以設(shè)計(jì)獎勵機(jī)制讓它們競爭如對抗游戲或協(xié)作如共同搬運(yùn)物體。競爭給擊敗對手的 Agent 正獎勵給被擊敗的 Agent 負(fù)獎勵。協(xié)作給共同完成任務(wù)的群體一個共享的大獎勵。這里需要注意“信用分配”問題即如何將群體獎勵合理地分配給個體。ML-Agents 提供了Group Reward等機(jī)制來輔助處理。6.4 利用課程學(xué)習(xí)攻克難關(guān)對于非常困難的任務(wù)直接訓(xùn)練可能無法收斂。課程學(xué)習(xí)允許你定義多個關(guān)卡逐步提升難度。behaviors: MoveToTarget: trainer_type: ppo # ... 其他超參數(shù) curriculum: - name: EasyLevel # 第一階段課程 completion_criteria: measure: reward # 以獎勵為衡量標(biāo)準(zhǔn) behavior: MoveToTarget threshold: 1.0 # 當(dāng)平均獎勵超過1.0時進(jìn)入下一階段 min_lesson_length: 1000 # 本階段至少訓(xùn)練1000步 value: 0.0 # 這個參數(shù)會傳遞給環(huán)境用于控制難度 parameters: obstacle_count: 0 # 無障礙物 target_range: 5.0 # 目標(biāo)出現(xiàn)范圍較小 - name: HardLevel completion_criteria: measure: reward behavior: MoveToTarget threshold: 5.0 min_lesson_length: 5000 value: 1.0 parameters: obstacle_count: 5 # 增加5個障礙物 target_range: 10.0 # 目標(biāo)出現(xiàn)范圍變大在你的 Agent 腳本中可以通過Academy實(shí)例讀取這些課程參數(shù)并動態(tài)調(diào)整環(huán)境如生成障礙物。7. 血淚踩坑指南與調(diào)優(yōu)心法這部分是無數(shù)小時調(diào)試換來的經(jīng)驗(yàn)?zāi)軒湍惚荛_最常見的陷阱。7.1 獎勵函數(shù)設(shè)計(jì)藝術(shù)與科學(xué)的結(jié)合坑1獎勵稀疏。Agent 在成功前得不到任何反饋。解決設(shè)計(jì)“塑形獎勵”。例如在走迷宮時不僅給最終出口獎勵還給每一步更靠近出口一個微小正獎勵???獎勵沖突。例如同時獎勵“收集金幣”和“保持高速”Agent 可能會為了高速而繞過金幣。解決仔細(xì)權(quán)衡不同獎勵的權(quán)重strength或者設(shè)計(jì)更高級的獎勵結(jié)構(gòu)如分層獎勵。坑3局部最優(yōu)與獎勵黑客。Agent 找到了一個刷分但不合你意的漏洞。例如在一個需要跳躍的平臺游戲中如果“存活”有微小正獎勵而“墜落”有大懲罰Agent 可能學(xué)會了一動不動。解決增加負(fù)獎勵懲罰要非常小心。更好的辦法是修改環(huán)境或觀察空間堵上漏洞。實(shí)操心得大量使用Heuristic模式進(jìn)行手動測試。你親自操作 Agent感受當(dāng)前的獎勵設(shè)置是否合理。你覺得別扭或不合理的地方AI 學(xué)起來也一定困難。7.2 觀察空間給大腦恰到好處的信息坑1信息不足。沒給速度Agent 學(xué)不會平穩(wěn)移動沒給相對角度Agent 學(xué)不會有效轉(zhuǎn)向。解決從第一性原理思考完成這個任務(wù)一個智能體最少需要知道哪些信息坑2信息冗余或噪聲。提供了無關(guān)信息如天空盒顏色或包含大量噪聲會干擾學(xué)習(xí)。解決保持觀察空間簡潔、干凈、歸一化。例如位置坐標(biāo)可以相對于某個參考點(diǎn)或者進(jìn)行縮放???觀察值尺度不一。位置坐標(biāo)可能是幾十個單位而速度值可能是個位數(shù)。這會導(dǎo)致神經(jīng)網(wǎng)絡(luò)難以處理。解決在腳本中對觀察值進(jìn)行歸一化或者啟用Behavior Parameters中的Normalize選項(xiàng)對于簡單任務(wù)可能不需要。7.3 超參數(shù)調(diào)優(yōu)沒有銀彈只有耐心配置文件中的超參數(shù)沒有絕對的最優(yōu)值。但有一些啟發(fā)性原則batch_size和buffer_size通常保持默認(rèn)比例buffer_size是batch_size的 10-20 倍。如果任務(wù)復(fù)雜可以適當(dāng)增大。learning_rate最常見的調(diào)整參數(shù)。如果獎勵曲線震蕩劇烈上躥下跳嘗試調(diào)低如1.0e-4。如果學(xué)習(xí)速度太慢曲線幾乎不動嘗試調(diào)高如5.0e-4。使用linear衰減通常是好選擇。beta熵系數(shù)鼓勵探索。如果 Agent 過早地陷入單一行為模式可以適當(dāng)增加beta值。hidden_units和num_layers對于簡單任務(wù)如走到點(diǎn)128和2足夠。對于復(fù)雜任務(wù)如視覺輸入、多智能體可以嘗試增大網(wǎng)絡(luò)規(guī)模如256或512個單元3層。7.4 訓(xùn)練過程監(jiān)控與調(diào)試使用 TensorBoardML-Agents 訓(xùn)練時會自動生成 TensorBoard 日志。在命令行中進(jìn)入results文件夾下的具體運(yùn)行目錄運(yùn)行tensorboard --logdir .然后在瀏覽器打開提示的地址。你可以看到獎勵曲線、 episode 長度、熵值等關(guān)鍵指標(biāo)的可視化圖表。獎勵曲線穩(wěn)步上升是健康的如果劇烈波動或下降說明有問題。在 Unity 中實(shí)時觀察訓(xùn)練時多看看 Game 視圖。Agent 們是不是在“抽風(fēng)”是不是卡在某個角落這些直觀現(xiàn)象能給你最直接的調(diào)試線索。打印日志在 Agent 腳本的關(guān)鍵位置如獲得大獎勵或懲罰時使用Debug.Log可以幫助你理解 Agent 在何時因何故受到了獎勵。7.5 環(huán)境與物理的坑物理不穩(wěn)定訓(xùn)練中如果大量使用物理如剛體碰撞可能會導(dǎo)致模擬不一致影響學(xué)習(xí)。解決盡量簡化碰撞體使用ForceMode.VelocityChange替代ForceMode.Force以獲得更直接的控制或者考慮在訓(xùn)練時固定時間步長Time.fixedDeltaTime。Episode 長度失控如果 Agent 永遠(yuǎn)無法成功或失敗EndEpisode()不被調(diào)用會導(dǎo)致一個 Episode 無限長。解決在Agent腳本的FixedUpdate中設(shè)置一個最大步數(shù)計(jì)數(shù)器超時則給予懲罰并EndEpisode()。訓(xùn)練一個強(qiáng)大的游戲 AI 并非一蹴而就它更像是一場與算法的對話。你通過獎勵函數(shù)和觀察空間提出“問題”算法通過試錯給出“答案”。這個過程需要反復(fù)迭代、觀察和調(diào)整。但當(dāng)你在游戲中看到那個由你親手“培育”出來的智能體做出超出你預(yù)設(shè)的精彩行為時那種成就感是無與倫比的。ML-Agents 打開了一扇新的大門門后是讓游戲角色真正“活”過來的無限可能。