

本文属于机器翻译版本。若本译文内容与英语原文存在差异，则一律以英文原文为准。

# 训练和评估 AWS DeepRacer 模型
<a name="create-deepracer-project"></a>

 当您的 AWS DeepRacer 车辆沿着轨道行驶时，它会通过安装在正面的摄像头捕捉环境状态，并根据观察结果采取行动。您的 AWS DeepRacer 模型是一个将观察结果和操作映射到预期奖励的函数。训练您的模型是要找到或学习最大化预期奖励的函数，这使得经优化的模型能够规定您的车辆可以采取哪些行动（速度和转向角对）以便车辆从头到尾都沿赛道行驶。

在实际应用中，该函数由一个神经网络表示，该网络的训练包括找到给定观察到的环境状态序列下的最佳网络权重和相应的车辆行动。最优性的基本标准由模型的奖励函数描述，该函数鼓励车辆在不造成交通事故或违规的情况下合法而有效地行驶。简单的奖励函数可以返回 0（如果车辆在赛道上）、-1（如果车辆不在赛道上）和 \$11（如果车辆到达终点）。利用此奖励函数，车辆会因离开赛道而收到惩罚，并因到达目的地而获得奖励。如果时间或速度不是问题，这可能是一个很出色的奖励函数。

 假设您想让车辆在不偏离直线赛道的情况下尽可能快速地行驶。当车辆加速和减速时，车辆可左右转向以避开障碍物或保持在赛道内。在高速行驶时转向过大很容易导致车辆偏离赛道。转向过小可能无法帮助避免与障碍物或其他车辆相撞。一般来说，最佳操作是以较低的速度进行较大的转向或沿较锐利的曲线较小转向。为了鼓励这种行为，你的奖励函数必须分配一个正分来奖励速度更快的小回合， and/or 一个负分来惩罚速度更快的较大回合。类似地，奖励函数可以对沿着更直的路线加速或接近障碍物时减速返回正奖励。

