中心極限定理は「母集団の確率分布によらず、標本の大きさ n が十分に大きければ、和や標本平均の分布は正規分布に従う」という定理です。
数学的に証明されており、推測統計学の基礎になっている大定理ですが、本当にどんな分布でも …(中略)… 正規分布になるのか疑問に感じたことはないでしょうか?
どのような母集団でも本当に中心極限定理は成立するのか?Python スクリプトで検証してみました。
ソースコードのダウンロード
この記事で紹介するソースコードは Github よりダウンロードできます。Python3、numpy、matplotlib をインストール後、是非お手元のパソコンで試してみてください。
中心極限定理とは?
冒頭のように中心極限定理とは「母集団の確率分布によらず、標本の大きさ n が十分に大きければ、和や標本平均の分布は正規分布に従う」という定理です。
中心極限定理は平均だけでなく和についても成り立ちますが、ここでは簡単のため平均に限定します。
少しだけ噛み砕くと「もとの分布がどんな分布であっても、十分な数のサンプルを取り出して平均をとる、という試行を繰り返せば、その標本平均たちの分布は正規分布になる」というのです。
さらには、サンプル数を n、母集団の平均(母平均)を µ、分散(母分散)を σ2 とすると、N(µ, σ2/n) という正規分布になることが知られています。つまり、標本平均の分布の平均は、母平均に限りなく一致することを意味します。
極めて例外的なケースですが、中心極限定理が成立しない分布もあります。詳しくはWikipedia 中心極限定理を参照ください。
Python で中心極限定理を検証
「母集団がどんな分布であっても」というのが中心極限定理の最も「胡散臭い」ところです。
そこで、母集団を少しの規則性も許さない乱数の集まりで形成することにします。乱数の集まりからでも、正規分布に収束する結果が得られたら…認めざるを得ませんね。
要件
- まったく規則性のない乱数で母集団を形成
- サンプルを n 個抽出して平均を算出、この試行を繰り返して分布を記録
- 得られた分布の平均が母平均 µ とおおむね一致するかを確認
- 得られた分布の分散が母分散を n で割った値 σ2/n とおおむね一致するかを確認
ソースコード
Python3、numpy、matplotlib により実装してみました。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 |
""" ======================================= Experiment on the central limit theorem ======================================= Requirements Python3, numpy, matplotlib Document https://it-engineer-lab.com/archives/1237 """ import numpy as np import matplotlib.mlab as mlab import matplotlib.pyplot as plt n = 100 # 取り出すサンプルサイズ(適当に設定。ただし、十分大きい値であることが定理の前提。) num_trials = 10000 # 試行回数。(適当に設定。コンピュータなので1万回も余裕。) num_bins = 50 # ヒストグラムのビン数(適当に設定) # 母集団 # 0〜999の中からランダムで300個の整数を取得 population = np.random.randint(0, 1000, size=300) # (適当に設定) # 母集団からn個のサンプルをランダム抽出し、その平均値を取得。この試行を num_trials 回繰り返す。各回の平均値をリスト内包表記でセット。 # mean_list の中身 [1回目の平均値, 2回目の平均値, 3回目の平均値, ... num_trials回目の平均値] mean_list = [np.random.choice(population, n).mean() for i in range(num_trials)] mean_array = np.array(mean_list) # list to np.array def _round(num): """ 出力時に見やすいよう数値を丸める :param num: 数値 :return: 丸めた数値 """ return round(num, 2) # レポートの出力 print('母平均:', _round(population.mean())) print('母分散:', _round(population.var())) print('母分散/n:', _round(population.var() / n)) print('標本平均の分布:', 'N({0}, {1})'.format(_round(mean_array.mean()), _round(mean_array.var()))) # 以下、図の出力(上下2分割) plt.figure(figsize=(6, 8)) ax1 = plt.subplot(2, 1, 1) ax2 = plt.subplot(2, 1, 2) # 母集団を可視化(ヒストグラム) ax1.hist(population, bins=num_bins, alpha=0.8, normed=True) ax1.set_title('Histogram of the Population') # 各試行の平均値を可視化(ヒストグラムと確率密度を表示) # https://matplotlib.org/examples/statistics/histogram_demo_features.html _, bins, patches = ax2.hist(mean_array, num_bins, alpha=0.8, normed=True) y = mlab.normpdf(bins, mean_array.mean(), mean_array.std()) ax2.plot(bins, y) ax2.set_title('Distribution of sample mean') plt.tight_layout() plt.subplots_adjust(hspace=0.3) plt.show() ''' 実行結果(一例) 母平均: 489.45 母分散: 86307.64 母分散/n: 863.08 標本平均の分布: N(489.61, 865.81) 備考 スクリプト実行時に乱数で母集団を作るので、 結果の数値は実行する度に変わります。 ''' |
検証結果
上図は母集団の分布、下図は標本平均の分布です。
規則性のない母集団(上図)からも、悔しいほどに見事な正規分布(下図)が描かれました。
さらに数値の結果は
母平均: 489.45
母分散: 86307.64
母分散/n: 863.08
標本平均の分布: N(489.61, 865.81)
となりました。
得られた分布の平均 489.61 と母平均 489.45 はほぼ一致。
得られた分布の分散 865.81 も母分散/n 863.08 とおおむね一致しています。
スクリプト実行時に乱数を発生させて母集団を作るので、結果の図や数値は実行する度に変わりますが、お手元のパソコンで実行すると、中心極限定理が成立することを実際に確認できるかと思います。
結論
母集団がまったく規則性のない乱数から形成されていても、中心極限定理が成立することを検証・体感できました。
この記事で紹介するソースコードは Github よりダウンロードできます。Python3、numpy、matplotlib をインストール後、是非お手元のパソコンで試してみてください。
コメントを残す