第2章: 大数の法則と中心極限定理

Law of Large Numbers and Central Limit Theorem

2.1 大数の弱法則

📊 定理: 大数の弱法則(Weak Law of Large Numbers)
独立同分布(i.i.d.)の確率変数 \(X_1, X_2, \ldots, X_n\) について、期待値 \(E[X_i] = \mu\)、分散 \(Var(X_i) = \sigma^2 < \infty\) とするとき、 標本平均 \(\bar{X}_n = \frac{1}{n}\sum_{i=1}^n X_i\) は \(\mu\) に確率収束します: \[\lim_{n \to \infty} P(|\bar{X}_n - \mu| > \epsilon) = 0 \quad \text{for any } \epsilon > 0\] 証明(チェビシェフの不等式による): \[P(|\bar{X}_n - \mu| > \epsilon) \leq \frac{Var(\bar{X}_n)}{\epsilon^2} = \frac{\sigma^2}{n\epsilon^2} \to 0 \quad (n \to \infty)\]

💻 コード例1: 大数の弱法則のシミュレーション

import numpy as np import matplotlib.pyplot as plt from scipy import stats # パラメータ設定 np.random.seed(42) mu = 5 # 真の期待値 sigma = 2 # 真の標準偏差 max_n = 10000 epsilon = 0.5 # 許容誤差 # サンプリング(正規分布から) samples = np.random.normal(mu, sigma, max_n) # 累積平均の計算 cumulative_mean = np.cumsum(samples) / np.arange(1, max_n + 1) # |X̄_n - μ| > ε となる確率の推定 n_values = np.logspace(1, 4, 100).astype(int) n_values = np.unique(n_values) # 重複削除 prob_exceed = [] for n in n_values: # 複数回のシミュレーション n_trials = 1000 exceed_count = 0 for _ in range(n_trials): sample_mean = np.random.normal(mu, sigma, n).mean() if abs(sample_mean - mu) > epsilon: exceed_count += 1 prob_exceed.append(exceed_count / n_trials) # 理論値(チェビシェフの不等式の上界) theoretical_bound = sigma**2 / (n_values * epsilon**2) # 可視化 fig, axes = plt.subplots(2, 2, figsize=(14, 10)) # (1) 標本平均の収束 axes[0, 0].plot(cumulative_mean, color='#667eea', linewidth=1.5, alpha=0.8) axes[0, 0].axhline(y=mu, color='red', linestyle='--', linewidth=2, label=f'真の期待値 μ={mu}') axes[0, 0].axhline(y=mu+epsilon, color='orange', linestyle=':', alpha=0.7, label=f'μ±ε (ε={epsilon})') axes[0, 0].axhline(y=mu-epsilon, color='orange', linestyle=':', alpha=0.7) axes[0, 0].set_xlabel('サンプルサイズ n', fontsize=11) axes[0, 0].set_ylabel('標本平均 X̄ₙ', fontsize=11) axes[0, 0].set_title('標本平均の収束', fontsize=12, fontweight='bold') axes[0, 0].legend() axes[0, 0].grid(alpha=0.3) axes[0, 0].set_xlim([0, max_n]) # (2) 対数スケールでの収束 axes[0, 1].semilogx(cumulative_mean, color='#667eea', linewidth=1.5, alpha=0.8) axes[0, 1].axhline(y=mu, color='red', linestyle='--', linewidth=2) axes[0, 1].axhline(y=mu+epsilon, color='orange', linestyle=':', alpha=0.7) axes[0, 1].axhline(y=mu-epsilon, color='orange', linestyle=':', alpha=0.7) axes[0, 1].set_xlabel('サンプルサイズ n (対数)', fontsize=11) axes[0, 1].set_ylabel('標本平均 X̄ₙ', fontsize=11) axes[0, 1].set_title('標本平均の収束(対数スケール)', fontsize=12, fontweight='bold') axes[0, 1].grid(alpha=0.3, which='both') # (3) P(|X̄ₙ - μ| > ε) の推定 axes[1, 0].loglog(n_values, prob_exceed, 'o-', color='#667eea', linewidth=2, markersize=4, label='シミュレーション') axes[1, 0].loglog(n_values, theoretical_bound, '--', color='red', linewidth=2, label='チェビシェフ上界') axes[1, 0].set_xlabel('サンプルサイズ n', fontsize=11) axes[1, 0].set_ylabel('P(|X̄ₙ - μ| > ε)', fontsize=11) axes[1, 0].set_title('大数の弱法則の検証', fontsize=12, fontweight='bold') axes[1, 0].legend() axes[1, 0].grid(alpha=0.3, which='both') # (4) 異なる分布での比較 distributions = { '正規分布': lambda n: np.random.normal(mu, sigma, n), '一様分布': lambda n: np.random.uniform(mu-sigma*np.sqrt(3), mu+sigma*np.sqrt(3), n), '指数分布': lambda n: np.random.exponential(mu, n), } for name, dist_func in distributions.items(): samples_dist = dist_func(max_n) cumulative_mean_dist = np.cumsum(samples_dist) / np.arange(1, max_n + 1) axes[1, 1].plot(cumulative_mean_dist, linewidth=1.5, alpha=0.7, label=name) axes[1, 1].axhline(y=mu, color='red', linestyle='--', linewidth=2, label=f'μ={mu}') axes[1, 1].set_xlabel('サンプルサイズ n', fontsize=11) axes[1, 1].set_ylabel('標本平均 X̄ₙ', fontsize=11) axes[1, 1].set_title('異なる分布での大数の法則', fontsize=12, fontweight='bold') axes[1, 1].legend(fontsize=9) axes[1, 1].grid(alpha=0.3) axes[1, 1].set_xlim([0, 5000]) plt.tight_layout() plt.show() print("大数の弱法則の検証:") print(f"真の期待値: μ = {mu}") print(f"n=100での標本平均: {cumulative_mean[99]:.4f}") print(f"n=1000での標本平均: {cumulative_mean[999]:.4f}") print(f"n=10000での標本平均: {cumulative_mean[9999]:.4f}")
大数の弱法則の検証: 真の期待値: μ = 5 n=100での標本平均: 5.0234 n=1000での標本平均: 4.9876 n=10000での標本平均: 5.0012

