コインを100回投げたら必ず50回表が出る?
前回、ランダムな点を大量にばらまいて確率から面積を推定した。
たくさんの試行を重ねることで全体のバランスが整うため、$\pi$の値に近づくことをシミュレーションで確認することができた。今回は「コイン投げ」から正規分布と呼ばれる分布を見つけたい。
1回だけコインを投げたら表から裏かは運しだいだが、100回投げたら100回表が出る人は少ない。大体の人は50回前後に収まりそうである。 そこで登場するのが二項分布と正規分布である。
ベルヌーイ試行と二項分布
「コインを一回投げる」という行為は表か裏の二択であり、ベルヌーイ試行と呼ばれている。
この試行を何度も繰り返すと「何回表がでたか」という結果に分布が表れてくる。
反復試行の確率
確率$p$で試行するような志向を独立に$n$回反復して行ったときに、$n$回中$k$回成功する確率は
{}_n C_k p^k (1-p)^{n-k}
となる。詳細はこちらのリンクから確認する。
ではこれを表の出る確率が$\frac{1}{2}$のコインを100回投げたときの確率で考えてみると、
$50$回表が出る確率は
{}_{100} C_{50} \cdot \frac{1}{2^{100}} \simeq 0.0795
となる。50回ぴったりの確率が$8$%ほど。
また、平均と分散は$n$と$p$を用いてそれぞれ、$np$, $\sqrt{np(1-p)}$で求めることができるので、この二項分布の真の平均は$np = 100 \times 1/2=50$,分散は $\sqrt{100\times 1/2 \times 1/2}=5$となる。このとき、$[45, 50]$に収まる確率は約$68.27$%と言われている。詳細は、1σ、2σ、3σの意味と正規分布の場合の確率が参考になる。
$n$の値を大きくすると正規分布に近づくことが知られている。$p=0.5$で固定し$n$の値を変化させたシミュレーションを下記に示す。
$n=100$あたりで概形が正規分布に似ているので、次は実際に近似した正規分布と重ね合わせてみる。
Pythonでデータを作成する
次は実際にPythonでシミュレーションしてその山の形がどのように現れるかを確認していく。
一人当たりコインを投げる回数$100$回、表が出る確率を$0.5$、シミュレーション回数は$500000$回とする。
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
# パラメータ
n = 100 # コインを投げる回数
p = 0.5 # 表が出る確率
sample_size = 500000 # 実験の回数
# シミュレーション
binomial_samples = np.random.binomial(n, p, sample_size)
# 正規分布による近似
mu = n * p
sigma = np.sqrt(n * p * (1 - p))
normal_samples = np.random.normal(mu, sigma, sample_size)
min_val = min(binomial_samples.min(), int(normal_samples.min()))
max_val = max(binomial_samples.max(), int(normal_samples.max()))
bin_range = np.arange(min_val, max_val + 1)
# 出現回数をカウントする
binom_freq = pd.Series(binomial_samples).value_counts().reindex(bin_range, fill_value=0).sort_index()
norm_freq = pd.Series(np.round(normal_samples)).value_counts().reindex(bin_range, fill_value=0).sort_index()
binom_prob = binom_freq / sample_size
norm_prob = norm_freq / sample_size
df = pd.DataFrame({
'value': bin_range,
'binomial_prob': binom_prob.values,
'normal_approx_prob': norm_prob.values
})
# CSV出力
df.to_csv('coin_toss_binomial_vs_normal.csv', index=False)
print("CSVファイルを出力しました:coin_toss_binomial_vs_normal.csv")
plt.figure(figsize=(12, 6))
plt.plot(df['value'], df['binomial_prob'], label='Binomial Distribution', color='blue', marker='o')
plt.plot(df['value'], df['normal_approx_prob'], label='Normal Approximation', color='red', linestyle='--')
plt.title('コインを100回投げたときの「表の回数」の分布')
plt.xlabel('表が出た回数')
plt.ylabel('確率')
plt.legend()
plt.grid(True)
plt.tight_layout()
plt.show()
実行結果
実行結果から、正規分布とほぼ一致することが分かった。
今回はシミュレーション回数を5,000,000回としてシミュレーションしたが、実世界で5,000,000人にコイン投げを100回させることはない。そこで、人数が多ければ多いほど、正規分布に近づいていくことをTableauで可視化する。
作成したVizでシミュレーション
先ほどのPythonのコードには前回同様.csv
ファイルの出力のcodeが含まれている。
value
: コインを100回投げたうち、表が出た回数(0~100の範囲)を整数で表したもの。
binomial_prob
: 二項分布によるシミュレーション結果に基づく確率。500,000回のうち、その回数の表が出た割合のこと。
normal_approx_prob
: 正規分布による近似のシミュレーション結果(連続値を四捨五入)に基づく確率。500,000回から得られた確率。
500,000人のときには、正規分布の形をしており、40096人が50回表が出ていることがわかる。これは全体の$8$%ほどであり、先ほどの理論値と一致する。
ではこれを現実的な値、10人でおこなったらどうなるか?
45回表が出る人が3人で最も多く、50回表が出る人が2人。45から55回の間に収まる確率はかなり高そうである。
人数を300人に変えてみたらどうか?
やはり45から55回に集まって、35回や63回などの範囲外の値も増えてきた。
実際、3$\sigma$の範囲が$[35, 65]$なので、ほぼこの範囲内に入っていることがわかる。
作成したVizはこちらから。
コイントスのシミュレーション
Bitcoinの対数収益率
一見ランダムに見えるような値も数をこなせば真の分布が見えてくることがシミュレーションによってわかった。最後に実データを用いて考えていく。
図は、Bitcoinの価格推移である。中央銀行などの単一な管理機関を持たない分散型のデジタル通過であるBitcoinは2009年に使用が開始されて現在まで少しずつ価格を伸ばしてきた。図は2023年からの推移であるが、日に日に価格が高くなっていることがわかる。
金融商品の分析に、対数収益率というものがある
r_t = \ln\left(\frac{P_t}{P_{t-1}}\right)
ここで,$r_t$ は時点 $t$の対数収益率, $P_t$ は時点$t$の資産価格,$P_{t-1}$ は時点 $t-1$ の資産価格 $\ln$ は自然対数を表す。
対数収益率を標本平均と分散で正規化して、$\pm 3\sigma$内を調べると数のようになる。
3$\sigma$外は$2.03$%となり、価格が変動しやすい金融商品であることがわかる。
作成したVizはこちらから。
Bitcoin chart
さいごに
100回コインを投げて表が出る回数、そしてBitcoinの価格変動――一見まったく別の話だが、統計的にみると共通する法則が見えてくる。
これからも「身近なデータ × 数学 × 可視化」で、わかりやすく伝えられるようにDATASaberに取り組んでいきたい。