Computer Vision Engineer: от детекции и Doc-AI до продакшнаВведение и быстрый стартМетрики CV простым языком

Метрики CV простым языком

Уроки курсаМетрики CV простым языком

IoU/Dice для масок: когда какую метрику брать и почему

IoU и Dice измеряют, насколько предсказанная маска совпадает с истинной. IoU — отношение пересечения к объединению, строже. Dice — удвоенное пересечение к сумме площадей, мягче к ошибкам. Для детекции и instance segmentation обычно IoU, для медицинской сегментации (маленькие объекты, важна каждая точка) — Dice. Можно использовать обе для полной картины.

Ключевые идеи

  • IoU: пересечение / объединение. Строже, требует точного совпадения.
  • Dice: 2 × пересечение / (площадь_1 + площадь_2). Чувствительнее к маленьким объектам.
  • IoU используют в детекции (COCO), Dice — в медицинской сегментации.
  • При одинаковом пересечении Dice всегда выше IoU.

Формулы

IoU (Intersection over Union):

— площадь пересечения (пиксели, где обе маски = 1). — площадь объединения (пиксели, где хотя бы одна маска = 1).

Dice Coefficient:

В числителе удвоенное пересечение, в знаменателе — сумма площадей обеих масок.

Связь между IoU и Dice

Можно выразить одно через другое:

При IoU = 0.5 → Dice = 0.67. При IoU = 0.7 → Dice = 0.82. Dice всегда выше для тех же данных.

Пример вычисления

Истинная и предсказанная маски 4×4:

import numpy as np

# Истинная маска (где объект)
true_mask = np.array([[1, 1, 0, 0],
                      [1, 1, 0, 0],
                      [0, 0, 1, 1],
                      [0, 0, 1, 1]])

# Предсказанная маска
pred_mask = np.array([[1, 0, 0, 0],
                      [1, 1, 0, 0],
                      [0, 0, 1, 0],
                      [0, 0, 1, 1]])

def calculate_iou(true_mask, pred_mask):
    intersection = np.sum(true_mask & pred_mask)
    union = np.sum(true_mask | pred_mask)
    return intersection / union if union != 0 else 0

def calculate_dice(true_mask, pred_mask):
    intersection = np.sum(true_mask & pred_mask)
    sum_masks = np.sum(true_mask) + np.sum(pred_mask)
    return 2 * intersection / sum_masks if sum_masks != 0 else 0

iou = calculate_iou(true_mask, pred_mask)
dice = calculate_dice(true_mask, pred_mask)

print(f"Intersection: {np.sum(true_mask & pred_mask)}")  # 5
print(f"Union: {np.sum(true_mask | pred_mask)}")        # 9
print(f"IoU: {iou:.3f}")                                 # 0.556
print(f"Dice: {dice:.3f}")                               # 0.714

Пересечение — 5 пикселей, объединение — 9. IoU = 5/9 ≈ 0.56, Dice = 2×5/(8+8) = 10/16 ≈ 0.71. Dice выше, как и ожидалось.

Когда использовать IoU

  • Детекция объектов: IoU между предсказанным bbox и ground truth. Порог 0.5 — стандарт для засчитывания детекции.
  • Instance segmentation: COCO использует IoU для оценки масок. mAP@[.5:.95] — среднее по порогам IoU.
  • Большие объекты: если объект занимает много пикселей, IoU стабилен. Маленькие ошибки не сильно влияют.

Когда использовать Dice

  • Медицинская сегментация: опухоли, органы на МРТ/КТ часто маленькие. Dice чувствительнее к каждому пикселю.
  • Несбалансированные маски: если объект 1% изображения, IoU может быть низким даже при хорошем результате. Dice стабильнее.
  • Loss-функция: Dice Loss часто используют для обучения (1 - Dice). Дифференцируем, работает лучше IoU Loss на малых объектах.

Частые проблемы

  1. Пустые маски: если обе маски пустые (нет объекта), что вернуть? Соглашение: IoU = 1 (идеальное совпадение), но код выше вернёт 0/0. Добавьте проверку:
    if union == 0:
        return 1.0 if np.sum(true_mask) == 0 else 0.0
    
  2. Dice завышает для больших объектов: если объект 90% изображения, даже при плохой границе Dice будет высоким. Используйте IoU для контроля.
  3. IoU слишком строг для мелочей: сегментировали сосуд шириной 2 пикселя, ошиблись на 1 пиксель — IoU упал вдвое. Dice стабильнее.
  4. Разные метрики — разные выводы: IoU = 0.5 может быть приемлемым, Dice = 0.67 выглядит лучше. Сравнивайте модели по одной метрике.

Практические советы

  • Для бенчмарков: используйте ту метрику, что принята в датасете (COCO — IoU, медицина — Dice).
  • Для отладки: считайте обе. Если IoU низкий, но Dice высокий — проблема с границами, а не с общим совпадением.
  • Для loss: Dice Loss + CE (Cross Entropy) — популярная комбинация для сегментации.

Связанные понятия

  • GIoU (Generalized IoU): улучшенная версия IoU, учитывает расстояние между bbox. Используется в детекции.
  • Focal Loss: взвешивает сложные примеры сильнее. Комбинируется с Dice для несбалансированных классов.
  • Hausdorff Distance: метрика для оценки границ. Измеряет максимальное расстояние между контурами.

Итоги

  • IoU = пересечение / объединение. Строже, стандарт для детекции и COCO.
  • Dice = 2 × пересечение / (сумма площадей). Чувствительнее к маленьким объектам.
  • При одинаковом пересечении Dice всегда выше IoU: Dice = 2×IoU / (1+IoU).
  • Используйте IoU для детекции и больших объектов, Dice — для медицинской сегментации.
  • Для полной оценки считайте обе метрики.

Дальше по курсу

В следующем шаге разберём замеры латентности (latency) и throughput для CV-моделей. Узнаем, как корректно мерить время inference, учитывать warmup, и почему среднее время обманчиво — нужен p95.