3. 环境与智能体交互
强化学习的核心闭环是智能体(Agent)与环境(Environment)之间的持续交互。无论是训练一个机器人行走、优化一个推荐系统,还是调度数据中心资源,所有问题都必须被抽象为“环境接口 + 观测空间 + 动作空间 + 奖励信号”四元组。本章将深入拆解环境接口的工程实现方式、观测与动作空间的形式化定义方法,以及奖励信号设计的核心原则与常见陷阱,帮助学习者建立从理论问题到可训练代码的桥梁。
3.1 环境接口设计:从物理世界到代码契约
核心原理:环境接口是智能体与模拟器或真实系统之间的“软件契约”。 Gymnasium 已成为事实标准,其核心抽象为 reset() 和 step() 两个方法。reset() 负责初始化环境并返回初始观测;step(action) 接收动作,推进环境一个时间步,返回四元组 (observation, reward, terminated, truncated, info)。这个接口设计的精妙之处在于它将“环境如何运行”与“智能体如何决策”完全解耦,使得同一套强化学习算法可以无缝迁移到不同任务中。
判断方法与操作流程:设计一个高质量环境接口需要遵循以下流程:
- 明确时间步语义:确定一个 step 对应真实世界的多少时间(如 0.1 秒控制周期),这直接影响训练效率与物理仿真精度。
- 定义终止条件:区分
terminated(任务达成或失败,如机器人摔倒)与truncated(达到最大步数或超时)。两者在训练中处理方式不同——前者意味着 episode 自然结束,后者通常需要 bootstrapping。 - 实现信息隐藏:环境内部状态(如物理引擎中的坐标)不应直接暴露给智能体,只能通过观测函数输出部分信息,这模拟了真实世界的部分可观测性。
- 保证可复现性:支持随机种子设置,确保实验可对比。
工程实践要点:在实现自定义环境时,建议继承 gymnasium.Env 基类,并严格定义 observation_space 和 action_space 属性。使用 gymnasium.spaces.Box 表示连续空间(需指定 low 和 high 边界),Discrete 表示离散空间。对于复杂观测(如视觉+传感器融合),使用 Dict 空间组合。务必在 step() 中做动作合法性校验,防止非法输入导致仿真崩溃。
| 接口方法 | 输入 | 输出 | 关键职责 |
|---|---|---|---|
| reset() | seed, options | obs, info | 重置环境状态,返回初始观测 |
| step(action) | action | obs, reward, terminated, truncated, info | 执行动作,推进环境,返回转移结果 |
| render() | mode | 图像/窗口 | 可视化调试(训练时建议关闭) |
| close() | 无 | 无 | 释放资源(如关闭渲染窗口) |
常见误区:许多初学者将 terminated 与 truncated 混为一谈。在 PPO 或 DQN 实现中,如果错误地将 truncated 当作 terminated 处理,会导致价值函数对“因超时结束”的状态进行错误 bootstrap,造成价值估计偏差。正确做法是:当 truncated=True 时,仍应使用 V(s') 进行自举;当 terminated=True 时,目标值直接为 r。
3.2 观测空间与动作空间的形式化定义
核心原理:观测空间 O 定义了智能体“能看到什么”,动作空间 A 定义了智能体“能做什么”。在数学上,观测是状态 s 的函数 o = O(s),而策略 π(a|o) 是基于观测的条件概率分布。动作空间的设计直接影响算法的选择:离散动作空间适合 DQN、PPO 等;连续动作空间需要 DDPG、SAC、TD3 等算法。混合动作空间(如先选技能再选参数)则需要更复杂的架构。
判断方法与操作流程:定义观测与动作空间时,应遵循“最小充分”原则:
- 观测空间设计:只包含决策所需的最小信息集。例如,在倒立摆任务中,观测只需摆杆角度和角速度,无需位置信息。对图像观测,应统一尺寸并归一化到 [0,1] 或 [-1,1]。对多源异构数据,使用 Dict 空间并分别归一化。
- 动作空间设计:优先使用物理意义明确的动作表示。对于机器人控制,使用关节力矩或目标位置比使用关节速度更稳定。对于离散动作,应保证动作集合的完备性(覆盖所有可行选择)和互斥性(无歧义)。
- 动作掩码(Action Masking):当某些动作在特定状态下非法时(如棋盘游戏中落子已占位置),应使用动作掩码将非法动作的概率置为 0,而不是依赖奖励惩罚。
经验提醒:连续动作空间务必设置合理的边界(low/high),并在环境内部做 clip 处理。但要注意,clip 动作会导致策略梯度估计偏差——如果动作频繁触界,说明边界设置不合理或奖励函数未约束动作幅度。更好的做法是在奖励函数中加入动作幅度的惩罚项,让智能体学会在边界内动作。
# 示例:自定义环境空间定义
import gymnasium as gym
from gymnasium import spaces
import numpy as np
class RobotArmEnv(gym.Env):
def __init__(self):
super().__init__()
# 观测:关节角度(3) + 关节角速度(3) + 末端位置(3)
self.observation_space = spaces.Box(
low=np.array([-3.14]*3 + [-5.0]*3 + [-2.0]*3),
high=np.array([3.14]*3 + [5.0]*3 + [2.0]*3),
dtype=np.float32
)
# 动作:关节力矩指令(3),范围 [-1, 1]
self.action_space = spaces.Box(
low=-1.0, high=1.0, shape=(3,), dtype=np.float32
)
# 也可以使用 Dict 组合不同来源的观测
# self.observation_space = spaces.Dict({
# "joint_state": spaces.Box(...),
# "camera_image": spaces.Box(low=0, high=255, shape=(64,64,3), dtype=np.uint8)
# })
3.3 奖励信号设计原则:塑造学习的方向盘
核心原理:奖励函数 R(s,a,s') 是强化学习中最具主观性的设计环节,它定义了“什么行为是好的”。奖励信号设计的核心矛盾在于稀疏性与密集性之间的权衡。稀疏奖励(如围棋的胜/负)易于定义但难以学习;密集奖励(如每一步的距离惩罚)加速收敛但可能引入局部最优。奖励塑形(Reward Shaping)理论指出,只要塑形函数 F(s,s') = γΦ(s') - Φ(s) 满足基于势能的形式,就不会改变最优策略。
判断方法与操作流程:设计奖励函数应遵循以下步骤:
- 从任务目标倒推:明确最终评价指标(如到达目标点、得分最大化),将其作为稀疏奖励的基准。
- 添加过程引导:使用势能函数
Φ(s)引导智能体,例如距离目标的负距离、任务进度的百分比。确保塑形项满足γΦ(s') - Φ(s)形式。 - 惩罚危险行为:对碰撞、越界、超时等行为给予明确负奖励,但惩罚幅度不宜过大,否则智能体会倾向于“什么都不做”来避免惩罚。
- 奖励归一化:将奖励尺度控制在 [-1, 1] 或 [0, 1] 区间,有助于稳定训练。使用 RunningMeanStd 对奖励流进行动态归一化。
案例拆解:自动驾驶变道决策
背景与约束:在高速公路场景中训练自动驾驶车辆变道策略。初始稀疏奖励为:成功变道 +1,碰撞 -10,超时 -1。直接训练发现智能体几乎不学习变道,因为随机探索很难触发成功事件。
分析过程:通过观察训练曲线,发现奖励信号过于稀疏,智能体陷入“原地不动”的局部最优。引入势能塑形:Φ(s) = -|d_target - d_current|,其中 d 为车辆与目标车道的横向距离。塑形奖励为 γΦ(s') - Φ(s),当车辆靠近目标车道时获得正向引导。
实际操作:修改奖励函数为 r = r_sparse + 0.5 * (γΦ(s') - Φ(s))。同时增加安全约束:当与后车距离小于安全阈值时,额外施加 -0.1 的惩罚。
结果对比:加入塑形后,训练收敛速度提升约 3 倍,成功率从 12% 提升至 87%。但发现智能体学会“先远离再靠近”的绕路策略来获取更多塑形奖励,通过限制塑形项仅在横向距离单调递减时生效,解决了该问题。
复盘经验:奖励塑形必须基于势能函数,否则会改变最优策略;塑形系数不宜过大(0.1~0.5 倍稀疏奖励量级);需要监控塑形奖励与稀疏奖励的比例,防止智能体“刷分”。
| 设计原则 | 推荐做法 | 反例 |
|---|---|---|
| 稀疏性 | 先定义稀疏目标奖励,再逐步添加塑形 | 一开始就设计复杂密集奖励 |
| 可学习性 | 奖励应随行为改善单调递增 | 奖励函数存在大量平坦区域 |
| 鲁棒性 | 对观测噪声不敏感 | 依赖精确的传感器读数 |
| 安全性 | 对危险行为有明确惩罚 | 惩罚过重导致保守行为 |
| 可解释性 | 每个奖励分量有明确语义 | 多个奖励项相互耦合 |
常见误区总结:
- 奖励过密导致“刷分”:智能体找到奖励漏洞(如原地转圈获得正奖励),而非完成任务目标。
- 忽略时间成本:未对每步施加微小时间惩罚(如 -0.01),导致智能体行动迟缓。
- 奖励尺度不一致:不同奖励分量数量级差异过大(如 +100 与 -0.1),小分量被淹没。
- 忽视部分可观测性:奖励依赖智能体无法观测的状态信息,导致训练不稳定。
总结复盘:环境接口、观测/动作空间与奖励信号三者构成强化学习问题的“输入输出契约”。接口设计决定了工程实现的稳定性,空间定义决定了算法选择的自由度,而奖励设计则直接决定了学习的方向与效率。在实际项目中,建议先以最小可行环境跑通训练流程,再逐步迭代优化观测表示与奖励塑形。记住一个核心原则:环境是客观的,但观测与奖励是设计者主观的“透镜”——透镜磨得越好,智能体看世界越清晰,学习效率越高。