正規逆ガンマ分布の事後分布のパラメータ更新式と予測分布の導出
正規逆ガンマ分布の事後分布のパラメータ更新式と予測分布の導出
Udemyの「ベイズ推定とグラフィカルモデル:コンピュータビジョン基礎1」(テキスト:"Computer vision: models, learning and inference" by Simon Prince)で, 事後分布のパラメータ式のみ載っていたので,実際に導出できるかのメモ.
正規逆ガンマ分布の事後分布
Normal-inverse-gamma distribution - Wikipedia
尤度を正規分布,事前分布を正規逆ガンマ分布とした場合, 共役関係により事後分布も正規逆ガンマ分布になる.
事後分布 | 尤度 | 共役事前分布 |
---|---|---|
正規逆ガンマ分布 | 正規分布 | 正規逆ガンマ分布 |
ベイズの事後分布の式を展開して,正規逆ガンマ分布の式を代入していくと以下の式になる.
この事後分布の正規逆ガンマ分布のパラメータは以下のようになる.
- $d_{i}$: (正規分布に従う)観測データ
- $I$: 観測データ数(標本の大きさ)
パラメータの導出
参考:http://patricklam.org/teaching/conjugacy_print.pdf
事後分布は尤度×事前分布に比例するので
は正規逆ガンマの係数より除外すると
expの中の分子を展開して平方完成する
ここで平方完成用に項を追加
よって,
ここから,事後分布の新しいパラメータは以下のようになる.
正規逆ガンマ分布の予測分布(predictive density)
正規逆ガンマ分布の事後分布を使った予測分布は以下の積分の式になる.
$x^{*}$:正規分布に従う新しいデータ
: 新しいデータの正規分布
: 正規逆ガンマ分布の事後分布
この予測分布はt分布になることをまず確認する.
t分布になることを確認
補題「正規逆ガンマ分布を分散パラメータで積分するとt分布になる」を利用する.
導出の流れ:
新しいデータ$x^{*}$の正規分布と事後分布の正規逆ガンマ分布の積より,正規逆ガンマ分布のもっている正規分布との積が計算でき,新しいデータ$x^{*}$と平均パラメータ$\mu$との2次元正規分布になる.
1次元正規分布と逆ガンマ分布の積により新しいデータ$x^{*}$に対する正規逆ガンマ分布になる
正規逆ガンマ分布を分散パラメータで積分するのでt分布になる.
参考:https://people.eecs.berkeley.edu/~jordan/courses/260-spring10/lectures/lecture5.pdf
ここで,正規分布の積より,1つの変数が新しいデータ$x^{*}$, もう1つの変数が平均パラメータ$\mu$を持つ2次元正規分布になる.
しかし,平均パラメータ$\mu$で積分するのでが新しいデータ$x^{*}$についての1次元正規分布になる.
予測分布のt分布のパラメータを導出
参考:https://www.cs.ubc.ca/~murphyk/Papers/bayesGauss.pdf
ガウス積分は,$\int_{-\infty}^{\infty}\exp{(-a(x-b)^{2})} dx = \sqrt{\frac{\pi}{a}}$ より, expの中身を平方完成してガウス積分の形を作る.
右の項の分子の式はまとめることができるので,
よって,expの中身は,パラメータ$\mu$を持った項と定数項に分けることができる.
よって正規分布の積は,
よって,1次元正規分布になる.
残りの積分を考えると, この正規分布と逆ガンマの積より正規逆ガンマ分布になり, 正規逆ガンマ分布を分散についてt分布になる.
ここで,正規逆ガンマ分布の積分は以下の一般化t分布になる.
よって,予測分布は,
t分布の式を展開してまとめる
$-(\tilde{\alpha}+\frac{1}{2})$ 乗の中身を展開する.積和の形を作っていく.
括弧の中身を展開する.
よって,
t分布の元の式に代入すると,
とおくと
テキスト:"Computer vision: models, learning and inference" by Simon Prince p.59 (4.25), (4.26)式と同じ式になる.
コード
以上の式を使って,観測データが与えられたら,
- 事後分布のパラメータを計算
- そこから予測分布のt分布を決定
するようなクラスをつくる.
# code by Baysian import scipy as sp from scipy import stats from scipy import special class Baysian_Normal(): def __init__(self, prior_alpha, prior_beta, prior_delta, prior_gamma, data_x, *args, **kwargs): ''' prior: √(γ/2πσ^2)・β^α/Γ(α)・(1/σ^2)^(α+1)exp(- (2β + γ(δ-μ)^2 / (2 σ^2)) - alpha: df - N: data number Post: - alpha_post = alpha + N / 2 - gamma_post = gamma + N - delta_post = (gamma*delta + sum (d)) / (gamma + N) - beta_post = beta + sum(d^2)/2 + gamma*delta^2/2 - (gamma*delta + sum(d))^2/(2(gamma + N)) ''' self.parameters_of_posterior = {} data = sp.array(data_x).flatten() n = len(data) posterior_alpha = prior_alpha + n / 2 posterior_gamma = prior_gamma + n posterior_delta = (prior_gamma*prior_delta + sp.sum(data)) / (prior_gamma + n) posterior_beta = prior_beta + sp.sum(data**2)/2 + (prior_gamma*prior_delta**2)/2 - ( prior_gamma*prior_delta + sp.sum(data))**2/(2*(prior_gamma + n)) self.parameters_of_posterior["alpha"] = posterior_alpha self.parameters_of_posterior["beta"] = posterior_beta self.parameters_of_posterior["gamma"] = posterior_gamma self.parameters_of_posterior["delta"] = posterior_delta def norm_inv_gamma_pdf(mu, sigma2, alpha, beta, gamma, delta): ''' N(mu |δ,σ2/λ)・IG(σ2|α,β) return pdfM ''' col = len(mu) row = len(sigma2) sigma2 = sp.sort(sigma2)[::-1]# desc IG = stats.invgamma(a=alpha, scale=beta) Mpdf_sigma2 = IG.pdf(x=sigma2).reshape(-1, 1) Mpdf_sigma2 = sp.repeat(Mpdf_sigma2, repeats=col, axis=1) Mpdf_N = sp.zeros_like(Mpdf_sigma2) for r in sp.arange(row): N = stats.norm(loc=delta, scale=sp.sqrt(sigma2[r]/gamma)) Mpdf_N[r] = N.pdf(x=mu) return Mpdf_N * Mpdf_sigma2 def posterior_NormInvGamma_pdf(self, mu, sigma2): return norm_inv_gamma_pdf(mu, sigma2, alpha=self.parameters_of_posterior["alpha"], beta=self.parameters_of_posterior["beta"], gamma=self.parameters_of_posterior["gamma"], delta=self.parameters_of_posterior["delta"]) def sampling_posterior_NormInvGamma(self, N=1): IG = stats.invgamma(scale=self.parameters_of_posterior["beta"], a=self.parameters_of_posterior["alpha"]) sigma2 = IG.rvs(size=N) mu = sp.array([]) for s2 in sigma2: normal = stats.norm(loc=self.parameters_of_posterior["delta"], scale=s2/self.parameters_of_posterior["gamma"]) mu = sp.append(mu, normal.rvs(size=1)) return sp.vstack((mu, sigma2)) def predictive_dist(self): ''' t-dist ''' tilde_alpha = self.parameters_of_posterior["alpha"] tilde_beta = self.parameters_of_posterior["beta"] tilde_gamma = self.parameters_of_posterior["gamma"] tilde_delta = self.parameters_of_posterior["delta"] return stats.t(loc=tilde_delta, scale=1/sp.sqrt(tilde_alpha/tilde_beta * tilde_gamma/(tilde_gamma+1)), df=2*tilde_alpha) parameters = { "prior_alpha": 1, "prior_beta": 1, "prior_delta": 0, "prior_gamma": 1 } bn = Baysian_Normal(**parameters, data_x=[0, 1, -1, 0.5, -0.5]) bn.parameters_of_posterior
{'alpha': 3.5, 'beta': 2.25, 'gamma': 6, 'delta': 0.0}