• 利用 random 与 tertools 模块解决概率问题


    Python 中的 random 与 tertools 模块可以得到伪随机数与排列、组合,下面利用这两个模块求解一些有趣的概率问题。

    一、random 与 tertools 模块

    random 模块常用函数:

    • random():返回一个位于区间 [0,1] 内的实数;
    • uniform(a, b):返回一个位于区间 [a,b] 内的实数;
    • randint(a, b):返回一个位于区间 [a,b] 内的整数;
    • choice(sequence):返回一个位于 sequence 中的元素,其中,sequence 为一个有序序列,如 list、string 或者 tuple 等类型;
    • randrange([start], stop[, step]):等效于 choice(range([start], stop[, step]))
    • shuffle(sequence [, random]):无返回值,用于打乱 sequence 中元素的排列顺序;
    • sample(sequence, n):返回一个由 n 个 sequence 中的元素组成的分片,其中,sequence 也可以是 set 类型。

    itertools 模块常用函数:

    • permutations(sequence, k)):从序列 sequence 中得到包含 k 个元素的所有排列。
    • combinations(sequence, k)):从序列 sequence 中得到包含 k 个元素的所有组合。

    二、概率趣题

    每当网上有人发布与条件概率悖论相关的帖子时,总会引来无数旁人的围观与争论,五花八门的分析乍看像模像样,实则让人晕头转向。现在我不去理论分析计算,只根据概率论中的 大数定律,利用计算机重复模拟事件,最终求出问题的准确答案(尽管有可能自己并不理解背后的道理)。

    1、羊车门问题

    有一个抽奖节目,台上有三扇关闭的门,一扇门后面停着汽车,其余门后都是山羊,只有主持人知道每扇门后面是什么。参赛者可以选择一扇门,在开启它之前,主持人会开启另外一扇门,露出门后的山羊,然后允许参赛者更换自己的选择。问题是:参赛者更换选择后能否增加赢得汽车的机会?

    该问题的 Python 3.x 解答程序如下:

    from random import *
    
    def once(doors = 3):		# 一次事件的模拟
    	car = randrange(doors)	# 一扇门后面停着汽车
    	man = randrange(doors)	# 参赛者预先选择一扇门
    	return car == man	# 参赛者是否最初就选择到车
    
    h = 0	# 坚持选择赢得汽车的次数                    
    c = 0	# 改变选择赢得汽车的次数 
    times = int(1e6) # 重复实验的次数
    
    for i in range(times): 
    	if once():	h += 1
    	else:		c += 1
    
    print("维持选择:",h/times*100,"%
    改变选择:",c/times*100,"%")
    

    维持选择: 33.268 %
    改变选择: 66.732 %
    

    2、姊妹花

    一个家庭中有两个小孩,已知其中一个是女孩,求另一个小孩也是女孩的概率。

    from random import * # 0 表示女孩,1 表示男孩
    
    family = (lambda n :[{randrange(2),randrange(2)} for i in range(n)])(int(1e6))
    
    both = family.count({0})                # 都是女孩的家庭数
    exist = len(family) - family.count({1}) # 有女孩的家庭数
    
    print(both/exist)
    

    0.33332221770186543
    

    没有那些深奥的分析过程,寥寥数行代码就得到了问题的答案,想必这也是计算机引入数学计算与证明的好处。

    3、生日悖论

    每个人都有生日,偶尔会遇到与自己同一天过生日的人,但在生活中这种缘分似乎并不常有。我们猜猜看:在 50 个人当中出现这种缘分的概率有多大,是 10%、20% 还是 50%?

    from random import *
    
    counter, times = 0, int(1e6)
    for i in range(times):
    	if len({randrange(365) for i in range(50)}) != 50: # 存在同一天生日的人
    		counter += 1
    
    print('在 50 个人中有相同生日的概率为:',counter/times)
    

    在 50 个人中有相同生日的概率为: 0.970109
    

    在 50 个人中有相同生日的概率高达 97%,这个数字恐怕高出了绝大多数人的意料。我们没有算错,是我们的直觉错了,科学与生活又开了个玩笑。正因为计算结果与日常经验产生了如此明显的矛盾,该问题被称为「生日悖论」,它体现的是理性计算与感性认识的矛盾。

    4、扑克牌问题

    概率论给我们带来了很多匪夷所思的反常结果,条件概率尤其如此。譬如:

    1. 四个人打扑克,其中一个人说,我手上有一个 A。请问他手上有不止一个 A 的概率是多少?
    2. 四个人打扑克,其中一个人说,我手上有一个黑桃 A。请问他手上有不止一个 A 的概率又是多少?
    from random import *
    
    cards = [i for i in range(52)]
    counter = [0, 0, 0, 0]
    
    def once():           # 0 表示黑桃 A
    	global cards
    	ace = set(sample(cards, 13)) & {0,1,2,3}
    	return len(ace), 0 in ace
    
    for i in range(int(1e6)):
    	a, s = once() # a 表示 A 的个数, s 表示是否有黑桃 A
    	if a:
    		counter[1] += 1
    		if s:	counter[3] += 1
    	if a > 1:
    		counter[0] += 1
    		if s:	counter[2] += 1
    
    print('情况一:', counter[0]/counter[1], '
    情况二:', counter[2]/counter[3])
    

    情况一: 0.3694922900321386 
    情况二: 0.5613778028656186
    

    有趣的事情出来了:如果这个人宣布了手中 A 的花色,他手中持有多个 A 的概率竟然会大大增加。可这又该如何理解呢?

  • 相关阅读:
    LR和SVM的相同和不同
    Logistic Regression理论总结
    LibSVM源码剖析(java版)
    CTR预估中的贝叶斯平滑方法(二)参数估计和代码实现
    支持向量机(SVM)中的 SMO算法
    《这就是搜索引擎》框架图
    Leetcode 初刷(1)
    tf中softmax_cross_entropy_with_logits与sparse_softmax_cross_entropy_with_logits
    python 判断是否为中文
    sklearn使用小记GridSearchCV
  • 原文地址:https://www.cnblogs.com/Pandaman/p/random-itertools.html
Copyright © 2020-2023  润新知