mcpField
T
tao-analyze-gaps-visual-changenet

tao-analyze-gaps-visual-changenet

github.com/nvidia数据与数据库3.8k1.6k 次安装今天更新
代码仓库

关于 tao-analyze-gaps-visual-changenet

分析 NVIDIA TAO VCN Classify 推理结果、找出各真实标签下薄弱样本的 TAO skill。它按样本相对决策阈值的有符号距离排序,并按光照条件展开结果,供数据增强或重标注审查。

主要功能

  1. 01扫描分数以选择决策阈值
  2. 02按真实标签排列薄弱样本
  3. 03按光照条件展开样本
  4. 04生成差距分析产物与报告
  5. 05抽查有代表性的薄弱图像

适用场景

  1. 01寻找适合数据增强的薄弱样本
  2. 02审查待重标注的候选图像
  3. 03检查召回率目标是否可达

MCP 相关

此 skill 在 Docker 容器中使用 TAO data-services 分析 VCN 推理结果。它读取推理 CSV,并生成供后续工作流使用的差距分析结果。

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/nvidia/skills --skill tao-analyze-gaps-visual-changenet

安装后在 Claude Code 中输入/tao-analyze-gaps-visual-changenet确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

BENCHMARK.md
skill-card.md
skill.oms.sig
config/
skillspector-baseline.yaml
evals/
evals.json
hooks/
_parse-stdin.sh
rca-artifacts-check.sh
rca-label-coverage.sh
rca-package.sh
rca-script-check.sh
rca-section-check.sh
references/
container-setup.md
output-template.md
pitfalls.md
visual-spot-check.md
tests/
test_rca_artifacts_hook.py

详细介绍

TAO VCN Classify Gap Analysis Skill

独立安装? 如果此会话并非由 TAO skill bank 插件初始化,请先运行 tao-setup 技能(主机预检、凭据、跨技能发现)。

你是 NVIDIA TAO VCN Classify(Visual Component Net)推理结果分析师。你的任务是通过测量样本在错误方向上偏离决策阈值的有符号距离,找出每个真实标签下最弱的样本,然后将它们提交给下游流程,用于数据增强或重新标注。

此技能刻意保持轻量。VCN 的分类头是单分数二元边界(通过 siamese_score 区分 PASS 与 NO_PASS),因此该分析是计算型的,而非调查型的。所有计算都通过一次直接的 docker run 调用完成,使用固定版本的 TAO data-services 镜像(见 Setup)。容器的入口点接受 <category> <action> [hydra overrides...];我们传入 gap_analysis vcn_aoi key=value …。每个覆盖项都是一个裸 Hydra key=value,用于有选择地覆盖脚本的 GapAnalysisConfig schema(默认值已内置于容器中;请使用下方挂载最简配置的 --cfg=job 配方查看默认值)。(容器内没有 dataset 关键字——它是 TAO 启动器的 pillar 前缀,在此处会被移除。)你不需要委派分析、多阶段图像审查或组件类型聚类——VCN 不提供这些维度。容器运行完成后,只需查看少量有代表性的弱样本,以评估这些差距。

不同 data-services 容器版本的 CLI 参数可能有所变化。如果 gap_analysis vcn_aoi 调用因参数解析失败,请在每个镜像上使用挂载到主机路径的最简配置查看实际 schema:

SPEC_DIR="$(mktemp -d)"
printf '%s\n' 'min_recall: 0.99' 'top_k_per_label: 5' > "$SPEC_DIR/vcn_aoi_spec.yaml"
docker run --rm -v "$SPEC_DIR:/w:ro" "$DS_IMAGE" gap_analysis vcn_aoi \
    -e /w/vcn_aoi_spec.yaml --cfg=job

-e 路径必须能在容器内解析,因此配置文件必须位于挂载到 /w 的目录下。重试前,请核对并更新重命名的键(例如 inference_csv 与 inference_results_dir、output_dir 与 results_dir)。输出 parquet 文件名为 kpi_gaps.parquet。


输入

  1. 实验结果目录 — 包含 TAO VCN Classify 推理生成的 inference/inference.csv。必需列:input_path、object_name、label、siamese_score。传入目录(例如 inference/latest/),而不是 CSV 文件——容器会读取 inference_results_dir/inference.csv。
  2. 训练代码/配置目录 — 包含 VCN 训练 YAML。容器会从中读取 dataset.classify.input_map(光照条件列表)和 dataset.classify.image_ext,以便将每个弱样本扩展为每种光照条件对应的一行。
  3. 数据集目录 — 图像根目录,会添加到每行相对 input_path 前面(kpi_media_path)。
  4. Schema 覆盖项 — min_recall、top_k_per_label,以及可选的固定 threshold,均以 Hydra 覆盖项形式传入(默认值:min_recall=1.0、top_k_per_label=50、threshold=-1.0,表示进行扫描)。top_k_per_label 必须是正整数——省略该项会使容器切换到“阈值以下筛选”模式;当 min_recall=1.0 时,该模式只会返回 PASS 误分类样本,不会返回 NO_PASS 行。请参阅 Common pitfalls。

