# 创建一个新的学习环境
本教程将介绍创建unity环境的过程
unity环境是使用unity引擎来训练增强学习代理器的应用
设置unity项目
1. 打开一个项目导入unity机器学习包, 或者新建一个项目重新导入 增强学习 接口包:
* [ML-Agents package without TensorflowSharp](https://s3.amazonaws.com/unity-agents/ML-AgentsNoPlugin.unitypackage)
* [ML-Agents package with TensorflowSharp](https://s3.amazonaws.com/unity-agents/ML-AgentsWithPlugin.unitypackage)
2. 重命名 `TemplateAcademy.cs` (包括类名) :
所有 Template 文件 都在 `Assets -> Template -> Scripts`里. 通常命名方式为 `YourNameAcademy`.
3. 把 `YourNameAcademy.cs` 拖到一个新的对象上 (`Unity` -> `GameObject` -> `Create Empty`)
同时重命名这个对象 `YourNameAcademy`. `YourNameAcademy` 会用来控制所有环境的逻辑,
确保附加的对象是一个留在场景中,不管环境重置,或其他环境行为
4. 把 `Brain.cs` 拖到一个新的对象上并重命名 `YourNameBrain1`.
把对象作为 `YourNameAcademy` 的子对象
注意 你可以有多个 brains 在 Academy 下但所有brain不同名
5. 禁用窗口对话框和屏幕分辨率
1.`Edit` -> `Project Settings` -> `Player` -> `Resolution and Presentation`.
2. 设置 `Display Resolution Dialogue` 为 `Disabled`.
3.勾选`Run In Background`.
4. 点击 `Splash Image`.
5. 取消 `Show Splash Screen` (Unity Pro only)
6. 如果你要在Unity中使用Tensorflow Sharp, 你必须:
1. 确保你使用Unity 2017.1以上版本.
2. 确保你已经加载了TensorflowSharp. 下载地址(https://s3.amazonaws.com/unity-agents/TFSharpPlugin.unitypackage).
3. `Edit` -> `Project Settings` -> `Player`
4. 对于你选择的平台(**`PC, Mac and Linux Standalone`**, **`iOS`** 或者 **`Android`**):
1. `Other Settings`.
2. 选择 `Scripting Runtime Version`为`Experimental (.NET 4.6 Equivalent)`
3. 在`Scripting Defined Symbols`, 添加字符`ENABLE_TENSORFLOW`
5. 重启unity
操作`YourNameAcademy`
1. 点击对象**`YourNameAcademy`**.
2. 在inspector面板, 可以设置academy一下内容:
* **`Max Steps`**每一训练集的最大长度(如果您不希望环境在某一时间后重置),则设置为0。
* **`Wait Time`** 在测试环境中运行时的步骤之间的实时性。仅当使用步骤发生在` update() `。
* **`Frames To Skip`** 在步骤间跳过的帧数(或物理更新)。代理器会在每一帧都调用但是行为只会在每步中出现.
* **`Training Configuration`** 和 **`Inference Configuration`** 第一个定义了引擎在训练时的配置,第二个定义在测试/推理时间. 当参数`train_model` 设置为True时训练模式只能为外部训练 . 可调参数如下:
* `Width`和`Height` 对应的宽度和高度,窗口的像素(必须大于0). 通常在训练期间将其设置为小尺寸,而在推理过程中用于可视化的更大尺寸。
* `Quality Level` 确定如何执行渲染. 通常在训练过程中设置为小值,在推理过程中为了可视化价使用高值.
* `Time Scale` 物理加速. 如果环境使用的物理计算, 训练中提高这个值, 在推理中设置为 `1.0f`. 否则设置为 `1.0f`.
* `Target Frame Rate` 帧渲染频率. 如果环境使用观察, 在训练中提高这个值, 推理中设置为`60`. 如果没有使用观察, 训练中设置为 `1`
* **`Default Reset Parameters`** 在重置时你可以设置默认配置. 字符会映射为浮点, 你能在 academy中调用 `resetParameters["YourDefaultParameter"]`
3. 在 **`InitializeAcademy()`**中, 你可以定义 Academy的初始化. 请注意,该命令在训练会话开始时只运行一次.
3. 在 **`AcademyStep()`**中, 定义环境逻辑的每一步. 使用这个函数去修改环境中的代理器.
4. 在 **`AcademyReset()`**中, 每新训练集重置. 它应该包含对于特定环境的代码用来设置环境. 注意`AcademyReset()` 训练会话开始时 调用 用来确保第一个集和其他一样.
## 执行`YourNameBrain`
每个在academy下的brain :
1. 点击`YourNameBrain`
2. 在inspector面板中, 你可以修改**`Brain Parameters`**
* `State Size` 提供给代理器的变量数 (s).**public override List CollectState()里的变量
* `Action Size` 每个代理采取的可能操作数 .**public override void AgentStep(float[] act)里接收act的变量
* `Memory Size` 代理器记住每一步的浮动数.
* `Camera Resolutions` 包含分辨率参数的可伸缩长度列表:`height`和`width`。 .
如果你想摄像机输出为黑白勾选 `Black And White` .
* `Action Descriptions` 用人类可读的语言描述每个可用动作的意思的列表.
* `State Space Type` 和 `Action Space Type`. 同样`discrete`或者`continuous`.
* `discrete` 对应的行为为 `int`.
* `continuous` 对应的行为为 `float`.
3. 如果你想运行时收集数据, 勾选 **`Collect Data`**. 这个方法中, 状态和行动通过大脑将保存在文件夹`saved_plays`
4. 你可以选择 `YourNameBrain` 的类型. 一下四个可选项:
* `External` : 如果你想调用python,环境中至少有一个外部模式
* `Player` : 手动控制你的代理器. 如果行为空间是离散的, 必须将输入键映射到相应的整数值. 如果行为空间是连续的, 你必须映射输入键相应指标和浮点值 .
* `Heuristic` : 你可以让你的大脑自动对观察结果和状态做预设好的反应. 你需要拖一个 `Decision` 脚本到`YourNameBrain`. 创建自定义反应, 你必须 :
* 重命名 `TemplateDecision.cs` (还有类名) 你想要的新反应的名字. 约定的命名方式为 `YourNameDecision`.
* 执行 `Decide`: 给定一个代理的状态、观察和记忆,这个函数必须返回一个与代理器所采取的操作相对应的浮动数组. 如果行动空间为离散, 这个数组为 1.
* 随意项, 执行 `MakeMemory`: 给定一个代理的状态、观察和记忆,这个函数必须返回一个与代理的新记忆相对应的浮动数组.
* `Internal` : 注意这个选项你必须有 Tensorflow Sharp 设置. 下面是必须完成的地方:
* `Graph Model` : 这个必须为 `bytes`文件对应已经训练好的Tensorflow 图. (你必须先把二进制文件拖进unity,再把二进制文件拖到inspector)
* `Graph Scope` : 当你训练你的tensorflow 模型时设置了一个范围, 所有你的占位符(placeholder)名称将有前缀. 你必须在此指定前缀.
* `Batch Size Node Name` : 如果批处理大小是图的输入之一,则必须在占位符中指定名称. brain将自动使批量大小等于与brain相连的代理数量.
* `State Node Name` : 如果你的图形使用状态作为输入,则必须在此占位符中指定名称.
* `Recurrent Input Node Name` : 如果你的图形使用循环输入/记忆作为输入,并输出新的循环输入/记忆,则必须在输入占位符中指定名称.
* `Recurrent Output Node Name` : 如果你的图形使用循环输入/记忆作为输入,并输出新的循环输入/记忆,则必须在输入占位符中指定名称.
* `Observation Placeholder Name` : 如果你的图使用观察作为输入,你必须在此处指定。注意,观测值等于brain参数中“Camera Resolutions”的长度
* `Action Node Name` : 指定与图中的brain动作相对应的占位符名称. 如果行动空间是连续的, 输出一定为`Action Space Size`一个浮点长度方向的张量(tensor) , 如果行动空间为离散, 输出必须为一个整形为1长度的张量.
* `Graph Placeholder` : 如果你的图需要额外的固定输入(例如:噪声水平),你可以在这里指定它们. 注意在你的图里, 这些必须与int的一维张量或大小为1的浮点对应.
* `Name` : 对应占位符的名字.
* `Value Type` : 整型和浮点.
* `Min Value`和'Max Value' : 指定最大最小值供给(包含最值) 占位符选择. 该值将在每个步骤的均匀分布中进行采样. 如果你想让这个值固定 同时设置 `Min Value` 和`Max Value` 为同样的值.
## 执行`YourNameAgent`
1. 重命名`TemplateAgent.cs`. 约定的命名为`YourNameAgent`.
2.把 `YourNameAgent.cs` 代表代理器的对象上.
(Example: 如果你想做自动驾驶, 把 `YourNameAgent.cs` 挂到看上去像车的对象上)
3. 在你代理器inspector面板, 把代理器对应的brain拖进 `Brain` 框.
注意,同一个brain可以有不同的代理器.
如果你通过脚本的方式想给一个代理器一个brain或者改变它的brain, 使用`ChangeBrain()`.
4. 在你代理器inspector面板, 你可以指定摄像头, 你的代理器可以用来观察. 这么做, 拖 `Observations` 框. 注意 如果你想要一个摄像机去单独移动你的代理器, 你可以设置你的摄像头作为代理器的子对象
5. 如果 `Reset On Done` 被勾选, `Reset()` 会在代理器完成时被调用.否则, `AgentOnDone()` 会被调用. 注意如果`Reset On Done`没有勾选, 代理器会被保持 "done" 直到Academy重置. 这就意味着它不会在环境中采取任何行为.
6. 执行`YourNameAgent.cs` :
* `InitializeAgent()` : 这个方法用来初始化你的代理器. 代理器创建时被调用.
* `CollectState()` : 必须返回与代理器所在的状态相对应的浮动列表. 如果状态空间类型为离散, 返回长度1的列表,其中包含与您的状态等价的浮点数
* `AgentStep()` : 这个方法每帧调用, 你必须定义你的代理器会输入的行为. 你必须定义 奖励 和 代理器是否完成.这样做, 修改代理器中的 `reward` 和`done`.
* `AgentReset()` : 这个函数在开始时调用, 当Academy重置和当代理器完成时 ( `Reset On Done` 被勾选).
* `AgentOnDone()` : 如果 `Reset On Done` 没有被勾选, 这个函数会在代理器完成时被调用. `Reset()` 只会在Academy重置时调用
如果你想脚本调用代理器, 我们建议你保存代理器为预制件和在每一步或者重置时实例化. 如果你想这么做, 你可以使用`GiveBrain(brain)`来拥有代理器.
你也能用 `RemoveBrain()` 从brain中取消
# 定义反馈函数
这个奖励函数用来奖励或者惩罚代理器发生行为.
参数调整的参考*****
* 奖励
* 得分
* 还活着
* 成功消灭敌人
* 获得HP
* 上升阶级
* 惩罚
* 受伤
* 下跌阶级
* 代理器死亡
小的惩罚同样被在每一步以 最佳代理行为是尽可能快地完成一训练集
注意 奖励在每一步中都重置为0, 你必须添加奖励 (`reward += rewardIncrement`). 如果你在Academy中使用`skipFrame` 和设置你的奖励不是递增的, 因为奖励每步而不是每帧你会丢失信息.
## Agent Monitor
* 你可以添加 `AgentMonitor.cs` t每个代理器中 `YourNameAgent.cs`. 在inspector面板, 你可以看到:
* `Fixed Position` : 如果被勾选, 检测器 会一直在屏幕的左上角. 注意你只能使用一个检测器,否则左上角会重合.
* `Vertical Offset`:如果`Fixed Position`没有被勾选, 检测器会一直跟着代理器. 使用`Vertical Offset`来决定检测器离代理器多远
* `Display Brain Name` : brain名,如果有同名的代理器在不同的brain那么这个选项就很有用
* `Display Brain Type` : 展示brain的类型.
* `Display FrameCount` : 从代理器开始到现在的帧数.
* `Display Current Reward`: 实时获取代理器获得的奖励数
* `Display Max Reward` : 从训练会话开始,获得的最大奖励.
* `Display State` : 代理器的状态.
* `Display Action` : 代理器的行为.
如果从外部brain中传入值, 那么这个值会在检测器上用条状来展示 (绿色代表正数 /红色代表负数).
这个条状最大值默认为1
但如果代理器的值大于这个值,那么代理器的值会被设为最大值
请关注我的微信公众号获取有关unity机器学习的推送: