1 DeepRacer介绍
AWS DeepRacer 是一个综合性的学习系统, 供各个水平的用户用来学习和探索强化学习以及试验和构建自动驾驶应用程序。
DeepRacer可分为两个主要部分:
AWS DeepRacer Console:在线训练和评估强化学习模型在模拟自动驾驶环境
AWS DeepRacer 车辆:1/18 比例的 RC 车辆,导入训练好的 AWS DeepRacer 模型上运行推理用于自动驾驶
本文从两个主要部分讨论DeepRacer的使用:
DeepRacer在线训练:从奖励函数、赛车知识和强化学习参数3个方向出发,优化模型线上及线下的性能
DeepRacer物理赛车:提供DeepRacer硬件使用过程中的标准流程,避免错误的配置流程导致性能不佳,包括:初次开箱配置、再次使用时的检查流程,以及debug流程
2 奖励函数基本思想
DeepRacer底层技术基于强化学习,在强化学习中,agent(智能体)学习的目标被表示为reward(收益),收益通过environment(环境)传递给agent。reward在每个时间点上是一个标量。而agent的目标,是最大化收到的总体reward。因此,与计算机中的贪心算法不同,强化学习的agent的目标并非最大化当前的reward,而是最大化长期reward的累计公式。
在DeepRacer训练中,模拟器通过给agent反回reward来与其交互,而agent根据reward来更新自己的策略。在《Reinforcement learning: An introduction》一书中, reward 由状态,动作和下一个状态共同决定。
在强化学习项目中,reward function的设计是其中重点,也是最耗费时间的部分,因为在提高agent能力的同时,还要避免agent投机取巧,找到提高奖励值的方法。
在DeepRacer中,可以通过定义reward_function函数来设置奖励函数
def reward_function(params):
reward = ...
return reward
其中,传入的参数params是一个字典,可以通过params获取小车当前的状态,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
参数的具体定义可以在下方链接查看:
https://docs.aws.amazon.com/zh_cn/deepracer/latest/developerguide/deepracer-reward-function-input.html
根据params提供的参数,官方提供了3个基础的奖励函数示例:
默认奖励函数:follow the center line,越接近中线,则分数越高
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 at varying distances 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
return float(reward)
stay inside the two borders,只要车子一直在边线内即可得分
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 agent 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 float(reward)
prevent zig-zag,在
follow the center line
奖励的基础上,当转弯角度大于阈值时,按比例降低奖励值:
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)
3 自定义奖励函数
使用上面的奖励函数,通常可以训练出一个比较稳定的模型,然而DeepRacer竞赛评判的标准除了稳定,还关注速度。因此,我们可以将更多的params提供的参数用上,下面是几个稍微复杂的奖励函数例子。
在不出界的基础上,根据速度是否高于某个阈值决定得分的高低,保证了稳定性和速度:
def reward_function(params):
all_wheels_on_track = params['all_wheels_on_track']
speed = params['speed']
SPEED_THRESHOLD = 1.0
reward = -10.0 if not all_wheels_on_track else 1.0 if speed < SPEED_THRESHOLD else 2.0
# 可以尝试不同的奖励值
# reward = -10.0 if not all_wheels_on_track else 1.0 if speed < SPEED_THRESHOLD else 5.0
return reward
基于例子1,增加对速度的打分,在不出界的情况下,以速度的平方为奖励值。
def reward_function(params):
speed=params['speed']
all_wheels_on_track = params['all_wheels_on_track']
reward = -10.0 if not all_wheels_on_track else speed ** 3
# 可以尝试不同的scale
# reward = -10.0 if not all_wheels_on_track else speed ** 2
return reward
在高完成度时给予agent更高的奖励,鼓励agent尝试更稳定的路线,完成度越高,奖励值越多。也可以尝试对progress进行log指数变换,找出适合的值。
完成度的值域为:[0,100]
def reward_function(params):
progress = params["progress"]
reward = -10.0 if not params["all_wheels_on_track"] else progress
# 可以尝试不同的指数变换
# reward = -10.0 if not params["all_wheels_on_track"] else progress ** 0.5
return reward
4 结合赛车知识
4.1 晚切弯
每个DeepRacer赛道都存在弯道,例如经典的入门赛道re:Invent 2018有5个弯道,其中4个较大的转角,1个较小的转角。
与我们直觉不同,实际比赛中的最优的过弯路线并非最近的路线,而是让赛车保持持续的动量的晚切弯。因为赛车在半径大的弧线上的速度能够比在半径小的弧线上更快,这也和赛车的侧向抓地力有关。
下图红色的车最大速度沿圆圈形势,它可以保持在圆形路径上,是因为车的横向抓地力在把它向圆心拉动,同时车自身的动力及其持续的动量促使其向车头所指的方向运动,这两个趋势共同维持了圆形运动。
因此,在赛车过弯时,赛车手通常使用晚切弯(late apex)技术,而非选择最短的路线。晚切弯是指在过弯时,稍微延迟时机并大力刹车,更晚拐入,但更早摆正赛车;他们擦过弯内侧的时间会更晚。这样做是为了让出弯后的路线更加平直,并在末尾直道处达到更高的速度。
4.2 Waypoints
上面我们讲了在赛车比赛中的晚切弯知识,那么在DeepRacer训练中如何结合这些知识呢?我们可以通过waypoints参数自定义DeepRacer的行走路线,让agent在过弯时选择最优的late apex。
waypoints 代表了赛道上的每一个位置,waypoints一共有3组(L = 左边, C = 中心 and R = 右边),在地图上一共有154个数字,不同的赛道的waypoints也不尽相同。
waypoints模板:
def reward_function(params):
center_variance = params["distance_from_center"] / params["track_width"]
#racing line
left_lane = [] # Fill in the waypoints
center_lane = [] # Fill in the waypoints
right_lane = [] # Fill in the waypoints
# Speed
fast = [] # Fill in the waypoints, 2m/s
slow = [] # Fill in the waypoints, 1m/s
reward = 21
if params["all_wheels_on_track"]:
reward += 10
else:
reward -= 10
if params["closest_waypoints"][1] in left_lane and params["is_left_of_center"]:
reward += 10
elif params["closest_waypoints"][1] in right_lane and not params["is_left_of_center"]:
reward += 10
elif params["closest_waypoints"][1] in center_lane and center_variance < 0.4:
reward += 10
else:
reward -= 10
if params["closest_waypoints"][1] in fast:
if params["speed"] == 2 :
reward += 10
else:
reward -= 10
elif params["closest_waypoints"][1] in slow:
if params["speed"] == 1 :
reward += 10
else:
reward -= 10
return float(reward)
根据以上的模板,我们可以将自定义的waypoints路径和速度填入5个lane变量中,这样就可以在训练时候让小车根据我们希望的路径和速度行驶。
5 强化学习的参数理解
5.1 深度强化学习算法
DeepRacer 的底层算法是深度强化学习,其中可以选择的算法有两个,我们可以根据训练的时间和赛道类型选择合适的模型:
PPO(Proximal Policy Optimization):基于Policy Gradient的思想,是主流的深度强化学习算法之一。PPO对样本的利用效率较低,训练时需要大量样本,鲁棒性较高,对超参数不敏感,收敛效果较好。
SAC(Soft Actor-Critic):基于DDPG的思想,与PPO相比,对样本的利用程度更高,所需要的样本数更少。但SAC鲁棒性较低,对超参数敏感,收敛效果较差。
5.2 超参数
深度强化学习的底层是神经网络结合强化学习,因此我们可以配置的超参数分为2大类:
强化学习超参数
神经网络超参数
深度学习参数的简介如下(具体介绍可以在官方文档中查看):
Gradient descent batch size
:从经验缓冲区中随机采样的最近车辆经验数,用于更新基础深度学习神经网络权重。
Number of epochs
:在梯度下降期间,遍历训练数据(经验缓冲区的随机样本)以更新神经网络权重的次数。
Learning rate
:更新权重时,新权重的占比。
Entropy
:不确定性概率,模型有一定概率选择随机探索。
Discount factor
:未来奖励对预期奖励的影响程度。
Loss type
:损失函数的类型。分为
Mean squared error loss (
均方误差损失
)
和
Huber loss (Huber
损失
)
类型。
Number of experience episodes between each policy-updating iteration
:经验缓冲区的大小,用于记录过去的经验。
根据以上超参数的定义,有如下调参建议:
如果奖励函数过于激进,导致模型不易收敛,可以尝试降低
learning rate
或选择
huber loss
,让学习的过程更加平滑;
如果模型在过弯时反应不够灵敏,或转弯时机总是比较晚,可以尝试提高
discount factor
,让模型更注重远期奖励;
反之,如果模型在过弯时过于灵敏,过早转弯,可以尝试降低
discount factor
,避免模型过于关注远期奖励,同时,也可以使用waypoints来解决;
Reward的延迟也要在
discount factor
的设置中考虑,如果reward设置的的延迟较高时,可以适当提高
discount factor
值;而reward实时性较好时,可以降低
discount factor
值;
Batch size
与
epoch
越大,模型在训练的权重更新则越平滑。但如果
batch siz
e或
epoch
过大,会导致训练速度降低及收敛至局部最优,因此可以联合调试
batch size
和
epoch
的值;
适当增加经验缓冲区大小,会提升模型的收敛的稳定性,如果模型始终不收敛或性能震动较大,可以尝试适当增加经验缓冲区的大小;
与PPO模型相比,在使用SAC模型时,建议使用更高的
epoch
来缓解算法本身对超参数敏感的问题;
如果模型训练过程中的性能提升过于缓慢,可以适当增加
entropy
值,提升模型随机探索的可能性;
如果模型的性能提升过于缓慢或变动较小,可以适当增加
entropy
值;反之,如果模型在收敛过程中震荡较大,可以适当降低
entropy
值;
5.3 Action Space
Action space指的是agent可选的动作范围,在DeepRacer训练配置中,可以选择下面两种action space
Continuous action space:连续动作空间,提供速度和转角的上下限,agent可在范围中寻找合适的值
Discrete action space:离散动作空间,提供action的组合(速度+转角)
通常情况下,continuous action space较难收敛,需要更多的训练时间和更精细的奖励函数配置。
6 设备初次开箱配置
在对DeepRacer物理车进行初始开箱的配置时,需要较复杂的步骤以保证硬件的正确配置。
配置路由器,确保路由器无网络连接(当DeepRacer出现新版本,DeepRacer 在连接路由器后会被要求强制更新,国内由于资源问题,有一定概率导致DeepRacer更新后系统损坏)
确定DeepRacer配套充电宝的电量
确定DeepRacer配套马达及备用马达的电量
取出DeepRacer的别针,注意不要弄断计算模块和赛车底座间的连接线
将马达电池安装至DeepRacer中
确定马达开启(开启后会听到两短一长滴声提示,如无提示可确认马达是否有电,以及连接线是否正确连接)
安装底部别针
安装充电宝
确定充电宝充电开启状态后,对DeepRacer进行开机操作,DeepRacer开机成功后,尾部会有灯光亮起
计算机断开网络
使计算机通过USB线与连接DeepRacer
浏览器进入deepracer.aws
根据DeepRacer底部密码进入DeepRacer控制台
在控制台中,配置DeepRacer的WiFi连接,并获取DeepRacer在WiFI下的IP地址
断开计算机与DeepRacer的连接,并让计算机处于相同WiFi下
输入之前获取的IP地址,再次根据DeepRacer底部密码进入DeepRacer控制台
确定摄像头可用,如摄像头不可用需要重新插入摄像头,并重新启动DeepRacer
将DeepRacer架起,置于胶带上,避免DeepRacer轮胎着地导致调整速度时损坏DeepRacer
配置DeepRacer的前进方向、及前进后退速度(其中,前进方向在点击reverse后,并非立即更改,需点击next后更改才会生效)
配置DeepRacer的前进角度(center value),通过手动控制DeepRacer向前确定前进方向无误
配置DeepRacer的最大左右转角方向(建议±40°)
配置静摩擦力参数,保持车辆落地时不动
将DeepRacer置于真实跑道的各个位置, 查看摄像头在各个位置接收的光线问题,如图像受到的光线影响较大,需要使用遮挡等方式解决光线问题
尝试使用机器内置的sample model在跑道中运行,确定跑道及车辆无问题
上传自己训练的模型
建议在尝试在使用复杂模型前,自行训练一个鲁棒性高的简单模型测试车辆运行的稳定性(建议使用基于follow the center策略的模型)
7 再次使用时的检查流程
与开箱时的初次配置不同,再次使用DeepRacer时,主要的任务是检查DeepRacer的配置是否更改,以及硬件是否稳定。
开启路由器
安装充电宝及马达电池
DeepRacer开机
检查摄像头是否可用,如摄像头不可用,需重新插入摄像头,并重启机器
如在使用的路由器与上次相同,可先尝试直接连接上次DeepRacer的IP地址,如无法连接,则重新通过路由器确定DeepRacer的IP地址
检查DeepRacer的速度及角度是否与之前配置的不同,如差异较大,可重新配置
使用鲁棒性较高的简单模型重新测试车辆运行的稳定性
8 标准硬件问题排查及解决办法
车辆校准问题:
车辆校准过程中,如出现无法转弯的情况,可查看底部的两根黑头线是否连接稳定,可重新插入每一个连接线
车辆校准过程中,如出现手动控制车辆前进时,每次前进方向都不同,可尝试方面前进速度,确保前进方向的稳定性
车辆校准过程中,如出现翻转车辆前进方向后无效果,可点击next进入下一步,查看翻转效果
车辆校准过程中,如忘记打开马达,请重新启动机器,否则会导致速度或方向与实际预估的情况不同
如车辆校准过程中,如无法正常校准车辆(center value、最大转角),即使模型无问题,仍建议更换车辆,可考虑是模型的自我修正,仍有一定概率影响比赛
车辆不动时:
检查马达电池是否电量充足,将马达与充电器连接,如红灯绿灯同时亮起,则表示未充满电;如仅绿灯亮起,则代表电量已满
如马达电池充足,请检查马达是否开启,可关闭并重新开启马达电池,确保听到二短一长的滴声
在速度较慢的情况下,车辆会由于摩擦力导致在地面时无法转动。提起车辆,如车辆转动缓慢,请尝试提高车辆的速度
当使用者在关闭马达时请勿修改calibartion中的任何配置(移动速度、方向等),会导致速度或方向与真实情况不同,甚至车辆无法移动,如果发生过此情况,请重新启动DeepRacer恢复速度配置
如车辆无法转弯,查看车辆底座的黑色控制线是否松动,可在固定控制线后重新启动车辆
车辆摄像头不更新时:
确保非网络连接问题导致的视频流卡顿,尝试多次刷新页面,如由于网络连接问题导致,可尝试重启WiFi
如非视频流卡顿,可重启DeepRacer,并重新检查摄像头
如重启后无更新,则是摄像头接口由于震动导致连接断开,可尝试拔掉摄像头重新安装
如重新安装后仍无更新,可尝试安装其他摄像头,确认是否为摄像头问题
WiFi网络故障:
确保DeepRacer正确连接WiFi,车辆的WiFI指示灯为蓝色时,则车辆连接成功,如为白色,则表示尚未连接
2. 确保WiFi下连接设备不超过两台(控制端与车辆端),断掉其他设备的连接
3. 查看WiFi所用信道的占用状态,可通过WiFi分析仪等app查看,如信道占用较严重可更改路由器的信道配置
4. 在大型活动时,信道占用影响较严重,建议在场人员手机启动飞行模式,避免信道的占用,由于WiFi设备的性能限制,目前暂无其他较好的解决方案,建议采用功率较强的WiFi设备
模型无法正常工作时:
确定摄像头连接是否正常,如摄像头无输入,则模型无法运行
如模型性能较差,可先确认前进角度、速度及最大转角的配置是否正确
如以上配置均正确,性能仍较差,可尝试使用鲁棒性较高的简单模型(如follow the center)确认是否为模型自身问题
如是鲁棒性较高的模型性能也较差,可将车辆置于赛道上不同位置,确认是否为灯光等因素影响,可尝试使用遮挡等方式解决灯光问题
如以上均无问题,可考虑是否为模型线上线下表现不一致,尝试更改强化学习参数或策略
如点击启动后车辆不动,可提起车辆,确定是否为速度原因
如果模型速度始终较慢,可考虑增加车辆绝对速度
如增加绝对速度后,模型速度依然较慢,考虑使用其他模型,确定是否为模型本身计算问题
如模型始终不动,可确认模型训练时的action space是否为continuous,某一版本的DeepRacer会出现不支持基于continuous action space训练的模型,如遇到此情况,请根据官网文档进行刷机
如模型无法转弯,可查看底部的两根黑头线是否连接稳定,可重新插入每一个连接线
计算机无法与DeepRacer车辆连接时:
确保连接线无问题,尝试多条连接线
尝试重启DeepRacer车辆后连接
如使用的计算机为MacOS,可按以下步骤操作,激活设备的以太网USB网络
选择要打开的网络图标(在屏幕的右上角)以打开网络首选项.
或者,选择命令 + 空格,键入网络选择,然后选择网络系统首选项.
检查 Deepracer 是否列为 Connected (已连接)。如果 DeepRacer 已列出但未连接,请确保车辆和计算机之间的微型 USB/USB 电缆已牢固地插紧。
如果DeepRacer网络未在那里列出或列出但插入 USB 电缆时未连接,请选择自动Localtion然后选择
验证 AWS DeepRacer 网络已启动并以下列方式运行:
当计算机连接到DeepRacer网络,刷新https://deepracer.aws浏览器上的页面,然后继续其余部分入门指南的说明Connect 到 Wi-Fi.
如果DeepRacer未连接网络,断开计算机与 AWS DeepRacer 车辆的连接,然后重新连接。当 Deepracer 网络变为 Connected (已连接) 时,请继续按照 Get Started Guide (入门指南) 说明执行操作。
如果DeepRacer仍未连接设备上的网络,重启计算机和 AWS DeepRacer 车辆并重复步骤 1在此过程中,如有必要。
如果上述补救措施仍然无法解决问题,则设备证书可能已损坏。请按照以下步骤为 AWS DeepRacer 车辆生成新证书,以修复损坏的文件。
在 AWS DeepRacer 车辆上生成新证书
拔下微型 USB/USB 电缆来终止计算机和 AWS DeepRacer 车辆之间的 USB 连接。
将 AWS DeepRacer 车辆 Connect 到监视器(使用 HDMI 到 HDMI 电缆)以及 USB 键盘和鼠标。
登录 AWS DeepRacer 操作系统。如果这是首次登录设备操作系统,请使用DeepRacer在要求输入密码时,然后根据需要继续更改密码,然后在后续登录时使用更新的密码。
打开一个终端窗口,并键入以下 Shell 命令。可以选择终端快捷方式应用-> 系统工具在桌面上打开一个终端窗口。或使用文件浏览器,导航到/usr/bin文件夹,然后选择侏儒终端以打开它。
sudo /opt/aws/deepracer/nginx/nginx_install_certs.sh && sudo reboot
出现提示时,输入在上一步中使用或更新的密码。
以上命令安装新证书并重新启动设备。此外,还将设备控制台的密码恢复为在 AWS DeepRacer 车辆底部的默认值。
从车辆上断开显示器、键盘和鼠标的连接,然后使用微型 USB/USB 电缆将其重新连接到计算机。
确定计算机确实连接到设备网络(https://deepracer.aws) 再次然后继续Connect 到 Wi-Fi
车辆IP地址经常发生变化:
利用计算机通过USB线连接到DeepRacer,或缺最新的IP地址
如希望IP地址固定,请更改路由器的网络的 DHCP 服务器配置
马达电池锁定时:
当马达电池长期电量不足时,会发生锁定情况,请定期为马达电池充电,避免锁定
如电池锁定,可将电池连接器插入到匹配的彩色电缆连接器中,红色到红色,白色到白色
断开电池与电缆的连接
AWS DeepRacer 车辆电池将会立即可用。将红色 2 针连接器重新连接到车辆传动系连接器,然后用魔术贴带将电池固定到车辆上。
将开关推到“开启”位置,打开车辆驱动系统。聆听是否发出指示信号(两声短促的哔哔哔声),以确认电池已成功解锁
9 参考资料
https://www.linkedin.com/pulse/aws-deepracer-free-student-workshop-run-faster-using-your-cheuk-lam/
https://docs.aws.amazon.com/zh_cn/deepracer/latest/developerguide/deepracer-console-train-evaluate-models.html
https://aws.amazon.com/deepracer/getting-started/
https://docs.aws.amazon.com/zh_cn/deepracer/index.html