opção
LarLar Skill Ciência de dados e ML tao-analyze-gaps-visual-changenet

tao-analyze-gaps-visual-changenet

NVIDIA/skills NVIDIA/skills

Identifica as amostras mais fracas por rótulo de referência nas experiências do NVIDIA TAO VCN Classify, executando um contêiner Docker que realiza varredura de limiares, pontuação de fragilidade e expansão por condição de iluminação; em seguida, apresenta as K principais amostras fracas para aumento de dados ou reclassificação em etapas posteriores.

...Expandir tudo
2
Tempo atualizado 28 de Setembro de 2026

Análise de lacunas do TAO VCN Classify

Você é analista dos resultados de inferência do NVIDIA TAO VCN Classify (Visual Component Net). Sua função é identificar as amostras mais fracas por rótulo de referência, medindo a distância assinada do limiar de decisão na direção errada, para depois destacá-las para aumento ou reclassificação em etapas posteriores.

Esta habilidade é intencionalmente leve. O cabeçalho de classificação do VCN é um limite binário de pontuação única (PASS vs NO_PASS por siamese_score), portanto, a análise é computacional, não investigativa. Todo o cálculo ocorre por meio de uma única invocação direta do Docker contra a imagem `tao_toolkit.data_services ` declarada no arquivo ` versions.yaml ` (resolvida em tempo de execução — consulte Configuração). O ponto de entrada do contêiner aceita ` [substituições do Hydra...]`; passamos ` gap_analysis vcn_aoi key=value …`. Cada substituição é um simples par chave=valor do Hydra que substitui seletivamente o esquema GapAnalysisConfig do script (os padrões estão embutidos no contêiner; verifique com docker run ... gap_analysis vcn_aoi --cfg=job). (Não há a palavra-chave dataset dentro do contêiner — esse é o prefixo “pillar” do lançador TAO e é omitido aqui.) Você não precisa de análise delegada, auditorias de imagem em múltiplas fases ou agrupamento por tipo de componente — o VCN não expõe essas dimensões. Visualize apenas um pequeno conjunto de amostras fracas representativas para qualificar as lacunas após o retorno do contêiner.

