python - 有没有循环的 Monty Hall 问题的 Pandas/Numpy 实现?
问题描述
这更像是一种好奇心练习......
如果您还没有听说过蒙蒂霍尔问题,可以在这个很棒的youtube 视频中解释它。
我使用 numpy 在 python 中模拟了它:
import numpy as np
num_games = 100000
options = np.arange(1, 4, 1)
stick_result = 0
switch_result = 0
for i in range(1, num_games + 1):
winning_door = np.random.randint(1, 4)
first_choice = np.random.randint(1, 4)
if winning_door == first_choice:
stick_success += 1
# remove a door that isn't the winning_door or the first_choice
door_to_remove = np.random.choice(options[~np.isin(options, [winning_door, first_choice])])
options_with_one_door_removed = options[~np.isin(options, door_to_remove)]
# switch door to remaining option that isn't the first choice
second_choice_after_switch = options_with_one_door_removed[~np.isin(options_with_one_door_removed, first_choice)]
if winning_door == second_choice_after_switch:
switch_result += 1
这是否可以在没有 for 循环的情况下完成?这是我到目前为止所拥有的,但我不确定如何进行门切换。
import numpy as np
num_games = 100000
options = np.arange(1, 4, 1)
winning_door = np.random.randint(1, 4, num_games)
first_choice = np.random.randint(1, 4, num_games)
stick_successes = (winning_door == first_choice).sum()
# remove a door that isn't the winning_door or the first_choice
door_to_remove = ???
options_with_one_door_removed = ???
# switch door to remaining option that isn't the first choice
second_choice_after_switch = ???
switch_successes = (winning_door == second_choice_after_switch).sum()
您必须确定游戏节目主持人从游戏的每个实例中移除哪扇门(winning_door
&first_choice
数组的每一行),然后将其切换first_choice
到剩余的另一扇门。)
有任何想法吗?
解决方案
您最大的问题是choice
使用蒙版进行矢量化。这可能看起来像:
def take_masked_along_axis(arr, where, index, axis):
""" Take the index'th non-masked element along each 1d slice along axis """
assert where.dtype == bool
assert index.shape[axis] == 1
# np.searchsorted would be faster, but does not vectorize
unmasked_index = (where.cumsum(axis=axis) > index).argmax(axis=axis)
unmasked_index = np.expand_dims(unmasked_index, axis=axis) # workaround for argmax having no keepdims
return np.take_along_axis(arr, unmasked_index, axis=axis)
def random_choice_masked_along_axis(arr, where, axis):
""" Like the above, but choose the indices via a uniform random number """
assert where.dtype == bool
index = np.random.sample(arr.shape[:axis] + (1,) + arr.shape[axis+1:]) * where.sum(axis=axis, keepdims=True)
return take_masked_along_axis(arr, where, index, axis=axis)
使代码的第一部分类似于
options_broadcast = np.broadcast_to(options, (3, num_games))
removable = (options != options_broadcast) & (options != options_broadcast)
door_to_remove = random_choice_masked_along_axis(options_broadcast, where=removable, axis=0)
推荐阅读
- karate - 空手道 - 有没有办法将字符串与字符串列表匹配?
- javascript - 解释剪贴板中的 html 代码并将其粘贴到 html 视图格式中
- apache-flink - 如何通过检测组的第一条消息将消息组分配给窗口?
- c# - 具有相同内容,不同绑定的 WPF tabitems
- java - 增加子序列递归Java
- php - 我如何自定义重置密码验证消息以及表单验证?
- android - 是否可以为 aar 文件(如 apk)创建符号?
- angular - 垫表数据刷新
- javascript - for 循环第二次单击 Dom 元素在 puppeteer 中不起作用
- ios - 如何将拖动事件传递给其他视图