ホーム » 分布 » 超幾何分布

超幾何分布」カテゴリーアーカイブ

二項分布と超幾何分布

二項分布

  • 抽出方法: 復元抽出
  • 試行の独立性: 各試行は独立
  • 確率: 各試行で成功確率は一定

超幾何分布

  • 抽出方法: 非復元抽出
  • 試行の独立性: 各試行は独立していない
  • 確率: 各試行で成功確率が変化

グラフの比較

今回の実験では、二項分布と超幾何分布の違いを視覚的に比較します。二項分布は、復元抽出を行う場合に適用され、各試行が独立しており、成功確率が一定です。一方、超幾何分布は、非復元抽出を行う場合に適用され、試行ごとに成功確率が変化します。実験では、母集団のサイズ、成功対象の数、抽出回数を変え、それぞれのグラフを描画します。特に、サンプルサイズが大きい場合や母集団が小さい場合など、分布の形状に顕著な違いが現れる条件に注目して比較を行います。これにより、抽出方法による分布の違いを視覚的に確認し、二項分布と超幾何分布の特性を理解します。

復元抽出と非復元抽出の比較(広範囲のパラメータ設定)

import numpy as np
import matplotlib.pyplot as plt
from scipy.stats import binom, hypergeom

# グラフを描画する関数
def plot_comparison(M, N_A, n, ax):
    # 非復元抽出(超幾何分布)
    rv_hypergeom = hypergeom(M, N_A, n)
    x_values = np.arange(0, n+1)
    pmf_hypergeom = rv_hypergeom.pmf(x_values)

    # 復元抽出(二項分布)
    p = N_A / M  # 豆Aを引く確率
    rv_binom = binom(n, p)
    pmf_binom = rv_binom.pmf(x_values)

    # グラフ描画
    ax.plot(x_values, pmf_hypergeom, 'bo-', label='非復元抽出 (超幾何分布)', markersize=5)
    ax.plot(x_values, pmf_binom, 'ro-', label='復元抽出 (二項分布)', markersize=5)
    condition_text = f'M = {M}, N_A = {N_A}, n = {n}'
    ax.text(0.05, 0.95, condition_text, transform=ax.transAxes,
            fontsize=12, verticalalignment='top')
    ax.set_xlabel('豆Aの数')
    ax.set_ylabel('確率')
    ax.grid(True)
    ax.legend()

# パラメータ比を一定に保ったグラフを作成
M_values = [50, 150, 250, 350, 450]
N_A_values = [15, 45, 75, 105, 135]  # M の 30%
n_values = [7, 22, 37, 52, 67]       # M の 15%

# サブプロットを作成(縦に並べる)
fig, axs = plt.subplots(5, 1, figsize=(10, 30))

# 異なるパラメータ設定でグラフを描画
for i in range(5):
    plot_comparison(M=M_values[i], N_A=N_A_values[i], n=n_values[i], ax=axs[i])

# レイアウトの自動調整
plt.tight_layout()

# 余白の手動調整
plt.subplots_adjust(right=0.95)

plt.show()

復元抽出と非復元抽出の比較(顕著な違いが現れる条件)

import numpy as np
import matplotlib.pyplot as plt
from scipy.stats import binom, hypergeom

# グラフを描画する関数
def plot_comparison(M, N_A, n, ax):
    # 非復元抽出(超幾何分布)
    rv_hypergeom = hypergeom(M, N_A, n)
    x_values = np.arange(0, n+1)
    pmf_hypergeom = rv_hypergeom.pmf(x_values)

    # 復元抽出(二項分布)
    p = N_A / M  # 豆Aを引く確率
    rv_binom = binom(n, p)
    pmf_binom = rv_binom.pmf(x_values)

    # グラフ描画
    ax.plot(x_values, pmf_hypergeom, 'bo-', label='非復元抽出 (超幾何分布)', markersize=5)
    ax.plot(x_values, pmf_binom, 'ro-', label='復元抽出 (二項分布)', markersize=5)
    condition_text = f'M = {M}, N_A = {N_A}, n = {n}'
    ax.text(0.05, 0.95, condition_text, transform=ax.transAxes,
            fontsize=12, verticalalignment='top')
    ax.set_xlabel('豆Aの数')
    ax.set_ylabel('確率')
    ax.grid(True)
    ax.legend()

# サブプロットを作成(縦に並べる)
fig, axs = plt.subplots(3, 1, figsize=(10, 18))  # 高さを調整

# 条件1: サンプルサイズが大きい場合
plot_comparison(M=100, N_A=30, n=80, ax=axs[0])

# 条件2: 全体のサイズが小さい場合
plot_comparison(M=20, N_A=6, n=15, ax=axs[1])

# 条件3: 極端な割合の場合
plot_comparison(M=100, N_A=90, n=30, ax=axs[2])