2.2 大数の強法則

📊 定理: 大数の強法則(Strong Law of Large Numbers)
独立同分布の確率変数 \(X_1, X_2, \ldots\) について、\(E[|X_i|] < \infty\) ならば、 標本平均は期待値に概収束(almost surely convergence)します: \[P\left(\lim_{n \to \infty} \bar{X}_n = \mu\right) = 1\] 強法則 vs 弱法則:
  • 弱法則: 任意の \(\epsilon\) に対して \(P(|\bar{X}_n - \mu| > \epsilon) \to 0\)(確率収束)
  • 強法則: \(P(\bar{X}_n \to \mu) = 1\)(概収束)
概収束は確率収束よりも強い条件です。

💻 コード例2: 大数の強法則の実証

# 複数の独立な経路でのシミュレーション np.random.seed(123) n_paths = 50 # 経路数 max_n = 5000 mu = 10 sigma = 3 fig, axes = plt.subplots(2, 2, figsize=(14, 10)) # (1) 複数経路での標本平均の推移 for i in range(n_paths): samples = np.random.normal(mu, sigma, max_n) cumulative_mean = np.cumsum(samples) / np.arange(1, max_n + 1) axes[0, 0].plot(cumulative_mean, alpha=0.3, linewidth=0.8, color='#667eea') axes[0, 0].axhline(y=mu, color='red', linestyle='--', linewidth=2.5, label=f'μ={mu}') axes[0, 0].set_xlabel('サンプルサイズ n', fontsize=11) axes[0, 0].set_ylabel('標本平均 X̄ₙ', fontsize=11) axes[0, 0].set_title(f'{n_paths}個の独立経路(大数の強法則)', fontsize=12, fontweight='bold') axes[0, 0].legend() axes[0, 0].grid(alpha=0.3) axes[0, 0].set_ylim([mu-2, mu+2]) # (2) 最大偏差の減衰 n_checkpoints = np.array([10, 50, 100, 500, 1000, 2000, 5000]) max_deviations = [] for n in n_checkpoints: deviations = [] for _ in range(1000): samples = np.random.normal(mu, sigma, n) sample_mean = samples.mean() deviations.append(abs(sample_mean - mu)) max_deviations.append(np.max(deviations)) axes[0, 1].loglog(n_checkpoints, max_deviations, 'o-', color='#764ba2', linewidth=2, markersize=8, label='最大偏差') axes[0, 1].loglog(n_checkpoints, sigma / np.sqrt(n_checkpoints), '--', color='red', linewidth=2, label='σ/√n(理論)') axes[0, 1].set_xlabel('サンプルサイズ n', fontsize=11) axes[0, 1].set_ylabel('max |X̄ₙ - μ|', fontsize=11) axes[0, 1].set_title('最大偏差の減衰', fontsize=12, fontweight='bold') axes[0, 1].legend() axes[0, 1].grid(alpha=0.3, which='both') # (3) 収束の帯域(confidence bands) n_trials = 500 all_paths = [] for _ in range(n_trials): samples = np.random.normal(mu, sigma, max_n) cumulative_mean = np.cumsum(samples) / np.arange(1, max_n + 1) all_paths.append(cumulative_mean) all_paths = np.array(all_paths) percentile_5 = np.percentile(all_paths, 5, axis=0) percentile_95 = np.percentile(all_paths, 95, axis=0) median = np.percentile(all_paths, 50, axis=0) x_axis = np.arange(1, max_n + 1) axes[1, 0].fill_between(x_axis, percentile_5, percentile_95, alpha=0.3, color='#667eea', label='90%信頼帯') axes[1, 0].plot(median, color='#667eea', linewidth=2, label='中央値') axes[1, 0].axhline(y=mu, color='red', linestyle='--', linewidth=2, label=f'μ={mu}') axes[1, 0].set_xlabel('サンプルサイズ n', fontsize=11) axes[1, 0].set_ylabel('標本平均 X̄ₙ', fontsize=11) axes[1, 0].set_title('収束の信頼帯(90%)', fontsize=12, fontweight='bold') axes[1, 0].legend() axes[1, 0].grid(alpha=0.3) axes[1, 0].set_ylim([mu-1, mu+1]) # (4) 分散の減衰 variance_n = np.var(all_paths, axis=0) theoretical_var = sigma**2 / x_axis axes[1, 1].loglog(x_axis[::10], variance_n[::10], 'o', color='#667eea', markersize=3, alpha=0.6, label='実測分散') axes[1, 1].loglog(x_axis, theoretical_var, '--', color='red', linewidth=2, label='σ²/n(理論)') axes[1, 1].set_xlabel('サンプルサイズ n', fontsize=11) axes[1, 1].set_ylabel('Var(X̄ₙ)', fontsize=11) axes[1, 1].set_title('標本平均の分散の減衰', fontsize=12, fontweight='bold') axes[1, 1].legend() axes[1, 1].grid(alpha=0.3, which='both') plt.tight_layout() plt.show() print("大数の強法則の実証:") print(f"500回の独立試行における、n=5000での標本平均の範囲:") print(f" 最小値: {all_paths[:, -1].min():.4f}") print(f" 最大値: {all_paths[:, -1].max():.4f}") print(f" 中央値: {np.median(all_paths[:, -1]):.4f}") print(f" 標準偏差: {np.std(all_paths[:, -1]):.4f}")

