二項分布と超幾何分布
二項分布
- 抽出方法: 復元抽出
- 試行の独立性: 各試行は独立
- 確率: 各試行で成功確率は一定
超幾何分布
- 抽出方法: 非復元抽出
- 試行の独立性: 各試行は独立していない
- 確率: 各試行で成功確率が変化
グラフの比較
今回の実験では、二項分布と超幾何分布の違いを視覚的に比較します。二項分布は、復元抽出を行う場合に適用され、各試行が独立しており、成功確率が一定です。一方、超幾何分布は、非復元抽出を行う場合に適用され、試行ごとに成功確率が変化します。実験では、母集団のサイズ、成功対象の数、抽出回数を変え、それぞれのグラフを描画します。特に、サンプルサイズが大きい場合や母集団が小さい場合など、分布の形状に顕著な違いが現れる条件に注目して比較を行います。これにより、抽出方法による分布の違いを視覚的に確認し、二項分布と超幾何分布の特性を理解します。
復元抽出と非復元抽出の比較(広範囲のパラメータ設定)
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個を抽出する場合、非復元抽出では次の試行に与える影響が大きくなり、復元抽出との差が明確に現れます。また、成功確率が極端に高いか低い場合も、非復元抽出の影響で分布が変わりやすくなります。一方、サンプルサイズが小さい場合や母集団が非常に大きい場合には、各抽出の影響が少なく、二項分布と超幾何分布の違いは目立たなくなります。
2014 Q5(4)
テレビ番組の視聴満足回数の調査で満足と答えた回数のそれぞれ人数の適合度検定を実施し適合を判断する手順を述べました。
コード
多項確率が、に忠実に基づく場合と、各番組または各回答者の満足度が異なるモデルにおいて、カイ二乗統計量、尤度比統計量、およびp-値を計算し、モデルの適合性を比較します。
import numpy as np
from scipy.stats import chi2
import matplotlib.pyplot as plt
# シミュレーションの設定
n = 100 # 回答者数
p_true = 0.6 # 真の成功確率(忠実なモデル)
categories = np.arange(5) # カテゴリ (0~4)
n_simulations = 1000 # シミュレーション回数
# 忠実なモデルの確率 q_j
qj_true = [np.math.comb(4, j) * (p_true ** j) * ((1 - p_true) ** (4 - j)) for j in categories]
# 統計量を記録するリスト
chi_squared_true = []
likelihood_ratio_true = []
chi_squared_noisy_program = []
likelihood_ratio_noisy_program = []
chi_squared_noisy_responder = []
likelihood_ratio_noisy_responder = []
# 二項分布に従わない (qj_noisy_program): q_j をランダムに変更してズラす
qj_noisy_program = np.array(qj_true) + np.random.uniform(-0.1, 0.1, size=len(qj_true))
qj_noisy_program = np.clip(qj_noisy_program, 0, None) # 確率が0未満にならないようにする
qj_noisy_program = qj_noisy_program / np.sum(qj_noisy_program) # 確率なので正規化
# 各回答者の満足度が異なる場合(qj_noisy_responder)をランダム設定
p_responders = np.random.uniform(0.35, 0.85, size=n)
qj_noisy_responder = np.zeros(len(categories))
for p in p_responders:
qj_responder = [np.math.comb(4, j) * (p ** j) * ((1 - p) ** (4 - j)) for j in categories]
qj_noisy_responder += qj_responder
qj_noisy_responder /= np.sum(qj_noisy_responder)
# シミュレーション開始
for _ in range(n_simulations):
# 忠実なモデル(均一)
obs_true = np.random.multinomial(n, qj_true)
exp_true = n * np.array(qj_true)
chi2_stat_true = np.sum((obs_true - exp_true) ** 2 / exp_true) # カイ二乗統計量
likelihood_stat_true = 2 * np.sum(obs_true * np.log(obs_true / exp_true, where=(obs_true > 0))) # 尤度比統計量
chi_squared_true.append(chi2_stat_true)
likelihood_ratio_true.append(likelihood_stat_true)
# 各番組の満足度が異なる場合
obs_noisy_program = np.random.multinomial(n, qj_noisy_program)
exp_noisy_program = n * np.array(qj_true)
chi2_stat_noisy_program = np.sum((obs_noisy_program - exp_noisy_program) ** 2 / exp_noisy_program) # カイ二乗統計量
likelihood_stat_noisy_program = 2 * np.sum(obs_noisy_program * np.log(obs_noisy_program / exp_noisy_program, where=(obs_noisy_program > 0))) # 尤度比統計量
chi_squared_noisy_program.append(chi2_stat_noisy_program)
likelihood_ratio_noisy_program.append(likelihood_stat_noisy_program)
# 各回答者の満足度が異なる場合
obs_noisy_responder = np.random.multinomial(n, qj_noisy_responder)
exp_noisy_responder = n * np.array(qj_true)
chi2_stat_noisy_responder = np.sum((obs_noisy_responder - exp_noisy_responder) ** 2 / exp_noisy_responder) # カイ二乗統計量
likelihood_stat_noisy_responder = 2 * np.sum(obs_noisy_responder * np.log(obs_noisy_responder / exp_noisy_responder, where=(obs_noisy_responder > 0))) # 尤度比統計量
chi_squared_noisy_responder.append(chi2_stat_noisy_responder)
likelihood_ratio_noisy_responder.append(likelihood_stat_noisy_responder)
# 平均値を計算
mean_chi2_true = np.mean(chi_squared_true)
mean_likelihood_true = np.mean(likelihood_ratio_true)
mean_chi2_noisy_program = np.mean(chi_squared_noisy_program)
mean_likelihood_noisy_program = np.mean(likelihood_ratio_noisy_program)
mean_chi2_noisy_responder = np.mean(chi_squared_noisy_responder)
mean_likelihood_noisy_responder = np.mean(likelihood_ratio_noisy_responder)
# 各統計量に対応するp値を計算
p_value_chi2_true = 1 - chi2.cdf(mean_chi2_true, df=3)
p_value_likelihood_true = 1 - chi2.cdf(mean_likelihood_true, df=3)
p_value_chi2_noisy_program = 1 - chi2.cdf(mean_chi2_noisy_program, df=3)
p_value_likelihood_noisy_program = 1 - chi2.cdf(mean_likelihood_noisy_program, df=3)
p_value_chi2_noisy_responder = 1 - chi2.cdf(mean_chi2_noisy_responder, df=3)
p_value_likelihood_noisy_responder = 1 - chi2.cdf(mean_likelihood_noisy_responder, df=3)
# 結果の出力
print(f"忠実なモデル(均一)の平均カイ二乗統計量: {mean_chi2_true:.4f}, 平均p値: {p_value_chi2_true:.4f}")
print(f"忠実なモデル(均一)の平均尤度比統計量: {mean_likelihood_true:.4f}, 平均p値: {p_value_likelihood_true:.4f}")
print(f"各番組の満足度が異なる場合の平均カイ二乗統計量: {mean_chi2_noisy_program:.4f}, 平均p値: {p_value_chi2_noisy_program:.4f}")
print(f"各番組の満足度が異なる場合の平均尤度比統計量: {mean_likelihood_noisy_program:.4f}, 平均p値: {p_value_likelihood_noisy_program:.4f}")
print(f"各回答者の満足度が異なる場合の平均カイ二乗統計量: {mean_chi2_noisy_responder:.4f}, 平均p値: {p_value_chi2_noisy_responder:.4f}")
print(f"各回答者の満足度が異なる場合の平均尤度比統計量: {mean_likelihood_noisy_responder:.4f}, 平均p値: {p_value_likelihood_noisy_responder:.4f}")
# カイ二乗分布のPDFを計算
x = np.linspace(0, 20, 500) # x軸の範囲
pdf = chi2.pdf(x, df=3) # 自由度3のPDF
# グラフの描画
plt.figure(figsize=(10, 6))
plt.plot(x, pdf, label="自由度3のカイ二乗分布", linewidth=2)
plt.axvline(mean_chi2_true, color="blue", linestyle="--", label=f"忠実モデルのカイ二乗: {mean_chi2_true:.2f}")
plt.axvline(mean_likelihood_true, color="cyan", linestyle="--", label=f"忠実モデルの尤度比: {mean_likelihood_true:.2f}")
plt.axvline(mean_chi2_noisy_program, color="green", linestyle="--", label=f"番組ごとに異なるカイ二乗: {mean_chi2_noisy_program:.2f}")
plt.axvline(mean_likelihood_noisy_program, color="lime", linestyle="--", label=f"番組ごとに異なる尤度比: {mean_likelihood_noisy_program:.2f}")
plt.axvline(mean_chi2_noisy_responder, color="red", linestyle="--", label=f"回答者ごとに異なるカイ二乗: {mean_chi2_noisy_responder:.2f}")
plt.axvline(mean_likelihood_noisy_responder, color="magenta", linestyle="--", label=f"回答者ごとに異なる尤度比: {mean_likelihood_noisy_responder:.2f}")
plt.xlabel("$X^2$ 値", fontsize=12)
plt.ylabel
plt.ylabel("確率密度", fontsize=12)
plt.title("自由度3のカイ二乗分布と統計量", fontsize=14)
plt.legend(fontsize=12) # ここで凡例を表示
plt.grid(alpha=0.5)
plt.show()
忠実なモデル(均一)の平均カイ二乗統計量: 4.1751, 平均p値: 0.2432
忠実なモデル(均一)の平均尤度比統計量: 4.3247, 平均p値: 0.2285
各番組の満足度が異なる場合の平均カイ二乗統計量: 13.2002, 平均p値: 0.0042
各番組の満足度が異なる場合の平均尤度比統計量: 16.4412, 平均p値: 0.0009
各回答者の満足度が異なる場合の平均カイ二乗統計量: 10.3066, 平均p値: 0.0161
各回答者の満足度が異なる場合の平均尤度比統計量: 8.5302, 平均p値: 0.0362
忠実なモデルの平均p-値は大きく、モデルによく適合していることが分かります。一方、各番組または各回答者の満足度が異なるモデルではp-値が0.05以下となり、モデルがデータに適合していないことが分かります。
2014 Q5(3)
テレビ番組の視聴満足回数の調査で満足と答えた回数のそれぞれ人数の適合度検定のための尤度比検定量と自由度を求めました。
コード
多項確率が、に忠実に基づく場合と、ランダムにノイズを加えた(ズレた)場合についてシミュレーションを行い、尤度比統計量とp-値を計算して比較します。
# 2014 Q5(3) 2025.1.17
import numpy as np
from scipy.stats import chi2
import matplotlib.pyplot as plt
# シミュレーションの設定
n = 100 # 人数
p_true = 0.6 # 真の成功確率
categories = np.arange(5) # カテゴリ (0~4)
n_simulations = 1000 # シミュレーション回数
# 二項分布モデルに基づく q_j の計算 (忠実な設定)
qj_true = [np.math.comb(4, j) * (p_true ** j) * ((1 - p_true) ** (4 - j)) for j in categories]
# 二項分布に従わない (qj_noisy): q_j をランダムに変更してズラす
qj_noisy = np.array(qj_true) + np.random.uniform(-0.1, 0.1, size=len(qj_true))
qj_noisy = np.clip(qj_noisy, 0, None) # 確率が0未満にならないようにする
qj_noisy = qj_noisy / np.sum(qj_noisy) # 確率なので正規化
# 尤度比統計量を記録するリスト
likelihood_ratio_true = []
p_values_true = []
likelihood_ratio_noisy = []
p_values_noisy = []
for _ in range(n_simulations):
# 忠実なモデルの観測データ
obs_true = np.random.multinomial(n, qj_true)
exp_true = n * np.array(qj_true)
likelihood_stat_true = 2 * np.sum(obs_true * np.log(obs_true / exp_true, where=(obs_true > 0)))
p_val_true = 1 - chi2.cdf(likelihood_stat_true, df=3) # 自由度 = カテゴリ数 - 1 - 推定パラメータ数
likelihood_ratio_true.append(likelihood_stat_true)
p_values_true.append(p_val_true)
# ズレたモデルの観測データ
obs_noisy = np.random.multinomial(n, qj_noisy)
exp_noisy = n * np.array(qj_true) # 忠実な期待値を使用
likelihood_stat_noisy = 2 * np.sum(obs_noisy * np.log(obs_noisy / exp_noisy, where=(obs_noisy > 0)))
p_val_noisy = 1 - chi2.cdf(likelihood_stat_noisy, df=3)
likelihood_ratio_noisy.append(likelihood_stat_noisy)
p_values_noisy.append(p_val_noisy)
# 平均尤度比統計量を計算
mean_likelihood_true = np.mean(likelihood_ratio_true)
mean_likelihood_noisy = np.mean(likelihood_ratio_noisy)
# カイ二乗分布のPDFを計算
x = np.linspace(0, 20, 500) # x軸の範囲
pdf = chi2.pdf(x, df=3) # 自由度3のPDF
# 結果の出力
print(f"忠実なモデルの平均尤度比統計量: {mean_likelihood_true:.4f}")
print(f"忠実なモデルの平均p値: {np.mean(p_values_true):.4f}")
print(f"ズレたモデルの平均尤度比統計量: {mean_likelihood_noisy:.4f}")
print(f"ズレたモデルの平均p値: {np.mean(p_values_noisy):.4f}")
# グラフの描画
plt.figure(figsize=(10, 6))
plt.plot(x, pdf, label="自由度3のカイ二乗分布", linewidth=2)
plt.axvline(mean_likelihood_true, color="blue", linestyle="--", label=f"忠実モデルの平均: {mean_likelihood_true:.2f}")
plt.axvline(mean_likelihood_noisy, color="red", linestyle="--", label=f"ズレモデルの平均: {mean_likelihood_noisy:.2f}")
plt.xlabel("$X^2$ 値", fontsize=12)
plt.ylabel("確率密度", fontsize=12)
plt.title("自由度3のカイ二乗分布と平均尤度比統計量", fontsize=14)
plt.legend(fontsize=12)
plt.grid(alpha=0.5)
plt.show()
忠実なモデルの平均尤度比統計量: 3.9418
忠実なモデルの平均p値: 0.3909
ズレたモデルの平均尤度比統計量: 16.7360
ズレたモデルの平均p値: 0.0081
忠実なモデルの平均p-値は大きく、モデルによく適合していることが分かります。一方、ランダムにノイズを加えた(ズレた)モデルではp-値が0.05以下となり、モデルがデータに適合していないことが分かります。
2014 Q5(2)
テレビ番組の視聴満足回数の調査で満足と答えた回数のそれぞれ人数の適合度カイ二乗統計量と自由度を求めました。
コード
多項確率が、に忠実に基づく場合と、ランダムにノイズを加えた(ズレた)場合についてシミュレーションを行い、適合度カイ二乗統計量とp-値を計算して比較します。
# 2014 Q5(2) 2025.1.16
import numpy as np
from scipy.stats import chi2
import matplotlib.pyplot as plt
# シミュレーションの設定
n = 100 # 人数
p_true = 0.6 # 真の成功確率
categories = np.arange(5) # カテゴリ (0~4)
n_simulations = 1000 # シミュレーション回数
# 二項分布モデルに基づく q_j の計算 (忠実な設定)
qj_true = [np.math.comb(4, j) * (p_true ** j) * ((1 - p_true) ** (4 - j)) for j in categories]
# 二項分布に従わない (qj_noisy): q_j をランダムに変更してズラす
qj_noisy = np.array(qj_true) + np.random.uniform(-0.1, 0.1, size=len(qj_true))
qj_noisy = np.clip(qj_noisy, 0, None) # 確率が0未満にならないようにする
qj_noisy = qj_noisy / np.sum(qj_noisy) # 確率なので正規化
# カイ二乗統計量と p 値を記録するリスト
chi_squared_true = []
p_values_true = []
chi_squared_noisy = []
p_values_noisy = []
for _ in range(n_simulations):
# 忠実なモデルの観測データ
obs_true = np.random.multinomial(n, qj_true)
exp_true = n * np.array(qj_true)
chi2_stat_true = np.sum((obs_true - exp_true) ** 2 / exp_true)
p_val_true = 1 - chi2.cdf(chi2_stat_true, df=3) # 自由度 = カテゴリ数 - 1 - 推定パラメータ数
chi_squared_true.append(chi2_stat_true)
p_values_true.append(p_val_true)
# ズレたモデルの観測データ
obs_noisy = np.random.multinomial(n, qj_noisy)
exp_noisy = n * np.array(qj_true) # 忠実な期待値を使用
chi2_stat_noisy = np.sum((obs_noisy - exp_noisy) ** 2 / exp_noisy)
p_val_noisy = 1 - chi2.cdf(chi2_stat_noisy, df=3)
chi_squared_noisy.append(chi2_stat_noisy)
p_values_noisy.append(p_val_noisy)
# 平均カイ二乗統計量を計算
mean_chi2_true = np.mean(chi_squared_true)
mean_chi2_noisy = np.mean(chi_squared_noisy)
# カイ二乗分布のPDFを計算
x = np.linspace(0, 20, 500) # x軸の範囲
pdf = chi2.pdf(x, df=3) # 自由度3のPDF
# 結果の出力
print(f"忠実なモデルの平均カイ二乗統計量: {mean_chi2_true:.4f}")
print(f"忠実なモデルの平均p値: {np.mean(p_values_true):.4f}")
print(f"ズレたモデルの平均カイ二乗統計量: {mean_chi2_noisy:.4f}")
print(f"ズレたモデルの平均p値: {np.mean(p_values_noisy):.4f}")
# グラフの描画
plt.figure(figsize=(10, 6))
plt.plot(x, pdf, label="自由度3のカイ二乗分布", linewidth=2)
plt.axvline(mean_chi2_true, color="blue", linestyle="--", label=f"忠実モデルの平均: {mean_chi2_true:.2f}")
plt.axvline(mean_chi2_noisy, color="red", linestyle="--", label=f"ズレモデルの平均: {mean_chi2_noisy:.2f}")
plt.xlabel("$X^2$ 値", fontsize=12)
plt.ylabel("確率密度", fontsize=12)
plt.title("自由度3のカイ二乗分布と平均カイ二乗統計量", fontsize=14)
plt.legend(fontsize=12)
plt.grid(alpha=0.5)
plt.show()
忠実なモデルの平均カイ二乗統計量: 3.8112
忠実なモデルの平均p値: 0.4026
ズレたモデルの平均カイ二乗統計量: 13.4317
ズレたモデルの平均p値: 0.0236
忠実なモデルの平均p-値は大きく、モデルによく適合していることが分かります。一方、ランダムにノイズを加えた(ズレた)モデルではp-値が0.05以下となり、モデルがデータに適合していないことが分かります。
2014 Q5(1)
テレビ番組の視聴満足回数の調査で満足と答えた回数のそれぞれ人数との組みが多項分布に従うのを利用し多項確率を構成する二項分布の確率pの最尤推定量を求めました。
コード
真の確率pに基づいてシミュレーションを行い、最尤推定値を計算し、真の確率pと比較します。
# 2014 Q5(1) 2025.1.15
import numpy as np
import matplotlib.pyplot as plt
# シミュレーションのパラメータ
n_simulations = 10000 # シミュレーション回数
n = 100 # 調査対象の人数
p_true = 0.6 # 真の満足確率
# nj のシミュレーション (j = 0, 1, 2, 3, 4)
data = np.random.binomial(4, p_true, size=n_simulations * n).reshape(n_simulations, n)
# 各シミュレーションでの最尤推定値を計算
p_estimates = np.sum(data, axis=1) / (4 * n)
# 平均値(推定されたp^の期待値)を計算
mean_p_estimate = np.mean(p_estimates)
# 推定されたp^の平均値と真の値を出力
print(f"推定された最尤推定値の平均: {mean_p_estimate:.4f}")
print(f"真の値: {p_true:.4f}")
# グラフの描画
plt.hist(p_estimates, bins=30, density=True, alpha=0.75, label="推定された $\\hat{p}$")
plt.axvline(p_true, color='red', linestyle='dashed', label=f"真の値 $p = {p_true}$")
plt.xlabel("推定された $\\hat{p}$")
plt.ylabel("密度")
plt.title("最尤推定値 $\\hat{p}$ の分布")
plt.legend()
plt.grid(alpha=0.5)
plt.show()
推定された最尤推定値の平均: 0.5997
真の値: 0.6000
シミュレーションの結果、最尤推定値は、真の確率pに近い値を示しました。
2016 Q4(2)
n個の標準正規分布に従う乱数が-1以上1以下となる個数が従う分布を求めました。また乱数が0以上1以下となる確率の推定値の分散を求めました。
コード
この実験では、標準正規分布N(0,1)と、n個の標準正規分布に従う乱数のうち-1以上1以下となる個数Yの分布、およびその確率を推定する量の分布を確認します。
# 2016 Q4(2) 2024.11.24
import numpy as np
import matplotlib.pyplot as plt
from scipy.stats import binom, norm
# ---- グラフ 1: 標準正規分布 N(0,1) と範囲 (|Z| < 1) ----
# パラメータの設定
n_samples = 10000 # サンプル数
z_min, z_max = -1, 1 # 条件の範囲 (|Z| < 1)
# 標準正規分布 N(0,1) に従う乱数を生成します
samples = np.random.normal(0, 1, n_samples)
# 理論的な標準正規分布の確率密度関数を計算します
x1 = np.linspace(-4, 4, 500)
pdf_theoretical = norm.pdf(x1, loc=0, scale=1)
# ---- グラフ 2: Y の分布(二項分布) ----
# シミュレーションの設定
n_trials = 1000 # シミュレーションの試行回数
n = 50 # サンプルサイズ (1試行あたりの乱数生成数)
theta = 0.3413 # 真の成功確率 (0 < Z < 1)
# Y の分布を計算
Y_values = []
for _ in range(n_trials):
samples_trial = np.random.normal(0, 1, n)
Y = np.sum((samples_trial > z_min) & (samples_trial < z_max)) # 絶対値が1以下の個数
Y_values.append(Y)
# 理論的な二項分布
p_Y = 2 * theta # |Z| < 1 の確率
x2 = np.arange(0, n + 1)
binomial_pmf_Y = binom.pmf(x2, n, p_Y)
# ---- グラフ 3: θ̂2 の分布と理論分布 ----
# θ̂2 = Y / (2n) を計算
theta_hat_2_values = [Y / (2 * n) for Y in Y_values]
# 理論分布用のデータ
x3 = np.linspace(0, 1, 100)
binomial_pdf_theta_2 = norm.pdf(x3, loc=p_Y / 2, scale=np.sqrt(p_Y * (1 - p_Y) / (4 * n)))
# ---- 3つのグラフを描画 ----
plt.figure(figsize=(10, 12)) # グラフ全体のサイズを指定
# グラフ 1
plt.subplot(3, 1, 1)
plt.hist(samples, bins=50, density=True, alpha=0.5, label='全データ (N(0,1))', color='purple')
plt.axvspan(z_min, z_max, color='orange', alpha=0.3, label='|Z| < 1 の領域')
plt.plot(x1, pdf_theoretical, 'r-', label='理論分布 (N(0,1))', linewidth=2)
plt.title('N(0,1) に従う乱数のヒストグラムと領域', fontsize=14)
plt.xlabel('Z 値', fontsize=12)
plt.ylabel('確率密度', fontsize=12)
plt.legend(fontsize=12)
plt.grid(alpha=0.3)
# グラフ 2
plt.subplot(3, 1, 2)
plt.hist(Y_values, bins=np.arange(0, n + 2) - 0.5, density=True, alpha=0.6, color='green', label='Y の分布 (シミュレーション)')
plt.plot(x2, binomial_pmf_Y, 'ro-', label='理論分布 (Binomial)', markersize=4)
plt.title('Y の分布と理論分布の比較', fontsize=14)
plt.xlabel('Y 値', fontsize=12)
plt.ylabel('確率密度', fontsize=12)
plt.legend(fontsize=12)
plt.grid(alpha=0.3)
# グラフ 3
plt.subplot(3, 1, 3)
plt.hist(theta_hat_2_values, bins=10, density=True, alpha=0.6, color='blue', label='$\\hat{\\theta}_2$ の分布 (シミュレーション)')
plt.plot(x3, binomial_pdf_theta_2, 'r-', label='理論分布 $N(\\theta, V[\\hat{\\theta}_2])$', linewidth=2)
plt.title('$\\hat{\\theta}_2$ の分布と理論分布の比較', fontsize=14)
plt.xlabel('$\\hat{\\theta}_2$ 値', fontsize=12)
plt.ylabel('確率密度', fontsize=12)
plt.legend(fontsize=12)
plt.grid(alpha=0.3)
# グラフを表示
plt.tight_layout() # 全体を整える
plt.show()
この実験によってYが二項分布B(n,2θ)に従うことと、が正規分布に従うことが確認できました。
2016 Q4(1)
n個の標準正規分布に従う乱数が0以上1以下となる個数が従う分布を求めました。また乱数が0以上1以下となる確率の推定値の分散を求めました。
コード
この実験では、標準正規分布N(0,1)と、n個の標準正規分布に従う乱数のうち0以上1以下となる個数Xの分布、およびその確率を推定する量の分布を確認します。
# 2016 Q4(1) 2024.11.23
import numpy as np
import matplotlib.pyplot as plt
from scipy.stats import binom, norm
# ---- グラフ 1: 標準正規分布 N(0,1) と範囲 (0 < Z < 1) ----
# パラメータの設定
n_samples = 10000 # サンプル数
z_min, z_max = 0, 1 # 条件の範囲 (0 < Z < 1)
# 標準正規分布 N(0,1) に従う乱数を生成します
samples = np.random.normal(0, 1, n_samples)
# 理論的な標準正規分布の確率密度関数を計算します
x1 = np.linspace(-4, 4, 500)
pdf_theoretical = norm.pdf(x1, loc=0, scale=1)
# ---- グラフ 2: X の分布(二項分布) ----
# シミュレーションの設定
n_trials = 1000 # シミュレーションの試行回数
n = 50 # サンプルサイズ (1試行あたりの乱数生成数)
theta = 0.3413 # 真の成功確率 (0 < Z < 1)
# X の分布を計算
X_values = []
for _ in range(n_trials):
samples_trial = np.random.normal(0, 1, n)
X = np.sum((samples_trial > z_min) & (samples_trial < z_max))
X_values.append(X)
# 理論的な二項分布
x2 = np.arange(0, n + 1)
binomial_pmf = binom.pmf(x2, n, theta)
# ---- グラフ 3: θ̂1 の分布と理論分布 ----
# θ̂1 = X / n を計算
theta_hat_1_values = [X / n for X in X_values]
# 理論分布用のデータ
x3 = np.linspace(0, 1, 100)
binomial_pdf = norm.pdf(x3, loc=theta, scale=np.sqrt(theta * (1 - theta) / n))
# ---- 3つのグラフを描画 ----
plt.figure(figsize=(10, 10)) # グラフ全体のサイズを指定
# グラフ 1
plt.subplot(3, 1, 1)
plt.hist(samples, bins=50, density=True, alpha=0.5, label='全データ (N(0,1))', color='purple')
plt.axvspan(z_min, z_max, color='orange', alpha=0.3, label='0 < Z < 1 の領域')
plt.plot(x1, pdf_theoretical, 'r-', label='理論分布 (N(0,1))', linewidth=2)
plt.title('N(0,1) に従う乱数のヒストグラムと領域', fontsize=14)
plt.xlabel('Z 値', fontsize=12)
plt.ylabel('確率密度', fontsize=12)
plt.legend(fontsize=12)
plt.grid(alpha=0.3)
# グラフ 2
plt.subplot(3, 1, 2)
plt.hist(X_values, bins=np.arange(0, n + 2) - 0.5, density=True, alpha=0.6, color='green', label='X の分布 (シミュレーション)')
plt.plot(x2, binomial_pmf, 'ro-', label='理論分布 (Binomial)', markersize=4)
plt.title('X の分布と理論分布の比較', fontsize=14)
plt.xlabel('X 値', fontsize=12)
plt.ylabel('確率密度', fontsize=12)
plt.legend(fontsize=12)
plt.grid(alpha=0.3)
# グラフ 3
plt.subplot(3, 1, 3)
plt.hist(theta_hat_1_values, bins=10, density=True, alpha=0.6, color='blue', label='$\\hat{\\theta}_1$ の分布 (シミュレーション)')
plt.plot(x3, binomial_pdf, 'r-', label='理論分布 $N(\\theta, V[\\hat{\\theta}_1])$', linewidth=2)
plt.title('$\\hat{\\theta}_1$ の分布と理論分布の比較', fontsize=14)
plt.xlabel('$\\hat{\\theta}_1$ 値', fontsize=12)
plt.ylabel('確率密度', fontsize=12)
plt.legend(fontsize=12)
plt.grid(alpha=0.3)
# グラフを表示
plt.tight_layout() # 全体を整える
plt.show()
この実験によってXが二項分布B(n,θ)に従うことと、が正規分布に従うことが確認できました。
2017 Q3(1)
二項分布の極限をとってポアソン分布を導出しました。
λ=5に固定しnを徐々に増加させて二項分布がポアソン分布に近づくのか確認してみます。
# 2017 Q3(1) 2024.11.2
import numpy as np
import matplotlib.pyplot as plt
# パラメータ
lambda_value = 5 # ポアソン分布の λ
n_values = [10, 50, 100, 500, 1000] # 二項分布の異なる n 値
sample_size = 10000 # サンプル数
# サブプロットの設定
fig, axes = plt.subplots(len(n_values), 1, figsize=(8, len(n_values) * 3))
fig.suptitle("二項分布の極限がポアソン分布に収束")
# 各 n に対するシミュレーションとプロット
for i, n in enumerate(n_values):
p = lambda_value / n # 与えられた λ に対する p の計算
binomial_samples = np.random.binomial(n, p, sample_size) # 二項分布のサンプル
poisson_samples = np.random.poisson(lambda_value, sample_size) # ポアソン分布のサンプル(比較用)
# ヒストグラムのプロット
axes[i].hist(binomial_samples, bins=range(0, 20), alpha=0.5, label=f"二項分布(n={n}, p={p:.3f})", density=True)
axes[i].hist(poisson_samples, bins=range(0, 20), alpha=0.5, label=f"ポアソン分布(λ={lambda_value})", density=True)
axes[i].legend()
axes[i].set_xlabel("x")
axes[i].set_ylabel("確率密度")
axes[i].set_title(f"n = {n}, p = {p:.5f}")
plt.tight_layout(rect=[0, 0, 1, 0.96])
plt.show()
nが大きくなるにつれて二項分布はポアソン分布に近づくのが確認できました。
2018 Q3(5)
二項分布の条件付き確率質量関数のパラメータの最尤推定の問題をやりました。
コード
として、 よりを求めます。まずはfsolveを使用してモーメント法による推定値を求めてみます。
# 2018 Q3(5) 2024.10.17
from scipy.optimize import fsolve
# パラメータ設定
n = 8 # 試行回数
observed_mean = 3.5 # 仮定した標本平均
# モーメント法の方程式
def moment_eq(theta, observed_mean, n):
return observed_mean - (n * theta) / (1 - (1 - theta)**n)
# 数値的に方程式を解く
theta_hat = fsolve(moment_eq, 0.1, args=(observed_mean, n))[0]
# 結果を表示
print(f"θ ハット: {theta_hat}")
θ ハット: 0.4328142334547646
求まりました。
次に反復計算で解いてみます。
# 2018 Q3(5) 2024.10.17
import numpy as np
# パラメータ設定
n = 8 # 試行回数
observed_mean = 3.5 # 仮定された標本平均
max_iterations = 100 # 最大反復回数
tolerance = 1e-6 # 収束判定の閾値
# 初期推定値
theta_hat = observed_mean / n
# 反復計算
for iteration in range(max_iterations):
new_theta_hat = (observed_mean / n) * (1 - (1 - theta_hat) ** n)
# 収束判定
if abs(new_theta_hat - theta_hat) < tolerance:
break
theta_hat = new_theta_hat
# 結果の表示
print(f"θ ハット: {theta_hat}")
θ ハット: 0.432814320144486
同じ値になりました。
次は単純にθを0.01から0.99まで変化させてが1になるθを見つけます。
# 2018 Q3(5) 2024.10.17
import numpy as np
import matplotlib.pyplot as plt
# パラメータ設定
n = 8 # 試行回数
observed_mean = 3.5 # 仮定した標本平均
theta_values = np.linspace(0.01, 0.99, 100) # θを0.01から0.99まで100点で変化させる
# f(θ) の定義
def f_theta(theta, n, observed_mean):
return (n * theta) / (observed_mean * (1 - (1 - theta) ** n))
# f(θ) を計算
f_values = f_theta(theta_values, n, observed_mean)
# f(θ) = 1 となる交点を見つける
intersection_index = np.argmin(np.abs(f_values - 1))
theta_hat = theta_values[intersection_index]
# 交点の θ ハットの値を表示
print(f"θ ハット: {theta_hat}")
# グラフの描画
plt.plot(theta_values, f_values, label='f(θ)', color='blue')
plt.axhline(y=1, color='red', linestyle='--', label='y = 1')
plt.xlabel("θ", fontsize=12)
plt.ylabel("f(θ)", fontsize=12)
plt.title("f(θ) のグラフ (左辺 / 右辺の比)", fontsize=14)
plt.legend()
plt.grid(True)
# グラフの表示
plt.show()
θ ハット: 0.43565656565656563
概ね同じ値になりました。
2018 Q3(4)
二項分布の期待値と条件付き期待値との比が2倍になるパラメータを求めました。
コード
n=8に固定しθを変化させて、η(θ)、E[X]、2E[X]の理論値をプロットしてみます。
# 2018 Q3(4) 2024.10.16
import numpy as np
import matplotlib.pyplot as plt
# パラメータ設定
n = 8 # 試行回数
theta_values = np.linspace(0.01, 0.2, 50) # θを0.01から0.2まで50点で変化
# 条件付き期待値 η(θ) と 条件なしの期待値 E[X] を計算
eta_values = n * theta_values / (1 - (1 - theta_values) ** n) # η(θ)
EX_values = n * theta_values # E[X]
# 二倍のE[X]をプロットするための値
double_EX_values = 2 * EX_values
# グラフの描画
plt.plot(theta_values, eta_values, label='条件付き期待値 η(θ)', color='blue', linestyle='-', marker='o', markersize=4)
plt.plot(theta_values, EX_values, label='条件なし期待値 E[X]', color='green', linestyle='--')
plt.plot(theta_values, double_EX_values, label='2倍の E[X]', color='red', linestyle=':')
# 二倍の関係になるθの位置を求め、プロット
intersection_index = np.argmin(np.abs(eta_values - double_EX_values))
intersection_theta = theta_values[intersection_index]
intersection_eta = eta_values[intersection_index]
plt.scatter(intersection_theta, intersection_eta, color='black', zorder=5, label=f'η(θ) = 2E[X] (θ ≈ {intersection_theta:.3f})')
# キャプションの表示
plt.xlabel("θ", fontsize=12)
plt.ylabel("期待値", fontsize=12)
plt.title("θ に対する η(θ) と E[X] の比較 (理論値)", fontsize=14)
plt.legend()
plt.grid(True)
# グラフの表示
plt.show()
θ=0.083辺りで、η(θ)=2E[X]となることが確認できました。
次に、シミュレーションし同様に描画してみます。
# 2018 Q3(4) 2024.10.16
import numpy as np
import matplotlib.pyplot as plt
# パラメータ設定
n = 8 # 試行回数
theta_values = np.linspace(0.01, 0.2, 50) # θを0.01から0.2まで50点で変化
num_simulations = 100000 # シミュレーション回数
# シミュレーションによる条件付き期待値 η(θ) と 条件なし期待値 E[X] を計算
eta_values = []
EX_values = []
for theta in theta_values:
# 二項分布のサンプリング
binom_samples = np.random.binomial(n, theta, num_simulations)
# 条件付きサンプル (X >= 1)
samples_X_geq_1 = binom_samples[binom_samples >= 1]
# 条件付き期待値 η(θ)
eta = np.mean(samples_X_geq_1)
eta_values.append(eta)
# 条件なし期待値 E[X]
EX = np.mean(binom_samples)
EX_values.append(EX)
# 2倍のE[X]を計算
double_EX_values = 2 * np.array(EX_values)
# グラフの描画
plt.plot(theta_values, eta_values, label='条件付き期待値 η(θ)', color='blue', linestyle='-', marker='o', markersize=4)
plt.plot(theta_values, EX_values, label='条件なし期待値 E[X]', color='green', linestyle='--')
plt.plot(theta_values, double_EX_values, label='2倍の E[X]', color='red', linestyle=':')
# 二倍の関係になるθの位置を求め、プロット
intersection_index = np.argmin(np.abs(np.array(eta_values) - double_EX_values))
intersection_theta = theta_values[intersection_index]
intersection_eta = eta_values[intersection_index]
plt.scatter(intersection_theta, intersection_eta, color='black', zorder=5, label=f'η(θ) = 2E[X] (θ ≈ {intersection_theta:.3f})')
# キャプションの表示
plt.xlabel("θ", fontsize=12)
plt.ylabel("期待値", fontsize=12)
plt.title("θ に対する η(θ) と E[X] の比較 (シミュレーション)", fontsize=14)
plt.legend()
plt.grid(True)
# グラフの表示
plt.show()
シミュレーションも同じ結果になりました。