奖励功能是您的 AWS DeepRacer 模式的重要组成部分。在训练 AWS DeepRacer 模型时，您必须提供它。训练涉及在赛道上从起点到终点的重复情节。在一个情节中，代理将与赛道交互以通过最大化预期的累积奖励来了解最佳的行动方案。最后，训练将产生一个强化学习模型。在训练之后，代理通过对模型运行推断来实施自动驾驶，以在任何给定状态下采取最佳行动。这可以在使用虚拟代理的模拟环境中完成，也可以在带有物理代理（例如 AWS DeepRacer 规模的车辆）的真实环境中完成。

 要在实践中训练强化学习模型，您必须选择一种学习算法。目前，AWS DeepRacer 控制台仅支持近端策略优化 ([PPO](https://arxiv.org/pdf/1707.06347.pdf)) 和软角色批评者 (SAC) 算法。然后，您可以选择支持所选算法的深度学习框架，除非您想从头开始编写。AWS DeepRacer 与 A SageMaker I 集成，使一些常用的深度学习框架（例如 [TensorFlow](https://www.tensorflow.org/)）在 AWS DeepRacer 控制台中随时可用。使用框架可以简化训练作业的配置和执行，并使您能够专注于创建和增强特定于您的问题的奖励函数。

 训练强化学习模型是一个迭代过程。首先，定义一个奖励函数来一次性覆盖代理在环境中的所有重要行为，这是很有挑战性的。其次，通常会调整超参数以确保令人满意的训练绩效。两者都需要试验。谨慎的做法是从简单的奖励函数开始，然后逐步增强。AW DeepRacer S 使您能够克隆经过训练的模型，然后使用它来启动下一轮训练，从而简化了这一迭代过程。在每次迭代中，您可以向奖励函数引入一个或多个更复杂的处理方法来处理之前忽略的变量，也可以系统地调整超参数直到结果收敛。

 与机器学习中的一般实践一样，您必须先评估一个训练后的强化学习模型以确定其有效性，然后再将它部署到物理代理以在实际情况中运行推理。对于自动驾驶，评估可以基于车辆从开始到结束在指定赛道上停留的频率或车辆在不偏离赛道的情况下完成路线的速度。借助 AWS DeepRacer 模拟，您可以运行评估并发布性能指标，以便在[排行榜](deepracer-racing-series.md)上与其他 AWS DeepRacer 用户训练的模型进行比较。

**Topics**
+ [了解赛车类型并启用 AWS 支持的传感器 DeepRacer](deepracer-choose-race-type.md)
+ [使用 AWS DeepRacer 控制台训练和评估 AWS DeepRacer 模型](deepracer-console-train-evaluate-models.md)
+ [AWS DeepRacer 奖励功能参考](deepracer-reward-function-reference.md)

# 了解赛车类型并启用 AWS 支持的传感器 DeepRacer
<a name="deepracer-choose-race-type"></a>

在 AWS Le DeepRacer ague 中，您可以参加以下类型的赛车赛事：
+ **计时赛**：在畅通无阻的赛道上争分夺秒，力求以最快的速度完成一圈。
+ **避障赛**：在有固定障碍物的赛道上争分夺秒，力求以最快的速度完成一圈。
+ **Head-to-bot 赛车**：在同一条赛道上与一辆或多辆其他车辆竞赛，目标是在其他车辆之前越过终点线。

AWS DeepRacer 社区竞赛目前仅支持计时赛。

您应该在 AWS DeepRacer 车辆上尝试使用不同的传感器，使其具备足够的能力来观察给定比赛类型的周围环境。下一节将介绍 [AWS DeepRacer 支持的传感器，这些传感器](#deepracer-how-it-works-autonomous-driving-sensors)可以支持支持的自动驾驶赛事类型。

**Topics**
+ [为 AWS DeepRacer 赛车类型选择传感器](#deepracer-how-it-works-autonomous-driving-sensors)
+ [配置用于训练 AWS DeepRacer 模型的代理](#deepracer-configure-agent)
+ [为计时赛量身定制 AWS DeepRacer 培训](#deepracer-get-started-training-simple-time-trial)
+ [为避开物体竞赛量身定制 AWS DeepRacer 训练](#deepracer-get-started-training-object-avoidance)
+ [为 head-to-bot比赛量身定制 AWS DeepRacer 训练](#deepracer-get-started-training-h2h-racing)

## 为 AWS DeepRacer 赛车类型选择传感器
<a name="deepracer-how-it-works-autonomous-driving-sensors"></a>

您的 AWS DeepRacer 车辆配有前置单目摄像头作为默认传感器。您可以添加另一台前置单目摄像机来制作前置立体摄像机，或者使用 LiDAR 单元来补充单目摄像机或立体摄像机。

以下列表总结了 AWS DeepRacer 支持的传感器的功能以及简要 cost-and-benefit分析：

**前置摄像机**  <a name="term-deepracer-sensor-front-facing-monocular-camera"></a>
 单镜头前置摄像机可以捕捉主机赛车前方环境的图像，包括赛道边界和形状。它是最便宜的传感器，适用于处理更简单的自动驾驶任务，例如在标记良好的赛道上进行无障碍计时赛。通过适当的训练，它可以避开赛道上固定位置的静止障碍物。但是，障碍物位置信息内置在经过训练的模型中，因此，该模型可能会过度拟合，并且可能无法推广到其他障碍物的放置位置。当静止物体放置在随机位置上或赛道上有其他移动的赛车时，模型不太可能聚合。  
在现实世界中，AWS DeepRacer 车辆配备了单镜头前置摄像头作为默认传感器。该摄像机配备 120 度广角镜头，可捕获 RGB 图像，然后以每秒 15 帧 (fps) 的速度将其转换为 160 x 120 像素的灰度图像。这些传感器属性保留在模拟器中，以最大限度地提高训练后的模型从仿真顺利转移到现实世界的机会。

**前置立体摄像机**  <a name="term-deepracer-sensor-front-facing-stereo-cameras"></a>
立体摄像机有两个或更多镜头，可以以相同的分辨率和频率捕捉图像。来自两个镜头的图像用于确定观测到的物体的深度。来自立体摄像机的深度信息对于主机赛车非常有用，可以避免撞到前方的障碍物或其他赛车，尤其是在更动态的环境下。但是，增加的深度信息会使训练的收敛速度更慢。  
 在 AWS DeepRacer 实体车辆上，双镜头立体摄像头是通过添加另一台单镜头摄像头并将每个摄像头安装在车辆的左侧和右侧来构造的。AWS DeepRacer 软件可同步两台摄像机拍摄的图像。捕获的图像被转换为灰度图像，堆叠起来，然后输入神经网络进行推理。在模拟器中复制了相同的机制，以便训练模型很好地推广到现实世界的环境。

**LiDAR 传感器**  <a name="term-deepracer-sensor-rear-mount-lidar"></a>
 LiDAR 传感器使用旋转激光发出可见光谱之外的光脉冲，以及每个脉冲返回所需的时间。特定脉冲击中的物体的方向和距离被记录为以 LiDAR 单元为中心的大型 3D 地图中的一个点。  
例如，LiDAR 可以帮助探测主赛车的盲点，以避免在赛车变道时发生碰撞。通过将 LiDAR 与单目或立体摄像机相结合，可以使主机赛车捕获足够的信息，从而采取适当的行动。但是，与摄像机相比，LiDAR 传感器的成本更高。神经网络必须学习如何解析 LiDAR 数据。因此，需要更长的时间训练才能收敛。  
 在 AWS DeepRacer 实体车辆上，LiDAR 传感器安装在后部并向下倾斜 6 度。它以每秒 10 次旋转的角速度旋转，范围为 15 厘米到 2 米。它可以检测主机赛车后方和旁边的物体，以及不受赛车部件阻挡的前方高大物体。选择角度和范围是为了使 LiDAR 单元不易受到环境噪声的影响。

 您可以使用以下支持的传感器组合来配置 AWS DeepRacer 车辆：
+ 仅限前置单镜头摄像机。

  这种配置非常适合计时赛，也适合在固定位置有物体的避障赛。
+ 仅前置立体摄像机。

  这种配置非常适合在固定或随机位置有物体的避障赛。
+ 带 LiDAR 的前置单镜头摄像机。

  这种配置非常适合避障或 head-to-bot赛车。
+ 带 LiDAR 的前置立体摄像机。

  这种配置非常适合避障或 head-to-bot赛车，但对于计时赛来说，可能不是最经济的。

当您添加更多传感器以使您的 AWS DeepRacer 车辆从计时赛到避开物体再到 head-to-bot赛车时，车辆会收集更多有关环境的数据，以便在训练中输入底层神经网络。这使得训练更具挑战性，因为模型需要处理日益增加的复杂性。最后，您学习训练模型的任务变得更加艰巨。

要逐步学习，你应该先开始计时赛训练，然后再开始避开物体，然后再开始 head-to-bot比赛。您将在下一节中找到更多详细建议。

## 配置用于训练 AWS DeepRacer 模型的代理
<a name="deepracer-configure-agent"></a>

 要训练强化学习模型，让 AWS DeepRacer 车辆参加避障或 head-to-bot赛车比赛，您需要为代理配置适当的传感器。对于简单的计时赛，您可以使用配置了单镜头摄像机的默认代理。在配置代理时，您可以自定义操作空间并选择神经网络拓扑，以便它们能够更好地与所选传感器配合使用，满足预期的行驶要求。此外，您还可以在训练期间更改代理的外观以在视觉上帮助识别。

配置后，代理配置将记录为模型元数据的一部分，用于训练和评估。为了进行评估，代理会自动检索记录的配置，以使用指定的传感器、操作空间和神经网络技术。

本部分将引导您完成在 AWS DeepRacer 控制台中配置代理的步骤。

**在 AWS DeepRacer 控制台中配置 AWS DeepRacer 代理**

1. 登录 A [WS DeepRacer 控制台](https://console.aws.amazon.com/deepracer)。

1. 在主导航窗格中选择 **Garage (车库)**。

1. 首次使用 **Garage (车库)** 时，您会看到 **WELCOME TO THE GARAGE (欢迎使用车库)** 对话框。选择 **>** 或 **<** 浏览 AWS DeepRacer 车辆支持的各种传感器的简介，或者选择 **X** 关闭对话框。您可以在 **Garage (车库)** 的帮助面板中找到此介绍性信息。

1. 在 **Garage (车库)** 页面上，选择 **Build new vehicle (构建新车辆)**。

1.  在 **Mod your own vehicle (改装自己的车辆)** 页面上，在 **Mod specifications (改装规范)** 下，选择一个或多个传感器，尝试了解能够满足预期赛车类型的最佳组合。

   要为你的 AWS DeepRacer 车辆计时赛进行训练，请选择 C **amera**。对于避障或 head-to-bot赛车，您需要使用其他类型的传感器。要选择**立体摄像机**，请确保您已经购买了额外的单镜头摄像机。AWS 用两台单镜头相机 DeepRacer 制造了立体相机。您可以在一辆车上使用单镜头摄像机或双镜头立体摄像机。无论哪种情况，如果您只想让经过训练的模型能够检测和避开避避避障碍物或 head-to-bot赛车中的盲点，则可以在代理中添加激光雷达传感器。

1. 在 **Garage (车库)** 页面的 **Neural network topologies (神经网络拓扑)** 下，选择支持的网络拓扑。

   一般来说，更深的神经网络（层次较多）更适合在具有复杂曲线和急转弯的更复杂赛道上行驶、规避静止障碍物的比赛或与其他移动车辆的比赛。但是，更深的神经网络的训练成本更高，模型需要更长的时间才能融合。另一方面，更浅的网络（层次较少）成本更低，需要的训练时间更短。训练后的模型能够处理较简单的赛道条件或行驶要求，例如在没有竞争对手的无障碍赛道上进行的计时赛。

   具体而言，AWS DeepRacer 支持 **3 层 CNN** 或 **5 层** CNN。

1. 在 **Garage (车库)** 页面上，选择 **Next (下一步)** 以继续设置代理的操作空间。

1. 在 **Action space (操作空间)** 页面上，保留第一次训练的默认设置。对于后续训练，请尝试不同的转向角度、最高速度及其粒度设置。然后选择**下一步**。

1. 在 “为**你的车辆着色以在人群中脱颖而出**” 页面上，在 “命**名你的**车型” 中输入一个名字， DeepRacer然后从**车辆颜色列表中为特工选择一种颜色**。然后，选择 **Submit (提交)**。

1. 在 **Garage (车库)** 页面上，检查新代理的设置。要进行其他修改，请选择 **Mod vehicle (改装车辆)**，然后从**步骤 4** 开始重复上述步骤。

现在，您的代理已准备好进行训练了。

## 为计时赛量身定制 AWS DeepRacer 培训
<a name="deepracer-get-started-training-simple-time-trial"></a>

如果这是您首次使用 AWS DeepRacer，则应从简单的计时赛开始，熟悉如何训练 AWS DeepRacer 模型来驾驶您的车辆。这样，您就可以更好地了解奖励函数、代理、环境等基本概念。您的目标是训练一个模型，让赛车保持在赛道上并尽可能快地完成一圈。然后，您可以将经过训练的模型部署到您的 AWS DeepRacer 车辆上，在无需任何额外传感器的情况下在物理轨道上测试驾驶。

要针对此场景训练模型，您可以从 AWS DeepRacer 控制台上的 **Garag** e 中选择默认代理。默认代理已配置为单个前置摄像机、默认操作空间和默认神经网络拓扑。在转向更复杂的 DeepRacer 模型之前，使用默认代理开始训练 AWS 模型会很有帮助。

要使用默认代理训练模型，请遵循以下建议。

1. 开始使用形状更规则且转弯较少的简单赛道来训练模型。使用默认的奖励函数。然后训练模型 30 分钟。训练作业完成后，在同一条赛道上评估您的模型，以观察代理能否完成一圈。

1. 阅读有关[奖励函数参数](deepracer-reward-function-input.md)的信息。通过不同的激励措施继续训练，以奖励代理人更快地前进。将下一个模型的训练时间延长到 1-2 小时。比较第一次训练和第二次训练之间的奖励图。继续试验，直到奖励图表停止改善。

1. 阅读有关[操作空间](deepracer-how-it-works-action-space.md)的更多信息。通过提高最高速度（例如 1 m/s）对模型进行第 3 次训练。要修改操作空间，您必须在有机会进行修改时在**车库**中建造一个新的代理。更新代理的最高速度时，请注意，最高速度越高，代理在评估中完成赛道的速度就越快，您的 AWS DeepRacer 车辆在物理赛道上完成一圈的速度也就越快。但是，更高的最高速度通常意味着训练的收敛时间更长，因为代理更有可能在弯道上超冲从而偏离轨道。您可能需要降低粒度，为代理提供更多的加速或减速空间，并通过其他方式进一步调整奖励函数，以帮助训练更快地收敛。训练收敛后，评估第三个模型，看看单圈时间是否有所改善。继续探索，直到没有更多改进。

1. 选择更复杂的赛道，然后重复**步骤 1** 到**步骤 3**。在与您用来训练的赛道不同的赛道上评估您的模型，看看模型如何推广到不同的虚拟轨道并[推广到现实世界的环境](deepracer-how-it-works-virtual-to-physical.md)。

1. （可选）尝试不同的[超参数](deepracer-console-train-evaluate-models.md#deepracer-iteratively-adjust-hyperparameters)值以改进训练过程，然后重复**步骤 1** 到**步骤 3**。

1. （可选）检查和分析 AWS DeepRacer 日志。有关可用于分析日志的示例代码，请参阅 [https://github.com/aws-samples/aws-deepracer-workshops/tree/master/log-](https://github.com/aws-samples/aws-deepracer-workshops/tree/master/log-analysis) analysis。

## 为避开物体竞赛量身定制 AWS DeepRacer 训练
<a name="deepracer-get-started-training-object-avoidance"></a>

 

在您熟悉计时赛并训练了几个融合模型之后，接下来是下一个要求更高的挑战——避障赛。在这里，您的目标是训练一个能够在不偏离轨道的情况下尽可能快地完成一圈的模型，同时避免撞到放置在赛道上的物体。对于代理来说，这显然是一个更难学习的问题，而且训练需要更长的时间才能收敛。

AWS DeepRacer 控制台支持两种类型的避障训练：可以将障碍物放置在轨道上的固定位置或随机位置。在固定位置下，障碍物在整个训练作业中都固定在同一位置。在随机位置下，障碍物会随机改变各自的位置。

由于系统的自由度较低，因此对于固定位置的避障赛，训练更容易收敛。但是，当位置信息内置到训练后的模型中时，模型可能会过度拟合。因此，模型可能过度拟合，可能无法很好地推广。为了避开随机放置的障碍物，训练更难融合，因为代理必须不断学习，避免在以前从未见过的地方碰到障碍物。但是，使用此选项训练的模型往往可以更好地推广，并且可以很好地转移到现实世界的比赛中。首先，在固定位置放置障碍物，熟悉行为，然后应对随机位置。

在 AWS DeepRacer 模拟器中，障碍物是长方体箱子，其尺寸（9.5 英寸（长）x 15.25 英寸（宽）x 10/5 英寸（高））与 AWS 车辆的包裹箱相同。 DeepRacer 如果您将包装盒作为障碍物放在物理赛道上，则可以更轻松地将经过训练的模型从模拟器转移到现实世界。

要尝试避障，请遵循以下步骤中概述的推荐做法：

1. 使用默认代理或通过自定义现有代理或构建新代理来尝试新的传感器和操作空间。您应将最高速度限制在 0.8 以下 m/s ，将速度粒度限制为 1 或 2 级。

   首先在固定位置放置 2 个物体，训练模型约 3 小时。使用示例奖励函数，在您将要参加比赛的赛道或与该赛道非常相似的赛道上训练模型。**AWS S DeepRacer mile Speedway（中级）**赛道是一条简单的赛道，这使其成为准备登顶比赛的不错选择。在同一赛道上放置相同数量的障碍物，以评估模型。观察预期的奖励融合数（如果有）。

1. 阅读有关[奖励函数参数](deepracer-reward-function-input.md)的信息。试用您的奖励函数的变体。将障碍物数量增加到 4。训练代理，看看训练是否在相同的训练时间内趋于一致。如果没有，请再次调整奖励函数，降低最高速度或减少障碍物的数量，然后再次训练代理。重复试验，直到没有更显著的改进。

1. 现在，继续训练避开随机位置的障碍物。您需要为代理配置其他传感器，这些传感器可从 **Garag** e 的 AWS DeepRacer 控制台中获得。您可以使用立体摄像机。或者，您可以将 LiDAR 单元与单镜头摄像机或立体摄像机结合使用，但训练时间应该更长。将操作空间设置为相对较低的最高速度（例如 2 m/s），以便训练更快地收敛。对于网络架构，请使用浅层神经网络，经发现，该网络足以避障。

1. 开始训练新代理 4 个小时的避障，在简单的赛道上随机放置 4 个物体。然后在同一条赛道上评估您的模型，看看它能否在随机放置障碍物的情况下完成圈数。如果不行，您可能需要调整奖励函数，尝试不同的传感器并延长训练时间。另一个技巧是，您可以尝试克隆现有模型以继续训练，以利用以前学到的经验。

1. （可选）为操作空间选择更高的最高速度，或者在赛道上随机放置更多障碍物。尝试不同的传感器组合，调整奖励函数和超参数值。尝试 **5 层 CNN** 网络拓扑。然后，重新训练模型以确定它们如何影响训练的收敛性。

## 为 head-to-bot比赛量身定制 AWS DeepRacer 训练
<a name="deepracer-get-started-training-h2h-racing"></a>

在完成了避障训练之后，你现在已经准备好迎接更高级别的挑战了：为 head-to-bot比赛训练模型。与避障赛事不同， head-to-bot赛车的环境充满活力，车辆在移动。您的目标是训练您的 AWS DeepRacer 车辆的模型，使其与其他行驶中的车辆竞争，从而在不偏离轨道或撞向任何其他车辆的情况下先到达终点线。在 AWS DeepRacer 控制台中，您可以让您的代理与 1-4 辆机器人车辆竞争，从而训练 head-to-bot赛车模型。一般来说，您应该在更长的赛道上设置更多的障碍物。

每辆自动程序赛车都以恒定速度沿着预定义的路径行驶。您可以让它改变车道或保持在起跑车道上。与避障训练类似，您可以让自动程序赛车在两条车道上均匀分布在赛道上。控制台限制您在赛道上最多有 4 辆自动程序车辆。赛道上有更多的竞争赛车可以让学习代理有更多机会与其他赛车一起面对更多不同的情况。这样，它可以在一次训练作业中学到更多知识，并且代理可以更快地接受训练。但是，每次训练可能需要更长的时间才能收敛。

要使用自动程序赛车训练代理，应将代理操作空间的最高速度设置为高于自动程序赛车的（恒定）速度，以便代理在训练期间有更多的超越机会。作为一个好的起点，你应该将特工的最高速度设置为0.8 m/s ，将机器人飞行器的移动速度设置为0.4 m/s。如果您允许自动程序车辆变道，则训练将变得更具挑战性，因为代理不仅必须学习如何避免在同一车道上撞上前方行驶中的赛车，还必须学习如何避免在另一条车道上撞上前方行驶中的另一辆行驶中的赛车。您可以将自动程序车辆设置为以随机间隔更改车道。间隔长度是在开始训练作业之前从您指定的时间范围（例如 1s 到 5s）中随机选择的。这种变道行为更类似于现实世界的 head-to-bot赛车行为，训练有素的经纪人应该能产生更好的表现。但是，模型将需要更长的训练时间来收敛。

请按照以下建议步骤重复 head-to-bot赛车训练：

1. 在 AWS DeepRacer 控制台的 **Garag** e 中，构建一个配置有立体摄像头和激光雷达单元的新训练代理。仅使用立体摄像机对抗自动程序赛车，就可以训练出相对较好的模型。当代理变道时，LiDAR 有助于减少盲点。不要将最高速度设置得太高。1 m/s 是一个好起点。

1. 要进行 head-to-bot赛车训练，请从两辆机器人车辆开始。将机器人的移动速度设置为低于代理的最高速度（例如， m/s 如果代理的最高速度为 1 m/s，则为 0.5）。禁用变道选项，然后选择您刚创建的训练代理。使用其中一个奖励函数示例或进行最少的必要修改，然后训练 3 小时。使用您将要参加比赛的赛道，或者使用与该赛道非常相似的赛道。**AWS S DeepRacer mile Speedway（中级）**赛道是一条简单的赛道，这使其成为准备登顶比赛的不错选择。训练完成后，在同一赛道上评估训练后的模型。

1. 要完成更具挑战性的任务，请克隆你训练过的模型以制作第二个 head-to-bot赛车模型。继续使用更多自动程序赛车进行实验，或者启用变道选项。从随机间隔超过 2 秒的慢速变道操作开始。您可能还想尝试使用自定义奖励函数。通常，如果您不考虑超越其他赛车和保持正轨之间的平衡，则您的自定义奖励函数逻辑可能与避障的逻辑类似。基于您之前的模型表现，您可能需要再训练 3 到 6 个小时。评估您的模型并查看模型的性能。

# 使用 AWS DeepRacer 控制台训练和评估 AWS DeepRacer 模型
<a name="deepracer-console-train-evaluate-models"></a>

 要训练强化学习模型，您可以使用 AWS DeepRacer 控制台。在控制台中，创建一个训练任务，选择支持的框架以及可用的算法，添加新的奖励函数，然后配置训练设置。您也可以继续在模拟器中观看训练。您可以在中找到 step-by-step说明[训练您的第一个 AWS DeepRacer 模型](deepracer-get-started-training-model.md)。

本节介绍如何训练和评估 AWS DeepRacer 模型。其中还演示了如何创建和改进奖励函数、操作空间如何影响模型的性能以及超级参数如何影响训练成绩。您还可以了解如何克隆模型来扩展训练会话，如何使用模拟器来评估训练成绩，以及如何解决在从模拟转向真实环境时面临的一些挑战。

**Topics**
+ [创建奖励函数](#deepracer-train-models-define-reward-function)
+ [探索操作空间来训练稳健的模型](#deepracer-define-action-space-for-training)
+ [系统性调整超级参数](#deepracer-iteratively-adjust-hyperparameters)
+ [检查 AWS DeepRacer 培训工作进度](#deepracer-examine-training-progress)
+ [克隆已训练模型以开始新的训练通行](#deepracer-clone-trained-model)
+ [在模拟中评估 AWS DeepRacer 模型](#deepracer-evaluate-models-in-simulator)
+ [针对真实环境优化训练 AWS DeepRacer 模型](#deepracer-evaluate-model-test-approaches)

## 创建奖励函数
<a name="deepracer-train-models-define-reward-function"></a>

[奖励功能](deepracer-reward-function-reference.md)描述了当您的 AWS DeepRacer 车辆从赛道上的一个位置移动到新位置时的即时反馈（作为奖励或惩罚分数）。该函数的目的是鼓励车辆沿赛道快速行驶到目的地，避免事故或违规。理想的驾驶过程会由于其操作或其目标状态赢得较高的分数。非法或绕路的驾驶过程得到的分数较低。训练 AWS DeepRacer 模型时，奖励功能是唯一针对应用程序的部分。

通常，您设计奖励函数来用作激励计划。不同的激励策略会导致不同的车辆行为。要使车辆驾驶速度更快，函数应为车辆沿赛道行驶提供奖励。该函数应对车辆完成一圈用时过长或者偏离赛道进行罚分。为了避免之字形驾驶模式，可以为在赛道的直道部分转向更少的车辆进行奖分。奖励函数可在车辆通过特定里程时给出正分数，这一里程通过 [`waypoints`](deepracer-reward-function-input.md) 来测量。这可以减少等待或者在错误方向上驾驶的情况。您也可以更改奖励函数以将赛道情况考虑在内。但是，在奖励函数中越多地考虑特定于环境的信息，您训练的模型过度拟合的可能性就越高，通用性就越低。要使您的模型适用性更强，您可以探索[操作空间](#deepracer-define-action-space-for-training)。

如果激励计划未周详考虑，它可能导致[负面效应这样的意外后果](https://en.wikipedia.org/wiki/Cobra_effect)。出现这种情况是因为即时反馈是必要的，但没有足够的条件用于强化学习。单独的即时奖励本身也无法确定驾驶路线是否理想。在特定位置，一个驾驶路线可以获得较高的奖励。随后的驾驶路线可能会偏离赛道，得到较低的分数。在这种情况下，车辆在该位置应该按高分驾驶路线行驶。只有当平均而言，从给定位置往后的所有移动会得到高分时，才认为前往下一个位置的驾驶路线是理想的。未来的反馈按一定比例折扣，使得在平均奖励计算中，只包含少量以后的驾驶路线或位置。

创建[奖励函数](deepracer-reward-function-reference.md)的一个良好做法是先创建一个涵盖基本场景的简单函数。您可以增强函数来处理更多操作。现在我们来看一些简单的奖励函数。

**Topics**
+ [简单奖励函数示例](#deepracer-reward-function-simple-examples)
+ [增强奖励函数](#deepracer-iteratively-enhance-reward-functions)

### 简单奖励函数示例
<a name="deepracer-reward-function-simple-examples"></a>

我们可以通过首先考虑最基本的情况来构建奖励函数。也就是在直道上从起点行驶到终点且不偏离赛道的情况。在这种情况下，奖励函数逻辑仅依赖于 `on_track` 和 `progress`。作为试验，您可以从以下逻辑开始：

```
def reward_function(params):
    if not params["all_wheels_on_track"]:
        reward = -1
    else if params["progress"] == 1 :
        reward = 10
    return reward
```

此逻辑在代理行驶偏离赛道时进行罚分。在代理行驶到终点线时奖分。这对实现既定目标是合理的。但是，代理会在起点线和终点线之间自由行驶，包括在赛道上向后行驶。训练不仅可能需要很长时间才能完成，并且训练模型在部署到实际车辆中时会导致驾驶效率低下。

实际上，如果代理能够在 bit-by-bit整个培训过程中进行学习，则学习效率会更高。这意味着奖励函数应该随着车辆在赛道上的行进逐渐加大给予的奖励。为了让代理在直线赛道上驾驶车辆，我们可以按下面所示改进奖励函数：

```
def reward_function(params):
    if not params["all_wheels_on_track"]:
        reward = -1
    else:
        reward = params["progress"]
    return reward
```

 利用此函数，代理可以在越接近终点线时获得更多奖励。这应该减少或消除向后驾驶的非生产性试验。通常，我们希望奖励函数在操作空间上更均匀地分配奖励。创建有效的奖励函数可能是一项颇具挑战性的任务。您应该从一个简单的函数开始，并逐步增强或改进该函数。对于系统性试验，函数可能会更稳健和高效。

### 增强奖励函数
<a name="deepracer-iteratively-enhance-reward-functions"></a>

在您成功训练了简单直道的 AWS DeepRacer 模型后，AWS DeepRacer 车辆（虚拟或物理）可以在不偏离赛道的情况下自行驾驶。如果您让车辆在环形赛道上行驶，它将不会保持在赛道上。奖励函数忽略了通过转弯来保持在赛道上的操作。

要使车辆处理这些操作，您必须增强奖励函数。在代理进行允许的转弯时，函数应该予以奖励，如果代理做出了非法转弯，则应给予罚分。然后，您便可以开始另一轮训练。要利用以前的训练，您可以通过克隆以前训练的模型并传递以前学习的知识来开始新的训练。您可以按照这种模式逐步向奖励功能添加更多功能，以训练您的 AWS DeepRacer 车辆在日益复杂的环境中行驶。

有关更高级的奖励函数，请参阅以下示例：
+ [示例 1：在计时赛中紧贴中心线行驶](deepracer-reward-function-examples.md#deepracer-reward-function-example-0)
+ [示例 2：在计时赛中保持在界内](deepracer-reward-function-examples.md#deepracer-reward-function-example-1)
+ [示例 3：在计时赛中防止之字形行驶](deepracer-reward-function-examples.md#deepracer-reward-function-example-2)
+ [示例 4：保持在一条车道而不撞到静止障碍物或移动的车辆](deepracer-reward-function-examples.md#deepracer-reward-function-example-3)

## 探索操作空间来训练稳健的模型
<a name="deepracer-define-action-space-for-training"></a>

作为通则，您训练的模型应该尽可能稳健，这样就可以将其应用到尽可能多的环境。稳健的模型是可以应用到广泛赛道形状和条件的模型。一般而言，一个稳健的模型不够“智能”，因为其奖励函数没有包含特定于环境的具体知识的能力。否则，您的模型更可能仅适用于类似于训练环境的环境。

在奖励函数中明确包含特定于环境的信息会导致特征工程。特征工程有助于减少训练时间，在针对特定环境定制解决方案时会很有用。但是，要训练具有一般适用性的模型，您应该避免尝试大量特征工程。

例如，在圆形赛道上训练模型时，如果您在奖励函数中明确包含了这种集合属性，就不能预期得到适合任何非圆形赛道的训练模型。

如何才能在训练出尽可能稳健的模型的同时，确保奖励函数尽可能简单？ 探索操作空间的一种方法是生成您的代理可以采取的操作。另一种是通过基础训练算法的[超级参数](#deepracer-iteratively-adjust-hyperparameters)进行实验。通常，您同时使用这两种方法。在这里，我们将重点介绍如何探索操作空间，为您的 AWS DeepRacer 车辆训练一个强大的模型。

在训练 AWS DeepRacer 模型时，动作 (`a`) 是速度（`t`米/秒）和转向角度（以度为单位）`s`的组合。代理的操作空间定义了代理可以使用的速度和转向角度范围。对于具有 `m` 个速度、`(v1, .., vn)` 和 `n` 个转向角度的不连续操作空间 `(s1, .., sm)`，操作空间中有 `m*n` 个可能的操作：

```
a1:           (v1, s1)
...
an:           (v1, sn)

...
a(i-1)*n+j:   (vi, sj)
...

a(m-1)*n+1:   (vm, s1)
...
am*n:         (vm, sn)
```

`(vi, sj)` 的实际值取决于 `vmax` 和 `|smax|` 的范围，不均匀分布。

每次开始训练或迭代 AWS DeepRacer 模型时，都必须先指定`n``m`、`vmax`和 `|smax|` /或同意使用其默认值。根据您的选择，AWS DeepRacer 服务会生成您的代理可在培训中选择的可用操作。生成的操作并非均匀分布在操作空间上。

一般情况下，操作数越多、操作范围越大就会向您的代理提供更多的空间或选项，从而根据赛道情况做出更为多变的选择，例如具有不规则转弯角度或方向的弯曲赛道。对代理可用的选项越多，就越能处理赛道情况变化。因此，您即使使用简单奖励函数，训练模型也可以有广泛的应用范围。

例如，您的代理可以使用粗粒度的操作空间，其中只有少量速度和转弯角度，快速学习如何处理直线赛道。在弯曲赛道上，此粗粒度的操作空间可能会导致代理转过头，在转弯时偏离赛道。这是因为没有足够的选项供其处理来调整速度或转弯。增加速度数量和/或转弯角度数量，代理应该具备更好的能力来处理转弯，保持在赛道上。同样，如果您的代理以之字形移动，您可以尝试增加转向范围的数量，从而减少在任意给定步骤中的突然转向。

当操作空间太大时，训练性能可能会受到负面影响，因为探索操作空间用时更长。请确保在模型的一般适用性与训练性能要求之间实现效益平衡。这种优化涉及系统性实验。

## 系统性调整超级参数
<a name="deepracer-iteratively-adjust-hyperparameters"></a>

提升模型性能的一种方法是制订更好或更高效的训练过程。例如，为获取稳健的模型，在代理的操作空间中，训练必须向代理提供或多或少的均匀分布采样。这需要充分权衡探索和开发。影响这些情况的变量包括所用的训练数据量（`number of episodes between each training` 和 `batch size`）、代理学习的速度 (`learning rate`) 以及探索部分 (`entropy`)。要使训练切实可行，您可能需要加快学习过程。影响这一情况的变量包括 `learning rate`、`batch size`、`number of epochs` 和 `discount factor`。

影响训练过程的变量称为超级参数。这些算法特性并非基础模型的属性。遗憾的是，超级参数本质上是经验性的。其最佳值对于所有实际用途未知，需要通过系统性实验来得出。

在讨论可以调整以调整 AWS DeepRacer 模型训练性能的超参数之前，让我们定义以下术语。

数据点  
数据点也称为*经验*，它是 (*s,a,r,s’*) 的元组，其中 *s* 表示摄像头捕捉到的观察（或者状态），*a* 表示车辆采取的操作，*r* 表示所述操作带来的预期奖励，以及 *s’* 表示在采取之后的新观察。

情节  
情节是一段时间，在这段时间中，车辆从给定起点启动，然后到达终点完成赛道，或者跑出赛道。它是一系列经验的具体表达。不同的情节可以有不同的长度。

经验缓冲区  
经验缓冲区包含多个已排序的数据点，在训练过程中，从不同长度的固定数量情节上收集这些数据点。对于 AWS DeepRacer，它对应于安装在您的 AWS DeepRacer 车辆上的摄像头拍摄的图像以及车辆采取的行动，并作为从中提取用于更新底层（策略和价值）神经网络的输入来源。

Batch  
批次是排序的经验列表，表示一段时间中的一部分模拟，用于更新策略网络权重。它是经验缓冲区的子集。

训练数据  
训练数据是从经验缓冲区中随机采样的批次组，用于训练策略网络权重。




**算法超级参数及其效果**  

| 超参数 | 说明 | 
| --- | --- | 
|  **Gradient descent batch size (梯度下降批大小)**   | 从经验缓冲区中随机采样的最近车辆经验数，用于更新基础深度学习神经网络权重。随机采样有助于减少输入数据中内在的关联。使用较大的批大小可以推动对神经网络更稳定和更平滑的更新，但需要注意训练时间较长或者速度较慢的可能性。[\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/zh_cn/deepracer/latest/developerguide/deepracer-console-train-evaluate-models.html) | 
|  **Number of epochs (纪元数)**  | 在梯度下降期间，遍历训练数据以更新神经网络权重的次数。训练数据对应于来自经验缓冲区的随机样本。使用较大的纪元数可以推动更稳定的更新，但预计训练速度较慢。当批大小较小时，您可以使用较少的纪元数[\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/zh_cn/deepracer/latest/developerguide/deepracer-console-train-evaluate-models.html) | 
|  **Learning rate (学习速率)**  |  在每次更新期间，新权重的一部分可以来自梯度下降（或上升）的贡献，其余部分来自现有权重值。学习速率控制控制梯度下降（或上升）更新对网络权重的贡献度。使用较高的学习速率可以包括更多的梯度下降贡献，从而加快训练，但请注意，如果学习速率太高，预期奖励可能不会收敛。 [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/zh_cn/deepracer/latest/developerguide/deepracer-console-train-evaluate-models.html)  | 
| Entropy |  用于确定何时向策略分布添加随机性的不确定性程度。增加的不确定性有助于 AWS DeepRacer 车辆更广泛地探索行动领域。较大的熵值会推动车辆更彻底地探索操作空间。 [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/zh_cn/deepracer/latest/developerguide/deepracer-console-train-evaluate-models.html)  | 
| Discount factor (折扣系数) |  系数指定了未来奖励对预期奖励的影响程度。**折扣系数**值越大，行驶过程中考虑贡献时需要考虑的距离就越远，训练就越慢。使用折扣系数 0.9，车辆根据行驶过程的接下来 10 个步骤提供奖励。使用折扣系数 0.999，车辆根据行驶过程的接下来 1000 个步骤提供奖励。建议的折扣系数值是 0.99、0,999 和 0.9999。 [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/zh_cn/deepracer/latest/developerguide/deepracer-console-train-evaluate-models.html)  | 
| Loss type (损耗类型) |  用于更新网络权重的目标函数的类型。一个良好的训练算法应该对代理的策略进行渐进式改变，使它逐渐从采取随机行动转变为采取战略性行动以增加奖励。但是，如果算法进行了过大的更改，训练将变得不稳定，代理最终也不会学习。[https://en.wikipedia.org/wiki/Huber_loss](https://en.wikipedia.org/wiki/Huber_loss) 和 [https://en.wikipedia.org/wiki/Mean_squared_error](https://en.wikipedia.org/wiki/Mean_squared_error) 类型针对小型更新的行为方式相似。但是，随着更新变得越来越大，**Huber loss (Huber 损耗)** 相比 **Mean squared error loss (均方误差损耗)** 占用的增量较小。当您遇到收敛问题时，请使用 **Huber loss (Huber 损耗)** 类型。当收敛正常并且您希望提高训练速度时，请使用 **Mean squared error loss (均方误差损耗)** 类型。 [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/zh_cn/deepracer/latest/developerguide/deepracer-console-train-evaluate-models.html)  | 
| Number of experience episodes between each policy-updating iteration (每次策略更新迭代之间的经验情节数) | 从中提取训练数据的经验缓冲区的大小，这些数据用于学习策略网络权重。经验情节是一段时间，在这段时间中，代理从给定起点启动，然后到达终点完成赛道，或者跑出赛道。它由一系列经验组成。不同的情节可以有不同的长度。对于简单强化学习问题，较小的缓冲区可能已足够，学习速度较快。对于具有更多局部最大值的更复杂问题，需要更大的经验缓冲区来提供更多不相关的数据点。在这种情况下，训练更慢但更稳定。建议的值为 10、20 和 40。[\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/zh_cn/deepracer/latest/developerguide/deepracer-console-train-evaluate-models.html) | 

## 检查 AWS DeepRacer 培训工作进度
<a name="deepracer-examine-training-progress"></a>

启动训练作业之后，您可以检查各个情节的奖励和赛道完成情况等训练指标，以便确定模型在训练作业中的性能。在 AWS DeepRacer 控制台上，指标显示在**奖励图表**中，如下图所示。

![\[\]](http://docs.aws.amazon.com/zh_cn/deepracer/latest/developerguide/images/best-model-bar-reward-graph2.png)


您可以选择查看在各个情节中赢得的奖励、每次迭代的平均奖励、每个情节的进度、每次迭代的平均进度或这些指标的任意组合。为此，请在**奖励图表**的底部切换**奖励（轮次、平均值）**或**进度（轮次、平均值）**开关。每个情节的奖励和进度以不同颜色的散点图显示。平均奖励和赛道完成情况以线形图显示，从第一次迭代之后开始。

 奖励范围显示在图形的左侧，进度范围 (0-100) 显示在右侧。要读取某个训练指标的精确值，请将鼠标移动到图形上靠近数据点的位置。

当训练仍在进行时，图形每 10 秒自动更新一次。您可以选择刷新按钮以手动更新指标显示。

如果平均奖励和赛道完成情况表现出收敛的趋势，则训练任务良好。特别是，如果每个情节的进度持续达到 100%，并且奖励呈平稳状态，则表示模型可能已收敛。如果不是，请克隆模型并重新训练。

## 克隆已训练模型以开始新的训练通行
<a name="deepracer-clone-trained-model"></a>

如果您克隆之前的训练模型作为新一轮训练的起点，就可以提升训练效率。要执行此操作，请修改超级参数以利用已经学习的知识。

在本节中，您将学习如何使用 AWS DeepRacer 控制台克隆经过训练的模型。

**使用 AWS DeepRacer 控制台对强化学习模型进行迭代训练**

1. 如果您尚未登录，请登录 AWS DeepRacer 控制台。

1. 在**模型**页面上，选择已训练的模型，然后从**操作**下拉菜单列表中选择**克隆**。

1. 对于 **Model details (模型详细信息)**，执行以下操作：

   1. 如果您不想为克隆的模型生成名称，请将 `RL_model_1` 键入 **模型名称**中。

   1. （可选）在 to-be-cloned模型描述中**描述模型-可选**。

1. 对于 **环境模拟**，请选择另一个赛道选项。

1. 对于 **Reward function (奖励函数)**，请选择可用奖励函数示例之一。修改奖励函数。例如，请考虑转向。

1. 展开 **Algorithm settings (算法设置)** 并尝试不同的选项。例如，将 **Gradient descent batch size (梯度下降批大小)** 值从 32 更改为 64，或者增加 **Learning rate (学习速率)** 以加快学习速度。

1. 使用选择的不同 **Stop conditions (停止条件)** 进行实验。

1. 选择 **Start training (开始训练)** 以开始新一轮的训练。

与平时训练稳健的机器学习模型一样，您务必进行系统的实验以找到最佳解决方案。

## 在模拟中评估 AWS DeepRacer 模型
<a name="deepracer-evaluate-models-in-simulator"></a>

评估模型是为了测试已训练模型的性能。在 AWS 中 DeepRacer，标准性能指标是连续完成三圈的平均时间。使用此指标，对于任意两个模型，如果一个模型比另一个模型能够让代理在同一个赛道上行驶得更快，那么这个模型就更好。

一般而言，评估模型涉及以下任务：

1. 配置并启动评估作业。

1. 在任务运行时观察正在进行的评估。这可以在 AWS DeepRacer 模拟器中完成。

1. 在评估任务完成后检查评估摘要。您可以随时终止正在进行的评估任务。
**注意**  
评估时间取决于您选择的标准。如果您的模型不符合评估标准，则评估将继续运行，直到达到 20 分钟的上限。

1. （可选）将评估结果提交给符合条件[的 AWS DeepRacer 排行榜](deepracer-racing-series.md)。排行榜上的排名让您可以了解您的模型相对于其他参赛者的表现如何。

使用 AWS DeepRacer 车辆在物理轨道上行驶时测试 AWS DeepRacer 模型，请参阅[操作您的 AWS DeepRacer 车辆](operate-deepracer-vehicle.md)。

## 针对真实环境优化训练 AWS DeepRacer 模型
<a name="deepracer-evaluate-model-test-approaches"></a>

许多因素会影响训练模型的真实表现，包括[操作空间](#deepracer-define-action-space-for-training)的选择、[奖励函数](#deepracer-train-models-define-reward-function)、训练中使用的[超级参数](#deepracer-iteratively-adjust-hyperparameters)以及[车辆校准](deepracer-calibrate-vehicle.md)和[真实赛道](deepracer-build-your-track.md)条件。此外，模拟仅仅是（通常很粗糙）真实世界的近似。这些情况使得将在模拟中训练的模型在应用到真实世界时，取得满意的成绩成为了一项挑战。

训练模型以提供稳定的真实性能通常需要在模拟环境中多次迭代对[奖励函数](#deepracer-train-models-define-reward-function)、[操作空间](#deepracer-define-action-space-for-training)、[超级参数](#deepracer-iteratively-adjust-hyperparameters)和[评估](#deepracer-evaluate-models-in-simulator)的探索，然后在真实环境中[测试](deepracer-drive-your-vehicle.md)。最后一步涉及所谓的*simulation-to-real 世界*（*sim2real*）转移，可能会感到笨拙。

为了帮助应对 *sim2real* 挑战，请注意以下几点：
+ 确保良好校准了您的车辆。

  这非常重要，因为模拟环境很可能是部分代表了真实环境。此外，代理在每一步中根据当前赛道情况采取操作，而赛道情况是摄像头捕获的图像。在高速下，它无法探测到足够远的距离来计划其路线。为了适应这种情况，模拟对速度和转向施加了限制。要确保训练模型在真实世界中正常工作，车辆必须经过正确的校准以匹配这些和其他模拟设置。有关校准车辆的更多信息，请参阅[校准您的 AWS 车辆 DeepRacer](deepracer-calibrate-vehicle.md)。
+ 首先使用默认模型测试您的车辆。

  您的 AWS DeepRacer 车辆带有加载到其推理引擎中的预训练模型。在真实环境中测试自己的模型之前，请确保车辆在默认模型中可以良好地运行。如果不行，请检查物理赛道设置。在修建不正确的物理赛道中测试模型可能会导致性能欠佳。在这种情况下，请重新配置或修理您的赛道，然后再启动或恢复测试。
**注意**  
在运行 AWS DeepRacer 车辆时，无需调用奖励函数即可根据经过训练的策略网络推断出操作。
+ 确保模型在模拟中正常工作。

  如果您的模型不能正常工作，可能是整个模型或赛道有缺陷。要找出根本原因，您应首先[在模拟中评估模型](#deepracer-evaluate-models-in-simulator)，检查模拟的代理是否可以至少完成一圈而不偏离赛道。您可以通过检查奖励的收敛并观察代理在模拟器中的轨迹，来查找原因。如果奖励在模拟的代理完成一圈达到最大值而没有衰退时，这可能是一个良好的模型。
+ 不要过度训练模型。

  模型在模拟中稳定地完成赛道后继续训练会导致模型中的过度拟合。过度拟合的模型无法在真实环境中良好运行，因为它无法处理哪怕是模拟赛道与真实环境中很小的差别。
+ 使用来自不同迭代的多个模型。

  典型的训练会话会生成一系列模型，这些模型介于拟合不足与过度拟合之间。因为没有先验标准来确定正好合适的模型，所以您应该从代理在模拟器中完成一圈开始，到其能稳定跑圈之间，选择几个模型候选。
+ 在测试中，从低速开始，逐步增加驾驶速度。

  测试部署到车辆上的模型时，首先从较小的最高速度值开始。例如，您可以将测试速度限制设置为小于训练速度限制 10%。然后，逐渐增加测试速度限制，直到车辆开始正常行驶。您可以在校准车辆时使用设备控制台设置测试速度限制。如果车辆的速度太快，例如速度超过了在模拟器中训练时的速度，模型在实际赛道上可能无法良好表现。
+ 使用车辆在不同开始位置测试模型。

  模型学习在模拟中采用了特定路线，可能会对其在赛道上的位置比较敏感。您应在赛道边界内的不同位置开始车辆测试（从左边到中间到右边），以查看模型是否在特定位置表现良好。大多数模型倾向于让车辆靠近白线的某一边。为了帮助分析车辆的路径，逐个步骤绘制模拟中车辆的位置 (x, y)，确定您的车辆在真实环境中可能采取的路线。
+ 在直道上开始测试。

  在直道上导航比在弯道上要容易得多。在直道上开始测试有助于快速排除欠佳的模型。如果车辆大部分时间无法按照直道行驶，模型在外道上的表现也不会好。
+ 注意车辆仅采取一种类型操作的行为，

  当您的车辆仅采取一种类型操作的行为时，例如，车辆仅向左转向，则模型可能过度拟合或拟合不足。对于给定模型参数，训练中过多迭代会导致模型过度拟合。迭代太少会导致拟合不足。
+ 注意车辆沿赛道边界纠正其路径的能力。

  良好的模型在车辆靠近赛道边界时会纠正自身。大多数良好训练的模型具有此功能。如果车辆可以在赛道两端边界纠正自己，可以认为这是一个稳健的高质量模型。
+ 注意车辆表现出的不一致行为。

  策略模型表示在给定状态下采取行动的概率分布。将训练模型加载到其推理引擎后，车辆可以根据模型的执行选择最可能的操作，一次一个步骤。如果操作概率均匀分步，则车辆采取概率相等或相近的任意一个操作。这将导致不稳定的驾驶行为。例如，当车辆一段时间（例如，一半时间）沿直线行驶，而其余时间会进行不必要的转向，那么模型拟合不足或过度拟合。
+ 注意车辆仅进行一种转向类型（左或右）的情况。

  如果车辆左转非常好但在尝试右转时出现问题，或者，如果车辆只能很好地右转但左转则不行，您需要仔细校准或重新校准车辆的转向。或者，您可以尝试使用其训练设置接近实际测试环境设置的模型。
+ 注意车辆的突然转弯和偏离赛道。

  如果车辆大部分时间按照正确路线行驶，但突然偏离赛道，则可能是由于环境的干扰。大多数常见干扰包括意外或无意识的反光。在这种情况下，在赛道周围使用隔离或者其他方式来减少眩光。

# AWS DeepRacer 奖励功能参考
<a name="deepracer-reward-function-reference"></a>

 以下是 AWS DeepRacer 奖励功能的技术参考。

**Topics**
+ [AWS DeepRacer 奖励函数的输入参数](deepracer-reward-function-input.md)
+ [AWS DeepRacer 奖励功能示例](deepracer-reward-function-examples.md)

# AWS DeepRacer 奖励函数的输入参数
<a name="deepracer-reward-function-input"></a>

AWS DeepRacer 奖励函数将字典对象作为输入。

```
def reward_function(params) :
    
    reward = ...

    return float(reward)
```

`params` 词典对象包含以下键/值对：

```
{
    "all_wheels_on_track": Boolean,        # flag to indicate if the agent is on the track
    "x": float,                            # agent's x-coordinate in meters
    "y": float,                            # agent's y-coordinate in meters
    "closest_objects": [int, int],         # zero-based indices of the two closest objects to the agent's current position of (x, y).
    "closest_waypoints": [int, int],       # indices of the two nearest waypoints.
    "distance_from_center": float,         # distance in meters from the track center 
    "is_crashed": Boolean,                 # Boolean flag to indicate whether the agent has crashed.
    "is_left_of_center": Boolean,          # Flag to indicate if the agent is on the left side to the track center or not. 
    "is_offtrack": Boolean,                # Boolean flag to indicate whether the agent has gone off track.
    "is_reversed": Boolean,                # flag to indicate if the agent is driving clockwise (True) or counter clockwise (False).
    "heading": float,                      # agent's yaw in degrees
    "objects_distance": [float, ],         # list of the objects' distances in meters between 0 and track_length in relation to the starting line.
    "objects_heading": [float, ],          # list of the objects' headings in degrees between -180 and 180.
    "objects_left_of_center": [Boolean, ], # list of Boolean flags indicating whether elements' objects are left of the center (True) or not (False).
    "objects_location": [(float, float),], # list of object locations [(x,y), ...].
    "objects_speed": [float, ],            # list of the objects' speeds in meters per second.
    "progress": float,                     # percentage of track completed
    "speed": float,                        # agent's speed in meters per second (m/s)
    "steering_angle": float,               # agent's steering angle in degrees
    "steps": int,                          # number steps completed
    "track_length": float,                 # track length in meters.
    "track_width": float,                  # width of the track
    "waypoints": [(float, float), ]        # list of (x,y) as milestones along the track center

}
```

输入参数的更多详细技术参考如下所示。

## all\$1wheels\$1on\$1track
<a name="reward-function-input-all_wheels_on_track"></a>

**类型：**`Boolean`

**范围：**`(True:False)`

一个 `Boolean` 标记，指示代理是在赛道上还是偏离赛道。如果车辆的任一车轮位于赛道边界外，则将车辆视为偏离赛道 (`False`)。如果车辆的所有车轮都在两个赛道边界内，则将车辆视为在赛道上 (`True`)。下图显示了代理在赛道上。

![\[\]](http://docs.aws.amazon.com/zh_cn/deepracer/latest/developerguide/images/deepracer-reward-function-input-all_wheels_on_track-true.png)


下图显示了代理偏离赛道。

![\[\]](http://docs.aws.amazon.com/zh_cn/deepracer/latest/developerguide/images/deepracer-reward-function-input-all_wheels_on_track-false.png)


**示例：***使用 `all_wheels_on_track` 参数的奖励函数*

```
def reward_function(params):
    #############################################################################
    '''
    Example of using all_wheels_on_track and speed
    '''

    # Read input variables
    all_wheels_on_track = params['all_wheels_on_track']
    speed = params['speed']

    # Set the speed threshold based your action space
    SPEED_THRESHOLD = 1.0

    if not all_wheels_on_track:
        # Penalize if the car goes off track
        reward = 1e-3
    elif speed < SPEED_THRESHOLD:
        # Penalize if the car goes too slow
        reward = 0.5
    else:
        # High reward if the car stays on track and goes fast
        reward = 1.0

    return float(reward)
```

## closest\$1waypoints
<a name="reward-function-input-closest_waypoints"></a>

**类型**：`[int, int]`

**范围**：`[(0:Max-1),(1:Max-1)]`

最接近代理当前位置 `(x, y)` 的两个相邻 `waypoint` 的从零开始的索引。距离是根据与代理中心的欧氏距离来测量的。第一个元素指代理后面最近的路点，第二个元素指代理前面最近的路点。`Max` 是路点列表的长度。在[waypoints](#reward-function-input-waypoints)的图示中，`closest_waypoints` 将为 `[16, 17]`。

**示例：**使用 `closest_waypoints` 参数的奖励函数。

以下示例奖励函数演示如何使用 `waypoints`、`closest_waypoints` 和 `heading` 来计算即时奖励。

AWS DeepRacer 支持以下库：数学、随机 NumPy SciPy、和 Shapely。要使用一个库，请在函数定义 `def function_name(parameters)` 的上方添加一个 import 语句 `import supported library`。

```
# Place import statement outside of function (supported libraries: math, random, numpy, scipy, and shapely)
# Example imports of available libraries
#
# import math
# import random
# import numpy
# import scipy
# import shapely

import math

def reward_function(params):
    ###############################################################################
    '''
    Example of using waypoints and heading to make the car point in the right direction
    '''

    # Read input variables
    waypoints = params['waypoints']
    closest_waypoints = params['closest_waypoints']
    heading = params['heading']

    # Initialize the reward with typical value
    reward = 1.0

    # Calculate the direction of the center line based on the closest waypoints
    next_point = waypoints[closest_waypoints[1]]
    prev_point = waypoints[closest_waypoints[0]]

    # Calculate the direction in radius, arctan2(dy, dx), the result is (-pi, pi) in radians
    track_direction = math.atan2(next_point[1] - prev_point[1], next_point[0] - prev_point[0])
    # Convert to degree
    track_direction = math.degrees(track_direction)

    # Calculate the difference between the track direction and the heading direction of the car
    direction_diff = abs(track_direction - heading)
    if direction_diff > 180:
        direction_diff = 360 - direction_diff

    # Penalize the reward if the difference is too large
    DIRECTION_THRESHOLD = 10.0
    if direction_diff > DIRECTION_THRESHOLD:
        reward *= 0.5

    return float(reward)
​
```

## closest\$1objects
<a name="reward-function-input-closest_objects"></a>

**类型**：`[int, int]`

**范围**：`[(0:len(objects_location)-1), (0:len(objects_location)-1)]`

 最接近代理当前位置 (x, y) 的两个物体的从零开始的索引。第一个索引指代理后面最近的物体，第二个索引指代理前面最近的物体。如果只有一个物体，则两个索引都为 0。

## distance\$1from\$1center
<a name="reward-function-input-distance_from_center"></a>

**类型**：`float`

**范围**：`0:~track_width/2`

代理中心和赛道中心之间的位移（以米为单位）。当代理的任一车轮位于赛道边界外时可观察到的最大位移，并且根据赛道边界的宽度，它可以略小于或大于 `track_width` 的一半。

![\[\]](http://docs.aws.amazon.com/zh_cn/deepracer/latest/developerguide/images/deepracer-reward-function-input-distance_from_center.png)


**示例：***使用 `distance_from_center` 参数的奖励函数*

```
def reward_function(params):
    #################################################################################
    '''
    Example of using distance from the center
    '''

    # Read input variable
    track_width = params['track_width']
    distance_from_center = params['distance_from_center']

    # Penalize if the car is too far away from the center
    marker_1 = 0.1 * track_width
    marker_2 = 0.5 * track_width

    if distance_from_center <= marker_1:
        reward = 1.0
    elif distance_from_center <= marker_2:
        reward = 0.5
    else:
        reward = 1e-3  # likely crashed/ close to off track

    return float(reward)
```

## heading
<a name="reward-function-input-heading"></a>

**类型**：`float`

**范围**：`-180:+180`

代理相对于坐标系 x 轴的前进方向（以度为单位）。

![\[\]](http://docs.aws.amazon.com/zh_cn/deepracer/latest/developerguide/images/deepracer-reward-function-input-heading.png)


**示例：***使用 `heading` 参数的奖励函数*

有关更多信息，请参阅 [`closest_waypoints`](#reward-function-input-closest_waypoints)。

## is\$1crashed
<a name="reward-function-input-crashed"></a>

**类型**：`Boolean`

**范围**：`(True:False)`

一个布尔标记，用于指示代理的最终状态是否为撞向另一个物体（`True` 或 `False`）。

## is\$1left\$1of\$1center
<a name="reward-function-input-is_left_of_center"></a>

**类型**：`Boolean`

**范围**：`[True : False]`

一个 `Boolean` 标记，用于指示代理是位于赛道中心的左侧 (`True`) 还是右侧 (`False`)。

## is\$1offtrack
<a name="reward-function-input-offtrack"></a>

**类型**：`Boolean`

**范围**：`(True:False)`

一个布尔标记，用于指示代理的最终状态是否为脱离赛道（True 或 False）。

## is\$1reversed
<a name="reward-function-input-is_reversed"></a>

**类型**：`Boolean`

**范围**：`[True:False]`

一个布尔标记，用于指示代理是顺时针行驶 (True) 还是逆时针行驶 (False)。

此参数在您针对每个过程改变方向时使用。

## objects\$1distance
<a name="reward-function-input-objects_distance"></a>

**类型**：`[float, … ]`

**范围**：`[(0:track_length), … ]`

环境中物体之间相对于起始线的距离列表。第 i 个元素测量沿赛道中心线第 i 个物体与起始线之间的距离。

**注意**  
abs \$1 (var1) - (var2)\$1 = 汽车与物体的接近程度, WHEN var1 = ["objects\$1distance"][index] and var2 = params["progress"]\$1params["track\$1length"]  
要获取车辆前方最近物体和车辆后方最近物体的索引，请使用“closest\$1objects”参数。

## objects\$1heading
<a name="reward-function-input-objects_heading"></a>

**类型**：`[float, … ]`

**范围**：`[(-180:180), … ]`

物体前进方向（以度为单位）列表。第 i 个元素测量第 i 个物体的前进方向。对于静止物体，其前进方向为 0。对于自动程序车辆，相应元素的值是车辆的前进角度。

## objects\$1left\$1of\$1center
<a name="reward-function-input-objects_left_of_center"></a>

**类型**：`[Boolean, … ]`

**范围**：`[True|False, … ]`

布尔标记列表。第 i 个元素值指示第 i 个物体位于赛道中心的左侧 (True) 还是右侧 (False)。

## objects\$1location
<a name="reward-function-input-objects_location"></a>

**类型**：`[(x,y), … ]`

**范围**：`[(0:N,0:N), … ]`

所有物体位置的列表，每个位置都是 ([x, y](#reward-function-input-x_y)) 的元组。

列表的大小等于赛道上的物体数。注意，物体可能是静止的障碍物，移动的自动程序车辆。

## objects\$1speed
<a name="reward-function-input-objects_speed"></a>

**类型**：`[float, … ]`

**范围**：`[(0:12.0), … ]`

赛道上物体的速度（米/秒）列表。对于静止物体，其速度为 0。对于自动程序车辆，值为您在训练中设置的速度。

## 进度
<a name="reward-function-input-progress"></a>

**类型**：`float`

**范围**：`0:100`

赛道完成百分比。

**示例：***使用 `progress` 参数的奖励函数*

有关更多信息，请参阅[步骤](#reward-function-input-steps)。

## speed
<a name="reward-function-input-speed"></a>

**类型**：`float`

**范围**：`0.0:5.0`

观察到的代理速度，以米/秒 (m/s) 为单位。

![\[\]](http://docs.aws.amazon.com/zh_cn/deepracer/latest/developerguide/images/deepracer-reward-function-input-speed.png)


**示例：***使用 `speed` 参数的奖励函数*

有关更多信息，请参阅 [all\$1wheels\$1on\$1track](#reward-function-input-all_wheels_on_track)。

## steering\$1angle
<a name="reward-function-input-steering_angle"></a>

**类型**：`float`

**范围**：`-30:30`

前轮与代理中心线之间的转向角（以度为单位）。负号 (-) 表示向右转向，正号 (\$1) 表示向左转向。代理中心线不一定与赛道中心线平行，如下图所示。

![\[\]](http://docs.aws.amazon.com/zh_cn/deepracer/latest/developerguide/images/deepracer-reward-function-steering.png)


**示例：***使用 `steering_angle` 参数的奖励函数*

```
def reward_function(params):
    '''
    Example of using steering angle
    '''

    # Read input variable
    abs_steering = abs(params['steering_angle']) # We don't care whether it is left or right steering

    # Initialize the reward with typical value
    reward = 1.0

    # Penalize if car steer too much to prevent zigzag
    ABS_STEERING_THRESHOLD = 20.0
    if abs_steering > ABS_STEERING_THRESHOLD:
        reward *= 0.8

    return float(reward)
```

## 步骤
<a name="reward-function-input-steps"></a>

**类型**：`int`

**范围**：`0:Nstep`

完成的步骤数。步骤对应于代理按照当前策略所采取的操作。

**示例：***使用 `steps` 参数的奖励函数*

```
def reward_function(params):
    #############################################################################
    '''
    Example of using steps and progress
    '''

    # Read input variable
    steps = params['steps']
    progress = params['progress']

    # Total num of steps we want the car to finish the lap, it will vary depends on the track length
    TOTAL_NUM_STEPS = 300

    # Initialize the reward with typical value
    reward = 1.0

    # Give additional reward if the car pass every 100 steps faster than expected
    if (steps % 100) == 0 and progress > (steps / TOTAL_NUM_STEPS) * 100 :
        reward += 10.0

    return float(reward)
```

## track\$1length
<a name="reward-function-input-track_len"></a>

**类型**：`float`

**范围**：`[0:Lmax]`

赛道长度（以米为单位）。`Lmax is track-dependent.`

## track\$1width
<a name="reward-function-input-track_width"></a>

**类型**：`float`

**范围**：`0:Dtrack`

赛道宽度（以米为单位）。

![\[\]](http://docs.aws.amazon.com/zh_cn/deepracer/latest/developerguide/images/deepracer-reward-function-input-track_width.png)


**示例：***使用 `track_width` 参数的奖励函数*

```
def reward_function(params):
    #############################################################################
    '''
    Example of using track width
    '''

    # Read input variable
    track_width = params['track_width']
    distance_from_center = params['distance_from_center']

    # Calculate the distance from each border
    distance_from_border = 0.5 * track_width - distance_from_center

    # Reward higher if the car stays inside the track borders
    if distance_from_border >= 0.05:
        reward = 1.0
    else:
        reward = 1e-3 # Low reward if too close to the border or goes off the track

    return float(reward)
```

## x, y
<a name="reward-function-input-x_y"></a>

**类型**：`float`

**范围**：`0:N`

包含赛道的模拟环境的沿 x 和 y 轴的代理中心位置（以米为单位）。原点位于模拟环境的左下角。

![\[\]](http://docs.aws.amazon.com/zh_cn/deepracer/latest/developerguide/images/deepracer-reward-function-input-x-y.png)


## waypoints
<a name="reward-function-input-waypoints"></a>

**类型**：`[float, float]` 的 `list`

**范围**：`[[xw,0,yw,0] … [xw,Max-1, yw,Max-1]]`

沿赛道中心排列、取决于赛道的 `Max` 里程的有序列表。每个里程碑均由 (xw,i, yw,i) 坐标描述。对于环形赛道，第一个路径点与最后一个路径点相同。对于直道和其他非环形赛道，第一个路径点与最后一个路径点不同。

![\[\]](http://docs.aws.amazon.com/zh_cn/deepracer/latest/developerguide/images/deepracer-reward-function-input-waypoints.png)


**示例**：*使用 `waypoints` 参数的奖励函数*

有关更多信息，请参阅 [`closest_waypoints`](#reward-function-input-closest_waypoints)。

# AWS DeepRacer 奖励功能示例
<a name="deepracer-reward-function-examples"></a>

以下列出了 AWS DeepRacer 奖励功能的一些示例。

**Topics**
+ [示例 1：在计时赛中紧贴中心线行驶](#deepracer-reward-function-example-0)
+ [示例 2：在计时赛中保持在界内](#deepracer-reward-function-example-1)
+ [示例 3：在计时赛中防止之字形行驶](#deepracer-reward-function-example-2)
+ [示例 4：保持在一条车道而不撞到静止障碍物或移动的车辆](#deepracer-reward-function-example-3)

## 示例 1：在计时赛中紧贴中心线行驶
<a name="deepracer-reward-function-example-0"></a>

 此示例确定代理距中心线的距离，如果代理靠近赛道的中心，则提供更高的奖励，鼓励代理紧贴中心线行驶。

```
def reward_function(params):
    '''
    Example of rewarding the agent to follow center line
    '''
    
    # Read input parameters
    track_width = params['track_width']
    distance_from_center = params['distance_from_center']

    # Calculate 3 markers that are increasingly further away from the center line
    marker_1 = 0.1 * track_width
    marker_2 = 0.25 * track_width
    marker_3 = 0.5 * track_width

    # Give higher reward if the car is closer to center line and vice versa
    if distance_from_center <= marker_1:
        reward = 1
    elif distance_from_center <= marker_2:
        reward = 0.5
    elif distance_from_center <= marker_3:
        reward = 0.1
    else:
        reward = 1e-3  # likely crashed/ close to off track

    return reward
```

## 示例 2：在计时赛中保持在界内
<a name="deepracer-reward-function-example-1"></a>

 此示例在代理保持在界内时给予更高的奖励，让代理弄清楚完成一圈的最佳路线。编程和理解很容易，但可能需要更长的时间才能融合。

```
def reward_function(params):
    '''
    Example of rewarding the agent to stay inside the two borders of the track
    '''
    
    # Read input parameters
    all_wheels_on_track = params['all_wheels_on_track']
    distance_from_center = params['distance_from_center']
    track_width = params['track_width']
    
    # Give a very low reward by default
    reward = 1e-3

    # Give a high reward if no wheels go off the track and 
    # the car is somewhere in between the track borders 
    if all_wheels_on_track and (0.5*track_width - distance_from_center) >= 0.05:
        reward = 1.0

    # Always return a float value
    return reward
```

## 示例 3：在计时赛中防止之字形行驶
<a name="deepracer-reward-function-example-2"></a>

 此示例奖励代理紧贴中心线行驶，但如果转向角太大，则会受到惩罚（减少奖励），这有助于防止之字形行驶。代理在模拟器中学习了平稳驾驶，在部署到实际车辆时倾向于保持相同的行为。

```
def reward_function(params):
    '''
    Example of penalize steering, which helps mitigate zig-zag behaviors
    '''
    
    # Read input parameters
    distance_from_center = params['distance_from_center']
    track_width = params['track_width']
    abs_steering = abs(params['steering_angle']) # Only need the absolute steering angle

    # Calculate 3 marks that are farther and father away from the center line
    marker_1 = 0.1 * track_width
    marker_2 = 0.25 * track_width
    marker_3 = 0.5 * track_width

    # Give higher reward if the car is closer to center line and vice versa
    if distance_from_center <= marker_1:
        reward = 1.0
    elif distance_from_center <= marker_2:
        reward = 0.5
    elif distance_from_center <= marker_3:
        reward = 0.1
    else:
        reward = 1e-3  # likely crashed/ close to off track

    # Steering penality threshold, change the number based on your action space setting
    ABS_STEERING_THRESHOLD = 15 

    # Penalize reward if the car is steering too much
    if abs_steering > ABS_STEERING_THRESHOLD:
        reward *= 0.8

    return float(reward)
```

## 示例 4：保持在一条车道而不撞到静止障碍物或移动的车辆
<a name="deepracer-reward-function-example-3"></a>

 

此奖励函数奖励代理保持在赛道边界内，如果代理太靠近前面的物体，则会受到惩罚。代理可变道以避免撞车。总奖励是奖励和惩罚的加权总和。此示例在惩罚方面的权重更高，以避免撞车。尝试使用不同的平均权重，以针对不同的行为结果进行训练。

 

```
import math
def reward_function(params):
    '''
    Example of rewarding the agent to stay inside two borders
    and penalizing getting too close to the objects in front
    '''
    all_wheels_on_track = params['all_wheels_on_track']
    distance_from_center = params['distance_from_center']
    track_width = params['track_width']
    objects_location = params['objects_location']
    agent_x = params['x']
    agent_y = params['y']
    _, next_object_index = params['closest_objects']
    objects_left_of_center = params['objects_left_of_center']
    is_left_of_center = params['is_left_of_center']
    # Initialize reward with a small number but not zero
    # because zero means off-track or crashed
    reward = 1e-3
    # Reward if the agent stays inside the two borders of the track
    if all_wheels_on_track and (0.5 * track_width - distance_from_center) >= 0.05:
        reward_lane = 1.0
    else:
        reward_lane = 1e-3
    # Penalize if the agent is too close to the next object
    reward_avoid = 1.0
    # Distance to the next object
    next_object_loc = objects_location[next_object_index]
    distance_closest_object = math.sqrt((agent_x - next_object_loc[0])**2 + (agent_y - next_object_loc[1])**2)
    # Decide if the agent and the next object is on the same lane
    is_same_lane = objects_left_of_center[next_object_index] == is_left_of_center
    if is_same_lane:
        if 0.5 <= distance_closest_object < 0.8:
            reward_avoid *= 0.5
        elif 0.3 <= distance_closest_object < 0.5:
            reward_avoid *= 0.2
        elif distance_closest_object < 0.3:
            reward_avoid = 1e-3  # Likely crashed
    # Calculate reward by putting different weights on
    # the two aspects above
    reward += 1.0 * reward_lane + 4.0 * reward_avoid
    return reward
```