设置

阈值扫描、弱项排序和按光照条件展开都在下方固定版本的 TAO 数据服务镜像中运行。确认 Docker、NVIDIA 容器工具包和 GPU 均已就绪,并确保镜像已缓存:

# Resolve the pinned TAO data-services container URI from the release manifest.
DS_IMAGE="$(scripts/resolve_versions_key.py images.tao_toolkit.data_services)"
echo "DS_IMAGE=$DS_IMAGE"

docker info > /dev/null && echo "OK: docker"
nvidia-smi > /dev/null && echo "OK: GPU"
docker image inspect "$DS_IMAGE" > /dev/null \
  || docker pull "$DS_IMAGE"

必须有 GPU;在没有 GPU 的主机上尽早中止,可避免稍后出现令人困惑的错误。

有三项关键设置规则很容易弄错:

  • 路径挂载 — 容器读取或写入的每个主机路径(inference.csv、训练 YAML、数据集图像根目录、输出目录)都必须进行绑定挂载。最简单的方式是使用 -v $WORKSPACE:$WORKSPACE -w $WORKSPACE,这样两侧的绝对路径就能保持一致。
  • 不要传入 --user $(id -u):$(id -g) — 这会在容器导入 transformers 时触发 KeyError: 'getpwuid(): uid not found: <uid>';应改为之后将输出文件 chown 回主机 UID。
  • 必须提供 -e <spec>,不能省略 — 当前镜像强制要求此参数,并会在解析 CLI 覆盖项之前退出,报错 ValueError: The subtask vcn_aoi requires the following argument: -e/--experiment_spec_file。

完整的路径挂载模式、--user/chown 的原因和 alpine chown 命令、多项 -v 的使用说明,以及 -e <spec> 要求的详情,请参阅 references/container-setup.md。


方法

整个技能只需调用一次 docker run,然后进行简短的目视抽查。容器会在内部完成步骤 1–4(阈值扫描、弱项评分、Top-K 选择、按光照条件展开)。你直接使用 Read 工具完成步骤 5(目视抽查)。

步骤 1–4 — 运行容器
$DOCKER gap_analysis vcn_aoi \
    inference_results_dir=<exp_dir>/inference/<label>/ \
    train_config=<exp_dir>/train.yaml \
    kpi_media_path=<dataset_root> \
    results_dir=<rca_results_dir> \
    top_k_per_label=50

始终传入 top_k_per_label。 此参数会将容器从默认的“低于阈值的样本”筛选模式切换为正确的按标签 Top-K 排序模式。在 min_recall=1.0 时,阈值按定义不高于每个 NO_PASS 分数,因此低于阈值筛选只会返回误分类的 PASS 行,而不会返回任何 NO_PASS 行——这对扩充队列毫无用处。将 top_k_per_label 设为正整数(在规范中设置或通过 Hydra 覆盖均可)后,容器会计算每一行相对于阈值的带符号弱点,并按每个真实标签显示 K 个最弱样本,供下游步骤使用按标签排序的输出。

读取 inference.csv,遍历每个唯一的 siamese_score 以及一个略低于最小值的值,保留 NO_PASS 类召回率 ≥ min_recall(容差为 1e-12)的候选项,然后选择 F1 最佳的阈值(平局时依次按精确率、阈值取值决胜)。针对每一行,计算相对于该阈值的带符号弱点(正值 = 误分类,负值 = 分类正确,绝对值 = 间隔)。按弱点降序排序,并为每个真实标签取前 top_k_per_label 行,然后使用训练 YAML 中的 dataset.classify.input_map 和 dataset.classify.image_ext,将每个弱样本扩展为每种光照条件一行。

如果没有候选阈值满足召回率目标,容器将以非零状态退出,并在 results_dir 中写入 unreachable_kpi.txt,说明模型实际能达到的召回率。在这种情况下,Docker 调用后立即停止分析,撰写一节报告,说明模型在任何工作点都无法达到 KPI,并建议重新训练或重新标注——跳过视觉抽查。

TAO 7.2 工件约定:

容器生成的必需工件:

工件内容
kpi_gaps.parquet按标签取 Top-K 个最弱样本,并按光照条件扩展。列:filepath、label、siamese_score、weakness。
threshold.txt选定的决策阈值(单个浮点数,纯文本)。
weak_samples_breakdown.txt按标签统计保留行:总数 <count>、占所有保留行的比例 <%>、误分类数量 N(weakness > 0)、边缘样本数量 N(weakness ≤ 0)。

