вариант

tao-analyze-gaps-visual-changenet

NVIDIA/skills NVIDIA/skills

Выявляет самые слабые образцы по каждой этикетке эталонных данных в экспериментах NVIDIA TAO VCN Classify путем запуска контейнера Docker, который выполняет прогон по пороговому значению, оценку слабости и расширение по условиям освещения, а затем выделяет K лучших слабых образцов для последующего расширения или перемаркировки.

...Расширить все
2
Обновлено время 28 сентября 2026 г.

Навык анализа пробелов в системе TAO VCN Classify

Вы являетесь аналитиком результатов инференса NVIDIA TAO VCN Classify (Visual Component Net). Ваша задача — выявлять самые слабые образцы по каждой метке «истинного значения» путем измерения знакового расстояния от порога принятия решения в неправильном направлении, а затем выделять их для последующего расширения или перемаркировки.

Этот навык намеренно выполнен в облегченном варианте. Классификатор VCN представляет собой бинарную границу с единственным результатом (PASS или NO_PASS по siamese_score), поэтому анализ носит вычислительный характер, а не исследовательский. Весь расчёт осуществляется в рамках одного прямого вызова Docker run с использованием образа tao_toolkit.data_services, объявленного в файле versions.yaml (определяется во время выполнения — см. раздел «Настройка»). Точка входа контейнера принимает [переопределения Hydra...]; мы передаём gap_analysis vcn_aoi key=value …. Каждое переопределение представляет собой простой ключ-значение Hydra, которое выборочно переопределяет схему GapAnalysisConfig скрипта (значения по умолчанию встроены в контейнер; проверьте с помощью docker run ... gap_analysis vcn_aoi --cfg=job). (Внутри контейнера нет ключевого слова dataset — это префикс столбца запуска TAO, который здесь опускается.) Вам не нужны делегированный анализ, многоэтапные проверки образов или кластеризация по типам компонентов — VCN не предоставляет доступ к этим аспектам. Просмотрите лишь небольшой набор репрезентативных слабых образцов, чтобы определить пробелы после возврата контейнера.

Интерфейс CLI может меняться в зависимости от сборки контейнера data-services. Если вызов gap_analysis vcn_aoi завершается с ошибкой при разборе аргументов, проверьте фактическую схему один раз для каждого образа с помощью команды docker run --rm "$DS_IMAGE" gap_analysis vcn_aoi --cfg=job и приведите в соответствие все переименованные ключи (например, inference_csv и inference_results_dir, output_dir и results_dir) перед повторной попыткой. Имя выходного файла в формате Parquet — kpi_gaps.parquet.

Входные данные

  1. Каталог результатов эксперимента — содержит файл inference/inference.csv, полученный в результате инференции TAO VCN Classify. Обязательные столбцы: input_path, object_name, label, siamese_score. Передайте каталог (например, inference/latest/), а не файл CSV — контейнер считывает файл из папки inference_results_dir/inference.csv.
  2. Каталог с кодом и конфигурацией обучения — содержит файл YAML модели VCN для обучения. Контейнер считывает из него файлы dataset.classify.input_map (список условий освещения) и dataset.classify.image_ext, чтобы развернуть каждую «слабую» выборку в одну строку для каждого варианта освещения.
  3. Каталог набора данных — к относительному пути input_path из каждой строки (kpi_media_path) добавляется корень каталога изображений.
  4. Переопределения схемы — min_recall, top_k_per_label и, опционально, жестко зафиксированный порог передаются в качестве переопределений Hydra (значения по умолчанию: min_recall=1.0, top_k_per_label=50, threshold=-1.0, что означает полный проход). top_k_per_label должен быть положительным целым числом — его пропуск переключает контейнер в режим «фильтра ниже порога», который при min_recall=1,0 возвращает только ошибочные классификации PASS и ноль строк NO_PASS. См. раздел «Распространённые ошибки».

Настройка

Проход по порогу, ранжирование слабых мест и расширение по каждому освещению выполняются внутри образа tao_toolkit.data_services, объявленного в файле versions.yaml. Определите конкретный URI один раз в начале запуска, затем убедитесь в наличии Docker, набора инструментов контейнеров NVIDIA и графического процессора, а также проверьте, что образ кэширован:

# Определите конкретный URI nvcr.io/... для tao_toolkit.data_services из файла 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 обычно экспортируется установленным банком навыков. Если эта переменная не задана, перед началом работы укажите путь к корневому каталогу репозитория банка навыков. Требуется графический процессор (GPU); досрочное прерывание процесса на хосте без GPU позволит избежать непонятных ошибок на поздних этапах.

