• 正文
  • 相关推荐
申请入驻 产业图谱

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

11/05 09:44
89
加入交流群
扫码加入
获取工程师必备礼包
参与热点资讯讨论

转载自公众号:敢敢AUTOHUB

简介

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 从观测到干预动作的接口

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

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 进度标签。成功轨迹的第  步标签是 ,从零逐渐增加到一;失败轨迹的归一化值保持为零,原始值使用 -500 作为明显的失败信号。这个标签不是环境真实奖励,而是一个用于学习“成功轨迹通常怎样变好”的代理监督。它让价值函数能够在终点奖励之外提供每一步的相对进展刻度。

def label_episode(transitions, fail_value=-500):
    """为一条 episode 写入 raw_value 与 raw_norm。"""
    T = len(transitions)
    denom = max(T - 1, 1)
    success = is_success(transitions)
    if success:
        for t, tr in enumerate(transitions):
            tr["raw_value"] = t - (T - 1)
            tr["raw_norm"] = 1.0 if T == 1 else float(t / denom)
    else:
        for tr in transitions:
            tr["raw_value"] = fail_value
            tr["raw_norm"] = 0.0
    return transitions

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

工程价值

4.2 双价值头与保守估计

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

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

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

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

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

5.2 代码中的 FutureHead 与 TwinQHead

class FutureHead(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) if mode == "dense" else 0
        out_dim = latent_dim if mode == "pooled" else latent_dim * self.n_tokens
        self.proj = nn.Sequential(
            nn.Linear(hidden_size, 4 * hidden_size), nn.GELU(),
            nn.Linear(4 * hidden_size, out_dim)
        )

    def forward(self, h_t):
        z = self.proj(h_t)
        return z if self.mode == "pooled" else z.view(z.size(0), self.n_tokens, -1)

class TwinQHead(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))

    def forward(self, feat):
        return self.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 使用长度为八的历史窗口,把最近的价值增量放在一起观察,只有当实际增量持续低于期望进展速率时,风险才会累积。风险还乘以 ,任务越接近完成,剩余进展越少,短暂波动越不应触发强制恢复。

6.2 TVR 公式与公开实现

在公开配置中,、、,干预阈值为 。风险头接收未来潜变量和价值历史编码,训练目标是上式计算出的连续 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) - 1
    V_t = float(values_hist[-1])
    total = 0.0
    for i in range(K):
        delta_i = float(values_hist[K - i]) - float(values_hist[K - i - 1])
        total += (gamma ** i) * (epsilon - delta_i)
    return float((1.0 - V_t) * total)

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

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

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

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

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

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

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

7.2 资格筛选和余弦检索

