【統計】Pythonで二項分布を理解する

確率分布の1つに二項分布があります。今回は二項分布がどんなものなのかということを、Pythonでグラフを描いて、実際の分布を確認しながら見ていこうと思います。

二項分布とは

ベルヌーイ試行

「成功か失敗か」「表か裏か」のように、2種類の結果しか得られないような試行をベルヌーイ試行と呼びます。ベルヌーイ試行では2つのうち一方の結果を「成功」とみなし、確率変数Xがとる値を”1″、もう一方を「失敗」とみなし、確率変数Xがとる値を”0″とみなします。成功確率p(0<p<1)とすると、それぞれの確率は以下のようになります。

P(X=1)=p
P(X=0)=1-p

このとき、各試行は独立であることが前提です。独立であるとは、たとえばコインを連続で投げたとき、2回目に投げる結果は1回目の結果に影響されないことを意味します。それぞれの試行は他のどの志向の影響も受けない場合を独立であると言います。

何回もコインを投げまくっているうちにコインが変形して、裏しか出なくなるみたいな試行はそれ以前の試行の影響を受けているので、独立であるとは言えません。

二項分布

このベルヌーイ試行をn回行ったとき、成功回数Xが従う確率分布のことを二項分布と言います。n回のベルヌーイ試行を行うときにk回成功する確率(X=kとなる確率)は次式のようになります。

二項分布

コインを10回投げて表が6回出る確率をを求めてみます。コインを投げて表が出る確率はp=0.5なので、以下のような計算になります。

P(X=6)=10C6×0.56×(1-0.5)10-6=0.205

Pythonで確認してみる

コインをn回投げて表が出る回数の確率

二項分布のグラフをPythonで書いて確認してみましょう。まずは必要ライブラリの読込と、二項分布の確率関数を定義します。

import matplotlib.pyplot as plt
import math
import numpy as np

#二項分布の確率関数
def binomial(x, n, p):
    ret = (math.factorial(n) / (math.factorial(x) * math.factorial(n-x))) * np.power(p, x) * np.power(1-p, n-x)
    return ret

コインを10回投げて表が出る回数の確率をグラフにしてみます。

fig, ax = plt.subplots(facecolor="w")
n = 10  #試行回数
p = 0.5 #成功確率

#グラフ用
fig_y = range(10)
fig_y = []

for i in range(10):
    x = i
    result = binomial(x, n, p)
    fig_y.append(result)

#点と線両方を描画
ax.plot(fig_x,fig_y)
ax.scatter(fig_x,fig_y)
#軸タイトル
ax.set_xlabel("コインを10回投げて表が出る回数(回)", fontfamily='Meiryo')
ax.set_ylabel("確率", fontfamily='Meiryo')
コインを10回投げて表が出る回数の確率

先ほど二項分布の確率関数を定義しましたが、scipyのbinom()を使えば、同じ結果が得られます。

## 別例
fig, ax = plt.subplots(facecolor="w")

n = 10  #試行回数
p = 0.5 #成功確率
x = range(n)    #x軸
f = binom(n, p) #確率分布
y = f.pmf(x)    #y軸

#点と線両方を描画
ax.plot(x,y)
ax.scatter(x,y)
#軸タイトル
ax.set_xlabel("コインを10回投げて表が出る回数(回)", fontfamily='Meiryo')
ax.set_ylabel("確率", fontfamily='Meiryo')
コインを10回投げて表が出る回数の確率

グラフから、表が5回出る確率が最も高いことがわかります。

試行回数が増えていった場合

次に、試行回数を増やしていった場合の二項分布のグラフを見ていきます。先ほどはコインを10回投げましたが、20回、50回..と試行回数を増やしていったとき、コインの表が出る回数の確率はどのように変化するのでしょうか。

プログラムは以下のようになります。

#試行回数を変えたときの分布
samples = [10, 20, 50, 100]

fig, ax = plt.subplots(facecolor="w")

for i in range(4):
    n = samples[i] #試行回数
    p = 0.5 #成功確率
    x = range(n)    #x軸
    f = binom(n, p) #確率分布
    y = f.pmf(x)    #y軸
    
    ax.plot(x,y, label="n={} p={}".format(n,p))
    
ax.legend()
ax.set_xlabel("成功回数(回)", fontfamily='Meiryo')
ax.set_ylabel("確率", fontfamily='Meiryo')
plt.show()
試行回数を変えたときの分布

試行回数が多くなるほど、分布の山は右側にスライドしていることがわかります。トライする数が増えれば成功数も増えるので、直感的に腑に落ちる結果だと思います。また、試行回数が多くなるほどグラフの山が小さくなり、成功回数の分布が広がっていくこともわかります。

確率が増えていった場合

今度は試行回数が同じ状況で成功確率(コインの表が出る確率)が大きくなっていったときの変化を見てみます。例では試行回数を200回に固定し、成功確率を上げていきます。

#成功確率を変えたときの分布
probability = [0.1, 0.2, 0.3, 0.5, 0.8]

fig, ax = plt.subplots(facecolor="w")

for i in range(5):
    n = 200 #試行回数
    p = probability[i] #成功確率
    x = range(n)    #x軸
    f = binom(n, p) #確率分布
    y = f.pmf(x)    #y軸
    
    ax.plot(x,y, label="n={} p={}".format(n,p))
    
ax.legend()
ax.set_xlabel("成功回数(回)", fontfamily='Meiryo')
ax.set_ylabel("確率", fontfamily='Meiryo')
plt.show()
成功確率を変えたときの分布

成功確率が大きくなるほど、グラフの山が右側にスライドしていることがわかります。まあこれも当然の結果だと思います。

Pythonでデータサイエンスするなら

Pythonでデータサイエンスをするなら、以下の書籍がおすすめです。Pandas、matplotlib、Numpy、scikit-learnといったデータサイエンスに必要なライブラリを、体系立てて一通り学ぶことができます。

ややお値段高めですが、これ1冊で十分という内容・ボリュームなので、損はしないと思います^^

まとめ

二項分布についてPythonを使いながら視覚的にまとめました。二項分布は基本的な確率分布として広く知られているので、押さえておきたいところです。

二項分布を用いた検定については以下をご覧ください。

ではでは👋