tao-analyze-gaps-visual-changenet
Original:🇺🇸 English
Translated
6 scripts
Performs gap analysis on NVIDIA TAO Visual ChangeNet (VCN) Classify experiments by invoking the data-services container (`tao_toolkit.data_services` from `versions.yaml`) directly via `docker run … gap_analysis vcn_aoi …` — picks the optimal decision threshold, ranks per-sample weakness, and emits a top-K weakest parquet expanded per-lighting for downstream augmentation. Use when analyzing VCN classification failures, picking SDA augmentation targets, auditing PASS/NO_PASS boundary cases, or running DEFT gap analysis on an AOI ChangeNet model.
7installs
Added on
NPX Install
npx skill4agent add promptingcompany/nv-skills tao-analyze-gaps-visual-changenetTags
Translated version includes tags in frontmatterSKILL.md Content
View Translation Comparison →TAO VCN Classify Gap Analysis Skill
You are an analyst for NVIDIA TAO VCN Classify (Visual Component Net) inference results. Your job is to identify the weakest samples per ground-truth label by measuring signed distance from the decision threshold in the wrong direction, then surface them for downstream augmentation or relabeling.
This skill is intentionally lightweight. VCN's classify head is a single-score binary boundary (PASS vs NO_PASS by ), so the analysis is computational, not investigative. The whole computation lives behind one direct invocation against the image declared in (resolved at runtime — see Setup). The container's entrypoint takes ; we pass . You do not need subagents, multi-phase image audits, or component-type clustering — VCN does not expose those dimensions. View only a small set of representative weak samples to qualify the gaps after the container returns.
siamese_scoredocker runtao_toolkit.data_servicesversions.yaml<category> <action> [hydra overrides...]gap_analysis vcn_aoi key=value …The CLI surface can shift between data-services container builds. If a invocation fails on argument parsing, introspect the actual schema once per image with and reconcile any renamed keys before retrying. See for the key-rename reconciliation and the full pitfalls list. The output parquet name is .
gap_analysis vcn_aoidocker run --rm "$DS_IMAGE" gap_analysis vcn_aoi --cfg=jobreferences/troubleshooting.mdkpi_gaps.parquetInputs
- Experiment result directory — contains (required columns
inference/inference.csv,input_path,object_name,label). Pass the directory (e.g.siamese_score), not the CSV file.inference/latest/ - Training code/config directory — contains the VCN train YAML; the container reads and
dataset.classify.input_mapfor per-lighting expansion.dataset.classify.image_ext - Dataset directory — image root () prepended to each row's relative
kpi_media_path.input_path - Schema overrides — ,
min_recall, and optionally a hard-pinnedtop_k_per_label, passed as Hydra overrides (defaults:threshold,min_recall=1.0,top_k_per_label=50meaning sweep).threshold=-1.0must be a positive integer — omitting it flips the container into "below-threshold filter" mode, which attop_k_per_labelreturns only PASS misclassifications and zero NO_PASS rows.min_recall=1.0
See for the full input detail, the override semantics, and the per-default explanation.
references/parameters-and-artifacts.mdGapAnalysisConfigSetup
The threshold sweep, weakness ranking, and per-lighting expansion all run inside the image declared in . Resolve the concrete URI once at the top of the run, then confirm Docker, the NVIDIA container toolkit, and a GPU are present and ensure the image is cached:
tao_toolkit.data_servicesversions.yamlbash
# 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_PATHsession_startA GPU is required (the same image is used across the AOI loop and other actions assume CUDA is present). Aborting early on a GPU-less host saves a confusing late error.
Path mounting. Every host path the container reads or writes — , the train YAML, the dataset image root, and the output dir — must be bind-mounted. The simplest pattern is to mount the workspace root with identical paths inside and outside the container so absolute paths in args resolve the same on both sides:
inference.csvbash
WORKSPACE=<absolute path that contains inference.csv, train YAML, dataset images, and the output dir>
DOCKER="docker run --gpus all --rm --ipc=host --user $(id -u):$(id -g) -v $WORKSPACE:$WORKSPACE -w $WORKSPACE $DS_IMAGE"If , the train YAML, and the dataset images live in different roots, pass multiple flags — but every absolute path you pass in args must resolve inside the container.
inference.csv-vCLI overrides cover the common case. , , and optionally are passed as Hydra overrides on the command line; defaults baked into the container (, , to sweep) handle most runs. If the container also accepts a spec file via (verify with ), passing one is a convenience, not a requirement — override only what you need.
min_recalltop_k_per_labelthresholdmin_recall=1.0top_k_per_label=50threshold=-1.0-e <spec>--cfg=jobMethod
The whole skill is a single invocation followed by a small visual spot-check. The container does Steps 1–4 internally (threshold sweep, weakness scoring, top-K selection, per-lighting expansion). You handle Step 5 (visual spot-check) directly with the Read tool.
docker runStep 1–4 — Run the container
bash
$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=50Always pass. This is the argument that switches the container from the default "samples below threshold" filter into proper top-K-per-label ranking. Attop_k_per_labelthe threshold is by construction at-or-below every NO_PASS score, so the below-threshold filter returns ONLY misclassified PASS rows and zero NO_PASS rows — useless as an augmentation queue. Withmin_recall=1.0set to a positive integer (either in the spec or as a Hydra override), the container computes signed weakness against the threshold for every row and surfaces the K weakest per ground-truth label, which is the per-label ranked output downstream steps consume.top_k_per_label
The container sweeps every unique (plus one value just below the minimum), keeps candidates with NO_PASS recall ≥ (tolerance ), picks the best-F1 threshold (tie-break: precision, then threshold value), scores signed weakness per row, takes the top per ground-truth label, and expands each into one row per lighting. See for the exact computation, the override defaults, and the artifact table.
siamese_scoremin_recall1e-12top_k_per_labelreferences/parameters-and-artifacts.mdIf no candidate threshold meets the recall target, the container exits non-zero and writes into explaining which recall the model can actually achieve. In that case, stop the analysis after the docker call, write a one-section report explaining the model fundamentally cannot reach the KPI at any operating point, and recommend retraining or relabeling — skip the visual spot-check.
unreachable_kpi.txtresults_dirContainer writes into : (top-K weakest per label, expanded per lighting; columns , , , ), , , , and (only when the recall target is unreachable). See for the per-artifact contents. Print the container's stdout summary (chosen threshold, kept-row counts, per-label breakdown) to your own stdout so the script-check hook can verify the run produced output.
results_dirkpi_gaps.parquetfilepathlabelsiamese_scoreweaknessthreshold.txtmetrics.jsonweak_samples_breakdown.txtunreachable_kpi.txtreferences/parameters-and-artifacts.mdStep 5 — Visual spot check (small, fixed)
Skip this step if exists in — there is nothing meaningful to spot-check when the model can't reach the KPI at any threshold.
unreachable_kpi.txtresults_dirOtherwise, use the Read tool to view the test images for:
- The 5 weakest PASS samples (the top of the "PASS misclassified as NO_PASS" pile) — pick by sorting rows where
kpi_gaps.parquetbylabel == 'PASS'descending.weakness - The 5 weakest NO_PASS samples (the top of the "NO_PASS misclassified as PASS" pile) — same, with .
label != 'PASS'
kpi_gaps.parquetfilepathClassify each viewed sample as exactly one of:
- mislabeled — visual content disagrees with the CSV label
- edge case — genuinely ambiguous boundary case
- data quality — corrupted, dark, wrong crop, bad framing
- systematic — model has learned the wrong feature (the image looks "obviously PASS/NO_PASS" but the model disagrees)
Copy each viewed image (resized to 128×128 if PIL is available, otherwise just copy) into so it can be embedded inline in the report.
<results_dir>/rca_images/This is the only image inspection required. Do not view dozens of images, do not run failure mode clustering, do not audit goldens — VCN does not have golden images.
Reference invocation
The paste-and-edit end-to-end recipe (workspace, four paths, two numeric knobs, spec-file write, docker run, and the stdout sanity print that surfaces row counts for the script-check hook) lives in . Use it verbatim, editing only the workspace, paths, and knobs.
references/recipe.mdOutputs
Write everything into a timestamped folder under the experiment result directory: . The container's outputs (, , , , and when applicable) go straight there; the visual spot-check writes ; the packaging hook adds and automatically when is written. See for the full folder tree.
<experiment_result_dir>/rca_results/YYYY-MM-DD_HHMMSS/kpi_gaps.parquetthreshold.txtmetrics.jsonweak_samples_breakdown.txtunreachable_kpi.txtrca_images/rca_config/claude_session.jsonlRCA_Report.mdreferences/parameters-and-artifacts.mdAt the start of the run, get the real timestamp by running in Bash. Do NOT hardcode or guess. If the user specifies a custom output path, use that instead but maintain the same internal structure.
date +%Y-%m-%d_%H%M%SCommon pitfalls
The most consequential failure is forgetting when — at that recall the chosen threshold sits at or below every NO_PASS score, so the fallback below-threshold filter matches ONLY misclassified PASS rows and ends up with zero NO_PASS rows. Always include an explicit positive . The full pitfalls list (spec file outside , unresolved sentinels, wrong/unpulled image tag, path-mount mismatch, handling, missing columns, missing train-YAML keys, prefix mismatch, no GPU inside the container) and the CLI-drift reconciliation are in .
top_k_per_labelmin_recall=1.0kpi_gaps.parquettop_k_per_label$WORKSPACE???unreachable_kpi.txtinference.csvkpi_media_pathreferences/troubleshooting.mdReport Structure
Write the RCA report into the timestamped output folder. It is a 7-section computational gap analysis (Verdict, Threshold Selection, Weakness Distribution, Top-K Weakest Samples, Visual Spot Check, Per-Label Breakdown, Recommended Actions), 1000–1800 words, with the confusion-matrix and per-label tables filled from and the spot-check rows from . When exists, replace sections 3–6 with one short section quoting that file and collapse section 7 to a single retrain-or-relabel recommendation. See for the complete skeleton with every section heading, table layout, and the unreachable-KPI variant.
metrics.jsonkpi_gaps.parquetunreachable_kpi.txtreferences/rca-report-structure.mdExecution Order
- Resolve from
DS_IMAGE(versions.yaml), then runimages.tao_toolkit.data_services,docker info, andnvidia-smi(pulling if missing) once to confirm the environment. Abort with a clear message if any fail.docker image inspect "$DS_IMAGE" - Run to get the timestamp; create
date +%Y-%m-%d_%H%M%S.<experiment_result_dir>/rca_results/<timestamp>/ - Write into the timestamped dir with
vcn_aoi_spec.yamlandmin_recallfilled in. Keep it undertop_k_per_labelso the$WORKSPACEpath resolves inside the container.-e - Run . The container writes
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,metrics.jsonintoweak_samples_breakdown.txt. Print the chosen threshold and kept-row counts to stdout so the script-check hook can verify the run produced output.results_dir - If exists, skip Step 6 and write the abridged report. Otherwise continue.
unreachable_kpi.txt - Pick 10 weak samples (5 weakest PASS + 5 weakest NO_PASS) from , view each test image with Read, classify, and copy each into
kpi_gaps.parquet.rca_images/ - Write last — writing it triggers the packaging hook, which copies session logs and skill config alongside.
RCA_Report.md