昔に本当か?と思ってやった内容です。
当時衝撃を受けたことをふと思い出したので記事にしてみました。
中心極限定理とは
中心極限定理とは、期待値 $\mu$、分散 $\sigma^2$ の任意の確率分布に従う母集団から$n$個の要素を無作為復元抽出したときの標本平均 $\overline{X_n}$の分布は、$n$が十分大きい時には正規分布$N(\mu,\frac{\sigma^2}{n})$へ近づいていく定理。
簡単に言うと、どんな母集団でもランダムサンプリングした値の平均は正規分布になるというものです。
これを聞いたとき本当にどんな母集団でも成り立つのか?と思った時がありました。
実験1. サイコロ(一様分布)
まずは簡単な分布で見てみます。
import random
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
# 分布
def sample():
return random.choice([1, 2, 3, 4, 5, 6])
# 分布のグラフを可視化
x = []
for _ in range(1000):
x.append(sample())
sns.histplot(x, kde=True)
plt.show()
print("平均", np.mean(x))
print("分散", np.var(x))
print("中心極限定理の予想分散", np.var(x) / 100)
# 中心極限定理
x = []
for _ in range(1000):
# ランダムサンプリングした値の平均
n = []
for _ in range(100):
n.append(sample())
x.append(np.mean(n))
sns.histplot(x, kde=True)
plt.show()
print("平均", np.mean(x))
print("分散", np.var(x))
平均 3.458
分散 2.842236
中心極限定理の予想分散 0.02842236
平均 3.49769
分散 0.0301697639
見事に正規分布に近い形になっていますね。
以降は同じコードで sample 関数のみを変えていきます。
実験2. 正規分布+一様分布
2つの異なる分布を混ぜてみます。
def sample():
if random.random() < 0.5:
return np.random.normal(-5, 0.5, 1)[0]
else:
return np.random.randint(2, 10)
平均 1.2720335834082035
分散 20.963113365580693
中心極限定理の予想分散 0.20963113365580693
平均 1.2417630631941023
分散 0.19920439968876935
かなり変な分布ですが、中心極限定理後は正規分布になっていますね。
実験3. 適当な分布
10%で1、30%で3、60%で7の値を取ります。
離散値のみの分布です。
def sample():
r = random.random()
if r < 0.1:
return 1
elif r < 0.4:
return 3
return 7
平均 5.084
分散 5.264944000000001
中心極限定理の予想分散 0.052649440000000006
平均 5.206840000000001
分散 0.05042041440000001
実験4. 適当な分布2
正規分布ですが、-0.5~0は-10、0~1なら5を取る分布です。
def sample():
n = np.random.normal(0, 2.0, 1)[0]
if -0.5 < n < 0:
return -10
if 0 < n < 1:
return 5
return n
平均 0.054707802397646575
分散 16.841994983744684
中心極限定理の予想分散 0.16841994983744685
平均 -0.10518644858242933
分散 0.17155630468517633
かなり変な分布ですが中心極限定理後は正規分布っぽくなっていますね。
中心極限定理が成り立たない場合(コーシー分布)
どんな母集団でもといっていますが成り立たない場合があり、それは分布が平均と分散を持たない場合らしいです。
例えばコーシー分布は平均や分散を持たないので成り立たないらしいです。
rng = np.random.default_rng()
def sample():
return rng.standard_cauchy(1)[0]
図は見やすいように-25~25の範囲に限定しています。
また少し時間がかかったのでサンプリング回数を1000×100回から100×100回に減らしています。
sns.histplot(x, kde=True)
plt.xlim(-25, 25)
plt.show()
平均 0.7673117788880744
分散 526.8258258406837
中心極限定理の予想分散 5.268258258406837
平均 -0.1085017568639298
分散 39.99723980324434
見た目は正規分布っぽいですが平均と分散の数字は全然違いますね。
確かに中心極限定理が成り立っていなそうです。