news 2026/4/20 23:09:50

别再被直觉骗了!用Python模拟10000次,带你彻底搞懂三门问题(蒙提霍尔悖论)

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
别再被直觉骗了!用Python模拟10000次,带你彻底搞懂三门问题(蒙提霍尔悖论)

用Python暴力模拟10000次:为什么直觉在三门问题中总是错的?

第一次听说三门问题时,我和大多数人一样坚信"换不换门概率都一样"。直到亲手用代码模拟了上万次游戏过程,那些冰冷的数字才彻底击碎了我的直觉认知。这大概就是程序员独有的浪漫——当逻辑和直觉打架时,让计算机用海量实验告诉我们真相。

1. 反直觉的概率陷阱

想象你参加一档真人秀节目,面前有三扇关闭的门:门A、门B和门C。主持人告诉你其中一扇门后是辆跑车,另外两扇门后是山羊。你选择了门A后,主持人(他知道每扇门后有什么)打开了门C展示一只山羊,然后问你:"要不要换成门B?"

大多数人会这样思考

  • 现在剩下两扇门(A和B)
  • 跑车在任意一扇门后的概率应该是50%对50%
  • 所以换不换无所谓

这个推理听起来完全合理,但却是完全错误的。让我们用Python模拟来揭示其中的概率把戏。

关键提示:主持人的行为不是随机的——他一定会打开一扇有山羊的门,这个动作传递了额外信息。

2. 构建模拟实验

我们将用Python模拟这个游戏10000次,分别统计"坚持初始选择"和"更换选择"的胜率。以下是完整的实验代码:

import random from collections import defaultdict def monty_hall_simulation(trials=10_000): results = defaultdict(int) for _ in range(trials): # 随机放置汽车(0,1,2分别代表三扇门) car_position = random.randint(0, 2) # 玩家初始选择 first_choice = random.randint(0, 2) # 主持人打开一扇有山羊的门 opened_door = next( door for door in range(3) if door != first_choice and door != car_position ) # 玩家决定是否换门 switch_choice = next( door for door in range(3) if door != first_choice and door != opened_door ) # 记录结果 if first_choice == car_position: results["stay_win"] += 1 if switch_choice == car_position: results["switch_win"] += 1 return results

运行这个函数,你会得到类似这样的输出:

