Unity機器學習 ML-Agents第一個例子


上一節我們安裝了機器學習mlagents的開發環境,本節我們創建第一個例子,了解什么是機器學習。
我們的例子很簡單,就是讓機器人自主移動到目標位置,不能移動到地板范圍外。

首先我們來簡單的了解以下機器學習的過程。

機器學習的過程

MLAgents機器強化學習的過程(reinforcement learning)
observation - 監視,觀察
decision - 決策
action - 行動
reward - 獎罰
這4個步驟的翻譯可能不是很準確,大概就是先觀察,后決策,然后行動,最后獎罰。

腳本開始
我們首先創建一個新腳本,我這里創建了MoveToTarget.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Unity.MLAgents;public class MoveToTarget : Agent
{}

機器學習的類都要要繼承Agent基類。

Observation、Action(監視和行動)
我們首先通過覆寫CollectObservations函數,它負責觀察或者監視數據,本例是讓代理(agent)觀察目標target的方位。
然后覆寫OnActionReceived函數,通過接受到的緩沖區的數據進行行動,這里我們要注意機器學習的算法只適用于數字,這意味著機器不知道什么是對象(object),也不知道什么是左右移動,它只負責處理數字,例如float,int類型數據。

接下來,我們在Unity中創建一個agent(代理-盒子,藍色),target(目標-球形,黃色),還有地板plane(盒子,灰色)。如下圖:


理解重要參數
在agent上添加我們的腳本MoveToTarget,這時會自動添加一個BehaviorParameters的行為參數腳本。

?
?

離散的意義

我們先來理解下離散的意義:
假如我們離散輸入1,分支0輸入5。
在這里插入圖片描述
代碼中覆寫Action接收。 我們看下log,因為只有一個離散分支,所以是DiscreteActions[0]

public class MoveToTarget : Agent
{public override void OnActionReceived(ActionBuffers actions){Debug.Log(actions.DiscreteActions[0]);}
}

因為我們覆寫了行動Action,我們還需要一個請求決策。我們在agent對象上添加DecisionRequester(決策請求),參數DecisonPeriod是請求的周期。
在這里插入圖片描述
接下來我們就可以執行,看輸出了什么。

調試和查看輸出

?首先開打cmd,讓我們進入vent虛擬環境中。上一篇文章我們講過了,就是那個MLApp\venv\Scripts\activate.bat批處理文件,確保正常是這樣的。
在這里插入圖片描述
然后我們輸入

mlagents-learn
然后會出現一個漂亮的Unity Logo,并且告訴我們,可以開始Unity運行了。如下圖:
在這里插入圖片描述
Unity運行后,我們看到cmd窗口和Unity的輸出已經開始了。

在這里插入圖片描述

我們可以看到離散的輸出,因為設置了5,這里也只有0-4。

連續類型

接下來我們測試連續型
在Unity中我們把SpaceType改為continuous。并且設置Size為1。
在這里插入圖片描述
腳本也需要改為接收連續型

public class MoveToTarget : Agent
{public override void OnActionReceived(ActionBuffers actions){Debug.Log(actions.ContinuousActions[0]);}
}

我們繼續開始運行,在cmd中輸入mlagents-learn
這時我們會得到一個報錯:
在這里插入圖片描述

是因為我們重試使用了相同的默認ID進行再次訓練,這里我們要么使用mlagents-learn --force來強制覆蓋學習,要么更換ID,mlagents-learn --run-id=test2。

那么虛擬環境開啟后,我們運行Unity。
運行后,我們得到的log如下:
在這里插入圖片描述

我們看到了,連續的就是-1到1的浮點數。到這里我們就了解了離散和連續的區別了。

監視和行動代碼
下面我們將繼續完善腳本,收集監視信息。
我們需要覆寫CollectObservations(VectorSensor sensor)函數。這個函數你可以理解成AI,就是人工智能需要哪些數據才能解決你的問題。在本例中,我們希望盒子(agent)對象移動到球(target)對象的位置。我們思考以下,我們需要知道的數據有哪些?


?如果你想agent能夠移動到目標,是不是需要知道agent在哪,target在哪,所以要知道兩個目標的位置,所以我們通過傳感器把坐標傳入監視。所以代碼里我們把兩個物體的坐標位置傳遞給觀察器。

	[SerializeField] Transform targetTfm;	public override void CollectObservations(VectorSensor sensor){sensor.AddObservation(transform.position);sensor.AddObservation(targetTfm.transform.position);}

