Confusion Matrix
혼동 행렬은 모델의 예측을 실제 레이블과 클래스별로 집계합니다. 읽는 방법, 산출되는 지표, 객체 탐지용 혼동 행렬을 다룹니다.
혼동 행렬은 분류 모델의 예측이 실제 레이블과 어떻게 일치하는지 집계하는 표입니다. 한 축에는 실제 클래스가, 다른 축에는 예측 클래스가 표시되며 각 셀은 해당 클래스 쌍에 속하는 예제 수를 집계합니다. 올바른 예측은 대각선에, 모든 오예측은 대각선 바깥에서 어떤 클래스를 어떤 클래스로 잘못 분류했는지 정확히 나타내는 셀에 표시됩니다. 따라서 혼동 행렬은 일반적으로 모델 오류를 처음 살펴보는 표준 방법이며, 정확도, 정밀도, 재현율, F1 점수를 계산하는 기반입니다.
이진 혼동 행렬 읽기#
클래스가 두 개인 경우 행렬에는 네 개의 셀이 있습니다.
- 참 양성(TP): 결함이 있는 부품을 결함이 있다고 표시하는 것처럼, 양성 예제를 양성으로 예측한 경우입니다.
- 거짓 양성(FP): 음성 예제를 양성으로 예측한 경우이며, 제1종 오류 또는 오경보라고도 합니다.
- 거짓 음성(FN): 양성 예제를 음성으로 예측한 경우이며, 제2종 오류 또는 미탐이라고도 합니다.
- 참 음성(TN): 음성 예제를 음성으로 예측한 경우입니다.
대부분의 이진 분류 지표는 이 네 가지 개수의 비율입니다. 정밀도는 TP / (TP + FP), 재현율은 TP / (TP + FN), 정확도는 (TP + TN)을 네 항목의 전체 합으로 나눈 값입니다. 어떤 대각선 밖의 셀이 더 중요한지는 애플리케이션에 따라 다릅니다. 암 선별 검사는 거짓 음성을 줄이도록 조정하고, 스팸 필터는 거짓 양성을 줄이도록 조정합니다.
다중 클래스 혼동 행렬#
클래스가 N개이면 행렬의 크기는 N × N입니다. scikit-learn의 confusion_matrix에서 사용하는 방향에서는 각 행이 실제 클래스이고 각 열이 예측 클래스입니다. 행을 따라 읽으면 해당 클래스의 예제가 어떤 클래스로 분류되었는지 알 수 있으므로, 행의 전체 합 중 대각선 셀의 비율이 해당 클래스의 재현율입니다. 열을 따라 읽으면 모델이 해당 클래스로 예측한 항목의 실제 클래스가 무엇인지 알 수 있으므로, 열의 전체 합 중 대각선 셀의 비율이 해당 클래스의 정밀도입니다. 일부 도구는 행렬을 전치해 표시하므로, 차트의 축 레이블을 기준으로 읽어야 합니다.
from sklearn.metrics import confusion_matrix
# 이미지 10개의 실제 레이블과 예측 레이블
y_true = ["cat", "cat", "cat", "dog", "dog", "dog", "dog", "fox", "fox", "fox"]
y_pred = ["cat", "cat", "dog", "dog", "dog", "dog", "cat", "fox", "dog", "fox"]
# 이 레이블 순서에서 행은 실제 클래스이고 열은 예측 클래스입니다
labels = ["cat", "dog", "fox"]
matrix = confusion_matrix(y_true, y_pred, labels=labels)
print(matrix)고양이, 개, 여우의 출력 행은 각각 [2 1 0], [1 3 0], [0 1 2]입니다. 대각선에는 이미지 10개 중 7개가 있으므로 정확도는 0.7입니다. 개 열에는 고양이 한 개와 여우 한 개가 모여 있으므로 개 정밀도는 3 / 5 = 0.6입니다. 개 행에서는 이미지 한 개가 고양이로 잘못 분류되므로 개 재현율은 3 / 4 = 0.75입니다. 정규화된 행렬은 각 셀을 실제 클래스의 전체 개수로 나누므로 대각선에 클래스별 재현율이 표시되며, 크기가 크게 다른 클래스를 비교할 수 있습니다.
객체 탐지용 혼동 행렬#
탐지에서는 배경 클래스를 추가합니다. 탐지기는 아무것도 없는 위치에 박스를 출력하거나 객체를 완전히 놓칠 수 있기 때문입니다. 먼저 교집합 대비 합집합(IoU)을 기준으로 예측을 레이블과 매칭한 다음 집계합니다. 매칭된 쌍은 클래스 셀에 들어가고, 매칭되지 않은 예측은 배경에 대한 거짓 양성으로, 매칭되지 않은 레이블은 배경으로 예측된 거짓 음성으로 집계됩니다. 빈 이미지 영역은 집계할 수 없으므로 배경-배경 셀은 비어 있고, 따라서 탐지 행렬에는 참 음성이 없습니다. YOLO26 검증은 배경용 행과 열을 하나씩 추가한 행렬을 만들고, IoU가 0.45를 초과하는 기준으로 예측을 레이블과 매칭합니다. 또한 예측 클래스는 세로축에, 실제 클래스는 가로축에 배치하고 이를 confusion_matrix.png로 저장합니다.
from ultralytics import YOLO
# Load a pretrained YOLO26 nano detector
model = YOLO("yolo26n.pt")
# Validation builds the confusion matrix and saves it as confusion_matrix.png
metrics = model.val(data="coco8.yaml")
matrix = metrics.confusion_matrix.matrix # rows: predicted class, columns: true class
# 80 COCO classes plus one background row and column
print(matrix.shape)
# Class 0 is "person": correct detections and people the model missed
print(f"Person TP: {matrix[0, 0]:.0f}, missed: {matrix[-1, 0]:.0f}")행렬의 크기는 (81, 81)이며, 마지막 행은 어떤 예측과도 매칭되지 않은 레이블상의 사람 수를 집계합니다.
혼동 행렬과 관련 도구 비교#
- ROC 곡선: 의사결정 임계값마다 하나의 점이 있으며, 각 점은 해당 임계값의 혼동 행렬을 참 양성률과 거짓 양성률로 요약합니다.
- 평균 정밀도(mAP): 모든 신뢰도 수준에서 동일한 TP 및 FP 판정을 사용해 계산하는 주요 탐지 점수로, 어떤 클래스끼리 혼동되는지는 표시하지 않습니다.
- 정확도: 행렬을 하나의 숫자, 즉 대각선의 합을 전체 합으로 나눈 값으로 축약한 것입니다. 데이터셋의 95%가 음성인 경우, 항상 "음성"이라고 예측하는 모델은 정확도 95%를 기록하지만 혼동 행렬에는 참 양성이 하나도 없습니다.