{ 'stay_win': 3325, # 坚持选择的获胜次数 'switch_win': 6675 # 更换选择的获胜次数 }

3. 实验结果分析

让我们把多次模拟结果整理成对比表格:

策略获胜次数胜率
坚持初始选择3,32533.25%
更换选择6,67566.75%

这个结果可能让你大吃一惊——更换选择后的胜率几乎是坚持选择的两倍!为什么会出现这种情况?

概率重新分配的关键点

  1. 初始选择时,每扇门有1/3的概率
  2. 主持人打开一扇门后,他没有给你的初始选择带来新信息
  3. 但他打开门的行为,把另外两扇门(你未选的)的总概率2/3集中到了剩下的那扇门上

4. 可视化概率变化

为了更直观理解,让我们用ASCII图表展示概率流动过程:

初始概率分布: +-------+-------+-------+ | 1/3 | 1/3 | 1/3 | | 门A | 门B | 门C | +-------+-------+-------+ 假设你选择门A,主持人打开门C(山羊): 概率重新分配: +-------+-------+-------+ | 1/3 | 2/3 | 0 | | 门A | 门B | (已开)| +-------+-------+-------+

这个可视化说明了一个关键洞见:主持人的行为本质上是帮你排除了一个错误选项,把另外两扇门的概率优势集中到了剩下的那扇门上

5. 极端案例验证

如果还是难以接受,考虑一个极端版本——有100扇门:

  1. 你随机选择一扇门(胜率1%)
  2. 主持人打开98扇门,留下你的选择和另一扇门
  3. 现在你会坚持1%胜率的选择,还是切换到那扇被精心保留的门?

在这个极端案例中,直觉会明显倾向于"应该换门",因为主持人用他的行为把99%的概率集中到了那扇门上。三门问题只是这个逻辑的迷你版本。

6. 常见误区解析

在与数百名开发者讨论这个问题后,我总结了最常见的几种认知偏差:

误区一:独立事件假设

  • 错误认为主持人开门后,剩下两门概率应该重新计算
  • 实际上主持人行为与你的初始选择相关,不是独立事件

误区二:忽略信息价值

  • 低估了"主持人知道门后情况"这一信息
  • 如果主持人随机开门(可能开到汽车),情况就完全不同

误区三:小样本错觉

  • 用少量试验(如玩3次)来判断概率
  • 概率规律需要大样本才能显现

7. 进阶思考:代码优化与扩展

我们的基础模拟已经证明了结论,但还可以做更多有趣探索:

优化1:动态可视化

import matplotlib.pyplot as plt def plot_probability_trend(max_trials=10_000): stay_probs, switch_probs = [], [] for n in range(1, max_trials+1): results = monty_hall_simulation(1) stay_probs.append(sum(stay_probs[-1:]) + results['stay_win'] / n) switch_probs.append(sum(switch_probs[-1:]) + results['switch_win'] / n) plt.plot(stay_probs, label='坚持选择') plt.plot(switch_probs, label='更换选择') plt.axhline(y=1/3, color='r', linestyle='--') plt.axhline(y=2/3, color='g', linestyle='--') plt.legend() plt.show()

这段代码会绘制胜率随试验次数变化的曲线,直观展示大数定律如何使概率收敛到理论值。

扩展1:多门多奖品版本

def extended_monty_hall(doors=3, prizes=1, trials=10_000): results = {'stay':0, 'switch':0} for _ in range(trials): # 随机放置奖品 positions = random.sample(range(doors), prizes) # 玩家初始选择 choice = random.randint(0, doors-1) # 主持人打开门(确保不暴露奖品) opened = [d for d in range(doors) if d != choice and d not in positions] opened = random.sample(opened, doors-prizes-1) # 切换选择 switch = [d for d in range(doors) if d != choice and d not in opened] switch = random.choice(switch) # 统计结果 if choice in positions: results['stay'] += 1 if switch in positions: results['switch'] += 1 return results

这个扩展版本可以模拟更多门和奖品的情况,比如:

  • 5扇门2辆汽车
  • 10扇门3辆汽车

运行结果会展示不同配置下的最优策略变化。

8. 为什么这个悖论如此著名?

三门问题之所以成为经典,是因为它完美展示了人类认知的几个脆弱点:

  1. 概率直觉的局限性:我们进化出的直觉适合处理简单确定的情况,对复杂概率容易误判
  2. 信息价值的误估:难以意识到主持人行为中包含的关键信息
  3. 确认偏误:一旦形成初始判断(如"概率应该均等"),就会寻找支持这个判断的证据

在数据分析项目中,我多次遇到类似情况——团队成员对某些统计结果表示怀疑,因为"不符合直觉"。这时候最好的解决方法就是像我们这里做的一样:用代码和实验说话

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/20 23:04:23

如何实现typed.js动画模块的按需加载:提升网页性能的完整指南

如何实现typed.js动画模块的按需加载:提升网页性能的完整指南 【免费下载链接】typed.js A JavaScript Typing Animation Library 项目地址: https://gitcode.com/gh_mirrors/ty/typed.js typed.js是一款轻量级的JavaScript打字动画库,能够为网页…

作者头像 李华
网站建设 2026/4/20 22:58:17

C源代码生成器在DDD领域建模中的强大应用

C#源代码生成器在DDD领域建模中的强大应用 【免费下载链接】csharp-source-generators A list of C# Source Generators (not necessarily awesome) and associated resources: articles, talks, demos. 项目地址: https://gitcode.com/gh_mirrors/cs/csharp-source-generato…

作者头像 李华
网站建设 2026/4/20 22:55:16

Nanotron中的谱μTransfer参数化:神经网络扩展的终极解决方案

Nanotron中的谱μTransfer参数化:神经网络扩展的终极解决方案 【免费下载链接】nanotron Minimalistic large language model 3D-parallelism training 项目地址: https://gitcode.com/gh_mirrors/na/nanotron Nanotron是一个专注于大型语言模型3D并行训练的…

作者头像 李华
网站建设 2026/4/20 22:55:14

019、代码大模型微调:为代码生成与理解任务定制模型

代码大模型微调:深夜调试引发的思考 上周排查一个生产环境问题,凌晨三点盯着日志里那段自动生成的SQL语句发愣。模型确实生成了语法正确的代码,但它把用户订单表orders和日志表event_logs做了笛卡尔积——一个初级开发者都不会犯的错误。那一刻我意识到:通用大模型能写代码…

作者头像 李华