1. DeepRacer奖励函数设计基础当你第一次接触DeepRacer时最让人头疼的就是如何设计一个有效的奖励函数。这就像教一个刚学开车的小朋友你需要明确告诉他什么行为值得表扬什么行为应该避免。奖励函数就是AI赛车手的教练它决定了赛车在训练过程中学习什么样的驾驶策略。在DeepRacer比赛中赛道通常由一系列航点(waypoints)组成这些点连起来形成了赛道的中心线。我们的首要目标就是让赛车尽可能贴近这条中心线行驶。想象一下就像骑自行车时保持平衡一样离中心线越近获得的奖励就应该越高。这里有个简单的距离奖励计算公式def distance_reward(params): track_width params[track_width] distance_from_center params[distance_from_center] # 计算距离中心线的比例(0到1之间) normalized_distance distance_from_center / (track_width/2) # 确保奖励在0到1之间 reward 1 - normalized_distance return max(0.001, reward) # 避免零奖励这个基础版本虽然简单但在实践中你会发现它有几个明显问题赛车可能会为了保持绝对居中而牺牲速度或者在弯道处表现不佳。我曾经在一个简单赛道上测试过这个基础版本结果赛车在直道上表现不错但一到弯道就会明显减速最终圈速很不理想。2. 赛道几何与航向角优化2.1 航向角偏差惩罚单纯考虑距离中心线是不够的我们还需要关注赛车的朝向是否正确。这就引入了航向角(heading)的概念 - 即赛车当前方向与赛道方向的夹角。在急转弯处这个角度差可能很大我们需要相应调整奖励。计算航向角偏差的关键代码如下def heading_reward(params): waypoints params[waypoints] closest_waypoints params[closest_waypoints] heading params[heading] # 计算赛道方向(当前点和下一个点的连线方向) next_point waypoints[closest_waypoints[1]] prev_point waypoints[closest_waypoints[0]] track_direction math.atan2(next_point[1]-prev_point[1], next_point[0]-prev_point[0]) track_direction math.degrees(track_direction) # 计算方向差异(0-180度之间) direction_diff abs(track_direction - heading) if direction_diff 180: direction_diff 360 - direction_diff # 方向差异越大奖励越小 if direction_diff 30: # 超过30度就给予严重惩罚 return 0.001 else: return 1 - (direction_diff / 30)2.2 动态权重调整在实际比赛中我发现直道和弯道需要不同的奖励策略。直道上可以更注重速度而弯道则需要更关注航向准确性。于是我对奖励函数做了动态调整# 计算当前赛段的曲率(判断是直道还是弯道) def calculate_curvature(waypoints, closest_waypoints, lookahead5): points waypoints[closest_waypoints[0]:closest_waypoints[0]lookahead] if len(points) 3: return 0 # 使用三点法计算曲率 x [p[0] for p in points] y [p[1] for p in points] dx np.gradient(x) dy np.gradient(y) d2x np.gradient(dx) d2y np.gradient(dy) curvature np.abs(dx*d2y - dy*d2x) / (dx*dx dy*dy)**1.5 return np.mean(curvature) # 根据曲率动态调整奖励权重 curvature calculate_curvature(waypoints, closest_waypoints) if curvature 0.1: # 弯道 heading_weight 0.7 speed_weight 0.3 else: # 直道 heading_weight 0.3 speed_weight 0.73. 速度优化策略3.1 理想速度曲线DeepRacer比赛中最大的挑战之一就是速度控制。赛车不能一直全速前进特别是在弯道处。我们需要为每个赛段定义理想速度这通常通过分析最优赛车线得到。一个实用的速度奖励函数如下def speed_reward(params): speed params[speed] waypoints params[waypoints] closest_waypoints params[closest_waypoints] # 获取当前赛段的理想速度(可以预先计算存储) optimal_speed get_optimal_speed(closest_waypoints[0]) # 计算速度差异 speed_diff abs(optimal_speed - speed) # 小差异不惩罚大差异二次惩罚 if speed_diff 0.5: return 1 elif speed_diff 1.0: return 1 - (speed_diff-0.5)**2 else: return 0.0013.2 加速度控制除了绝对速度加速度控制也很重要。突然的加速或减速都会影响赛车稳定性。我们可以通过记录上一步的速度来判断加速度class SpeedMonitor: def __init__(self): self.last_speed 0 self.last_step 0 def acceleration_reward(self, params): current_speed params[speed] steps params[steps] # 计算加速度(m/s^2) if steps self.last_step 1: acceleration (current_speed - self.last_speed) * 15 # 15 steps per second else: acceleration 0 # 更新记录 self.last_speed current_speed self.last_step steps # 加速度在±3m/s^2内不惩罚 if abs(acceleration) 5: # 急加速/急刹车 return 0.001 elif abs(acceleration) 3: return 0.5 else: return 14. 高级奖励策略4.1 进度奖励为了让赛车尽快完成比赛我们需要引入进度奖励。这就像告诉赛车手你完成得越快奖励越多。但要注意平衡即时奖励和长期奖励。def progress_reward(params): progress params[progress] steps params[steps] # 基准步数(根据赛道长度和理想速度估算) benchmark_steps 150 # 当前进度对应的理想步数 ideal_steps steps / (progress/100) if progress 0 else float(inf) # 计算进度奖励 if ideal_steps benchmark_steps: return 1 (benchmark_steps - ideal_steps)/benchmark_steps else: return max(0.001, 1 - (ideal_steps - benchmark_steps)/benchmark_steps)4.2 赛道边界处理赛车偶尔偏离赛道是难免的但我们要确保它能快速回到正轨。一个有效的边界处理策略是def track_edge_reward(params): all_wheels_on_track params[all_wheels_on_track] distance_from_center params[distance_from_center] track_width params[track_width] if not all_wheels_on_track: return 0.001 # 完全出界 # 接近边界时给予警告 edge_distance (track_width/2) - distance_from_center if edge_distance 0.1: # 离边界只有10cm return 0.3 elif edge_distance 0.2: return 0.7 else: return 14.3 综合奖励函数最后我们需要将所有奖励组件合理地组合起来。经过多次实验我发现这样的权重分配效果不错def reward_function(params): # 计算各组件奖励 dist_reward distance_reward(params) head_reward heading_reward(params) speed_rew speed_reward(params) accel_rew speed_monitor.acceleration_reward(params) progress_rew progress_reward(params) edge_rew track_edge_reward(params) # 动态权重调整 curvature calculate_curvature(params[waypoints], params[closest_waypoints]) if curvature 0.1: # 弯道 weights { distance: 0.4, heading: 0.3, speed: 0.1, acceleration: 0.1, progress: 0.05, edge: 0.05 } else: # 直道 weights { distance: 0.2, heading: 0.1, speed: 0.4, acceleration: 0.2, progress: 0.05, edge: 0.05 } # 综合奖励 reward ( dist_reward * weights[distance] head_reward * weights[heading] speed_rew * weights[speed] accel_rew * weights[acceleration] progress_rew * weights[progress] edge_rew * weights[edge] ) return float(max(0.001, reward))在实际比赛中我使用这个奖励函数后赛车圈速提升了约15%。最关键的是赛车在不同类型的赛道上都表现稳定既能快速通过直道又能优雅地过弯。