行動里,actions就是(decision - 決策)的結果,我們根據決策數據進行行動。

	//行動float moveSpd = 10f;public override void OnActionReceived(ActionBuffers actions){float moveX = actions.ContinuousActions[0];float moveZ = actions.ContinuousActions[1];transform.position += new Vector3(moveX, 0f, moveZ) * Time.deltaTime * moveSpd;}

?因為我們給觀察函數的信息是兩個坐標,相當于6個float類型,所以Vector Observations 的 SpaceSize需要填寫6。而行動,我們只需要移動agent的x和z軸,所以Vector Action的SpaceSize填寫2。
在這里插入圖片描述

如何讓機器學習
你可以把機器學習看成是訓練小狗,如果小狗完成了指定動作,你可以給它骨頭。反之,給予懲罰。
在本例中,我們在地板周圍圍上4面墻體。我們判斷如果它移動到墻就扣分,如果移動都目標就加分,我們在Unity里給Plane圍上4個wall。我們添加墻體,并勾選墻體和target 的Collider的IsTrigger,方面我們進行一個觸發處理。

?

添加獎勵模塊腳本

	private void OnTriggerEnter(Collider other){Debug.Log("OnTriggerEnter:"+other.name);if (other.name.Equals("target")){ AddReward(+1f); //獎勵EndEpisode();   //結束經歷plane.material.color = Color.green;Debug.Log("獎勵");}else if (other.name.Equals("wall")){AddReward(-1f); //懲罰EndEpisode();   //結束plane.material.color = Color.grey;Debug.Log("懲罰");}}

上面的代碼中,如果碰到了target,我們調用AddReward +1,并結束本段AI,讓plane的顏色變為綠色,反之如果碰到了wall,那么就AddReward -1,plane變成灰色。

回合結束處理
每當得到獎勵或者懲罰,會調用EndEpisode。當本段落結束后我們希望它繼續訓練,我們需要把agent對象重新復位,我們要覆寫函數OnEpisodeBegin。
?

    //當一段經歷開始public override void OnEpisodeBegin(){transform.position = Vector3.zero;Debug.Log("經歷開始");}

運行mlagent虛擬機后我們運行unity,可以看到機器已經開始學習如何跑到target的位置了,剛開始很艱難,常常碰到墻壁,慢慢的碰到target的概率會越來越大。
效果如下:
請添加圖片描述

運行過程中,可能開始agent對象很笨,基本原地打轉,經過長周期的運行會越來越快的找尋到target。

幾個參數

這里有幾個點要說明

MaxStep(最大步)

在這里插入圖片描述

這里的MaxStep是一段(Episode)最大步數,如果我們不想每次運行嘗試步數太長,可以給一個數值,你可以嘗試1000,10000這樣的數字,到達這個后,會重新進入OnEpisodeBegin。設置的目的是如果代理一直運行都沒有碰到過target,只是躲避了wall,那么可能達不到我們訓練的目的。

Heuristic (啟發)
這個我的理解是通過你的控制來測試你的運行邏輯是否正確。屬于一個調試功能。
?

//啟發public override void Heuristic(in ActionBuffers actionsOut){ActionSegment<float> continuousActions = actionsOut.ContinuousActions;continuousActions[0] = Input.GetAxisRaw("Horizontal");continuousActions[1] = Input.GetAxisRaw("Vertical");}

我們可以修改agent的BehaviorParameters的BehaviorType為Heuristic(啟發),然后運行Unity就可以控制agent。模擬機器是否遇到target和wall會復位,進行調試。

機器學習加快的辦法
還有一個機器學習加速的辦法,那就是把當前的訓練場景復制很多個,讓他們同時運行來達到機器訓練加速的目的,我們可以把場景和腳本稍加修改。如下:
?

我們需要修改腳本,把原來的position改為localPosition。因為這樣很容易復用我們的代碼,并且只用復制幾個圖中的ground就可以了。

全代碼如下:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Unity.MLAgents;
using Unity.MLAgents.Actuators;
using Unity.MLAgents.Sensors;public class MoveToTarget : Agent
{[SerializeField] Transform targetTfm;[SerializeField] Renderer plane;float moveSpd = 30f;//通過傳感器把坐標傳入監視public override void CollectObservations(VectorSensor sensor){sensor.AddObservation(transform.localPosition);sensor.AddObservation(targetTfm.transform.localPosition);}//行動接收public override void OnActionReceived(ActionBuffers actions){float moveX = actions.ContinuousActions[0];float moveZ = actions.ContinuousActions[1];transform.localPosition += new Vector3(moveX, 0f, moveZ) * Time.deltaTime * moveSpd;}//當一段經歷開始public override void OnEpisodeBegin(){transform.localPosition = Vector3.zero;Debug.Log("經歷開始");}//啟發public override void Heuristic(in ActionBuffers actionsOut){ActionSegment<float> continuousActions = actionsOut.ContinuousActions;continuousActions[0] = Input.GetAxisRaw("Horizontal") * Time.deltaTime * moveSpd;continuousActions[1] = Input.GetAxisRaw("Vertical") * Time.deltaTime * moveSpd;}private void OnTriggerEnter(Collider other){//Debug.Log("OnTriggerEnter:"+other.name);if (other.name.Equals("target")){ AddReward(+1f); //獎勵EndEpisode();   //結束經歷plane.material.color = Color.green;//Debug.Log("獎勵");}else if (other.name.Equals("wall")){AddReward(-1f); //懲罰EndEpisode();   //結束plane.material.color = Color.grey;//Debug.Log("懲罰");}}}

我們修改完畢后,然后運行mlagents環境并運行Unity,明顯批量的速度更快了。如下圖:
請添加圖片描述
從GIF中能看到,亮起綠色的頻率越來越快了。在我的機器上到最后就只有綠色的亮起了。

在這里插入圖片描述

等機器運算完畢后會生成MovetoTart1.onnx文件。

然后在
H:\UnityProject\MLApp\venv\Scripts\results\就能看到我們所有的mlagents測試數據,包含我們需要的訓練后的MoveToTar.onnx文件,我們把它復制到Unity/Assets中。這個onnx就是經過AI訓練的大腦的神經網絡。

我們把這個文件拖動到Model里。

?

BehaviorType選擇InferenceOnly,點擊Unity運行,這樣這個agent就擁有找尋target的AI了。

環境設置
機器學習的環境是可以自定義配置的,可以參考這里。
創建一個movetarget.yaml文件,放到Unity/config文件夾(建立一個)
?

behaviors:MoveToTar1:trainer_type: ppohyperparameters:batch_size: 10buffer_size: 100learning_rate: 3.0e-4beta: 5.0e-4epsilon: 0.2lambd: 0.99num_epoch: 3learning_rate_schedule: linearbeta_schedule: constantepsilon_schedule: linearnetwork_settings:normalize: falsehidden_units: 128num_layers: 2reward_signals:extrinsic:gamma: 0.99strength: 1.0max_steps: 500000time_horizon: 64summary_freq: 10000

通過下面的指令進行,就是按照自定的參數來執行了。具體參數意義有機會我們后面再聊。

使用這個配置文件開啟機器學習,輸入下面的指令:

mlagents-learn config/movetarget.yaml --run-id=test5

在這里插入圖片描述

進一步優化機器

我們繼續上一個測試。當運行的時候,把target的位置改變,我們發現agent可能就找不到目標了,可以思考下為什么?如下面的動畫:

請添加圖片描述

對的,因為在機器學習的時候我們的target的位置一直沒有發生變化,所以AI可能覺得目標是死物,所以我們可以通過修改腳本,讓target每段運算完畢后改變位置,發生變化,機器就會變得聰明些。

我們修改代碼如下:

    public override void OnEpisodeBegin(){transform.localPosition = new Vector3(Random.Range(-9f, 0f), 0f, Random.Range(-4f, 4f));targetTfm.localPosition = new Vector3(Random.Range(1f, 9f), 0f, Random.Range(-4f, 4f));//Debug.Log("經歷開始");}

我們每次開始都隨機以下target和agent的位置,但是不會重合。然后再進行機器學習。

我們輸入下面指令,在上一次運行的test5的基礎上進行test8運算

mlagents-learn config/movetarget.yaml --initialize-from=test5 --run-id=test8

運算后我們覆蓋onnx文件,繼續運行,結果如下:
請添加圖片描述

Web監控

要在訓練期間監控代理性能的統計信息,請使用 TensorBoard指令。

可以開另外一個cmd,進入虛擬環境(venv),輸入下面指令:

tensorboard --logdir results

在這里插入圖片描述
然后再瀏覽器輸入地址就可以了

http://localhost:6006/


根據圖表,你可以看到各種曲線,來修改你的機器訓練。

本章內容就到這里了,官方還有很多種機器學習的例子,如果有興趣可以自行學習。有機會下一篇文章我們進一步擴展,或者做另外一個有意思的Demo。

本章源碼

GitHub - thinbug/MLApp

引用:
https://github.com/Unity-Technologies/ml-agents/blob/main/docs/Learning-Environment-Create-New.md
?

Unity機器學習2 ML-Agents第一個例子_ml-agents小狗-CSDN博客

Unity中訓練一個ML-Agents項目—解決torch和mlagents配置問題_mlagents訓練_LLLQQQismmmmme的博客-CSDN博客

Unity 對接 ML-Agents 初探_艾沃尼斯的博客-CSDN博客

GitHub - thinbug/MLApp

Unity之ml-agents(一):環境配置及初步使用_mlagents-CSDN博客

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/165428.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/165428.shtml
英文地址,請注明出處:http://en.pswp.cn/news/165428.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

分布式鎖之基于zookeeper實現分布式鎖(三)

3. 基于zookeeper實現分布式鎖 實現分布式鎖目前有三種流行方案&#xff0c;分別為基于數據庫、Redis、Zookeeper的方案。這里主要介紹基于zk怎么實現分布式鎖。在實現分布式鎖之前&#xff0c;先回顧zookeeper的相關知識點 3.1. 知識點回顧 3.1.1. 安裝啟動 安裝&#xff1a…

『亞馬遜云科技產品測評』活動征文|搭建圖床chevereto

『亞馬遜云科技產品測評』活動征文&#xff5c;搭建圖床chevereto 提示&#xff1a;本篇文章授權活動官方亞馬遜云科技文章轉發、改寫權&#xff0c;包括不限于在 Developer Centre, 知乎&#xff0c;自媒體平臺&#xff0c;第三方開發者媒體等亞馬遜云科技官方渠道 文章目錄 『…

Python 獲取本地和廣域網 IP

Python 獲取本地IP &#xff0c;使用第三方庫&#xff0c;比如 netifaces import netifaces as nidef get_ip_address():try:# 獲取默認網絡接口&#xff08;通常是 eth0 或 en0&#xff09;default_interface ni.gateways()[default][ni.AF_INET][1]# 獲取指定網絡接口的IP地…

字符串相加

題意&#xff1a; 給定兩個字符串形式的非負整數 num1 和num2 &#xff0c;計算它們的和并同樣以字符串形式返回。 你不能使用任何內建的用于處理大整數的庫&#xff08;比如 BigInteger&#xff09;&#xff0c; 也不能直接將輸入的字符串轉換為整數形式。 示例 1&#xff…

利用STM32CubeMX解讀時鐘樹

1&#xff0c;低速時鐘 LSE是外部晶振作時鐘源&#xff0c;主要提供給實時時鐘模塊&#xff0c;所以一般采用32.768KHz。LSI是由內部RC振蕩器產生&#xff0c;也主要提供給實時時鐘模塊&#xff0c;頻率大約為40KHz。(LSE和LSI)只是提供給芯片中的RTC(實時時鐘)及IWDG(獨立看門…

【c++】棧教程

今天來講講棧 棧是什么&#xff1f; 老樣子&#xff0c;先來看一道題&#xff1a; 【棧】棧的基本操作 描述 棧的定義&#xff1a;棧是一種特殊的表這種表只在表頭進行插入和刪除操作。因此&#xff0c;表頭對于棧來說具有特殊的意義&#xff0c;稱為棧頂。相應地&#xff0…

佳易王羽毛球館計時計費軟件燈控系統安裝教程

佳易王羽毛球館計時計費軟件燈控系統安裝教程 佳易王羽毛球館計時計費軟件&#xff0c;點擊開始計時的時候&#xff0c;自動打開燈&#xff0c;結賬后自動關閉燈。 因為場館每一場地的燈功率都很大&#xff0c;需要加裝交流接觸器。這個由專業電工施工。 1、計時計費功能 &…

docker安裝mysql8

之前自己在網上找了一些docker安裝mysql8的方法&#xff0c;結果都不行&#xff0c;于是自己根據自己遇到的情況再結合網上搜索到的安裝方式調整了一下&#xff0c;成功執行安裝。以下是我自己的執行命令 先拉取docekr鏡像 docker pull mysql:8.0.20啟動鏡像 docker run -p 3…

使用Git bash切換Gitee、GitHub多個Git賬號

Git是分布式代碼管理工具&#xff0c;使用命令行的方式提交commit、revert回滾代碼。這里介紹使用Git bash軟件來切換Gitee、GitHub賬號。 ? ? 假設在gitee.com上的郵箱是alicefoxmail.com 、用戶名為alice&#xff1b;在github上的郵箱是bobfoxmail.com、用戶名為bob。 賬號…

tcp/ip協議2實現的插圖,數據結構2 (19 - 章)

(68) 68 十九1 選路請求與消息 函rtalloc,rtalloc1,rtfree (69)

HarmonyOS ArkTS 保存應用數據(十)

1 概述 在移動互聯網蓬勃發展的今天&#xff0c;移動應用給我們生活帶來了極大的便利&#xff0c;這些便利的本質在于數據的互聯互通。因此在應用的開發中數據存儲占據了非常重要的位置&#xff0c;HarmonyOS應用開發也不例外。 2 什么是首選項 首選項為應用提供Key-Value鍵…

Java面向對象第2天

精華筆記&#xff1a; 構造方法&#xff1a;構造函數、構造器、構建器---------------復用給成員變量賦初始值代碼 作用&#xff1a;給成員變量賦初始值 與類同名&#xff0c;沒有返回值類型(連void都沒有) 在創建(new)對象時被自動調用 若自己不寫構造方法&#xff0c;則編…

Electron+VUE3開發簡版的編輯器【文件預覽】

簡版編輯器的功能主要是: 打開對話框,選擇文件后臺讀取文件文件前端展示文件內容。主要技術棧是VUE3、Electron和Nodejs,VUE3做頁面交互,Electron提供一個可執行Nodejs的環境以及支撐整個應用的環境,nodeJS負責讀取文件內容。 環境配置、安裝依賴這些步驟就不再敘述了。 …

SQL Server 百萬數據查詢優化技巧三十則

點擊上方藍字關注我 互聯網時代的進程越走越深&#xff0c;使用MySQL的人也越來越多&#xff0c;關于MySQL的數據庫優化指南很多&#xff0c;而關于SQL SERVER的T-SQL優化指南看上去比較少&#xff0c;近期有學習SQLSERVER的同學問到SQL SERVER數據庫有哪些優化建議&#xff1f…

Linux進程通信——信號(一)

原理 對于 Linux來說&#xff0c;實際信號是軟中斷&#xff0c;許多重要的程序都需要處理信號。 信號&#xff0c;為 Linux 提供了一種處理異步事件的方法。比如&#xff0c;終端用戶輸入了ctrlc來中斷程序&#xff0c;會通過信號機制停止一個程序。 概述 信號的名字和編號 …

【Docker】從零開始:8.Docker命令:Commit提交命令

【Docker】從零開始&#xff1a;8.Docker命令:Commit命令 基本概念鏡像鏡像分層什么是鏡像分層為什么 Docker 鏡像要采用這種分層結構 本章要點commit 命令命令格式docker commit 操作參數實例演示1.下載一個新的ubuntu鏡像2.運行容器3.查看并安裝vim4.退出容器5提交自己的鏡像…

【數據結構/C++】線性表_雙鏈表基本操作

#include <iostream> using namespace std; typedef int ElemType; // 3. 雙鏈表 typedef struct DNode {ElemType data;struct DNode *prior, *next; } DNode, *DLinkList; // 初始化帶頭結點 bool InitDNodeList(DLinkList &L) {L (DNode *)malloc(sizeof(DNode))…

成為AI產品經理——模型評估概述

目錄 一、模型宣講和評估的原因 二、模型宣講 三、模型評估 1. 重要特征 ① 特征來源 ②特征意義 2.選擇測試樣本 3.模型性能和穩定性 一、模型宣講和評估的原因 劉海豐老師提到他們在做一個金融AI產品未注重模型指標&#xff0c;過于注重業務指標&#xff0c;導致產生…

解決:ImportError: cannot import name ‘Adam‘ from ‘keras.optimizers‘

解決&#xff1a;ImportError: cannot import name ‘Adam‘ from ‘keras.optimizers‘ 背景 在使用之前的代碼時&#xff0c;報錯&#xff1a; from keras.optimizers import Adam ImportError: cannot import name ‘Adam’ 報錯問題 from keras.optimizers import Adam I…

2023年亞太數學建模大賽--A題(水果采摘機器人的圖像識別功能)

中國是世界上最大的蘋果生產國&#xff0c;年產量約為 3500 萬噸。同時&#xff0c;中國也是世界上最大的蘋果出口國&#xff0c;世界上每兩個蘋果中就有一個出口到國。世界上每兩個蘋果中就有一個來自中國&#xff0c;中國出口的蘋果占全球出口量的六分之一以上。來自中國。中…