Неизвестная область на маске: как исключить её из оценки сегментации
Разметчик выделил дефект на детали, но участок под сильным бликом оставил неизвестным. В маске ему присвоили значение 255. При оценке сегментации эти пиксели случайно объявили фоном. Модель получила штраф за обнаруженный там дефект, хотя правильного ответа никто не задавал. После изменения освещения метрика стала меняться вместе с площадью блика, а команда приняла это за изменение качества.
Неизвестная область должна исключаться из сравнения по явному правилу. Её нельзя автоматически считать отрицательным классом. Для этого в целевой маске выделяют специальный код, который не принадлежит обычным классам. В оценке одни и те же пиксели исключаются из пересечения, объединения и всех прочих счётчиков ошибок.
Оценка использует маску допустимых пикселей
Рассмотрим бинарную задачу: 1 означает дефект, 0 — фон, 255 — отсутствие достоверной разметки. Модель выдаёт только 0 или 1. Чтобы вычислить IoU дефекта, сначала выбираем позиции target != 255. Затем считаем площадь, где дефект есть у обеих сторон, и площадь, где он есть хотя бы у одной. Исключение только из числителя оставит неправильный знаменатель.
import numpy as np
target = np.array([[1, 1, 255], [0, 0, 255]])
pred = np.array([[1, 0, 1], [0, 1, 1]])
valid = target != 255
intersection = ((pred == 1) & (target == 1) & valid).sum()
union = (((pred == 1) | (target == 1)) & valid).sum()
iou = float(intersection / union) if union else None
naive_target = np.where(target == 255, 0, target)
naive_union = ((pred == 1) | (naive_target == 1)).sum()
naive = float(((pred == 1) & (naive_target == 1)).sum() / naive_union)
print("valid", int(valid.sum()), "ignored", int((~valid).sum()))
print("IoU", iou, "unknown_as_background", naive)
assert (intersection, union) == (1, 3)
assert np.isclose(iou, 1/3) and np.isclose(naive, 1/5)
assert not (np.full((2, 2), 255) != 255).any()На четырёх размеченных пикселях IoU равен одной трети. Если неизвестные области объявить фоном, он падает до одной пятой. Дополнительные «ошибки» возникли там, где правильного класса вообще нет. Пример также проверяет полностью неизвестную маску: такой кадр не должен давать привычное число качества. Верните отсутствие оценки и учтите кадр в отдельном счётчике.
Обучение и оценка требуют одного соглашения
В PyTorch CrossEntropyLoss поддерживает ignore_index для целевых индексов классов: соответствующие позиции не участвуют в вычислении градиента и выбранном усреднении. Этот параметр сам по себе не исправляет вашу реализацию IoU. В функции метрик нужно отдельно применить тот же код исключения. Для других функций потерь механизм может отличаться, особенно если они принимают вероятности по классам.
Не перепутайте код неизвестной области с допустимым классом. Если 255 уже означает один из объектов в исходном формате, выберите другое представление при загрузке и сохраните таблицу соответствий. В маске классов нельзя применять обычную интерполяцию фотографии: промежуточное значение между 0 и 255 не становится новым осмысленным классом. При resize используйте режим, сохраняющий дискретные метки, и проверяйте набор уникальных значений после преобразования.
Как читать итоговую метрику
Покажите рядом долю размеченных пикселей и число кадров с доступной оценкой. Если игнорируемая площадь выросла вдвое, сравнение IoU до и после становится менее прямым: оценка идёт по другому набору позиций. Особенно опасно, когда разметчики исключают именно самые сложные дефекты. Сохраняйте причину исключения и проверяйте её распределение по источникам и сменам.
Для общего отчёта заранее выберите способ агрегации: сумма пересечений и объединений по всем кадрам либо среднее покадровых IoU. Эти значения могут различаться из-за размеров объектов и количества доступных пикселей. Не смешивайте их под одним названием. Правило для кадров без дефекта тоже фиксируйте отдельно, чтобы отсутствие объединения не превращалось молча в идеальное качество.
В приёмку добавьте неизвестную полосу, неизвестный весь кадр, обычный фон и дефект на границе известной области. Если меняется библиотека метрик, сравните счётчики на этих маленьких масках до большого запуска. Так вы проверите смысл числа, а не только отсутствие исключения в коде.
Если известна только часть объекта, не достраивайте её автоматически до полного контура для оценки. Сначала задайте правило разметки видимой области. Иначе различие между видимой и полной формой будет ошибочно отнесено к качеству сегментации.
В курсе вы работаете с сегментацией, IoU и Dice, подготовкой датасетов и отчётом качества. Следующая задача — связать соглашение о разметке с обучением, проверкой масок и сервисной оценкой модели, чтобы итоговый показатель отражал размеченную область. Откройте программу платного курса «Computer Vision Engineer: от детекции и Doc-AI до продакшна».
Продолжить на практике
- Computer Vision Engineer: от детекции и Doc-AI до продакшна ↗
Практический курс по Computer Vision. Соберёте продакшн-сервис: датасет → обучение (YOLO/RT-DETR, SAM), трекинг, OCR/Doc-AI, веб-приложение (UI+API) и мониторинг. Экспорт в ONNX/TensorRT/OpenVINO, батчинг/квантование под CPU/GPU. Плюс профессиональные блоки: mAP/IoU/Dice и калибровка доверия, QA разметки и аугментации, p95/стоимость, дрейф данных и алерты, guardrails (NMS/правила), A/B-тесты, Triton/gRPC/FastAPI.
