[Python 100일 챌린지] Day 96 - 모델 평가하기
모델이 정말 좋은가? 제대로 평가해보자! 단순히 정확도만 보면 속을 수 있습니다. 교차 검증, ROC 곡선, 혼동 행렬… 모델을 다각도로 평가하는 방법을 마스터하세요!
(30분 완독 ⭐⭐⭐)
🎯 오늘의 학습 목표
📚 사전 지식
- Day 94: 선형 회귀 모델
- Day 95: 로지스틱 회귀
- 기본적인 통계 개념
🎯 학습 목표 1: 교차 검증으로 안정적인 평가하기
💡 “정확도가 매번 달라요!” 당황스럽죠? 정상입니다! 데이터를 어떻게 나누느냐에 따라 달라질 수 있어요. 오늘 배울 교차 검증으로 이 문제를 해결합니다! 😊
단순 분리의 문제점
1
2
3
4
from sklearn.model_selection import train_test_split
# 문제: 운이 좋으면 정확도 높고, 나쁘면 낮음!
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2)
K-Fold 교차 검증
데이터를 K개로 나눠서 K번 평가
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
from sklearn.model_selection import cross_val_score
from sklearn.linear_model import LogisticRegression
from sklearn.datasets import load_iris
import numpy as np
# 데이터 로드
iris = load_iris()
X, y = iris.data, iris.target
# 모델 생성
model = LogisticRegression(max_iter=1000)
# 5-Fold 교차 검증
scores = cross_val_score(model, X, y, cv=5)
print("각 Fold 정확도:", scores)
print(f"평균 정확도: {scores.mean():.4f} (+/- {scores.std():.4f})")
출력:
1
2
각 Fold 정확도: [0.9667 0.9667 0.9333 0.9333 1.0000]
평균 정확도: 0.9600 (+/- 0.0251)
시각화: K-Fold 과정
graph TD
A[전체 데이터] --> B[Fold 1]
A --> C[Fold 2]
A --> D[Fold 3]
A --> E[Fold 4]
A --> F[Fold 5]
B --> G[Fold 1로 테스트<br/>나머지로 훈련]
C --> H[Fold 2로 테스트<br/>나머지로 훈련]
D --> I[Fold 3로 테스트<br/>나머지로 훈련]
E --> J[Fold 4로 테스트<br/>나머지로 훈련]
F --> K[Fold 5로 테스트<br/>나머지로 훈련]
G --> L[평균 정확도]
H --> L
I --> L
J --> L
K --> L
Stratified K-Fold (계층화)
클래스 비율 유지하며 분리
1
2
3
4
5
6
7
8
9
10
from sklearn.model_selection import StratifiedKFold, cross_val_score
# 클래스 불균형 데이터
y_imbalanced = np.array([0]*90 + [1]*10) # 90% vs 10%
# Stratified K-Fold 사용
skf = StratifiedKFold(n_splits=5, shuffle=True, random_state=42)
scores = cross_val_score(model, X, y, cv=skf)
print(f"Stratified K-Fold 평균 정확도: {scores.mean():.4f}")
🎯 학습 목표 2: ROC 곡선과 AUC 이해하기
ROC 곡선이란?
Receiver Operating Characteristic (수신자 조작 특성)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
from sklearn.datasets import make_classification
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import roc_curve, auc, RocCurveDisplay
import matplotlib.pyplot as plt
# 이진 분류 데이터 생성
X, y = make_classification(n_samples=1000, n_features=20,
n_informative=15, random_state=42)
# 데이터 분리
X_train, X_test, y_train, y_test = train_test_split(
X, y, test_size=0.3, random_state=42
)
# 모델 학습
model = LogisticRegression()
model.fit(X_train, y_train)
# ROC 곡선 계산
y_pred_proba = model.predict_proba(X_test)[:, 1]
fpr, tpr, thresholds = roc_curve(y_test, y_pred_proba)
roc_auc = auc(fpr, tpr)
# ROC 곡선 그리기
plt.figure(figsize=(10, 8))
plt.plot(fpr, tpr, color='blue', lw=2,
label=f'ROC curve (AUC = {roc_auc:.2f})')
plt.plot([0, 1], [0, 1], color='red', lw=2, linestyle='--',
label='Random (AUC = 0.50)')
plt.xlim([0.0, 1.0])
plt.ylim([0.0, 1.05])
plt.xlabel('False Positive Rate (FPR)', fontsize=12)
plt.ylabel('True Positive Rate (TPR)', fontsize=12)
plt.title('ROC Curve', fontsize=14)
plt.legend(loc="lower right")
plt.grid(True, alpha=0.3)
plt.savefig('roc_curve.png', dpi=150, bbox_inches='tight')
print(f"ROC AUC Score: {roc_auc:.4f}")
print("그래프 저장: roc_curve.png")
AUC 해석
| AUC 값 | 모델 성능 |
|---|---|
| 1.0 | 완벽한 분류 |
| 0.9 ~ 1.0 | 매우 좋음 |
| 0.8 ~ 0.9 | 좋음 |
| 0.7 ~ 0.8 | 보통 |
| 0.5 ~ 0.7 | 나쁨 |
| 0.5 | 동전 던지기 |
실전 예제: 여러 모델 비교
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
from sklearn.tree import DecisionTreeClassifier
from sklearn.ensemble import RandomForestClassifier
from sklearn.svm import SVC
# 여러 모델 학습
models = {
'Logistic Regression': LogisticRegression(),
'Decision Tree': DecisionTreeClassifier(random_state=42),
'Random Forest': RandomForestClassifier(n_estimators=10, random_state=42),
'SVM': SVC(probability=True, random_state=42)
}
plt.figure(figsize=(10, 8))
for name, model in models.items():
# 학습
model.fit(X_train, y_train)
# ROC 곡선
y_pred_proba = model.predict_proba(X_test)[:, 1]
fpr, tpr, _ = roc_curve(y_test, y_pred_proba)
roc_auc = auc(fpr, tpr)
# 그리기
plt.plot(fpr, tpr, lw=2, label=f'{name} (AUC = {roc_auc:.2f})')
plt.plot([0, 1], [0, 1], 'k--', lw=2, label='Random (AUC = 0.50)')
plt.xlabel('False Positive Rate')
plt.ylabel('True Positive Rate')
plt.title('ROC Curves - Model Comparison')
plt.legend(loc="lower right")
plt.grid(True, alpha=0.3)
plt.savefig('roc_comparison.png', dpi=150, bbox_inches='tight')
print("모델 비교 그래프 저장: roc_comparison.png")
🎯 학습 목표 3: 회귀 모델 평가 지표 활용하기
MAE, MSE, RMSE, R²
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
from sklearn.datasets import make_regression
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LinearRegression
from sklearn.metrics import mean_absolute_error, mean_squared_error, r2_score
import numpy as np
# 회귀 데이터 생성
X, y = make_regression(n_samples=100, n_features=1,
noise=10, random_state=42)
# 데이터 분리
X_train, X_test, y_train, y_test = train_test_split(
X, y, test_size=0.2, random_state=42
)
# 모델 학습
model = LinearRegression()
model.fit(X_train, y_train)
# 예측
y_pred = model.predict(X_test)
# 평가 지표 계산
mae = mean_absolute_error(y_test, y_pred)
mse = mean_squared_error(y_test, y_pred)
rmse = np.sqrt(mse)
r2 = r2_score(y_test, y_pred)
print("회귀 모델 평가:")
print(f"MAE: {mae:.2f} (평균 절대 오차)")
print(f"MSE: {mse:.2f} (평균 제곱 오차)")
print(f"RMSE: {rmse:.2f} (제곱근 평균 제곱 오차)")
print(f"R²: {r2:.4f} (결정계수)")
출력:
1
2
3
4
5
회귀 모델 평가:
MAE: 7.23 (평균 절대 오차)
MSE: 73.45 (평균 제곱 오차)
RMSE: 8.57 (제곱근 평균 제곱 오차)
R²: 0.9854 (결정계수)
평가 지표 비교
| 지표 | 설명 | 장점 | 단점 |
|---|---|---|---|
| MAE | 절대 오차의 평균 | 직관적 | 이상치에 둔감 |
| MSE | 제곱 오차의 평균 | 이상치 강조 | 단위가 제곱 |
| RMSE | MSE의 제곱근 | 원래 단위 | 계산 복잡 |
| R² | 설명력 (0~1) | 해석 쉬움 | 변수 증가 시 증가 |
💻 실전 예제: 완전한 모델 평가 파이프라인
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
from sklearn.datasets import load_breast_cancer
from sklearn.model_selection import cross_val_score, StratifiedKFold
from sklearn.linear_model import LogisticRegression
from sklearn.preprocessing import StandardScaler
from sklearn.metrics import (classification_report, confusion_matrix,
roc_auc_score, accuracy_score)
import numpy as np
# 유방암 데이터 로드
cancer = load_breast_cancer()
X, y = cancer.data, cancer.target
# 데이터 전처리
scaler = StandardScaler()
X_scaled = scaler.fit_transform(X)
# 1. 교차 검증
print("=" * 50)
print("1. 교차 검증 (5-Fold)")
print("=" * 50)
model = LogisticRegression(max_iter=10000)
cv_scores = cross_val_score(model, X_scaled, y, cv=5)
print(f"각 Fold 정확도: {cv_scores}")
print(f"평균 정확도: {cv_scores.mean():.4f} (+/- {cv_scores.std():.4f})")
# 2. 훈련/테스트 분리 및 평가
from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test = train_test_split(
X_scaled, y, test_size=0.2, random_state=42
)
model.fit(X_train, y_train)
y_pred = model.predict(X_test)
y_pred_proba = model.predict_proba(X_test)[:, 1]
print("\n" + "=" * 50)
print("2. 테스트 세트 평가")
print("=" * 50)
print(classification_report(y_test, y_pred,
target_names=['악성', '양성']))
# 3. ROC AUC
roc_auc = roc_auc_score(y_test, y_pred_proba)
print(f"\nROC AUC Score: {roc_auc:.4f}")
# 4. 혼동 행렬
print("\n" + "=" * 50)
print("3. 혼동 행렬")
print("=" * 50)
cm = confusion_matrix(y_test, y_pred)
print(cm)
print(f"\nTrue Negative: {cm[0][0]}")
print(f"False Positive: {cm[0][1]}")
print(f"False Negative: {cm[1][0]}")
print(f"True Positive: {cm[1][1]}")
📊 모델 선택 기준
문제 유형별 추천 지표
graph TD
A[모델 평가] --> B{문제 유형?}
B -->|회귀| C[R²<br/>RMSE<br/>MAE]
B -->|분류| D{클래스 균형?}
D -->|균형| E[Accuracy<br/>F1-Score]
D -->|불균형| F[Precision<br/>Recall<br/>ROC AUC]
F --> G{비용이 다른가?}
G -->|FP 비용↑| H[Precision 중요]
G -->|FN 비용↑| I[Recall 중요]
실무 예시
| 문제 | 중요 지표 | 이유 |
|---|---|---|
| 스팸 필터 | Precision | 정상 메일을 스팸으로 분류하면 안 됨 |
| 암 진단 | Recall | 암을 놓치면 안 됨 |
| 추천 시스템 | F1-Score | Precision과 Recall 모두 중요 |
| 집값 예측 | RMSE | 큰 오차에 페널티 |
⚠️ 주의사항
1. 과적합 체크
1
2
3
4
5
6
7
8
9
# 훈련 정확도 vs 테스트 정확도
train_acc = model.score(X_train, y_train)
test_acc = model.score(X_test, y_test)
print(f"훈련 정확도: {train_acc:.4f}")
print(f"테스트 정확도: {test_acc:.4f}")
if train_acc - test_acc > 0.1:
print("⚠️ 과적합 의심!")
2. 데이터 누수 방지
1
2
3
4
5
6
7
8
9
# ❌ 잘못된 방법: 전체 데이터로 스케일링
X_scaled = scaler.fit_transform(X)
X_train, X_test = train_test_split(X_scaled, ...)
# ✅ 올바른 방법: 훈련 데이터로만 fit
X_train, X_test = train_test_split(X, ...)
scaler.fit(X_train)
X_train_scaled = scaler.transform(X_train)
X_test_scaled = scaler.transform(X_test)
3. 평가 지표 선택
1
2
3
4
5
# 클래스 불균형 시 정확도는 의미 없음!
y = [0]*95 + [1]*5 # 95% vs 5%
# 모든 것을 0으로 예측해도 정확도 95%!
# → Precision, Recall, F1-Score 사용
📝 요약
- 교차 검증: 안정적인 성능 평가 (K-Fold, Stratified K-Fold)
- ROC AUC: 분류 모델의 전체적인 성능 (0.5~1.0)
- 회귀 지표: MAE (직관적), RMSE (이상치 강조), R² (설명력)
- 핵심: 문제에 맞는 지표 선택이 중요!
🧪 연습 문제
문제: 모델 평가 종합
아래 코드의 빈 칸을 채워 완전한 평가를 수행하세요.
1
2
3
4
5
6
7
8
9
10
11
12
from sklearn.datasets import load_iris
from sklearn.model_selection import cross_val_score
from sklearn.tree import DecisionTreeClassifier
iris = load_iris()
X, y = iris.data, iris.target
model = DecisionTreeClassifier(random_state=42)
# TODO:
# 1. 5-Fold 교차 검증 수행
# 2. 평균 정확도와 표준편차 출력
✅ 정답
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
from sklearn.datasets import load_iris
from sklearn.model_selection import cross_val_score
from sklearn.tree import DecisionTreeClassifier
iris = load_iris()
X, y = iris.data, iris.target
model = DecisionTreeClassifier(random_state=42)
# 5-Fold 교차 검증
scores = cross_val_score(model, X, y, cv=5)
print(f"각 Fold 정확도: {scores}")
print(f"평균 정확도: {scores.mean():.4f}")
print(f"표준편차: {scores.std():.4f}")
🤔 자주 묻는 질문 (FAQ)
Q1: 교차 검증을 항상 해야 하나요?
A: 데이터가 적을 때는 필수, 많을 때는 선택! 📊
언제 교차 검증이 필수인가?
1
2
3
4
# 데이터 양에 따른 가이드
데이터 < 1,000개 → 교차 검증 필수 ✅
데이터 1,000~10,000 → 교차 검증 권장 👍
데이터 > 10,000개 → 단순 분리도 OK (하지만 CV가 더 신뢰성 있음)
실생활 비유:
시험을 1번만 보면 운이 좋아서/나빠서 점수가 왜곡될 수 있어요. 하지만 5번 보고 평균 내면 실력이 정확히 나옵니다!
1
2
3
4
5
6
7
# 한 번만 분리 (운에 좌우됨)
X_train, X_test = train_test_split(X, y, test_size=0.2)
accuracy = model.score(X_test, y_test) # 85% or 75%? 매번 다름!
# 교차 검증 (안정적)
scores = cross_val_score(model, X, y, cv=5)
accuracy = scores.mean() # 평균 80% (신뢰 가능!)
언제 생략해도 될까?
- ✅ 데이터가 수만 개 이상
- ✅ 빠른 프로토타입 제작 중
- ✅ 계산 시간이 매우 오래 걸림 (딥러닝 등)
최선의 방법:
1
2
3
4
5
6
7
8
9
10
11
12
13
# 1. 교차 검증으로 모델 선택
models = [LogisticRegression(), RandomForest(), SVM()]
best_model = None
best_score = 0
for model in models:
score = cross_val_score(model, X, y, cv=5).mean()
if score > best_score:
best_score = score
best_model = model
# 2. 선택된 모델을 전체 데이터로 학습
best_model.fit(X, y)
Q2: AUC가 정확도보다 좋은 이유가 뭔가요?
A: 불균형 데이터에 강하고, 임계값에 독립적이기 때문! 🎯
문제 상황: 사기 거래 탐지
1
2
3
4
5
6
7
8
9
# 데이터: 정상 9,900건, 사기 100건 (1%)
y = [0]*9900 + [1]*100
# 모델이 항상 "정상"이라고 예측
predictions = [0] * 10000
# 정확도
accuracy = 9900 / 10000 = 0.99 # 99%! (대박?)
# → 하지만 사기를 하나도 못 잡음! 💀
AUC의 장점:
장점 1: 불균형 데이터에 강함
1
2
3
4
5
# 정확도: 클래스 불균형에 영향 받음
# 항상 "정상" 예측 → 99% 정확도 (쓸모없음)
# AUC: 양성/음성을 동등하게 평가
# 항상 "정상" 예측 → AUC = 0.5 (동전 던지기)
장점 2: 임계값 독립적
1
2
3
4
5
6
7
8
# 정확도: 임계값 0.5 고정
proba = [0.51, 0.49, 0.48, 0.52]
predictions = [1, 0, 0, 1] # 0.5 기준
accuracy = ... # 임계값에 따라 달라짐
# AUC: 모든 임계값 고려
# 0.3, 0.4, 0.5, 0.6, 0.7... 전부 테스트
# → 전반적인 분류 능력 평가
실전 예시:
| 모델 | 정확도 | AUC | 평가 |
|---|---|---|---|
| A | 99% | 0.50 | ❌ 나쁨 (항상 음성 예측) |
| B | 85% | 0.92 | ✅ 좋음 (진짜 분류 잘함) |
| C | 95% | 0.75 | 🤔 보통 (불균형 데이터) |
언제 무엇을 사용?
1
2
3
4
5
6
7
8
# 균형 잡힌 데이터 (50:50)
→ 정확도 OK
# 불균형 데이터 (90:10, 99:1)
→ AUC 필수! (또는 F1-Score)
# 실무에서는
→ 정확도 + AUC + Precision + Recall 모두 확인!
Q3: K-Fold에서 K를 어떻게 정하나요?
A: 일반적으로 5 또는 10, 데이터 양에 따라 조정! 🔢
일반적인 가이드:
1
2
3
4
데이터 < 100개 → K = 5 (또는 LOOCV)
데이터 100~1,000 → K = 5
데이터 1,000~10,000 → K = 10
데이터 > 10,000 → K = 5 (계산 효율)
K 값에 따른 트레이드오프:
K가 작을 때 (K=3):
1
2
3
4
5
6
7
# 장점:
- 빠름 (3번만 학습)
- 각 훈련 세트가 큼 (67%)
# 단점:
- 평가 불안정 (샘플 적음)
- 편향(bias) 높음
K가 클 때 (K=10, K=20):
1
2
3
4
5
6
7
# 장점:
- 평가 안정적 (평균의 힘)
- 편향 낮음
# 단점:
- 느림 (10번, 20번 학습)
- 각 훈련 세트가 작아짐
특수한 경우:
LOOCV (Leave-One-Out Cross-Validation)
1
2
3
4
5
6
7
8
9
10
from sklearn.model_selection import LeaveOneOut
# K = n (데이터 개수)
# 데이터가 매우 적을 때 (< 100개)
loo = LeaveOneOut()
scores = cross_val_score(model, X, y, cv=loo)
# 장점: 최대한 많은 데이터로 학습
# 단점: 매우 느림 (n번 학습)
실전 추천:
1
2
3
4
5
6
7
8
# 기본값: K=5
scores = cross_val_score(model, X, y, cv=5)
# 좀 더 신뢰성 원하면: K=10
scores = cross_val_score(model, X, y, cv=10)
# 연구 논문 쓸 때: K=10
# 빠른 실험: K=3
계산 시간 고려:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import time
# K=5: 5번 학습
start = time.time()
scores_5 = cross_val_score(model, X, y, cv=5)
time_5 = time.time() - start
# K=10: 10번 학습
start = time.time()
scores_10 = cross_val_score(model, X, y, cv=10)
time_10 = time.time() - start
print(f"K=5: 평균 {scores_5.mean():.3f}, 시간 {time_5:.2f}초")
print(f"K=10: 평균 {scores_10.mean():.3f}, 시간 {time_10:.2f}초")
# 보통 성능 차이 < 1% but 시간 2배
Q4: ROC 곡선을 어떻게 해석하나요?
A: 왼쪽 위 모서리에 가까울수록 좋습니다! 📈
ROC 곡선 기본:
1
2
3
4
5
6
# 축의 의미
X축: FPR (False Positive Rate) = FP / (FP + TN)
→ "거짓 경보 비율" (정상을 양성으로 오판)
Y축: TPR (True Positive Rate) = TP / (TP + FN)
→ "진짜 양성 찾는 비율" (Recall과 같음)
그래프 해석:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
1.0 | ● ← 완벽한 모델 (0, 1)
TPR | /
| / ---- ← 좋은 모델 (왼쪽 위)
0.5 | / ---- ← 나쁜 모델 (대각선)
|/----
0.0 +----------------
0.0 0.5 1.0
FPR
왼쪽 위 모서리 = 최고!
→ FPR 낮고(거짓 경보 적음) + TPR 높음(진짜 많이 찾음)
대각선 = 동전 던지기
→ AUC = 0.5 (무작위)
오른쪽 아래 = 최악
→ AUC < 0.5 (예측을 반대로 하면 더 좋음!)
실전 예시:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 스팸 필터
# 완벽한 모델 (AUC = 1.0)
TPR = 1.0 # 스팸 100% 찾음
FPR = 0.0 # 정상 메일 하나도 안 막음
→ "신이시여!"
# 좋은 모델 (AUC = 0.9)
TPR = 0.95 # 스팸 95% 찾음
FPR = 0.05 # 정상 5% 오판
→ "실전 가능!"
# 나쁜 모델 (AUC = 0.6)
TPR = 0.6 # 스팸 60%만 찾음
FPR = 0.4 # 정상 40% 막음
→ "쓸모없음!"
곡선의 모양으로 판단:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# 모양 1: 계단식 (매우 좋음)
1|●
|●
|●
|●
0+----
→ 거의 완벽
# 모양 2: 부드러운 곡선 (좋음)
1| ●
| /
| /
|/
0+----
→ 실전 가능
# 모양 3: 대각선 (나쁨)
1| /
| /
| /
|/
0+----
→ 무작위
Q5: 회귀와 분류의 평가 지표를 헷갈려요!
A: 간단히 정리해드릴게요! 🎯
회귀 (숫자 예측):
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# 목표: 실제값과 예측값의 차이 최소화
# MAE (Mean Absolute Error)
→ 평균 절대 오차
→ "평균적으로 5만원 차이"
→ 이해하기 쉬움 ✅
# MSE (Mean Squared Error)
→ 평균 제곱 오차
→ 큰 오차에 큰 페널티
→ 단위가 제곱 ⚠️
# RMSE (Root Mean Squared Error)
→ MSE의 제곱근
→ 원래 단위로 돌아옴
→ 가장 많이 사용 ⭐
# R² (R-squared)
→ 설명력 (0~1)
→ "데이터를 80% 설명"
→ 비교에 좋음 👍
분류 (카테고리 예측):
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# 목표: 올바른 클래스 예측
# Accuracy (정확도)
→ 전체 중 맞춘 비율
→ 간단하지만 불균형에 약함 ⚠️
# Precision (정밀도)
→ "양성이라고 한 것 중 진짜 양성"
→ 거짓 양성 피하고 싶을 때 (스팸 필터)
# Recall (재현율)
→ "진짜 양성 중 찾아낸 비율"
→ 놓치면 안 될 때 (암 진단)
# F1-Score
→ Precision과 Recall의 조화 평균
→ 균형 잡힌 평가 ⭐
# AUC (Area Under ROC Curve)
→ 전반적인 분류 능력
→ 불균형 데이터에 강함 ⭐⭐
빠른 참조표:
| 문제 유형 | 주요 지표 | 보조 지표 |
|---|---|---|
| 회귀 | RMSE, R² | MAE, MSE |
| 분류 (균형) | Accuracy, F1 | Precision, Recall |
| 분류 (불균형) | AUC, F1 | Precision, Recall |
실전 팁:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# 회귀 평가
from sklearn.metrics import mean_squared_error, r2_score
import numpy as np
rmse = np.sqrt(mean_squared_error(y_test, y_pred))
r2 = r2_score(y_test, y_pred)
print(f"RMSE: {rmse:.2f}, R²: {r2:.3f}")
# 분류 평가 (균형)
from sklearn.metrics import accuracy_score, f1_score
acc = accuracy_score(y_test, y_pred)
f1 = f1_score(y_test, y_pred)
print(f"Accuracy: {acc:.3f}, F1: {f1:.3f}")
# 분류 평가 (불균형)
from sklearn.metrics import roc_auc_score, f1_score
auc = roc_auc_score(y_test, y_proba)
f1 = f1_score(y_test, y_pred)
print(f"AUC: {auc:.3f}, F1: {f1:.3f}")
📚 다음 학습
Day 97: ChatGPT API 활용하기 ⭐⭐⭐⭐
내일은 드디어 ChatGPT API를 활용해봅니다! AI와 대화하는 프로그램을 만들어요!
“정확도만 보면 속습니다. 문제에 맞는 평가 지표를 선택하세요!” 🚀
Day 96/100 Phase 10: AI/ML 입문 #100DaysOfPython
