tao-mine-aoi-images について
ターゲット画像とソース画像を埋め込み、近傍画像を検索して重複を除いた parquet を作成する DEFT ワークフロースキルです。次の VCN AOI 学習ラウンドに使う類似画像の準備を想定しています。
主な機能
- 01ターゲットとソースの parquet を埋め込み
- 02指定した距離指標で最近傍を検索
- 03検索した画像パスの重複を除去
- 04ラベルによるフィルタリング(任意)
- 05検索サマリーと中間 parquet を出力
活用シーン
- 01弱いターゲットに似たソース画像の検索
- 02次の学習ラウンド向け画像データの準備
- 03複数の検索処理で埋め込みを再利用
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ promptingcompany/ nv-skills --skill tao-mine-aoi-imagesインストール後、Claude Code で/tao-mine-aoi-imagesを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
BENCHMARK.mdskill-card.mdskill.oms.sigevals/evals.jsonhooks/_parse-stdin.shmining-artifacts-check.shmining-package.shmining-script-check.shmining-section-check.shreferences/invocation.mdreporting_spec.mdtroubleshooting.md詳細
DEFT 採掘・埋め込みスキル
VCN AOI 向けの DEFT 埋め込み後採掘ワークフローを運用します。役割は、ターゲット画像のパーケットファイル(ギャップ分析またはルーティングの出力)とソースプールを受け取り、ターゲットに似た採掘済みソース画像を重複排除したパーケットファイルとして作成し、次のトレーニングラウンドにすぐ投入できる状態にすることです。
ワークフローは固定されており、決定論的です。ターゲットを埋め込み、ソースプールを埋め込み、その後で最近傍を採掘します。 各ステップの出力パーケットファイルが、次のステップの入力になります。反復検索も、クラスタリング処理も、Human-in-the-loop による選択もありません。深さを左右するのは、複数フェーズにわたる調査ではなく、適切なエンコーダーと topn の選択です。
このスキルは、versions.yaml で宣言された tao_toolkit.data_services イメージに対する 3 回の直接的な docker run 呼び出しを薄くラップしたものです(実行時に解決されます。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 ランチャーのピラープレフィックスであり、ここでは省略されます。データサービスのリリースによってスキーマキーの名前が変わる場合があるため、判断に迷ったら、イメージごとに一度 docker run --rm "$DS_IMAGE" embedding image_embeddings --cfg=job と ... tmm nearest_neighbors --cfg=job で内容を確認してください。エントリーポイントの仕様、--cfg=job による確認、コピーして編集できるエンドツーエンドの手順については、references/invocation.md を参照してください。
入力
- ターゲットのパーケットファイル — ギャップ分析の出力です。通常は
tao-route-visual-changenet-samplesのmining_gaps.parquet(ルーティングを省略した場合はtao-analyze-gaps-visual-changenetのgaps.parquet)です。必須列はfilepathです。labelも存在する場合は、採掘時にラベルを考慮したフィルタリングを利用できます。それ以外の場合、採掘タスクはフィルターを何も通知せずに適用しません。 - ソースプール — 採掘対象となる候補画像のパーケットファイルで、
filepath列が必要です。ユーザーが CSV しか持っていない場合は、ステップ 2 の前に同じ列構成でパーケットファイルに変換してください。ラベルを考慮したフィルタリングを行うには、プールにlabel列も必要です。 - 埋め込み仕様ファイル —
model、model_path、batch_size、および(model_pathが TAO の.pth/.ckptの場合に限り)model_config_pathを含む YAML です。ステップ 1 と 2 で再利用します。input_parquet/output_parquetは実行ごとに Hydra オーバーライドとして指定します。両方の埋め込みステップで同じ仕様ファイルを使用する必要があります。異なるエンコーダーからの埋め込みは比較できず、エンコーダーの不一致は「採掘された画像に関連性がない」という報告の最も一般的な原因です。 - 採掘仕様ファイル —
topn、knn_metric、filter_by_label、および(変更することはまれな)source_embed_column_name/target_embed_column_nameを含む YAML です。source_parquet/target_parquet/output_parquetは実行時の Hydra オーバーライドです。SigLIP と CLIP の埋め込みにはknn_metric: cosineを使用してください。filter_by_label: trueであっても、いずれかの埋め込みパーケットファイルにlabel列がない場合、コンテナは警告をログに記録し、フィルタリングを行わずに処理を続行します。
セットアップ
マイニングと埋め込みのタスクは、versions.yaml で宣言されている tao_toolkit.data_services イメージ内にあります。実行の最初に具体的な URI を一度だけ解決し、その後、ほかの作業を始める前に Docker、NVIDIA Container Toolkit、GPU が利用可能であることを確認してください。
# Resolve tao_toolkit.data_services → concrete nvcr.io/... URI from versions.yaml
DS_IMAGE=$(python3 -c "import yaml,os; print(yaml.safe_load(open(os.environ['TAO_SKILL_BANK_PATH']+'/versions.yaml'))['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"
TAO_SKILL_BANK_PATH は、プラグインの session_start フックによってエクスポートされます。設定されていない場合(例:Claude Code プラグインの外で実行する場合)は、解決する前にスキルバンクのリポジトリルートを指定してください。エンコーダーのフォワードパスと cuML/cuDF の k-NN 検索の両方に GPU が必要です。CUDA がなければ、どちらの処理も失敗します。
パスのマウント。 コンテナが読み書きするすべてのホストパス(入力の Parquet、出力ディレクトリ、ソースプールの画像ルート)は、バインドマウントする必要があります。最も簡単で予測しやすい方法は、ワークスペースのルートをコンテナ内外で同一のパスとしてマウントすることです。これにより、Parquet の引数内の絶対パスが両方で同じように解決されます。
WORKSPACE=<absolute path that contains all parquets, outputs, and the source-pool images>
DOCKER="docker run --gpus all --rm --ipc=host --user $(id -u):$(id -g) -v $WORKSPACE:$WORKSPACE -w $WORKSPACE $DS_IMAGE"
以下の 3 つの実行では $DOCKER を再利用してください。
CSV ソースプール。 ソースプールが CSV でのみ提供されている場合は、pd.read_csv(...).to_parquet(..., index=False) を使って事前に Parquet に変換し、filepath 列(および存在する場合は label)をそのまま保持してください。パスのプレフィックスを追加しないでください。コンテナは入力 Parquet をそのまま読み込み、$WORKSPACE マウントによってホストとコンテナのパスが同一に保たれます。
イテレーションごとに 2 つの仕様ファイルを一度作成してください。 両ファイルは $WORKSPACE 内に配置し、-e 引数がマウントの両側で解決されるようにします。実行ごとの値は仕様ファイルに含めず、実行時に Hydra のオーバーライドとして渡します。デフォルトは、埋め込みでは model: SigLIP、model_path: google/siglip-base-patch16-224、batch_size: 64、マイニングでは topn: 5、knn_metric: cosine、filter_by_label: "false"(スキーマが文字列として読み取るため引用符で囲みます)です。SigLIP/CLIP には cosine を、それ以外には euclidean/manhattan を使用してください。model_path が TAO チェックポイントの場合に限り、model_config_path を追加してください。どのフィールドも CLI でインラインに上書きできます(例:topn=10)。Hydra は CLI のオーバーライドを仕様ファイルに適用します。
仕様ファイルのテンプレート(原文どおりのもの)、CSV の変換スニペット、マウントおよびイメージ解決の詳細については、references/invocation.md を参照してください。
方法
3 つのコマンドを順番に実行します。各コマンドの出力 Parquet が、次のコマンドの入力になります。通常の Bash として実行してください。Setup の $DOCKER エイリアスがコンテナ、GPU、マウントを処理します。各実行は共通の形式に従います。-e <spec> で組み込みのデフォルトを指定し、その後、実行ごとのパスに対する Hydra のオーバーライドをいくつか指定します。
Step 1 — 対象画像を埋め込む
$DOCKER embedding image_embeddings -e <embedding_spec.yaml> \
input_parquet=<target_parquet> output_parquet=<target_embeddings_parquet>
ギャップ分析/ルーティングの出力を読み込み、filepath、embedding、および引き継がれる追加メタデータ列(例:label、siamese_score、weakness)を含む Parquet を書き出します。埋め込み列が存在することをスクリプトチェックフックが確認できるよう、出力スキーマ(pd.read_parquet(...).columns)を標準出力に表示してください。仕様ファイルを編集せずに、実行ごとに model/model_path/batch_size を上書きするには、Hydra のオーバーライドとして追加してください。
Step 2 — ソースプールを埋め込む
$DOCKER embedding image_embeddings -e <embedding_spec.yaml> \
input_parquet=<source_pool_parquet> output_parquet=<source_embeddings_parquet>
Step 1 と同じ形式のコマンドを、ソースプールに対して実行します。Step 1 と同一の embedding_spec.yaml を使用し、ここでは model/model_path/batch_size を異なる値で上書きしないでください。2 つのステップでエンコーダー設定が一致していないと、比較可能な埋め込みが生成されません。
ステップ 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 を出力します。コンテナは出力 parquet と同じ場所に mining_summary.txt も出力します。このファイルには、クエリ数、近傍数、除去した重複数、および(ラベルフィルタリングが有効な場合)保持・除外したペア数が記録されます。スイープ時はインラインの Hydra オーバーライドで topn、knn_metric、filter_by_label を調整できるため、仕様ファイルを書き換える必要はありません。filter_by_label=true でも、いずれかの埋め込み parquet に label 列がない場合、コンテナは警告をログに出してフィルタリングせずに処理を続行します。検索結果が多すぎるように見える場合や、異なるラベルのペアが含まれる場合は、まず docker ログでその警告を確認してください。
3 つのステップすべてを 1 つのストリーム形式の Bash ブロックで実行し、行数の健全性チェックを出力する、貼り付けて編集できる完全な手順については、references/invocation.md を参照してください。
出力
すべてのファイルを、実験/イテレーションディレクトリ内のタイムスタンプ付きフォルダーに出力します。Mining_Report.md が書き込まれると、パッケージングフックが mining_config/ と claude_session.jsonl を自動的に追加します。
<output_dir>/mining_results/YYYY-MM-DD_HHMMSS/
├── Mining_Report.md # Full mining report
├── embedding_spec.yaml # The -e spec used for Steps 1 and 2
├── mining_spec.yaml # The -e spec used for Step 3
├── target_embeddings.parquet # Step 1 output (filepath, embedding, + carried metadata)
├── source_embeddings.parquet # Step 2 output (filepath, embedding, + carried metadata)
├── mined.parquet # Step 3 output — unique mined source filepaths
├── mining_summary.txt # Auto-emitted next to mined.parquet by the container
├── mining_config/ # Auto-copied by hook
└── claude_session.jsonl # Auto-copied by hook
実行の開始時に、Bash で date +%Y-%m-%d_%H%M%S を実行して実際のタイムスタンプを取得します。ハードコードしたり、推測したりしないでください。ユーザーがカスタムの出力パスを指定した場合は、そのパスをそのまま使用しますが、内部のディレクトリ構成は同じにしてください。
検索した parquet は、後続の学習で使用する成果物です。2 つの埋め込み parquet は中間生成物ですが、保持しておく価値があります。同じソースプールに対する複数回の検索で再利用でき、「無関係に見える」という報告があった場合にエンコーダーレベルでデバッグするための唯一の手掛かりとなるためです。
よくある問題
出力が使いものにならなくなる最も一般的な原因は、エンコーダーの不一致です。両方の埋め込みステップで同じ embedding_spec.yaml を使用し、model/model_path/batch_size のオーバーライドは、両方のステップに適用するか、どちらにも適用しないでください。そのほかによくある問題として、埋め込みステップのスキップ、filter_by_label=true のときに label 列がない(警告なしで何も行われない)、$WORKSPACE の外にある仕様ファイル、未解決の ??? センチネル、model_config_path のない TAO チェックポイント、parquet に変換されていない CSV プール、ホストとコンテナ間のパスの不一致、GPU がない、誤ったイメージタグ、topn × N_targets がソース数を超えている(想定どおりであり、バグではありません。実際に検索された件数を報告してください)などがあります。
これらの問題それぞれの詳しい診断と修正方法については、references/troubleshooting.md を参照してください。
レポート構成
レポートは簡潔にまとめてください(600~1200 語)。検索は決定論的なパイプラインです。重要なのは、説明を書くことではなく、エンコーダーの選択、行数、警告なしでフィルタリングが行われなかったケースを監査できるようにすることです。レポートは「判定」「入力」「エンコーダーの整合性」「検索の実行」「ラベルごとの内訳(ターゲット parquet に label 列がない場合は省略)」「出力の健全性」「推奨アクション」の 7 セクションで構成されます。
各セクションとフィールドを網羅した、記入用の完全なレポートテンプレートについては、references/reporting_spec.md を参照してください。
実行順序
versions.yamlのimages.tao_toolkit.data_servicesからDS_IMAGEを解決し、次にdocker info、nvidia-smi、docker image inspect "$DS_IMAGE"を一度実行して環境を確認します。イメージがない場合はプルします。いずれかが失敗した場合は、明確なメッセージを表示して中止します。date +%Y-%m-%d_%H%M%Sを実行してタイムスタンプを取得し、<output_dir>/mining_results/<timestamp>/を作成します。- タイムスタンプ付きディレクトリに
embedding_spec.yamlとmining_spec.yamlを書き込み、エンコーダーの選択とマイニングの設定値を記入します。-eのパスがコンテナ内で解決されるよう、これらのファイルは$WORKSPACEの配下に置きます。 - ソースプールが CSV の場合は、先に parquet に変換します(
filepathとlabelは保持します)。 - Step 1(ターゲットの埋め込み)を
docker run … embedding image_embeddings -e embedding_spec.yaml input_parquet=… output_parquet=…で実行します。出力 parquet の行数と列を標準出力に表示します。 - Step 1 と同一の
embedding_spec.yamlを使用して Step 2(ソースプールの埋め込み)を実行します。出力の行数と列を表示します。 - Step 3(最近傍のマイニング)を
docker run … tmm nearest_neighbors -e mining_spec.yaml source_parquet=… target_parquet=… output_parquet=…で実行します。mining_summary.txtがmined.parquetの隣に書き込まれたことを確認します。 - target embeddings parquet とマイニング出力を filepath で結合し、両方に
labelがある場合は、ラベルごとの内訳(Section 5)を計算します。 - 最後に
Mining_Report.mdを書き込みます。これによりパッケージングフックが実行され、セッションログとスキル設定が一緒にコピーされます。