Три правила настройки являются ключевыми и их легко нарушить:

  • Монтирование путей — каждый путь на хосте, который контейнер читает или в который записывает (inference.csv, YAML для обучения, корневой каталог образа набора данных, каталог вывода), должен быть смонтирован с привязкой; проще всего это сделать с помощью -v $WORKSPACE:$WORKSPACE -w $WORKSPACE, чтобы абсолютные пути разрешались одинаково с обеих сторон.
  • Не передавайте --user $(id -u):$(id -g) — это вызывает ошибку KeyError: 'getpwuid(): uid not found: ' во время импорта трансформеров контейнером; вместо этого chown впоследствии возвращает UID хоста.
  • -e является обязательным, а не опциональным параметром — текущие образы строго требуют его наличия и завершают работу с ошибкой ValueError: «The subtask vcn_aoi requires the following argument: -e/--experiment_spec_file» перед разбором переопределений из командной строки.

См. файл references/container-setup.md для ознакомления с полным шаблоном подключения по пути, обоснованием использования--user/chown и командой chown в Alpine, рекомендациями по использованию нескольких параметров --v, а также подробностями о требовании -e .

Метод

Весь навык представляет собой один вызов docker run, за которым следует небольшая визуальная выборочная проверка. Контейнер внутренне выполняет шаги 1–4 (проход по порогам, оценка уязвимостей, выбор top-K, расширение по каждому источнику освещения). Вы выполняете шаг 5 (визуальную выборочную проверку) непосредственно с помощью инструмента Read.

Шаги 1–4 — Запуск контейнера

$DOCKER gap_analysis vcn_aoi \
    inference_results_dir=/inference/

Всегда передавайте параметр top_k_per_label. Это аргумент, который переключает контейнер с фильтра по умолчанию «выборки ниже порогового значения» на правильный рейтинг top-K-per-label. При min_recall=1.0 пороговое значение по определению находится на уровне или ниже каждого оценки NO_PASS, поэтому фильтр «ниже порогового значения» возвращает ТОЛЬКО неправильно классифицированные строки PASS и ноль строк NO_PASS — что бесполезно в качестве очереди расширения. Если top_k_per_label установлен в положительное целое число (либо в спецификации, либо в качестве переопределения Hydra), контейнер вычисляет слабость со знаком относительно порога для каждой строки и выделяет K самых слабых строк для каждой метки истинного значения, которые и являются ранжированным выходом по меткам, потребляемым последующими этапами.

Считывает файл inference.csv, просматривает каждое уникальное значение siamese_score плюс одно значение чуть ниже минимума, оставляет кандидаты с коэффициентом воспроизведения класса NO_PASS ≥ min_recall (с допуском 1e-12 ), а затем выбирает пороговое значение с наилучшим показателем F1 (при равенстве: точность, затем значение порогового значения). Для каждой строки вычисляет знак слабости относительно этого порога (положительный = ошибочная классификация, отрицательный = правильная, величина = отклонение). Сортирует по слабости в порядке убывания и берет top_k_per_label лучших строк для каждого ярлыка истинных значений, затем расширяет каждую слабую строку до одной строки на каждое условие освещения с помощью dataset.classify.input_map и dataset.classify.image_ext из YAML-файла обучения.

Если ни одно из пороговых значений не соответствует целевому показателю воспроизведения, контейнер завершает работу с ненулевым кодом и записывает файл unreachable_kpi.txt в каталог results_dir с объяснением, какого показателя воспроизведения модель может фактически достичь. В этом случае остановите анализ после вызова Docker, составьте отчёт из одного раздела, объясняющий, что модель принципиально не может достичь KPI ни в одной рабочей точке, и порекомендуйте переобучение или перемаркировку — пропустите визуальную выборочную проверку.

Контейнер записывает в каталог results_dir:

Артефакт Содержимое
kpi_gaps.parquet Top-K самых слабых результатов по каждой метке, с разбивкой по условиям освещения. Столбцы: filepath, label, siamese_score, weakness.
threshold.txt Выбранный порог принятия решения (одно число с плавающей запятой, обычный текст).
metrics.json При выбранном пороге: точность, полнота, F1, матрица путаницы {tp, fp, tn, fn}, а также по каждому ярлыку {total, mean_weakness, median_weakness, max_weakness, n_misclassified}.
weak_samples_breakdown.txt Разбивка сохраненных строк по меткам: общее количество, <%> из всех сохраненных строк: N неправильно классифицированных (слабость > 0), N пограничных (слабость ≤ 0).
unreachable_kpi.txt Записывается только в том случае, если целевой показатель recall недостижим. Наличие этого файла означает: пропустить шаг 5, составить сокращённый отчёт, рекомендовать переобучение.

