2、强化学习入门:马尔可夫决策过程、状态空间与动作空间设计、奖励函数设计原则
各位同学好,我是你们的老朋友。今天咱们来聊聊强化学习落地关节控制的第一道坎——MDP建模。说实话,我见过太多项目死在了这一步。不是算法不够先进,而是问题本身就没定义清楚。
强化学习说白了,就是让机器人自己学会怎么动。但怎么学?学什么?这得先有个框架。马尔可夫决策过程(MDP)就是这个框架的数学基础。我个人习惯把MDP理解成一个“规则说明书”,它规定了机器人能看到什么、能做什么、做得好不好。
2.1 马尔可夫决策过程:机器人的“世界观”
MDP由五个元素组成:状态S、动作A、转移概率P、奖励R、折扣因子γ。你想想看,这不就是机器人每天在干的事吗?看到当前状态(关节角度),决定下一步动作(输出力矩),然后环境给出反馈(奖励),进入下一个状态。
这里有个关键点——马尔可夫性。说白了就是“未来只取决于现在,跟过去没关系”。我在做六轴机械臂项目时,一开始总想把历史轨迹都塞进状态里,结果状态维度爆炸,训练慢得要死。后来发现,只要当前关节角度和角速度足够精确,历史信息其实没那么重要。
核心公式:
P(s_{t+1} | s_t, a_t) = P(s_{t+1} | s_0, a_0, ..., s_t, a_t)
嗯,这个公式看着唬人,其实意思就是:下一步只跟当前步有关。
我的经验:实际项目中,完全满足马尔可夫性很难。比如关节摩擦就有记忆效应。我的做法是:把最近3-5步的状态堆叠起来作为输入。既保留了时序信息,又不至于维度太高。
2.2 状态空间设计:你到底想让机器人看到什么?
状态空间设计,说白了就是决定机器人的“眼睛”能看到什么。我见过最离谱的设计,是把摄像头图像直接塞进去,结果训练了三天三夜,机器人只会原地转圈。
对于关节控制,我个人建议状态空间包含以下内容:
- 关节位置(角度):必须的,机器人得知道自己胳膊在哪
- 关节速度(角速度):同样必须,不然控制会抖得像帕金森
- 目标位置/轨迹:告诉机器人它要去哪
- 可选:关节加速度、力矩历史:看具体任务需求
举个例子,我做过一个四足机器人项目。状态空间设计成:
状态 = [
12个关节的角度, # 12维
12个关节的角速度, # 12维
机身姿态(roll/pitch/yaw), # 3维
机身线速度, # 3维
目标前进速度 # 1维
]
# 总共 31 维状态空间
避坑指南:我曾经把状态空间设计得太大(加了加速度、加加速度、地面反力等),结果训练时Q值估计方差巨大,策略根本收敛不了。后来我学乖了——能用位置和速度解决的,绝不加加速度。状态维度控制在20-50维是比较舒服的范围。
2.3 动作空间设计:给机器人装“肌肉”
动作空间就是机器人的“肌肉”怎么发力。这里有两个流派:
| 类型 | 描述 | 适用场景 | 我的评价 |
|---|---|---|---|
| 连续动作 | 直接输出力矩/位置增量 | 精细控制、连续轨迹跟踪 | 推荐,更自然 |
| 离散动作 | 输出离散的档位(如:加速、减速、保持) | 简单任务、低精度控制 | 不推荐用于关节控制 |
我个人强烈推荐使用连续动作空间。为什么?你想想看,关节控制本质上就是连续量的调节。你用离散动作去控制,就像用开关控制水龙头——要么太大要么太小,永远调不到刚刚好。
动作空间设计时要注意:
- 归一化:把动作输出限制在[-1, 1]之间,再映射到实际力矩范围。这样有利于神经网络训练。
- 平滑约束:我习惯在动作输出上加一个低通滤波,防止机器人突然发力把自己搞坏。
- 安全限幅:力矩上限、位置极限,这些必须在动作空间层面就卡死。
代码示例:动作空间归一化
# 实际力矩范围:-10Nm 到 10Nm
action_normalized = policy_output # 范围 [-1, 1]
actual_torque = action_normalized * 10.0 # 映射到 [-10, 10]
# 再加个平滑处理
smoothed_torque = 0.9 * prev_torque + 0.1 * actual_torque
2.4 奖励函数设计:机器人的“价值观”
奖励函数是强化学习里最玄学、也最关键的部分。说白了,你给机器人什么奖励,它就学会什么。我见过一个项目,奖励函数只惩罚位置误差,结果机器人学会了疯狂抖动——因为抖动可以暂时减小误差,但能耗和磨损完全没考虑。
奖励函数设计原则,我总结为三条:
- 稀疏 vs 密集:密集奖励(每一步都给反馈)训练快,但容易陷入局部最优。稀疏奖励(只有完成任务才给奖励)训练慢,但策略更鲁棒。我的做法是:先用密集奖励快速训练出基础策略,再用稀疏奖励微调。
- 多目标平衡:跟踪精度、能耗、平滑性、安全性,这些目标往往互相冲突。我习惯用加权求和,但权重需要仔细调。
- 奖励塑形:可以加一些辅助奖励引导探索。比如让机器人先学会“保持站立”,再学“走路”。
举个例子,一个典型的关节跟踪奖励函数:
reward = - w1 * position_error^2
- w2 * velocity_error^2
- w3 * torque^2
- w4 * jerk^2
+ w5 * task_completion_bonus
其中:
- position_error:位置跟踪误差(主要目标)
- velocity_error:速度跟踪误差(防止超调)
- torque:力矩惩罚(节能)
- jerk:加加速度惩罚(平滑性)
- task_completion_bonus:任务完成奖励(稀疏奖励)
我的经验:权重w1到w5怎么调?我一般先让w1=1,其他全设为0,看看机器人能不能学会基本跟踪。然后逐步加入其他项,每次只加一项,观察行为变化。这样调出来的奖励函数,每个项的作用我都心里有数。
避坑指南:我曾经在奖励函数里加了“关节不要超过极限”的惩罚项,结果机器人学会了“永远不动”——因为不动就不会超限,还能拿到零奖励(比负奖励好)。这就是典型的“奖励黑客”现象。后来我改成:只有超出极限才惩罚,正常范围内不惩罚。
2.5 实战中的MDP建模流程
好了,理论说完了,咱们来点实际的。我一般按以下步骤来建模:
- 明确任务目标:是位置跟踪?力控制?还是轨迹规划?目标不同,状态和奖励设计完全不同。
- 确定状态空间:从最小集开始(位置+速度),逐步增加。每次增加一个维度,都要问自己:这个信息真的必要吗?
- 设计动作空间:连续动作,归一化,加安全限幅。先用手动控制测试一下动作范围是否合理。
- 编写奖励函数:先密集后稀疏,多目标加权。在仿真里快速迭代,观察行为是否符合预期。
- 验证MDP:在仿真里跑几个episode,看看状态转移是否合理,奖励是否在预期范围内。
这一步走扎实了,后面的算法训练才能事半功倍。我见过太多人一上来就调PPO、SAC的参数,结果MDP本身就有问题,调来调去都是白费功夫。
总结一下:MDP建模是强化学习落地的基石。状态空间决定机器人“看什么”,动作空间决定机器人“怎么动”,奖励函数决定机器人“学什么”。这三者设计好了,后面的训练就是水到渠成的事。
好了,今天就聊到这。记住,好的MDP设计胜过一百次算法调参。下次咱们聊聊具体的强化学习算法怎么选、怎么调。有什么问题,欢迎随时交流。