大模型智能|分享
来源 | 量子位
奖励不只是告诉智能体‘什么是对的’,更重要的是‘不能让它钻空子’。那段时间我反复调整奖励函数,加了很多约束,慢慢地,智能体学出来的策略开始变得合理了。
你有没有过这种时刻——论文看懂了,算法原理也明白了,别人的 demo 跑得通,心里还挺有底。结果自己写环境的时候,状态怎么定义?动作怎么设计?奖励怎么给?每一步都在怀疑:我是不是根本不适合搞这个?
2024 年 3 月,我开始学习多智能体强化学习(MARL)的时候,就是这种状态。那会儿读过一些论文,跑过几个现成的环境,心里还挺有底,觉得自己差不多算是入门了。现在想想挺好笑的。真正开始写自己的第一个环境才发现,我根本不知道从哪下手。
当时的困惑很具体:我要做的是让多个 AGV 在仓库里协同工作,既要完成任务,又不能撞到一起,还得尽量省时间。听起来很清楚对吧?但坐下来开始写的时候,脑子里全是问号。
AGV 的状态该用什么表示?只给位置够不够?要不要给速度?其他 AGV 的信息要不要给?给多少?动作空间是「上下左右」这么简单,还是要控制速度和转向?奖励怎么给才能让它们既完成任务,又不会互相抢?
那段时间我经常盯着空白的代码文件发呆。不是不会写代码,是不知道该写什么。后来我意识到,问题不在于「怎么实现」,而在于「要实现什么」。
写环境这件事,本质上不是编程问题,是建模问题。你要做的是把一个现实场景翻译成强化学习能理解的语言——定义这个世界是什么样的,智能体能做什么,做对了会怎样,做错了又会怎样。
这个翻译过程,才是最难的部分。
我记得第一版环境写得特别简单。AGV 的状态就是它的坐标,动作就是上下左右四个方向,奖励是到达目标点给 +1,撞墙或者撞到其他 AGV 给 -1。看起来很合理对吧?结果训练的时候,智能体根本学不出来。曲线一直是平的,就像什么都没学到一样。
我当时的第一反应是:肯定是算法有问题。于是换了好几个算法,MAPPO、QMIX、MADDPG、VDN 都试了,结果还是一样。后来我开始怀疑超参数,调学习率、调批大小、调网络结构......折腾了好几天,曲线还是平的。
直到有一天,我坐下来仔细想:如果我是 AGV,拿到这些信息,我能做出正确决策吗? 答案是不能。只给一个坐标,我怎么知道该往哪走?我不知道目标在哪,不知道其他 AGV 在哪,甚至不知道障碍物在哪。智能体学不出来,不是因为它笨,是因为我给的信息根本不够它做判断。
那是我第一次真正理解:写环境,首先要回答的是「智能体需要什么信息才能做决策」。不是「我能给它什么」,而是「它需要什么」。这两个问题听起来差不多,实际上完全不同。前者是从实现的角度思考,后者是从任务的角度思考。
后来我重新设计了状态空间。除了 AGV 自己的位置,还加了到目标点的相对方向和距离,周围一定范围内的障碍物信息,以及能看到的其他 AGV 的相对位置和移动方向。状态维度一下从 2 维变成了十几维,但训练效果立刻不一样了。智能体开始能学到一些基本的行为——朝目标方向走,看到障碍物会绕开。
但新的问题又来了。有时候智能体会学出一些很奇怪的策略。比如有一次,我发现有个 AGV 总是停在原地不动。一开始我以为是 bug,后来仔细看才发现:它在等其他 AGV 把任务都做完。
因为我的奖励设计是「完成任务 +1」,只要不撞车就不扣分。那这个 AGV 算盘打得精——我不动就不会出错,反正别人会把任务做完,我躺平不是挺好的吗?
这让我意识到奖励设计的重要性。奖励不只是告诉智能体「什么是对的」,更重要的是「不能让它钻空子」。
那段时间我反复调整奖励函数,加了很多约束:每走一步给一点点负奖励,逼着它尽快完成任务;如果负载不均衡,给惩罚;如果路径太长,也给惩罚。慢慢的,智能体学出来的策略开始变得合理了。
但又有新问题。有一次我发现,训练的时候效果特别好,几个 AGV 配合得天衣无缝,几乎不会冲突。我当时还挺高兴,觉得终于搞定了。结果把模型拿到仿真环境里一跑,完全不行。AGV 到处撞,策略乱七八糟。
我花了很长时间才找到原因:训练的时候,我为了方便调试,给智能体提供了「全知视角」——它能看到所有 AGV 的实时位置和意图。但在真实场景里,每个 AGV 只能通过传感器看到有限范围内的东西,根本不可能知道其他 AGV 在想什么。
我设计的那个「世界」太理想了,理想到不真实。
这个问题在研究里特别常见。论文里经常看到「我们假设智能体能获得完整的环境信息」,但现实世界哪有这种好事?传感器有限,通信有延迟,很多信息就是拿不到。
如果你按理想情况设计环境,训练出来的策略在现实里就会水土不服。
后来我重新设计了观测空间。每个 AGV 只能看到自己传感器范围内的信息,看不到的地方就是未知的。这样一改,训练难度一下就上去了。因为智能体不再「全知」,它得学会从有限的信息里推断环境状态。
这时候我开始理解图强化学习的价值。在多 AGV 场景里,每个 AGV 是一个节点,它们之间的关系——谁离谁近、谁在往哪走、谁要去哪个目标——可以用图结构表示。
图不是静态的,会随着 AGV 的移动不断变化。用图结构建模这些关系,比简单地把所有信息拼成一个向量要清晰得多。
一开始我只是把 AGV 之间的距离连成边,后来发现这还不够。AGV 和任务之间也有关系——哪个任务离哪个 AGV 近?哪个任务更紧急?
如果把任务也当成图里的节点,整个问题的结构就更清楚了。AGV 节点、任务节点、障碍物节点,通过不同类型的边连接,形成一个动态的关系图。
这种图结构的好处是,智能体不需要知道所有信息,只需要知道它「能看到」的那部分子图。这个子图随着 AGV 的移动在变化,但结构是一致的。这样训练出来的策略,泛化能力会好很多——因为它学的是关系,而不是固定的坐标。
但图结构也带来新的问题:怎么表示这个图?用邻接矩阵吗?那维度会爆炸。用边列表吗?那怎么输入到网络里?
后来我发现图神经网络可以处理这种可变大小的图结构,它能把节点的特征和边的关系编码成一个固定维度的表示。虽然我主要在做环境设计,但理解 GNN 怎么处理图结构,确实帮我更好地设计了状态空间。
那段时间我也会跟 AI 聊,问它一些我卡住的地方。但我发现,AI 给的建议,最有用的不是具体实现,而是帮我理清思路。
它会问我一些问题:「你的智能体真的需要这个信息吗?」「这个奖励会不会引导出你不想要的行为?」「如果是你,拿到这些信息,你能做决策吗?」这些问题逼着我重新审视自己的设计,很多时候问题就在这个审视的过程中暴露出来。
慢慢的我也摸出来一些很朴素的判断:如果训练不收敛,先怀疑环境,再怀疑算法。因为大多数时候,问题不在于算法不够好,而在于环境没设计对。
如果智能体学出奇怪的行为,别急着骂它笨,先看看是不是奖励设计有问题,或者不小心给它留了钻空子的余地。如果训练效果好但实际表现差,检查一下是不是给了它「现实中拿不到」的信息。
还有一个很重要的习惯:先跑最小版本。不要一上来就写完整的复杂环境,先写一个最简单的、能跑通的版本。可能就是个 5×5 的网格,2 个 AGV,2 个任务点,没有障碍物。
跑通了,看曲线,确认基本逻辑没问题,再一点点加复杂度。加障碍物,加更多 AGV,加动态任务......每加一样东西,都重新训练一遍,看性能变化。这样如果出问题,你能立刻知道是哪个环节出了问题。
写环境还有个很容易被忽视的事情:验证。训练之前,一定要做 sanity check。让智能体用随机策略跑几遍,看环境会不会崩,奖励分布合不合理。手动设计一个简单策略,看能拿到多少奖励。如果一个「显然正确」的策略都拿不到高奖励,那肯定是环境设计有问题。
比如我会写一个贪心策略:每个 AGV 总是去最近的任务点。这个策略不是最优的,但至少是合理的。如果这个策略的表现还不如随机,说明奖励函数肯定有问题。有一次我发现贪心策略总是得负分,仔细一查才发现,我把「每步时间惩罚」设得太大了,导致完成任务的正奖励都补不回来。
现在回过头看,写环境这件事,真的是一个「做中学」的过程。没有哪本教材能教你怎么设计一个「对」的环境,因为「对」本身就是相对的,取决于你的任务、你的约束、你的目标。你只能不断试错,不断调整,在一次次的失败里,慢慢摸清楚这个「世界」该怎么运转。
有意思的是,当我在 AGV 任务分配这个场景里把环境写顺了,再去看其他问题,发现很多思路是相通的。比如多机器人协作、无人机编队、物流调度,虽然场景不同,但核心都是:怎么建模多个智能体之间的关系?怎么平衡个体目标和整体目标?怎么在部分可观测的情况下做决策?
这些问题,归根结底还是环境设计的问题。你定义了状态,就定义了这个世界的「眼睛」;你定义了动作,就定义了这个世界的「手脚」;你定义了奖励,就定义了这个世界的「价值观」。而图结构,则是你用来描述这个世界「关系」的语言。
写环境就像在设计一个小世界。但这个世界很容易写得太聪明,聪明到不真实。智能体会严格按照你给的规则行事,如果规则歪了,它学出来的策略就是歪的;如果规则太理想,策略在现实里就用不了。
所以写环境的过程,也是不断拷问自己的过程:这个假设合理吗?这个信息真的能拿到吗?这个奖励真的能引导出我想要的行为吗?这个世界,足够真实吗?
从 2024 年 3 月到现在,不到两年时间,我写过的环境已经有很多个了。AGV 任务分配、多机器人协作、路径规划......每一个问题都是一个新环境,每一个环境也都经历过好几版推倒重来。有的是因为状态空间设计得不够合理,有的是奖励函数引导出了意想不到的行为,有的是发现「训练时的假设」在实际场景里根本站不住脚。
每次重写的时候,我都在想:这个环境,离「真实」又近了一步吗?
因为写环境这件事,本质上就是在定义「什么是真实问题」。算法是通用的,MAPPO、QMIX、MADDPG 拿来就能用。但环境是具体的,每一个实际问题,都需要你重新思考:这个世界的规则是什么?多智能体之间怎么协作?什么样的行为才是整体最优的?
这也是为什么我觉得,强化学习真正的难点,不在算法,在环境。算法是工具,环境才是你要解决的那个「实际问题」本身。
现在我也不再像一开始那样慌了。因为我知道,这就是这件事的样子。它不会一次就对,也不该一次就对。每一次重写,都是对问题理解的加深。每一个新环境,都是对「真实世界」的一次新翻译。
毕竟,世界本来就是在不断修正中慢慢成型的,我们设计的这些小世界,也不例外。

