Py学习  »  Python

数据科学 | 用Python让你相信:坚持也不一定是对的

运筹OR帷幄 • 4 年前 • 300 次点击  

↑↑↑↑↑点击上方蓝色字关注我们!







『运筹OR帷幄』转载


作者:吹牛Z(公众号:数据不吹牛)


编者按:
本文是对三门悖论的一次重访,以一份简单的代码,从统计的角度验证了“换门策略“的正确性。语言活泼,也可以作为休闲娱乐文章一读。


据不完全统计,面对这个经典的统计悖论,80%的人凭直觉做出了错误的选择,然而他们却坚信自己才是对的。不信?那就和我一起穿越下。


我,莫名其妙的出现在舞台中央,所有聚光灯齐齐射来,突如其来的强光刺的我睁不开眼,只听见场下震耳欲聋的呐喊“坚持你的选择!坚持你的选择!”


我赶紧捋了捋脑中残存的思绪,原来,我穿越到另一个有奖闯关者身上。他一路披荆斩棘,KO掉来自全国的所有竞争对手,此刻,正面临最后一个挑战,眼前5000万大奖唾手可得,万万没想到被我给穿(挤)下线了。

最后一关,是一个叫做“决定”的挑战,奖金高达5000万元:


生存,还是毁灭,这是一个问题。换,还是不换,这也是一个问题。

乍一看,第一步就是TMD盲选啊,而且被我挤下线的那个倒霉虫已经遵循“什么不会就选C”的选择题黄金定律选择了C门。

此刻,主持人友善的打开了B门,门后空空如也,然后狡黠一笑,挑着眉问:“先生,你是坚持最初的选择C呢?还是投向A门的怀抱?”

“坚持你的选择!不要做临阵变卦的蠢货!”观众嘶声力竭。


我有点懵逼,毕竟没怎么经历过这么大的阵仗,赶紧紧闭双眼,试图让注意力集中,嘴里念念有词的回忆当年做选择题的要诀:

  • 三长一短就选短

  • 三短一长就选长

  • 参差不齐就选D

  • 三个选项就蒙C


从经验的角度来看,蒙C的确是目前的最优选项啊!我清了清嗓子,笃定的开腔”我坚持我最初的选择!”


主持人笑出了鱼尾纹,优雅的打开了所有的门,C门后空空如也,而A门后则是金光闪闪的终极大奖。

擦!大奖擦擦擦擦肩而过!

“看呐!你终于为自己的固执付出代价了!”观众瞬间换了腔调,嘲讽的声浪几乎把人吞没。

我胸口越来越闷,一股气拧成团堵在嗓子眼,尽全力想呼出救命却发不出任何声音,突然,眼前一片漆黑。



不知过了多久,再次被强光刺醒,发现自己又回到了舞台中央,再次听见震耳欲聋的呐喊“坚持你的选择!坚持你的选择!”《恐怖游轮》中无线循环的场景闯入脑中,一声声卧槽在心中回荡。

“哥们,是你把我挤下线了把!就你这智商,还想赢大奖?”脑海中另一个声音无比清晰。

我不禁回应道:“刚才C还不是你选的,我只是错信了傻X而已”

“告诉你吧,第一次的选择并不重要,关键在于,在主持人帮你打开一扇门之后,一定要改变最初的选择!

“扯吧你,改了选项之后的选择题,一定是错的,当我不知道考场潜规则嘛!”我是个经验主义者,对他的话表露出一脸不屑。


“这样吧,蠢货,我换个思路给你讲清楚,总体逻辑其实是一样的。

假设你现在面前有1000扇门,只有一扇门背后藏着奖品,你第一次随便选一个门,然后主持人会帮你在你没选择的999扇门中打开998扇没有奖品的门,现在场上还剩你最初选择的那个门,和主持人帮你排除之后的一个门,你换不换?”

“这个,当然是换的中奖概率更大!但是我们这个玩法好像不太一样吧”我似懂非懂。

“三扇门选择的逻辑也是一样的!只是样本量不同而已!”他扯着嗓子怒吼。

“我就是不信,刚才其实只是运气不好,再来一轮准没问题!”于是,我又一轮坚持自己的选择,又一次与大奖擦肩而过,又一次胸闷,又一次回到了重生点。


“哥,我为什么运气这么差!”我被这突如其来的循环穿越搞的近乎绝望,只想尽快逃出这个鬼循环。

