베이즈 추론에서 사전·사후 분포와 MCMC, Gibbs 샘플링
사전·사후 분포를 바탕으로 베이즈 추론을 구성하고 MCMC, Gibbs 샘플링의 선택과 수렴 진단을 정리한다.
2026-08-14 · 최초 발행 2024-04-29
사전지식이 데이터와 만나는 지점
베이즈 통계는 관측 전의 믿음인 사전 분포와 관측 데이터의 우도를 결합해, 관측 후의 믿음인 사후 분포를 만든다. 관계는 Posterior ∝ Likelihood × Prior로 나타낼 수 있으며, 정규화 상수는 주변우도(marginal likelihood)다.
사후분포가 단순하면 직접 다룰 수 있지만, 복잡한 모델에서는 표본을 얻는 과정이 문제의 중심이 된다. MCMC(Markov Chain Monte Carlo)는 마르코프 연쇄를 통해 이 사후분포를 근사하는 샘플을 생성하는 방법론이다. 대표적인 접근에는 Metropolis-Hastings, Gibbs, HMC/NUTS가 있다.
Gibbs 샘플링은 각 변수의 조건부분포를 번갈아 샘플링하는 블록 업데이트 방식이다. 조건부분포가 표준분포 형태로 닫혀 있으면 구현하기 수월하다.
모델 설정부터 의사결정까지 이어지는 흐름
베이즈 모델링은 문제를 정의한 뒤 모델·우도·사전을 정하고, 사후 추론과 진단·검증을 거쳐 사후예측과 의사결정으로 이어진다. 모델 비교는 예측 성능과 정보 기준인 LOO, WAIC를 바탕으로 수행한다.
사전 분포는 정보성 또는 약정보성으로 선택할 수 있다. 이는 과적합을 제어하고 안정적인 추정을 유도하는 데 사용된다. 공액 사전(conjugate)을 쓰면 계산이 단순해지며, 비공액 모델은 MCMC가 필요하다.
알고리즘은 모델의 구조에 맞춰 고른다. Metropolis-Hastings는 범용적이지만 튜닝이 필요하고, Gibbs는 조건부분포를 쉽게 구성할 수 있을 때 효율적이다. HMC/NUTS는 고차원 연속 파라미터에서 효율적이며, 선택의 기준은 혼합(mixing)을 개선하고 자기상관을 낮추는 데 있다.
수렴 여부는 R-hat(≤1.01~1.05), 유효 샘플 크기(ESS), 트레이스 및 ACF 플롯으로 점검한다. HMC에서 divergence나 treedepth 경고가 발생하면 재파라미터라이제이션 또는 step-size 조정이 필요하다. 체인 병렬화, 벡터화, 정규화와 비중심화 파라미터화도 속도와 안정성을 높이는 수단이다. 사후예측(PPC)과 교차검증(LOO)을 자동화하면 운영 편의성도 높일 수 있다.
R-hat>1.05 또는 ESS가 낮으면 반복 횟수를 늘리고 초기값을 다변화하거나 재파라미터라이제이션을 적용한다. HMC divergence가 다발하면 target_accept 상향(예: 0.9→0.99), 스케일 조정, 비중심화를 검토한다.
샘플러별로 달라지는 선택 기준
| 알고리즘 | 성능(수렴/효율) | 확장성(고차원) | 일관성(추정 안정성) | 안정성(수치/튜닝) | 운영 편의 |
|---|---|---|---|---|---|
| Metropolis-Hastings | 중간, 제안 분포 의존 | 중간 | 중간, 자기상관 높을 수 있음 | 튜닝 필요(제안분산) | 구현 용이, 해석 쉬움 |
| Gibbs | 높음(조건부분포 용이 시) | 낮음~중간(블록화 필요) | 높음, 수락-거부 없음 | 조건부분포 요구 조건 큼 | 특정 모델에 매우 편리 |
| HMC/NUTS | 높음(빠른 혼합) | 높음(연속 파라미터) | 높음, ESS/시간 우수 | 튜닝 자동화(NUTS), 기하정보 필요 | 현대적 라이브러리에서 표준 |
불확실성을 모델에 반영하는 적용 장면
A/B 테스트의 전환율 추정에는 베타-이항 모델을 사용할 수 있다. 사전은 약정보성 베타(1,1) 또는 (0.5,0.5)이며, 사후분포를 바탕으로 베스트 팔 선택과 베이지안 의사결정을 수행한다.
신용위험이나 사기탐지에서는 로지스틱 회귀에 계층 사전을 적용해 소표본 세그먼트를 안정화할 수 있다. 임계값은 사후예측 분포와 비용 함수를 이용해 최적화한다. 생산품 결함률 추정에서는 로버스트 포아송 또는 음이항 모델과 라인·공정별 랜덤효과를 두어, 불확실성을 포함한 품질 KPI를 관리한다.
상태공간 모델이나 다변량 회귀를 이용하는 시계열 예측에서는 베이지안 필터링으로 구조적 변동을 사전에 반영해 드리프트 과적합을 완화한다. 결측·잠재변수 모델에서는 Gibbs로 결측치와 파라미터를 교번 샘플링하고, 데이터 증강으로 수렴 안정화를 시도한다.
사후 신뢰구간은 의사결정 리스크를 가시화한다. 예를 들어 95% credible interval을 제공할 수 있다. 약정보성 사전을 도입하면 분산 과대 문제를 완화하고 지표 변동성이 1030% 감소할 수 있으며, 이는 도메인과 사전 설정에 의존한다. 고차원 연속 모델에서 HMC/NUTS를 사용하면 동일 ESS 기준 계산시간을 25배 단축할 수 있고, 자동 진단은 재작업률 감소에 기여한다.
베타-이항 모델을 PyMC로 구성하기
전제조건: Python ≥ 3.10, pymc==5.10.4, arviz==0.17.1
설정: 전환 수 x=56, 노출 n=400, 사전 Beta(1,1)
# pip install "pymc==5.10.4" "arviz==0.17.1"
import pymc as pm
import arviz as az
import numpy as np
rng = np.random.default_rng(42)
x, n = 56, 400
with pm.Model() as model:
p = pm.Beta("p", alpha=1.0, beta=1.0)
y = pm.Binomial("y", n=n, p=p, observed=x)
idata = pm.sample(
draws=2000, tune=1000, chains=4, target_accept=0.9, random_seed=42, progressbar=False
)
ppc = pm.sample_posterior_predictive(idata, var_names=["y"], random_seed=42, progressbar=False)
print(az.summary(idata, var_names=["p"], kind="stats"))
print("Posterior 95% CrI:", az.hdi(idata.posterior["p"], hdi_prob=0.95).to_numpy().mean(axis=(0,1)))
# 간단 진단
rhat = az.rhat(idata, var_names=["p"]).to_array().item()
ess = az.ess(idata, var_names=["p"]).to_array().item()
print(f"R-hat={rhat:.3f}, ESS={ess:.0f}")
# 사전-사후 비교(정규화 지양, 개략 값 출력)
mean_post = idata.posterior["p"].values.flatten().mean()
print(f"Posterior mean p ≈ {mean_post:.4f}")
R-hat>1.05 또는 ESS가 낮으면 draws/tune을 늘리거나 target_accept를 높인다. 극단 비율 데이터에서는 약정보성 사전(Beta(0.5,0.5))이 경계값 수렴 안정화에 쓰일 수 있다.
조건부분포를 번갈아 갱신하는 Gibbs 샘플러
전제조건: Python ≥ 3.10, numpy ≥ 1.26
설정: 목표분포 N(μ, Σ)에서 조건부분포가 정규인 사실 이용
import numpy as np
rng = np.random.default_rng(123)
# 목표: (X, Y) ~ N(mu, Sigma)
mu = np.array([0.0, 0.0])
Sigma = np.array([[1.0, 0.8],
[0.8, 1.5]])
# 조건부분포 파라미터 계산 보조
def cond_params(mu, Sigma, given_idx, val):
# X|Y 또는 Y|X의 평균/분산 계산
i, j = given_idx, 1 - given_idx
mu_i, mu_j = mu[i], mu[j]
s_ii, s_jj = Sigma[i, i], Sigma[j, j]
s_ij = Sigma[i, j]
mean = mu_i + s_ij / s_jj * (val - mu_j)
var = s_ii - s_ij**2 / s_jj
return mean, np.sqrt(var)
T = 50_000
burn = 5_000
samples = np.zeros((T, 2))
# 초기값
x, y = 0.0, 0.0
for t in range(T):
m_x, s_x = cond_params(mu, Sigma, given_idx=0, val=y)
x = rng.normal(m_x, s_x)
m_y, s_y = cond_params(mu, Sigma, given_idx=1, val=x)
y = rng.normal(m_y, s_y)
samples[t] = [x, y]
post = samples[burn:]
est_mean = post.mean(axis=0)
est_cov = np.cov(post.T)
print("Estimated mean:", est_mean)
print("Estimated covariance:\n", est_cov)
# 간단 자기상관 체크
def autocorr(x, lag=1):
x = x - x.mean()
return np.corrcoef(x[:-lag], x[lag:])[0,1]
print("ACF lag1 (X, Y):", autocorr(post[:,0]), autocorr(post[:,1]))
Gibbs는 블록 업데이트로 혼합을 개선할 수 있다. ACF가 높으면 블록 크기를 조정하거나 파라미터 재스케일링을 검토한다.