一年前,我用 RL 造了一批非自回归决策模型

📅 发布时间:2026/10/3 21:56:16
一年前,我用 RL 造了一批非自回归决策模型
我是AI时代的无业游民我游荡在现实与意念之间一年前我用 RL 造了一批非自回归决策模型背景与痛点一年前我在做一个实时竞价场景的决策系统。核心需求是在 20ms 内对每一次请求给出一个多维动作——出价、预算分配、投放时段选择。最初团队用的是自回归autoregressive序列生成把动作拆成 token 序列逐个解码。听起来很优雅但上线后问题暴露得很彻底。第一个问题是延迟不可控。自回归解码的步数与动作维度成正比当动作空间扩展到 12 维时P99 延迟直接冲到 80ms远超预算。第二个问题是误差累积前一个 token 的微小偏差会作为条件输入传给下一步导致最终动作分布漂移。第三个问题更隐蔽——在 RL 训练中自回归策略的 log-prob 计算需要对每个 token 做条件概率分解这让优势函数的估计方差显著变大训练极不稳定。我们试过几种缓解手段动作维度降维、用 KV Cache 加速、对 token 做 beam search 剪枝。但这些都是工程补丁没有触及根本矛盾——自回归的串行依赖与决策任务需要的并行、低延迟、全局一致性本质上是冲突的。不解决这个矛盾代价就是每次大促前都要重新调参线上延迟抖动无法根治。方案设计我决定换一条路非自回归决策模型。核心思路是——动作的各个维度之间不存在因果依赖它们应该被并行预测而不是串行生成。选型时我对比了三条路线方案核心机制优势致命缺陷自回归 RL逐 token 解码条件概率分解表达能力强可建模复杂依赖延迟高、误差累积、训练方差大扩散策略从噪声逐步去噪生成动作多模态分布拟合好推理步数多实时性差非自回归 RL单次前向并行输出全部动作维度延迟恒定、训练稳定需解决维度间一致性问题我明确放弃了扩散策略因为去噪步数在实时场景下无法压到 20ms 以内。也放弃了继续优化自回归因为那是逆着任务本质做工程。最终选择非自回归 RL但必须解决一个关键问题并行输出的各维度之间如何保持全局一致性我的答案是引入一个共享的隐状态编码器让所有动作维度从同一个隐表示中解耦预测再通过一个轻量的 consistency head 做维度间约束。这相当于把串行依赖换成了并行约束。核心实现共享隐状态编码器关键决策是编码器不直接输出动作而是输出一个隐状态zzz所有动作头共享zzz。classSharedEncoder(nn.Module):def__init__(self,state_dim,hidden_dim,n_actions):super().__init__()self.backbonenn.Sequential(nn.Linear(state_dim,hidden_dim),nn.LayerNorm(hidden_dim),nn.GELU(),nn.Linear(hidden_dim,hidden_dim),)# 每个动作维度一个独立头但共享 backboneself.action_headsnn.ModuleList([nn.Linear(hidden_dim,1)for_inrange(n_actions)])self.consistencynn.Linear(hidden_dim,n_actions*n_actions)defforward(self,state):zself.backbone(state)actionstorch.cat([head(z)forheadinself.action_heads],dim-1)returnactions,z为什么不直接用一个大 Linear 输出所有维度因为独立头 共享 backbone 的结构在 RL 中更容易做 per-dimension 的 advantage 归一化且梯度不会在维度间互相干扰。一致性约束与 RL 目标非自回归最大的风险是各维度各说各话。我加了一个 consistency loss惩罚维度间的矛盾组合defconsistency_loss(actions,z,consistency_layer):# 预测维度间关系矩阵relationconsistency_layer(z).view(-1,n_actions,n_actions)# 动作间的实际外积outeractions.unsqueeze(-1)*actions.unsqueeze(-2)returnF.mse_loss(relation,outer.detach())RL 目标用的是 PPO但把 log-prob 改为各维度独立 log-prob 之和defppo_loss(actions,old_log_probs,advantages,clip_ratio0.2):# 各维度独立高斯策略log_prob 直接相加new_log_probsgaussian_log_prob(actions,mu,sigma).sum(dim-1)ratio(new_log_probs-old_log_probs).exp()surr1ratio*advantages surr2ratio.clamp(1-clip_ratio,1clip_ratio)*advantagesreturn-torch.min(surr1,surr2).mean()这里有个坑各维度 log-prob 相加隐含了独立性假设。如果动作维度间强相关这个假设会引入偏差。我的处理是让 consistency loss 显式建模相关性从而在策略层面补偿独立性假设的损失。训练稳定性处理非自回归 RL 最容易炸的地方是 advantage 估计。我的做法是对每个动作维度单独做 running mean/std 归一化而不是全局归一化。这样避免了某个维度方差过大主导整个梯度。效果验证在离线回放数据集约 200 万条真实竞价记录上做了对比指标自回归 PPO非自回归 PPOP50 延迟32ms6msP99 延迟81ms9ms训练收敛步数120k45k策略熵收敛后0.310.58离线收益提升baseline7.2%延迟的改善是结构性的——非自回归单次前向延迟与动作维度无关。训练收敛更快因为 log-prob 计算不再有串行依赖方差更小。策略熵更高说明探索更充分没有过早坍缩。可复现步骤用相同的数据集和 reward 函数分别跑两个策略固定随机种子记录每 1k 步的延迟和收益。关键是要在相同硬件上测延迟且 batch size 一致。边界与演进非自回归决策模型不是万能的。它的适用边界很明确适用动作维度间弱相关或可通过显式约束建模、延迟敏感、需要并行决策的场景。比如实时竞价、推荐排序中的多目标打分、机器人低层控制。不适用动作维度间存在强因果依赖比如自然语言生成、路径规划中的序列决策此时自回归的串行依赖是必要的强行非自回归会损失表达能力。下一步优化方向有两个一是把 consistency head 换成更结构化的图神经网络显式建模维度间的依赖图二是在训练中引入课程学习先学弱相关维度再逐步加入强相关维度。另外当前的一致性约束是静态的未来可以做成动态的——根据状态自适应调整约束强度。回头看这个方案的核心判断是不要用自回归去解一个本质上是并行决策的问题。这个判断一年前成立现在依然成立。