Mímisbrunnr知恵の泉

← ベイズ統計 一覧

🎓 レベル:基礎 | 重要度:A(必須)

📎 前提:共役性とは | 数理:共役事前分布(統計)・ベルヌーイ分布・二項分布(統計)

要点(BLUF)

1. 導出:肩の指数を足すだけ

成功確率 θ[0,1]\theta\in[0,1] を推定します。nn 回中 kk 回成功(ベルヌーイ分布・二項分布)。

尤度のカーネル(二項係数 (nk)\binom{n}{k}θ\theta を含まない定数):

p(kθ)=(nk)θk(1θ)nk    θk(1θ)nkp(k\mid\theta)=\binom{n}{k}\theta^{k}(1-\theta)^{n-k}\;\propto\;\theta^{k}(1-\theta)^{n-k}

事前のカーネル(ベータ関数 B(a,b)B(a,b) は正規化定数):

p(θ)=1B(a,b)θa1(1θ)b1    θa1(1θ)b1p(\theta)=\frac{1}{B(a,b)}\theta^{a-1}(1-\theta)^{b-1}\;\propto\;\theta^{a-1}(1-\theta)^{b-1}

事後 = 尤度カーネル × 事前カーネル。指数法則で肩を足すだけです。

p(θk)θk(1θ)nk尤度θa1(1θ)b1事前=θ(a+k)1(1θ)(b+nk)1\begin{aligned} p(\theta\mid k) &\propto \underbrace{\theta^{k}(1-\theta)^{n-k}}_{\text{尤度}}\cdot\underbrace{\theta^{a-1}(1-\theta)^{b-1}}_{\text{事前}}\\[4pt] &= \theta^{(a+k)-1}\,(1-\theta)^{(b+n-k)-1} \end{aligned}

これは Beta(a+k, b+nk)\mathrm{Beta}(a+k,\ b+n-k) のカーネルそのもの。よって

θBeta(a,b), kBin(n,θ)  θkBeta(a+k, b+nk)\theta\sim\mathrm{Beta}(a,b),\ k\sim\mathrm{Bin}(n,\theta)\ \Longrightarrow\ \theta\mid k\sim\mathrm{Beta}(a+k,\ b+n-k)

正規化定数(ベータ関数)は最後にベータ族の定義から自動で決まるので、計算は不要です(完全導出と試験での問われ方は 共役事前分布)。

2. 事後の要約をコードで出す

Beta(2,2)\mathrm{Beta}(2,2) 事前・n=20,k=14n{=}20,\,k{=}14 の事後 Beta(16,8)\mathrm{Beta}(16,8) について、平均・MAP・95%信用区間を求めます。

import numpy as np
from scipy import stats

n, k = 20, 14
a, b = 2, 2
a_post, b_post = a + k, b + (n - k)          # Beta(16, 8)
post = stats.beta(a_post, b_post)

lo, hi = post.interval(0.95)
map_est = (a_post - 1) / (a_post + b_post - 2)   # ベータの最頻値 (a>1,b>1)
print(f"事後 = Beta({a_post}, {b_post})")
print(f"事後平均 = {post.mean():.4f}")
print(f"事後MAP  = {map_est:.4f}")
print(f"事後SD   = {post.std():.4f}")
print(f"95%信用区間 = [{lo:.3f}, {hi:.3f}]")

出力:

事後 = Beta(16, 8)
事後平均 = 0.6667
事後MAP  = 0.6818
事後SD   = 0.0943
95%信用区間 = [0.471, 0.836]

出力の意味:事後平均 0.6670.667 と MAP 0.6820.682 がわずかにずれるのは、事後がまだ少し非対称だから(点推定の使い分けは 点推定と損失関数)。最尤推定 k/n=0.70k/n=0.70 より両方とも 0.5 寄りなのは、Beta(2,2)\mathrm{Beta}(2,2) が「0.5 付近だろう」と軽く引っぱっているためです。

3. ハイパーパラメータ=擬似観測:事前の強さが事後を引っぱる

更新則 aa+k, bb+(nk)a\to a+k,\ b\to b+(n-k) を逆から読むと、aa仮想の成功回数bb仮想の失敗回数。だから

同じデータ(n=20,k=14n{=}20,\,k{=}14、最尤 0.700.70)に、強さ・位置の違う事前をぶつけてみます。

import numpy as np

n, k = 20, 14
print(f"{'事前':<18}{'a+b(強さ)':>10}{'事前平均':>10}{'事後平均':>10}")
for (pa, pb, name) in [(1, 1,  "Beta(1,1)一様"),
                       (2, 2,  "Beta(2,2)弱"),
                       (20, 5, "Beta(20,5)強・高め"),
                       (5, 20, "Beta(5,20)強・低め")]:
    prior_mean = pa / (pa + pb)
    post_mean  = (pa + k) / (pa + pb + n)     # 事後平均 = (a+k)/(a+b+n)
    print(f"{name:<18}{pa+pb:>10}{prior_mean:>10.3f}{post_mean:>10.3f}")

出力:

