기본 개념
- ELPD(Expected Log Predictive Density)는 모델이 새로운 데이터를 얼마나 잘 예측하는지를 나타내는 지표로, 주어진 데이터 포인트에 대해 모델이 예측한 확률의 로그 값(로그확률)을 합산한 것입니다. $$\text{ELPD} = \sum_{i=1}^{n} \log p(y_i \mid \text{data})$$
- $n$: 데이터 포인트의 수
- $y_i$: 실제 관측된 데이터 포인트
- $p(y_i \mid \text{data})$: 모델이 해당 데이터 포인트에 대해 예측한 확률
- 확률은 일반적으로 0과 1 사이의 값이기 때문에, 여러 개의 확률 값을 곱하면 그 결과는 매우 작아질 수 있고 이로 인해서 무시되는 값이 발생하면 확률 값의 왜곡이 발생할 수 있으며, 나아가 모델 비교도 어려워진다.
예시
- 예를 들어, 어떤 데이터 세트가 3개의 관측값 $y_1$, $y_2$, $y_3$로 구성되어 있다고 가정해 봅시다. 모델이 각 데이터 포인트에 대해 다음과 같은 예측 확률을 제공했다고 가정합니다:
- $p(y_1 \mid \text{data}) = 0.8$, $p(y_2 \mid \text{data}) = 0.5$, $p(y_3 \mid \text{data}) = 0.7$
- 그럼 ELPD는 다음과 같이 계산됩니다:
$$\text{ELPD} = \log(0.8) + \log(0.5) + \log(0.7)≈ -1.273$$
- 해석해보면, ELPD가 -1.273이므로, 모델이 주어진 데이터에 대해 어느 정도 잘 예측했지만, 완벽하지는 않음을 알 수 있습니다.
- ELPD 값이 높을수록 모델이 실제 데이터를 잘 예측하고 있다는 것을 의미합니다.
- 반대로, ELPD 값이 낮거나 음수일 경우, 모델이 데이터에 대해 잘 예측하지 못하고 있을 가능성이 있습니다.
코드
import numpy as np
from scipy.stats import norm
# 예제 데이터 생성
np.random.seed(42)
X = np.random.normal(0, 1, 100)
Y = 2.5 * X + np.random.normal(0, 1, 100)
# 간단한 선형 회귀 모델: Y = aX + b, 여기서 a = 2.5, b = 0 (가정)
a = 2.5
b = 0
sigma = 1 # 오차(표준편차) 가정
# 모델의 예측
Y_pred = a * X + b
# 로그 우도 계산
log_likelihoods = norm.logpdf(Y, loc=Y_pred, scale=sigma)
# ELPD 계산
ELPD = np.sum(log_likelihoods)
# 결과 출력
print(f"ELPD: {ELPD}")
ELPD: -136.93821065514777
ELPD 기반 평가 방법론
- WAIC: WAIC는 모델의 예측 성능을 평가하는 정보 기준 중 하나로, 모델의 복잡성을 벌점으로 고려한 ELPD 추정치입니다. WAIC는 각 데이터 포인트에 대한 posterior predictive distribution을 평가하여, 이를 기반으로 ELPD를 추정합니다
import numpy as np
from scipy.stats import norm
# 예제 데이터 생성
np.random.seed(42)
X = np.random.normal(0, 1, 100)
Y = 2.5 * X + np.random.normal(0, 1, 100)
# 간단한 선형 회귀 모델
a = 2.5 # 선형 회귀 계수
b = 0 # 절편
sigma = 1 # 오차의 표준편차
# 모델의 예측
Y_pred = a * X + b
# 로그 우도 계산
log_likelihoods = norm.logpdf(Y, loc=Y_pred, scale=sigma)
# 각 데이터 포인트별로 로그 우도 계산
lppd = np.sum(np.log(np.mean(np.exp(log_likelihoods))))
# 벌점 계산 (모델 복잡성을 고려한 보정)
p_waic = np.sum(np.var(log_likelihoods))
# WAIC 계산
WAIC = -2 * (lppd - p_waic)
print(f"WAIC: {WAIC}")
WAIC: 3.2927246702999566
- LOO:LOO는 교차 검증 기법의 하나로, 데이터셋에서 한 개의 데이터 포인트를 제외하고 모델을 학습한 뒤, 그 데이터 포인트에 대한 예측 성능을 평가하는 방식입니다. 이 과정을 모든 데이터 포인트에 대해 반복하여 평균 성능을 구합니다.
import numpy as np
from scipy.stats import norm
# 예제 데이터 생성
np.random.seed(42)
X = np.random.normal(0, 1, 100)
Y = 2.5 * X + np.random.normal(0, 1, 100)
# 간단한 선형 회귀 모델
a = 2.5 # 선형 회귀 계수
b = 0 # 절편
sigma = 1 # 오차의 표준편차
# LOO-CV를 위한 로그 우도 계산 함수
def log_likelihood_loo(X_train, Y_train, X_test, Y_test, a, b, sigma):
# 간단한 선형 회귀 예측
Y_pred = a * X_test + b
# 로그 우도 계산
return norm.logpdf(Y_test, loc=Y_pred, scale=sigma)
# LOO-CV 계산
n = len(X)
log_likelihoods_loo = np.zeros(n)
for i in range(n):
# Leave-one-out 방식: i번째 데이터 포인트를 제외하고 학습
X_train = np.delete(X, i)
Y_train = np.delete(Y, i)
# i번째 데이터 포인트 예측 (테스트)
X_test = X[i]
Y_test = Y[i]
# i번째 데이터에 대해 로그 우도 계산
log_likelihoods_loo[i] = log_likelihood_loo(X_train, Y_train, X_test, Y_test, a, b, sigma)
# LOO ELPD 계산
ELPD_LOO = np.sum(log_likelihoods_loo)
print(f"LOO ELPD: {ELPD_LOO}")
LOO ELPD: -136.93821065514777
언제 쓸 것인가?
특징 |
WAIC |
LOO-CV |
계산 방식 |
전체 데이터셋에서 ELPD 추정 후 복잡성 벌점 적용 |
각 데이터 포인트를 순차적으로 제외하며 학습 및 평가 |
모델 복잡성 보정 |
모델 복잡성을 고려하여 벌점 추가 |
데이터 포인트별 성능을 평가하여 적합도 계산 |
계산 비용 |
상대적으로 적음 |
데이터셋이 클 경우 매우 큼 (PSIS-LOO로 개선 가능) |
예측 성능 평가 |
불확실성을 반영하여 ELPD 추정 |
새로운 데이터에 대한 일반화 성능 평가에 더 유리 |
해석의 직관성 |
덜 직관적일 수 있음 |
각 데이터에 대한 모델의 예측 성능을 직관적으로 평가 |
적용 상황 |
데이터셋이 클 때 유리, 빠름 |
데이터셋이 작거나, 더 높은 정확성이 필요한 경우 |