it

몬티홀의 딜레마 직접 실험해본 결과

IT's me 2021. 9. 21. 16:06

최근 넷플릭스 드라마 D.P에서도 그렇고 문제적 남자에서도 몬티홀의 딜레마에 나오고 있어서 궁금해졌습니다. 두군데에서 설명하는 문제에 대해서 이해가 될 것 같기도 하고 안될것 같기도 해서 말이죠.  몬티홀의 딜레마 간단하게 설명해볼게요.  

 

몬티홀이라는 미국 오락 프로그램 사회자가 낸 확률 문제 

 

1. 세개의 문이 있습니다. 

 

2. 세개의 문 중에 하나는 새 자동차가 있고 두개의 문에는 염소가 있습니다.

 

3. 세개 문 중에 하나를 뽑아 선택된 상품을 얻게 됩니다. 

 

4. 먼저 참가자가 문을 하나 고르게 합니다. 여기서 편의상 1번 문을 선택했다고 가정합니다.

 

5. 사회자는 정답을 알고 있고 다른 문중에 염소가 있는 문을 하나 열어줍니다. 

세개의 문 중에 자동차가 하나 , 염소가 둘 있음

6. 이제 사회자가 다시 묻습니다. 1번과 2번 문이 남아있습니다. 문을 바꿀 수 있는 기회를 드리겠습니다. 바꾸시겠습니까?

 

여러분은 문을 바꾸시겠습니까? 대부분의 사람은 1번과 2번이 남았으므로 각각 1/2 확률로 정답일 것이며 내가 선택한 1번을 굳이 바꿀 필요를 느끼지 못하는 것이 더 많을 겁니다. 괜히 바꿨다가 못받는 경우에 대해서 굉장히 억울하게 생각할거란 말이죠.

 

실제론 아래처럼 2번문 확률이 66%가 되고 1번 문은 그대로 33%가됩니다. 

 

하지만 사회자가 정답을 알고 있고 반드시 염소 문을 선택한기 때문에 확률에 영향을 미치게 됩니다. 쉽게 이해하려면 문을 백개로 늘려보면 됩니다. 

 

도박마 28화 - 몬티홀 문제에서 문을 100개로 늘린 경우를 설명

이 경우 좀 더 확실하게 뭔가 느껴지지 않을까 싶은데요. 사회자가 98개의 문을 제거하면 남은 한개의 문은 99% 자기가 선택한 문은 처음 그대로 1%의 확률이라는 거죠. 


프로그램 증명

코딩을 조금 할줄 알아서 코드를 만들어서 증명하려고 했는데 이미 나무위키에 증명하는 소스 코드가 있군요. 바퀴를 두번 만들순 없으니 그대로 차용해서 돌려보겠습니다. 

package test;

public class Monty_Hall_problem {
    public static void main(String[] args) {

        int normal_win_rate=0; // 바꾸지 않아서 이긴 횟수
        int normal_lose_rate=0; // 바꾸지 않아서 진 횟수
        int change_win_rate=0; // 바꿔서 이긴 횟수
        int change_lose_rate=0; // 바꿔서 진 횟수

        for(int i=0;i<100000;i++){ // 총 10만 번 반복한다.
            int reward = (int)(Math.random()*3+1); // 주최자는 1~3중 정답을 하나 숨김
            int answer = (int)(Math.random()*3+1); // 참가자는 1~3중 하나를 고름

            /*이때 주최자는 염소를 고른 뒤 참가자에게 바꿀지 말지 제안한다.*/
            
            //주최자는 참가자의 답과 보상이 아닌 것을 택함
            int val = (int)(Math.random()*3+1);
            while(reward == val || answer == val){
                val = (int)(Math.random()*3+1);
            }

            //바꾸지 않았을 시
            if(reward == answer) normal_win_rate++; //바꾸지 않아서 이겼을 경우 1승 추가
            else normal_lose_rate++; //바꾸지 않아서 졌을 경우 1패 추가

            //바꿨을 시
            int change = (int)(Math.random()*3+1);
            while(val == change || answer == change){ //이때 참가자는 바꾸기로 결정
                change = (int)(Math.random()*3+1);
            }
            if(reward == change) change_win_rate++; //바꿔서 이겼을 경우 1승 추가
            else change_lose_rate++; //바꿔서 졌을 경우 1패 추가

        }

        System.out.println("normal_win_rate : "+normal_win_rate); // 바꾸지 않아서 이긴 횟수 출력
        System.out.println("normal_lose_rate : "+normal_lose_rate); // 바꾸지 않아서 진 횟수 출력
        long normal_rate = (normal_win_rate*100)/(normal_win_rate+normal_lose_rate); //확률계산
        System.out.println("rate : "+normal_rate+"%"); //바꾸지 않아서 이길 확률
        System.out.println();

        System.out.println("change_win_rate : "+change_win_rate); // 바꿔서 이긴 횟수 출력
        System.out.println("change_lose_rate : "+change_lose_rate); // 바꿔서 진 횟수 출력
        long change_rate = (change_win_rate*100)/(change_win_rate+change_lose_rate); //확률계산
        System.out.println("rate : "+change_rate+"%"); //바꿔서 이길 확률

    }
}

 

코드 내용은 몬티홀의 딜레마 그대로 변경하는 경우와 변경하지 않는 경우를 각각 10만번씩 실제로 돌려보는 겁니다. 

 

결과는?

normal_win_rate : 33086
normal_lose_rate : 66914
rate : 33%

change_win_rate : 66914
change_lose_rate : 33086
rate : 66% 

변경하지 않는 경우 33%, 변경하는 경우 66% 입니다. 


사실 이 몬티홀의 딜레마를 보면서 머리로는 억지로 이해가 되는데 가슴으로 이해가 되지 않는다고 할까 그런 느낌이 있습니다. 직관적으로 이해하게되면 아무런 문제가 없을텐데 말이죠. 제일 와닿는건 문을 극단적으로 갯수를 늘려보는 겁니다. 사회자가 문을 제거하면 남은 문이 정답일 확률은 계속해서 어마어마하게 높아지는 거니까요. 

 

사회자에게 한가지 가정이 있잖아요. 정답을 열수 없다와 참가자가 열었던 문은 열 수 없다. 참가자가 선택한 문은 정답일지 아닐지 알수 없다. 사회자는 나머지 문 중에서 정답을 제외한 문을 소거해나간다. 

 

참가자가 선택한 문을 제외한 나머지 열리지 않는 문은 계속해서 확률이 높아진다. 뭐 그렇게 생각합니다.

 

이걸 해설을 보지 않고 또 결과를 듣지 않고 직관적으로 바로 정답을 외칠수 있는 머리였다면 참 좋았을텐데 말이죠. 인생도 달라졌을테구요.