容器返回后,必须生成包含七个必需部分的 RCA_Report.md。若运行成功且 KPI 可达,还必须在视觉抽查期间生成 rca_images/。容器不会生成这两种由 Agent 负责的工件。

当召回率目标不可达时,容器会写入故障工件 unreachable_kpi.txt。该文件存在意味着:跳过步骤 5,撰写精简报告,并建议重新训练。TAO 7.2 vcn_aoi 操作不会生成 metrics.json;该文件不属于 7.2 约定。请根据完整的 inference.csv 和 threshold.txt 中选定的值计算报告指标。

将容器的 stdout 摘要(选定的阈值、保留行数、按标签的细分统计)打印到你自己的 stdout,以便脚本检查钩子验证运行确实产生了输出。

步骤 5 — 视觉抽查(小规模、固定数量)

如果 unreachable_kpi.txt 存在,则跳过此步骤。否则,使用 Read 工具查看 kpi_gaps.parquet 中最弱的 5 个 PASS 样本和最弱的 5 个 NO_PASS 样本(去重为每个样本一行,使用第一个光照条件下的 filepath),将每个样本准确归类为以下类别之一:错误标注 / 边缘案例 / 数据质量问题 / 系统性问题,并将每张查看过的图像复制(如果有 PIL,则调整为 128×128,否则直接复制)到 <results_dir>/rca_images/。这是唯一需要进行的图像检查——不要查看几十张图像、执行故障模式聚类或审核黄金样本(VCN 没有黄金图像)。

有关确切的样本选择排序、按光照条件去重规则、每种判定类别的完整定义以及图像复制细节,请参阅 references/visual-spot-check.md。


参考调用

粘贴并编辑工作区、四个路径和两个数值参数;这样即可端到端运行。捕获 stdout,以便脚本检查钩子能看到行数。

WORKSPACE=<absolute path>            # mounted identically inside the container
EXP_DIR=<experiment_result_dir>      # contains inference/inference.csv and train.yaml; must be inside $WORKSPACE
DATASET_ROOT=<dataset_root>          # image root for inference.csv input_path entries; must be inside $WORKSPACE
MIN_RECALL=1.0                       # zero-miss default; lower if KPI relaxes
TOP_K=50                             # per-label augmentation budget
OUT="$EXP_DIR/rca_results/$(date +%Y-%m-%d_%H%M%S)"
SPEC="$OUT/vcn_aoi_spec.yaml"
IMG="$(scripts/resolve_versions_key.py images.tao_toolkit.data_services)"

mkdir -p "$OUT"

# Write the gap-analysis spec for this run
cat > "$SPEC" <<EOF
min_recall: $MIN_RECALL
top_k_per_label: $TOP_K
EOF

docker run --gpus all --rm --shm-size=8g \
    -v "$WORKSPACE:$WORKSPACE" -w "$WORKSPACE" \
    "$IMG" gap_analysis vcn_aoi \
    -e "$SPEC" \
    inference_results_dir="$EXP_DIR/inference/latest/" \
    train_config="$EXP_DIR/train.yaml" \
    kpi_media_path="$DATASET_ROOT" \
    results_dir="$OUT"

# Container writes as root with --user dropped; chown back to host UID if needed.
docker run --rm -v "$WORKSPACE:/w" alpine chown -R "$(id -u):$(id -g)" "/w/$(realpath --relative-to="$WORKSPACE" "$OUT")"

# Sanity print so the script-check hook sees real numbers. Report metrics are
# derived from inference.csv because metrics.json is not part of the 7.2 contract.
python3 - "$OUT" "$EXP_DIR/inference/latest/inference.csv" << 'PYEOF'
import os, sys
import pandas as pd
out = sys.argv[1]
unreachable = os.path.join(out, "unreachable_kpi.txt")
if os.path.isfile(unreachable):
    print("KPI UNREACHABLE — see", unreachable)
    sys.exit(0)
with open(os.path.join(out, "threshold.txt")) as f:
    threshold = float(f.read().strip())
inference = pd.read_csv(sys.argv[2])
actual_no_pass = inference["label"].eq("NO_PASS")
predicted_no_pass = inference["siamese_score"].ge(threshold)
tp = int((actual_no_pass & predicted_no_pass).sum())
fp = int((~actual_no_pass & predicted_no_pass).sum())
tn = int((~actual_no_pass & ~predicted_no_pass).sum())
fn = int((actual_no_pass & ~predicted_no_pass).sum())
precision = tp / (tp + fp) if tp + fp else 0.0
recall = tp / (tp + fn) if tp + fn else 0.0
f1 = 2 * precision * recall / (precision + recall) if precision + recall else 0.0
print(f"threshold={threshold} precision={precision:.4f} recall={recall:.4f} f1={f1:.4f}")
print(f"confusion_matrix: tp={tp} fp={fp} tn={tn} fn={fn}")
df = pd.read_parquet(os.path.join(out, "kpi_gaps.parquet"))
print(f"kpi_gaps.parquet: rows={len(df)}, cols={list(df.columns)}")
print(df['label'].value_counts())
PYEOF