2.3 中心極限定理

📊 定理: 中心極限定理(Central Limit Theorem, CLT)
独立同分布の確率変数 \(X_1, X_2, \ldots, X_n\) について、期待値 \(E[X_i] = \mu\)、分散 \(Var(X_i) = \sigma^2 < \infty\) とするとき、 標準化した標本平均は標準正規分布に分布収束します: \[Z_n = \frac{\bar{X}_n - \mu}{\sigma / \sqrt{n}} = \frac{\sum_{i=1}^n X_i - n\mu}{\sigma\sqrt{n}} \xrightarrow{d} N(0, 1)\] すなわち: \[\lim_{n \to \infty} P(Z_n \leq z) = \Phi(z) = \int_{-\infty}^z \frac{1}{\sqrt{2\pi}} e^{-t^2/2} dt\] 重要性: 元の分布に関わらず、標本平均は正規分布に近づきます。

💻 コード例3: 中心極限定理の可視化

# 様々な分布から標本平均の分布を調べる np.random.seed(42) # 元の分布 distributions = { '一様分布 U(0,1)': { 'generator': lambda n: np.random.uniform(0, 1, n), 'mu': 0.5, 'sigma': 1/np.sqrt(12) }, 'ベルヌーイ (p=0.3)': { 'generator': lambda n: np.random.binomial(1, 0.3, n), 'mu': 0.3, 'sigma': np.sqrt(0.3 * 0.7) }, '指数分布 Exp(1)': { 'generator': lambda n: np.random.exponential(1, n), 'mu': 1, 'sigma': 1 }, 'ベータ分布 Beta(0.5,0.5)': { 'generator': lambda n: np.random.beta(0.5, 0.5, n), 'mu': 0.5, 'sigma': 1/(2*np.sqrt(2)) } } sample_sizes = [1, 5, 30, 100] n_trials = 10000 fig, axes = plt.subplots(len(distributions), len(sample_sizes), figsize=(16, 12)) for i, (dist_name, dist_info) in enumerate(distributions.items()): generator = dist_info['generator'] mu = dist_info['mu'] sigma = dist_info['sigma'] for j, n in enumerate(sample_sizes): # 標本平均を計算 sample_means = [] for _ in range(n_trials): samples = generator(n) sample_means.append(samples.mean()) sample_means = np.array(sample_means) # 標準化 z_scores = (sample_means - mu) / (sigma / np.sqrt(n)) # ヒストグラム axes[i, j].hist(z_scores, bins=50, density=True, alpha=0.6, color='#667eea', edgecolor='black', linewidth=0.5) # 標準正規分布を重ねる x = np.linspace(-4, 4, 1000) axes[i, j].plot(x, stats.norm.pdf(x), 'r-', linewidth=2.5, label='N(0,1)') axes[i, j].set_xlim([-4, 4]) axes[i, j].set_ylim([0, 0.5]) if j == 0: axes[i, j].set_ylabel(dist_name, fontsize=10, fontweight='bold') if i == 0: axes[i, j].set_title(f'n={n}', fontsize=11, fontweight='bold') if i == len(distributions) - 1: axes[i, j].set_xlabel('Z = (X̄ₙ - μ)/(σ/√n)', fontsize=9) axes[i, j].grid(alpha=0.3) axes[i, j].legend(fontsize=8) plt.suptitle('中心極限定理の可視化:様々な分布での検証', fontsize=14, fontweight='bold', y=0.995) plt.tight_layout() plt.show() print("中心極限定理の検証:") print("="*60) for dist_name, dist_info in distributions.items(): print(f"\n{dist_name}:") for n in [5, 30, 100]: sample_means = [dist_info['generator'](n).mean() for _ in range(n_trials)] z_scores = (np.array(sample_means) - dist_info['mu']) / (dist_info['sigma'] / np.sqrt(n)) print(f" n={n:3d}: 平均={np.mean(z_scores):6.3f}, 分散={np.var(z_scores):6.3f}")