# レイアウトの自動調整
plt.tight_layout()

# 余白の手動調整
plt.subplots_adjust(right=0.95)

plt.show()

考察

二項分布と超幾何分布の違いが顕著になるのは、サンプルサイズが全体に対して大きい場合や、母集団が小さい場合です。例えば、全体の豆の数が100個で80個を抽出する場合や、母集団が20個でそのうち15個を抽出する場合、非復元抽出では次の試行に与える影響が大きくなり、復元抽出との差が明確に現れます。また、成功確率が極端に高いか低い場合も、非復元抽出の影響で分布が変わりやすくなります。一方、サンプルサイズが小さい場合や母集団が非常に大きい場合には、各抽出の影響が少なく、二項分布と超幾何分布の違いは目立たなくなります。

2021 Q2(4)

事前分布と尤度から事後確率が最大となるパラメータの推定値を求めました。

コード

数式を使った計算

# 2021 Q2(4)  2024.8.24

import numpy as np
from scipy.special import comb

# 事前分布 P(N_A)
def prior(NA):
    return NA + 1

# 尤度関数 P(X = 4 | N_A)
def likelihood(NA):
    return comb(NA, 4) * comb(100 - NA, 11) / comb(100, 15)

# 事後分布 P(N_A | X = 4) (正規化定数は省略)
def posterior(NA):
    return prior(NA) * likelihood(NA)

# N_A の範囲
NA_values = np.arange(4, 90)

# 事後分布の計算
posterior_values = [posterior(NA) for NA in NA_values]

# 最大値を取る N_A (事後モード) を探索
NA_mode = NA_values[np.argmax(posterior_values)]

NA_mode
30

プロット

# 2021 Q2(4)  2024.8.24

import numpy as np
import matplotlib.pyplot as plt
from scipy.special import comb

# 事前分布 P(N_A)
def prior(NA):
    return NA + 1

# 正規化定数
C = 1 / 5151

# 尤度関数 P(X = 4 | N_A)
def likelihood(NA):
    return comb(NA, 4) * comb(100 - NA, 11) / comb(100, 15)

# 事後分布 P(N_A | X = 4)
def posterior(NA):
    return prior(NA) * likelihood(NA)

# N_A の範囲を0から100まで(事前分布用)
NA_values_full = np.arange(0, 101)

# 事前分布を計算(0から100まで)
prior_values_full = [C * prior(NA) for NA in NA_values_full]

# N_A の範囲を4から89まで(事後分布用)
NA_values = np.arange(4, 90)

# 事後分布の計算
posterior_values = [posterior(NA) for NA in NA_values]

# 事後分布の正規化
posterior_sum = sum(posterior_values)
posterior_values_normalized = [value / posterior_sum for value in posterior_values]

# 事前分布が存在しない場合の事後分布(尤度のみを正規化)
likelihood_values = [likelihood(NA) for NA in NA_values]
likelihood_sum = sum(likelihood_values)
likelihood_values_normalized = [value / likelihood_sum for value in likelihood_values]

# 3つの分布を重ねて表示
plt.figure(figsize=(10, 6))

# 事前分布のプロット(0から100まで)
plt.plot(NA_values_full, prior_values_full, 'g-', label=r'事前分布 $P(N_A)$', markersize=5)

# 事後分布のプロット(4から89まで)
plt.plot(NA_values, posterior_values_normalized, 'bo-', label=r'事後分布 $P(N_A | X = 4)$', markersize=5)

# 事前分布が存在しない場合の事後分布(尤度のみ)
plt.plot(NA_values, likelihood_values_normalized, 'r-', label=r'事前分布なし $P(N_A | X = 4)$', markersize=5)

# 事後モードのプロット
NA_mode = NA_values[np.argmax(posterior_values_normalized)]
plt.axvline(NA_mode, color='blue', linestyle='--', label=f'事後モード: {NA_mode}')

# 事前分布なしの場合の最尤推定値のプロット
NA_mode_likelihood = NA_values[np.argmax(likelihood_values_normalized)]
plt.axvline(NA_mode_likelihood, color='red', linestyle=':', label=f'最尤推定値 (事前分布なし): {NA_mode_likelihood}')

# グラフの設定
plt.xlabel(r'$N_A$')
plt.ylabel(r'確率')
plt.title(r'事前分布ありとなしの比較')
plt.grid(True)
plt.legend()
plt.show()

2021 Q2(2)

超幾何分布の当たりの数の推定値を尤度比を使って求めました。

コード

シミュレーションによる計算

# 2021 Q2(2)  2024.8.22

import numpy as np
from scipy.special import comb

# 尤度関数 L(N_A) を定義
def L(NA):
    return comb(NA, 4) * comb(100 - NA, 11) / comb(100, 15)

