tao-analyze-gaps-visual-changenet

Par nvidia · skills

Effectue une analyse des écarts sur les expériences NVIDIA TAO Visual ChangeNet (VCN) Classify en invoquant les data-services

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

Skill TAO VCN Classify Gap Analysis

Vous êtes analyste pour les résultats d'inférence NVIDIA TAO VCN Classify (Visual Component Net). Votre rôle est d'identifier les échantillons les plus faibles par étiquette ground-truth en mesurant la distance signée du seuil de décision dans la mauvaise direction, puis de les signaler pour augmentation ou réétiquetage en aval.

Ce skill est intentionnellement léger. La classify head de VCN est une frontière binaire à score unique (PASS vs NO_PASS par siamese_score), l'analyse est donc computationnelle, non investigative. L'intégralité du calcul s'exécute derrière un appel docker run direct contre l'image tao_toolkit.data_services déclarée dans versions.yaml (résolue à l'exécution — voir Setup). L'entrypoint du conteneur accepte <category> <action> [hydra overrides...]; on passe gap_analysis vcn_aoi key=value …. Vous n'avez pas besoin de sous-agents, d'audits d'images multi-phases, ou de clustering par type de composant — VCN n'expose pas ces dimensions. Visionnez seulement un petit ensemble d'échantillons faibles représentatifs pour qualifier les lacunes après le retour du conteneur.

La surface CLI peut changer entre les builds du conteneur data-services. Si un appel gap_analysis vcn_aoi échoue sur l'analyse d'arguments, introspectez le schéma réel une fois par image avec docker run --rm "$DS_IMAGE" gap_analysis vcn_aoi --cfg=job et réconciliez toute clé renommée avant de réessayer. Voir references/troubleshooting.md pour la réconciliation des renommages de clés et la liste complète des pièges. Le nom du fichier parquet de sortie est kpi_gaps.parquet.


Entrées

  1. Répertoire de résultats d'expérience — contient inference/inference.csv (colonnes obligatoires input_path, object_name, label, siamese_score). Passez le répertoire (par ex. inference/latest/), pas le fichier CSV.
  2. Répertoire de code/config d'entraînement — contient la YAML d'entraînement VCN; le conteneur lit dataset.classify.input_map et dataset.classify.image_ext pour l'expansion par éclairage.
  3. Répertoire de dataset — racine des images (kpi_media_path) ajoutée en préfixe au input_path relatif de chaque ligne.
  4. Overrides de schémamin_recall, top_k_per_label, et optionnellement un threshold épinglé dur, passés comme overrides Hydra (défauts: min_recall=1.0, top_k_per_label=50, threshold=-1.0 signifiant sweep). top_k_per_label doit être un entier positif — l'omettre bascule le conteneur en mode « filtre below-threshold », qui à min_recall=1.0 retourne uniquement les mauvaises classifications PASS et zéro lignes NO_PASS.

Voir references/parameters-and-artifacts.md pour le détail complet des entrées, la sémantique override GapAnalysisConfig, et l'explication par défaut.


Setup

Le sweep de seuil, le classement de faiblesse, et l'expansion par éclairage s'exécutent tous dans l'image tao_toolkit.data_services déclarée dans versions.yaml. Résolvez l'URI concret une fois au début du run, puis confirmez Docker, le toolkit NVIDIA container, et la présence d'une GPU, et assurez-vous que l'image est en cache:

# Résoudre tao_toolkit.data_services → URI concret nvcr.io/... depuis 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 est exporté par le hook session_start du plugin. S'il n'est pas défini (par ex. en exécution hors du plugin Claude Code), pointez-le sur la racine du repo skill-bank avant la résolution.

Une GPU est requise (la même image est utilisée dans la boucle AOI et les autres actions supposent que CUDA est présent). Arrêter tôt sur un host sans GPU évite une erreur confuse tardive.

Montage de chemins. Chaque chemin host que le conteneur lit ou écrit — inference.csv, la YAML d'entraînement, la racine des images du dataset, et le répertoire de sortie — doit être bind-monté. Le motif le plus simple est de monter la racine du workspace avec des chemins identiques à l'intérieur et à l'extérieur du conteneur pour que les chemins absolus dans les args se résolvent identiquement des deux côtés:

WORKSPACE=<chemin absolu contenant inference.csv, train YAML, images du dataset, et le répertoire de sortie>
DOCKER="docker run --gpus all --rm --ipc=host --user $(id -u):$(id -g) -v $WORKSPACE:$WORKSPACE -w $WORKSPACE $DS_IMAGE"

Si inference.csv, la YAML d'entraînement, et les images du dataset vivent dans des racines différentes, passez plusieurs flags -v — mais chaque chemin absolu que vous passez dans les args doit se résoudre à l'intérieur du conteneur.

Les overrides CLI couvrent le cas courant. min_recall, top_k_per_label, et optionnellement threshold sont passés comme overrides Hydra en ligne de commande; les défauts intégrés au conteneur (min_recall=1.0, top_k_per_label=50, threshold=-1.0 pour sweep) gèrent la plupart des runs. Si le conteneur accepte aussi un fichier spec via -e <spec> (vérifier avec --cfg=job), en passer un est une commodité, pas une obligation — overridez seulement ce que vous avez besoin.


Méthode

Le skill entier est un appel docker run unique suivi d'une petite vérification visuelle. Le conteneur exécute les étapes 1–4 en interne (sweep de seuil, scoring de faiblesse, sélection top-K, expansion par éclairage). Vous gérez l'étape 5 (vérification visuelle spot-check) directement avec l'outil Read.

Étapes 1–4 — Exécuter le conteneur

$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

Toujours passer top_k_per_label. C'est l'argument qui bascule le conteneur du filtre par défaut « samples below threshold » vers un classement top-K-per-label approprié. À min_recall=1.0 le seuil est par construction à ou sous chaque score NO_PASS, donc le filtre below-threshold retourne UNIQUEMENT les lignes PASS mal classifiées et zéro lignes NO_PASS — inutile comme queue d'augmentation. Avec top_k_per_label défini à un entier positif (soit dans la spec soit comme override Hydra), le conteneur calcule la faiblesse signée contre le seuil pour chaque ligne et surface les K plus faibles par étiquette ground-truth, ce qui est la sortie classée par label que les étapes aval consomment.

Le conteneur balaie chaque siamese_score unique (plus une valeur juste sous le minimum), garde les candidats avec NO_PASS recall ≥ min_recall (tolérance 1e-12), choisit le meilleur seuil F1 (tie-break: precision, puis valeur du seuil), score la faiblesse signée par ligne, prend les top top_k_per_label par étiquette ground-truth, et développe chaque en une ligne par éclairage. Voir references/parameters-and-artifacts.md pour le calcul exact, les défauts override, et la table des artifacts.

Si aucun seuil candidat ne satisfait la cible de recall, le conteneur sort non-zéro et écrit unreachable_kpi.txt dans results_dir expliquant quel recall le modèle peut réellement atteindre. Dans ce cas, arrêtez l'analyse après l'appel docker, écrivez un rapport d'une section expliquant que le modèle ne peut fondamentalement pas atteindre le KPI à aucun point d'opération, et recommandez le réentraînement ou le réétiquetage — skip la vérification visuelle.

Le conteneur écrit dans results_dir: kpi_gaps.parquet (top-K plus faibles par label, développés par éclairage; colonnes filepath, label, siamese_score, weakness), threshold.txt, metrics.json, weak_samples_breakdown.txt, et unreachable_kpi.txt (uniquement quand la cible de recall est inaccessible). Voir references/parameters-and-artifacts.md pour le contenu par artifact. Imprimez le résumé stdout du conteneur (seuil choisi, comptages de lignes conservées, breakdown par label) vers votre propre stdout pour que le hook script-check puisse vérifier que le run a produit une sortie.

Étape 5 — Vérification visuelle spot-check (petite, fixe)

Skip cette étape si unreachable_kpi.txt existe dans results_dir — il n'y a rien de significatif à spot-checker quand le modèle ne peut pas atteindre le KPI à aucun seuil.

Sinon, utilisez l'outil Read pour voir les images de test pour:

  • Les 5 échantillons PASS les plus faibles (le haut de la pile « PASS mal classifiés comme NO_PASS ») — choisissez en triant les lignes kpi_gaps.parquetlabel == 'PASS' par weakness décroissant.
  • Les 5 échantillons NO_PASS les plus faibles (le haut de la pile « NO_PASS mal classifiés comme PASS ») — même, avec label != 'PASS'.

kpi_gaps.parquet est déjà développé par éclairage (plusieurs lignes par sample). Pour le spot-check, dédupliquéz en une ligne par (input_path, object_name) — choisissez la ligne dont filepath utilise le PREMIER éclairage depuis la YAML d'entraînement (une image par sample suffit — la classify head de VCN voit tous les éclairages empilés, mais pour un spot-check humain une est représentative).

Classifiez chaque sample vu comme exactement un de:

  • mislabeled — le contenu visuel est en désaccord avec l'étiquette CSV
  • edge case — cas de frontière genuinement ambigu
  • data quality — corrompu, sombre, mauvaise crop, mauvais framing
  • systematic — le modèle a appris la mauvaise feature (l'image semble « évidemment PASS/NO_PASS » mais le modèle est en désaccord)

Copiez chaque image vue (redimensionnée à 128×128 si PIL est disponible, sinon juste copier) dans <results_dir>/rca_images/ pour pouvoir être embarquée inline dans le rapport.

C'est la seule inspection d'image requise. Ne visionnez pas des douzaines d'images, ne lancez pas de clustering de mode d'échec, n'auditez pas les goldens — VCN n'a pas d'images golden.


Invocation de référence

La recette end-to-end paste-and-edit (workspace, quatre chemins, deux knobs numériques, écriture de spec-file, docker run, et le print sanity stdout qui surface les comptages de lignes pour le hook script-check) vit dans references/recipe.md. Utilisez-la verbatim, en n'éditant que le workspace, les chemins, et les knobs.


Sorties

Écrivez tout dans un dossier horodaté sous le répertoire de résultats d'expérience: <experiment_result_dir>/rca_results/YYYY-MM-DD_HHMMSS/. Les sorties du conteneur (kpi_gaps.parquet, threshold.txt, metrics.json, weak_samples_breakdown.txt, et unreachable_kpi.txt le cas échéant) y vont directement; la vérification visuelle spot-check écrit rca_images/; le hook de packaging ajoute rca_config/ et claude_session.jsonl automatiquement quand RCA_Report.md est écrit. Voir references/parameters-and-artifacts.md pour l'arborescence complète du dossier.

Au début du run, obtenez l'horodatage réel en exécutant date +%Y-%m-%d_%H%M%S en Bash. Ne le pas hardcoder ou deviner. Si l'utilisateur spécifie un chemin de sortie personnalisé, utilisez-le à la place mais maintenez la même structure interne.


Pièges courants

L'échec le plus conséquent est d'oublier top_k_per_label quand min_recall=1.0 — à ce recall le seuil choisi s'assoit à ou sous chaque score NO_PASS, donc le filtre below-threshold de fallback correspond UNIQUEMENT aux lignes PASS mal classifiées et kpi_gaps.parquet se retrouve avec zéro lignes NO_PASS. Toujours inclure un top_k_per_label positif explicite. La liste complète des pièges (spec file hors de $WORKSPACE, sentinelles ??? non résolues, tag image incorrect/non pulé, path-mount mismatch, gestion unreachable_kpi.txt, colonnes inference.csv manquantes, clés YAML d'entraînement manquantes, mismatch de préfixe kpi_media_path, pas de GPU à l'intérieur du conteneur) et la réconciliation de dérive CLI sont dans references/troubleshooting.md.


Structure du rapport

Écrivez le rapport RCA dans le dossier de sortie horodaté. C'est une analyse computationnelle de lacune à 7 sections (Verdict, Threshold Selection, Weakness Distribution, Top-K Weakest Samples, Visual Spot Check, Per-Label Breakdown, Recommended Actions), 1 000–1 800 mots, avec la confusion-matrix et les tables par label remplies depuis metrics.json et les lignes spot-check depuis kpi_gaps.parquet. Quand unreachable_kpi.txt existe, remplacez les sections 3–6 par une seule courte section citant ce fichier et collapser la section 7 en une simple recommandation retrain-or-relabel. Voir references/rca-report-structure.md pour le squelette complet avec chaque heading de section, layout de table, et la variante unreachable-KPI.


Ordre d'exécution

  1. Résolvez DS_IMAGE depuis versions.yaml (images.tao_toolkit.data_services), puis exécutez docker info, nvidia-smi, et docker image inspect "$DS_IMAGE" (pulling si manquant) une fois pour confirmer l'environnement. Arrêtez avec un message clair si un quelconque échoue.
  2. Exécutez date +%Y-%m-%d_%H%M%S pour obtenir l'horodatage; créez <experiment_result_dir>/rca_results/<timestamp>/.
  3. Écrivez vcn_aoi_spec.yaml dans le répertoire horodaté avec min_recall et top_k_per_label remplis. Gardez-le sous $WORKSPACE pour que le chemin -e se résolve à l'intérieur du conteneur.
  4. Exécutez docker run … "$DS_IMAGE" gap_analysis vcn_aoi -e vcn_aoi_spec.yaml inference_results_dir=… train_config=… kpi_media_path=… output_dir=…. Le conteneur écrit kpi_gaps.parquet, threshold.txt, metrics.json, weak_samples_breakdown.txt dans results_dir. Imprimez le seuil choisi et les comptages de lignes conservées vers stdout pour que le hook script-check puisse vérifier que le run a produit une sortie.
  5. Si unreachable_kpi.txt existe, skip l'étape 6 et écrivez le rapport abrégé. Sinon continuez.
  6. Choisissez 10 weak samples (5 plus faibles PASS + 5 plus faibles NO_PASS) depuis kpi_gaps.parquet, visionnez chaque image de test avec Read, classifiez, et copiez chaque dans rca_images/.
  7. Écrivez RCA_Report.md en dernier — l'écrire déclenche le hook packaging, qui copie les logs de session et la config du skill à côté.

Skills similaires