개요

  • 쿠키 두 그릇이 있다.
  • 첫 번째 그릇: 40 개의 쿠키가 담겨 있다.
    • 바닐라 쿠키 30개
    • 초콜렛 쿠키 10개
  • 두 번째 그릇: 40개의 쿠키가 담겨 있다.
    • 바닐라 쿠키 20개
    • 초콜렛 쿠키 20개

문제 : 어떤 그릇인지 보지 않고 한 그릇에서 임의로 쿠키를 집었는데 바닐라 쿠키였다. 그렇다면 이 때 이 바닐라 쿠키가 그릇1에서 나왔을 가능성은?

풀이

손으로 풀기

바닐라 쿠키가 나온 상태에서 그릇 1의 가능성을 따지는 것이므로 다음의 식을 풀면 된다.

p(1)p(1)

베이즈 정리(Bayes' theorem)이 다음과 같으므로,

p(AB)=p(A) p(BA)p(B)p(AB)=p(A) p(BA)p(B)

식도 다음과 같이 꾸며보자.

p(B1V)=p(B1) p(VB1)p(V)p(B1V)=p(B1) p(VB1)p(V)

생각해야 할 변수가 많으므로 표로 정리해야 이해하기 쉽다.

설명
p(B1)p(B1) 그릇1을 선택할 확률 1212
p(V)p(V) 바닐라 쿠키를 선택할 확률 모름
p(VB1)p(VB1) 그릇1에서 바닐라 쿠키를 선택할 확률 3040=343040=34
p(VB2)p(VB2) 그릇2에서 바닐라 쿠키를 선택할 확률 2040=122040=12
p(B1V)p(B1V) 바닐라 쿠키를 선택했는데 그릇1에서 나왔을 확률 이 값이 답이다

바닐라 쿠키를 선택할 확률 p(V)p(V)를 먼저 구해보자.

다음의 두 값을 구해 더하면 된다.

  • 그릇1에서 바닐라 쿠키를 선택할 확률.
  • 그릇2에서 바닐라 쿠키를 선택할 확률.

식은 다음과 같이 두 가지 형태로 만들 수 있는데

p(V)=p(V and B1)+p(V and B2)=p(V)p(B1V)+p(V)p(B2V)p(V)=p(V and B1)+p(V and B2)=p(V)p(B1V)+p(V)p(B2V) p(V)=p(B1 and V)+p(B2 and V)=p(B1)p(VB1)+p(B2)p(VB2)p(V)=p(B1 and V)+p(B2 and V)=p(B1)p(VB1)+p(B2)p(VB2)

첫번째의 경우 양 변을 p(V)로 나눠주면 1=p(B1V)+p(B2V)1=p(B1V)+p(B2V) 이 나오므로 의미가 없다.

따라서 두 번째 식을 사용해 계산한다.

p(V)=p(B1 and V)+p(B2 and V)=p(B1)p(VB1)+p(B2)p(VB2)=12×3040+12×2040=38+28=58p(V)=p(B1 and V)+p(B2 and V)=p(B1)p(VB1)+p(B2)p(VB2)=12×3040+12×2040=38+28=58

이제 p(V)p(V)를 구했으니 식에 대입해 보자.

p(B1V)=12×3458=3858=35p(B1V)=12×3458=3858=35

따라서, 답은 3535 이다.

Think-Bayes 책에서 제공하는 라이브러리를 사용해 풀기

"""This file contains code for use with "Think Bayes",
by Allen B. Downey, available from greenteapress.com

Copyright 2012 Allen B. Downey
License: GNU GPLv3 http://www.gnu.org/licenses/gpl.html
"""

from thinkbayes import Pmf

pmf = Pmf()
pmf.Set('Bowl 1', 0.5)  # p(B1)
pmf.Set('Bowl 2', 0.5)  # p(B2)

pmf.Mult('Bowl 1', 0.75)    # p(B1) * p(V | B1)
pmf.Mult('Bowl 2', 0.5)     # p(B2) * p(V | B2)

pmf.Normalize()

print pmf.Prob('Bowl 1')

위의 파이썬 코드를 실행하면 0.6이 나온다.

$ python cookie.py
0.6

직접 코딩해 풀기

(study) 파이썬을 활용한 베이지안 통계 저자가 제공하는 라이브러리를 사용하는 것은 편리한 일이지만, 파이썬2에서만 돌아가고 상속구조가 있어 한 눈에 보기 불편하다는 단점이 있다.

그래서 책의 소스코드를 보고 다음과 같이 자바스크립트로 문제를 풀어 보았다.

// 사전 분포
const pmf = {
    'Bowl1': (1/2), // p(B_1)
    'Bowl2': (1/2), // p(B_2)
};

// 우도
const pvb1 = (3/4);
const pvb2 = (1/2);


// p(B_1) * p(V|B_1)
// p(B_2) * p(V|B_2)
pmf['Bowl1'] = pmf['Bowl1'] * pvb1;
pmf['Bowl2'] = pmf['Bowl2'] * pvb2;

// 정규화
function normalize(dict) {
    const values = Object.values(dict);
    const sum = values.reduce((a, b) => a + b);
    const result = {};
    Object.keys(dict).forEach((key) => {
        result[key] = dict[key] / sum;
    });
    return result;
}

console.log(normalize(pmf));

// 결과는 { Bowl1: 0.6, Bowl2: 0.4 }

normalize를 사용하는 방식이 인상적이다.

  • 그 결과로, B_1B_2를 한 번에 구할 수 있다.
  • 한편, normalizep(V)를 계산해 적용하는 작업이므로 수작업으로 p(V)를 계산하지 않아도 된다는 장점이 있다.

공산을 사용해 풀기

공산을 사용하면 매우 간단하게 풀 수 있다.

베이즈 정리의 공산 형태는 다음과 같다.

o(AD)=o(A)×p(DA)p(DB)사후 공산=사전 공산×우도비o(AD)=o(A)×p(DA)p(DB) = ×

위에서 문제를 풀 때 사용한 변수명을 적용해 보자.

o(B1D)=o(B1)×p(DB1)p(DB2)o(B1D)=o(B1)×p(DB1)p(DB2)

변수를 표로 정리해 보자.

설명
o(B1D)o(B1D) 바닐라 쿠키가 그릇1 에서 나왔을 사후 공산 모름
o(B1)o(B1) 그릇1을 선택 : 그릇2를 선택 1:1=111:1=11
p(DB1)p(DB1) 그릇1에서 바닐라 쿠키를 선택할 확률 3040=343040=34
p(DB2)p(DB2) 그릇2에서 바닐라 쿠키를 선택할 확률 2040=122040=12
o(B1D)=o(B1)×p(DB1)p(DB2)=1×3412=64o(B1D)=o(B1)×p(DB1)p(DB2)=1×3412=64

사후 공산이 6464이므로, 다음을 알 수 있다.

그릇 1에서 바닐라 쿠키가 나왔을 확률:그릇 2에서 바닐라 쿠키가 나왔을 확률=6:4 1 : 2 =6:4

따라서 그릇1에서 바닐라 쿠키가 나왔을 확률은 66+4=0.666+4=0.6 이다.