37
43

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

最も基本的なベイズ定理のpython実装

Last updated at Posted at 2017-10-22

はじめに

当記事は講談社発行の「ベイズ推論による機械学習入門」のP.15からの例題を理解するためにPythonでコーディングしたものです

詳しいく知りたい方はぜひ同書籍を購入してみてください

事後確率推定

問題

  • 赤玉と白玉が入った袋が2つ存在する(それぞれA,Bとする)
  • 袋Aには赤玉が2つ、白玉が1つはいっている
  • 袋Bには赤玉が1つ、白玉が4つはいっている
  • 主催者はA,Bどちらかの袋を選ぶが、どちらが選ばれたかは不明である
  • 参加者は袋から玉を取り出し、色を確認したら袋に戻す
  • 参加者が取り出した玉の色から、選ばれた袋がA,Bのどちらであるか推定せよ

ベイズ定理

ベイズ定理の言葉自体は知っている方も多いかと思います。
下記の数式で表現され、事前確率と尤度比から事後確率を算出する例のアレですね

p(X | Y) = \frac{p(Y | X) p(X)}{p(Y)}

数式に不慣れな方はこれだけみても「???」だと思いますが、やっていることは非常に簡単です

  1. p(X) = 袋が選ばれる確率(事前確率)。今回はA,Bの2つがランダムで選ばれるので0.5ですね
  2. p(Y | X) = 赤白玉が選ばれる確率。袋Aで赤が選ばれたのであれば2/3ですね
  3. p(X | Y) = 玉が選ばれた後に、それがどの袋かを表す確率(事後確率)。

つまりランダムでしかなかった確率に、取り出した玉の確率をかけて補正してるだけなんですね
これを袋A,Bの2通り計算し、その比率を計算すればA,Bのそれぞれが選ばれた確率が求まるわけです
(p(Y)については今回の結果に影響を与えないため省略しています)

python実装

エンジニアならコードで語れ!ってことで上記の実装をしてみました。これでどれだけ簡単なことをやっているかは理解していただけるかと思います

まず最初に袋と玉が選ばれた際の確率を定義します

# 袋の種類
BAG_A = 0
BAG_B = 1

# 玉の色
BALL_RED = 0
BALL_WHITE = 1

# 袋を選ぶ確率
_prob_bag = []
_prob_bag.insert(BAG_A, 1/2)
_prob_bag.insert(BAG_B, 1/2)

# 袋内の玉の色を選ぶ確率
_prob_ball = []

_prob_ball_a = []
_prob_ball_a.insert(BALL_RED, 2/3)
_prob_ball_a.insert(BALL_WHITE, 1/3)
_prob_ball.insert(BAG_A, _prob_ball_a)

_prob_ball_b = []
_prob_ball_b.insert(BALL_RED, 1/4)
_prob_ball_b.insert(BALL_WHITE, 3/4)
_prob_ball.insert(BAG_B, _prob_ball_b)

次に事後確率を計算する関数を定義します
先程説明したとおりそれぞれの袋で事前確率を、選んだ玉の確率で補正をかけていくだけですね

# 事後確率を計算する
def posterior(ball_list, bag):
    if len(ball_list) == 1:
        return _prob_ball[bag][ball_list[0]] * _prob_bag[bag]
    else:
        return _prob_ball[bag][ball_list[0]] * posterior(ball_list[1:], bag)

# 袋Aが選ばれる確率を計算する
def posterior_a(ball_list):
    return posterior(ball_list, BAG_A) / (posterior(ball_list, BAG_A) + posterior(ball_list, BAG_B))

たったこれだけです。非常に簡単ですね
じゃあ実際に計算してみましょう

まずは赤玉が1つだけ選ばれた時の確率です

ball = [BALL_RED] * 1
posterior_a(ball)
0.7272727272727273

赤玉が多い袋Aの確率があがりましたね
じゃあもっと赤玉が選ばれ、赤5個/白3個選ばれた場合はどうなるでしょう

ball = [BALL_RED] * 5
ball.extend([BALL_WHITE] * 3)

posterior_a(ball)
0.9221091861712114

92%と飛躍的にあがりましたね

じゃあ同じ比率だけど試行回数が5倍になった場合はどうなるでしょう

ball = [BALL_RED] * 5 * 5
ball.extend([BALL_WHITE] * 3 * 5)

posterior_a(ball)
0.9999956995134158

ほぼ袋Aだといってよい状況になったかと
同じ比率でも試行回数が増えれば増えるほど確率が変化することがわかります

最後に

ベイズ定理の公式自体はわかりにくいかもしれませんが、やっていることは非常に簡単だということがわかったかと思います
我々エンジニアは数式で理解して、コーディングして理解を深めるってやり方が一番腹落ちしやすいのかなあということでやってみました

37
43
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
37
43

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?