A interface da CLI pode variar entre as compilações de contêineres de serviços de dados. Se uma invocação de `gap_analysis vcn_aoi ` falhar na análise de argumentos, examine o esquema real uma vez por imagem com ` docker run --rm "$DS_IMAGE" gap_analysis vcn_aoi --cfg=job e reconcilie quaisquer chaves renomeadas (por exemplo, inference_csv vs. inference_results_dir, output_dir vs. results_dir) antes de tentar novamente. O nome do arquivo Parquet de saída é kpi_gaps.parquet.

Entradas

  1. Diretório de resultados do experimento — contém o arquivo inference/inference.csv da inferência do TAO VCN Classify. Colunas obrigatórias: input_path, object_name, label, siamese_score. Passe o diretório (por exemplo, inference/latest/), e não o arquivo CSV — o contêiner lê o arquivo inference_results_dir/inference.csv.
  2. Diretório de código/configuração de treinamento — contém o arquivo YAML de treinamento do VCN. O contêiner lê dataset.classify.input_map (lista de condições de iluminação) e dataset.classify.image_ext a partir dele para expandir cada amostra fraca em uma linha por condição de iluminação.
  3. Diretório do conjunto de dados — a raiz da imagem é anexada ao caminho relativo input_path de cada linha (kpi_media_path).
  4. Substituições de esquema — min_recall, top_k_per_label e, opcionalmente, um limite fixo são passados como substituições do Hydra (padrões: min_recall=1,0, top_k_per_label=50, threshold=-1,0, o que significa varredura). top_k_per_label deve ser um número inteiro positivo — omitir esse parâmetro coloca o contêiner no modo “filtro abaixo do limiar”, o que, com min_recall=1,0, retorna apenas classificações errôneas do tipo PASS e zero linhas do tipo NO_PASS. Consulte Armadilhas comuns.

Configuração

A varredura de limiar, a classificação de vulnerabilidades e a expansão por iluminação são executadas dentro da imagem tao_toolkit.data_services declarada no arquivo versions.yaml. Resolva a URI específica uma vez no início da execução; em seguida, confirme se o Docker, o kit de ferramentas de contêineres da NVIDIA e uma GPU estão presentes e certifique-se de que a imagem esteja armazenada em cache:

# Resolver tao_toolkit.data_services → URI concreta nvcr.io/... a partir do arquivo 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 geralmente é exportado pelo banco de habilidades instalado. Se não estiver definido, aponte-o para a raiz do repositório do banco de habilidades antes da resolução. É necessária uma GPU; interromper o processo logo no início em um host sem GPU evita um erro confuso mais tarde.

Três regras de configuração são fundamentais e fáceis de errar:

  • Montagem de caminho — todos os caminhos do host que o contêiner lê ou grava (inference.csv, YAML de treinamento, raiz da imagem do conjunto de dados, diretório de saída) devem ser montados por bind, o que é mais simples com -v $WORKSPACE:$WORKSPACE -w $WORKSPACE, para que os caminhos absolutos sejam resolvidos de forma idêntica em ambos os lados.
  • Não passe --user $(id -u):$(id -g) — isso aciona o erro KeyError: 'getpwuid(): uid not found: ' durante a importação dos transformadores pelo contêiner; em vez disso, o chown retorna o UID do host posteriormente.
  • -e é obrigatório, não opcional — as imagens atuais exigem isso e encerram com ValueError: A subtarefa vcn_aoi requer o seguinte argumento: -e/--experiment_spec_file antes de analisar as substituições da CLI.

Consulte references/container-setup.md para obter o padrão completo de montagem de caminhos, a justificativa para--user/chown e o comando chown do Alpine, orientações sobre o uso de múltiplos --v e detalhes sobre a exigência de -e .

Método

Toda a tarefa consiste em uma única invocação do `docker run`, seguida por uma breve verificação visual pontual. O contêiner executa as etapas 1 a 4 internamente (varredura de limiares, pontuação de vulnerabilidades, seleção dos K principais, expansão por iluminação). Você realiza a etapa 5 (verificação visual pontual) diretamente com a ferramenta Read.

Etapas 1 a 4 — Execute o contêiner

$DOCKER gap_analysis vcn_aoi \
    inference_results_dir=/inference/

Sempre passe o parâmetro top_k_per_label. Esse é o argumento que muda o contêiner do filtro padrão “amostras abaixo do limite” para o ranking adequado top-K-per-label . Com min_recall=1.0, o limiar é, por definição, igual ou inferior a todas as pontuações NO_PASS; portanto, o filtro “abaixo do limiar” retorna APENAS linhas PASS classificadas incorretamente e zero linhas NO_PASS — o que é inútil como fila de aumento. Com top_k_per_label definido como um número inteiro positivo (seja na especificação ou como uma substituição do Hydra), o contêiner calcula a fraqueza assinada em relação ao limiar para cada linha e apresenta as K mais fracas por rótulo de verdade fundamental, que é a saída classificada por rótulo consumida pelas etapas posteriores.

Lê o arquivo inference.csv, varre todos os valores únicos de siamese_score mais um valor logo abaixo do mínimo, mantém os candidatos com recall da classe NO_PASS ≥ min_recall (com tolerância de 1e-12 ) e, em seguida, seleciona o limiar com o melhor F1 (desempate: precisão e, em seguida, valor do limiar). Para cada linha, calcula a fraqueza assinada a partir desse limiar (positiva = classificação incorreta, negativa = correta, magnitude = margem). Classifica por fraqueza em ordem decrescente e seleciona os top_k_per_label principais por rótulo de referência; em seguida, expande cada linha fraca em uma linha por condição de iluminação usando dataset.classify.input_map e dataset.classify.image_ext do YAML de treinamento.

Se nenhum limiar candidato atender à meta de recall, o contêiner sai com valor diferente de zero e grava o arquivo unreachable_kpi.txt no diretório results_dir, explicando qual recall o modelo pode realmente atingir. Nesse caso, interrompa a análise após a chamada do Docker, redija um relatório de uma seção explicando que o modelo é fundamentalmente incapaz de atingir o KPI em qualquer ponto de operação e recomende retreinamento ou reetiquetamento — pule a verificação visual aleatória.

O contêiner grava no diretório results_dir:

Artefato Conteúdo
kpi_gaps.parquet Os Top-K mais fracos por rótulo, expandidos por iluminação. Colunas: filepath, label, siamese_score, weakness.
threshold.txt Limite de decisão escolhido (único valor de tipo float, texto simples).
metrics.json No limiar escolhido: precisão, recall, f1, matriz de confusão {tp, fp, tn, fn}, além de, por rótulo , {total, média_de_fraqueza, mediana_de_fraqueza, máxima_de_fraqueza, n_de_classificações_erradas}.
weak_samples_breakdown.txt Discriminação das linhas mantidas por rótulo: total, <%> de todas as linhas mantidas, N classificadas incorretamente (fraqueza > 0), N marginais (fraqueza ≤ 0).
unreachable_kpi.txt Somente gravado quando a meta de recall é inatingível. A presença deste arquivo significa: pular a Etapa 5, gerar o relatório resumido, recomendar retreinamento.

Imprima o resumo da saída padrão do contêiner (limite escolhido, contagem de linhas mantidas, detalhamento por rótulo) na sua própria saída padrão para que o gancho de verificação do script possa verificar a saída gerada pela execução.

Etapa 5 — Verificação visual pontual (pequena, fixa)

Pule esta etapa se o arquivo unreachable_kpi.txt existir. Caso contrário, use a ferramenta Read para visualizar as 5 amostras PASS mais fracas e as 5 amostras NO_PASS mais fracas do arquivo kpi_gaps.parquet (deduplicadas para uma linha por amostra, usando o caminho de arquivo FIRST-lighting), classifique cada uma como exatamente uma das seguintes categorias: rotulagem incorreta / caso limite / qualidade dos dados / sistemática e copie cada imagem visualizada (redimensionada para 128×128 se o PIL estiver disponível; caso contrário, basta copiar) para /rca_images/. Essa é a única inspeção de imagens necessária — não visualize dezenas de imagens, não execute agrupamento por modo de falha nem audite imagens de referência (o VCN não possui imagens de referência).

Consulte references/visual-spot-check.md para obter a ordem exata de seleção de amostras, a regra de deduplicação por iluminação, a definição completa de cada categoria de veredicto e os detalhes da cópia de imagens.

Chamada da referência

Cole e edite o espaço de trabalho, os quatro caminhos e os dois parâmetros numéricos; isso executa o processo de ponta a ponta. Capture a saída padrão (stdout) para que o gancho de verificação de script veja as contagens de linhas.

WORKSPACE=           # montado de forma idêntica dentro do contêiner
EXP_DIR=     # contém inference/inference.csv e train.yaml; deve estar dentro de $WORKSPACE
DATASET_ROOT=         # raiz das imagens para as entradas do caminho de entrada do arquivo inference.csv; deve estar dentro de $WORKSPACE
MIN_RECALL=1.0                       # padrão de zero erros; reduza se o KPI for menos rigoroso
TOP_K=50                             # orçamento de aumento por rótulo
OUT="$EXP_DIR/rca_results/$(date +%Y-%m-%d_%H%M%S)"
SPEC="$OUT/vcn_aoi_spec.yaml"
IMG=$(python3 -c "import yaml,os; print(yaml.safe_load(open(os.environ['TAO_SKILL_BANK_PATH']+'/versions.yaml'))['images']['tao_toolkit']['data_services'])")

mkdir -p "$OUT"

# Grave a especificação da análise de lacunas para esta execução
cat > "$SPEC" <<EOF
min_recall: $MIN_RECALL
top_k_per_label: $TOP_K
EOF

docker run --gpus all --rm --ipc=host \
    -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"

# O contêiner grava como root com a opção --user desativada; reatribua a propriedade ao UID do host, se necessário.
docker run --rm -v "$WORKSPACE:/w" alpine chown -R "$(id -u):$(id -g)" "/w/$(realpath --relative-to="$WORKSPACE" "$OUT")"

# Saída de verificação para que o hook de verificação de script veja valores reais
python3 - "$OUT" << 'PYEOF'
import json, os, sys
out = sys.argv[1]
unreachable = os.path.join(out, "unreachable_kpi.txt")
if os.path.isfile(unreachable):
    print("KPI INACESSÍVEL — consulte", unreachable)
    sys.exit(0)
with open(os.path.join(out, "threshold.txt")) as f:
    print("limite:", f.read().strip())
with open(os.path.join(out, "metrics.json")) as f:
    m = json.load(f)
print(f"precision={m['precision']:.4f} recall={m['recall']:.4f} f1={m['f1']:.4f}")
import pandas as pd
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

Saídas

Grave tudo em uma pasta com data e hora no diretório de resultados do experimento. As saídas do contêiner vão diretamente para lá; a verificação visual grava em rca_images/; qualquer gancho de empacotamento em tempo de execução pode adicionar artefatos de captura de sessão/configuração após o arquivo RCA_Report.md ser gravado.

/rca_results/AAAA-MM-DD_HHMMSS/
├── RCA_Report.md              # Relatório completo de análise de lacunas (você o escreve)
├── kpi_gaps.parquet           # Contêiner: os K mais fracos por rótulo, expandidos por iluminação
├── threshold.txt              # Contêiner: limiar de decisão escolhido (único número real)
├── metrics.json               # Contêiner: matriz de confusão + estatísticas de distribuição por rótulo
├── weak_samples_breakdown.txt # Contêiner: contagem por rótulo / amostras mal classificadas / contagens marginais
├── unreachable_kpi.txt        # Contêiner: SOMENTE quando nenhum limiar atinge o min_recall
├── rca_images/                # Você: miniaturas das 10 amostras fracas visualizadas
├── rca_config/                # Copiado automaticamente pelo hook
└── session log/artifacts      # Opcional, captura de pacotes dependente do tempo de execução

No início da execução, obtenha o carimbo de data/hora real executando ` date +%Y-%m-%d_%H%M%S ` no Bash. NÃO codifique manualmente nem adivinhe. Se o usuário especificar um caminho de saída personalizado, use-o, mas mantenha a mesma estrutura interna.

Armadilhas comuns

O modo de falha de maior consequência é esquecer o `top_k_per_label` quando` min_recall=1.0`: nessa taxa de recall, o limiar escolhido fica igual ou abaixo de todas as pontuações NO_PASS; portanto, sem top_k_per_label, o contêiner recorre a um filtro de “amostras abaixo do limiar” que retorna APENAS linhas PASS classificadas incorretamente e zero linhas NO_PASS, interrompendo a fila de aumento. Sempre inclua um top_k_per_label positivo explícito (padrão 50) na especificação ou como uma substituição do Hydra.

Consulte references/pitfalls.md para obter a lista de verificação completa, que abrange: esquecimento do `top_k_per_label`; passar o parâmetro `--user`; chamar apenas com substituições do Hydra (sem `-e `); arquivo de especificação fora do `$WORKSPACE`; arquivo de especificação com sentinelas `???` não resolvidas; imagem não baixada / tag incorreta; incompatibilidade de caminho de montagem; arquivo unreachable_kpi.txt gravado; arquivo inference.csv sem as colunas obrigatórias; YAML de treinamento sem dataset.classify.input_map ou image_ext; kpi_media_path não correspondendo aos prefixos de input_path; e nenhuma GPU detectada de dentro do contêiner.

Estrutura do Relatório

Escreva o arquivo RCA_Report.md como uma análise computacional concisa (1.000–1.800 palavras) das lacunas — a profundidade vem de números precisos e de uma lista clara de ações, não de narrativa. O modelo completo do relatório (7 seções: Veredicto, Seleção de Limiares, Distribuição de Pontos Fracos, Amostras Mais Fracas Top-K, Verificação Visual Pontual, Discriminação por Rótulo, Ações Recomendadas — com a matriz de confusão e os layouts das tabelas) está em references/output-template.md. Quando o arquivo unreachable_kpi.txt existir, substitua as seções 3 a 6 por uma única seção curta citando o conteúdo desse arquivo e resuma a seção 7 a uma única recomendação: retreinar ou reclassificar.

Ordem de execução

  1. Resolva DS_IMAGE a partir do arquivo versions.yaml (images.tao_toolkit.data_services); em seguida, execute docker info, nvidia-smi e docker image inspect "$DS_IMAGE" (baixando a imagem caso esteja ausente) uma vez para confirmar o ambiente. Aborta com uma mensagem clara se houver alguma falha.
  2. Execute ` date +%Y-%m-%d_%H%M%S ` para obter o carimbo de data/hora; crie ` /rca_results/` e `/`.
  3. Grave o arquivo `vcn_aoi_spec.yaml` no diretório com o carimbo de data/hora, preenchendo os campos ` min_recall ` e `top_k_per_label`. Mantenha-o no diretório `$WORKSPACE` para que o caminho `-e ` seja resolvido dentro do contêiner.
  4. Execute docker run … "$DS_IMAGE" gap_analysis vcn_aoi -e vcn_aoi_spec.yaml inference_results_dir=… train_config=… kpi_media_path=… output_dir=…. O contêiner grava os arquivos kpi_gaps.parquet, threshold.txt, metrics.json e weak_samples_breakdown.txt no diretório results_dir. Imprima o limiar escolhido e as contagens de linhas mantidas na saída padrão (stdout) para que o gancho de verificação do script possa conferir a saída gerada pela execução.
  5. Se o arquivo unreachable_kpi.txt existir, pule a Etapa 6 e gere o relatório resumido. Caso contrário, continue.
  6. Selecione 10 amostras fracas (as 5 mais fracas com PASS + as 5 mais fracas com NO_PASS) do arquivo kpi_gaps.parquet, visualize cada imagem de teste com o comando Read, classifique-as e copie cada uma para a pasta rca_images/.
  7. Grave o RCA_Report.md por último — gravá-lo aciona o gancho de empacotamento, que copia os logs da sessão e a configuração da habilidade junto com ele.
Ver no GitHub
---
name: tao-analyze-gaps-visual-changenet
description: Identifies the weakest samples per ground-truth label in NVIDIA TAO VCN Classify experiments by running a Docker container that performs threshold sweep, weakness scoring, and per-lighting expansion, then surfaces top-K weak samples for downstream augmentation or relabeling.
license: Apache-2.0
---

# 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 `siamese_score`), so the analysis is computational, not investigative. The whole computation lives behind one direct `docker run` invocation against the `tao_toolkit.data_services` image declared in `versions.yaml` (resolved at runtime — see Setup). The container's entrypoint takes `<category> <action> [hydra overrides...]`; we pass `gap_analysis vcn_aoi key=value …`. Each override is a bare Hydra `key=value` that selectively overrides the script's `GapAnalysisConfig` schema (defaults are baked into the container; introspect with `docker run ... gap_analysis vcn_aoi --cfg=job`). (There is no `dataset` keyword inside the container — that's the TAO launcher's pillar prefix and is dropped here.) You do **not** need delegated analysis, 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.

CLI surface can shift between data-services container builds. If a `gap_analysis vcn_aoi` invocation fails on argument parsing, introspect the actual schema once per image with `docker run --rm "$DS_IMAGE" gap_analysis vcn_aoi --cfg=job` and reconcile any renamed keys (e.g. `inference_csv` vs `inference_results_dir`, `output_dir` vs `results_dir`) before retrying. Output parquet name is `kpi_gaps.parquet`.

---

## Inputs

1. **Experiment result directory** — contains `inference/inference.csv` from TAO VCN Classify inference. Required columns: `input_path`, `object_name`, `label`, `siamese_score`. Pass the **directory** (e.g. `inference/latest/`), not the CSV file — the container reads `inference_results_dir/inference.csv`.
2. **Training code/config directory** — contains the VCN train YAML. The container reads `dataset.classify.input_map` (lighting condition list) and `dataset.classify.image_ext` from it to expand each weak sample into one row per lighting.
3. **Dataset directory** — image root prepended to the relative `input_path` from each row (`kpi_media_path`).
4. **Schema overrides** — `min_recall`, `top_k_per_label`, and optionally a hard-pinned `threshold` are passed as Hydra overrides (defaults: `min_recall=1.0`, `top_k_per_label=50`, `threshold=-1.0` meaning sweep). **`top_k_per_label` must be a positive integer** — omitting it flips the container into "below-threshold filter" mode, which at `min_recall=1.0` returns only PASS misclassifications and zero NO_PASS rows. See Common pitfalls.

---

## Setup

The threshold sweep, weakness ranking, and per-lighting expansion all run inside the `tao_toolkit.data_services` image declared in `versions.yaml`. 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:

```bash
# 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` is usually exported by the installed skill bank. If it is unset, point it at the skill-bank repo root before resolving. A GPU is required; aborting early on a GPU-less host saves a confusing late error.

