Skip to main content

세그멘테이션 평가 지표

학습 목표

  • Pixel Accuracy, IoU, mIoU의 정의와 계산법을 설명할 수 있다
  • Dice Score와 IoU의 관계를 이해한다
  • 태스크별 적합한 평가 지표를 선택할 수 있다
  • 코드로 평가 지표를 계산할 수 있다

왜 중요한가

세그멘테이션은 픽셀 단위로 예측하므로 분류의 Accuracy와는 다른 평가 체계가 필요합니다. 배경이 이미지의 대부분을 차지하는 경우, Pixel Accuracy만으로는 소규모 객체의 세그멘테이션 품질을 파악할 수 없습니다. mIoU와 Dice Score가 표준 지표로 사용됩니다.

핵심 지표

Pixel Accuracy

전체 픽셀 중 올바르게 분류된 픽셀의 비율입니다. 직관적이지만 클래스 불균형에 취약합니다.

IoU (Intersection over Union)

클래스별로 예측 영역과 정답 영역의 겹침 정도를 측정합니다. Jaccard Index라고도 합니다.
IoU = TP / (TP + FP + FN)

mIoU (mean IoU)

모든 클래스의 IoU를 평균한 값으로, 세그멘테이션의 표준 평가 지표입니다.

Dice Score (F1 Score)

의료 영상에서 주로 사용되는 지표로, IoU와 유사하지만 겹침에 더 큰 가중치를 줍니다.
Dice = 2 * TP / (2 * TP + FP + FN)
지표수식범위특징
Pixel Accuracy올바른 픽셀 / 전체 픽셀0~1불균형에 취약
mIoU클래스별 IoU 평균0~1표준 지표
Dice Score2*교집합 / 합0~1의료 표준
Boundary IoU경계 영역의 IoU0~1경계 정밀도 평가

구현

import torch
import numpy as np

def compute_iou_per_class(pred, target, num_classes):
    """클래스별 IoU를 계산합니다."""
    ious = []
    for cls in range(num_classes):
        pred_mask = (pred == cls)
        target_mask = (target == cls)

        intersection = (pred_mask & target_mask).sum().float()
        union = (pred_mask | target_mask).sum().float()

        if union == 0:
            ious.append(float('nan'))  # 해당 클래스 없음
        else:
            ious.append((intersection / union).item())

    return ious

def compute_miou(pred, target, num_classes):
    """mIoU를 계산합니다."""
    ious = compute_iou_per_class(pred, target, num_classes)
    valid_ious = [iou for iou in ious if not np.isnan(iou)]
    return np.mean(valid_ious) if valid_ious else 0.0

def compute_dice(pred, target, num_classes):
    """클래스별 Dice Score를 계산합니다."""
    dice_scores = []
    for cls in range(num_classes):
        pred_mask = (pred == cls).float()
        target_mask = (target == cls).float()

        intersection = (pred_mask * target_mask).sum()
        dice = (2 * intersection) / (pred_mask.sum() + target_mask.sum() + 1e-8)
        dice_scores.append(dice.item())

    return dice_scores

# 사용 예시
pred = torch.tensor([[0, 0, 1, 1],
                      [0, 0, 1, 2],
                      [0, 2, 2, 2],
                      [0, 2, 2, 2]])

target = torch.tensor([[0, 0, 1, 1],
                        [0, 0, 1, 1],
                        [0, 0, 2, 2],
                        [0, 2, 2, 2]])

miou = compute_miou(pred, target, num_classes=3)
print(f"mIoU: {miou:.4f}")

dice = compute_dice(pred, target, num_classes=3)
for i, d in enumerate(dice):
    print(f"클래스 {i} Dice: {d:.4f}")

IoU와 Dice의 관계

# IoU와 Dice는 단조 관계
# Dice = 2 * IoU / (1 + IoU)
# IoU = Dice / (2 - Dice)

iou = 0.75
dice = 2 * iou / (1 + iou)  # 0.857
print(f"IoU {iou} → Dice {dice:.3f}")

지표 선택 가이드

도메인추천 지표이유
자율주행mIoU모든 영역 균형 평가
의료 영상Dice Score의료 커뮤니티 표준
위성 영상mIoU + Boundary IoU경계 정밀도 중요
일반 장면mIoUCOCO, Cityscapes 표준
네, IoU와 Dice는 단조 증가 관계입니다. IoU가 높을수록 Dice도 높아집니다. 다만 같은 모델이라도 Dice 수치가 IoU보다 항상 높게 나오므로, 두 지표를 직접 비교하면 안 됩니다.
포함하는 것이 일반적이지만, 논문이나 벤치마크에 따라 배경을 제외하는 경우도 있습니다. 다른 모델과 비교할 때는 동일한 기준인지 반드시 확인하세요.

체크리스트

  • IoU와 Dice Score의 계산법을 이해했다
  • mIoU의 의미와 계산 과정을 설명할 수 있다
  • Pixel Accuracy의 한계를 이해했다
  • 도메인에 맞는 평가 지표를 선택할 수 있다

다음 문서