def segment_is_eligible(start_vf, end_vf, delta_threshold, target_vf_threshold):
    return (
        float(end_vf) - float(start_vf) >= float(delta_threshold)
        and float(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 上限来控制目标质量。换句话说,记忆库解决的是“恢复到哪里”的选择问题,不能单独替代恢复策略的控制能力。

工程价值

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

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

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

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

8.2 逐 token 交叉熵与动作块

难点提示:FAST 的 token 预测损失只衡量动作编码是否接近示范,并不直接保证真实机械臂的接触力、碰撞风险或目标可达性。部署时必须把动作限幅、碰撞检测和人工接管保留在策略输出之外,形成最后一道安全边界。

def fast_decoder_v2_ce_loss(logits, gt_tokens, label_smoothing=0.0):
    # logits: [B, N, n_bins], gt_tokens: [B, T, D]
    B, T, D = gt_tokens.shape
    n_bins = logits.size(-1)
    gt_flat = gt_tokens.reshape(B, T * D)
    logits_flat = logits.reshape(B, T * D, n_bins)
    ce = F.cross_entropy(
        logits_flat.reshape(-1, n_bins), gt_flat.reshape(-1),
        label_smoothing=label_smoothing, reduction="none"
    ).reshape(B, T, D)
    return {"ce": ce.mean(), "token_count": torch.tensor(B * T * D)}

这段代码对应 research_impl/fast_decoder_v2.py 的损失核心,实际实现还会根据时间步和动作维度施加权重,并计算 token accuracy。动作块训练的优点是一次恢复可以覆盖多个控制周期,减少触发器每一步都重新决定的开销;风险是错误动作会连续执行一小段时间,因此部署时仍要保留安全检查、人工接管和动作限幅。恢复策略的训练样本来自记忆挖掘得到的连接片段,若目标筛选过于宽松,模型学到的可能只是“向高价值图像靠近”的外观偏好,而不是可执行的接触控制。

9. 从代码看完整训练流程

9.1 run.py 的阶段依赖

ORDER = ("nttg", "vf", "annotate", "mining", "vq1", "memory", "vq2")

if a.stage == "all":
    stages = ORDER
else:
    stages = (a.stage,)

for stage in stages:
    cmd, env, output = commands(a, stage)
    print(f"[{stage}] " + shlex.join(map(str, cmd)), flush=True)
    output.mkdir(parents=True, exist_ok=True)
    subprocess.run(cmd, check=True, env=env, cwd=SRC)

run.py 的价值不在于提供一个复杂的调度器,而在于把每个阶段的输入输出路径固定下来。VF 必须依赖 buffer_nttg,Annotation 必须依赖 VF checkpoint,Mining 必须依赖带价值预测的缓冲区,Memory 和 VQ2 又必须显式拿到 VQ1 checkpoint。这样的依赖检查减少了“用错实验目录”的风险,也说明 UniIntervene 的训练并不是端到端一次反向传播,而是多个有明确数据契约的离线阶段。对不了解项目的读者,最重要的流程图可以写成:先定义进展,再预测价值;用价值趋势标出需要接管的片段;从高价值片段建立目标库;最后学习如何从当前失败状态到达目标。

9.2 VQ1 的多任务损失

公开配置将未来预测、Q 值、干预、TVR 和当前价值辅助损失的权重都设为 1。实际训练会先从 <VQ_QUERY> 隐藏状态提取共享表征,再同时计算未来 latent、双 Q、当前价值和风险头。这样做的优点是多个任务共享视觉语言语义空间,缺点是不同损失对数据质量的敏感性不同:未来预测需要相邻帧,Q 值需要可信的代理价值,干预损失需要准确的 mining 标签,恢复目标则依赖另一个阶段生成的记忆库。训练日志和 checkpoint 中必须保存配置、价值来源和数据分割,否则很难判断性能变化来自模型结构还是数据管线。

10. Jev 与 UniIntervene 的区别

10.1 只保留有用的思想联系

Jev 在本文中只提供一个入口:复杂输入经过模型处理后,应当输出能被程序直接使用的判断。UniIntervene 把这个接口化思路落到机器人强化学习中,判断对象变成动作后果、任务进展和是否需要恢复。它们不属于同一套模型,本文也不把 Jev 写成 UniIntervene 的组成模块;真正需要理解的是 UniIntervene 如何把价值估计、TVR 风险、恢复目标和 FAST 动作串成闭环。这样处理可以保留概念联系,同时把主要篇幅放在机器人算法、训练数据和执行流程上。

10.2 一张表看清边界

对比维度 Jev UniIntervene
核心对象 通用的结构化判断与软件接口 真实机器人 HiL-RL 的价值判别、干预和恢复
输入 可泛化的状态、上下文或多模态信息 相机观测、语言指令、候选动作和价值历史
输出 可供下游程序读取的判断结果 未来潜变量、双 Q 值、TVR、干预分数和动作块
训练重点 判断结果的结构化与可组合性 NTTG/VF、未来预测、趋势风险、记忆检索和动作解码
本文关系 只作为接口化判别思想的引子 文章分析和代码流程的主体

11. 总结

UniIntervene 把真实机器人强化学习中的人工接管拆成两个结构化问题:先用动作条件的未来价值和时序风险判断当前策略是否已经持续停滞,再从经过价值筛选的历史经验中检索恢复目标,并用 FAST 目标条件策略生成一段可执行纠正动作。本文借用 Jev 的思想来说明为什么这些输出需要成为明确的软件接口,但实现主体仍是 UniIntervene 的机器人价值模型和控制闭环。核心问题在于,完整流程必须把标签、预测、检索和动作执行连成一条数据链,可以记成七步:NTTG 定义进度,VF 学习代理价值,Annotation 写回预测,Mining 标注停滞,VQ1 学习未来与干预,Memory 筛选高价值目标,VQ2 学习恢复动作。人类仍然保留在闭环中,但角色从频繁纠正每一次卡顿,逐步转向处理真正危险、罕见和分布外的情况。

相关推荐