恒美微站 Logo 恒美微站
  • 首页
  • 关于我们
  • 建站服务
  • 主题模板
  • 案例展示
  • 资讯中心
  • 联系我们

从20秒到7.6秒:DeepRacer奖励函数迭代优化实战

  • 首页
  • 资讯中心
  • /
  • 从20秒到7.6秒:DeepRacer奖励函数迭代优化实战

相关资讯

AI选品Agent如何提升跨境电商选品成功率 2026/9/15 11:50:38
C语言 从数组构建堆(Building Heap from Array) 2026/9/15 11:45:38
C++ 从数组构建堆(Building Heap from Array) 2026/9/15 11:45:38

最新资讯

TinaCMS 内容全文检索包 @tinacms/search:架构解析、模糊搜索机制与演进历程
LEANN flashlib_ivf 后端实战:用 FlashLib IVF-Flat 在 CUDA GPU 上加速近似最近邻检索
内存地址与偏移:逆向安全的核心地基与调试实战
断点回归RDD:因果推断的准实验精密方法
MMSegmentation 中的 BEiT 骨干网络:从权重转换到 ADE20K 语义分割实战
LogicFlow 画布 API 完全指南:resize / focusOn / zoom / fitView 与坐标换算实战

今日推荐

GDPR下大数据架构重构与隐私保护实践
多组学数据平台架构设计与优化实践
企业主数据管理系统架构设计与实施全解析

本周热门

AI SDK Harness 依赖更新指南:掌握 harness 包 SDK 依赖的升级、桥接同步与一致性校验
Refine v5 Ant Design NumberField 组件实战:基于 Intl 的本地化数字格式化
Flutter应用改名全指南:从Android到iOS的配置与工具实践

本月精选

自研推理加速器Redwood:两周内实现PyTorch模型高效部署的实战教程
V4L2摄像头采集实战:从camera_client.rar到出图全流程解析
从“谁发明了钢琴键”到知识问答智能体:RAG与记忆工程实践

从20秒到7.6秒:DeepRacer奖励函数迭代优化实战

