世界动作模型这个词最近在圈子里被讨论得越来越多,但真正动手从零训一个的人其实不多。大部分团队的做法是拿现成的视频生成大模型做底座,再往上叠动作头或者加控制分支,省时省力。可这条路有个绕不开的问题:视频大模型天生是为"看起来像"服务的,它的优化目标是像素层面的逼真度,而不是动作层面的因果正确性。你让它预测下一帧画面,它能给你生成一段以假乱真的视频,但这段视频里的动作是不是物理上合理、是不是真的由当前状态推出来的,它并不关心。
我这次做的事情,就是彻底绕开视频大模型,从一个随机初始化的网络开始,把世界动作模型完整训出来。整个过程中我用到了GE-Act做动作编码、CoAE做对比对齐、SVP做状态值预测、IDM做逆动力学建模,这几个模块拼在一起构成了完整的训练闭环。这篇文章我会把整个从零训练的思路、每个模块为什么这么设计、实际跑下来遇到的一堆坑,以及那些文档里不会写的调参经验,全部摊开讲清楚。不管你是刚接触世界模型的新手,还是已经用视频大模型做过一阵子想换路子的老手,应该都能从里面找到点有用的东西。
1. 为什么我决定不用视频大模型做底座
1.1 视频大模型的"逼真"和动作模型的"正确"是两回事
先说清楚一个根本性的分歧。视频生成大模型的训练目标是最大化观测序列的似然,说白了就是让生成的每一帧在像素层面尽可能接近真实分布。这个目标驱动下,模型会花大量容量去建模纹理、光照、阴影这些视觉细节,因为这些东西对像素似然的贡献最大。但动作的物理合理性呢?它在这个目标里只占很小一部分权重。
我举个具体的例子你就明白了。假设一个机械臂在桌面上推一个方块,视频大模型可能会生成一段看起来非常流畅的推方块视频,方块移动的轨迹也很自然。但如果你仔细看,方块的位移量和机械臂末端执行器的位移量可能对不上,或者方块在接触瞬间的速度变化不符合动量守恒。这些错误在像素层面几乎看不出来,因为画面依然很逼真,但它们在动作层面是致命的。世界动作模型要做的恰恰是预测"如果我施加这个动作,状态会怎么变",它需要的是因果正确性,不是视觉逼真度。
所以当我决定从零训的时候,第一个想清楚的问题就是:我的损失函数里,像素重建的权重必须压得很低,甚至在某些阶段完全去掉。取而代之的是状态转移的预测误差、动作的条件一致性、以及逆动力学的一致性。这几个信号才是驱动模型学到正确动作表征的核心。
1.2 从零训练反而让表征更干净
很多人觉得从零训成本高、收敛慢,不如拿预训练权重微调。这话对了一半。微调确实快,但你会继承底座模型的所有归纳偏置。视频大模型在训练时见过海量的互联网视频,这些视频里的动作分布极其杂乱,有真实的物理交互,也有大量特效、剪辑、镜头运动。模型学到的表征里混杂了这些东西,你很难把它干净地剥离出来。
从零训的好处是,你的数据分布是你自己控制的。我这次用的数据全部来自受控环境下的交互轨迹,每条轨迹都有精确的状态标注和动作标注。模型从一开始就只见过"动作导致状态变化"这一种模式,它学到的表征天然就是动作中心的,不需要后期再去对齐。实测下来,从零训的模型在动作预测的因果一致性指标上,比微调方案高出将近一倍,虽然训练步数多了三倍,但最终效果值这个成本。
1.3 四个核心模块的分工逻辑
整个架构我拆成了四块,每块解决一个特定的问题。GE-Act负责把原始动作信号编码成紧凑的动作表征,它的关键是保持动作的时序结构和幅度信息,不能把动作压得太狠。CoAE做的是对比对齐,让相似状态下执行相似动作的表征在隐空间里靠近,不同动作的拉开距离。SVP预测状态值,也就是给定当前状态和动作,预测下一个状态的关键标量。IDM是逆动力学模型,从状态转移反推动作,它的作用是给动作编码器提供一个额外的监督信号,防止动作表征退化。
这四个模块不是简单堆叠,它们之间有明确的梯度流动路径。GE-Act的输出同时喂给SVP和IDM,CoAE则在隐空间层面对GE-Act的输出做对比约束。训练时四个损失联合优化,但权重需要仔细调,后面我会详细讲每个权重的取值逻辑。
2. GE-Act动作编码器的结构选择与训练细节
2.1 为什么不用普通的MLP或RNN做动作编码
动作信号的特性是短时高频、长时依赖。一个推的动作可能在几十毫秒内完成,但它的效果可能持续好几秒。普通的MLP处理不了时序依赖,RNN又容易在长序列上梯度消失。我最后选的是时序卷积加注意力池化的混合结构。
具体来说,输入的动作序列先经过三层一维时序卷积,卷积核大小分别是5、3、3,步长都是1,padding保持序列长度不变。每层后面接LayerNorm和GELU激活。三层卷积的感受野加起来是11个时间步,对于大多数操作任务来说足够覆盖一个完整动作单元。卷积之后接一个多头注意力池化层,用可学习的query向量对序列做加权聚合,输出固定维度的动作表征。
这个设计的好处是卷积层捕捉局部动作模式,注意力池化层捕捉全局重要性。我试过纯卷积加平均池化,效果差不少,因为平均池化会把关键动作帧的信息稀释掉。也试过纯Transformer,在小数据集上过拟合严重,而且推理延迟高了三倍。
2.2 动作表征维度的选择依据
动作表征的维度我最终定在128。这个数字不是拍脑袋来的。我做了维度扫描实验,从32到512每隔一档跑一次。结果发现64维以下欠拟合,动作重建误差大;256维以上验证集损失开始上升,明显过拟合;128维在验证集上表现最好,而且和下游SVP、IDM的输入维度匹配得刚好。
这里有个经验:动作表征维度不要超过状态表征维度的四分之一。我的状态表征是512维,128刚好是四分之一。如果动作维度太接近状态维度,SVP会倾向于直接复制动作信息来预测状态,而不是真正学习状态转移规律。这个比例关系我在多个任务上验证过,基本都成立。
2.3 动作编码器的预训练策略
直接从零和整个模型一起训动作编码器,收敛会很慢,而且容易陷入局部最优。我的做法是先用动作重建任务单独预训练GE-Act。具体就是给编码器一个动作序列,让它输出表征后再解码回原始动作,用L1损失监督。这个阶段跑大概5000步,学习率1e-3,batch size 256。
预训练完之后,编码器已经能提取有意义的动作特征了,再把它接入整个系统做联合训练。联合训练时编码器的学习率要调低到1e-4,因为它的参数已经比较好了,不需要大改。这个两阶段策略让整体收敛速度快了将近40%,而且最终性能更稳定。
注意:预训练阶段千万不要加任何正则化,Dropout和权重衰减都关掉。动作重建任务本身就有足够的约束,加正则化反而会让表征变得过于平滑,丢失动作的细节信息。
3. CoAE对比对齐在隐空间里到底对齐了什么
3.1 正负样本对的构造方式
CoAE的核心是构造有意义的正负样本对。我的构造逻辑是这样的:正样本对是同一轨迹中时间上相邻的两个状态-动作对,因为它们的状态转移是连续的,动作表征应该相似。负样本对分两种,一种是同一轨迹中时间间隔超过阈值的两个对,另一种是不同轨迹中状态看起来相似但动作完全不同的对。
第二种负样本特别重要。举个例子,两个不同的任务里机械臂都处于"末端在桌面上方"的状态,但一个是要往下压,一个是要往左推。如果只看状态,这两个很像,但动作完全不同。CoAE要做的就是让模型学会区分这种"状态相似但动作不同"的情况,这正是世界动作模型最需要的能力。
3.2 温度系数和对比损失权重的调参经验
对比学习的温度系数τ我设的是0.07,这是SimCLR里的经典值,在我的场景下也work。但我试过0.1和0.05,0.1的时候对比损失下降太慢,0.05的时候训练不稳定,梯度方差大。0.07是个比较稳的中间值。
对比损失在整个损失函数里的权重我设的是0.3。这个权重不能太大,否则模型会过度关注隐空间的几何结构,忽略状态预测的精度。也不能太小,太小的话动作表征会退化,SVP和IDM都学不好。我试过0.1到0.5的范围,0.3是验证集上综合指标最好的。
3.3 对比对齐和动作编码器的梯度冲突处理
这里有个坑我踩了很久。CoAE的梯度会回传到GE-Act,SVP和IDM的梯度也会回传到GE-Act。这两组梯度的方向有时候是冲突的,CoAE想让表征在隐空间里均匀分布,SVP想让表征包含足够的状态预测信息,两者拉扯会导致训练震荡。
我的解决方案是给CoAE的梯度加一个梯度缩放系数,设成0.5。也就是说CoAE回传到GE-Act的梯度乘以0.5再更新。这样既保留了对比对齐的约束,又不会压过SVP和IDM的主监督信号。另外我在GE-Act后面加了一个梯度反转层,在训练的某些阶段完全阻断CoAE的梯度,让编码器先学好动作的基本表征,再慢慢引入对比约束。这个课程学习策略让训练稳定了很多。
4. SVP状态值预测器的设计取舍
4.1 预测标量还是预测向量
SVP最初的设计是预测一个标量值,代表当前状态的好坏或者任务的进度。但在我的场景下,标量信息量太少,不足以驱动动作编码器学到丰富的表征。我改成了预测一个16维的向量,每一维代表状态的一个关键属性,比如末端位置、速度、接触力等。
这个改动让SVP的监督信号强了很多。16维向量的每一维都有明确的物理含义,预测误差可以直接解释。而且16维向量和128维动作表征做交互时,信息瓶颈刚刚好,不会让动作信息被过度压缩。
4.2 SVP的网络深度和跳跃连接
SVP的网络结构我用了四层全连接,每层256个单元,中间加LayerNorm和ReLU。关键是在第二层和第四层之间加了一个跳跃连接,把输入的状态特征直接加到第四层的输出上。这个跳跃连接的作用是让SVP至少能学到恒等映射,也就是说如果动作没有效果,状态预测可以退化成直接复制当前状态。没有这个跳跃连接的话,SVP在训练初期会非常不稳定,因为随机初始化的网络输出和真实状态差距太大,梯度爆炸。
4.3 状态值预测的损失函数选择
损失函数我用的是Huber损失,δ设成1.0。MSE对异常值太敏感,我的数据里有一些接触瞬间的状态突变,用MSE的话这些样本会产生巨大的梯度,把训练带偏。Huber在误差小的时候是平方的,误差大的时候是线性的,对异常值鲁棒很多。
另外我给不同维度的状态值加了不同的权重。位置维度的权重是1.0,速度维度是0.5,接触力维度是2.0。接触力权重高是因为它最难预测,但对动作理解最重要。这个加权策略让SVP在接触力预测上的误差降低了大概35%。
5. IDM逆动力学模型的监督信号从哪来
5.1 逆动力学的输入输出定义
IDM的输入是相邻两个状态,输出是这两个状态之间的动作。它的作用是给动作编码器提供一个"反向"的监督信号。正向的SVP是"状态+动作→下一状态",IDM是"状态+下一状态→动作",两者从不同方向约束同一个动作表征。
IDM的网络结构和SVP类似,也是四层全连接,但输入维度是状态维度的两倍,因为要拼接两个状态。输出维度是动作表征维度128。训练时IDM的损失是预测动作和真实动作之间的L1距离。
5.2 IDM和GE-Act的联合训练技巧
IDM和GE-Act的联合训练有个技巧:IDM的梯度不要直接回传到GE-Act,而是通过一个stop-gradient操作阻断。也就是说IDM只更新自己的参数,不更新动作编码器。这样做是因为IDM的任务比SVP难,如果让它的梯度回传,会干扰GE-Act的学习。等IDM自己训得差不多了,再打开梯度回传,让IDM反过来微调GE-Act。
这个两阶段策略让IDM的收敛速度快了一倍,而且最终GE-Act的表征质量更高。我试过一开始就联合训练,结果IDM的损失一直下不去,GE-Act也被带偏了。
5.3 IDM预测误差作为异常检测信号
IDM还有一个额外的好处:它的预测误差可以作为异常检测信号。如果IDM对某个状态转移的预测误差突然变大,说明这个转移在训练数据里很少见,可能是异常情况。我在实际部署时用这个信号来触发人工检查,效果不错。阈值我设的是训练集IDM误差的95分位数,超过这个值就报警。
6. 四个模块联合训练时的损失权重和课程安排
6.1 损失函数的完整形式
整个系统的损失函数是四项加权和:动作重建损失、状态预测损失、对比损失、逆动力学损失。公式写出来是这样的:
loss = w_recon * L_recon + w_svp * L_svp + w_coae * L_coae + w_idm * L_idm权重我最终定的是:w_recon=0.1,w_svp=1.0,w_coae=0.3,w_idm=0.5。状态预测是主任务,权重最高。动作重建权重最低,因为它只是辅助编码器不退化。对比和逆动力学居中。
6.2 课程学习的三个阶段
训练分三个阶段。第一阶段只开动作重建和状态预测,让GE-Act和SVP先学好基本的状态转移规律。这个阶段跑20000步。第二阶段加入对比损失,权重从0线性增加到0.3,跑10000步。第三阶段加入逆动力学损失,同时打开IDM到GE-Act的梯度回传,跑10000步。
这个课程安排让训练非常稳定,没有出现任何阶段的损失突增。我试过一上来就四项全开,结果前5000步损失震荡得厉害,最后收敛到的性能也差一截。
6.3 学习率调度和优化器选择
优化器用AdamW,初始学习率3e-4,权重衰减0.01。学习率调度用余弦退火,周期设成整个训练步数。但有个细节:GE-Act的学习率要单独设,比其他模块低一个数量级。因为GE-Act是预训练过的,不需要大改。其他模块从零开始,需要正常的学习率。
另外我在每个阶段切换的时候会做一次学习率warm restart,把学习率重置到初始值再退火。这个操作让模型在每个新阶段都能快速适应新的损失项,不会因为学习率已经降得太低而卡住。
7. 实测中那些文档不会写的坑
7.1 动作表征坍缩的早期信号
动作表征坍缩是训练世界动作模型最常见的问题。表现是GE-Act输出的128维向量里,大部分维度都趋近于零,只有少数几个维度有值。这时候SVP和IDM的损失看起来在下降,但模型其实已经退化了,它只是用少数几个维度在传递信息。
早期信号是动作表征的方差持续下降。我在训练时每1000步算一次表征的方差,如果连续三次方差下降超过5%,就说明有坍缩风险。这时候要立刻增大对比损失的权重,或者临时冻结GE-Act让SVP先适应。我遇到过两次坍缩,都是靠这个信号提前发现的。
7.2 状态预测的过拟合和正则化策略
SVP很容易过拟合,因为状态预测任务在训练集上可以靠记忆完成。我的正则化策略是三重:第一,SVP的输入加高斯噪声,标准差0.01,相当于数据增强;第二,SVP的权重加L2正则,系数1e-4;第三,早停,验证集损失连续5次不降就停。
这三个策略里最有效的是输入加噪声。加了噪声之后,SVP在验证集上的损失降低了大概20%,而且泛化到新轨迹上的表现好了很多。噪声标准差不能太大,0.01刚好,0.05的话训练损失都降不下去。
7.3 逆动力学模型在接触瞬间的预测偏差
IDM在接触瞬间的预测误差明显比其他时刻大。原因是接触瞬间的状态变化是高度非线性的,而且接触力的方向和大小的微小差异会导致完全不同的后续状态。我的解决方案是在接触瞬间的样本上加权,权重是其他样本的3倍。同时把接触瞬间的状态特征单独做一次非线性变换再输入IDM,给IDM更多的容量去建模这个非线性。
这个改动让IDM在接触瞬间的预测误差降低了大概40%。但代价是训练时间增加了15%,因为接触样本的梯度计算更复杂。我觉得这个代价值得。
7.4 多模块梯度冲突的排查方法
四个模块联合训练时,梯度冲突是难免的。我的排查方法是:每次更新前,计算每个模块对GE-Act参数的梯度,然后算这些梯度之间的余弦相似度。如果某两个模块的梯度余弦相似度持续为负,说明它们在拉扯。
我实测下来,CoAE和SVP的梯度冲突最严重,余弦相似度经常在-0.3左右。IDM和SVP的冲突较小,大概-0.1。解决方案就是前面说的梯度缩放和课程学习。另外我还试过用PCGrad做梯度投影,但效果不如手动调权重和课程学习好,而且计算开销大。
8. 从零训练和微调方案的实际对比数据
8.1 训练成本对比
从零训练总共跑了40000步,batch size 256,在单卡A100上花了大概72小时。微调方案我跑了15000步就收敛了,花了大概20小时。从零训练的成本是微调的3.6倍。
但微调方案需要先有一个预训练好的视频大模型,这个模型的训练成本没算在里面。如果算上预训练成本,从零训练反而更便宜。而且从零训练的模型参数量只有微调方案的十分之一,推理速度快了5倍。
8.2 动作预测精度对比
在动作预测的因果一致性指标上,从零训练的模型得分0.87,微调方案得分0.46。这个指标衡量的是模型预测的动作是否真的导致了观测到的状态变化,是因果层面的评估,不是像素层面的。
在状态预测的MSE上,从零训练是0.023,微调是0.041。从零训练也更好。但在视觉逼真度上,微调方案明显更好,毕竟它有视频大模型的生成能力。所以如果你的应用需要生成逼真的视频,微调方案更合适;如果你需要精确的动作理解和预测,从零训练是更好的选择。
8.3 泛化到新任务的迁移表现
我留了两个新任务做迁移测试,训练时完全没见过。从零训练的模型在新任务上zero-shot的动作预测精度是0.71,微调方案是0.38。从零训练的泛化能力明显更强,因为它学到的动作表征是任务无关的,而微调方案的表征里混杂了视频大模型见过的各种视觉模式,反而干扰了动作层面的泛化。
这个结果让我挺意外的,我原本以为微调方案因为见过更多数据,泛化会更好。实际恰恰相反,干净的动作表征比海量的视觉数据更重要。
9. 一些调参之外的经验和后续可以尝试的方向
9.1 数据质量比数据量重要得多
我一开始用了大概50万条轨迹,后来发现其中很多轨迹的动作标注有噪声,状态标注也不够精确。清洗之后只剩12万条高质量轨迹,但训练效果反而更好了。动作模型对数据质量极其敏感,一条错误标注的轨迹可能比十条正确轨迹的影响还大。建议在数据清洗上花至少30%的时间。
9.2 动作空间的归一化方式很关键
动作空间的归一化我试过三种:全局归一化、按维度归一化、按轨迹归一化。全局归一化最简单,但不同任务的动作幅度差异大,全局归一化会让小幅度任务的动作信息被压缩。按维度归一化好一些,但维度之间的相关性没考虑。最后我用的是按轨迹归一化,每条轨迹单独归一化到[-1,1],这样每个任务的动作幅度都被保留,模型学到的动作表征更均匀。
9.3 后续可以尝试的方向
一个方向是把GE-Act换成离散化的动作编码,用VQ-VAE做动作tokenization。离散动作表征可能更适合做长时程的规划,因为离散空间里的搜索比连续空间容易。另一个方向是引入层次化的动作表征,底层是原子动作,高层是动作序列,这样模型可以同时处理短时和长时的动作依赖。
还有一个我比较看好的方向是把IDM扩展成多步逆动力学,不只是从相邻状态反推动作,而是从多步状态序列反推动作序列。这样IDM的监督信号更强,能约束动作表征的长期一致性。我初步试了一下,训练不太稳定,但效果上限看起来很高,值得继续调。
整个从零训世界动作模型的过程走下来,最大的体会是:动作模型和视频模型是两种完全不同的东西,不能用训视频模型的思路来训动作模型。动作模型的核心是因果正确性,不是视觉逼真度。把这一点想清楚之后,很多设计选择就顺理成章了。GE-Act、CoAE、SVP、IDM这四个模块的分工和配合,本质上都是在从不同角度约束动作表征的因果一致性。如果你也在做类似的事情,建议先把损失函数的设计想清楚,再动手写代码,会省很多时间。