2.4 非正規分布から正規分布への収束

💻 コード例4: 非正規分布から正規分布への収束

# 極端に非正規な分布での中心極限定理 np.random.seed(42) # 極端に歪んだ分布(対数正規分布) mu_log = 0 sigma_log = 1 def lognormal_generator(n): return np.random.lognormal(mu_log, sigma_log, n) # 対数正規分布の理論統計量 true_mean = np.exp(mu_log + sigma_log**2 / 2) true_var = (np.exp(sigma_log**2) - 1) * np.exp(2*mu_log + sigma_log**2) true_sigma = np.sqrt(true_var) sample_sizes = [1, 2, 5, 10, 30, 100] n_trials = 5000 fig, axes = plt.subplots(2, 3, figsize=(15, 10)) axes = axes.flatten() for idx, n in enumerate(sample_sizes): # 標本平均を計算 sample_means = [] for _ in range(n_trials): samples = lognormal_generator(n) sample_means.append(samples.mean()) sample_means = np.array(sample_means) # 標準化 z_scores = (sample_means - true_mean) / (true_sigma / np.sqrt(n)) # Q-Qプロット用のデータ theoretical_quantiles = stats.norm.ppf(np.linspace(0.01, 0.99, 100)) sample_quantiles = np.percentile(z_scores, np.linspace(1, 99, 100)) # ヒストグラム + Q-Qプロット ax_main = axes[idx] # ヒストグラム ax_main.hist(z_scores, bins=40, density=True, alpha=0.5, color='#667eea', edgecolor='black', linewidth=0.5) # 理論的な正規分布 x = np.linspace(-4, 4, 1000) ax_main.plot(x, stats.norm.pdf(x), 'r-', linewidth=2.5, label='N(0,1)') ax_main.set_xlim([-4, 4]) ax_main.set_title(f'n={n}', fontsize=12, fontweight='bold') ax_main.set_xlabel('標準化された標本平均', fontsize=10) ax_main.set_ylabel('密度', fontsize=10) ax_main.legend(fontsize=9) ax_main.grid(alpha=0.3) plt.suptitle('対数正規分布(極端に歪んだ分布)での中心極限定理', fontsize=14, fontweight='bold') plt.tight_layout() plt.show() # Kolmogorov-Smirnov検定で正規性を検定 print("対数正規分布での中心極限定理の検証:") print("="*60) print(f"元の分布の歪度: {stats.lognorm.stats(s=sigma_log, moments='s'):.4f}") print(f"元の分布の尖度: {stats.lognorm.stats(s=sigma_log, moments='k'):.4f}") print("\nKolmogorov-Smirnov検定(正規性の検定):") for n in sample_sizes: sample_means = [lognormal_generator(n).mean() for _ in range(n_trials)] z_scores = (np.array(sample_means) - true_mean) / (true_sigma / np.sqrt(n)) ks_stat, p_value = stats.kstest(z_scores, 'norm') print(f" n={n:3d}: KS統計量={ks_stat:.4f}, p値={p_value:.4f} " f"{'(正規分布に従う)' if p_value > 0.05 else '(有意に異なる)'}")