发布时间:2026/9/15 11:50:38
从20秒到7.6秒:DeepRacer奖励函数迭代优化实战 1. 先把赛事背景和项目目标说清楚1.1 这个项目到底在做什么2018年底的AWS re:Invent大会上我第一次见到DeepRacer这个只有手掌大小的自动驾驶小车。它跑在一条铺在地板上的环形赛道上背后靠的是强化学习——不是有人教它怎么打方向盘而是让模型在环境里自己试错试错了就给负面反馈开对了就给奖励最终学出一套能跑完赛道的策略。我参加的那次赛事本质上是“用强化学习训练一台虚拟赛车跑出一条赛道的最短时间”。赛道是模拟器里的固定环形赛道车的传感器输入很简单摄像头画面用来检测赛道边界和车道位置、当前速度、转向角度、偏离赛道中心的距离。模型输出两个值一个是油门速度一个是转向角。你不需要碰任何物理硬件所有训练都在云端的模拟器里跑。我给自己定的目标很直接让这辆车在赛道上稳定跑完一圈并且把单圈时间压缩到我能做到的极限。最终成绩是7.6秒一圈和一个真人驾驶RC遥控车跑同样的赛道相比这个成绩不快但在当时的DeepRacer模拟器环境下这个数字意味着车辆的轨迹已经相当平滑没有太多多余摆动和刹车。1.2 为什么说奖励函数是DeepRacer的核心DeepRacer的训练流程是一条标准强化学习链路智能体 策略网络决定动作 环境模拟器 奖励信号告诉模型什么行为好、什么行为坏。其中模拟器是固定的环境引擎改不了能改的就两个地方一个是超参数训练轮数、学习率、batch size另一个就是奖励函数。奖励函数就是一段Python函数它接收当前状态车的位置、方向盘角度、速度、偏离赛道中心的距离等返回一个数值。模拟器每隔一小段时间调用一次这个函数根据返回值决定这次行为的“奖”或“罚”。这个函数的设计决定了模型的方向。如果奖励只跟速度挂钩那模型学到的策略就是“猛踩油门”结果就是车冲出赛道。如果奖励只跟“贴近赛道中线”挂钩车倒是稳稳在中线跑但速度慢到像在散步。好的奖励函数既要鼓励“快”又要约束“稳”还要引导模型学会走最优路线外内外切弯这三者之间需要平衡。1.3 迭代优化的整体循环整个项目不是“写一个奖励函数丢进训练等结果”这么简单。实际操作中训练是一个循环而且大部分时间花在“调函数—看日志—分析问题—再调函数”这个循环上写一个奖励函数v1启动训练。训练跑到一定轮数后打开训练日志观察奖励曲线、完成率、单圈时间、速度分布。根据日志里的异常表现修改奖励函数或超参数。重新训练重复第2步。每次迭代之间我记录下改了什么、预期解决什么问题、日志里有没有体现预期的变化。这个习惯帮了大忙因为奖励函数调参是个极度容易“东一榔头西一棒子”的活没有记录改到最后你根本不知道哪个版本起的作用。严格来说这个标题里的“多次迭代优化奖励函数后最快7.6秒/圈”指的就是这套循环跑了大约十几个版本每个版本都是“改奖励函数 → 训练 → 看log → 再改”的路子。后面几节我会把每个关键版本的思路、日志现象、调整内容全部拆开讲。2. 日志分析先学会读懂训练信号2.1 训练日志里到底有什么在DeepRacer的控制台里训练过程中会实时返回一组指标曲线。很多人一看训练开始就直接等最终结果其实这些曲线就是“模型的体检报告”每一段都透露着模型当前的状态。我把关键指标分成三组来看奖励相关指标Total Reward总奖励、Reward Per Episode每轮奖励均值。这一组反映的是模型整体表现趋势。正常情况下随着训练轮数增加总奖励应该不断上升然后趋于平缓。如果曲线一直抖动、不上升说明奖励函数和模型之间没匹配好模型根本没理解信号含义。任务完成类指标Completion Rate单轮完成率即跑完全程的比例、Percentage of Track Completed赛道完成百分比。这两个指标是最直观的“车到底跑得完跑不完赛道”的信号。如果完成率长期低于10%先别急着调奖励函数先看是不是赛道入口初始化有问题或者模型一直在起点附近转圈。状态类指标Average Speed平均速度、Distance from Center偏离中线距离、Steering Angle转向角分布。这三个指标反映驾驶风格。平均速度低但完成率高说明模型学会了保守驾驶速度高但完成率低说明策略激进但缺少控车能力。我在每个版本训练过程中每隔50轮就截图一次这些曲线然后把关键数字记录下来。这样做的好处是训练完之后我可以“回放”整个学习过程知道车是在哪个阶段开始学会过弯的或者是在哪个阶段开始退化的。2.2 奖励曲线怎么判断好坏万事开头难但“看懂奖励曲线”这件事其实有规律可循。我第一次拿到训练日志时满眼都是锯齿状的曲线完全不知道算好还是坏。后来反复对照几次总结出几条经验曲线持续上升但波动很大正常现象。强化学习本身带有随机性每个episode的环境初始状态不同、探索动作不同奖励有波动是必然的。只要你把窗口拉大看趋势是上升的就说明方向是对的。曲线长时间横盘模型可能陷入局部最优或者奖励信号太平滑模型觉得“怎么走都差不多”缺少梯度。这时候需要给奖励函数增加区分度让好行为和坏行为之间的分数差更大。曲线先升后降模型过拟合了。它可能记住了某一段赛道的特定走法一旦环境判断边界发生变化表现反而下滑。遇到这个情况我会马上停止当前训练调整超参数比如降低学习率、增加batch size或者简化奖励函数。以我那个7.6秒版本的最终训练为例奖励曲线的形态是一个“前30轮快速爬升30到80轮震荡上升80轮之后基本平缓”的形状。这个形状说明模型在30轮左右学到了基本的循迹能力后续的震荡其实是探索过程中尝试激进走法的结果而80轮后趋向平稳意味着策略基本成熟了。2.3 log里那几个被我忽略后来又捡起来的字段前面说的是控制台自带的曲线但训练过程中还会生成更详细的日志文件里面记录了每个step的完整状态。很多人根本不看这些原始日志只盯着汇总曲线这就会漏掉很多关键信息。我后来在项目中期开始深入分析log文件发现有几个字段非常有用steering_angle每个step的方向盘角度。如果这个值频繁在±30度以上切换说明车一直在左右大幅摆动轨迹必然是蛇形圈速肯定快不了。throttle每个step的油门输出。我见过很多版本油门输出在直道和弯道之间没有明显区分说明模型没有学会“弯道减速、直道加速”这个基本逻辑。position或者centerline distance车离赛道中线的距离。这个字段能帮你判断车辆在赛道上的横向位置分布连续多个step都在赛道边缘说明模型倾向于走极端路线。比如有一个版本我在summary曲线上看到平均速度很高但单圈时间却很慢矛盾得很。打开原始log一看才发现车一直在赛道外侧压路肩跑虽然油门踩得大但整体路程变长了圈速自然上不去。光看汇总曲线根本找不到这个原因。3. 奖励函数的设计与迭代3.1 第一版教科书式奖励函数结果原地打转我的第一版奖励函数是从官方示例改的。官方给的模板思路是奖励靠近赛道中线、惩罚偏离赛道、根据速度额外给奖励。我抄过来略微改了参数看起来逻辑没问题def reward_function(params): distance_from_center params[distance_from_center] track_width params[track_width] speed params[speed] # 偏离中线越远奖励越低 distance_reward 1 - (distance_from_center / track_width) # 基础奖励 速度奖励 reward distance_reward speed * 0.1 return float(max(reward, 1e-3))这个函数的问题很典型线性惩奖结构太平滑。偏离中线0.1米和0.3米的分数差异不够大模型感觉不到“贴边走”和“走中间”之间有本质区别于是学到了一种极其保守的策略——以极低速度在赛道中间蠕动。训练了60轮之后完成率倒是上去了但单圈时间惨不忍睹平均20多秒一圈而且车速从来没有超过1.5 m/s。看日志时最明显的一个现象是Total Reward一直在涨但Average Speed纹丝不动。按理说奖励函数里已经加了速度项为什么速度不加因为“贴中线”的奖励始终占主导模型只要乖乖待在中间就能拿高分没有动力去冒险加速。奖励函数引导什么模型就学什么引导力弱的信号等于不存在。3.2 第二版惩罚转向圈速稍微稳定了第一版的问题让我意识到不能平铺直叙地给奖励要让“好行为”和“坏行为”之间的分数差足够大。第二版我做了两件事把中线偏离惩罚改成指数形式偏离越远惩罚倍数越大让车“怕”离开中线。新增转向惩罚如果转向角在短时间step里变化过大扣分抑制蛇形行驶。def reward_function(params): distance_from_center params[distance_from_center] track_width params[track_width] speed params[speed] steering abs(params[steering_angle]) # 指数型偏离惩罚 distance_reward 1 - (distance_from_center / track_width) ** 2 # 转向角惩罚转向越大分数越低 steering_penalty 1 - min(steering / 30.0, 1.0) reward distance_reward * 0.7 steering_penalty * 0.2 speed * 0.1 return float(max(reward, 1e-3))跑完这个版本最明显的变化是单圈时间从20多秒拉到了12秒左右赛道完成率维持在85%左右。但仔细观察日志我发现一个新的问题车辆在进弯时转向角突然变大车速同时跟着骤降出弯后速度重新起来——整个轨迹是“减速—大幅打方向—加速”的折线而不是“平滑划过弯道”的弧线。这种走法虽然能完成赛道但每一圈都会在弯道浪费大量时间。原因也清楚我之前写的转向惩罚是全局统一的不管你在直道还是弯道只要转向角大就扣分。模型为了规避惩罚选择了“弯道前重刹、大角度打方向”这种策略反正只要每个step的转向角不离谱就行连续性没人管。3.3 第三版引入正弦函数流畅度终于上来转机出现在第三版。我在一次翻资料时看到有人讨论“如何让奖励函数对转向角的过渡更加平滑”提到了正弦函数映射的思路。核心逻辑是把转向角的增量映射成一条平滑曲线让连续两个step之间转向角的差值成为关键评分项而不是只看单步的转向角大小。import math def reward_function(params): distance_from_center params[distance_from_center] track_width params[track_width] speed params[speed] steering params[steering_angle] prev_steering params.get(previous_steering_angle, 0) # 连续step之间转向角增量 steering_diff abs(steering - prev_steering) # 用正弦函数将转向增量映射到 [0, 1] # 增量接近0时正弦值接近0但不惩罚增量越大惩罚越强 smooth_factor math.sin(min(steering_diff, 90) * math.pi / 180) distance_reward 1 - (distance_from_center / track_width) ** 2 speed_reward min(speed / 4.0, 1.0) reward (distance_reward * 0.5 speed_reward * 0.3) * (1 - smooth_factor * 0.4) return float(max(reward, 1e-3))这段代码的原理是当车辆方向盘的增量从0变到90度时正弦函数的值从0平滑增长到1作为惩罚权重乘在总分上。增量越小奖励越接近上限增量越大奖励被压缩得越狠。模型必须学会“用连续的、小幅度转向来过弯”而不是“瞬间猛打方向盘”。这一版的训练结果单圈时间第一次突破了9.5秒。日志里最直观的变化是Steering Angle曲线从原来的锯齿变成了一条相对平滑的正弦状曲线进弯和出弯之间没有明显的角度跳变。Average Speed也上来了因为车不用再在弯道前重刹可以保持更高的转速滑过弯心。3.4 几个关键参数的平衡到了这个阶段奖励函数已经不再是“有没有用”的问题而是“平衡点在哪”的问题。我有几个参数来回调了很久参数作用我的最终设置备注distance_reward权重控制赛道中线约束力0.5过低会导致抄近道、走外圈过高会导致贴中线行驶、速度上不去speed_reward权重鼓励速度0.3过高会让模型超速过弯失控过低则模型趋于保守smooth_factor惩罚系数抑制转向突变0.4过高会让车“不敢转弯”过弯直接冲出赛道过低则回到蛇形奖励下限防止所有动作都被零奖励1e-3不能设为0否则模型会丧失梯度信号我最终的7.6秒版本就是在这一版基础上微调出来的。关键改动是把speed_reward的计算从线性映射改成带阈值的分段方式速度低于1.5 m/s时不额外加分高于3.0 m/s时按满分计。这个调整让模型意识到“短时间低速过弯可以接受但长时间低速会吃亏”反而在弯道处理上更果断。4. 完整迭代记录与关键复盘4.1 从20秒到7.6秒的版本演进表# CHANGELOG: 奖励函数迭代记录 | 版本 | 核心思路 | 单圈时间 | 完成率 | 主要问题 | |------|----------|----------|--------|----------| | v1 | 线性中线距离速度加分 | ~20s | 95% | 车速极低模型过于保守 | | v2 | 指数化中线距离转向角惩罚 | ~12s | 85% | 弯道重刹、折线轨迹严重 | | v3 | 正弦转向增量化速度权重重构 | ~9.5s | 88% | 弯中速度仍有下降空间 | | v4 | 速度分段奖励中线惩罚细化 | ~8.8s | 90% | 个别弯道走线仍不够贴内 | | v5 | 加入赛道方位角引导弯道识别 | ~8.2s | 92% | 偶有震荡部分路段保守 | | v6 | 简化引导项超参调整增大batch | ~7.6s | 95% | 基本稳定个别轮次波动 |每一次迭代都不是推倒重来。v4和v5的区别只是我在v3的框架上调整了两个权重系数并新增了一个“赛道方位角”的引导信号——这个信号告诉模型当前弯道的方向变化率帮助它提前为入弯做准备。但我加了之后发现收益有限又在v6里部分简化掉了只保留最有效的部分。4.2 超参数调优笔记奖励函数需要配合超参数才能发挥效果。我在v6版本同时调整了几个训练超参这里直接给出我的最终选择Batch size批大小从16调到了32。批次越大梯度估计越稳奖励曲线更平滑但训练耗时更长。对于我这种只看结果的比赛场景稳定优先。Learning rate学习率从0.0003降到了0.0001。v4阶段出现了过拟合现象具体表现为训练后期奖励曲线开始下滑降低学习率后明显改善。Epoch数10次。试过5次欠拟合策略不成熟和20次过拟合泛化差10次是这个赛道复杂度下的合理值。Action space动作空间我把转向角离散成15个档位而不是默认的7个档位。档位越多动作越细腻车越能走平滑的弧线但训练难度也成正比增加。15个档位是我的甜点值再多训练时间就不太够用了。有个细节容易忽略动作空间对奖励函数的影响非常大。档位少的时候模型在弯道里只能选择“大角打过去”或“保持直行”你奖励函数写得再好它也表现不了平滑过弯因为动作选择压根没有平滑档位。所以如果你是新手建议先确认动作空间的分辨率再谈奖励函数优化。4.3 一个值得单独说的机制方位角引导段v5版本里我加入的“赛道方位角引导”信号值得单独拿出来讲讲。原理是模拟器返回的state里包含一个heading值代表车头当前朝向与赛道中心线的夹角。通过这个值我可以判断“车是不是正对着赛道方向”。def reward_function(params): heading params[heading] waypoints params[waypoints] closest_point params[closest_waypoint_index] # 下一目标点在赛道坐标系中的方向 next_point waypoints[(closest_point 3) % len(waypoints)] prev_point waypoints[closest_point] track_direction math.atan2(next_point[1] - prev_point[1], next_point[0] - prev_point[0]) * 180 / math.pi # 与赛道方向对齐时给奖励 direction_diff abs(track_direction - heading) if direction_diff 180: direction_diff 360 - direction_diff direction_reward max(0.0, 1 - direction_diff / 90.0) return float(max(direction_reward, 1e-3))这里读取的是下一个waypoint方向与当前车头朝向的差距。差距越小奖励越高。它的作用就像GPS导航一样告诉模型“你的车头现在没对着前面的路该修正了”。加上这个信号后模型在长直道和缓弯之间的衔接更流畅了因为车可以提前对准方向不需要等到了弯心才匆匆修正航向。但我也发现这个引导在训练早期的负面作用模型过分依赖航向对齐导致它在急弯处宁可“笔直冲向赛道边缘”也不敢打方向因为它认为航向偏差带来的惩罚太重了。最后的解决方法是在v6里把这个信号的权重从0.4降到了0.2并且增加了距离赛道边缘的硬性惩罚兜底。5. 常见问题与排查技巧5.1 训练时间与收敛判断很多人问到底训练多久才能跑出好成绩我的经验是看赛道复杂度和任务难度别用固定轮数硬套。我的赛道只有一圈是一个椭圆带两个S弯的组合结构不复杂。在前几轮训练中单圈时间就已经降到了10秒内v6版本跑了差不多120轮后基本收敛在7.6到7.8秒之间。判断收敛有一个可复用的标准连续20轮训练的单圈时间变化不超过0.3秒并且最终评估时完成率高于90%。满足这两条我就认为当前配置已经收敛可以停止训练进入评估阶段。如果你训练了200轮还在持续改善别急着停——说明模型还在学新东西反而是好事。5.2 过拟合与赛道迁移问题DeepRacer有个鼻祖级问题模型在训练赛道上跑得飞快换个赛道就废了。这就是强化学习的过拟合现象。我在v2版本里遇到过训练赛道的单圈时间已经进入10秒但把模型放到一条形状不同但长度相近的赛道评估时连一圈都跑不完。解决思路有几个组合拳降低学习率让模型对训练数据的记忆没那么强。增加探索噪声如果你用的是PPO算法可以调高entropy系数让模型在训练过程中见识更丰富的状态提高泛化能力。在奖励函数里减少对特定赛道特征的依赖。比如“某一段赛道特别直”这种信息如果奖励函数里针对它做了特别优化换赛道就会失效。所以奖励函数越通用越好最好只依赖速度、转向、偏离中线这几个通用状态。5.3 日志分析的常见误区日志分析看着简单其实坑很多。我总结三个最常见的误区只看平均值不看分布奖励曲线的平均值上升不代表每轮都在变好有可能是少数轮次表现特别好拉高了均值大部分轮次还在原地踏步。建议同时关注分位数曲线比如25%分位的单圈时间。忽略时间维度训练前期奖励上升快后期上升慢甚至横盘这是正常的。不要因为后期曲线平了就觉得没救了先对比一下当前的绝对数值是否已经达到预期。把单一指标当唯一标准单圈时间提升也可能是因为模型学会了抄近道而赛道外沿虽然有缓冲区但这不是你想要的驾驶策略。我建议除了看单圈时间还要看完成率和赛道边界的触碰次数多指标结合才能确认质量。5.4 实操中的意外问题速查表现象可能原因处理办法训练初期Total Reward一直为负奖励函数返回值存在负数模型梯度异常将所有奖励结果通过max函数限制到正数单圈时间一直下不来但完成率很高奖励函数对速度的引导力太弱提高speed_reward权重或在速度上做分段奖励训练中段奖励曲线开始下跌学习率过大导致策略震荡降低学习率或增加batch size评估时模型在测试赛道完全跑不了过拟合模型记住了训练赛道特征简化奖励函数减少对赛道特征的依赖车辆在起点附近反复横跳模型进入“探索死循环”奖励信号区分度不够大幅提高好行为和坏行为的奖励差异让模型快速试错出有效策略6. 最后分享几点个人体会回头再看这个项目我觉得它最有价值的地方不是7.6秒这个数字本身而是暴露了强化学习工程化过程中那个最核心的矛盾——你想要的和你给模型的信号永远是两回事。模型不会听懂你写的注释它只看到数值。任何一个环节的信号解释有误最后策略都会歪到让你意想不到的方向。我的建议很简单每次训练后都花十分钟看日志记录下来你预期模型应该有的表现和它实际的表现然后针对差异去修改奖励函数。不要跳步。我自己跳过几次步比如直接从v1跳到v3结果训练了两百多轮发现方向完全错了白白浪费了好几个小时的计算时间。老老实实一个版本一个版本地迭代反而是最快的方式。最后再留一个非常实用的小技巧在迭代过程中把每个版本的奖励函数和对应训练日志归档到一起命名格式用“版本号_改动点_时间”这种结构。因为在第10次迭代的时候你大概率已经忘了第3次迭代里存在的那个关键细节。这个习惯不只对这个项目有效后续我做任何涉及RL调参的任务都是靠这套归档方式找回灵感的。

关于恒美微站

恒美微站专注于为个体商户、工作室提供极简自助建站服务,让每个人都能轻松拥有专业网站。

快速链接

  • 关于我们
  • 建站服务
  • 主题模板
  • 案例展示
  • 资讯中心

服务项目

  • 可视化建站
  • 拖拽编辑
  • 主题定制
  • SEO 优化
  • 网站托管

联系方式

  • 📍 地址:北京市朝阳区建国路 88 号
  • 📞 电话:400-888-8888
  • ✉️ 邮箱:info@hmyw.cn
  • 🕐 时间:周一至周日 9:00-18:00

© 2024 恒美微站 hmyw.cn 版权所有 | 京 ICP 备 12345678 号