Выведите сводку stdout контейнера (выбранное пороговое значение, количество сохраненных строк, разбивка по лейблам) в свой собственный stdout, чтобы хук script-check мог проверить выходные данные, сгенерированные в ходе запуска.

Шаг 5 — Визуальная выборочная проверка (небольшая, фиксированная)

Пропустите этот шаг, если существует файл unreachable_kpi.txt. В противном случае используйте инструмент «Read» для просмотра 5 самых слабых образцов с результатом «PASS» и 5 самых слабых образцов с результатом «NO_PASS» из файла kpi_gaps.parquet (очищенного от дубликатов до одной строки на образец с использованием пути к файлу FIRST-lighting), классифицируйте каждый из них как один из следующих типов: «mislabeled» / «edge case» / «data quality » / «systematic», и скопируйте каждое просмотренное изображение (измененное до размера 128×128, если доступен PIL, в противном случае просто скопируйте) в папку /rca_images/. Это единственная необходимая проверка изображений — не просматривайте десятки изображений, не выполняйте кластеризацию по режимам сбоев и не проводите аудит эталонных изображений (у VCN нет эталонных изображений).

См. файл references/visual-spot-check.md для ознакомления с точным порядком отбора образцов, правилом удаления дубликатов по условиям освещения, полным определением каждой категории вердикта и подробностями копирования изображений.

Вызов скрипта

Вставьте и отредактируйте рабочую область, четыре пути и два числовых параметра; это запускает процесс от начала до конца. Перехватите stdout, чтобы хук проверки скриптов видел количество строк.

WORKSPACE=           # монтируется идентично внутри контейнера
EXP_DIR=     # содержит файлы inference/inference.csv и train.yaml; должен находиться внутри $WORKSPACE
DATASET_ROOT=         # корневой каталог изображений для записей input_path в файле inference.csv; должен находиться внутри $WORKSPACE
MIN_RECALL=1.0                       # значение по умолчанию для нулевого пропуска; уменьшайте, если требования к KPI снижаются
TOP_K=50                             # бюджет на увеличение данных для каждого лейбла
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"

# Записать спецификацию анализа пробелов для данного запуска
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"

# Контейнер записывает данные как пользователь root с отключенным параметром --user; при необходимости верните права владения (chown) к UID хоста.
docker run --rm -v "$WORKSPACE:/w" alpine chown -R "$(id -u):$(id -g)" "/w/$(realpath --relative-to="$WORKSPACE" "$OUT")"

# Вывод данных для проверки, чтобы хук script-check видел реальные числа
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)
    sys.exit(0)