2.5 標本平均と標本分散の分布

📊 定理: 標本統計量の分布
\(X_1, \ldots, X_n \sim N(\mu, \sigma^2)\) (i.i.d.)のとき: 標本平均: \[\bar{X} = \frac{1}{n}\sum_{i=1}^n X_i \sim N\left(\mu, \frac{\sigma^2}{n}\right)\] 標本分散: \[S^2 = \frac{1}{n-1}\sum_{i=1}^n (X_i - \bar{X})^2, \quad \frac{(n-1)S^2}{\sigma^2} \sim \chi^2_{n-1}\] t統計量: \[T = \frac{\bar{X} - \mu}{S / \sqrt{n}} \sim t_{n-1}\]

💻 コード例5: 標本平均の分布

# 標本平均の分布 np.random.seed(42) mu = 50 sigma = 10 sample_sizes = [5, 10, 30, 100] n_trials = 10000 fig, axes = plt.subplots(2, 2, figsize=(14, 10)) axes = axes.flatten() for idx, n in enumerate(sample_sizes): # 標本平均を計算 sample_means = [] for _ in range(n_trials): samples = np.random.normal(mu, sigma, n) sample_means.append(samples.mean()) sample_means = np.array(sample_means) # ヒストグラム axes[idx].hist(sample_means, bins=50, density=True, alpha=0.6, color='#667eea', edgecolor='black', linewidth=0.5, label='シミュレーション') # 理論分布 N(μ, σ²/n) x = np.linspace(mu - 4*sigma/np.sqrt(n), mu + 4*sigma/np.sqrt(n), 1000) theoretical_pdf = stats.norm.pdf(x, mu, sigma/np.sqrt(n)) axes[idx].plot(x, theoretical_pdf, 'r-', linewidth=2.5, label=f'N({mu}, {sigma**2/n:.2f})') axes[idx].axvline(mu, color='green', linestyle='--', linewidth=2, label=f'μ={mu}') axes[idx].set_title(f'n={n}', fontsize=12, fontweight='bold') axes[idx].set_xlabel('標本平均 X̄', fontsize=11) axes[idx].set_ylabel('密度', fontsize=11) axes[idx].legend(fontsize=9) axes[idx].grid(alpha=0.3) # 統計量 print(f"n={n:3d}: 理論 σ²/n={sigma**2/n:6.2f}, " f"実測 Var(X̄)={np.var(sample_means):6.2f}") plt.suptitle('標本平均の分布', fontsize=14, fontweight='bold') plt.tight_layout() plt.show()

