Data Science!/프로젝트

[수학] 확률론 파이썬 실습 - 페르마&파스칼 (난이도 : 중)

양국남자 2021. 9. 14. 12:35

모든 수업은 파이썬 (Python 3 이상) 으로 진행됩니다. Pycharm 등 IDE 사용도 좋지만, Jupyter Notebook 이나 Google Colab 사용을 더욱 권장드립니다. Google Colab 에 있는 전체 컴필레이션은 확률편 마지막 강의에 링크걸어 올릴 예정입니다.

 

저번에 했던 확률론 관련해서 이번에는 실습으로 만나보겠습니다.

 

수학의 두 거장, 페르마와 파스칼을 만나보세요

 

다음과 같은 도박이 있다고 칩시다.

(출처 : 여기 영국 요크대학교 자료 참조 영문 주의.)

 

플레이어 1과 2는 동전을 던집니다. 앞면이 10개 나오면 1이 이기고, 뒷면이 10개 나오면 2가 이깁니다. 그런데 만일 앞면 8개, 뒷면 7개에서 게임이 중단될 경우 판돈을 어떻게 나누어야 할까요? 다음과 같은 방법을 생각할 수 있겠죠

 

1. 코인토스는 확률이 50/50 이니까 판돈을 50/50으로 나눈다

-> 플레이어 1이 지금 승리에 더 가까운데, 플레이어 1에게 불공정하지 않을까요?

 

2. 지금 점수에 따라서 나눈다. 즉 1은 8/15, 2는 7/15로 나눈다

-> 만일 0:1 이면 0/1 로 나눌껀가요?

 

3. 서로 상대방이 얼마나 승리에 가까운지에 따라 나눈다. 플레이어 1 은 3/5, 플레이어 2는 2/5

-> 좀 더 나아보이지만, 만일 9:1 같은 극단적 상황에서도 플레이어 1에게 9/10, 플레이어 2에게 1/10 주는건 좀 과하긴 하죠.

 

프랑스의 도박사 드 메레가 당시 최고의 수학자이던 파스칼에게 이 문제의 풀이를 의뢰했습니다. 파스칼은 이 문제의 풀이를 또 다른 수학계의 대스타 페르마에게 보내 자랑했습니다. 페르마의 답장은 다음과 같습니다. 끼리끼리 논다 놀아.

 

100프랑을 나누는 방법의 문제에 관해서, 나는 당신이 공평한 해결책을 찾았다고 생각합니다. 내가 게임에서 이기려면 2점만 필요했고 당신은 3점이 필요했기 때문에 동전을 4번 더 던지면 게임이 끝났을 것이라는 점을 알 수 있습니다. 왜냐하면 그 네 번의 던지기에서 당신이 승리에 필요한 3점을 얻지 못했다면, 이것은 내가 나의 승리에 필요한 2점을 얻었다는 것을 의미할 것입니다. 비슷한 방식으로 내가 승리에 필요한 2점을 얻지 못했다면 이것은 당신이 실제로 최소한 3점을 얻었고 따라서 게임에서 이겼음을 의미합니다. 따라서 다음과 같은 게임의 가능한 결말 목록이 완전하다고 생각합니다. 나는 '머리'를 'h'로, 꼬리를 't'로 표시했습니다. 나는 나 자신의 승리를 나타내는 결과에 별표를 표시했습니다. (h가 앞면, t가 뒷면)


당신도 이 모든 경우의 수의 확률이 동일함에는 이견이 없을 거라 생각합니다. 고로, 총 16가지 경우에 대해 저는 제가 이길 수 있는 11개의 경우에 따라 11/16, 당신은 5/16으로 나누어 가져야 한다고 생각합니다.

 

쉽게 말하자면, 파스칼은 7-8 상황에서 나올 수 있는 모든 경우의 수를 찾아냈습니다. 일단 4번 안에 승부는 나기 때문에, 2^4 해서 경우의 수는 총 16가지입니다. 그리고 파스칼은 모든 상황에서 본인이 이길 확률대로만 가져가는 방식을 제안했고, 페르마에게도 동의를 받았습니다.

 

여기서 나온 수학적 담론인 파스칼의 삼각형..은 이 블로그가 수학 전문 블로그가 아니므로 외부 링크로 대체하겠습니다. 

 

독ㅇ..아니 우리 21세기의 전산 기술은 역대 제이이이이이일!!

 

우리는 21세기의 과학 기술을 활용해서 이걸 파이썬으로 짜 보는게 목표입니다. 옛날에는 파스칼과 페르마가 출동해서 해결하는 문제였지만, 거인의 어께위에 서 있는 21세기에 전산기술의 힘을 빌리면 파이썬으로 비교적 간단하게 짜 볼 수 있어요.

 

확률강의 1편에서 보았던 itertools 가 필요합니다.

 

#플레이어1(앞면) 이 아직 결판나지 않은 동전 내기를 이길 확률을 구하는 함수
def win_unfinished_game(h, t):
    return P(at_least(h, 'h'), finishes(h, t))

#결과가 나올 때 최소 몇개(n)가 나올지 예측하는 함수입니다
#파이썬 스킬 응용 및 파이토닉한 문법연습을 위해 일부러 람다 써서 함수를 구현했습니다. 
def at_least(n, item):
    return lambda outcome: outcome.count(item) >= n

#플레이어 1이 h개 점수, 플레이어 2가 t개 점수가 필요할때 나오는 모든 결말들입니다.
def finishes(h, t):
    tosses = ['ht'] * (h + t - 1)
    return set(itertools.product(*tosses))

앞으로 승리까지 플레이어 1 2점, 플레이어 2 3점 이었습니다.

 

finishes(2, 3)

#결과 출력 코드입니다.

페르마가 일일이 편지에 적은 거 우리는 파이썬이 다 해줍니다.

 

 

favorable(at_least(2, 'h'), finishes(2, 3))

#결과값은 분포도로 나옵니다.

마지막으로, 승률을 구해 봅시다.

 

100 * win_unfinished_game(2, 3)
#68.75, 11/16 하면 0.6875 니까 68.75% 확률로 이긴다고 정확히 나옵니다.

 

오늘 여러분은 페르마와 파스칼이 머리 싸매고 끙끙대던 문제를 파이썬으로 손쉽게 해결하셨습니다. 다음 시간에는 부루마블 시뮬레이션으로 실습 하겠습니다. 

 

Data Science = Programming + Statistics + Probability + Machine Learning (+ Domain Knowledge)