Three setup rules are load-bearing and easy to get wrong:

- **Path mounting** — every host path the container reads or writes (`inference.csv`, train YAML, dataset image root, output dir) must be bind-mounted, simplest with `-v $WORKSPACE:$WORKSPACE -w $WORKSPACE` so absolute paths resolve identically on both sides.
- **Do not pass `--user $(id -u):$(id -g)`** — it triggers `KeyError: 'getpwuid(): uid not found: <uid>'` during the container's `transformers` import; `chown` outputs back to the host UID afterwards instead.
- **`-e <spec>` is required, not optional** — current images hard-require it and exit with `ValueError: The subtask vcn_aoi requires the following argument: -e/--experiment_spec_file` before parsing CLI overrides.

See `references/container-setup.md` for the full path-mounting pattern, the `--user`/`chown` rationale and `alpine` chown command, multi-`-v` guidance, and the `-e <spec>` requirement detail.

---

## Method

The whole skill is a single `docker run` 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.

### Step 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=50
```

> **Always pass `top_k_per_label`.** This is the argument that switches the container
> from the default "samples below threshold" filter into proper top-K-per-label
> ranking. At `min_recall=1.0` the 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. With `top_k_per_label`
> set 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.

Reads `inference.csv`, sweeps every unique `siamese_score` plus one value just below the minimum, keeps the candidates with NO_PASS-class recall ≥ `min_recall` (with `1e-12` tolerance), then picks the threshold with the best F1 (tie-break: precision, then threshold value). For every row, computes signed weakness from that threshold (positive = misclassified, negative = correct, magnitude = margin). Sorts by weakness descending and takes the top `top_k_per_label` per ground-truth label, then expands each weak row into one row per lighting condition using `dataset.classify.input_map` and `dataset.classify.image_ext` from the train YAML.

If **no** candidate threshold meets the recall target, the container exits non-zero and writes `unreachable_kpi.txt` into `results_dir` 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.

**Container writes into `results_dir`:**

| Artifact | Contents |
|----------|----------|
| `kpi_gaps.parquet` | Top-K weakest per label, expanded per lighting. Columns: `filepath`, `label`, `siamese_score`, `weakness`. |
| `threshold.txt` | Chosen decision threshold (single float, plain text). |
| `metrics.json` | At the chosen threshold: `precision`, `recall`, `f1`, confusion matrix `{tp, fp, tn, fn}`, plus per-label `{total, mean_weakness, median_weakness, max_weakness, n_misclassified}`. |
| `weak_samples_breakdown.txt` | Per-label kept-row breakdown: `<count>` total, `<%>` of all kept rows, `N` misclassified (weakness > 0), `N` marginal (weakness ≤ 0). |
| `unreachable_kpi.txt` | Only written when the recall target is unreachable. Presence of this file means: skip Step 5, write the abridged report, recommend retrain. |

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.

### Step 5 — Visual spot check (small, fixed)

Skip this step if `unreachable_kpi.txt` exists. Otherwise use the Read tool to **view** the 5 weakest PASS samples and the 5 weakest NO_PASS samples from `kpi_gaps.parquet` (deduplicated to one row per sample, using the FIRST-lighting `filepath`), classify each as exactly one of **mislabeled** / **edge case** / **data quality** / **systematic**, and copy each viewed image (resized to 128×128 if PIL is available, otherwise just copy) into `<results_dir>/rca_images/`. This is the only image inspection required — do not view dozens of images, run failure mode clustering, or audit goldens (VCN has no golden images).

See `references/visual-spot-check.md` for the exact sample-selection sort, the per-lighting deduplication rule, the full definition of each verdict category, and the image-copy detail.

---

## Reference invocation

Paste-and-edit the workspace, the four paths, and the two numeric knobs; this runs end-to-end. Capture stdout so the script-check hook sees row counts.

```bash
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=$(python3 -c "import yaml,os; print(yaml.safe_load(open(os.environ['TAO_SKILL_BANK_PATH']+'/versions.yaml'))['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 --ipc=host \
    -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
python3 - "$OUT" << 'PYEOF'
import json, os, sys
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:
    print("threshold:", f.read().strip())
with open(os.path.join(out, "metrics.json")) as f:
    m = json.load(f)
print(f"precision={m['precision']:.4f} recall={m['recall']:.4f} f1={m['f1']:.4f}")
import pandas as pd
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
```

---

## Outputs

Write everything into a timestamped folder under the experiment result directory. The container's outputs go straight there; the visual spot-check writes `rca_images/`; any runtime packaging hook may add session/config capture artifacts after `RCA_Report.md` is written.

```
<experiment_result_dir>/rca_results/YYYY-MM-DD_HHMMSS/
├── RCA_Report.md              # Full gap analysis report (you write this)
├── kpi_gaps.parquet           # Container: top-K weakest per label, expanded per lighting
├── threshold.txt              # Container: chosen decision threshold (single float)
├── metrics.json               # Container: confusion matrix + per-label distribution stats
├── weak_samples_breakdown.txt # Container: per-label count/misclassified/marginal counts
├── unreachable_kpi.txt        # Container: ONLY when no threshold meets min_recall
├── rca_images/                # You: thumbnails of the 10 viewed weak samples
├── rca_config/                # Auto-copied by hook
└── session log/artifacts      # Optional, runtime-dependent packaging capture
```

At the start of the run, get the real timestamp by running `date +%Y-%m-%d_%H%M%S` in Bash. Do NOT hardcode or guess. If the user specifies a custom output path, use that instead but maintain the same internal structure.

---

## Common pitfalls

The single most consequential failure mode is **forgetting `top_k_per_label` when `min_recall=1.0`**: at that recall the chosen threshold sits at or below every NO_PASS score, so without `top_k_per_label` the container falls back to a "samples below threshold" filter that returns ONLY misclassified PASS rows and zero NO_PASS rows, breaking the augmentation queue. Always include an explicit positive `top_k_per_label` (default 50) in the spec or as a Hydra override.

See `references/pitfalls.md` for the complete checklist, covering: forgetting `top_k_per_label`; passing `--user`; calling with only Hydra overrides (no `-e <spec>`); spec file outside `$WORKSPACE`; spec file with unresolved `???` sentinels; image not pulled / wrong tag; path-mount mismatch; `unreachable_kpi.txt` written; `inference.csv` missing required columns; train YAML missing `dataset.classify.input_map` or `image_ext`; `kpi_media_path` not matching `input_path` prefixes; and no GPU detected from inside the container.

---

## Report Structure

Write `RCA_Report.md` as a tight (1000–1800 word) computational gap analysis — depth comes from accurate numbers and a clear action list, not narrative. The full report template (7 sections: Verdict, Threshold Selection, Weakness Distribution, Top-K Weakest Samples, Visual Spot Check, Per-Label Breakdown, Recommended Actions — with the confusion-matrix and table layouts) is in `references/output-template.md`. When `unreachable_kpi.txt` exists, replace sections 3–6 with a single short section quoting that file's contents and collapse section 7 to one recommendation: retrain or relabel.

---

## Execution Order

1. Resolve `DS_IMAGE` from `versions.yaml` (`images.tao_toolkit.data_services`), then run `docker info`, `nvidia-smi`, and `docker image inspect "$DS_IMAGE"` (pulling if missing) once to confirm the environment. Abort with a clear message if any fail.
2. Run `date +%Y-%m-%d_%H%M%S` to get the timestamp; create `<experiment_result_dir>/rca_results/<timestamp>/`.
3. Write `vcn_aoi_spec.yaml` into the timestamped dir with `min_recall` and `top_k_per_label` filled in. Keep it under `$WORKSPACE` so the `-e` path resolves inside the container.
4. Run `docker run … "$DS_IMAGE" gap_analysis vcn_aoi -e vcn_aoi_spec.yaml inference_results_dir=… train_config=… kpi_media_path=… output_dir=…`. The container writes `kpi_gaps.parquet`, `threshold.txt`, `metrics.json`, `weak_samples_breakdown.txt` into `results_dir`. Print the chosen threshold and kept-row counts to stdout so the script-check hook can verify the run produced output.
5. If `unreachable_kpi.txt` exists, skip Step 6 and write the abridged report. Otherwise continue.
6. Pick 10 weak samples (5 weakest PASS + 5 weakest NO_PASS) from `kpi_gaps.parquet`, view each test image with Read, classify, and copy each into `rca_images/`.
7. Write `RCA_Report.md` last — writing it triggers the packaging hook, which copies session logs and skill config alongside.

Todos os arquivos

1 arquivos

Instalar tao-analyze-gaps-visual-changenet

Baixe e extraia os arquivos de habilidades para o diretório .claude/skills/.

Baixar ZIP

Clone o repositório e copie os arquivos da habilidade para o seu projeto.

git clone https://github.com/NVIDIA/skills/tree/main/skills/tao-analyze-gaps-visual-changenet # Copy SKILL.md to your .claude/skills/ directory

Copiar Copiar
Configuração rápida: Copie a pasta da habilidade para .claude/skills/ O Claude detectará e utilizará automaticamente a habilidade
Repositório NVIDIA/skills

Habilidades relacionadas

web-search
Tempo atualizado 29 de Junho de 2026
webapp-testing
Tempo atualizado 29 de Junho de 2026
lark-base
Tempo atualizado 5 de Julho de 2026
agentmail
Tempo atualizado 29 de Junho de 2026
OR