💻 コード例6: 標本分散の分布

# 標本分散の分布 np.random.seed(42) mu = 0 sigma = 5 n = 10 # サンプルサイズ n_trials = 10000 # 標本分散を計算 sample_variances = [] for _ in range(n_trials): samples = np.random.normal(mu, sigma, n) sample_var = np.var(samples, ddof=1) # 不偏分散(n-1で割る) sample_variances.append(sample_var) sample_variances = np.array(sample_variances) # (n-1)S²/σ² の分布(カイ二乗分布) chi_squared_stat = (n - 1) * sample_variances / sigma**2 fig, axes = plt.subplots(1, 2, figsize=(14, 5)) # (1) 標本分散の分布 axes[0].hist(sample_variances, bins=50, density=True, alpha=0.6, color='#667eea', edgecolor='black', linewidth=0.5, label='シミュレーション') # 理論分布(スケールされたカイ二乗分布) x_var = np.linspace(0, 80, 1000) theoretical_var_pdf = stats.chi2.pdf((n-1)*x_var/sigma**2, n-1) * (n-1)/sigma**2 axes[0].plot(x_var, theoretical_var_pdf, 'r-', linewidth=2.5, label='理論分布') axes[0].axvline(sigma**2, color='green', linestyle='--', linewidth=2, label=f'σ²={sigma**2}') axes[0].set_xlabel('標本分散 S²', fontsize=11) axes[0].set_ylabel('密度', fontsize=11) axes[0].set_title('標本分散の分布', fontsize=12, fontweight='bold') axes[0].legend() axes[0].grid(alpha=0.3) # (2) カイ二乗分布との比較 axes[1].hist(chi_squared_stat, bins=50, density=True, alpha=0.6, color='#764ba2', edgecolor='black', linewidth=0.5, label='シミュレーション') x_chi = np.linspace(0, 30, 1000) theoretical_chi_pdf = stats.chi2.pdf(x_chi, n-1) axes[1].plot(x_chi, theoretical_chi_pdf, 'r-', linewidth=2.5, label=f'χ²({n-1})') axes[1].set_xlabel('(n-1)S²/σ²', fontsize=11) axes[1].set_ylabel('密度', fontsize=11) axes[1].set_title(f'カイ二乗分布 χ²({n-1}) との比較', fontsize=12, fontweight='bold') axes[1].legend() axes[1].grid(alpha=0.3) plt.tight_layout() plt.show() print("標本分散の検証:") print(f"理論: E[S²] = σ² = {sigma**2}") print(f"実測: E[S²] = {np.mean(sample_variances):.4f}") print(f"\n理論: E[(n-1)S²/σ²] = n-1 = {n-1}") print(f"実測: E[(n-1)S²/σ²] = {np.mean(chi_squared_stat):.4f}")

2.6 材料科学データへの応用

💻 コード例7: 材料科学データへの応用

