はじめに
このエントリは、CodeIQの池澤あやかとプログラミングで学ぼう!機械学習のための数学講座【確率分布編】の後半部分の、サイコロの確率分布の記事中のコードが理解できなかったので、自分の理解できる範囲でコードを作った際の備忘です。
pythonは初心者のため、書き方が変な部分があるかもしれません。
環境
Python 2.7.10
サイコロの確率分布の公式の理解
公式
課題
Q. サイコロを5回投げて出る目の回数の確率分布を求めてください。確率分布は確率を列挙したものです。
サイコロの確率分布の公式は上記の式です。
公式の解説、確率分布とはということは、記事に詳しく書いてあるので、ここではコードを作るために必要な情報を書いていきます。
N
→
試行回数なので、課題では「サイコロを5回投げる」ので、N=5
N!
→
5の階乗。mathライブラリのfactorialメソッドを使います
k1 k2 k3 k4 k5 k6
→
サイコロをN回投げたとき、各サイコロの目の出た回数の組み合わせ
たとえば、5回投げた場合、
5回すべて1がでた場合、k1=5 k2=0 k3=0 k4=0 k5=0 k6=0
5回中6以外が1回ずつ出た場合、k1=1 k2=1 k3=1 k4=1 k5=1 k6=0
となります。
確率分布ではこの組み合わせごとの確率を求めていきます(という理解)。
確率分布を求めていく
まずはサイコロを5回投げたときの出目の組み合わせを洗い出します。
k1=5 k2=0 k3=0 k4=0 k5=0 k6=0のとき
k1=4 k2=1 k3=0 k4=0 k5=0 k6=0のとき
k1=4 k2=0 k3=1 k4=0 k5=0 k6=0のとき、、、
を考えてコードを書くのは大変なので、いったんkXが0~5すべて入った場合のk1~k6の組み合わせを全部出します
たとえばこんな感じ
#k1-k2-k3-k4-k5-k6
0-0-0-0-0-5
0-0-0-0-1-4
0-0-0-0-2-3
...
5-5-5-5-5-3
5-5-5-5-5-4
5-5-5-5-5-5
全組み合わせは下記のコードの再帰関数(create_pattern(k, list))で作っていきます。
その後、組み合わせのうち、k1~k6の合計が5になる組み合わせのみし、公式に合わせて確率を計算します。
#!/usr/bin/env python
import math
#再帰関数で全組み合わせを作る
#ハイフン区切りの組み合わせにする
def create_pattern(k, list):
if k == 1:
for i in xrange(0, 6):
list.append(str(i))
else:
new_list = []
for pattern in list:
for j in xrange(0, 6):
new_list.append(pattern + '-' + str(j))
list = new_list
if k == 6:
return list
else:
k = k + 1
return create_pattern(k, list)
# サイコロを投げる回数
n = 5
all_pattern_str_list = create_pattern(1, [])
#ハイフン区切りの組み合わせを分解して、合計が5の組み合わせのみ、確率を計算していく
for all_pattern_str in all_pattern_str_list:
tmp_list = all_pattern_str.split('-')
pattern_sum = 0
pattern_list = []
for tmp_str in tmp_list:
pattern_list.append(int(tmp_str))
if sum(pattern_list) == 5:
print pattern_list
#公式の分母(k1!k2!k3!k4!k5!k6!)を計算
denom = 1
for p in pattern_list:
denom = denom * math.factorial(p)
#確率の計算
print (math.factorial(n) / denom) * (1.0 / 6.0 ** n)
まとめ
記事中にもありますが、コードに落とすと、数学も理解しやすくなりました。