ML-Agents案例之看图配对
本案例源自ML-Agents官方的示例,Github地址:https://github.com/Unity-Technologies/ml-agents,本文是詳細(xì)的配套講解。
本文基于我前面發(fā)的兩篇文章,需要對ML-Agents有一定的了解,詳情請見:Unity強(qiáng)化學(xué)習(xí)之ML-Agents的使用、ML-Agents命令及配置大全。
我前面的相關(guān)文章有:
ML-Agents案例之Crawler
ML-Agents案例之推箱子游戲
ML-Agents案例之跳墻游戲
ML-Agents案例之食物收集者
ML-Agents案例之雙人足球
Unity人工智能之不斷自我進(jìn)化的五人足球賽
ML-Agents案例之地牢逃脫
ML-Agents案例之金字塔
ML-Agents案例之蠕蟲
ML-Agents案例之機(jī)器人學(xué)走路
環(huán)境說明
如圖所示,這個案例官方稱其為Hallway,智能體需要根據(jù)前面給的符號來去后面選擇對應(yīng)的符號,注意,這個案例的難點在于,智能體在選擇時是看不到給定的符號的,而我們的程序并不會幫助智能體去記錄看過的信息,這就要求智能體自己擁有記憶功能,即神經(jīng)網(wǎng)絡(luò)能夠自己學(xué)習(xí)出“以前看到過什么現(xiàn)在就選什么”這種行為模式,因此擁有記憶功能的循環(huán)神經(jīng)網(wǎng)絡(luò)中的大哥LSTM是必不可少的。而這在ML-Agents中只需要配置一下文件就能做到。
狀態(tài)輸入:首先智能體用了射線傳感器Ray Perception Sensor 3D,一共發(fā)射5條射線,檢測的標(biāo)簽有給定的O、給定的X、目標(biāo)的O、目標(biāo)的X、墻壁,一共5個標(biāo)簽。對于射線傳感器的詳細(xì)講解請查看ML-Agents案例之推箱子游戲。
另外,程序中還給了一個已執(zhí)行的步數(shù)除以最大步數(shù)來作為輸入,隨著游戲的運(yùn)行而增大,當(dāng)episode結(jié)束時這個值會等于1,個人認(rèn)為這個輸入作用不大,可有可無。
動作輸出:動作輸出只有一個離散輸出,這個輸出有0-4共5個值可供選擇。0代表什么都不做,1代表前進(jìn),2代表后退,3代表右轉(zhuǎn),4代表左轉(zhuǎn)。
因此Behavior Parameters設(shè)置如下:
代碼講解
智能體下掛載的腳本除去萬年不變的Decesion Requester,Model Overrider,Behavior Parameters,以及剛剛說明的Ray Perception Sensor 3D,就只剩下智能體的只有文件HallwayAgent.cs了:
初始化方法Initialize():
public override void Initialize() {// 尋找控制環(huán)境的腳本m_HallwaySettings = FindObjectOfType<HallwaySettings>();// 獲取剛體m_AgentRb = GetComponent<Rigidbody>();// 獲取渲染,便于改變材質(zhì)m_GroundRenderer = ground.GetComponent<Renderer>();// 獲取初始材質(zhì)m_GroundMaterial = m_GroundRenderer.material;// 獲取配置文件中的數(shù)據(jù)m_statsRecorder = Academy.Instance.StatsRecorder; }狀態(tài)輸入CollectObservations方法:
public override void CollectObservations(VectorSensor sensor) {// 可在編輯器中選擇用或不用if (useVectorObs){// 輸入現(xiàn)在已執(zhí)行步數(shù)除以最大步數(shù)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;// 獲取神經(jīng)網(wǎng)絡(luò)的第一個也是唯一一個離散輸出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;}// 執(zhí)行輸出transform.Rotate(rotateDir, Time.deltaTime * 150f);m_AgentRb.AddForce(dirToGo * m_HallwaySettings.agentRunSpeed, ForceMode.VelocityChange); }每一個episode(回合)開始時執(zhí)行的方法OnEpisodeBegin:
public override void OnEpisodeBegin() {var agentOffset = -15f;var blockOffset = 0f;// 取隨機(jī)數(shù)0或1m_Selection = Random.Range(0, 2);// 如果是0,場上出現(xiàn)O,位置作一定的隨機(jī)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,場上出現(xiàn)X,位置作一定的隨機(jī)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;}// 初始化智能體的位置和旋轉(zhuǎn),并作一定的隨機(jī),速度歸零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;// 取隨機(jī)數(shù)0或1var goalPos = Random.Range(0, 2);// 當(dāng)隨機(jī)數(shù)為0時,目標(biāo)的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;}// 當(dāng)隨機(jī)數(shù)為1時,目標(biāo)的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;}// 添加用于報告的統(tǒng)計信息(鍵值對),這些值將出現(xiàn)在Tensorboard中m_statsRecorder.Add("Goal/Correct", 0, StatAggregationMethod.Sum);m_statsRecorder.Add("Goal/Wrong", 0, StatAggregationMethod.Sum); }這里需要說明的是最后兩行代碼是在Tensorboard添加了兩個新的表格,第一個參數(shù)是表格的標(biāo)簽,即鍵,第二個是指,第三個是可選的變量,可選的有Average,MostRecent,Sum,Histogram。
當(dāng)與別的物體開始發(fā)生碰撞執(zhí)行方法OnCollisionEnter:
void OnCollisionEnter(Collision col) {if (col.gameObject.CompareTag("symbol_O_Goal") || col.gameObject.CompareTag("symbol_X_Goal")){// 當(dāng)匹配成果時if ((m_Selection == 0 && col.gameObject.CompareTag("symbol_O_Goal")) ||(m_Selection == 1 && col.gameObject.CompareTag("symbol_X_Goal"))){// 獎勵1分SetReward(1f);// 改變成綠色的材質(zhì)0.5秒StartCoroutine(GoalScoredSwapGroundMaterial(m_HallwaySettings.goalScoredMaterial, 0.5f));// 在Tensorboard成功項中給智能體加一分m_statsRecorder.Add("Goal/Correct", 1, StatAggregationMethod.Sum);}// 當(dāng)匹配失敗時else{SetReward(-0.1f);StartCoroutine(GoalScoredSwapGroundMaterial(m_HallwaySettings.failMaterial, 0.5f));// 在Tensorboard失敗項中給智能體加一分m_statsRecorder.Add("Goal/Wrong", 1, StatAggregationMethod.Sum);}// 結(jié)束游戲EndEpisode();} }// 攜程,短暫改變材質(zhì) IEnumerator GoalScoredSwapGroundMaterial(Material mat, float time) {m_GroundRenderer.material = mat;yield return new WaitForSeconds(time);m_GroundRenderer.material = m_GroundMaterial; }當(dāng)智能體沒有模型,人想手動錄制示例時可以采用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默認(rèn)不加這部分的時候,我們的模型中是沒有循環(huán)神經(jīng)網(wǎng)絡(luò)的,當(dāng)我們設(shè)置了這個參數(shù)后,相當(dāng)于給模型加入了一個LSTM,sequence_length指的是需要記住的經(jīng)驗序列長度,memory_size是智能體保存的記憶大小,必須是2的倍數(shù)。我們要合理設(shè)置參數(shù),設(shè)置過大將大大降低訓(xùn)練速度,過小會導(dǎo)致記不住東西。
效果演示
后記
本案例主要探討了ML-Agents中智能體的“記憶力”是怎么實現(xiàn)的,我們可以通過在配置文件中設(shè)置相應(yīng)的參數(shù)來給我們的模型添加上LSTM,讓智能體先觀察,后做“選擇題”,就能訓(xùn)練出一個具有記憶力的智能體。
總結(jié)
以上是生活随笔為你收集整理的ML-Agents案例之看图配对的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: WPF 分页控件应用
- 下一篇: 【转载】Linux中断处理学习笔记