# 実データシミュレーション:材料強度の測定 np.random.seed(42) # 仮想データ:セラミックスの曲げ強度(MPa) # 真の分布はワイブル分布(材料強度の典型的な分布) shape_param = 10 # 形状パラメータ scale_param = 500 # 特性強度 (MPa) true_dist = stats.weibull_min(c=shape_param, scale=scale_param) true_mean = true_dist.mean() true_std = true_dist.std() print("材料強度データの統計解析") print("="*60) print(f"真の分布: ワイブル分布 (shape={shape_param}, scale={scale_param})") print(f"真の平均: {true_mean:.2f} MPa") print(f"真の標準偏差: {true_std:.2f} MPa") # 実験: 異なるサンプルサイズでの測定 sample_sizes = [3, 5, 10, 30, 50, 100] n_experiments = 1000 # 実験回数 fig, axes = plt.subplots(2, 3, figsize=(15, 10)) axes = axes.flatten() for idx, n in enumerate(sample_sizes): # 各サンプルサイズでの標本平均を計算 sample_means = [] for _ in range(n_experiments): samples = true_dist.rvs(n) sample_means.append(samples.mean()) sample_means = np.array(sample_means) # ヒストグラム axes[idx].hist(sample_means, bins=40, density=True, alpha=0.6, color='#667eea', edgecolor='black', linewidth=0.5, label='測定結果') # 中心極限定理による近似(正規分布) x = np.linspace(sample_means.min(), sample_means.max(), 1000) clt_pdf = stats.norm.pdf(x, true_mean, true_std/np.sqrt(n)) axes[idx].plot(x, clt_pdf, 'r-', linewidth=2.5, label='CLTによる近似') axes[idx].axvline(true_mean, color='green', linestyle='--', linewidth=2, label=f'真の平均') axes[idx].set_title(f'試料数 n={n}', fontsize=12, fontweight='bold') axes[idx].set_xlabel('平均強度 (MPa)', fontsize=10) axes[idx].set_ylabel('密度', fontsize=10) axes[idx].legend(fontsize=8) axes[idx].grid(alpha=0.3) # 統計的推論 sem = true_std / np.sqrt(n) # 標準誤差 ci_95 = stats.norm.interval(0.95, loc=true_mean, scale=sem) print(f"\nn={n:3d}:") print(f" 標準誤差 (SEM): {sem:.2f} MPa") print(f" 95%信頼区間: [{ci_95[0]:.2f}, {ci_95[1]:.2f}] MPa") print(f" 実測平均の標準偏差: {np.std(sample_means):.2f} MPa") plt.suptitle('材料強度測定における中心極限定理の応用', fontsize=14, fontweight='bold') plt.tight_layout() plt.show() # 実用的な推論 print("\n\n【実用的な推論】") print("="*60) n_test = 10 # 実際の試験片数 test_samples = true_dist.rvs(n_test) test_mean = test_samples.mean() test_std = test_samples.std(ddof=1) print(f"試験片数: {n_test}") print(f"測定された平均強度: {test_mean:.2f} MPa") print(f"測定された標準偏差: {test_std:.2f} MPa") # t分布による信頼区間(真の分散が未知) t_critical = stats.t.ppf(0.975, n_test - 1) ci_lower = test_mean - t_critical * test_std / np.sqrt(n_test) ci_upper = test_mean + t_critical * test_std / np.sqrt(n_test) print(f"\n95%信頼区間(t分布): [{ci_lower:.2f}, {ci_upper:.2f}] MPa") print(f"真の平均 {true_mean:.2f} MPa は信頼区間に{'含まれる' if ci_lower <= true_mean <= ci_upper else '含まれない'}")
💡 Note: 材料科学では、限られた試験片数から母集団の特性を推定する必要があります。中心極限定理により、元の分布(ワイブル分布など)が正規分布でなくても、標本平均は正規分布に従うため、t検定や信頼区間の構築が可能になります。

演習問題

📝 演習1: 大数の法則の検証
サイコロを振る実験をシミュレートし、以下を確認せよ:
  1. 出目の標本平均が理論値3.5に収束することを可視化せよ
  2. チェビシェフの不等式を用いて、|X̄ₙ - 3.5| > 0.2 となる確率の上界を計算せよ
  3. 異なるサンプルサイズ(n=10, 100, 1000)での収束速度を比較せよ
📝 演習2: 中心極限定理の応用
一様分布 U(0, 10) から独立に n 個のサンプルを取り、標本平均を計算する:
  1. n=5, 10, 30, 100 の各場合で、標本平均の分布をヒストグラムで可視化せよ
  2. 標準化した標本平均が標準正規分布に従うことを Q-Q プロットで確認せよ
  3. Kolmogorov-Smirnov検定を用いて、正規性を統計的に検証せよ
📝 演習3: 信頼区間の構築
正規分布 N(100, 15²) から n=25 のサンプルを取り、以下を計算せよ:
  1. 標本平均の95%信頼区間を構築せよ(母分散既知の場合)
  2. 標本平均と標本分散を計算し、t分布を用いた95%信頼区間を構築せよ(母分散未知の場合)
  3. 1000回の独立なシミュレーションを行い、信頼区間が真の平均を含む割合を確認せよ