mcpField
T
tao-mine-aoi-images

tao-mine-aoi-images

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

关于 tao-mine-aoi-images

该技能将目标图像与候选源图像嵌入,再通过近邻搜索筛选相似图像,输出去重后的 Parquet 文件,供 VCN AOI 后续训练使用。迭代流程还可按历史记录排除已选样本。

主要功能

  1. 01为目标和源图像生成嵌入
  2. 02按近邻搜索相似源图像
  3. 03按标签过滤并去重结果
  4. 04迭代时排除历史已选样本
  5. 05输出 Parquet 与挖掘摘要

适用场景

  1. 01从候选池为目标图像寻找相似样本
  2. 02按标签限制图像匹配
  3. 03为迭代训练避免重复采样

安装

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

$npx skills add https://github.com/nvidia/skills --skill tao-mine-aoi-images

安装后在 Claude Code 中输入/tao-mine-aoi-images确认已加载。

包含的文件

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

BENCHMARK.md
skill-card.md
skill.oms.sig
config/
skillspector-baseline.yaml
evals/
evals.json
hooks/
_parse-stdin.sh
mining-artifacts-check.sh
mining-package.sh
mining-script-check.sh
mining-section-check.sh
references/
outputs-and-reporting.md
reference-invocation.md
setup.md
troubleshooting.md
scripts/
filter_mined_history.py
tests/
test_filter_mined_history.py

详细介绍

DEFT 挖掘与嵌入技能

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

你是 VCN AOI 的 DEFT 先嵌入后挖掘工作流的操作者。你的任务是获取一份弱目标图像的 parquet(差距分析或路由输出)和一个源池,然后生成一份去重后的挖掘源图像 parquet,其中的图像与目标相似,可供下一轮训练使用。迭代式 DEFT 调用方还会运行随附的历史感知后处理步骤,以避免再次选择先前迭代中已选取的样本。

该工作流固定且确定:嵌入目标图像,嵌入源池,挖掘最近邻,然后(对于迭代式工作流)移除先前挖掘出的样本。 每个 GPU 步骤的输出 parquet 都是下一步骤的输入;历史感知选择是主机端后处理步骤,不会再次执行 k-NN 搜索。工作流没有聚类环节或人工参与的选择步骤——挖掘深度取决于选择合适的编码器,以及设置足够大的 topn,以便历史过滤后仍有新候选项。

整个技能只是围绕固定版本的 TAO 数据服务镜像发起三次直接 docker run 调用,再加上一个可选的、随附的主机端 Python 后处理器,用于迭代历史处理(请参阅 versions.yaml,运行时会在 Setup 中解析)。容器的入口点接受 <category> <action> -e <spec.yaml> [hydra overrides...]——嵌入时传入 embedding image_embeddings -e <embedding_spec.yaml> …,挖掘时传入 tmm nearest_neighbors -e <mining_spec.yaml> …。-e 标志指向一个 YAML 文件,其中提供该子任务架构的默认值;其后的内容都是独立的 Hydra 覆盖项(key=value),用于按运行选择性地覆盖规范文件中的字段。(容器内没有 dataset 关键字——它是 TAO 启动器的 pillar 前缀,此处会将其省略。)如果镜像尚未缓存,请拉取一次:docker pull "$DS_IMAGE"(请先按照 Setup 解析 $DS_IMAGE)。

不同版本的数据服务可能会更改架构键名(RCA 技能遇到过 inference_csv → inference_results_dir、output_dir → results_dir 的更名)。不确定时,请针对每个镜像检查一次实际架构:docker run --rm "$DS_IMAGE" embedding image_embeddings --cfg=job 和 ... tmm nearest_neighbors --cfg=job。