# L(N_A + 1) / L(N_A) を計算し、条件を満たす最小の N_A を探索
# max(0, N_A - 85) ≤ 4 ≤ min(15, N_A) の式に基づき、取り出した豆Aが4粒の場合の N_A の範囲を設定 (4 ≤ N_A ≤ 89)
NA_values = np.arange(4, 90)
ratios = [(L(NA + 1) / L(NA)) for NA in NA_values]
NA_optimal = NA_values[np.where(np.array(ratios) < 1)[0][0]]

print(f"L(N_A + 1) / L(N_A) < 1 となる最小の N_A は {NA_optimal} です。")
L(N_A + 1) / L(N_A) < 1 となる最小の N_A は 26 です。

プロット

# 2021 Q2(2)  2024.8.22

import numpy as np
import matplotlib.pyplot as plt
from scipy.special import comb

# 尤度関数 L(N_A) を定義
def L(NA):
    return comb(NA, 4) * comb(100 - NA, 11) / comb(100, 15)

# N_A の範囲を設定
NA_values = np.arange(4, 90)
ratios = [(L(NA + 1) / L(NA)) for NA in NA_values]

# グラフの描画
plt.figure(figsize=(10, 6))
plt.plot(NA_values, ratios, 'bo-', label=r'$\frac{L(N_A + 1)}{L(N_A)}$', markersize=8)
plt.axhline(y=1, color='red', linestyle='--', label=r'$1$')
plt.xlabel(r'$N_A$')
plt.ylabel(r'$\frac{L(N_A + 1)}{L(N_A)}$')
plt.title(r'$N_A$ の尤度比 $\frac{L(N_A + 1)}{L(N_A)}$')
plt.legend()
plt.grid(True)
plt.show()

プロット(NA=26付近をズーム)

# 2021 Q2(2)  2024.8.22

import numpy as np
import matplotlib.pyplot as plt
from scipy.special import comb

# 尤度関数 L(N_A) を定義
def L(NA):
    return comb(NA, 4) * comb(100 - NA, 11) / comb(100, 15)

# N_A の範囲を設定
NA_values = np.arange(4, 90)
ratios = [(L(NA + 1) / L(NA)) for NA in NA_values]

# 26付近のズームしたグラフを描画
plt.figure(figsize=(10, 6))
plt.plot(NA_values, ratios, 'bo-', label=r'$\frac{L(N_A + 1)}{L(N_A)}$', markersize=8)
plt.axhline(y=1, color='red', linestyle='--', label=r'$1$')
plt.xlabel(r'$N_A$')
plt.ylabel(r'$\frac{L(N_A + 1)}{L(N_A)}$')
plt.title(r'$N_A$ の尤度比 $\frac{L(N_A + 1)}{L(N_A)}$ (25 < $N_A$ < 30)')
plt.xlim(25, 30)  # N_A = 26 付近をズーム
plt.ylim(0.95, 1.05)  # y軸もズームして見やすく
plt.legend()
plt.grid(True)
plt.show()

2021 Q2(1)

超幾何分布の問題をやりました。

コード

シミュレーションによる計算

# 2021 Q2(1)  2024.8.21

import numpy as np
import matplotlib.pyplot as plt
from scipy.stats import hypergeom

# パラメータの設定
M = 100        # 全体の豆の数
N_A = 30       # 豆Aの数
n = 15         # 抽出する豆の数
x_values = np.arange(0, n+1)  # 可能な豆Aの数

# 理論的な超幾何分布のPMFを計算
rv = hypergeom(M, N_A, n)
pmf_theoretical = rv.pmf(x_values)

# 数値シミュレーションの設定
n_simulations = 10000  # シミュレーション回数
simulated_counts = []

# シミュレーションの実行
for _ in range(n_simulations):
    # 袋の中の豆を表すリスト(1が豆A、0が豆B)
    bag = np.array([1]*N_A + [0]*(M - N_A))
    # 無作為に15個抽出
    sample = np.random.choice(bag, size=n, replace=False)
    # 抽出した中の豆Aの数をカウント
    count_A = np.sum(sample)
    simulated_counts.append(count_A)

# シミュレーションから得られたPMFを計算
pmf_simulated, bins = np.histogram(simulated_counts, bins=np.arange(-0.5, n+1.5, 1), density=True)

# グラフの描画
plt.figure(figsize=(10, 6))

# 理論的なPMFの描画
plt.plot(x_values, pmf_theoretical, 'bo-', label='理論的PMF', markersize=8)

# シミュレーション結果をヒストグラムとして描画
plt.hist(simulated_counts, bins=np.arange(-0.5, n+1.5, 1), density=True, alpha=0.5, color='red', label='シミュレーション結果')

# グラフの設定
plt.xlabel('豆Aの数')
plt.ylabel('確率')
plt.title('超幾何分布のPMF: 理論とシミュレーションの比較')
plt.legend()
plt.grid(True)
plt.show()