要说当下最没争议的一件事,就是几乎所有主流大模型都在做同一件事:预测下一个 Token。给定一段文本,按条件概率把下一个符号补出来,再一代一代往后接,接出段落、接出对话、接出代码。这个训练目标支撑了过去几年 AI 的大部分进步,但最近我在折腾一些和控制、规划相关的模拟项目时,越来越觉得它只是“在文本流里做延续”,天然缺了点什么。当我们真的想让模型去解决游戏策略、机械臂抓取、交通调度这类任务时,模型需要预测的不是下一句话,而是下一个状态——环境的、系统的、可交互世界里的下一个状态。这个命题如果成立,整个建模语言就得换一套。
这篇文章不打算站队说“next token 已经过时”或者“状态预测一定取代自回归”,那都是营销话术。我想认真拆一下:从“预测下一个 Token”到“预测下一个状态”,到底要改变什么、瓶颈在哪里、能不能落地。这篇文章适合对大模型技术路线感兴趣的研究者,也适合正在做具身智能、机器人控制、数字孪生这类偏“物理世界交互”方向的人。如果你只是做聊天机器人和文档助手,那可能感受不到这个问题的尖锐程度;但只要你的模型需要面对一个动态环境,迟早会遇到我今天要聊的这些坎。
1. 范式转移:从“下一句话”到“下一秒”
1.1 next token 范式到底在优化什么
自回归语言模型的核心公式很简单:最大化 P(x_t | x_1, x_2, ..., x_{t-1})。给定前面一串符号,预测下一个符号。为了训练这个目标,模型把文本分割成 token,用 softmax 输出一个覆盖整个词表的概率分布,然后最小化交叉熵。
这套机制把注意力、Transformer、扩散这些近年的大杀器全串起来了,也正因为它足够通用,一个统一的 token 接口可以同时覆盖文本、代码、图像 patch 甚至音频片段。你只要把数据压成离散符号,模型就能在上面做条件概率拟合。这个思路本质上是把“所有知识”编码成符号序列上的统计规律,靠语言这个大压缩信道来完成表征。对人类来说,这是一个极其高效的交互接口,毕竟我们说话、写文、看代码,本质上就是在这个离散符号空间里操作的。
但问题出在“对人类高效”这个前提上。语言建模优化的是“符号序列延续”,不是“物理世界演化”。文本中的因果关系被压缩进了词与词之间的条件概率,模型并不需要真正理解动量、遮挡、障碍、摩擦这些物理概念,它只需要在词汇统计层面输出一个合理答案。像一个读了大量棋谱但从未碰过棋子的人,你可以和他谈棋理,但他不是棋手。
1.2 预测 Token 时模型的真实局限
第一点,误差累积逃不掉。训练时模型看的是真实的前缀,推理时前缀里一半内容是模型自己生成的。一旦某个中间 token 抽歪了,后面全跟着漂。文本任务里这个问题还能扛一下,因为语言有冗余、有语法约束,错一个词常常能被上下文兜住。但对于连续状态,错一个分量,哪怕只错 0.1,后边 rollout 到几十步就可能完全分叉。
第二点,文本序列和目标动态之间存在接口错位。语言是离散的、高密度的,状态是连续的、有物理含义的。拿语言模型去预测速度、角度、受力这种量,等于让一个靠文字理解世界的人去估算一辆车两秒后侧滑的精确角度。也许他能从语料里背出一句“雨天路滑应减速”,但给不出能直接用于控制系统的预测结果。
第三点,缺少闭环反馈。语言模型处理的大多是单程任务:输入一段,输出一段。但控制、决策类的任务充满闭环:行动改变环境,环境产生新观测,新观测再决定下一步行动。预测下一个 Token 的模型没有内生回路,所以它天然不适合作为决策系统的主干,只能做外围的“知识问答”模块。
第四点,目标函数过于自信。交叉熵在一个高维离散空间上给了每个 token 一个概率,但模型其实并不知道自己不知道什么。它可能对某个没有任何依据的下一个状态给出几乎唯一的分布,这种过拟合式自信在物理交互中极危险。
做一个生活化类比:预测下一个 Token 像拿到剧本读下一句台词,台词接得再漂亮,演员也不会因此知道该怎么走位躲开忽然砸下来的木箱。预测下一个状态,像是在开车时必须估算两秒后自己车头的位置。前者锻炼表达,后者锻炼手感。
1.3 预测下一个状态的确切含义
把目标从 P(x_t | x_<t) 换成 P(s_{t+1} | s_t, a_t),这看起来只是下标变了,背后是整套建模哲学的转变。这里的 s_t 是某个动态系统的状态,可以是一组物理量,比如位置、速度、角度,也可以是一段视频经过编码后的隐向量;a_t 是系统施加的动作或控制输入,也可能不存在,比如纯环境演化预测。
这个目标本质上就是在学习一个“世界模型”:给定当前的局面和动作,推演出下一时刻的局面。强化学习社区很早就沿着这条路走过,出现了大量基于隐状态空间模型的规划算法,很多机器人论文里漂亮的产物都来自这种“想象未来”的能力。大模型的上下文学习能力如果和这个目标结合起来,会得到一个新的东西——它不是聊天机器人,更接近一个“可对话的物理推演器”。
需要澄清的是,这并不意味着要扔掉语言建模。语言仍然是极好的先验知识来源和人类交互接口。问题是,我们是否应该让语言建模成为唯一的训练目标,还是应该让“下一状态预测”作为并联目标进入主干模型。我的倾向是后者。
2. 目标函数重构:状态预测需要哪些关键能力
2.1 状态表征:显式状态还是隐式潜空间
要做“预测下一个状态”,第一步不是设计模型结构,而是确定状态长什么样。显式状态最好理解:物体的坐标、速度、朝向、温度、压力……只要这个系统能被一组数值描述,预测就退化为数值回归任务。这类状态的优点是干干净净,验证方便;缺点是真实世界几乎没有这么容易拿到的状态,传感器永远有噪声,而且很多关键量是观测不到的。
隐式潜状态则更通用。拿视频来说,画面里没有直接给出“木箱的动量”,但神经网络可以通过编码器把连续帧压缩成一组潜向量,潜向量里可能隐含着位置、形状、运动趋势等信息。模型在这个潜空间里做转移预测,再通过解码器把预测结果还原成画面或动作。
两条路并不互斥,实际项目里更推荐混合方案:显式可量化的物理量直接进输入向量,难观测的部分用潜变量补齐。例如机械臂抓取任务,我可以同时输入关节角度和末端位姿,再把图像经过一个小型视觉编码器提取的隐向量拼在一起,让预测模型自己决定依赖哪些特征。
选型建议是:如果任务有清晰的动力学方程,直接用显式状态,别装模作样上高维潜空间;如果任务以视觉输入为主且状态难以定义,老老实实训练状态编码器。编码器质量决定预测上限,状态表征如果乱七八糟,后面的转移模型再强也是白搭。
2.2 转移模型:从单点回归到分布预测
最朴素的状态预测实现是 L2 回归:输入当前状态和动作,输出预测的下一个状态,然后算均方误差。这个方案在玩具任务里能跑通,但很快会暴露一个致命问题——模型只学会了输出期望值,把所有不确定性全部压平了。
真实动态系统几乎都有随机性:传感器噪声、环境扰动、多模态的后续演化可能。一个移动的球可能正常滚动也可能撞上障碍物弹开;一辆车前面的行人可能直走也可能转向。当面对这种多模态未来时,均值不是好的预测,分布才是。
几个落地方式供参考:
- 混合密度网络(MDN):输出多个高斯成分的均值、方差和权重,让模型用“几坨分布”描述未来可能的状态。
- 扩散头:在潜变量空间用扩散模型做逆向采样,适合连续、高维状态,代价是推理慢。
- 离散化预测:把连续状态空间分成若干 bin,用分类目标预测下一个 bin 的分布。简单、稳定,但精度兑现全看 bin 的选取。
- 负对数似然回归:输出高斯分布的均值和方差,用 NLL 计算 loss。这个方案实现成本低,而且天然的方差估计能缓解幻觉问题。
我的经验是:先用负对数似然回归起步,如果任务中的多模态性非常明显,例如需要预测人类转弯或者车辆变道,再升级到混合密度头。别一开始上扩散头,调参成本会淹没项目本身。
2.3 与语言建模共存:不要把状态预测做成“抛弃 Token”
有一种极端做法是彻底抛弃文本 token,所有输入输出都换成状态向量。这种方案在固定仿真环境里也许可行,一旦面对开放世界马上崩。语言是模型珍贵的先验知识来源,大量物理直觉和社会常识都藏在语料里,全扔掉太可惜。
更好的做法是多任务联合训练。主干模型接受状态序列输入,也接受文本输入;语言任务继续训练模型的推理、常识、指令跟随能力,状态预测任务则专门负责“世界动态推演”。两个目标共享大部分参数,只在输出头上分叉。推理时,模型既能回答“物体在无外力作用下会做什么”,也能通过状态预测头直接给出下一帧的潜向量。
我在实际测试中发现一个微妙的收益:语言任务带来的语义对齐,竟然能显著改善状态预测在少样本场景里的泛化。原因很好懂,文本里的“抛出去的物体会沿抛物线运动”先验,虽然没有精确到坐标,但提供了一个极强的结构先验。模型不需要从零开始猜状态转移函数,它只需要在已有的常识骨架上做参数化拟合。这比纯状态数据训练收敛快得多。
3. 从想法到实验:一条可以落地的状态预测路径
3.1 先拿一个低维仿真环境练手
不要一上来就上视觉仿真和机械臂,调试成本会吃掉你所有时间。第一步是找一个状态维度在 5 到 20 之间的低维控制环境。倒立摆、双连杆机械臂、小车爬坡、简单的目标导航这类任务就够用了,它们的状态由角度、角速度或位置速度构成,动作维度也低,可以快速验证“状态预测模型到底能不能学出正确的动力学”。
选型时注意三点:
- 状态必须是直接可观测的,不要带复杂遮挡和部分可观测问题;
- 动力学要有一定非线性,纯线性系统体现不出预测模型和基线方法的区别;
- 仿真器要支持随机重置和动作采样,方便生成分布覆盖较全的训练集。
用随机策略加一小部分脚本策略混合采样,先生成几十万条轨迹。每一条轨迹是一串状态转移对:(s_t, a_t, s_{t+1}),模型的任务就是看完前面的状态序列和动作,预测下一时刻状态。
3.2 训练配置与 loss 设计
网络结构不需要太重。我用的实验配置是一个三到四层的 Transformer,输入是最近 4 到 8 步的状态窗口和对应动作,经过一层 embedding 后进入 Transformer,输出状态头给下一状态的均值和 log_std,loss 用高斯 NLL。
伪代码大致是:
import torch import torch.nn as nn class StatePredictor(nn.Module): def __init__(self, state_dim, action_dim, hidden_dim=256): super().__init__() self.state_embed = nn.Linear(state_dim, hidden_dim) self.action_embed = nn.Linear(action_dim, hidden_dim) self.transformer = nn.TransformerEncoder( nn.TransformerEncoderLayer(hidden_dim, nhead=4, batch_first=True), num_layers=3 ) self.mean_head = nn.Linear(hidden_dim, state_dim) self.logstd_head = nn.Linear(hidden_dim, state_dim) def forward(self, states, actions, action_mask=None): # states: (B, T, state_dim), actions: (B, T, action_dim) B, T, _ = states.shape state_tokens = self.state_embed(states) action_tokens = self.action_embed(actions) # 在序列维度上拼接,让模型同时感知状态和动作 tokens = state_tokens + action_tokens context = self.transformer(tokens) last_hidden = context[:, -1, :] mean = self.mean_head(last_hidden) logstd = torch.clamp(self.logstd_head(last_hidden), -3, 1) return mean, logstd def gaussian_nll_loss(mean, logstd, target): variance = torch.exp(2 * logstd) return ((target - mean) ** 2 / variance + 2 * logstd).mean()训练注意点:
- 状态要先做归一化,每个维度用均值方差标准化,否则角度、速度、位置共存的量纲差异会让收敛变得极慢。
- 动作也需要归一化到标准区间,不要用原始值。
- 学习率用 3e-4 加 cosine schedule,配合 AdamW。
- 训练 2 到 3 个 epoch 后看单步验证误差曲线,如果验证误差不降,先检查归一化和数据采样分布是否太窄。
3.3 从单步到多步:必须让模型在自身输出上展开
单步预测很快会过拟合到“看真值预测真值”的舒适圈。推理时模型要接上自己上一时刻的输出继续往后推,这中间有巨大的分布偏移。解决这个问题,最土也最有效的办法是在训练中做多步展开:把模型上一时刻的预测当作下一时刻的输入,连续展开 4 到 8 步,每一步都计算 loss,并且在后几步的输入上加少量噪声。
多步展开相当于把常见的 teacher forcing 改成了 scheduled sampling 的思路。初期用 80% 的真实状态做输入,逐渐提高到 50% 比例使用模型自己的预测输出,当模型开始在自身上跑稳时,单步误差一般不会再下降,但 rollout 误差曲线会变得明显更稳定。这也是你第一次真正感受到“状态预测和文本生成不是一回事”的时刻:文本错一两个词可以跳过,状态错一点就会越滚越偏,像雪崩。
除了加噪声,还可以在训练时随机截短状态窗口长度,让模型适应不同感知深度,避免它对固定窗口长度产生依赖。
3.4 闭环评测:只看单步误差等于自欺欺人
我见过不少团队在报告里写“单步预测误差 0.01,模型表现完美”,但实际把预测结果接入一个开环 rollout,跑 100 步以后误差已经大到完全没意义。所以状态预测项目的评估务必要分成三层:
- 单步预测误差,只作为训练监控指标;
- 多步 rollout 误差曲线,看模型在自身输出上的稳定性,通常是前 10 步误差较小,后 50 步快速发散,这是正常的,重点看发散的早晚和斜率;
- 下游任务指标,例如控制成功率、到达目标点的概率、碰撞率。只有这一层指标能代表真实价值。
我在实验里习惯画一条“rollout error vs horizon”的曲线,横轴是预测步数,纵轴是状态 MSE。如果模型预测 5 步内误差就已经超过某个阈值,说明多步展开训练做得还不够;如果滞后较长才发散,说明训练目的基本达到。
4. 我踩过的坑:状态预测常见问题与排查
4.1 均值回归:模型学会了“什么都不做”
预测未来分布时,模型最容易犯的错就是输出均值。因为均值的负对数似然损失比尝试预测多模态分布更稳健,明明一条轨迹的下一步可能是左拐或右拐,模型却输出一个“直行”。从期望误差上看,直行的确是最不容易错的答案,但它毫无价值。
一次我在单摆环境里做实验,模型 rollout 结果非常平滑,单步误差低得惊人,但展开一段时间后振幅渐趋为零,完全违背物理规律。排查半天才发现是损失里 log_std 被学成了一个特别大的值,模型在用“高不确定性”掩盖“低质量预测”。这还算好,更麻烦的是混合密度头出现模式坍缩,几个高斯成分跑到同一个位置。
解决方向两条:一条是结构性的,用扩散模型或 GAN 头强制输出多样本;另一条是训练性的,在损失函数里加入多样性奖励项,比如让混合密度头的各个成分保持足够的分布距离。我个人更推荐先从前者的最简单版本入手,因为调奖励项实在费时费力。
4.2 误差累积与模型自我幻觉
这几乎就是状态预测版的“幻觉”问题。模型在训练时没有见过自己犯过的错,推理时却必须持续面对自己的输出,于是它会沿着一个错误状态一路推演,越推越自信。这个现象在文本生成里表现为胡编乱造,在状态预测里表现为完全偏离真实物理轨迹,但模型给出的方差还很小。
应对方法前面提到的多步展开已经能缓解一大半。另一个有效的动作是输入下一个状态时人为注入一个“与误差相似量级”的噪声。这相当于对模型做对抗训练,让它从小学会容忍自身的预测噪声。还有一个小技巧:增加训练轨迹的高频部分占比,比如多采集一些状态突变明显的轨迹,让模型见惯了“大误差”,就不容易在推理时被自身错误带崩。
4.3 状态编码与动作对齐的坑
状态向量里的时间步和动作往往存在对齐延迟。仿真器里一个控制周期内,动作可能是在状态 s_t 之后执行的,但数据记录时经常存在一帧偏差。这个问题在低维环境不明显,一旦换成视觉输入和控制指令混合,就会成为静默杀手:模型以为自己在预测下一状态,实际拟合的是“昨天的状态和今天的动作之间的错位关系”,训练出来完全没有因果。
排查技巧是用互相关函数检查动作和状态变化之间的时间滞后,如果峰值不在 0 位置,就要做时间对齐再训练。这个排查往往会出现一个有趣结果:模型学会了“晚一个时间步照抄当前状态”,单步指标好看,rollout 完全失效。
4.4 评估分布过窄
单一策略采集的轨迹会让模型过拟合到那个策略的行为空间。换一个策略去 rollout,预测误差可能瞬间爆炸。排查方法是训练完成后,用完全不同分布的测试轨迹做一次泛化测试,比如训练时用慢速随机走,测试时用高速直线加急转弯,如果误差爆表,说明模型没有学到“动态规律”,只记住了训练分布。
更进一步可以用“预测误差归因”:分别查看位置、速度等各维度的误差贡献,判断模型是没学会耦合关系,还是只是某些维度的量纲没归一好。
4.5 状态预测常见问题速查表
| 常见症状 | 可能原因 | 排查方向 | 快速解法 |
|---|---|---|---|
| 单步误差极低,rollout 快速发散 | 训练只做单步,模型依赖真值前缀 | 看多步展开后的误差曲线 | 混合真实状态和预测状态作为输入,多步展开训练 |
| 预测结果总是趋于中间值 | 均方误差或 NLL 把分布压平 | 观察 rollouts 是否方差过大 | 换混合密度头或扩散头,强制输出多维候选 |
| 换策略后预测误差暴涨 | 训练轨迹分布太窄 | 对比训练集与测试集动作分布 | 联合采样多种策略,扩大数据覆盖度 |
| 模型在特定维度上波动异常 | 量纲不匹配或噪声比例大 | 对每个维度单独算误差分析 | 分维度归一化,对高噪声维度加权重衰减 |
| 训练 loss 下不去 | 状态动作时间对齐有问题 | 检查状态变化与动作的时滞 | 平移数据对齐,或用可微时间偏移模块 |
这些坑每一个我都不是只踩过一次。现在每开一个新实验,第一件事不是搭一个炫酷的模型,而是花半天时间把数据采样、对齐、归一化这类脏活做扎实。状态预测的容错率比文本生成低太多,数据上的一点点脏都会在 rollout 阶段被放大成一个灾难性的误差。
5. 哪些方向会最先吃到“下一状态预测”的红利
5.1 具身智能与机器人控制
机器人领域最需要状态预测,也最容易被状态预测改变。传统控制方法像 MPC 依赖精确的物理模型或动力学辨识,一旦环境变化超出建模范围,整条控制链就崩。而一个基于数据学习的状态预测模型,天然可以从视觉输入、力矩反馈、关节角度中学出环境动态,不需要手写方程。
实际项目里,可以先用状态预测模型做“想象搜索”:在预测出的多个未来轨迹里,根据目标函数选一条最有利的轨迹执行。这种方法不需要任务特定的奖励函数,只要状态预测模型足够准,规划出来的动作就会自然避开障碍、趋向目标。我见过一组对比实验:同样的机械臂抓取任务,用直接策略学习的方法在 5000 步训练后成功率还在 60% 徘徊,而换成状态预测加规划的三百步内就超过了这个水平。原因很简单,预测模型面对不同目标时不需要重训,它是一个环境通用模块。
5.2 自动驾驶、工业控制与科学模拟
自动驾驶里的状态预测已经在落地,只不过大多数系统还把它限制在感知模块内,比如预测周围车辆的未来位置。但状态预测的视野应该更宽:车本身、路面摩擦、交通参与者、甚至乘客意图,全都可以纳入一个统一状态空间,然后让模型对整个驾驶场景做未来推演。相比现在“感知一条线、预测一条线、控制一条线”的分立架构,统一状态预测模型能大幅度降低模块间误差传递。
工业控制里,状态预测模型可以作为数字孪生的核心引擎。复杂的化工反应、电力调度、机器人产线,物理机理不完全可建模,但状态数据多得惊人。用状态预测模型替代传统仿真器的近似环节,可以让控制策略的搜索在虚拟系统里先跑几千遍,再在真实系统上执行。
科学模拟也一样。分子动力学、流体仿真这些计算成本极高的任务,中间大量步骤可以用神经网络状态预测器加速,只在关键节点调用原始物理求解器校准。这类应用对预测精度要求极高,因为科学模拟不允许“大概齐”,但它能节省的时间远超想象。
风险也要讲清楚:状态预测模型是数据驱动的近似器,在分布外场景下一定会有幻觉,错误预测用在安全攸关系统里可能造成严重后果。所以真实场景部署必须搭配异常检测和安全边界机制,把模型输出的“自信度”当作一把双刃剑。
我个人最近在一个模拟器里搭了非常小的状态预测实验,状态十维、动作五维,模型是三层的 Transformer。单步 NLL 很快收敛到很低,但 rollout 到五十步之后已经完全偏离真实轨迹。这个结果让我对“大模型接管世界模型”的乐观预期冷静了很多。状态预测的真正难点不在模型容量,而在训练目标、数据分布和评估方式。反过来想,正因为这些难点还没有被彻底解决,一旦有人在某个场景里把它打通,哪怕只是固定领域,收益会比文本预测大得多。我接下来计划把语言任务拉回来做多目标联合训练,让模型既理解“常识里物体怎么动”,又能精确推演“这个环境里物体怎么动”。如果真的跑通了,再回来写一篇完整的技术拆解。