输入

  1. 目标 parquet — 差异分析输出,通常是 tao-route-visual-changenet-samples 生成的 mining_gaps.parquet(如果跳过路由,则使用 tao-analyze-gaps-visual-changenet 生成的 kpi_gaps.parquet)。必需的列:filepath。如果还包含 label,挖掘时即可进行标签感知筛选;否则,挖掘任务会静默跳过筛选。
  2. 源池 — 用于挖掘的候选图像 parquet,包含 filepath 列。如果用户只有 CSV,请在步骤 2 之前将其转换为包含相同列的 parquet。要进行标签感知筛选,源池还必须包含 label 列。
  3. 嵌入规范文件 — YAML 文件,包含 model、model_path、batch_size,并且(仅当 model_path 是 TAO .pth/.ckpt 文件时)包含 model_config_path。步骤 1 和步骤 2 共用此文件;每次运行的 input_parquet/output_parquet 通过 Hydra 覆盖项提供。两个嵌入步骤必须使用同一个规范文件——不同编码器生成的嵌入不可比较,而编码器不匹配是“挖出的图像看起来毫不相关”报告最常见的原因。
  4. 挖掘规范文件 — YAML 文件,包含 topn、knn_metric、filter_by_label,以及(很少更改的)source_embed_column_name/target_embed_column_name。运行时通过 Hydra 覆盖项提供 source_parquet/target_parquet/output_parquet。SigLIP 和 CLIP 嵌入应使用 knn_metric: cosine。当 filter_by_label: true 但任一嵌入 parquet 缺少 label 列时,容器会记录警告并继续执行,不进行筛选。
  5. 挖掘历史记录(仅限迭代工作流) — 运行级结果目录下的一个 JSON 台账,以及每次迭代对应的历史摘要。两个文件均由 scripts/filter_mined_history.py 管理。它通过规范化后的 filepath 标识样本,验证所有先前输出的哈希,并拒绝存在迭代间隙或重复选择的情况。恢复运行时,切勿手动编辑或重建此台账。

设置

请使用下面固定版本的 TAO data-services URI,然后先确认 Docker、NVIDIA 容器工具包和 GPU 均已就绪,再执行其他操作。编码器前向传递和 cuML/cuDF k-NN 搜索都需要 GPU;没有 CUDA,两步都会失败。

# 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"

容器读取或写入的所有主机路径都必须进行绑定挂载。最可预测的做法是以内外路径完全相同的方式挂载工作区根目录,然后对三次调用复用同一个 $DOCKER 别名:

WORKSPACE=<absolute path that contains all parquets, outputs, and the source-pool images>
DOCKER="docker run --gpus all --rm --shm-size=8g -v $WORKSPACE:$WORKSPACE -w $WORKSPACE $DS_IMAGE"

不要传递 --user $(id -u):$(id -g) —— 这会在任何工作开始前、导入 transformers 时触发 getpwuid() KeyError。容器以 root 身份运行;之后再将输出文件的所有者改回主机 UID。

每次迭代编写一次这两个规范文件,并将其放在 $WORKSPACE 下,这样 -e 参数在挂载路径的内外两侧都能解析;每次运行的值不要放入规范文件,而应通过 Hydra 覆盖项传递。如果源池是 CSV,请预先将其转换为 parquet(保留 filepath,并在存在时保留 label)。默认的 embedding_spec.yaml 使用 model: SigLIP、model_path: google/siglip-base-patch16-224、batch_size: 64;默认的 mining_spec.yaml 使用 topn: 5、knn_metric: cosine、filter_by_label: "false"(需加引号——该架构会将其读取为字符串)。迭代式 DEFT 工作流沿用 topn: 5 默认值;若用户指定了明确的值,则应保留。只有当历史摘要显示狭窄邻域中已有选择占主导时,才增加该值。

完整的环境说明、TAO_SKILL_BANK_PATH 处理方法、路径挂载的原因、getpwuid 的 chown 解决方法、CSV 转 parquet 代码片段,以及规范文件的原样编写代码块,请参阅 references/setup.md。


方法

依次运行 3 条命令。每条命令输出的 parquet 都是下一条命令的输入。将它们作为普通 Bash 命令运行;Setup 中的 $DOCKER 别名会处理容器、GPU 和挂载。每次调用的格式都相同:先用 -e <spec> 指定内置默认值,再添加少量针对本次运行的 Hydra 覆盖项。