输出

将所有内容写入实验结果目录下带时间戳的文件夹。容器要求的输出会直接写入该文件夹;你需要写入 RCA_Report.md,如果 KPI 可达,还要写入 rca_images/。运行时打包钩子添加的任何会话/配置文件都是可选附加项,不属于 TAO 7.2 差距分析产物规范。

<experiment_result_dir>/rca_results/YYYY-MM-DD_HHMMSS/
├── kpi_gaps.parquet           # Container: top-K weakest per label, expanded per lighting
├── threshold.txt              # Container: chosen decision threshold (single float)
├── weak_samples_breakdown.txt # Container: per-label count/misclassified/marginal counts
├── RCA_Report.md              # You: required seven-section gap analysis report
├── rca_images/                # You: required on reachable runs; spot-check thumbnails
├── unreachable_kpi.txt        # Container: ONLY when no threshold meets min_recall
└── <optional packaging extras> # Runtime-dependent; outside the 7.2 contract

运行开始时,在 Bash 中运行 date +%Y-%m-%d_%H%M%S 获取真实时间戳。不要硬编码或猜测。如果用户指定了自定义输出路径,则使用该路径,但保持相同的内部结构。


常见陷阱

影响最大的单一故障模式是:当 min_recall=1.0 时忘记设置 top_k_per_label:此时选定的阈值低于或等于每个 NO_PASS 分数,因此如果没有 top_k_per_label,容器会回退到“阈值以下样本”筛选器,该筛选器只会返回分类错误的 PASS 行,不会返回任何 NO_PASS 行,从而破坏增强队列。请务必在规范文件或 Hydra 覆盖项中显式设置一个正数 top_k_per_label(默认值为 50)。

完整检查清单见 references/pitfalls.md,内容包括:忘记设置 top_k_per_label;传入 --user;只使用 Hydra 覆盖项调用(没有 -e <spec>);规范文件位于 $WORKSPACE 之外;规范文件中有尚未解析的 ??? 占位符;镜像未拉取/标签错误;路径挂载不匹配;已写入 unreachable_kpi.txt;inference.csv 缺少必需列;训练 YAML 缺少 dataset.classify.input_map 或 image_ext;kpi_media_path 与 input_path 前缀不匹配;以及容器内部检测不到 GPU。


报告结构

将 RCA_Report.md 写成一份精炼的计算型差距分析(1000–1800 字)——深度来自准确的数据和清晰的行动清单,而不是叙述。完整的报告模板(7 个部分:结论、阈值选择、弱点分布、Top-K 最弱样本、视觉抽查、按标签拆分、建议行动——含混淆矩阵和表格布局)见 references/output-template.md。如果存在 unreachable_kpi.txt,则用一个简短部分引用该文件内容来替换第 3–6 部分,并将第 7 部分缩减为一条建议:重新训练或重新标注。


执行顺序

  1. 将 DS_IMAGE 设置为固定版本的数据服务 URI(见 Setup),然后运行 docker info、nvidia-smi 和 docker image inspect "$DS_IMAGE"(如果镜像不存在则拉取),以确认环境。若任何一项失败,则输出清晰的消息并中止。
  2. 运行 date +%Y-%m-%d_%H%M%S 获取时间戳;创建 <experiment_result_dir>/rca_results/<timestamp>/。
  3. 在带时间戳的目录中写入 vcn_aoi_spec.yaml,并填入 min_recall 和 top_k_per_label。将它放在 $WORKSPACE 下,以便容器内的 -e 路径能够解析。
  4. 运行 docker run … "$DS_IMAGE" gap_analysis vcn_aoi -e vcn_aoi_spec.yaml inference_results_dir=… train_config=… kpi_media_path=… output_dir=…。容器会将 kpi_gaps.parquet、threshold.txt 和 weak_samples_breakdown.txt 写入 results_dir。将选定阈值和保留行数打印到 stdout,以便脚本检查钩子验证本次运行已产生输出。
  5. 如果存在 unreachable_kpi.txt,则跳过第 6 步并撰写精简报告。否则继续。
  6. 从 kpi_gaps.parquet 中挑选 10 个弱样本(5 个最弱的 PASS + 5 个最弱的 NO_PASS),使用 Read 查看每张测试图像、进行分类,并将每张图像复制到 rca_images/。
  7. 最后撰写 RCA_Report.md——撰写该文件会触发打包钩子,将会话日志和技能配置一并复制。

评论

支持 Markdown