044 회귀 평가 지표 - R², MAPE
키워드: R2, MAPE
개요
R²와 MAPE는 MAE/RMSE와 다른 관점에서 모델 성능을 평가합니다. R²는 설명력을, MAPE는 백분율 오차를 측정합니다.
실습 환경
- Python 버전: 3.11 권장
- 필요 패키지:
pycaret[full]>=3.0
R² (R-squared, 결정 계수)
모델이 타겟 변동을 얼마나 설명하는지 측정:
R² = 1 - (SS_res / SS_tot)
= 1 - [Σ(yᵢ - ŷᵢ)² / Σ(yᵢ - ȳ)²]
- SS_res: 잔차 제곱합 (모델 오차)
- SS_tot: 총 제곱합 (타겟 변동)
import numpy as np
from sklearn.metrics import r2_score
y_true = np.array([100, 150, 200, 250, 300])
y_pred = np.array([110, 140, 210, 240, 295])
# 044 R² 계산
y_mean = y_true.mean()
ss_res = np.sum((y_true - y_pred) ** 2)
ss_tot = np.sum((y_true - y_mean) ** 2)
r2 = 1 - (ss_res / ss_tot)
print(f"R²: {r2:.4f}") # 0.982
# 044 sklearn으로 확인
r2_sklearn = r2_score(y_true, y_pred)
print(f"R² (sklearn): {r2_sklearn:.4f}")
R² 해석
| R² 값 | 해석 |
|---|---|
| 1.0 | 완벽한 예측 |
| 0.9+ | 매우 좋음 |
| 0.7-0.9 | 좋음 |
| 0.5-0.7 | 보통 |
| 0.3-0.5 | 약함 |
| < 0.3 | 나쁨 |
| 음수 | 평균보다 못함 |
# 044 R² 해석 예시
print("R² 해석:")
print(" R²=0.85는 모델이 타겟 변동의 85%를 설명한다는 의미")
print(" 나머지 15%는 설명되지 않는 변동 (노이즈, 누락된 특성 등)")
R²의 한계
1. 음수가 될 수 있음
y_true = np.array([10, 20, 30])
y_pred = np.array([100, 100, 100]) # 매우 나쁜 예측
r2 = r2_score(y_true, y_pred)
print(f"R² (나쁜 모델): {r2:.4f}") # 음수
# 044 평균으로 예측하는 것보다 못하면 R² < 0
2. 스케일에 독립적
# 044 동일한 R², 다른 절대 오차
y_true_small = np.array([1, 2, 3, 4, 5])
y_pred_small = np.array([1.1, 1.9, 3.1, 3.9, 5.1])
y_true_large = y_true_small * 1000
y_pred_large = y_pred_small * 1000
print(f"작은 스케일 R²: {r2_score(y_true_small, y_pred_small):.4f}")
print(f"큰 스케일 R²: {r2_score(y_true_large, y_pred_large):.4f}")
# 044 동일한 R²이지만 절대 오차는 1000배 차이
MAPE (Mean Absolute Percentage Error)
백분율 오차의 평균:
MAPE = (100/n) × Σ|(yᵢ - ŷᵢ) / yᵢ|
from sklearn.metrics import mean_absolute_percentage_error
y_true = np.array([100, 150, 200, 250, 300])
y_pred = np.array([110, 140, 210, 240, 295])
# 044 MAPE 계산
mape = np.mean(np.abs((y_true - y_pred) / y_true)) * 100
print(f"MAPE: {mape:.2f}%") # 5.07%
# 044 sklearn
mape_sklearn = mean_absolute_percentage_error(y_true, y_pred) * 100
print(f"MAPE (sklearn): {mape_sklearn:.2f}%")
MAPE 해석
| MAPE | 해석 |
|---|---|
| < 10% | 매우 정확 |
| 10-20% | 좋음 |
| 20-50% | 보통 |
| > 50% | 부정확 |
# 044 비즈니스 해석
mape = 8.5
print(f"MAPE {mape}%는 평균적으로 예측이 실제값의 {mape}% 정도 벗어난다는 의미")
print(f"예: 실제 가격 $100일 때, 예측은 $91.5 ~ $108.5 범위")
MAPE의 한계
1. 0에 가까운 값에서 폭발
y_true = np.array([0.001, 10, 20])
y_pred = np.array([0.002, 11, 19])
# 0에 가까운 값이 있으면 MAPE 폭발
mape = np.mean(np.abs((y_true - y_pred) / y_true)) * 100
print(f"MAPE (0 포함): {mape:.2f}%") # 매우 큰 값
2. 비대칭성
# 044 과대 예측과 과소 예측의 비대칭
y_true = np.array([100, 100])
y_pred_over = np.array([200, 200]) # 2배 과대 예측
y_pred_under = np.array([50, 50]) # 절반 과소 예측
mape_over = mean_absolute_percentage_error(y_true, y_pred_over) * 100
mape_under = mean_absolute_percentage_error(y_true, y_pred_under) * 100
print(f"과대 예측 MAPE: {mape_over}%") # 100%
print(f"과소 예측 MAPE: {mape_under}%") # 50%
# 044 같은 비율이지만 MAPE가 다름
PyCaret에서 R², MAPE 사용
from pycaret.regression import *
from pycaret.datasets import get_data
data = get_data('boston')
reg = setup(data, target='medv', session_id=42, verbose=False)
# 044 모델 생성
model = create_model('rf', verbose=False)
results = pull()
print("평가 지표:")
print(f"R²: {results['R2'].mean():.4f}")
print(f"MAPE: {results['MAPE'].mean():.4f}")
# 044 R² 기준 최적 모델
best_r2 = compare_models(sort='R2', n_select=1)
# 044 튜닝도 R² 기준
tuned = tune_model(model, optimize='R2')
지표 비교 종합
from pycaret.regression import *
from pycaret.datasets import get_data
import pandas as pd
data = get_data('boston')
reg = setup(data, target='medv', session_id=42, verbose=False)
# 044 여러 모델 비교
models_to_compare = ['lr', 'rf', 'xgboost', 'lightgbm']
results = []
for model_name in models_to_compare:
model = create_model(model_name, verbose=False)
metrics = pull()
results.append({
'Model': model_name,
'MAE': metrics['MAE'].mean(),
'RMSE': metrics['RMSE'].mean(),
'R2': metrics['R2'].mean(),
'MAPE': metrics['MAPE'].mean()
})
df = pd.DataFrame(results)
print("\n모델별 지표 비교:")
print(df.round(4))
지표 선택 가이드
| 상황 | 권장 지표 |
|---|---|
| 모델 설명력 평가 | R² |
| 비즈니스 보고 | MAPE |
| 이상치 있음 | MAE |
| 큰 오차 중시 | RMSE |
| 0 근처 값 있음 | MAE, RMSE (MAPE 피함) |
| 다른 스케일 비교 | MAPE, R² |
정리
- R²: 모델의 설명력 (0~1, 음수 가능)
- MAPE: 백분율 오차, 비즈니스 해석 용이
- R²가 높아도 절대 오차가 클 수 있음
- MAPE는 0에 가까운 값에서 문제
- 단일 지표가 아닌 여러 지표 종합 평가 권장
다음 글 예고
다음 글에서는 선형 회귀 상세를 다룹니다.
PyCaret 머신러닝 마스터 시리즈 #044