ELPD는 모델이 새로운 데이터를 얼마나 잘 예측하는지를 보여주는 지표입니다.

ELPD는 모델이 새로운 데이터를 얼마나 잘 예측하는지를 보여주는 지표입니다.
Photo by Mildly Useful / Unsplash

기본 개념

  • 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 추정 새로운 데이터에 대한 일반화 성능 평가에 더 유리
해석의 직관성 덜 직관적일 수 있음 각 데이터에 대한 모델의 예측 성능을 직관적으로 평가
적용 상황 데이터셋이 클 때 유리, 빠름 데이터셋이 작거나, 더 높은 정확성이 필요한 경우