stouchinglhh
Claude
sync processor from GitLab c697b6e: 版本 1.19.4 / 前端 1.12.4 —— 服务端 i18n(首屏不再闪英文)、推理模块并入模型页、前端抽出 shared/、缓存键改用前端号
bb59211
Raw History Blame Contribute Delete
4.71 kB
"""action 有效性 —— 监督信号是否真的存在、是否可用。
为什么重要
----------
**action 是 ACT 的监督信号**(``L1(预测, action)``)。没有它就算不出 loss。
而它是**派生**出来的,不是采出来的,所以有四种失效方式:
① 工作流没跑 / 跑失败 → action 还是采集端的**全零占位**
★ 最阴险:有列、有 7 维、能加载,全是 0 —— 不报任何错
② 整集派生失败(位姿样本不足)→ 列根本不写 → 导出时缺失
★ 训练直接 KeyError(2026-09-11 踩过)
③ 部分帧派生失败 → 那些帧的 action 是 null
④ 派生成功但数值离群 → 归一化统计量被撑大(交给 umi.slam_continuity 解释)
严重度
------
① ② 判 **FAIL** —— 没有监督信号,这一集对训练毫无价值。
③ 判 **WARN** —— 部分帧缺失,剩余帧仍可训练。
关于"全零"
----------
采集端在 UMI 硬件上写的就是全零(硬件不录 action),所以**必须区分**
"还没派生"和"派生了但动作真的是零"。判据是**整列方差**:
派生的 action 即使动作很小,帧间也会有变化;全零占位则方差严格为 0。
"""
from __future__ import annotations
from app.processing.cleaning.checks import (
CheckContext, CleaningCheck, register_check,
Finding, PASS, WARN, FAIL,
)
@register_check
class UmiActionPresentCheck(CleaningCheck):
slug = "umi.action_present"
label = "Action Validity"
version = "1.0"
description = "Missing supervision signal, all-zero placeholder, or frames never derived"
requires_channels = ("action",)
# 属于哪些设备卡片 —— 前端设置面板按它分 tab
device_cards = ("gripper_device",)
default_params = {
"min_coverage": 0.95, # 有 action 的帧占比下限
"zero_epsilon": 1e-9, # 判定"全零"的容差
}
default_severity = FAIL
def run(self, ctx: CheckContext) -> list[Finding]:
findings: list[Finding] = []
min_coverage = float(self.param(ctx, "min_coverage", 0.95))
epsilon = float(self.param(ctx, "zero_epsilon", 1e-9))
for stream in ctx.streams_of("action"):
rows = int(stream.rows or 0)
if not rows:
# 列存在但一行都没有 —— 与"列不存在"同义
findings.append(self.finding(
ctx, FAIL, stream=stream.key,
message="the action column has no data at all (derivation failed for the whole episode)",
metrics={"rows": 0},
))
continue
values = stream.series.get("action") or ()
usable = [item for item in values if item]
coverage = len(usable) / rows if rows else 0.0
# 整列方差 —— 区分"全零占位"和"动作真的很小"
flat: list[float] = []
for item in usable[:5000]: # 抽样即可,全零占位必然处处为零
try:
flat.extend(float(value) for value in item)
except (TypeError, ValueError):
continue
spread = (max(flat) - min(flat)) if flat else 0.0
all_zero = spread <= epsilon
metrics = {
"rows": rows,
"usable": len(usable),
"coverage": round(coverage, 4),
"value_spread": spread,
}
if all_zero and usable:
findings.append(self.finding(
ctx, FAIL, stream=stream.key,
message="action is all zeros - likely still the recorder placeholder (workflow never ran, or derivation failed)",
metrics=metrics,
))
continue
if not usable:
findings.append(self.finding(
ctx, FAIL, stream=stream.key,
message="the action column exists but every value is empty (derivation produced no frames)",
metrics=metrics,
))
continue
if coverage < min_coverage:
findings.append(self.finding(
ctx, WARN, stream=stream.key,
message=f"only {len(usable)}/{rows} frames have action"
f"({coverage:.1%}),其余帧无监督信号",
metrics=metrics,
))
continue
findings.append(self.finding(ctx, PASS, stream=stream.key,
metrics=metrics))
return findings