PRMLでは尤度は確率だが確率分布ではないと述べている。
観測データが生じる確率である尤度関数は (中略) 。尤度関数はは上の確率分布ではなく、正規化もされていないことを、もう一度強調しておく。
(C.M.ビショップ(2012)『パターン認識と機械学習 上』丸善出版、p.95。)
ただ、最尤推定の手続きを見ていると、(対数を取る前の)尤度は(i.i.d.を仮定できるときの)同時確率と相違ないように見える。
どういうことなのか?
最尤推定の流れと同時確率の確認¶
今一度最尤推定を振り返る。
例として、ある県に住む男性の身長の分布を調べたいとする。身長を平均、分散の正規分布に従う確率変数とみなして(仮定して・モデリングして)扱うこととする。
手元にランダム・サンプリングした10人分のデータがあり、次のようになっていたとする。
Source
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
n = 10
mu = 170
sigma2 = 25
sigma = np.sqrt(sigma2)
np.random.seed(0)
x = np.random.normal(loc=mu, scale=sigma, size=n).astype(int)
df = pd.DataFrame({"x": x})
df同時確率関数¶
10人のデータをとったとして、その組み合わせのデータが得られる確率(同時確率)は、データが独立同分布(i.i.d.)に従うと仮定すると、確率の独立性から同時確率は確率の積
と書くことができる。
パラメータは未知だが、仮にとすると、上記の10人の個々のに対応する確率は以下の表のp(x)列のようになる。
Source
from scipy.stats import norm
df.loc[:, "p(x)"] = norm.pdf(df["x"], loc=mu, scale=sigma)
dfSource
from myst_nb import glue
glue("joint_proba", df["p(x)"].product())Output
1.3396747297828266e-14これらの積(同時確率)はjoint_probaとなる。
プロット¶
パラメータの値を変えつつ確率を計算して分布を描くと次の図のようになる
Source
def joint_proba(x, loc: float, scale: float) -> float:
probabilities = norm.pdf(x, loc=loc, scale=scale)
return pd.Series(probabilities).product()
# 3d plot
mu_range = np.linspace(165, 185, 50)
sigma2_range = np.linspace(1, 60, 60)
Mu, Sigma2 = np.meshgrid(mu_range, sigma2_range)
Proba = np.array([joint_proba(df["x"], loc=_mu, scale=np.sqrt(_sigma2)) for _mu, _sigma2 in zip(Mu.flatten(), Sigma2.flatten())]).reshape(Mu.shape)
from matplotlib import cm
fig, ax = plt.subplots(dpi=120, subplot_kw={"projection": "3d"})
surf = ax.plot_surface(Mu, Sigma2, Proba, rstride=1, cstride=1, linewidth=1, antialiased=True, cmap=cm.coolwarm)
fig.colorbar(surf, shrink=0.5, aspect=5, pad=0.11)
ax.set(xlabel="μ", ylabel="σ^2", zlabel="joint probability")
fig.show()
プロット¶
同時確率のグラフに最尤推定値をプロットすると次のようになる。
Source
# plot
fig, ax = plt.subplots(dpi=120, subplot_kw={"projection": "3d"})
surf = ax.plot_surface(Mu, Sigma2, Proba, rstride=1, cstride=1, linewidth=1, antialiased=True, cmap=cm.coolwarm)
fig.colorbar(surf, shrink=0.5, aspect=5, pad=0.11)
ax.set(xlabel="μ", ylabel="σ^2", zlabel="joint probability")
# maximum likelihood estimates
mu_hat = df["x"].sum() / n
sigma2_hat = ((df["x"] - mu_hat)**2).sum() / n
p_hat = joint_proba(df["x"], loc=mu_hat, scale=np.sqrt(sigma2_hat))
# add a point
ax.scatter(mu_hat, sigma2_hat, p_hat, color="darkorange")
ax.text(mu_hat * 0.99, sigma2_hat, p_hat * 1.1, f"MLE (μ={mu_hat:.1f}, σ^2={sigma2_hat:.1f})", color="darkorange")
fig.show()
なお、同時確率を対数変換して対数尤度にすると次のようになる
Source
import warnings
with warnings.catch_warnings():
warnings.simplefilter("ignore")
# plot
fig, ax = plt.subplots(dpi=120, subplot_kw={"projection": "3d"})
surf = ax.plot_surface(Mu, Sigma2, np.log(Proba), rstride=1, cstride=1, linewidth=1, antialiased=True, cmap=cm.coolwarm)
fig.colorbar(surf, shrink=0.5, aspect=5, pad=0.11)
ax.set(xlabel="μ", ylabel="σ^2", zlabel="log likelihood")
# add a MLE point
ax.scatter(mu_hat, sigma2_hat, p_hat, color="darkorange")
ax.text(mu_hat * 0.99, sigma2_hat, p_hat * 1.1, f"MLE (μ={mu_hat:.1f}, σ^2={sigma2_hat:.1f})", color="darkorange")
fig.show()/home/mitama/.local/lib/python3.8/site-packages/mpl_toolkits/mplot3d/proj3d.py:124: RuntimeWarning: invalid value encountered in divide
txs, tys, tzs = vecw[0]/w, vecw[1]/w, vecw[2]/w