with open(os.path.join(out, "threshold.txt")) as f:
    print("пороговое значение:", 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

Результаты

Запишите всё в папку с отметкой времени в каталоге результатов эксперимента. Результаты контейнера попадают прямо туда; визуальная выборочная проверка записывает данные в rca_images/; любой хук упаковки на время выполнения может добавлять артефакты захвата session/config после записи файла RCA_Report.md.

/rca_results/YYYY-MM-DD_HHMMSS/
├── RCA_Report.md              # Полный отчёт по анализу пробелов (вы его составляете)
├── kpi_gaps.parquet           # Контейнер: top-K самых слабых по метке, с разбивкой по освещению
├── threshold.txt              # Контейнер: выбранный порог принятия решения (одно число с плавающей запятой)
├── metrics.json               # Контейнер: матрица путаницы + статистика распределения по меткам
├── weak_samples_breakdown.txt # Контейнер: количество по меткам / количество ошибочно классифицированных / количество маргинальных
├── unreachable_kpi.txt        # Контейнер: ТОЛЬКО если ни один порог не удовлетворяет min_recall
├── rca_images/                # Вам: миниатюры 10 просмотренных слабых образцов
├── rca_config/                # Автоматически копируется хуком
└── session log/artifacts      # Необязательно, запись упаковки, зависящая от времени выполнения

В начале запуска получите реальную метку времени, выполнив в Bash команду date +%Y-%m-%d_%H%M%S. НЕ используйте жестко заданные значения и не угадывайте. Если пользователь указал собственный путь вывода, используйте его, но сохраните ту же внутреннюю структуру.

Распространённые ошибки

Самый серьезный из всех возможных сбоев — забыть указать top_k_per_label при min_recall=1.0: при данном значении recall выбранный порог находится на уровне или ниже каждого значения NO_PASS, поэтому без top_k_per_label контейнер переключается на фильтр «выборки ниже порога», который возвращает ТОЛЬКО неправильно классифицированные строки PASS и ноль строк NO_PASS, что нарушает работу очереди аугментации. Всегда указывайте явное положительное значение top_k_per_label (по умолчанию 50) в спецификации или в качестве переопределения Hydra.

См. файл references/pitfalls.md для полного контрольного списка, охватывающего: забывание top_k_per_label; передачу параметра --user; вызов только с переопределениями Hydra (без -e ); файл спецификации вне $WORKSPACE; файл спецификации с неразрешенными сигнальными знаками ???; изображение не загружено / неправильный тег; несоответствие path-mount; наличие файла unreachable_kpi.txt; отсутствие обязательных столбцов в файле inference.csv; отсутствие в YAML-файле train параметров dataset.classify.input_map или image_ext; несовпадение префиксов kpi_media_path и input_path; а также отсутствие обнаружения GPU изнутри контейнера.

Структура отчёта

Напишите файл RCA_Report.md в виде лаконичного (1000–1800 слов) анализа вычислительных пробелов — глубина анализа достигается за счет точных цифр и четкого списка действий, а не за счет описательного текста. Полный шаблон отчета (7 разделов: «Вердикт», «Выбор порогового значения», «Распределение слабых мест», «Top-K самых слабых образцов», «Визуальная выборочная проверка», «Разбивка по меткам», «Рекомендуемые действия» — с матрицей путаницы и макетами таблиц) находится в файле references/output-template.md. Если файл unreachable_kpi.txt существует, замените разделы 3–6 одним коротким разделом, цитирующим содержание этого файла, и сведите раздел 7 к одной рекомендации: переобучить или перемаркировать.

Порядок выполнения

  1. Определите DS_IMAGE из файла versions.yaml (images.tao_toolkit.data_services), затем один раз запустите команды docker info, nvidia-smi и docker image inspect "$DS_IMAGE" (загрузив образ, если он отсутствует), чтобы проверить среду. В случае любой ошибки прервите процесс с чётким сообщением.
  2. Запустите команду `date +%Y-%m-%d_%H%M%S`, чтобы получить метку времени; создайте каталоги ` `, `/rca_results/` и `/`.
  3. Запишите файл vcn_aoi_spec.yaml в каталог с меткой времени, заполнив поля min_recall и top_k_per_label. Сохраните его в каталоге $WORKSPACE, чтобы путь -e разрешался внутри контейнера.
  4. Запустите команду 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.json` и `weak_samples_breakdown.txt ` в каталог `results_dir`. Выведите выбранное пороговое значение и количество сохраненных строк в стандартный вывод (stdout), чтобы хук script-check мог проверить, что запуск сгенерировал ожидаемый вывод.
  5. Если файл unreachable_kpi.txt существует, пропустите шаг 6 и запишите сокращённый отчёт. В противном случае продолжайте.
  6. Выберите 10 слабых образцов (5 самых слабых PASS + 5 самых слабых NO_PASS) из файла kpi_gaps.parquet, просмотрите каждое тестовое изображение с помощью команды Read, классифицируйте их и скопируйте каждое в каталог rca_images/.
  7. В конце создайте файл RCA_Report.md — его создание запускает хук упаковки, который копирует журналы сеанса и конфигурацию навыка.
Посмотреть на 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.

Все файлы

1 файлов

Установить tao-analyze-gaps-visual-changenet

Скачайте файлы навыков и распакуйте их в каталог .claude/skills/.

Скачать ZIP

Клонируйте репозиторий и скопируйте файлы навыка в свой проект.

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

Копировать Копировать
Быстрая настройка: Скопируйте папку со скиллом в каталог .claude/skills/ Claude автоматически обнаружит и начнет использовать этот скилл
Репозиторий NVIDIA/skills

Похожие навыки

web-search
Обновлено время 29 июня 2026 г.
webapp-testing
Обновлено время 29 июня 2026 г.
lark-base
Обновлено время 5 июля 2026 г.
agentmail
Обновлено время 29 июня 2026 г.
OR