“说白了,你不改变选择,中奖概率只有1/3,一旦改变了选择,中奖概率就会上升到2/3了”他直接抛出了结论,而且语气平和了许多,好像已经习惯了我的脑回路。

看着我紧皱的眉心,他叹了口气:“闭上眼睛吧,我带你到思维的平行世界,用逻辑和Python代码给你演示,演到你服为止”

在我们面前有3个门,大奖藏在某个门背后,我们给大奖所在的门编个号(1号,2号,3号),在1,2,3之间随机生成,生成几就表示大奖在几号门。要让你信服,我们会玩很多轮,所以定义一个函数,默认是生成100轮的正确答案(也就是玩100次)。
#这里我们默认是玩100轮def gen_random(num = 100):    #奖品在1,2,3号门中随机出现    lst = np.random.randint(1,4,size = num)    return lst


  猜法一,坚持最初的选择

猜法一就是盲猜,我们从1,2,3个门中随机猜一个,且不会因为主持人的干扰而改变想法,所以开始猜什么最终也就是什么,猜法一比较简单,我们直接定义一个函数:
#定义基于第一种猜法的函数def guess_one(num = 100):    #生成正确的答案    lst = gen_random(num)    #猜的轮数和前面生成的轮数一致,这里默认玩100次(生成100次正确答案,对应猜100次)    guess = np.random.randint(1,4,size = len(lst))    #计算有多少个正确的,相等即为正确,最终返回FALSE和TRUE的序列    judge = (lst == guess)    #因为TRUE默认是1,FALSE默认是0,我们直接求和,来计算正确率是多少    correct_rate = judge.sum() / len(judge)    print('Bro,这次我们玩%d轮~' % num)    print('在第二次不改变选择的策略下,你最终的中奖率是:%.2f' % (correct_rate * 100))

  猜法二,改变最初的选择 

猜法二,从1,2,3个门中随机猜一个,当主持人打开一个空门,改变最初的选择。

无论我们首次的选择是否中奖,在主持人第一次打开门阶段,我们选择的门不会被打开,背后是大奖的门也不会被打开(有时候可能是同一个)。

先生成数据:
#和上面一样,随机生成100次正确答案lst = gen_random(num)
#第一步,依然是随机猜100次guess = np.random.randint(1,4,size = len(lst))
#因为第二次我们会改变选择,这里创建一个列表来存储我们改变后的最终选择guess_change = []

  • 场景一:我们第一次猜的门没有奖品


如果正确答案和我们第一次猜的不一致,主持人排除掉一个门(空门)之后我们改变选择,最终选的肯定是正确答案。举个栗子:当我们选择的是A门,大奖藏在B门,那主持人帮我们打开的空门一定是C门,然后问我们是否改变选择。如果我们第一步猜的和正确答案不一致,改变选择之后一定会中奖。
#循环遍历每一轮的正确答案和我们第一步猜的结果for anwser,g in zip(lst,guess):    #当答案和我们猜的不一样,那我们改变选择之后就是正确答案    if anwser != g:        guess_change.append(anwser)


  • 场景二:我们第一次就猜对了


当我们猜的门和正确答案一致,主持人随机打开一扇门之后,我们会选择剩下一扇未被打开的空门。

继续举栗子:如果我们猜的A门,大奖就在A门,那么真理既然被我们选中,主持人在没有奖的B和C门中随机打开一扇都可以,然后问我们是否change,要是B门被打开,那么剩下A(我们第一步选择的)和C门,我们改变立场会投向C门的怀抱,结果就是大奖飞走了。



    
#如果我们第一次就猜到正确答案if anwser == g:    #生成一个正确答案的范围    anwser_range = [1,2,3]        #由于我们猜的就是正确答案,先排除掉(因为最后我们会改变选择)    anwser_range.remove(anwser)        #主持人在我们选择之外随机打开一个门    anwser_range.remove(anwser_range[random.randint(0,1)])        #剩下的一个就是我们最终选择的门    guess_change.append(anwser_range[0])

