NumPyro를 통한 베셀 선형 단일 회귀
개시하다
나는 확률 모델링에 푹 빠졌다.최근 페이로에서 MC를 수행하던 중 느린 것을 참지 못해 넘페이로에 입성했다.따라서 이 글에서 학습하는 동시에 NumPyro에서 베스탄 선형 단일 회귀를 실시한다.또한 가시화하려면 베이스 모델링의 가시화 라이브러리arviz를 사용하십시오.
소스 코드는 GiitHub에 공개됩니다.
장난감 데이터 만들기
이번에 사용한 데이터는 위조 데이터를 사용할 것이다.
구체적으로 우리는 다음과 같은 공식이 표현할 수 있는 데이터를 고려할 것이다.
y_i = 0.9x_i + 5 +\epsilon_{\rm real}
\epsilon_{\rm real}\sim {\mathcal N}(0, 0.5)
그럼 데이터 제작을 시작합시다.
우선 필요한 라이브러리 그룹을 준비합니다.
%matplotlib inline
import matplotlib.pyplot as plt
import numpy as np
import arviz as az
import numpyro
import numpyro.distributions as dist
import jax
plt.style.use('seaborn-darkgrid')
다음에 Numpy를 사용하여 데이터를 생성합니다.N = 100
alpha_real, beta_real = 0.9, 5
epsilon_real = np.random.normal(0, 0.5, N)
x = np.random.normal(10, 1, N)
y_real = alpha_real * x + beta_real
y = y_real + epsilon_real
생성 데이터를 그린 결과는 다음과 같다.베일스 선형 단회귀 모델
생성 과정
그럼 베스탄의 선형 단회귀 모델을 고려해 보자.
선형 단일 회귀는 기울기\alpha이고 슬라이스가\beta일 때 변수 yi에 관해서는 다음과 같이 쓸 수 있다.
y_i =\alpha x_i +\beta
이 선형 단일 회귀의 확률을 사용하여 다음과 같이 나타낸다.
{\boldsymbol y}\sim {\mathcal N}(\mu =\alpha {\boldsymbol x} +\beta,\sigma =\epsilon)
즉, 데이터 서열 {\boldsymboly}이 평균값\alpha{\boldsymbolx]+\beta, 표준 편차\epsilon의 정적 분포를 따른다고 가정한다.그러나 각 매개 변수\alpha,\beta,\epsilon에 관해서는 실제 값을 모르기 때문에 다음과 같이 미리 분포한다고 가정한다.이 예비 분포는 적당한 분포라면 다 된다.
\alpha\sim {\mathcal N}(\mu_\alpha,\sigma_\alpha)
\beta\sim {\mathcal N}(\mu_\beta,\sigma_\beta)
\epsilon\sim {\rm HalfCauchy(\sigma_\epsilon)}
이러한 사전 분포와 확률 모델의 도형 모델은 다음과 같이 쓸 수 있다.
이것은 NumPyro로 구현됩니다.
def model(x, y = None):
alpha = numpyro.sample("alpha", dist.Normal(0, 1))
beta = numpyro.sample("beta", dist.Normal(0, 10))
eplison = numpyro.sample("eplison", dist.HalfCauchy(5))
mu = numpyro.deterministic("mu", alpha * x + beta)
with numpyro.plate("data", size = len(x)):
y_pred = numpyro.sample("y_pred", dist.Normal(mu, eplison), obs=y)
추론
이어 MCMC에 따라 샘플링을 진행한다.이번에는 NO-U-turn sampler(NUTS)를 사용했다.
kernel = numpyro.infer.NUTS(model)
mcmc = numpyro.infer.MCMC(kernel, num_samples=1000, num_warmup=300, num_chains=4, chain_method="parallel")
mcmc.run(jax.random.PRNGKey(0), x, y)
arviz를 사용하여 샘플링 결과를 가시화합니다.az.plot_trace(mcmc, var_names=["alpha", "beta", "eplison"])
왼쪽은 내핵 밀도를 추정하는 도표다.나는 중심극제한리를 통해 정규 분포와 비슷한 도표임을 확인할 수 있다고 생각한다.
이것은 오른쪽에 쓴 견본에서 얻은 값이다.규칙성과 주기성이 보이지 않는 도표로 잘 섞인 모습을 엿볼 수 있다.
또
print_summary()
를 사용하면 주요 통계량을 볼 수 있다.mcmc.print_summary()
mean std median 5.0% 95.0% n_eff r_hat
alpha 0.95 0.05 0.95 0.86 1.04 1090.27 1.01
beta 4.56 0.54 4.56 3.71 5.44 1089.63 1.01
eplison 0.51 0.04 0.51 0.45 0.57 1546.22 1.00
Number of divergences: 0
예측 분포다음은 후방 분포의 샘플링에 따라 예측 분포를 생성한다.
먼저
get_samples()
를 사용하고 후분포에서 각 매개 변수\alpha,\beta,\epsilon을 샘플링한다.posterior_samples = mcmc.get_samples()
다음에 샘플을 채취한 매개 변수\alpha,\beta,\epsilon을 사용하여 {boldsymboly}의 예측 분포를 구한다.posterior_predictive = numpyro.infer.Predictive(model, posterior_samples)(
jax.random.PRNGKey(1), x
)
실제 데이터를 그리는 내핵밀도 추정과 사후분포 계산의 내핵밀도 추정._, ax = plt.subplots()
for y_pred in posterior_predictive["y_pred"][0:50]:
sns.kdeplot(y_pred, alpha=0.1, c='r', ax=ax)
# real data
sns.kdeplot(y, linewidth=3, color='k', ax=ax)
plt.xlabel('$y$', fontsize=16);
그림의 도표가 실제 데이터와 매우 가깝다는 것을 확인할 수 있다.
마지막으로 샘플링된 직선과\pm\sigma,\pm3\sigma의 불확실성을 테이프로 표현해 봤다.
def summary(samples):
s_mean, s_std = samples.mean(0), samples.std(0)
site_stats = {
"mean": s_mean,
"std": s_std,
"upper_sigma1": s_mean + s_std,
"lower_sigma1": s_mean - s_std,
"upper_sigma3": s_mean + 3 * s_std,
"lower_sigma3": s_mean - 3 * s_std
}
return site_stats
pred_summary = summary(posterior_predictive["y_pred"])
plt.plot(x, y, 'C0.');
# 直線
alpha_m = posterior_samples['alpha'].mean()
beta_m = posterior_samples['beta'].mean()
plt.plot(x, alpha_m * x + beta_m,
c='k', label='y = {:.2f} * x + {:.2f}'.format(alpha_m, beta_m))
# 範囲
idx = np.argsort(x)
x_ord = x[idx]
plt.fill_between(x_ord, pred_summary["upper_sigma1"][idx], pred_summary["lower_sigma1"][idx], alpha=0.3, color="b")
plt.fill_between(x_ord, pred_summary["upper_sigma3"][idx], pred_summary["lower_sigma3"][idx], alpha=0.1, color="b")
plt.xlabel('$x$', fontsize=16)
plt.ylabel('$y$', fontsize=16, rotation=0)
plt.legend(loc=2, fontsize=14)
좋은 느낌이 나오지 않나요?
넘페로는 파이로에 비해 MCMC의 속도가 빠르다. 앞으로 MCMC를 쓰면 넘페로, 변분 베이즈법, 신경망 쪽에서 여러 가지 신경 쓰는 일을 하고 싶다면 각각 파이로를 사용할 수 있지 않을까... 하는 생각이 든다. 어떨까?자세한 사람 있으면 알려주세요.
참고 자료
https://www.kyoritsu-pub.co.jp/bookdetail/9784320113374
Reference
이 문제에 관하여(NumPyro를 통한 베셀 선형 단일 회귀), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://zenn.dev/kajyuuen/articles/c89a9ca9a2d2f87a209e텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)