書籍ごとの説明¶
PRML以外ではどう書かれているか?
『統計学入門』
ここでわれわれが採用する原理は最尤原理 principle of maximum likelihoodといわれ「現実の標本は確率最大のものが実現した」という仮定である。すなわち、この標本が得られる確率は (中略) このようにもっともらしさを尤度 likelihood、その関数を尤度関数 likelihood functionと呼ぶ。
(東京大学教養学部統計学教室 編(1991)『統計学入門』東京大学出版会、p.217)
『現代数理統計学の基礎』
の同時確率関数もしくは同時確率密度関数においてをに置き換えたものを (中略)と書き、尤度関数(likelihood function)という。
(久保川達也(2017)『現代数理統計学の基礎』共立出版、p.121)
『はじめての統計データ分析』
母数を変数として扱い、データを定数として確率密度関数を扱った場合には、同じ式を尤度(likelihood)と呼びます。
(豊田秀樹(2016)『はじめての統計データ分析: ベイズ的ポスト p 値時代の統計学』朝倉書店、p.17)
『基礎からのベイズ統計学』
この式をの関数と見たときが確率です。同じ式をの関数と見たときが尤度です。について(確率について)足し上げると1になりましたが、について(尤度について)積分しても1になりません。
(豊田秀樹(2015)『基礎からのベイズ統計学: ハミルトニアンモンテカルロ法による実践的入門』朝倉書店、p.41)
豊田(2015)がわかりやすい。
例:二項分布¶
二項分布で考えてみる。の二項分布の場合、同時確率は次のようになる
Source
import numpy as np
from scipy.stats import binom
# 二項分布:n回試行してk回成功する確率
n = 10
p = 0.5
K = range(0, 11)
pmfs = [binom.pmf(k, n, p) for k in K]
cdfs = [binom.cdf(k, n, p) for k in K]
# cdfs = [sum(pmfs[:i+1]) for i in range(n + 1)] # ほぼ同じだけどやや不正確かも
fig, axes = plt.subplots(nrows=2)
xlim = [-0.5, 10.5]
axes[0].bar(K, pmfs)
axes[0].set(ylabel="probability", title="Binomial(k, n=10, p=0.5)", xlim=xlim)
axes[1].plot(K, cdfs, marker="o")
axes[1].set(xlabel="k", ylabel="cumulative probability", xlim=xlim)
axes[1].grid(True)
fig.show()
累積分布からもわかるように、について足し上げていった場合、
となっている。
今度はというデータが得られていてが未知の状況を仮定したときの尤度を見てみる。尤度を描いたものが次の図で、横軸はではなくとなっている。下の図は数値積分によって累積分布関数のようなもの(についての積分ではなくについての積分なので累積分布関数とは異なる)を計算したもの。
Source
from scipy import integrate
k = 5
n = 10
n_split = 101
fig, axes = plt.subplots(nrows=2)
P = np.linspace(0, 1, n_split)
pmfs = [binom.pmf(k, n, p) for p in P]
# cdfs = [binom.cdf(k, n, p) for p in P]
# cdfs = [sum(pmfs[:i+1]) / n_split for i in range(len(pmfs))]
# 台形公式 (trapezoidal rule) による数値積分
cdfs = [integrate.trapezoid(pmfs[:i+1], P[:i+1]) for i in range(len(pmfs))]
axes[0].plot(P, pmfs)
axes[0].set(ylabel="probability", title="likelihood of Binomial(k=5, n=10, p)")
axes[1].plot(P, cdfs)
axes[1].set(xlabel="p", ylabel="cumulative likelihood")
axes[1].axhline(cdfs[-1], color="darkorange", alpha=0.7)
axes[1].text(0, cdfs[-1] * 0.85, f"∑ p = {cdfs[-1]:.2f}", color="darkorange")
axes[1].grid(True)
fig.show()