Processing math: 0%

2016年4月23日土曜日

モンティホール問題をシミュレーションしてみる

最近、統計学にハマってるので、有名なモンティホール問題をベイズの定理で解いてみる
また、プログラムも組んで理論解と数値解の比較もしてみる
モンティ・ホール問題
3つの箱があり、その内1つにアタリがある
最初に自分は箱を1つ選ぶ
その後、司会者は「自分が選んだ箱」以外からハズレの箱を1つ公開する
自分は箱を選び直す権利があるが、選び直すべきか?

直感的には選び直しても確率は変わらないように思えるが、選び直すのが正解
いつ見ても不思議な問題w

 理論解(ベイズの定理)
箱をそれぞれ、箱1、箱2、箱3とする
自分は箱1を選択し、司会者が箱2をハズレ宣言したとき、それぞれの箱のアタリの確率を求める
事象A:箱1にアタリが入っている
事象B:司会者が箱2をハズレだと宣言する
とすると、それぞれの箱のアタリが入っている確率は、
    ・箱1
    P(A|B)
    ・箱2
    0
      (∵司会者は箱2がハズレと宣言してる)
    ・箱3
    1-P(A|B)
      (∵上記の余事象)
となり、箱1にある確率は「再選択しない時のアタリ率」、箱3にある確率は「再選択時のアタリ率」となる


箱1のアタリ確率はベイズの定理より P(A|B)=\frac{P(B|A) P(A)}{P(B)}
P(A)は「箱1にアタリが入っている」確率なので P(A)=\frac{1}{3}
P(B|A)は「箱1がアタリのとき、司会者が箱2を選ぶ」確率
箱1がアタリで、かつ自分は箱1を選んでいるため、司会者の選択肢は箱2、箱3の2択になる。よって P(B|A)=\frac{1}{2} P(B)は「司会者が箱2をハズレだと宣言する」確率
箱1を自分が選んでいるため、司会者の行動は下記の4通りになる
    ・箱1がアタリの場合は2通り(箱2or箱3)
    ・箱2がアタリの場合は1通り(箱3のみ)
    ・箱3がアタリの場合1通り(箱2のみ)
このとき、箱2が選択できるのは2通り
よって P(B)=\frac{2}{4}=\frac{1}{2} 以上より、
箱1にアタリがある(再選択せずにアタリを引く)確率は
P(A|B)=\frac{P(B|A) P(A)}{P(B)}=\frac{\frac{1}{2}\frac{1}{3}}{\frac{1}{2}}=\frac{1}{3} 箱3にアタリがある(選び直してアタリを引く)確率は 1-P(A|B)=1-\frac{1}{3}=\frac{2}{3}
よって、
選び直した方がアタリの確率が高い

 数値解(モンテカルロ法)
C++で組むとこんな感じ。一応、箱の数が3つ以上の場合にも対応した作り
再選択をしないパターンだと、結果がわかりにくいので、「再選択したときのアタリ確率」を求める
  1. /**
  2. MontyHall.cpp
  3. Monty Hall問題で、再選択時のアタリ確率
  4. */
  5. #include<iostream>
  6. #include<cstdlib>
  7.  
  8. #define N 50000000 // 試行回数
  9. #define NUM 3 // 箱の数
  10.  
  11. int main() {
  12. // 正解数をカウント
  13. long count = 0;
  14.  
  15. // 試行回数分ループ
  16. for(long i = 0; i < N; i++) {
  17.  
  18. // 箱の作成
  19. bool box[NUM];
  20. for(int n = 0; n < NUM; n++) box[n] = false;
  21. box[rand()%NUM] = true;
  22.  
  23. // 自分の選択
  24. int my_select = rand() % NUM;
  25.  
  26. // 司会者の選択
  27. int order_select;
  28. do {
  29. order_select = rand() % NUM;
  30. } while(order_select == my_select || box[order_select]);
  31.  
  32. // 解の変更
  33. int change_select;
  34. do {
  35. change_select = rand() % NUM;
  36. } while(my_select == change_select || order_select == change_select);
  37.  
  38. // 結果
  39. if(box[change_select]) count++;
  40. }
  41. std::cout<< "結果:"<< (double)count / N << std::endl;
  42. return 0;
  43. }
結果は
$ g++ MontyHall.cpp
$ ./a.out
結果:0.666652
分数にすると「2/3」になる
やはり、理論解と一致した

 結論
モンテホール問題は選び直した方が確率が高くなる
しかし、
いろんな確率の本を読んでいると、主観依存だから(ryとか、モデルの設定で変わるから(ryとか
もはや哲学の域で「確率とは何なのか」って感じで発狂したくなる
いろいろな解釈があるけど、数値解でも同様の結果になることから、僕は「確率は上がる」と主張したい

0 件のコメント:

コメントを投稿