第二个场景我们也可以顺手封装成一个完整函数,这个注释更加完整:
def guess_two(num = 100):    #和上面一样,随机生成100次正确答案    lst = gen_random(num)    #第一步,依然是随机猜100次    guess = np.random.randint(1,4,size = len(lst))    #因为第二次我们会改变选择,这里创建一个列表来存储我们改变后的最终选择    guess_change = []
for anwser,g in zip(lst,guess):
#无论是否中奖,在主持人第一次打开门阶段,我们选择的门不会被打开,背后是大奖的门也不会被打开(有时候可能是同一个) #举个栗子:当我们选择的是A门,大奖藏在B门,那主持人帮我们打开的空门一定是C门,然后问我们是否改变选择 #也就是说,当我们第一步猜的和正确答案不一致,改变选择之后一定会中奖
        #anwser是正确答案,g是我们第一步猜的 if anwser != g: #如果正确答案和我们第一次猜的不一致,主持人排除掉一个门之后我们那改变选择,肯定选的是正确答案——i guess_change.append(anwser)
else: #当我们猜的门和正确答案一致,主持人随机打开一扇门之后,我们会选择剩下的一扇未被打开的空门 #继续举栗子:如果我们猜的A门,大奖就在A门,那么真理既然被我们选中,主持人在没有奖的B和C门中随机打开一扇都可以 #然后问我们是否change,要是B门被打开,那么剩下A(我们第一步选择的)和C门,我们改变立场会转向C门,结果就是大奖飞走了
            anwser_range = [1,2,3] #我们选择的就是正确答案,先排除掉(因为最后我们会改变选择) anwser_range.remove(anwser) #主持人随机打开一个门 anwser_range.remove(anwser_range[random.randint(0,1)])
#剩下的一个就是我们最终选择的门 guess_change.append(anwser_range[0])
#到这一步,我们对刚才改变选择之后的结果进行汇总    guess_change = np.array(guess_change) #看看猜对了多少轮    judge = (lst == guess_change) #正确率是多少     correct_rate = judge.sum() / len(judge) print('Bro,这次我们玩%d轮~' % num) print('在第二次改变选择的策略下,你最终的中奖率是:%.2f' % (correct_rate * 100))

接下来,每种猜法分别玩10,100,1000直到1000万次。

猜法一:


猜法二:


坚持选择,获奖概率最终会稳定在33%,改变选择,最终会稳定在66%。在铁一般的事实面前,我完全信服了。

看着我错愕的眼神,他切掉了这个平行世界的代码界面,消失前脸上露出了一副“聪明人的快乐,就是这么朴实无华且枯燥”的表情。

聚光灯又一次打在我的身上,耳畔再次响起了主持人性感的声音:“先生,您是否改变最初的选择”。


已经记不清第一步是谁做出的选择,也不知道选的什么门,但是笃定的喊道:“改就完事儿了!

最终选择的门缓缓打开,大奖藏在其后!5000万!!!

在全场的欢呼声中,凭着我丰富的韭菜经验,一瞬间便规划好了理财方针:

  • 5000万的大奖,先交税,再花1000万成立程序猿不加班基金会

  • 1000万投P2P,保守估计15%的年化,一年光利息都有150万进账

  • 接着,1000万梭哈比特币,此币作为传家宝代代相传,价值不可估量

  • 最后,剩下的...


话音未落,眼前一黑。


我,大奖得主,韭菜大拿,不知道被谁挤下线了...



相关文章推荐

喜欢这样"文理兼下"来博君一笑的故事吗?来看看一个优秀的程序小哥坎坷的爱情之路吧。

点击蓝字标题,即可阅读数据科学 | 用爬虫辅助七夕剁手的正确姿势:要分步哦


其它

【数据科学】公交车总迟到?你大概掉进了“等待时间悖论

数据科学】实锤!用python扒一扒那些疯狂收割着大家的智商税的“烂片”和“艺人”



关于本文责编





温馨提示

可以在 公众号后台 回复关键词:“ 智能优化电子书 获得该专题负责人微信号。我们将择日聚集对该专题感兴趣的原创者们和相关责任编辑进行创作讨论,力争让每位原创作者能够有机会负责自己擅长和感兴趣的内容~

如果觉得有用, 请勿吝啬你的留言和赞哦!~


—— 完 ——



文章申明

Nov2019

文章作者:吹牛Z(公众号:数据不吹牛)

责任编辑:Mk

审核编辑:阿春

微信编辑:葡萄

文章转自公众号 数据不吹牛(ID:shujubuchuiniu),原文链接:三门悖论 | Python告诉你,为什么坚持不一定是对的



Python社区是高质量的Python/Django开发社区
本文地址:http://www.python88.com/topic/49782
 
300 次点击