018 분류 평가 지표 - Accuracy, Precision, Recall
키워드: 평가 지표, 정확도, 정밀도
개요
분류 모델을 평가할 때 단순히 정확도(Accuracy)만 보면 안 됩니다. 상황에 따라 Precision, Recall 등 다양한 지표가 더 중요할 수 있습니다.
이 글에서는 분류의 핵심 평가 지표인 Accuracy, Precision, Recall의 개념과 사용법을 알아봅니다.
실습 환경
- Python 버전: 3.11 권장
- 필요 패키지:
flaml[automl], scikit-learn
pip install flaml[automl] scikit-learn matplotlib
혼동 행렬 (Confusion Matrix)
모든 분류 평가 지표는 혼동 행렬에서 시작합니다.
이진 분류의 혼동 행렬
예측
Negative Positive
실제 Negative TN FP
Positive FN TP
| 용어 | 의미 | 설명 |
|---|---|---|
| TP (True Positive) | 진양성 | 실제 양성을 양성으로 예측 (정답) |
| TN (True Negative) | 진음성 | 실제 음성을 음성으로 예측 (정답) |
| FP (False Positive) | 위양성 | 실제 음성을 양성으로 예측 (오답) |
| FN (False Negative) | 위음성 | 실제 양성을 음성으로 예측 (오답) |
혼동 행렬 예시
from sklearn.metrics import confusion_matrix
import numpy as np
# 018 실제값과 예측값
y_true = [1, 0, 1, 1, 0, 1, 0, 0, 1, 0]
y_pred = [1, 0, 1, 0, 0, 1, 1, 0, 1, 0]
# 018 혼동 행렬
cm = confusion_matrix(y_true, y_pred)
print("혼동 행렬:")
print(cm)
# 018 각 요소 추출
tn, fp, fn, tp = cm.ravel()
print(f"\nTN={tn}, FP={fp}, FN={fn}, TP={tp}")
실행 결과
혼동 행렬:
[[4 1]
[1 4]]
TN=4, FP=1, FN=1, TP=4
1. Accuracy (정확도)
정의
전체 예측 중 맞은 예측의 비율입니다.
Accuracy = (TP + TN) / (TP + TN + FP + FN)
코드
from sklearn.metrics import accuracy_score
accuracy = accuracy_score(y_true, y_pred)
print(f"Accuracy: {accuracy:.4f}")
# 018 수동 계산
accuracy_manual = (tp + tn) / (tp + tn + fp + fn)
print(f"수동 계산: {accuracy_manual:.4f}")
실행 결과
Accuracy: 0.8000
수동 계산: 0.8000
Accuracy의 한계
불균형 데이터에서 문제가 됩니다.
# 018 불균형 예시: 실제 양성 5%, 음성 95%
y_true_imb = [0]*95 + [1]*5
y_pred_imb = [0]*100 # 모두 음성으로 예측
acc = accuracy_score(y_true_imb, y_pred_imb)
print(f"불균형 데이터 Accuracy: {acc:.2f}") # 0.95 (높지만 의미없음)
2. Precision (정밀도)
정의
양성으로 예측한 것 중 실제 양성의 비율입니다.
Precision = TP / (TP + FP)
"양성이라고 예측했을 때, 얼마나 맞았나?"
코드
from sklearn.metrics import precision_score
precision = precision_score(y_true, y_pred)
print(f"Precision: {precision:.4f}")
# 018 수동 계산
precision_manual = tp / (tp + fp)
print(f"수동 계산: {precision_manual:.4f}")
실행 결과
Precision: 0.8000
Precision이 중요한 경우
FP(위양성)의 비용이 큰 경우:
- 스팸 필터: 정상 메일을 스팸으로 분류하면 중요한 메일을 놓침
- 추천 시스템: 관련 없는 상품 추천은 사용자 경험 저하
- 범죄자 예측: 무고한 사람을 범죄자로 지목
3. Recall (재현율)
정의
실제 양성 중 양성으로 예측한 비율입니다.
Recall = TP / (TP + FN)
"실제 양성을 얼마나 잘 찾아냈나?"
Sensitivity(민감도), True Positive Rate(TPR)라고도 합니다.
코드
from sklearn.metrics import recall_score
recall = recall_score(y_true, y_pred)
print(f"Recall: {recall:.4f}")
# 018 수동 계산
recall_manual = tp / (tp + fn)
print(f"수동 계산: {recall_manual:.4f}")
실행 결과
Recall: 0.8000
Recall이 중요한 경우
FN(위음성)의 비용이 큰 경우:
- 암 진단: 암 환자를 정상으로 판단하면 치료 시기를 놓침
- 사기 탐지: 사기를 정상으로 판단하면 금전적 손실
- 보안 시스템: 침입자를 감지하지 못하면 보안 사고
Precision vs Recall 트레이드오프
Precision과 Recall은 일반적으로 트레이드오프 관계입니다.
from sklearn.datasets import load_breast_cancer
from sklearn.model_selection import train_test_split
from flaml import AutoML
import numpy as np
# 018 데이터 로드
X, y = load_breast_cancer(return_X_y=True)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
# 018 FLAML 학습
automl = AutoML()
automl.fit(X_train, y_train, task="classification", time_budget=30, verbose=0)
# 018 확률 예측
y_prob = automl.predict_proba(X_test)[:, 1]
# 018 다양한 임계값으로 Precision, Recall 계산
thresholds = [0.3, 0.5, 0.7]
print("임계값에 따른 Precision, Recall 변화:")
print("-" * 50)
for threshold in thresholds:
y_pred_t = (y_prob >= threshold).astype(int)
prec = precision_score(y_test, y_pred_t)
rec = recall_score(y_test, y_pred_t)
print(f"임계값 {threshold}: Precision={prec:.4f}, Recall={rec:.4f}")
실행 결과
임계값에 따른 Precision, Recall 변화:
--------------------------------------------------
임계값 0.3: Precision=0.9589, Recall=1.0000
임계값 0.5: Precision=0.9730, Recall=1.0000
임계값 0.7: Precision=0.9867, Recall=0.9867
지표 선택 가이드
| 상황 | 중요한 지표 | 이유 |
|---|---|---|
| 균형 데이터 | Accuracy | 전체적인 성능 파악 |
| 불균형 데이터 | Precision, Recall | 양성 클래스 성능 파악 |
| FP 비용이 큼 | Precision | 위양성 최소화 |
| FN 비용이 큼 | Recall | 위음성 최소화 |
| 둘 다 중요 | F1 Score | Precision과 Recall 균형 |
FLAML에서 지표 설정
# 018 Precision 최적화
automl.fit(X_train, y_train, task="classification",
time_budget=60, metric="precision")
# 018 Recall 최적화
automl.fit(X_train, y_train, task="classification",
time_budget=60, metric="recall")
분류 리포트
from sklearn.metrics import classification_report
print(classification_report(y_test, y_pred, target_names=['음성', '양성']))
실행 결과
precision recall f1-score support
음성 0.98 0.95 0.96 43
양성 0.97 0.99 0.98 71
accuracy 0.97 114
macro avg 0.97 0.97 0.97 114
weighted avg 0.97 0.97 0.97 114
시각화
import matplotlib.pyplot as plt
# 018 Precision-Recall 트레이드오프 시각화
from sklearn.metrics import precision_recall_curve
precision_arr, recall_arr, thresholds = precision_recall_curve(y_test, y_prob)
plt.figure(figsize=(8, 6))
plt.plot(recall_arr, precision_arr, 'b-', linewidth=2)
plt.xlabel('Recall')
plt.ylabel('Precision')
plt.title('Precision-Recall Curve')
plt.grid(True, alpha=0.3)
plt.tight_layout()
plt.show()
정리
| 지표 | 공식 | 의미 |
|---|---|---|
| Accuracy | (TP+TN)/(전체) | 전체 정확도 |
| Precision | TP/(TP+FP) | 양성 예측의 정확도 |
| Recall | TP/(TP+FN) | 실제 양성 탐지율 |
- Accuracy는 균형 데이터에서 유용합니다.
- Precision은 FP 비용이 클 때 중요합니다.
- Recall은 FN 비용이 클 때 중요합니다.
- Precision과 Recall은 트레이드오프 관계입니다.
- 상황에 맞는 지표를 선택하세요.
다음 글 예고
다음 글에서는 분류 평가 지표 - F1 Score, AUC에 대해 알아보겠습니다. Precision과 Recall을 종합한 F1 Score와 ROC AUC를 다룹니다.
FLAML AutoML 마스터 시리즈 #018