步骤 1 — 嵌入目标图像
$DOCKER embedding image_embeddings \
    -e <embedding_spec.yaml> \
    input_parquet=<target_parquet> \
    output_parquet=<target_embeddings_parquet>

读取差距分析/路由输出,并写入一个 parquet,其中包含 filepath、embedding 以及从输入逐字保留的其他元数据列(例如 label、siamese_score、weakness)。将输出架构(pd.read_parquet(...).columns)打印到 stdout,以便脚本检查钩子确认嵌入列存在。

如果需要在某次运行中覆盖 model/model_path/batch_size,又不想编辑 spec,可将它们作为 Hydra 覆盖项追加(例如 model_path=...)。

步骤 2 — 嵌入源池
$DOCKER embedding image_embeddings \
    -e <embedding_spec.yaml> \
    input_parquet=<source_pool_parquet> \
    output_parquet=<source_embeddings_parquet>

命令格式与步骤 1 相同,但应用于源池。使用与步骤 1 完全相同的 embedding_spec.yaml,且不要在此处以不同方式覆盖 model/model_path/batch_size——两个步骤的编码器配置不匹配会导致嵌入不可比较。

步骤 3 — 挖掘最近邻
$DOCKER tmm nearest_neighbors \
    -e <mining_spec.yaml> \
    source_parquet=<source_embeddings_parquet> \
    target_parquet=<target_embeddings_parquet> \
    output_parquet=<mined_parquet>

针对每个目标嵌入,根据所选度量找出距离最近的 topn 个源嵌入,跨目标去重,并写入仅包含一列(filepath)的 parquet,其中列出挖掘到的唯一源路径。对于单次运行,这可以是最终的 mined.parquet;对于 DEFT 迭代,请将其写为 mined_candidates.parquet,以便为步骤 4 保留不可变的候选集。容器还会在输出 parquet 旁生成 mining_summary.txt,其中包含:查询数、邻居数、移除的重复项,以及(启用标签过滤时)保留与丢弃的配对数。进行扫描时,可通过行内 Hydra 覆盖项调整 topn、knn_metric 或 filter_by_label——无需重写 spec。

当 filter_by_label=true 但其中一个嵌入 parquet 缺少 label 列时,容器会记录警告并继续运行,但不进行过滤。如果挖掘输出看起来比预期大,或包含跨标签配对,请先检查 docker 日志中是否有该警告,再判断任务是否正常执行。

请参阅 references/reference-invocation.md,其中提供了最简的复制并编辑式端到端操作方案(解析 $DS_IMAGE、写入两个 spec、运行全部三个步骤、chown 输出文件并打印行数),可将其作为单个流式 Bash 块运行。

步骤 4 — 考虑历史记录的筛选(仅限迭代式 DEFT)

在任何标签/相似度保留筛选之后运行,以确保输入代表实际符合训练条件的候选项:

python3 skills/data/tao-mine-aoi-images/scripts/filter_mined_history.py \
    --candidate-parquet <mined_candidates.parquet> \
    --output-parquet <mined.parquet> \
    --history-file <run_results_dir>/mining_history.json \
    --summary <iteration_dir>/mining_history_summary.json \
    --iteration <N> \
    --topn <topn>

输出会保留候选项的顺序和架构,但只包含此前已提交迭代中未选中的文件路径。账本会记录所选路径、候选项/输出哈希、计数和 topn;只有在验证这些制品后,--resume 才会复用已提交的迭代。零行输出表示当前 k-NN 候选集中没有新样本,这是有效结果。调用方需决定是否由其他生成器(例如 AnomalyGen)继续执行该迭代,或直接停止。当摘要报告的 historical_candidate_rate 较高时,请增大 topn 或扩展源池;如果每次迭代检索到的都是相同的低质量邻域,历史筛选无法凭空增加多样性。