事前                a+b(強さ)      事前平均      事後平均
Beta(1,1)一様              2     0.500     0.682
Beta(2,2)弱               4     0.500     0.667
Beta(20,5)強・高め         25     0.800     0.756
Beta(5,20)強・低め         25     0.200     0.422

出力の意味:弱い事前(a+b=2a+b=244)では事後平均がデータの 0.700.70 にほぼ張りつきます。一方、和が 2525 の強い事前は、データ20件と同等以上の「仮想データ」を持ち込むため、事後平均が事前平均の側へ大きく引っぱられます——「高め」は 0.7560.756、「低め」は 0.4220.422事前の強さ=持ち込む仮想データ件数だと体感できます。データが十分多ければ(na+bn\gg a+b)どの事前からも最尤値に収束しますが、小標本では事前の選択がそのまま効きます。

補足:事前平均 μ0=a/(a+b)\mu_0=a/(a+b)、事前標本サイズ ν=a+b\nu=a+b と置くと、事後平均は a+ka+b+n=νν+nμ0+nν+nkn\dfrac{a+k}{a+b+n}=\dfrac{\nu}{\nu+n}\mu_0+\dfrac{n}{\nu+n}\dfrac{k}{n} ——事前平均と最尤値(k/nk/n)を、件数を重みにして混ぜた加重平均です。nn\to\infty で最尤値に収束します。

図にすると、事前の強さで事後がどれだけ引っぱられるかが一目で分かります。

import numpy as np
from scipy import stats
import matplotlib.pyplot as plt
import japanize_matplotlib  # 日本語ラベル用

n, k = 20, 14
theta = np.linspace(0, 1, 400)
plt.figure(figsize=(7, 4))
for (pa, pb, name) in [(1, 1,  "一様 Beta(1,1)"),
                       (20, 5, "強・高め Beta(20,5)"),
                       (5, 20, "強・低め Beta(5,20)")]:
    post = stats.beta(pa + k, pb + (n - k))             # 事後 Beta(a+k, b+n-k)
    plt.plot(theta, post.pdf(theta), lw=2,
             label=f"{name} → 事後平均 {(pa+k)/(pa+pb+n):.3f}")
plt.axvline(k/n, color="black", ls=":", label=f"最尤 {k/n:.2f}")
plt.xlabel("θ(成功確率)"); plt.ylabel("事後密度")
plt.title("同じデータ(n=20,k=14)・違う事前で事後がどう動くか")
plt.legend(); plt.tight_layout(); plt.show()

グラフの意味:一様事前の事後(最尤 0.700.70 付近に山)に対し、強い事前は山が事前平均の側へずれます。強さ a+b=25a+b=25 はデータ件数 2020 を上回るので、「強・低め」では山が 0.420.42 まで引き下げられる——事前がデータより重い小標本では、事前の選択が結論を左右します。

4. 事後予測分布:次の観測を予測する(ベータ二項分布)

次に nn' 回投げたときの成功数 kk' を予測します。θ\theta を事後で積分して消すと、閉じた形のベータ二項分布になります(信用区間と事後予測分布 の一般式の具体形)。

p(kD)=01Bin(kn,θ)Beta(θa,b)dθ=BetaBinomial(kn,a,b)p(k'\mid D)=\int_0^1 \mathrm{Bin}(k'\mid n',\theta)\,\mathrm{Beta}(\theta\mid a',b')\,d\theta=\mathrm{BetaBinomial}(k'\mid n',a',b')

ここで a=a+k, b=b+nka'=a+k,\ b'=b+n-k は事後パラメータ。これを「θ\theta を事後平均に固定した素朴な二項予測」と比べます。

import numpy as np
from scipy import stats

a_post, b_post = 16, 8
post = stats.beta(a_post, b_post)
n_new = 10

# 事後予測:θ の不確実性を積分(ベータ二項)
pp = stats.betabinom(n_new, a_post, b_post)
# プラグイン:θ を事後平均に固定した二項
theta_hat = post.mean()
plug = stats.binom(n_new, theta_hat)

print(f"事後予測 BetaBinomial(10,16,8): 平均={pp.mean():.3f}, SD={pp.std():.3f}")
print(f"プラグイン Binom(10,{theta_hat:.3f}):    平均={plug.mean():.3f}, SD={plug.std():.3f}")
print(f"P(k'>=8): 事後予測={pp.sf(7):.3f}  プラグイン={plug.sf(7):.3f}")

出力:

事後予測 BetaBinomial(10,16,8): 平均=6.667, SD=1.738
プラグイン Binom(10,0.667):    平均=6.667, SD=1.491
P(k'>=8): 事後予測=0.339  プラグイン=0.299

出力の意味:平均はどちらも 6.676.67 で同じですが、標準偏差は事後予測 1.741.74 > プラグイン 1.491.49。事後予測は「データ自体のばらつき(二項のランダムさ)」に「θ\theta がまだ不確かなぶん」を上乗せするので、予測が広がります。「8回以上成功する確率」も 0.3390.3390.2990.299 と事後予測のほうが大きく、点推定に固定した予測が過信(裾を細く見積もる)であることが分かります。意思決定に予測を渡すなら、この広い事後予測を使うのが正直です。

5. 事前の選び方の定番

⚠️ よくある誤解

関連ノート