最近在复现几个具身智能方向的实验时,我反复看到一个非常有代表性的论文标题:《Grid or Nodes? Probing Object Memory in World Models Under Partial Observability》。这个标题几乎是一篇研究浓缩的摘要:它同时抛出了表征选择(Grid还是Node)、记忆目标(对象记忆)、模型类型(世界模型)、环境限定(部分可观测)四层信息,而且这四层彼此咬合得很紧。可以说,读懂了这个问题,就等于读懂了当前世界模型研究中最纠结的一条主线:对象记忆到底该用什么数据结构来承载。
这个问题的现实背景非常明确——一个机器人在真实环境里不可能一眼看全所有东西,它走进客厅时看到茶几,走进厨房后茶几就从视野里消失了。但它接下来可能还要回答“茶几在哪个方向”、“我经过茶几后走了多远”这类问题。这时候光有感知不够,必须要有记忆;而记忆的形式,直接决定了下游推理和规划的质量。围绕这一点,我看了不少相关工作,自己也动手搭过几套对比实验。这篇博文就把我对这个问题的拆解、对比实验思路、以及踩过的坑系统梳理一遍,希望能对那些准备入手世界模型、对象记忆或部分可观测决策的同学有帮助。
1. 标题拆解:一个看似简单、实则三层递进的研究问题
1.1 为什么世界模型绕不开“记忆”这个功能
世界模型的核心任务,是让智能体在内部建立一个关于外部环境的动态模型,用来做预测和规划。早期的一些经典做法,把整个世界压缩成一个连续的隐变量向量,用循环网络去预测下一帧的隐状态。这种思路在仿真环境里表现很好,因为仿真场景相对固定、光照变化小、对象数量可控。但一旦放到部分可观测的真实场景,问题就出来了:预测需要依赖的信息,不全在当前的观测里。
举个最直观的例子。一个智能体在一个房间里做导航,目标是把某个物体送过去。它已经转过一个墙角,目标物体完全离开了视野,但运动还要继续。这时候它的世界模型要能回答“目标物体相对于我,现在大概在哪个方向”,才能做出正确的转弯决策。这个问题的答案,不在当前帧的像素里,而在过去帧累积下来的记忆里。
所以记忆不是世界模型的附加功能,而是世界模型在部分可观测环境里能正常工作的前提。这个前提的关键,又在于记忆的存法——是存成一整块密集的网格,还是存成一堆相对独立的节点。这就引出了标题里的第一层对比。
1.2 “Grid or Nodes”:两种记忆逻辑的本质对立
先理解Grid和Nodes分别指什么。Grid路线,最典型的表现是栅格地图或密集特征图,把环境按照固定分辨率切成一个个格子,每个格子记录占用状态、类别分布、特征向量。这是一个以空间坐标为索引的连续表征:不管你关心的对象是桌子还是椅子,都落在同一个坐标系的格子里。
Nodes路线,对应的是场景图、拓扑图或对象为中心的离散集合。每个节点承载一个对象或一个地标,节点之间通过边连接,边上承载相对空间关系和语义关系。你不需要知道这个对象在世界坐标系里的精确坐标,只需要知道“茶几在沙发左边1.5米”这种节点间关系。
这两者的本质区别,是“以空间为中心”还是“以对象为中心”。Grid的优点是天然支持连续空间推理,路径规划、几何计算都很方便;缺点是信息大量冗余,记忆里存了大量墙壁、地板的细节,而真正关键的对象信息被淹没在稠密表征里。Nodes的优点是信息高度浓缩,直接服务于对象级别的推理;缺点是很依赖对象检测和关系提取的质量,一旦对象识别出错,记忆就跟着出错。
1.3 部分可观测性:让“是否有记忆”升级为“记忆长什么样”
如果环境完全可观测,智能体每一帧都能看到全部状态,那记忆问题就被淡化了——重新看一眼就行。但真实环境几乎都是部分可观测的。站在这个角度,部分可观测性带来两个难点。
第一,智能体不知道它没看到的东西发生了什么。对象可能被移走,可能被遮挡,可能自己运动。记忆需要具备“过期处理”的能力,不能永远坚信记忆里的对象还在原地。第二,智能体记忆中的对象和当前观测中的对象需要持续关联,也就是数据关联问题。某人离开房间再回来,你的记忆要判断这是同一个对象,不能因为重新出现就新建一个节点。
因此,部分可观测环境下评估一个记忆表征好不好,至少要看三件事:记忆写入是否高效、记忆读取是否准确、记忆更新是否灵活。这也解释了为什么单纯在仿真里测重建误差远远不够——那些指标很难反映记忆在真实决策链条中的作用。
2. 核心细节解析:两条技术路线到底在PK什么
2.1 Grid表征的实现方式与适用场景
把Grid落到具体实现里,最常见的形式是鸟瞰图(BEV)特征网格,或者三维体素网格。智能体不断把新观测到的对象信息填入对应坐标的格子,同时对已经离开视野的格子保留历史写入的特征。这个过程类似SLAM里维护占据栅格地图,只不过格子存的不只是occupied或free,而是对象类别、语义向量、置信度等更丰富的特征。
Grid表征的优势在于它与底层感知天然兼容。现在的视觉感知模型大多输出空间位置信息,比如检测框的中心坐标、深度值、分割掩码,这些都可以直接映射到网格的坐标上。而且,空间网格对不确定性建模很友好——你可以给每个格子记录一个置信度,当作当前格子信息的可靠程度。下游路径规划只需要在这些网格上做寻路,不需要关心对象级别的语义。
但Grid的硬伤也很明显:内存消耗与场景大小成正比,而不是与对象数量成正比。一个100米乘100米的大场景,如果分辨率做到0.1米,那就是100万格,即使大部分格子都是空的,也要把特征存在那里。另一个问题是固定分辨率造成的“细节取舍困难”——格子太小存不下长距离关系,格子太大又丢失对象边界信息。
2.2 Node表征的实现方式与适用场景
Node表征的核心,是让“对象”成为记忆的基本单位。一个比较成熟的做法是用对象编码器提取每个对象的特征向量,再加上一个位置向量和类别向量,构成一个节点。节点之间用相对位置边、语义关系边相连,边上的属性描述“在左边”“在上面”“是同一类”这类关系。整个记忆结构就是一个动态场景图。
这种做法的实现难点,在对象发现与跟踪。你需要在每一帧里判断:当前观测到的对象,和记忆里已有的哪些节点对应。这个判断如果做不好,记忆里就会积累大量重复节点或者错误关联。相关工作里常用匈牙利匹配算关联成本,或者用可学习的对比损失来训练关联头。
Node表征最大的价值,是它天然支持“遗忘”。节点是离散的、独立的,你可以给每个节点加一个时间戳和置信度,长时间未被激活且置信度低的节点可以直接被淘汰。这种灵活性在Grid里很难做到——你很难从密集网格里单独拆除“茶几”这个对象而不影响它旁边的空间关系。
2.3 两者的共同短板:时间维度上的存储策略
不管是Grid还是Node,都还缺一个维度:时间。记忆里除了“对象在哪里”,还必须要有“这个信息是什么时候知道的”。对象不是静止的,场景也不是。一个在一分钟前看到的节点,与一个在十秒前看到的节点,对决策的权重应当不同。
实操中最常用的做法,是把时间信息编码进特征里。比如给每个对象特征拼上一个时间编码向量,或者用循环网络对同一对象的多次观测做增量更新。Grid路线则通常维护一个“记忆年龄”矩阵,每次访问某个格子就重置年龄,长期不访问的格子逐帧衰减。
有意思的是,很多实验发现,单纯增加时间编码并不能解决记忆漂移问题。根本原因在于,世界模型在学习预测时,往往倾向于把所有误差都归因于可观测的部分,而忽视了记忆中的对象可能在后台发生了变化。换个角度说,模型学到的不是“环境里的对象可被移动”,而是“观测图像平滑过渡”,这就导致预测出来的记忆与现实逐渐脱节。
3. 实操过程:如何设计一组对比Grid与Node记忆的实验
3.1 训练数据与仿真环境的搭建策略
要公平对比两种表征,先得有一个可控的测试场景。我比较推荐从仿真环境入手,因为真实环境很难控制“部分可观测”的程度。我们可以把仿真场景设计成多房间结构,智能体在房间里漫游,视野范围用一个传感器截锥体模拟。这样天然形成部分可观测条件——它永远只能看到前方一块区域,背后的对象一旦离开视野,就只能靠记忆。
控制变量的关键,是让同一批轨迹同时用于两种记忆模式的训练。具体做法是,先设计一张地图,布置好对象位置,然后让智能体按固定轨迹运动,记录它在每个时间步的观测、位姿和内部状态。之后,再生成新的随机轨迹,用于评估记忆泛化性能。
环境设计上要注意几点:对象数量不能太少,至少要10个以上,否则区分不出记忆容量差异;对象要分可移动和不可移动两类,用来探测记忆更新能力;还要设计一些对称场景,避免模型靠位置先验捷径解决问题。
3.2 网络结构与损失函数设计建议
Grid路线的网络,大致是一个“感知编码器+空间记忆缓冲区+预测头”的结构。感知编码器接收当前观测图像,输出鸟瞰图特征;记忆缓冲区负责与历史鸟瞰图特征融合,融合方式可以是简单的加权平均,也可以用门控循环单元做逐格更新。预测头负责读出一块区域当前应出现的对象分布,用于计算预测损失。
Node路线的网络,则是一个“对象检测器+场景图构建器+动态更新模块”的结构。对象检测器输出每一帧的对象提议和特征;场景图构建器负责与已有节点做匹配,决定“新增、更新、连接”这三种操作;动态更新模块把图结构编码成全局记忆向量,供下游决策使用。
损失函数部分,除了任务相关的决策损失之外,我强烈建议加一个显式的对象位置预测损失。也就是说,在观测被遮挡的情况下,模型需要直接输出记忆中被遮挡对象的位置。这个损失能逼着记忆模块真正存下位置信息,而不是靠光流或惯性糊弄过去。如果没有这个损失,两种记忆模式的差异往往被下游策略网络吸收掉,评估结果看不出本质差别。
3.3 评估指标:别只盯着重建误差
很多做世界模型的人习惯看重建误差,觉得重建得越准,模型越好。但在这个对比问题里,重建误差会带来误导。因为Grid表征天然有空间平滑性,重建出来的画面往往在纹理上更接近真实观测;而Node表征重建的是对象级别的信息,纹理细节天然缺失。拿重建误差做PK,Grid几乎是稳赢,但这个“赢”和下游决策能力关系不大。
建议至少看三类指标。第一类是记忆召回率,把场景中的对象分成“目前可见”和“目前不可见”两组,分别统计模型对不可见对象的位置、类别预测准确度。这个指标能反映记忆的真实质量。第二类是下游任务成功率,比如“带路任务”和“寻找对象任务”——给定目标对象名,智能体需要规划一条路到达它所在的位置,成功率和路径次优性都是好指标。第三类是遗忘曲线,记录对象离开视野后,记忆预测精度随时间步的衰减速度,这个最能反映记忆的存续能力。
3.4 消融基线:需要排除哪些干扰因素
做消融实验时,最容易踩的坑是变量不干净。比如Grid表征的参数量往往远大于Node表征,如果在对比时没有控制总参数量,那差异可能是“容量差异”而不是“结构差异”。建议给两种方法设置相近的参数量预算,或者直接做一组“小Grid”与“大Node”的交叉对比。
另外一个重要污染源,是底层感知器的差异。Grid路线通常直接把图像编码成网格,Node路线通常先过对象检测器。如果检测质量参差不齐,实验结果就会混淆感知误差和记忆误差。解决办法是统一使用同一个预训练视觉编码器,只有在真正建立记忆模块时才分支,保证两种路线的感知起点一致。这样对比的才是记忆结构本身,而不是检测器的好坏。
4. 深入分析:为什么部分可观测场景下,Nodes并不总是胜出
4.1 对象记忆的“绑定”难题对Node路线的影响
理论上,在部分可观测场景里,Node表征应该是更有优势的一方:单个对象可以脱离视角而存在,你的记忆不需要为“看不见的区域”保留一整块网格。但实操中,Node表征有一个非常顽固的问题——对象绑定不稳定。
对象绑定是目标检测与多目标跟踪领域的老问题。在世界模型的记忆模块里,这个问题被放大:模型必须在连续的观测中判断“当前看到的这个杯子,是不是我刚才在另一个场景里看到的那个杯子”。如果判断错了,记忆库里就会出现分身节点或幽灵节点。分身节点导致记忆冗余,幽灵节点导致推理混乱。
最麻烦的是,这个问题难以通过增加节点特征维度来解决。因为两个不同对象在特征空间里的距离,可能比同一对象不同视角下的距离还要小——比如一对外观相似的椅子,你很难仅凭视觉特征判断它们是同一把还是两把。解决这类问题,通常需要引入运动一致性约束、空间连续性约束,甚至主动感知策略(让智能体走近一点确认一下),这些都已经超出了“记忆表征”本身的范畴。
4.2 无界累积与容量失控:Grid路线的隐性代价
Grid路线也不是没有好处。最大的好处是,它的存储空间是显式有界的。场景多大、分辨率多高,决定了记忆消耗的上限,超出的信息被截断或覆盖,不会无限增长。相比之下,Node表征的节点数量取决于检测到的对象数量,在开放场景里可能出现无界累积。
比如在一个动态场景里,智能体不断遇到新对象,节点数持续增长。如果不做清理,最终场景图会变得极其庞大,后续的图推理耗时剧增。这就需要在记忆模块里加入主动遗忘机制:根据节点的最后激活时间、任务相关性、置信度三个维度计算遗忘优先级。但这又会引入新的超参,调起来相当考验经验。
我个人的体会是,这两种路线不是纯对立关系,更多是成本结构不同。Grid把成本放在空间维度上,不管有多少对象,都按面积付费;Node把成本放在对象数量上,不管地图多大,只按目标数计费。把这个问题想清楚,就能明白通用智能体的记忆系统大概率是混合结构:用粗粒度Grid负责空间拓扑与路径规划,用细粒度Node负责对象语义与推理。
4.3 结合路线:层次化记忆的可行设计
既然两者各有优劣,很自然的想法是做层次化组合。一个可行的方案是:底层用稀疏Node保存对象信息,上层用粗粒度Grid保存空间信息,两者通过坐标映射建立联系。Node记录“某个对象的具体身份、状态”,Grid记录“这个对象大概在哪个区域、周围有什么”。
这种层次化结构在实现上要解决两个对齐问题。第一是位置对齐,Node的位置信息要和Grid的坐标严格对应,否则推理时会出现对象在Node里说在东边、在Grid里却在西边的矛盾。第二是同步更新问题,当一个Node被更新时,对应Grid格子的特征也要同步刷新;反之,Grid中某个区域的环境变化,也要提醒关联Node去验证自身状态是否过期。
层次化记忆已经在一些具身智能系统里有雏形,但它现在还缺少一套标准化的评测方法。比如,我们很难判断“Grid粗粒度负责到多粗、Node负责到多细”才是最优配置。从工程角度,比较好的切入点是在真实机器人平台上验证导航与问答的联合任务,让每个模块都有清晰的可解释中间输出,这样发现问题时能直接定位到是空间层错还是对象层错。
5. 常见问题与排查技巧实录
5.1 记忆中的对象频繁漂移怎么排查
我在实验里遇到最多的现象,是记忆模块里的对象位置随着时间推移慢慢漂出真实位置,而且方向没有规律。一开始我以为是预测网络的误差累积,后来排查定位到数据关联这一步:对象匹配错误导致同一个对象的多次观测被写进不同节点,于是记忆被“平均”了,位置自然居中漂移。
排查技巧很简单:把每个节点的更新日志打印出来,看它每次触发的是“新增”还是“更新”。如果同一个对象在轨迹中反复触发“新增”,基本可以断定关联策略出了问题。修复方式通常是降低匹配阈值,并引入运动方向约束——同一个对象的两次连续观测,其中心位置的运动速度不应该突变。
另一个处理漂移的有效方式,是给节点增加“观测计数”。每次成功关联就加一,关联失败得多的节点会被标记为低置信度,在推理时降低它的权重。实践下来,这个计数机制比单纯的时间戳衰减更稳,因为它反映了对象被“确认过”的次数,而不是单纯的时间流逝。
5.2 场景规模变大后性能断崖式下降
还有一个常见问题,是在小场景测试集上调参调得很好,一换到大规模场景,性能就崩。Grid路线的故障表现是显存爆炸,因为特征网格随地图面积线性增长;Node路线的故障表现是推理时间暴增,因为场景图里的节点交互变多,图神经网络聚合成本上升。
对Grid路线,我的建议是把记忆网格划分成局部块,只保留智能体周围一定范围内的精细网格,范围外的信息降采样成粗糙的占位网格。这个做法有些类似分层地图,能有效控制显存占用。对Node路线,则建议引入区域聚类,把相距较近的节点聚成一个“区域节点”,图推理先粗后细,先算区域间关系,再算区域内节点关系。
这些问题在论文里经常看不到,因为它们只有在工程落地的环节才会暴露出来。做研究时如果想早点发现,建议从一开始就准备一个大场景压力测试集,而不是连续几周只在小地图上迭代模型。
5.3 过度平滑导致对象记忆“消失”
另一个让我印象深刻的坑是:模型学会了把所有置信度都压到可见区域的格子上,而不可见区域的记忆特征逐渐趋同。这个现象在网格记忆里表现为“预测目标位置收敛到场景中心”,在场景图记忆里表现为“图注意力的权重全部集中到最近的节点上”。本质上,这是记忆信号被过度平滑了。
解决办法是加强监督信号的稀疏性。不要在每个时间步都用稠密的预测损失去更新整个记忆,而是在关键时间步用强信号修正记忆。比如,只在对象重新进入视野、或对象关系发生变化的时刻触发大批量更新,中间帧保持记忆状态不变。这样能避免模型为了压低每个时间步的平滑损失,而把记忆慢慢“磨平”。
实际操作中,可以给损失函数加一个稀疏掩码:只有在记忆中的对象被当前观测“命中”的时候,才计算该位置的预测损失;没有被命中的位置,由遗忘机制自然处理。这样模型就不会被迫去预测那些完全没有观测支撑的区域,也就不容易产生过度平滑的幻觉。
6. 个人实践体会:从对比实验到混合记忆的几点思考
做了一整轮Grid与Nodes的对比实验后,我最大的体会是:不要在“哪种表征更好”上纠结太久,这个问题本身在不设定任务时没有唯一答案。网格表征在定位、路径规划、连续控制任务里有天然优势,因为下游控制模块可以直接消费空间网格;节点表征在问答、推理、跨场景泛化任务里优势明显,因为对象级别的抽象更容易被语言和逻辑模块使用。
更实际的问题,是你的算法栈里什么模块最薄弱。如果对象检测器经常出错,那Node路线就是放大错误;如果你的空间定位漂移严重,那Grid路线就是雪上加霜。做技术选型,首先要看的不是表征的理论上限,而是它在现有pipeline里能发挥多少作用。
如果让我给准备做这个方向的同学一个建议,我会说:先从评测指标入手,先想清楚“什么样的记忆是好的记忆”,再决定用哪种结构。如果你需要判断的是“物体在哪个区域”,Grid可能是最省心的方案;如果你需要判断的是“这个物体和那个物体之间是什么关系”,Nodes才是更适合的载体。大部分时候,你其实是两类问题都要解决,那就朝着层次化结构走——先用节点把对象定义清楚,再用网格把空间锚定住,两个层面之间保持同步更新。这条路短期内不一定有惊艳效果,但长期来看,它是更接近通用智能体记忆架构的方向。