Think Bayes ベイズの定理のメモ 2

前回の続きです。

前回やった問題のコードを書き直して一般的なものにする。

■クッキーの問題
「クッキーの入った2つのボウルがある。
ボウル1 ? バニラクッキー 30枚 :チョコレートクッキー 10枚
ボウル2 ? バニラクッキー 20枚 :チョコレートクッキー 20枚
どちらかのボウルをランダムに選びクッキーを1つランダムに選んだ場合、
それがボウル1だという確率を求めよ。」

from thinkbayes import Pmf
class Cookie(Pmf):
    def __init__(self, hypos):
        Pmf.__init__(self)
        for hypo in hypos:
            self.Set(hypo, 1)
        self.Normalize()

    def Update(self, data):
        for hypo in self.Values():
            like = self.Likelihood(data, hypo)
            self.Mult(hypo, like)
        self.Normalize()

    mixes = {
        'Bowl 1':dict(vanilla=0.75, chocolate=0.25),
        'Bowl 2':dict(vanilla=0.5, chocolate=0.5),
        }

    def Likelihood(self, data, hypo):
        mix = self.mixes[hypo]
        like = mix[data]
        return like


def main():
    hypos = ['Bowl 1', 'Bowl 2']
    pmf = Cookie(hypos)
    pmf.Update('vanilla')
    for hypo, prob in pmf.Items():
        print hypo, prob
if __name__ == '__main__':
    main()

■20年前の早稲田大学の入試問題
「5回に1回の割合で帽子を忘れるくせのあるK君が、正月に A、B、C 3軒を順に年始回りをして家に帰ったとき、
帽子を忘れてきたことに気がついた。2軒目の家 B に忘れてきた確率を求めよ。」

from thinkbayes import Pmf
class Waseda(Pmf):
    def __init__(self, hypos):
        Pmf.__init__(self)
        for hypo in hypos:
            self.Set(hypo, 1)
        self.Normalize()

    def Update(self, data):
        for hypo in self.Values():
            like = self.Likelihood(data, hypo)
            self.Mult(hypo, like)
        self.Normalize()


    def Likelihood(self, data, hypo):
        if hypo == 'A':
            return 1/5.0
        elif hypo == 'B':
            return 4/25.0
        elif hypo == 'C'
            return 16/125.0


def main():
    hypos = ['A', 'B', 'C']
    pmf = Waseda(hypos)
    pmf.Update('B')
    for hypo, prob in pmf.Items():
        print hypo, prob
if __name__ == '__main__':
    main()

■喫煙者の推定の問題
「男性10人、女性7人が一室でパーティーを開いた。男子の喫煙者は5人、女性は3人である。
部屋に入ったら煙草の吸殻が1本、灰皿の上にあった。このとき、吸った人が女性である確率を求めなさい(煙草の吸い回しはしていないと仮定する)」

from thinkbayes import Pmf
class Tabaco(Pmf):
    def __init__(self, hypos):
        Pmf.__init__(self)
        for hypo in hypos:
            self.Set(hypo, 1)
        self.Normalize()

    def Update(self, data):
        for hypo in self.Values():
            like = self.Likelihood(data, hypo)
            self.Mult(hypo, like)
        self.Normalize()

    mixes = {
        'Men':dict(Smoke=1/2.0, NoSmoke=1/2.0),
        'Women':dict(Smoke=3/7.0, NoSmoke=4/7.0),
        }

    def Likelihood(self, data, hypo):
        mix = self.mixes[hypo]
        if hypo == 'Men':
         like = 10/17.0 * mix[data] 
         return like
        elif hypo == 'Women':
           like = 7/17.0 * mix[data] 
           return like


def main():
    hypos = ['Men', 'Women']
    pmf = Tabaco(hypos)
    pmf.Update('Smoke')
    for hypo, prob in pmf.Items():
        print hypo, prob
if __name__ == '__main__':
    main()	

=====フレームワークをカプセル化したとき=====

上のコードの共通化部分をカプセル化したとき。

■クッキーの問題

from thinkbayes import Suite
class Cookie(Suite):
    mixes = {
        'Bowl 1':dict(vanilla=0.75, chocolate=0.25),
        'Bowl 2':dict(vanilla=0.5, chocolate=0.5),
        }

    def Likelihood(self, data, hypo):
        mix = self.mixes[hypo]
        like = mix[data]
        return like

def main():
    suite = Cookie(['Bowl 1', 'Bowl 2'])
    suite.Update('vanilla')
    suite.Print()

if __name__ == '__main__':
    main()

■20年前の早稲田大学の入試問題

from thinkbayes import Suite
class Waseda(Suite):

    def Likelihood(self, data, hypo):
        if hypo == 'A':
            return 1/5.0
        elif hypo == 'B':
            return 4/25.0
        elif hypo == 'C':
            return 16/125.0


def main():
    suite = Waseda(['A', 'B', 'C'])
    suite.Update('B')
    suite.Print()

if __name__ == '__main__':
    main()

■喫煙者の推定の問題

from thinkbayes import Suite
class Smoke(Suite):

    mixes = {
        'Men':dict(Smoke=1/2.0, NoSmoke=1/2.0),
        'Women':dict(Smoke=3/7.0, NoSmoke=4/7.0),
        }

    def Likelihood(self, data, hypo):
        mix = self.mixes[hypo]
        if hypo == 'Men':
         like = 10/17.0 * mix[data] 
         return like
        elif hypo == 'Women':
           like = 7/17.0 * mix[data] 
           return like


def main():
    suite = Smoke(['Men', 'Women'])
    suite.Update('Smoke')
    suite.Print()

if __name__ == '__main__':
    main()	

喫煙者の推定の問題はもっとうまい方法があるかも。
今回は完全にメモ。

*7/24追記
喫煙者の問題で、事前確率を尤度の計算にもってきていたのを
事前確率のところに変更しました。

from thinkbayes import Suite
class Smoke(Suite):

 def __init__(self, hypos):
        Pmf.__init__(self)
        self.Set('Men', 10/17.0)
        self.Set('Women', 7/17.0)
        self.Normalize()

 def Update(self, data):
        for hypo in self.Values():
            like = self.Likelihood(data, hypo)
            self.Mult(hypo, like)
        self.Normalize()
 mixes = {
        'Men':dict(Smoke=1/2.0, NoSmoke=1/2.0),
        'Women':dict(Smoke=3/7.0, NoSmoke=4/7.0),
        }

 def Likelihood(self, data, hypo):
        mix = self.mixes[hypo]
        if hypo == 'Men':
         like = mix[data] 
         return like
        elif hypo == 'Women':
           like = mix[data] 
           return like

def main():
    suite = Smoke(['Men', 'Women'])
    suite.Update('Smoke')
    suite.Print()

if __name__ == '__main__':
    main()	

以上