输出和报告

将所有内容写入实验 / 迭代目录下带时间戳的文件夹。通过在 Bash 中运行 date +%Y-%m-%d_%H%M%S 获取实际时间戳——不要硬编码或猜测。如果用户指定了自定义输出路径,直接使用该路径,但保持相同的内部布局。写入 Mining_Report.md 时,打包钩子会自动添加 mining_config/ 和 claude_session.jsonl。

经过历史记录筛选的最终挖掘 parquet 是迭代式下游训练阶段使用的产物。请保留历史筛选前的候选 parquet、每次迭代的历史摘要,以及运行级别的 mining_history.json,并与两个嵌入 parquet 一起保存;这些文件有助于区分“k-NN 未找到任何内容”和“k-NN 返回的样本已在先前迭代中使用”。

完整的输出目录布局和 Mining_Report.md 原样模板(Verdict、Inputs、Encoder Consistency、Mining Run、Per-Label Breakdown、Output Sanity、Recommended Actions;保持 600–1200 词)请参见 references/outputs-and-reporting.md。


常见陷阱

最常见的失败是两个嵌入步骤使用的编码器不匹配——这是挖掘输出无效最常见的原因;两个步骤必须使用同一个 embedding_spec.yaml。其他常见陷阱包括:传入 --user(导致 getpwuid KeyError)、跳过嵌入步骤、缺少 label 列导致 filter_by_label=true 静默无操作、规格文件位于 $WORKSPACE 之外、未解决的 ??? 占位符、缺少 model_config_path 的 TAO 检查点、直接输入 CSV 源数据池、主机 / 容器路径不匹配、没有 GPU、尚未拉取的镜像或 :latest 镜像标签、topn × N_targets ≫ source size(这是预期情况——报告实际挖掘数量),以及 topn 过窄,导致历史筛选后无法得到任何新样本。

完整的陷阱列表及对应的确切错误、原因和修复方法,请参见 references/troubleshooting.md。


执行顺序

  1. 将 DS_IMAGE 设为固定版本的数据服务 URI(参见 Setup),然后运行 docker info、nvidia-smi 和 docker image inspect "$DS_IMAGE"(如果镜像不存在则先拉取)一次,以确认环境。任何一项失败时,都应输出清晰的消息并中止。
  2. 运行 date +%Y-%m-%d_%H%M%S 获取时间戳;创建 <output_dir>/mining_results/<timestamp>/。
  3. 在带时间戳的目录中写入 embedding_spec.yaml 和 mining_spec.yaml,填入编码器选择和挖掘参数。将这些文件放在 $WORKSPACE 下,以便 -e 路径能在容器内解析。
  4. 如果源数据池是 CSV,先将其转换为 parquet(保留 filepath 和 label)。
  5. 通过 docker run … embedding image_embeddings -e embedding_spec.yaml input_parquet=… output_parquet=… 运行步骤 1(嵌入目标数据)。将输出 parquet 的行数和列名打印到标准输出。
  6. 使用与步骤 1 完全相同的 embedding_spec.yaml 运行步骤 2(嵌入源数据池)。打印输出行数和列名。
  7. 通过 docker run … tmm nearest_neighbors -e mining_spec.yaml source_parquet=… target_parquet=… output_parquet=… 运行步骤 3(挖掘最近邻)。确认 mining_summary.txt 已写入原始 / 候选 parquet 所在目录。
  8. 对于迭代式 DEFT 调用方,应用所有已配置的保留筛选器,然后使用当前迭代编号、记录的 topn、运行级别的账本路径和一个单独的最终 mined.parquet 运行步骤 4。切勿将原始候选 parquet 直接用于累积训练。
  9. 如果目标嵌入 parquet 和最终挖掘输出都包含 label,则通过 filepath 连接二者,计算按标签划分的明细(第 5 节)。
  10. 最后写入 Mining_Report.md——写入该文件会触发打包钩子,将会话日志和技能配置一并复制。

评论

支持 Markdown