事後確率の推移をグラフで可視化する - 多面体サイコロ編
TL;DR
多面体のサイコロを投げる例で、事後確率が変わる様子を観察する。
- 事前確率があるとする(例えば1/6とか)=
before_p1
- サイコロを投げて結果を見る(実際のサイコロの目を見る、例えば6とか)
- 事後確率(結果を見た上で推定した確率)=
after_p1
(一投目の後) - 前回の事後確率を現在の事前確率と見なす =
after_p1
=before_p2
- もう一度サイコロを投げて結果を見る(実際のサイコロの目を見る、例えば8とか)
- 事後確率(結果を見た上で推定した確率) =
after_p2
(二投目の後) - これを繰り返すと事後確率が更新されていく(=より正確な推定ができる!)
以下のnotebookで実行したコード(+説明もついてる) github.com
シナリオ
誰かが4〜20面体のサイコロのいずれかを複数回投げた結果を見て、あなたはどの多面体のサイコロを投げたかを推測する。
(例えば、当然のことだが4面体のサイコロで6が出ることはない)
- 多面体のサイコロを使用する
- 4面体のサイコロで出る目 => [1, 2, 3, 4]
- 6面体のサイコロで出る目 => [1, 2, 3, 4, 5, 6]
- 8面体のサイコロで出る目 => [1, 2, 3, 4, 5, 6, 7, 8]
- 12面体のサイコロで出る目 => [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]
- 20面体のサイコロで出る目 => [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20]
内容
事前確率から事後確率を計算するクラス(共通)
以下のコードを参考にしているが、元のコードが複雑だったので必要な処理だけ雰囲気で書いている。
GitHub: AllenDowney/ThinkBayes
サイコロの場合の尤度を設定
class Dice(Suite): def Likelihood(self, data, hypo): if hypo < data: # 例) 4面体のサイコロで6が出る確率は0 return 0 else: return 1.0 / hypo # 例) 4面体のサイコロで4が出る確率は1/4、6面体のサイコロで4が出る確率は1/6
サイコロをたくさん投げる
サイコロを複数回投げて、どのサイコロを投げているかを推定する
- 投げた結果: [6, 8, 7, 7, 5, 4]
- サイコロを投げる度に、8面体である確率が高くなることが見て取れる。
suite = Dice([4, 6, 8, 12, 20]) result = [] rolls = [6, 8, 7, 7, 5, 4] for i, roll in enumerate(rolls): suite.Update(roll) posts = suite.Posts().copy() result.append(posts) plot_probability(posts, 'After {}'.format(rolls[:i+1]))
サイコロを投げる回数の推移によって確率が変わる様子をプロット
- 一投目(一番左)のときには、それぞれ6〜20面体のどのサイコロを投げたかの確率は大体低い(一投目が6だったので4面体である確率は0)
- 二投目(左から二番目)が8だったので、6面体である確率は0になった。残りは8〜20面体だが、8面体である確率が最も高い
- 三投目以降に出目が [7, 7, 5, 4] となっており、もし12〜20面体であれば出るはずの9以降の出目が存在しないため一定して8面体である確率が最も高い
- もちろん12〜20面体のサイコロで、偶然8以下の出目が出続けた可能性は存在するが、確率は極めて低い(当たり前!)
参考資料
- 書籍: Think Bayes - 日本語で読める(有料)
- Website: Think Bayes - pdfもhtmlもあるけど英語(無料)