ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

从 Jev 的结构化判断到 UniIntervene:机器人强化学习如何判断“继续还是接管”

从 Jev 的结构化判断到 UniIntervene:机器人强化学习如何判断“继续还是接管”

0. 简介

UniIntervene 是南洋理工大学团队提出的真实机器人人类在环强化学习方法,目标是减少机器人训练过程中对人工接管的依赖。论文在 UR7e 机械臂的抓取、插入、擦拭和折叠任务上报告了 88% 的平均成功率与 14.6% 的人工干预率,相比 HiL-SERL 的 81% 和 34.3% 有明显改善。文章的核心不是让机器人永远不犯错,而是让系统识别“当前策略虽然还在运动,却持续没有进展”的状态,并从过去的纠正经验中找到高价值恢复目标。Jev 在本文只作为思想引子:它提醒我们把模型判断设计成能被程序直接消费的结构化接口;真正的机器人方法仍然是 UniIntervene 自己的价值估计、时序风险和恢复策略。两者没有 API、权重或训练数据上的直接连接,后文会用较短篇幅说明这个边界。

1. Jev 的结构化判断视角

1.1 从自由文本回答到可执行判别

本文借用 Jev 的核心视角:复杂输入经过模型处理后,应当输出清晰、稳定、能进入后续程序的判断。在 UniIntervene 中,这个判断具体对应动作后果、任务进展和是否触发恢复,技术重点仍是机器人价值模型与控制闭环,最终输出会参与阈值判断和动作切换,并写入后续训练数据。

1.2 Jev 与 UniIntervene 的边界

Jev 是通用的结构化判断思想,UniIntervene 把类似接口用于机器人动作后果、任务进展和恢复控制。这里的关键是,后文只展开 UniIntervene 如何用价值函数、TVR 和恢复记忆完成闭环,并说明这些模块怎样在离线数据和在线执行之间传递结果,避免把概念类比写成算法等同。

直觉理解:Jev 关注“模型能否给出稳定、结构化的判断”,UniIntervene 进一步回答“机器人在什么观测下应该接管,以及接管后要执行哪一段动作”。

2. HiL-RL 为什么需要自动判断

2.1 人类在环强化学习的基本闭环

人类在环强化学习把人类操作者放进在线交互回路。策略先根据相机图像、任务指令和自身历史生成动作,机械臂执行后获得新的观测和奖励;当策略进入危险、失败或明显无效的状态时,操作者通过 SpaceMouse 接管末端执行器,给出一段纠正动作,然后把控制权交还给策略。纠正 transition 会被放进回放缓冲区,后续通过模仿学习或离策略强化学习更新策略。这个办法比完全依赖随机探索安全得多,尤其适合接触丰富、奖励稀疏、失败代价高的真实操作任务,但它的瓶颈也很直接:人必须持续盯着机器人,等待一个“现在该不该接管”的时刻。

2.2 失败不是唯一需要干预的状态

很多真实任务并不会在失败发生的瞬间给出清晰信号。内存条可能已经卡在插槽边缘,机械臂还在微小摆动;毛巾可能被抓住但折叠方向已经偏离;白板擦在移动,却没有覆盖到目标区域。这些状态未必违反安全约束,也未必马上触发终止条件,却会让后续几十步都停留在低价值区域。只训练失败检测器会漏掉这种“可继续执行但没有进展”的情况,只使用瞬时价值又会误伤正常的退让、重抓和重新对齐。UniIntervene 将问题改写为:当前动作的预期后果是什么,最近一段价值变化是否持续低于合理进展速度,如果确实停滞,是否存在可以到达的高价值恢复目标。

3. UniIntervene 的整体流程

3.1 从观测到干预动作的接口

论文把干预模块写成一个内部决策接口。给定当前观测o t o_tot​、语言指令ℓ \ellℓ和策略提出的动作a t a_tat​,模块同时输出动作价值估计、干预分数以及一段恢复动作。部署时,当干预分数低于阈值,系统执行原策略动作;分数超过阈值,则从恢复记忆中检索目标,并调用目标条件恢复策略生成动作块。这个接口把“是否接管”和“接管后怎么做”连接起来,避免了只训练触发器却没有可执行恢复器的问题。

