母比率の信頼区間(正規分布への近似を利用しないもの)
これは何か
- 母比率の信頼区間について調べたことをまとめたもの
- 信頼区間構築のやり方はいくつもあるが, 本記事では正規分布への近似を利用しないものについてまとめた
- 具体的には, 以下の2つの信頼区間について整理した
- Clopper-Pearson interval
- Jeffreys interval[1]
- 具体的には, 以下の2つの信頼区間について整理した
- 正規分布への近似を利用したやり方についてはこちらの記事でまとめた
記号の定義
- Binom
: 2項分布(n, p) - Beta
: ベータ分布(a, b) -
: ベータ関数\Beta \left(a, b \right) -
: ベータ分布B\Beta \left(\alpha; a, b \right) の下側(a, b) %点100\alpha
-
各信頼区間の概要
以後,
Clopper-Pearson interval
- 2項分布に基づく片側検定を2つ考えることにより導かれる信頼区間
ただし,
Clopper-Pearson intervalの導出
信頼区間の上限・下限をそれぞれ導出していく.
信頼区間の下限を導くにあたり, 有意水準
となる.
つまり元の不等式を言い換えると, 「ベータ分布の下側確率が
が不等式の解となる. これで求める信頼区間の下限の値が求められた.
上限の値についても同様に考える. 有意水準
となる.
つまり元の不等式を言い換えると, 「ベータ分布の上側確率が
が不等式の解となる. これで求める信頼区間の上限の値が求められた.
以上をまとめて, 信頼水準
となる. ただし,
Jeffreys interval
- ベイズ統計の枠組みで導出される信用区間
- 2項分布モデルにJeffreys priorを適用して得られる事後分布から計算される
Jeffreys intervalの導出
2項分布モデルBinom
Binom
つまりベータ分布Beta
Jeffreys priorの導出
Jeffreys priorは, Fisher情報量を
で定義される. そのため, 2項分布のFisher情報量を計算する. 2項分布のスコア関数(対数尤度のパラメータに関する1階偏微分)は
なので, Fisher情報量は
となる.
ゆえにJeffreys priorは
となる. (Jeffreys priorの導出終わり)
この事前分布を用いると,
つまりベータ分布Beta
あとは, 両端から
が求まる.
信頼区間の観察
参考までに, こちらの記事で紹介したAgresti–Coull intervalと合わせて可視化を行う.
信頼区間の数値例
実際に
(可視化コード)
import matplotlib.pyplot as plt
import numpy as np
from scipy.stats import norm, beta
def clopper_pearson_confidence_interval(n: int, x: int, alpha: float = 0.05) -> tuple[float, float]:
lower, upper = 0, 1
if x > 0:
lower = beta.ppf(alpha / 2, x, n - x + 1)
if x < n:
upper = beta.ppf(1 - alpha / 2, x + 1, n - x)
return (lower, upper)
def jeffreys_confidence_interval(n: int, x: int, alpha: float = 0.05) -> tuple[float, float]:
lower = beta.ppf(alpha / 2, x + 1/2, n - x + 1/2)
upper = beta.ppf(1 - alpha / 2, x + 1/2, n - x + 1/2)
return (lower, upper)
def agresti_coull_confidence_interval(n: int, x: int, alpha: float = 0.05) -> tuple[float, float]:
z = norm.ppf(1 - alpha / 2)
tilde_n = n + z**2
tilde_x = x + (z**2)/2
tilde_p = tilde_x / tilde_n
deviation = z * np.sqrt(tilde_p * (1 - tilde_p) / tilde_n)
lower = tilde_p - deviation
upper = tilde_p + deviation
return (lower, upper)
def main():
n = 20
alpha = 0.05
xs = np.arange(n + 1)
clopper_pearson_lower, clopper_pearson_upper = np.zeros(n + 1), np.zeros(n + 1)
jeffreys_lower, jeffreys_upper = np.zeros(n + 1), np.zeros(n + 1)
agresti_coull_lower, agresti_coull_upper = np.zeros(n + 1), np.zeros(n + 1)
for x in xs:
clopper_pearson_ci = clopper_pearson_confidence_interval(n, x, alpha)
clopper_pearson_lower[x], clopper_pearson_upper[x] = clopper_pearson_ci[0], clopper_pearson_ci[1]
jeffreys_ci = jeffreys_confidence_interval(n, x, alpha)
jeffreys_lower[x], jeffreys_upper[x] = jeffreys_ci[0], jeffreys_ci[1]
agresti_coull_ci = agresti_coull_confidence_interval(n, x, alpha)
agresti_coull_lower[x], agresti_coull_upper[x] = agresti_coull_ci[0], agresti_coull_ci[1]
plt.plot(xs, np.zeros(len(xs)), linestyle="-", color="black")
plt.plot(xs, np.ones(len(xs)), linestyle="-", color="black")
plt.plot(xs, clopper_pearson_lower, label="clopper-pearson", linestyle=":", marker="o", color="blueviolet", markerfacecolor='none')
plt.plot(xs, clopper_pearson_upper, linestyle=":", marker="o", color="blueviolet", markerfacecolor='none')
plt.plot(xs, jeffreys_lower, label="jeffreys", linestyle=":", marker="x", color="orange")
plt.plot(xs, jeffreys_upper, linestyle=":", marker="x", color="orange")
plt.plot(xs, agresti_coull_lower, label="agresti-coull", linestyle=":", marker="+", color="green")
plt.plot(xs, agresti_coull_upper, linestyle=":", marker="+", color="green")
plt.xlabel("$x$")
plt.ylabel("$p$")
plt.title(f"Confidence Intervals (n={n} / confidence level={1-alpha})")
plt.legend(loc="upper left")
plt.show()
if __name__ == "__main__":
main()
横軸を
すると, グラフから以下のことが読み取れる:
- Clopper-Pearson intervalは他のintervalsと比べて区間が広い
- この特徴は後述する被覆確率にも影響してくる
- Clopper-Pearson interval / Jeffreys intervalは0以上1以下の範囲に収まる
- こちらの記事でも触れたが, Agresti-Coull intervalなどでは0以上1以下の範囲からはみ出ることもある
信頼区間の被覆確率
被覆確率を「2項分布モデルのもとで, (確率変数としての)信頼区間が真の母比率を含む確率」と定義し, その値がどうなるかを調べてみる. 被覆確率を数式で表現すると以下のようになる(被覆確率は, 2項分布のパラメータ
他の母比率の信頼区間の解説記事を見ると, 被覆確率をモンテカルロシミュレーションで計算して比較しているケースが多い印象があるが, 被覆確率については上記のようにシミュレーションなしで計算が可能である.
実際に
(可視化コード)
import matplotlib.pyplot as plt
import numpy as np
from scipy.stats import norm, beta, binom
def clopper_pearson_confidence_interval(n: int, x: int, alpha: float = 0.05) -> tuple[float, float]:
lower, upper = 0, 1
if x > 0:
lower = beta.ppf(alpha / 2, x, n - x + 1)
if x < n:
upper = beta.ppf(1 - alpha / 2, x + 1, n - x)
return (lower, upper)
def jeffreys_confidence_interval(n: int, x: int, alpha: float = 0.05) -> tuple[float, float]:
lower = beta.ppf(alpha / 2, x + 1/2, n - x + 1/2)
upper = beta.ppf(1 - alpha / 2, x + 1/2, n - x + 1/2)
return (lower, upper)
def agresti_coull_confidence_interval(n: int, x: int, alpha: float = 0.05) -> tuple[float, float]:
z = norm.ppf(1 - alpha / 2)
tilde_n = n + z**2
tilde_x = x + (z**2)/2
tilde_p = tilde_x / tilde_n
deviation = z * np.sqrt(tilde_p * (1 - tilde_p) / tilde_n)
lower = tilde_p - deviation
upper = tilde_p + deviation
return (lower, upper)
def main():
n = 20
alpha = 0.05
ps = np.arange(0.02, 1, 0.02)
clopper_pearson_coverage_probabilities = np.zeros(len(ps))
jeffreys_coverage_probabilies = np.zeros(len(ps))
agresti_coull_coverage_probabilies = np.zeros(len(ps))
for index, p in enumerate(ps):
for x in np.arange(n + 1):
px = binom.pmf(x, n, p)
clopper_pearson_ci = clopper_pearson_confidence_interval(n, x, alpha)
if clopper_pearson_ci[0] <= p and p <= clopper_pearson_ci[1]:
clopper_pearson_coverage_probabilities[index] += px
jeffreys_ci = jeffreys_confidence_interval(n, x, alpha)
if jeffreys_ci[0] <= p and p <= jeffreys_ci[1]:
jeffreys_coverage_probabilies[index] += px
agresti_coull_ci = agresti_coull_confidence_interval(n, x, alpha)
if agresti_coull_ci[0] <= p and p <= agresti_coull_ci[1]:
agresti_coull_coverage_probabilies[index] += px
plt.plot(ps, (1 - alpha) * np.ones(len(ps)), linestyle="-", color="black")
plt.plot(ps, clopper_pearson_coverage_probabilities, label="clopper-pearson", linestyle=":", marker="o", color="blueviolet", markerfacecolor='none')
plt.plot(ps, jeffreys_coverage_probabilies, label="jeffreys", linestyle=":", marker="x", color="orange")
plt.plot(ps, agresti_coull_coverage_probabilies, label="agresti-coull", linestyle=":", marker="+", color="green")
plt.xlabel("$p$")
plt.ylabel("coverage probability")
plt.title(f"Coverage Probabilities (n={n} / confidence level={1-alpha})")
plt.legend(loc="lower center")
plt.show()
if __name__ == "__main__":
main()
横軸を真の母比率
すると, グラフから以下のことが読み取れる:
- Jeffreys intervalは, 被覆確率が想定している被覆確率のラインの周辺に分布している
- Clopper-Pearson intervalは, 想定している被覆確率のラインと比べてそれなりに高い被覆確率を保っている
個人的な所感
- Clopper-Pearson intervalの被覆確率の高さは活用シーンを選びそう
- Brown et al.(2001)のSection 4.2では
wastefully conservative
と評されている - とはいえ保守的に寄った意思決定をしたいシーンでは活用できるはず
- Brown et al.(2001)のSection 4.2では
参考文献
- Brown, L. D., Cai, T. T., and DasGupta, A. (2001). Interval Estimation for a Binomial Proportion. Statistical Science, 16(2), 101-133.
- Brown, L. D., Cai, T. T., and DasGupta, A. (2002). Confidence Intervals for a binomial proportion and asymptotic expansions. The Annals of Statistics, 30(1), 160–201
-
これは信用区間に分類されるものではあるが, 本記事では特に区別はしない ↩︎
Discussion