ML-Agents案例之看图配对
本案例源自ML-Agents官方的示例,Github地址:https://github.com/Unity-Technologies/ml-agents,本文是詳細的配套講解。
本文基于我前面發的兩篇文章,需要對ML-Agents有一定的了解,詳情請見:Unity強化學習之ML-Agents的使用、ML-Agents命令及配置大全。
我前面的相關文章有:
ML-Agents案例之Crawler
ML-Agents案例之推箱子游戲
ML-Agents案例之跳墻游戲
ML-Agents案例之食物收集者
ML-Agents案例之雙人足球
Unity人工智能之不斷自我進化的五人足球賽
ML-Agents案例之地牢逃脫
ML-Agents案例之金字塔
ML-Agents案例之蠕蟲
ML-Agents案例之機器人學走路
環境說明
如圖所示,這個案例官方稱其為Hallway,智能體需要根據前面給的符號來去后面選擇對應的符號,注意,這個案例的難點在于,智能體在選擇時是看不到給定的符號的,而我們的程序并不會幫助智能體去記錄看過的信息,這就要求智能體自己擁有記憶功能,即神經網絡能夠自己學習出“以前看到過什么現在就選什么”這種行為模式,因此擁有記憶功能的循環神經網絡中的大哥LSTM是必不可少的。而這在ML-Agents中只需要配置一下文件就能做到。
狀態輸入:首先智能體用了射線傳感器Ray Perception Sensor 3D,一共發射5條射線,檢測的標簽有給定的O、給定的X、目標的O、目標的X、墻壁,一共5個標簽。對于射線傳感器的詳細講解請查看ML-Agents案例之推箱子游戲。
另外,程序中還給了一個已執行的步數除以最大步數來作為輸入,隨著游戲的運行而增大,當episode結束時這個值會等于1,個人認為這個輸入作用不大,可有可無。
動作輸出:動作輸出只有一個離散輸出,這個輸出有0-4共5個值可供選擇。0代表什么都不做,1代表前進,2代表后退,3代表右轉,4代表左轉。
因此Behavior Parameters設置如下:
代碼講解
智能體下掛載的腳本除去萬年不變的Decesion Requester,Model Overrider,Behavior Parameters,以及剛剛說明的Ray Perception Sensor 3D,就只剩下智能體的只有文件HallwayAgent.cs了:
初始化方法Initialize():
public override void Initialize() {// 尋找控制環境的腳本m_HallwaySettings = FindObjectOfType<HallwaySettings>();// 獲取剛體m_AgentRb = GetComponent<Rigidbody>();// 獲取渲染,便于改變材質m_GroundRenderer = ground.GetComponent<Renderer>();// 獲取初始材質m_GroundMaterial = m_GroundRenderer.material;// 獲取配置文件中的數據m_statsRecorder = Academy.Instance.StatsRecorder; }狀態輸入CollectObservations方法:
public override void CollectObservations(VectorSensor sensor) {// 可在編輯器中選擇用或不用if (useVectorObs){// 輸入現在已執行步數除以最大步數sensor.AddObservation(StepCount / (float)MaxStep);} }動作輸出方法OnActionReceived:
public override void OnActionReceived(ActionBuffers actionBuffers) {// 時間懲罰,激勵智能體越快完成越好AddReward(-1f / MaxStep);MoveAgent(actionBuffers.DiscreteActions); }public void MoveAgent(ActionSegment<int> act) {var dirToGo = Vector3.zero;var rotateDir = Vector3.zero;// 獲取神經網絡的第一個也是唯一一個離散輸出var action = act[0];// 給離散輸出賦予各個值的意義switch (action){case 1:dirToGo = transform.forward * 1f;break;case 2:dirToGo = transform.forward * -1f;break;case 3:rotateDir = transform.up * 1f;break;case 4:rotateDir = transform.up * -1f;break;}// 執行輸出transform.Rotate(rotateDir, Time.deltaTime * 150f);m_AgentRb.AddForce(dirToGo * m_HallwaySettings.agentRunSpeed, ForceMode.VelocityChange); }每一個episode(回合)開始時執行的方法OnEpisodeBegin:
public override void OnEpisodeBegin() {var agentOffset = -15f;var blockOffset = 0f;// 取隨機數0或1m_Selection = Random.Range(0, 2);// 如果是0,場上出現O,位置作一定的隨機if (m_Selection == 0){symbolO.transform.position =new Vector3(0f + Random.Range(-3f, 3f), 2f, blockOffset + Random.Range(-5f, 5f))+ ground.transform.position;symbolX.transform.position =new Vector3(0f, -1000f, blockOffset + Random.Range(-5f, 5f))+ ground.transform.position;}// 如果是1,場上出現X,位置作一定的隨機else{symbolO.transform.position =new Vector3(0f, -1000f, blockOffset + Random.Range(-5f, 5f))+ ground.transform.position;symbolX.transform.position =new Vector3(0f, 2f, blockOffset + Random.Range(-5f, 5f))+ ground.transform.position;}// 初始化智能體的位置和旋轉,并作一定的隨機,速度歸零transform.position = new Vector3(0f + Random.Range(-3f, 3f),1f, agentOffset + Random.Range(-5f, 5f))+ ground.transform.position;transform.rotation = Quaternion.Euler(0f, Random.Range(0f, 360f), 0f);m_AgentRb.velocity *= 0f;// 取隨機數0或1var goalPos = Random.Range(0, 2);// 當隨機數為0時,目標的O放右邊,X放左邊if (goalPos == 0){symbolOGoal.transform.position = new Vector3(7f, 0.5f, 22.29f) + area.transform.position;symbolXGoal.transform.position = new Vector3(-7f, 0.5f, 22.29f) + area.transform.position;}// 當隨機數為1時,目標的O放左邊,X放右邊else{symbolXGoal.transform.position = new Vector3(7f, 0.5f, 22.29f) + area.transform.position;symbolOGoal.transform.position = new Vector3(-7f, 0.5f, 22.29f) + area.transform.position;}// 添加用于報告的統計信息(鍵值對),這些值將出現在Tensorboard中m_statsRecorder.Add("Goal/Correct", 0, StatAggregationMethod.Sum);m_statsRecorder.Add("Goal/Wrong", 0, StatAggregationMethod.Sum); }這里需要說明的是最后兩行代碼是在Tensorboard添加了兩個新的表格,第一個參數是表格的標簽,即鍵,第二個是指,第三個是可選的變量,可選的有Average,MostRecent,Sum,Histogram。
當與別的物體開始發生碰撞執行方法OnCollisionEnter:
void OnCollisionEnter(Collision col) {if (col.gameObject.CompareTag("symbol_O_Goal") || col.gameObject.CompareTag("symbol_X_Goal")){// 當匹配成果時if ((m_Selection == 0 && col.gameObject.CompareTag("symbol_O_Goal")) ||(m_Selection == 1 && col.gameObject.CompareTag("symbol_X_Goal"))){// 獎勵1分SetReward(1f);// 改變成綠色的材質0.5秒StartCoroutine(GoalScoredSwapGroundMaterial(m_HallwaySettings.goalScoredMaterial, 0.5f));// 在Tensorboard成功項中給智能體加一分m_statsRecorder.Add("Goal/Correct", 1, StatAggregationMethod.Sum);}// 當匹配失敗時else{SetReward(-0.1f);StartCoroutine(GoalScoredSwapGroundMaterial(m_HallwaySettings.failMaterial, 0.5f));// 在Tensorboard失敗項中給智能體加一分m_statsRecorder.Add("Goal/Wrong", 1, StatAggregationMethod.Sum);}// 結束游戲EndEpisode();} }// 攜程,短暫改變材質 IEnumerator GoalScoredSwapGroundMaterial(Material mat, float time) {m_GroundRenderer.material = mat;yield return new WaitForSeconds(time);m_GroundRenderer.material = m_GroundMaterial; }當智能體沒有模型,人想手動錄制示例時可以采用Heuristic方法:
public override void Heuristic(in ActionBuffers actionsOut) {var discreteActionsOut = actionsOut.DiscreteActions;if (Input.GetKey(KeyCode.D)){discreteActionsOut[0] = 3;}else if (Input.GetKey(KeyCode.W)){discreteActionsOut[0] = 1;}else if (Input.GetKey(KeyCode.A)){discreteActionsOut[0] = 4;}else if (Input.GetKey(KeyCode.S)){discreteActionsOut[0] = 2;} }配置文件
PPO算法:
behaviors:Hallway:trainer_type: ppohyperparameters:batch_size: 128buffer_size: 1024learning_rate: 0.0003beta: 0.03epsilon: 0.2lambd: 0.95num_epoch: 3learning_rate_schedule: linearnetwork_settings:normalize: falsehidden_units: 128num_layers: 2vis_encode_type: simplememory:sequence_length: 64memory_size: 128reward_signals:extrinsic:gamma: 0.99strength: 1.0keep_checkpoints: 5max_steps: 10000000time_horizon: 64summary_freq: 10000SAC算法:
behaviors:Hallway:trainer_type: sachyperparameters:learning_rate: 0.0003learning_rate_schedule: constantbatch_size: 512buffer_size: 200000buffer_init_steps: 0tau: 0.005steps_per_update: 10.0save_replay_buffer: falseinit_entcoef: 0.1reward_signal_steps_per_update: 10.0network_settings:normalize: falsehidden_units: 128num_layers: 2vis_encode_type: simplememory:sequence_length: 64memory_size: 128reward_signals:extrinsic:gamma: 0.99strength: 1.0keep_checkpoints: 5max_steps: 4000000time_horizon: 64summary_freq: 10000可以看到,相比也平常的配置,中間加入了一部分:
memory:sequence_length: 64memory_size: 128默認不加這部分的時候,我們的模型中是沒有循環神經網絡的,當我們設置了這個參數后,相當于給模型加入了一個LSTM,sequence_length指的是需要記住的經驗序列長度,memory_size是智能體保存的記憶大小,必須是2的倍數。我們要合理設置參數,設置過大將大大降低訓練速度,過小會導致記不住東西。
效果演示
后記
本案例主要探討了ML-Agents中智能體的“記憶力”是怎么實現的,我們可以通過在配置文件中設置相應的參數來給我們的模型添加上LSTM,讓智能體先觀察,后做“選擇題”,就能訓練出一個具有記憶力的智能體。
總結
以上是生活随笔為你收集整理的ML-Agents案例之看图配对的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: WPF 分页控件应用
- 下一篇: 域名解析文件hosts文件是什么?如何修