モンティ・ホール問題を考えてみた
IT技術
はじめに
こんにちは。今回は巷でウワサ?のモンティ・ホール問題について書こうと思います。
一般的に思うことと確率的に出される結果に相違がある良い例です。
モンティ・ホール問題とは
モンティ・ホール問題は、確率論における有名な話の一つで、アメリカのテレビゲームショー「Let's Make a Deal」に由来します。
あなたはゲームショーの参加者で、モンティ・ホールという司会者の前に立っています。目の前には閉じられた3つのドアがあり、そのうち1つのドアの後ろには車が、残り2つのドアの後ろにはヤギがそれぞれ隠されています。車またはヤギがどのドアの後ろにあるかは、あなたにはわかりません。
ゲームのルールはシンプルです。あなたは最初に3つのドアのうち、好きなドアを1つ選びます(しかし、その時点ではドアを開けません)。あなたがドアを選んだ後、モンティは残りの2つのドアのうち、ヤギが隠されているドアを1つ開けます。モンティは必ずヤギのいるドアを開けることができる人なので、必ずヤギが見えるようにドアを開けます。
この時点で、あなたには2つの選択肢があります。最初に選んだドアを貫くか、もう一つのまだ閉じたドアに変更するかです。
さあ、あなたはどうすべきでしょうか?
- ドアを変更した方がよいのでしょうか
- 最初の選択を貫くべきなのでしょうか
- それともどちらでも変わらないでしょうか
解答
回答は1(ドアを変更)となります。当然だよね。というかたはもうこれ以降は読む必要はありません。
結局ドアは2つ残されていて、車かヤギだけだから確率は1/2だから変わらない!!!という方、一緒に考えていきましょう。
事象の洗い出し
事象を洗い出してみます。
ヤギ、ヤギ、車は変わらないので、ドア1- ヤギ、ドア2- ヤギ、ドア3- 車の場合を考えてみます。
上記のようになります。
ここで注目すべきは、あなたがヤギのいるドアを選んだ場合、モンティさんは車のあるドアを選択できないという事実です。その場合、ドアを変更すると必ず正解となります。
他方で、あなたが車の隠されているドアを選んだ場合、モンティさんは残り2つのドアを選択できるということになります。その場合、ドアを変更すると必ずハズレになります。
ここで、一つ戦略を考えましょう。
最初に選んだドアから、ドアを必ず変更するという戦略をとってみます。
すると以下のようになります。
すると、最初にあなたがヤギのいるドアを選択した場合、必ず車をgetできますね。
一方で最初に車を選んでいた場合はヤギでハズレになってしまいます。
そして総合的に考えると、あなたが最初に選択するドアの確率は1/3で車、2/3でヤギとなります。
ですので最初に選んだドアから、ドアを必ず変更する戦略をとると正解の確率が1/2から2/3に上がるよ。というお話でした。
実際に計算してみる
1import random as rand
2# 正解のドア番号
3correct_door = 1
4# 試行回数のリスト
5trial_counts = [100, 10000]
6
7# 各試行回数ごとの選択結果を格納するdict
8results_initial = {}
9results_switched = {}
10results_randomly_chosen = {}
11
12for trial_count in trial_counts:
13 results_initial[trial_count] = []
14 results_switched[trial_count] = []
15 results_randomly_chosen[trial_count] = []
16 for _ in range(1, trial_count):
17
18 initial_choice = rand.randint(1, 3)
19 monty_choice = 0
20 possible_choices = [2, 3]
21 if initial_choice == correct_door:
22 monty_choice = rand.choice(possible_choices)
23 else:
24 monty_choices = [1,2,3]
25 monty_choices.remove(initial_choice)
26 monty_choices.remove(correct_door)
27 monty_choice = monty_choices[0]
28
29 # 最初の選択を維持
30 results_initial[trial_count].append(initial_choice)
31
32 # ランダムに選び直す
33 remaining_doors = [1, 2, 3]
34 remaining_doors.remove(monty_choice)
35 random_choice = rand.choice(remaining_doors)
36 results_randomly_chosen[trial_count].append(random_choice)
37
38 # 選択を変更
39 remaining_doors.remove(initial_choice)
40 switched_choice = remaining_doors[0]
41 results_switched[trial_count].append(switched_choice)
42
43# 各戦略の勝率を計算して表示
44for idx, trial_count in enumerate(trial_counts):
45 rate_initial = sum(1 for choice in results_initial[trial_count] if choice == correct_door) / trial_count
46 rate_switched = sum(1 for choice in results_switched[trial_count] if choice == correct_door) / trial_count
47 rate_randomly_chosen = sum(1 for choice in results_randomly_chosen[trial_count] if choice == correct_door) / trial_count
48
49 print("#"*30)
50 print(f"{trial_count}回実行した場合:")
51 print(f"最初のものを変えない場合: {rate_initial}")
52 print(f"ランダムに選択した場合: {rate_randomly_chosen}")
53 print(f"変えた場合: {rate_switched}")
1##############################
2100回実行した場合:
3最初のものを変えない場合: 0.37
4ランダムに選択した場合: 0.44
5変えた場合: 0.62
6##############################
710000回実行した場合:
8最初のものを変えない場合: 0.3227
9ランダムに選択した場合: 0.5
10変えた場合: 0.6772
最悪なのは最初の選択を変えない場合で確率は1/3ですね。
当然ですが、モンティさんが選んだ後、残り2つから適当に選んだ確率は1/2になっていることがわかります。
結果、最初に選んだドアから、ドアを必ず変更する戦略をとると正解の確率が2/3に上がることがわかりました。
「確率」は面白いですね。また、実装することで試行でき、それで一層理解を深めることができます。
ライトコードでは、エンジニアを積極採用中!
ライトコードでは、エンジニアを積極採用しています!社長と一杯しながらお話しする機会もご用意しております。そのほかカジュアル面談等もございますので、くわしくは採用情報をご確認ください。
採用情報へ
ライトコードに転職してまだ日は浅いですが、毎日新鮮でワクワクしてます!
おすすめ記事
immichを知ってほしい
2024.10.31