Recording Statistics:https://github.com/Unity-Technologies/ml-agents/blob/release_19/docs/Learning-Environment-Design.md#recording-statistics
目录
1.1.3 StatsRecorder m_Recorder
1.2.1 Academy.Instance.OnEnvironmentReset += EnvironmentReset
1.2.2 m_Recorder = Academy.Instance.StatsRecorder
1.3.1 foreach (var fa in listArea)
1.5.1 scoreText.text = $"Score: {totalScore}"
1.5.2 m_Recorder.Add("TotalScore", totalScore)
1.FoodCollectorSettings.cs
using UnityEngine;
using UnityEngine.UI;
using Unity.MLAgents;
public class FoodCollectorSettings : MonoBehaviour
{
[HideInInspector]
public GameObject[] agents; // 所有代理的 GameObject 数组
[HideInInspector]
public FoodCollectorArea[] listArea; // 所有 FoodCollectorArea 的数组
public int totalScore; // 总得分
public Text scoreText; // 显示得分的 UI Text 对象
StatsRecorder m_Recorder; // 记录环境统计信息的 StatsRecorder 对象
public void Awake()
{
// 注册 OnEnvironmentReset 方法,当环境被重置时执行
Academy.Instance.OnEnvironmentReset += EnvironmentReset;
m_Recorder = Academy.Instance.StatsRecorder; // 获取 StatsRecorder 对象
}
void EnvironmentReset()
{
// 清除所有标签为 "food" 的 GameObject
ClearObjects(GameObject.FindGameObjectsWithTag("food"));
// 清除所有标签为 "badFood" 的 GameObject
ClearObjects(GameObject.FindGameObjectsWithTag("badFood"));
// 获取所有标签为 "agent" 的 GameObject 并存入 agents 数组
agents = GameObject.FindGameObjectsWithTag("agent");
// 获取所有 FoodCollectorArea 并存入 listArea 数组,重置每个 FoodCollectorArea 的食物
listArea = FindObjectsOfType<FoodCollectorArea>();
foreach (var fa in listArea)
{
fa.ResetFoodArea(agents);
}
totalScore = 0; // 总得分清零
}
void ClearObjects(GameObject[] objects)
{
// 遍历所有 GameObject,销毁它们
foreach (var food in objects)
{
Destroy(food);
}
}
public void Update()
{
scoreText.text = $"Score: {totalScore}"; // 显示总得分
// 每 100 帧发送环境统计信息到 SideChannel,这些值将被平均每 summary_frequency 步,因此不需要每次 Update() 调用都发送
if ((Time.frameCount % 100) == 0)
{
m_Recorder.Add("TotalScore", totalScore);
}
}
}
这段代码是一个Unity脚本,它是FoodCollector场景中的游戏管理器,负责管理游戏的各种设置和重置环境。在FoodCollector游戏中,玩家需要控制代理来收集食物,避开毒物,以获得更高的分数。
在脚本中,有以下的功能:
agents
和listArea
数组:用于存储场景中的所有代理和食物区域(即游戏中的区域,包含食物和毒物)。totalScore
和scoreText
:用于存储当前分数和在UI中显示分数的文本。m_Recorder
:用于记录游戏中的统计信息,这些信息可以通过TensorBoard可视化分析。Awake()
函数:在游戏对象唤醒时,为OnEnvironmentReset
事件添加事件处理程序,并初始化统计信息记录器。EnvironmentReset()
函数:用于重置游戏环境,清除场景中的食物和毒物,重新设置食物区域,并重置分数。ClearObjects()
函数:用于清除场景中指定标签的所有游戏对象。Update()
函数:每帧更新UI中的分数显示,并定期将分数统计信息记录到m_Recorder
。
1.1 FoodCollectorSettings类
using UnityEngine.UI;
public class FoodCollectorSettings : MonoBehaviour
{
public int totalScore; // 总得分
public Text scoreText; // 显示得分的 UI Text 对象
StatsRecorder m_Recorder;
}
1.1.1 using UnityEngine.UI
using UnityEngine.UI;
UnityEngine.UI
是 Unity 引擎中用于实现 UI 界面的命名空间,包括了常见的 UI 元素类,例如 Text
、Button
、Image
等。在使用这些类之前,需要先添加引用:using UnityEngine.UI;
,这样可以避免每次使用时都需要输入完整的命名空间。
1.1.2 public Text scoreText
public Text scoreText;
这行代码定义了一个名为scoreText的公共变量,其类型为Text。在Unity中,Text是用于显示文本的组件。定义公共变量可以让其他脚本访问和修改该变量。这个变量通常用于在游戏界面上显示游戏分数等信息。
1.1.3 StatsRecorder m_Recorder
StatsRecorder m_Recorder;
StatsRecorder
是ML-Agents中的一个类,它用于记录模拟器的统计数据。在这个代码段中,m_Recorder
是一个StatsRecorder
类型的变量,它被赋值为Academy.Instance.StatsRecorder
。这意味着该变量指向ML-Agents中全局的统计记录器实例,可以使用它来记录模拟器中的数据,比如训练期间的分数,完成的任务数等等。
1.2 Awake()函数
public void Awake()
{
// 注册 OnEnvironmentReset 方法,当环境被重置时执行
Academy.Instance.OnEnvironmentReset += EnvironmentReset;
m_Recorder = Academy.Instance.StatsRecorder; // 获取 StatsRecorder 对象
}
Awake()
是 MonoBehaviour 的一个生命周期函数,用于在场景中创建一个物体时进行初始化。当场景中创建一个包含 FoodCollectorSettings
脚本的游戏对象时,Awake()
函数会被调用一次。
在这个函数中,首先调用 Academy.Instance.OnEnvironmentReset += EnvironmentReset;
语句,将 EnvironmentReset()
函数注册到了 OnEnvironmentReset
事件中,这个事件是在每个Episode(训练周期)开始时触发的。这样,当Agent开始一个新的训练周期时,EnvironmentReset()
函数就会被调用,用于重置场景状态和数据。
接着,使用 Academy.Instance.StatsRecorder
获取了一个名为 m_Recorder
的 StatsRecorder
对象,该对象用于在训练过程中收集统计信息,例如每个Episode的得分情况,用于在训练过程中监控智能体的学习效果。这样在后续的代码中就可以使用 m_Recorder
对象来收集并发送统计信息。
1.2.1 Academy.Instance.OnEnvironmentReset += EnvironmentReset
Academy.Instance.OnEnvironmentReset += EnvironmentReset;
这行代码用于将 EnvironmentReset
方法添加到 Academy
实例的 OnEnvironmentReset
事件中。OnEnvironmentReset
事件在每次环境重置时触发。在本例中,当环境重置时,EnvironmentReset
方法被调用。因此,通过这行代码,当环境重置时,可以确保 EnvironmentReset
方法被自动调用。
1.2.2 m_Recorder = Academy.Instance.StatsRecorder
m_Recorder = Academy.Instance.StatsRecorder;
这行代码的作用是将ML-Agents Academy实例的统计记录器(StatsRecorder)存储到类成员变量m_Recorder
中,以便在后续代码中使用。StatsRecorder
负责收集训练期间的统计信息(例如训练损失、奖励等),并将其发送到TensorBoard中进行可视化分析。通过将m_Recorder
成员变量设置为Academy.Instance.StatsRecorder
,可以轻松地记录并发送任何自定义的统计信息。
1.3 EnvironmentReset()
void EnvironmentReset()
{
// 清除所有标签为 "food" 的 GameObject
ClearObjects(GameObject.FindGameObjectsWithTag("food"));
// 清除所有标签为 "badFood" 的 GameObject
ClearObjects(GameObject.FindGameObjectsWithTag("badFood"));
// 获取所有标签为 "agent" 的 GameObject 并存入 agents 数组
agents = GameObject.FindGameObjectsWithTag("agent");
// 获取所有 FoodCollectorArea 并存入 listArea 数组,重置每个 FoodCollectorArea 的食物
listArea = FindObjectsOfType<FoodCollectorArea>();
foreach (var fa in listArea)
{
fa.ResetFoodArea(agents);
}
totalScore = 0; // 总得分清零
}
EnvironmentReset
函数在每次环境重置时被调用,它的作用是:
①清除之前生成的所有标签为 "food" 的游戏对象和标签为 "badFood" 的游戏对象。
②获取所有标签为 "agent" 的游戏对象,并将它们存入 agents
数组。
③获取所有的 FoodCollectorArea
组件,将它们存入 listArea
数组,并重置每个 FoodCollectorArea
中的食物。
④将 totalScore
清零,准备开始新的一轮游戏。
1.3.1 foreach (var fa in listArea)
foreach (var fa in listArea)
{
fa.ResetFoodArea(agents);
}
这段代码的作用是对每个 FoodCollectorArea
进行重置操作。在重置过程中,每个 FoodCollectorArea
的食物需要重新生成并放置在特定的位置,这些位置是与所有 agent
相关的。因此,需要传递 agents
数组作为参数,使每个 FoodCollectorArea
的食物与所有 agent
有关。这个过程中会调用 FoodCollectorArea
类中的 ResetFoodArea
方法来完成具体的重置操作。
1.4 ClearObjects()
void ClearObjects(GameObject[] objects)
{
// 遍历所有 GameObject,销毁它们
foreach (var food in objects)
{
Destroy(food);
}
}
这个函数的作用是清除所有传入数组 objects
中的 GameObject 对象。它首先遍历数组中的每个 GameObject,然后使用 Destroy()
函数销毁它们。在这段代码中,它被用来清除所有标签为 "food" 和 "badFood" 的 GameObject,因为这些 GameObject 会在环境重置时被重新生成。
1.5 Update()
public void Update()
{
scoreText.text = $"Score: {totalScore}"; // 显示总得分
// 每 100 帧发送环境统计信息到 SideChannel,这些值将被平均每 summary_frequency 步,因此不需要每次 Update() 调用都发送
if ((Time.frameCount % 100) == 0)
{
m_Recorder.Add("TotalScore", totalScore);
}
}
这段代码是在游戏每一帧更新时调用的,它的主要作用是更新显示总得分的文本和将总得分发送给 StatsRecorder
,以便将其记录在 TensorBoard 中。
首先,它将 totalScore
显示在 UI 中,以字符串 "Score: " 为前缀。
然后,它检查帧数是否为 100 的倍数,如果是,则将当前总得分值 totalScore
通过 StatsRecorder
发送到 TensorBoard 中。StatsRecorder
是一个用于记录环境统计信息的类,可以记录一些代理的学习进度、环境统计信息等。发送环境统计信息到 SideChannel,这些值将被平均每 summary_frequency 步,因此不需要每次 Update() 调用都发送,减轻了资源消耗。
问:这些统计信息可以通过 StatsRecorder 对象的 Add() 方法添加到 SideChannel 中,以便在 TensorBoard 中进行可视化和分析?SideChannel ?
这些统计信息可以通过 StatsRecorder 对象的 Add() 方法添加到 SideChannel 中。SideChannel 是 Unity ML-Agents 用于在训练期间传输数据的可选通道,它们提供了一种机制来共享和访问来自环境、代理和其他来源的数据。SideChannel 通常用于跟踪和分析训练期间的统计信息,例如训练代理的总回报或每个代理的动作分布等。StatsRecorder 是一种方便的 SideChannel,它可以用于记录任意数量的统计信息,并将它们发送到 TensorBoard 中进行分析和可视化。
1.5.1 scoreText.text = $"Score: {totalScore}"
scoreText.text = $"Score: {totalScore}";
这行代码将总得分 totalScore
显示在 UI 元素 scoreText
上,其中 $"Score: {totalScore}"
是一个字符串插值表达式,将字符串 "Score: " 和 totalScore
的值插入其中,形成最终的文本字符串。通过将该文本赋值给 scoreText.text
属性,更新 UI 元素上的文本显示。如果当前 totalScore
的值为 10
,那么最终的文本字符串会是 "Score: 10"。
1.5.2 m_Recorder.Add("TotalScore", totalScore)
m_Recorder.Add("TotalScore", totalScore)
这句代码将当前的总得分值 totalScore
添加到 StatsRecorder
对象的 TotalScore
统计信息中。这些统计信息可以通过 StatsRecorder
对象的 Add()
方法添加到 SideChannel
中,以便在 TensorBoard
中进行可视化和分析。在这里,每隔 100 帧发送一次环境统计信息,以减少发送的数据量,提高效率。
问 :"TotalScore" ?
"TotalScore" 是指将被记录到 TensorBoard 中的数据的名称。在这个例子中,我们将记录每个环境重置后的总分数。通过将名称设置为"TotalScore",我们可以轻松地在 TensorBoard 中找到此数据并进行分析和比较。当然,您可以将其设置为任何您喜欢的名称,只要在后续分析过程中使用相应的名称即可。
问:m_Recorder ?
m_Recorder
是一个 StatsRecorder
类型的变量,它是 Unity ML-Agents 中的一个工具,用于记录和保存模型的统计信息,例如奖励、损失、成功率等等。可以通过它将这些统计信息发送到 TensorBoard 中进行可视化分析。在这段代码中,使用 m_Recorder.Add()
方法将当前的总得分 totalScore
记录下来,并指定了它在 TensorBoard 中的名称为 "TotalScore",以便在 TensorBoard 中进行查看和分析。