I ψ ( o t , ℓ , a t ) = ( q ^ t , s t i n t , A t r e c ) , a t e x e c = { a t , s t i n t < τ i n t a t r e c , s t i n t ≥ τ i n t \mathcal{I}_{\psi}(o_t,\ell,a_t)=\left(\hat q_t, s_t^{\mathrm{int}}, A_t^{\mathrm{rec}}\right),\qquad a_t^{\mathrm{exec}}=\begin{cases}a_t,&s_t^{\mathrm{int}}<\tau_{\mathrm{int}}\\a_t^{\mathrm{rec}},&s_t^{\mathrm{int}}\geq\tau_{\mathrm{int}}\end{cases}Iψ​(ot​,ℓ,at​)=(q^​t​,stint​,Atrec​),atexec​={at​,atrec​,​stint​<τint​stint​≥τint​​

3.2 离线训练流水线与在线边界

从这个角度看,训练阶段的每个文件并不是孤立脚本,而是下一阶段的输入契约。

公开仓库的run.py将训练拆成 NTTG、VF、Annotation、Mining、VQ1、Memory、VQ2 七个阶段。NTTG 给成功和失败轨迹增加进度标签,VF 训练代理价值函数,Annotation 把价值预测写回缓冲区,Mining 根据价值趋势挖掘干预点,VQ1 联合训练未来预测、双 Q 头和干预头,Memory 构建恢复目标库,VQ2 使用 FAST 解码器学习恢复动作。仓库明确说明它提供的是离线训练 pipeline,并不包含论文中完整的真实机器人在线控制接入,因此复现时应把论文实验数字和本地代码能运行的训练阶段分开陈述。

4. Proxy Value Function:先定义什么叫进展

4.1 NTTG 标签把稀疏成功变成密集信号

进一步看,代理价值的作用不是替环境凭空创造奖励,而是把成功轨迹中的时间顺序转成可比较的进展刻度。

真实机器人任务常常只在终点给一个成功或失败结果,直接用这个稀疏奖励训练干预判别器,模型很难知道中间哪一步已经朝正确方向移动。UniIntervene 的公开实现先为每条轨迹构造 normalized time-to-go 进度标签。成功轨迹的第t tt步标签是t / ( T − 1 ) t/(T-1)t/(T−1),从零逐渐增加到一;失败轨迹的归一化值保持为零,原始值使用-500作为明显的失败信号。这个标签不是环境真实奖励,而是一个用于学习“成功轨迹通常怎样变好”的代理监督。它让价值函数能够在终点奖励之外提供每一步的相对进展刻度。

deflabel_episode(transitions,fail_value=-500):"""为一条 episode 写入 raw_value 与 raw_norm。"""T=len(transitions)denom=max(T-1,1)success=is_success(transitions)ifsuccess:fort,trinenumerate(transitions):tr["raw_value"]=t-(T-1)tr["raw_norm"]=1.0ifT==1elsefloat(t/denom)else:fortrintransitions:tr["raw_value"]=fail_value tr["raw_norm"]=0.0returntransitions

这段代码来自research_impl/nttg_label_buffer.py,它展示了代理价值的第一层来源:成功轨迹被赋予单调进度,失败轨迹被压到零。工程上需要注意,is_success会优先读取 transition 中的成功或失败标志,找不到时才回退到末步奖励,因此数据采集协议比标签函数本身更重要。这个标签也不等于最终的 Q 值,后续 VF 阶段仍然会使用 Bellman 一致性、进度回归和保守正则共同训练价值函数。换句话说,NTTG 解决的是“每一步大致处在成功路径的哪里”,而不是直接替代强化学习的价值估计。

工程价值:如果成功标志、episode 边界或末步奖励在采集时写错,NTTG 会把错误的轨迹顺序固化成监督信号,后面的 VF、TVR 和恢复记忆都会继承这个偏差。因此复现时应先抽样检查成功与失败轨迹的标签曲线,再运行后续训练阶段。

4.2 双价值头与保守估计

代理价值函数的职责是为后续模型提供一个冻结的、相对稳定的进展参照。公开训练脚本中同时考虑 TD 损失、NTTG 标签损失、成功轨迹进度损失和保守正则,目的是减少离线数据分布之外的过估计。VQ1 阶段又使用 twin Q head,并取两个预测的最小值作为动作价值。双头结构并不能保证价值绝对校准,但它能降低单个回归头过度乐观时对触发器和记忆检索的连锁影响。因为同一个价值信号既决定“是否应该介入”,又决定“哪些状态值得作为恢复目标”,价值模型的偏差会同时影响触发时机和恢复方向。

q ^ t = min ⁡ ( q ^ 1 , t , q ^ 2 , t ) , L Q = ∑ k = 1 2 SmoothL1 ⁡ ( q ^ k , t , q t ⋆ ) \hat q_t=\min\left(\hat q_{1,t},\hat q_{2,t}\right),\qquad \mathcal{L}_{Q}=\sum_{k=1}^{2}\operatorname{SmoothL1}(\hat q_{k,t},q_t^{\star})q^​t​=min(q^​1,t​,q^​2,t​),LQ​=k=1∑2​SmoothL1(q^​k,t​,qt⋆​)

5. Future-conditioned Action-Value:判断动作后果

5.1 当前画面不足以解释下一步

换句话说,模型要判断的不是“这一帧像不像成功”,而是“执行这个动作后,未来状态是否更接近成功”。

一张图像只能说明机械臂现在在哪里,不能直接说明候选动作会把系统带向哪里。对插入、接触和柔性物体任务而言,向下压、向后退和横向修正可能在当前帧看起来相似,但几步之后的结果完全不同。UniIntervene 因此把观测、指令和候选动作送入视觉语言骨干,在<VQ_QUERY>位置取出隐藏状态h t h_tht​,由未来头预测动作执行后的潜在视觉状态z ^ t + 1 \hat z_{t+1}z^t+1​,再将这个潜在状态送入双 Q 头估计价值。训练时,冻结的 V-JEPA2 视觉编码器提供真实下一帧的潜在目标,使未来头学习动作与后果之间的关系。

5.2 代码中的 FutureHead 与 TwinQHead

classFutureHead(nn.Module):"""h_t -> z_future_pred。"""def__init__(self,hidden_size,latent_dim,mode="pooled",n_tokens=0):super().__init__()self.mode=mode self.n_tokens=int(n_tokens)ifmode=="dense"else0out_dim=latent_dimifmode=="pooled"elselatent_dim*self.n_tokens self.proj=nn.Sequential(nn.Linear(hidden_size,4*hidden_size),nn.GELU(),nn.Linear(4*hidden_size,out_dim))defforward(self,h_t):z=self.proj(h_t)returnzifself.mode=="pooled"elsez.view(z.size(0),self.n_tokens,-1)classTwinQHead(nn.Module):def__init__(self,in_dim,accepts_dense=False):super().__init__()self.q1=nn.Sequential(nn.Linear(in_dim,in_dim),nn.GELU(),nn.Linear(in_dim,1))self.q2=nn.Sequential(nn.Linear(in_dim,in_dim),nn.GELU(),nn.Linear(in_dim,1))defforward(self,feat):returnself.q1(feat).squeeze(-1),self.q2(feat).squeeze(-1)

这段实现来自research_impl/vq1_heads.py的核心结构,完整版本还支持 dense latent 的注意力池化和干预头对 Q 值的条件输入。这里的分工非常清楚:FutureHead负责把语言视觉隐藏状态变成动作后果表征,TwinQHead负责把表征变成两个价值标量。未来预测的损失通常使用潜在空间距离,价值损失则对齐代理价值。这样做的好处是,价值头不必从一张静态图像直接猜成功概率,而是先利用动作条件的未来表示获得更稳定的进展证据。代价是训练需要下一帧图像、冻结的 V-JEPA2 编码器和更高的显存开销。

6. Temporal Value-Risk:区分波动和真正停滞

6.1 单步低价值为何会误触发

这里要区分:低价值本身不是错误,低价值持续不变才是需要解释的信号。

机器人在正常完成任务时也会短暂进入低价值状态。插入动作可能先退开再对齐,抓取柔性物体时可能松手重抓,擦拭任务则可能为了保持接触而沿边缘移动。若系统看到一次价值下降就接管,恢复策略会打断本来有机会成功的动作序列。UniIntervene 使用长度为八的历史窗口,把最近的价值增量放在一起观察,只有当实际增量持续低于期望进展速率时,风险才会累积。风险还乘以1 − V t 1-V_t1−Vt​,任务越接近完成,剩余进展越少,短暂波动越不应触发强制恢复。

6.2 TVR 公式与公开实现

R t = ( 1 − V t ) ∑ i = 0 K − 1 γ r i ( ϵ − Δ V t − i ) , Δ V i = V i − V i − 1 R_t=(1-V_t)\sum_{i=0}^{K-1}\gamma_r^i\left(\epsilon-\Delta V_{t-i}\right),\qquad \Delta V_i=V_i-V_{i-1}Rt​=(1−Vt​)i=0∑K−1​γri​(ϵ−ΔVt−i​),ΔVi​=Vi​−Vi−1​

在公开配置中,K = 8 K=8K=8、ϵ = 0.005 \epsilon=0.005ϵ=0.005、γ r = 0.9 \gamma_r=0.9γr​=0.9,干预阈值为0.5 0.50.5。风险头接收未来潜变量和价值历史编码,训练目标是上式计算出的连续 TVR;同时,Mining 阶段用下降、平台和骤降三类规则生成离线干预标签,VQ1 可使用 focal loss 处理干预点远少于普通点的类别不平衡。这里的设计把“风险估计”和“触发分类”放在同一条价值趋势上,但它们不完全等价:连续 TVR 告诉模型停滞程度,离散标签则告诉模型哪些时刻应当被标记为接管点。

def_compute_tvr_target(values_hist,gamma,epsilon):"""TVR_t = (1 - V_t) * sum gamma^i * (epsilon - delta_i)"""K=len(values_hist)-1V_t=float(values_hist[-1])total=0.0foriinrange(K):delta_i=float(values_hist[K-i])-float(values_hist[K-i-1])total+=(gamma**i)*(epsilon-delta_i)returnfloat((1.0-V_t)*total)

这段函数来自research_impl/hil_vlm_train.py。它按照从近到远的顺序累计短缺量,因此最新一步的短缺权重最高。实现中没有对风险结果强制截断,具体阈值和正负样本处理由配置与训练头决定;这意味着复现时不能只抄公式,还要同时读取history_window、epsilon、gamma_r、threshold和损失类型。一个实际的工程风险是代理价值尺度发生漂移后,1 − V t 1-V_t1−Vt​与ϵ \epsilonϵ的意义会变化,所以 VF 训练、Annotation 和 VQ1 训练之间必须保存来源信息,不能把不同版本的价值预测混在同一个缓冲区里。

难点提示:TVR 不是“价值低就接管”,而是“价值增长长期不够快才接管”。这一区分决定了模型会不会把正常的重新对齐误判成失败。

直觉理解:可以把价值曲线看成机器人走向目标的速度计。一次减速可能是转弯,连续八步几乎没有前进才更像被障碍物卡住;窗口和折扣项共同决定系统要等多久、又要多快响应。

7. Recovery Memory:接管以后恢复到哪里

7.1 从失败状态配对高价值目标

进一步看,恢复记忆的关键不是保存更多帧,而是保存已经被价值函数验证过的状态转移。

触发器只能回答“当前探索没有产生足够进展”,却不能回答“机器人应该回到哪个状态”。UniIntervene 从已标注轨迹中挖掘恢复片段:起点是潜在干预状态,终点必须比起点高出至少一个价值增量,并且终点价值达到最低阈值。公开的fold_towel配置使用固定跨度 32、价值提升阈值 0.4、目标价值下限 0.75、20 个进度区间和最多 240 个目标条目。对更短或更稳定的任务,可以使用不同跨度和采样配额。这样形成的记忆库不是任意历史帧,而是经过价值筛选的“从低进展区域走向高进展区域”的经验片段。

7.2 资格筛选和余弦检索

defsegment_is_eligible(start_vf,end_vf,delta_threshold,target_vf_threshold):return(float(end_vf)-float(start_vf)>=float(delta_threshold)andfloat(end_vf)>=float(target_vf_threshold))# MemoryBank.retrieve 内部对已归一化 key 做矩阵乘法scores=torch.matmul(key_subset,query.to(self.device))k=min(topk,key_subset.size(0))top_scores,local_indices=torch.topk(scores,k=k,dim=0)

第一段资格判断来自research_impl/memory_constraints.py,第二段检索逻辑来自research_impl/memory/memory_bank.py。检索前可以按任务过滤、排除当前 episode,并要求候选恢复步数达到最小值,这些约束用于减少跨任务混淆和训练数据泄漏。余弦相似度本身只说明当前失败上下文与历史起点相似,不能保证目标一定可达,所以记忆构建还需要固定跨度、进度分桶和每 episode 上限来控制目标质量。换句话说,记忆库解决的是“恢复到哪里”的选择问题,不能单独替代恢复策略的控制能力。

工程价值:记忆库的质量由“目标确实更有价值”和“目标仍然可达”两件事共同决定。只按相似度保存样本会得到看起来相近却无法执行的目标,因此必须同时保留价值提升阈值、任务过滤、episode 排除和进度分桶等约束。

8. FAST Recovery Policy:恢复动作如何生成

8.1 目标条件策略的输入与输出

直观理解是,记忆库只提供方向,控制器仍需根据当前姿态重新计算路径。

检索到目标状态后,恢复策略接收当前观测、任务指令和目标观测或状态,重新生成一段动作,而不是把历史轨迹原样回放。公开配置中的恢复 horizon 为 8,动作维度为 7,包含末端执行器运动和夹爪控制。FAST 把连续动作转换成频域压缩、量化和 BPE token,解码器逐 token 预测动作块。这样做与视觉语言动作模型的序列建模接口相容,也让恢复动作可以使用交叉熵训练。目标条件的作用是把“遇到失败后怎么办”约束成一个具体的到达问题,策略仍然需要根据当前姿态和物体位置做闭环修正。

8.2 逐 token 交叉熵与动作块

…详情请参照古月居

RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进