베이지안 통계 (Bayesian Statistics)¶
데이터가 주어졌을 때 모수의 불확실성을 확률로 표현하는 통계적 접근법. ML/DL에서 불확실성 정량화, 정규화, 하이퍼파라미터 튜닝 등에 활용됨.
왜 베이지안인가¶
빈도주의의 한계: - 점 추정만 제공, 불확실성 표현 제한적 - 사전 지식 반영 어려움 - "모수는 고정" 가정이 때로 부자연스러움
베이지안의 장점: - 불확실성 정량화: 예측의 신뢰도를 확률로 표현 - 사전 지식 활용: 기존 연구, 도메인 지식 반영 - 소표본에서 강점: 데이터가 적어도 합리적 추론 - 자연스러운 업데이트: 새 데이터로 믿음 점진적 갱신
베이지안 vs 빈도주의¶
| 관점 | 빈도주의 (Frequentist) | 베이지안 (Bayesian) |
|---|---|---|
| 확률의 의미 | 장기적 빈도 | 믿음의 정도 |
| 모수 θ | 고정된 미지의 값 | 확률 변수 |
| 추론 대상 | P(Data | θ) | P(θ | Data) |
| 사전 정보 | 사용 안 함 | 사전 분포로 반영 |
| 결과 | 점 추정, 신뢰구간 | 사후 분포 전체 |
| 해석 | "반복 시 95%가 참값 포함" | "95% 확률로 이 구간에 있음" |
직관적 차이:
질문: "이 동전의 앞면 확률은?"
빈도주의: "동전을 무한히 던지면 앞면 비율이 θ에 수렴"
θ는 고정된 값, 우리가 모를 뿐
베이지안: "내 믿음으로는 θ가 0.4~0.6 사이일 확률이 90%"
θ 자체가 불확실하고, 데이터로 업데이트함
베이즈 정리 복습¶
| 항 | 이름 | 의미 | 역할 |
|---|---|---|---|
| \(P(\theta)\) | 사전 분포 | 데이터 전 모수에 대한 믿음 | 기존 지식 반영 |
| \(P(D\|\theta)\) | 우도 | 모수가 주어졌을 때 데이터 확률 | 데이터의 증거력 |
| \(P(\theta\|D)\) | 사후 분포 | 데이터 후 모수에 대한 믿음 | 최종 추론 결과 |
| \(P(D)\) | 증거 | 정규화 상수 | 분포가 합이 1이 되게 |
핵심 공식 (비례 형태): $\(\text{Posterior} \propto \text{Likelihood} \times \text{Prior}\)$
베이즈 업데이트 예시¶
동전 던지기¶
import numpy as np
from scipy import stats
import matplotlib.pyplot as plt
def coin_flip_posterior(n_heads, n_tails, prior_alpha=1, prior_beta=1):
"""
Prior: Beta(alpha, beta)
Data: n_heads 성공, n_tails 실패
Posterior: Beta(alpha + n_heads, beta + n_tails)
"""
return stats.beta(prior_alpha + n_heads, prior_beta + n_tails)
# 시뮬레이션
np.random.seed(42)
true_p = 0.7
x = np.linspace(0, 1, 200)
fig, axes = plt.subplots(2, 3, figsize=(15, 8))
prior = stats.beta(1, 1) # 무정보적 사전 (균등분포)
n_heads, n_tails = 0, 0
for idx, n_flips in enumerate([0, 1, 5, 10, 50, 200]):
ax = axes.flatten()[idx]
# 새로운 관측
new_flips = n_flips - (n_heads + n_tails)
if new_flips > 0:
new_results = np.random.binomial(1, true_p, new_flips)
n_heads += new_results.sum()
n_tails += new_flips - new_results.sum()
posterior = coin_flip_posterior(n_heads, n_tails)
ax.plot(x, prior.pdf(x), 'b--', label='Prior', alpha=0.5)
ax.plot(x, posterior.pdf(x), 'r-', label='Posterior', linewidth=2)
ax.axvline(x=true_p, color='g', linestyle=':', label=f'True p={true_p}')
ax.fill_between(x, posterior.pdf(x), alpha=0.3, color='red')
ax.set_title(f'n={n_flips} (heads={n_heads})')
ax.legend()
ax.set_xlim(0, 1)
plt.tight_layout()
관찰 포인트: 1. 데이터 0개: 사후 = 사전 (업데이트 없음) 2. 데이터 적을 때: 사전이 강하게 영향 3. 데이터 많아지면: 사전 영향 감소, 데이터가 지배
사전 분포 (Prior Distribution)¶
사전 분포의 종류¶
| 유형 | 설명 | 예시 |
|---|---|---|
| 무정보적 (Non-informative) | 모수에 대해 아는 것 없음 | Uniform, Jeffreys |
| 약 정보적 (Weakly informative) | 합리적 범위만 제한 | 넓은 Normal, Half-Cauchy |
| 정보적 (Informative) | 강한 사전 믿음 | 이전 연구 결과 기반 |
| 켤레 사전 (Conjugate) | 계산 편의성 | 우도에 맞는 특정 분포 |
켤레 사전 분포 (Conjugate Prior)¶
사후 분포가 사전 분포와 같은 분포 family를 따르는 경우.
| 우도 | 켤레 사전 | 사후 | 예시 |
|---|---|---|---|
| Binomial | Beta | Beta | 성공률 추정 |
| Poisson | Gamma | Gamma | 발생률 추정 |
| Normal (μ 알려짐, σ² 추정) | Inverse-Gamma | Inverse-Gamma | 분산 추정 |
| Normal (σ² 알려짐, μ 추정) | Normal | Normal | 평균 추정 |
| Exponential | Gamma | Gamma | 대기 시간 |
| Multinomial | Dirichlet | Dirichlet | 범주 확률 |
왜 중요한가? 해석적 계산 가능 → MCMC 없이 빠른 추론.
# Beta-Binomial 예시: 클릭률 추정
def beta_binomial_update(alpha_prior, beta_prior, n_clicks, n_impressions):
"""
Prior: Beta(alpha_prior, beta_prior)
Data: n_clicks clicks in n_impressions
Posterior: Beta(alpha + clicks, beta + non-clicks)
"""
alpha_post = alpha_prior + n_clicks
beta_post = beta_prior + n_impressions - n_clicks
return alpha_post, beta_post
# 사전: Beta(2, 8) -> 평균 0.2에 대한 약한 믿음 (과거 경험)
# 데이터: 50 클릭 / 200 노출
alpha_post, beta_post = beta_binomial_update(2, 8, 50, 200)
posterior = stats.beta(alpha_post, beta_post)
print(f"사후 평균: {posterior.mean():.4f}")
print(f"사후 표준편차: {posterior.std():.4f}")
print(f"95% 신용 구간: {posterior.ppf([0.025, 0.975]).round(4)}")
# MLE (최대우도) 비교
mle = 50 / 200
print(f"MLE: {mle:.4f}")
# 사전이 MLE를 약간 수축(shrinkage)시킴
사전 분포 선택 가이드¶
실무 접근법:
- 도메인 지식 있으면 → 정보적 사전
-
과거 연구, 전문가 의견 반영
-
범위만 알면 → 약 정보적 사전
-
확률은 [0,1], 표준편차는 양수 등
-
전혀 모르면 → 무정보적/약 정보적 사전
- 결과에 크게 영향 안 주면서 정규화
# 약 정보적 사전 예시들
# 확률 (0~1): Beta(1, 1) = Uniform, 또는 Beta(2, 2)
# 양수 척도 (std 등): Half-Normal(0, 10) 또는 Half-Cauchy(0, 5)
# 무제한 위치 (mean): Normal(0, 100)
# 상관계수: LKJ prior (상관 행렬용)
# 권장: Stan, PyMC 문서의 "prior choice recommendations" 참고
사전 민감도 분석¶
# 다양한 사전으로 분석해서 결과가 얼마나 달라지는지 확인
priors = [(1, 1), (2, 8), (5, 5), (10, 2)] # 다양한 Beta 사전
n_clicks, n_total = 50, 200
plt.figure(figsize=(10, 4))
x = np.linspace(0, 0.5, 200)
for alpha, beta in priors:
alpha_post, beta_post = beta_binomial_update(alpha, beta, n_clicks, n_total)
posterior = stats.beta(alpha_post, beta_post)
label = f'Prior Beta({alpha},{beta}), Post mean={posterior.mean():.3f}'
plt.plot(x, posterior.pdf(x), label=label)
plt.axvline(x=n_clicks/n_total, color='k', linestyle='--', label='MLE')
plt.legend()
plt.title('Prior Sensitivity Analysis')
# 데이터가 충분하면 사전 선택에 덜 민감함
사후 분포 추론¶
점 추정¶
| 추정량 | 정의 | 손실 함수 | 사용 |
|---|---|---|---|
| MAP | \(\arg\max_\theta P(\theta\|D)\) | 0-1 손실 | 뾰족한 분포 |
| 사후 평균 | \(E[\theta\|D]\) | 제곱 손실 | 대칭 분포 |
| 사후 중앙값 | Median of \(P(\theta\|D)\) | 절대 손실 | 왜곡된 분포 |
# MAP vs 사후 평균
posterior = stats.beta(52, 158) # 클릭률 예시
# MAP (최빈값): Beta의 mode = (α-1)/(α+β-2)
map_estimate = (52 - 1) / (52 + 158 - 2)
posterior_mean = posterior.mean()
posterior_median = posterior.median()
print(f"MAP: {map_estimate:.4f}")
print(f"사후 평균: {posterior_mean:.4f}")
print(f"사후 중앙값: {posterior_median:.4f}")
# 대칭 분포에서는 세 값이 비슷
# 왜곡된 분포에서는 다를 수 있음
신용 구간 (Credible Interval)¶
베이지안 신용 구간: "모수가 이 구간에 있을 확률이 95%"
# Equal-tailed interval (ETI)
# 양쪽 2.5%씩 자름
ci_eti = posterior.ppf([0.025, 0.975])
print(f"95% ETI: {ci_eti.round(4)}")
# Highest Posterior Density (HPD) interval
# 가장 좁은 구간 (비대칭 분포에서 더 유용)
from scipy.optimize import minimize_scalar
def hpd_interval(dist, prob=0.95):
"""HPD 구간: 확률 밀도가 가장 높은 구간"""
alpha = 1 - prob
def interval_width(lower_prob):
lower = dist.ppf(lower_prob)
upper = dist.ppf(lower_prob + prob)
return upper - lower
result = minimize_scalar(interval_width, bounds=(0, alpha), method='bounded')
lower = dist.ppf(result.x)
upper = dist.ppf(result.x + prob)
return lower, upper
hpd = hpd_interval(posterior)
print(f"95% HPD: {np.round(hpd, 4)}")
신용 구간 vs 신뢰 구간¶
| 신용 구간 (Credible Interval) | 신뢰 구간 (Confidence Interval) |
|---|---|
| "θ가 이 구간에 있을 확률 95%" | "이런 구간들 중 95%가 θ 포함" |
| 직관적 해석 | 해석 어려움 |
| 사후 분포 기반 | 표본 분포 기반 |
| 사전 분포 필요 | 사전 분포 불필요 |
MCMC (Markov Chain Monte Carlo)¶
복잡한 사후 분포에서 샘플을 추출하는 방법. 해석적 계산 불가능할 때 필수.
왜 MCMC가 필요한가¶
문제: \(P(D) = \int P(D|\theta)P(\theta) d\theta\) 계산이 어려움 (고차원 적분)
해결: 사후 분포에서 직접 샘플 추출 → 적분 대신 샘플 평균
Metropolis-Hastings 알고리즘¶
def metropolis_hastings(log_posterior, initial, n_samples, proposal_std=0.5):
"""
Metropolis-Hastings 알고리즘
log_posterior: 사후의 log (정규화 상수 몰라도 됨)
"""
samples = [initial]
current = initial
accepted = 0
for _ in range(n_samples - 1):
# 1. 제안 분포에서 후보 제안
proposal = current + np.random.normal(0, proposal_std)
# 2. 수락 확률 계산 (log 스케일)
log_accept_ratio = log_posterior(proposal) - log_posterior(current)
# 3. 수락 또는 거절
if np.log(np.random.random()) < log_accept_ratio:
current = proposal
accepted += 1
samples.append(current)
acceptance_rate = accepted / (n_samples - 1)
return np.array(samples), acceptance_rate
# 예시: Beta(52, 158)에서 샘플링
def log_beta_posterior(theta, alpha=52, beta=158):
if theta <= 0 or theta >= 1:
return -np.inf
return (alpha - 1) * np.log(theta) + (beta - 1) * np.log(1 - theta)
samples, acc_rate = metropolis_hastings(log_beta_posterior, 0.3, 20000, proposal_std=0.02)
print(f"수락률: {acc_rate:.2%}") # 이상적: 20-50%
# 번인(burn-in) 제거
samples = samples[5000:]
print(f"MCMC 평균: {samples.mean():.4f}")
print(f"실제 평균: {stats.beta(52, 158).mean():.4f}")
MCMC 수렴 진단 (중요!)¶
문제: MCMC가 수렴했는지 어떻게 알 수 있나?
def diagnose_mcmc(samples, n_chains=4):
"""MCMC 진단"""
# 1. Trace plot: 시계열 확인
plt.figure(figsize=(12, 3))
plt.plot(samples, alpha=0.7)
plt.xlabel('Iteration')
plt.ylabel('θ')
plt.title('Trace Plot')
# 이상적: 특정 값 주위를 랜덤하게 왔다갔다 (fuzzy caterpillar)
# 나쁜 징후: 추세, 긴 자기상관, 제자리 멈춤
# R-hat (Gelman-Rubin) 통계량
# 여러 체인을 독립적으로 돌려서 비교
# R-hat < 1.01이면 수렴으로 간주
# ESS (Effective Sample Size)
# 자기상관 고려한 "실질적" 샘플 수
# ESS > 400 권장
def effective_sample_size(samples):
"""간단한 ESS 계산"""
n = len(samples)
acf = np.correlate(samples - samples.mean(), samples - samples.mean(), mode='full')
acf = acf[n-1:] / acf[n-1]
# 처음으로 음수가 되는 지점까지의 자기상관 합
for i in range(1, len(acf)):
if acf[i] < 0:
break
tau = 1 + 2 * acf[1:i].sum() # integrated autocorrelation time
return n / tau
ess = effective_sample_size(samples)
print(f"ESS: {ess:.0f} / {len(samples)} samples")
PyMC를 이용한 베이지안 추론¶
import pymc as pm
import arviz as az
# 클릭률 추정 예시
n_clicks = 50
n_impressions = 200
with pm.Model() as click_model:
# 사전 분포
p = pm.Beta('p', alpha=2, beta=8)
# 우도
clicks = pm.Binomial('clicks', n=n_impressions, p=p, observed=n_clicks)
# MCMC 샘플링
trace = pm.sample(2000, tune=1000, return_inferencedata=True,
random_seed=42)
# 결과 요약
print(az.summary(trace))
# 시각화
az.plot_posterior(trace)
az.plot_trace(trace)
# 수렴 진단
print(f"R-hat: {az.rhat(trace)}")
print(f"ESS: {az.ess(trace)}")
선형 회귀 (베이지안)¶
import pymc as pm
# 데이터 생성
np.random.seed(42)
n = 100
X = np.random.randn(n, 2)
true_weights = np.array([2.0, -1.5])
true_sigma = 0.5
y = X @ true_weights + np.random.randn(n) * true_sigma
with pm.Model() as linear_model:
# 사전 분포 (약 정보적)
weights = pm.Normal('weights', mu=0, sigma=10, shape=2)
sigma = pm.HalfNormal('sigma', sigma=1)
# 평균
mu = pm.math.dot(X, weights)
# 우도
y_obs = pm.Normal('y', mu=mu, sigma=sigma, observed=y)
# 추론
trace = pm.sample(2000, tune=1000, return_inferencedata=True)
# 결과
print(az.summary(trace, var_names=['weights', 'sigma']))
# 예측 불확실성
with linear_model:
pm.sample_posterior_predictive(trace, extend_inferencedata=True)
# 새 데이터에 대한 예측 분포 시각화 가능
베이지안 딥러닝¶
MC Dropout (Monte Carlo Dropout)¶
추론 시에도 Dropout 적용 → 예측 불확실성 추정.
이론적 배경: Dropout은 가우시안 프로세스의 근사 (Gal & Ghahramani, 2016)
import torch
import torch.nn as nn
class MCDropoutModel(nn.Module):
def __init__(self, input_dim, hidden_dim, output_dim, dropout_rate=0.5):
super().__init__()
self.fc1 = nn.Linear(input_dim, hidden_dim)
self.fc2 = nn.Linear(hidden_dim, hidden_dim)
self.fc3 = nn.Linear(hidden_dim, output_dim)
self.dropout = nn.Dropout(dropout_rate)
def forward(self, x):
x = torch.relu(self.fc1(x))
x = self.dropout(x) # 추론 시에도 적용!
x = torch.relu(self.fc2(x))
x = self.dropout(x)
return self.fc3(x)
def predict_with_uncertainty(model, x, n_samples=100):
"""MC Dropout으로 예측 불확실성 추정"""
model.train() # Dropout 활성화
predictions = []
with torch.no_grad():
for _ in range(n_samples):
pred = model(x)
predictions.append(pred)
predictions = torch.stack(predictions)
mean = predictions.mean(dim=0)
std = predictions.std(dim=0) # 불확실성
return mean, std
# 사용 예시
model = MCDropoutModel(10, 64, 1)
x = torch.randn(5, 10) # 5개 샘플
mean, uncertainty = predict_with_uncertainty(model, x)
# 불확실성이 높은 샘플 = 모델이 확신 못함
print(f"예측: {mean.squeeze()}")
print(f"불확실성: {uncertainty.squeeze()}")
언제 불확실성이 높은가?¶
- Epistemic uncertainty (모델 불확실성): 학습 데이터 부족
- 학습 데이터와 다른 영역의 입력
-
더 많은 데이터로 줄일 수 있음
-
Aleatoric uncertainty (데이터 불확실성): 데이터 자체의 노이즈
- 입력이 출력을 완전히 결정하지 못함
- 더 많은 데이터로 줄일 수 없음
# Heteroscedastic regression: aleatoric 불확실성 모델링
class UncertaintyModel(nn.Module):
def __init__(self, input_dim, hidden_dim):
super().__init__()
self.shared = nn.Sequential(
nn.Linear(input_dim, hidden_dim),
nn.ReLU(),
nn.Linear(hidden_dim, hidden_dim),
nn.ReLU()
)
self.mean_head = nn.Linear(hidden_dim, 1)
self.var_head = nn.Linear(hidden_dim, 1) # log variance
def forward(self, x):
h = self.shared(x)
mean = self.mean_head(h)
log_var = self.var_head(h) # log 스케일로 양수 보장
return mean, log_var
# Negative log-likelihood loss
def nll_loss(mean, log_var, target):
var = torch.exp(log_var)
return 0.5 * (log_var + (target - mean)**2 / var).mean()
ML에서의 베이지안 응용¶
베이지안 최적화 (Bayesian Optimization)¶
하이퍼파라미터 튜닝에 활용. Grid/Random search보다 효율적.
from sklearn.gaussian_process import GaussianProcessRegressor
from sklearn.gaussian_process.kernels import RBF, ConstantKernel
def bayesian_optimization(objective, bounds, n_iterations=30, n_initial=5):
"""
베이지안 최적화
objective: 최대화할 함수 (black-box)
bounds: (min, max) 튜플
"""
X_observed = []
y_observed = []
# 1. 초기 랜덤 탐색
for _ in range(n_initial):
x = np.random.uniform(bounds[0], bounds[1])
y = objective(x)
X_observed.append([x])
y_observed.append(y)
X_observed = np.array(X_observed)
y_observed = np.array(y_observed)
# GP 모델 (surrogate function)
kernel = ConstantKernel() * RBF()
gp = GaussianProcessRegressor(kernel=kernel, n_restarts_optimizer=10,
alpha=1e-6)
for i in range(n_iterations):
gp.fit(X_observed, y_observed)
# 2. Acquisition function 최대화
# Expected Improvement (EI)
x_candidates = np.linspace(bounds[0], bounds[1], 1000).reshape(-1, 1)
mu, sigma = gp.predict(x_candidates, return_std=True)
best_y = y_observed.max()
with np.errstate(divide='warn'):
improvement = mu - best_y
Z = improvement / (sigma + 1e-9)
ei = improvement * stats.norm.cdf(Z) + sigma * stats.norm.pdf(Z)
ei[sigma < 1e-9] = 0
# 3. 다음 탐색 지점
x_next = x_candidates[np.argmax(ei)]
y_next = objective(x_next[0])
X_observed = np.vstack([X_observed, x_next])
y_observed = np.append(y_observed, y_next)
if (i + 1) % 10 == 0:
print(f"Iter {i+1}: best y = {y_observed.max():.4f}")
best_idx = np.argmax(y_observed)
return X_observed[best_idx], y_observed[best_idx]
# 예시: 학습률 최적화
def objective(lr):
# 실제로는 모델 학습 후 validation loss 반환
return -((lr - 0.01)**2 * 1000 + 0.1 * np.random.randn())
best_lr, best_score = bayesian_optimization(objective, bounds=[0.0001, 0.1])
print(f"최적 학습률: {best_lr[0]:.6f}")
L2 정규화의 베이지안 해석¶
핵심 통찰: L2 정규화 = 가중치에 대한 가우시안 사전
# L2 정규화 손실: L(w) + λ||w||²
#
# 베이지안 해석:
# - 우도: P(D|w) ∝ exp(-L(w))
# - 가우시안 사전: P(w) ∝ exp(-λ||w||²) = N(0, 1/(2λ)I)
# - MAP 추정 = L2 정규화 최소화
#
# 따라서:
lambda_reg = 0.01
prior_variance = 1 / (2 * lambda_reg)
print(f"L2 λ={lambda_reg} ↔ 사전 분산 σ²={prior_variance}")
# λ가 크면 → 사전 분산 작음 → 가중치를 0에 가깝게 제한
# λ가 작으면 → 사전 분산 큼 → 가중치 자유도 높음
L1 정규화의 베이지안 해석¶
# L1 정규화 = 라플라스 사전
# P(w) ∝ exp(-λ|w|) = Laplace(0, 1/λ)
#
# 라플라스 분포는 0에서 뾰족함 → 많은 가중치가 정확히 0
# → Sparse solution (희소성)
모델 비교 (베이즈 팩터)¶
두 모델의 상대적 증거 비교.
# BIC를 이용한 베이즈 팩터 근사
def approx_log_bayes_factor(bic1, bic2):
"""
log(BF) ≈ (BIC2 - BIC1) / 2
"""
return (bic2 - bic1) / 2
# 해석 (Kass & Raftery, 1995)
# log(BF) > 5 (BF > 150): 매우 강한 증거 (M1 선호)
# log(BF) > 3 (BF > 20): 강한 증거
# log(BF) > 1 (BF > 3): 양의 증거
# log(BF) ≈ 0 (BF ≈ 1): 증거 없음 (동등)
# log(BF) < -1: M2 선호
# 예시
bic_simple = 100 # 간단한 모델
bic_complex = 95 # 복잡한 모델
log_bf = approx_log_bayes_factor(bic_simple, bic_complex)
print(f"log(BF) = {log_bf:.2f}")
print(f"BF = {np.exp(log_bf):.2f}")
if log_bf > 1:
print("복잡한 모델 선호")
else:
print("간단한 모델 선호 (Occam's razor)")
흔한 실수와 오해¶
1. 사전 분포를 데이터에서 결정¶
# 나쁜 예: 데이터 보고 사전 설정 (double dipping)
# data = ...
# prior_mean = data.mean() # 틀림!
# 사전은 데이터 보기 전의 믿음이어야 함
# 데이터로 사전을 정하면 사후가 과적합됨
2. "무정보적" 사전이 항상 좋다고 생각¶
# 무정보적 사전의 문제:
# 1. 변환에 불변하지 않음
# θ에 Uniform → log(θ)에는 Uniform 아님
# 2. 부적절한 사전 (improper prior)은 사후도 부적절할 수 있음
# 3. 실제로 "정보 없음"이 아닌 경우가 많음
# 권장: 약 정보적 사전
# - 물리적으로 말이 되는 범위 제한
# - 계산적으로 안정
3. 사후 분포의 모드만 보고¶
# MAP만 보고하면 불확실성 정보 손실
# 사후 분포 전체를 보고하거나, 최소한 신용 구간 함께
# 나쁜 예: "θ = 0.25"
# 좋은 예: "θ = 0.25 (95% CI: [0.20, 0.30])"
# 더 좋은 예: 사후 분포 시각화
4. MCMC 수렴 확인 안 함¶
# 반드시 확인:
# 1. Trace plot: 랜덤하게 왔다갔다 하는지
# 2. R-hat < 1.01
# 3. ESS > 400
# 4. 여러 체인이 같은 분포 탐색하는지
# 수렴 안 되면:
# - 샘플 수 늘리기
# - 튜닝(warm-up) 늘리기
# - 더 효율적인 샘플러 (NUTS, HMC)
# - 모델/파라미터화 재검토
5. 빈도주의 개념과 혼동¶
# 신뢰구간 vs 신용구간 해석 혼동
# 빈도주의: "장기적으로 95%가 참값 포함"
# 베이지안: "θ가 이 구간에 있을 확률 95%"
# p-value는 베이지안 개념이 아님!
# 베이지안에서는 사후 확률로 직접 판단
참고 자료¶
- Bayesian Data Analysis (Gelman et al.) - 베이지안 통계의 바이블
- PyMC Documentation - 실용적 구현
- ArviZ Documentation - MCMC 진단 시각화
- Probabilistic Machine Learning (Murphy) - ML 관점
- Stan Prior Recommendations - 사전 분포 선택 가이드
- Bayesian Deep Learning Survey - 딥러닝 불확실성
- Dropout as Bayesian Approximation (Gal & Ghahramani, 2016) - MC Dropout 이론