【问题标题】:Generating weighted random numbers生成加权随机数
【发布时间】:2013-11-21 04:53:29
【问题描述】:

您好,我正在为基因组学课程编写一些代码,但在某些方面遇到了困难。

我有一组互斥事件 概率

我想以给定的概率模拟随机抽样一个事件 n 次。

输入:概率 = {0.3, 0.2, 0.5} 事件{e1,e2,e3} n=100

输出:e3 应该有 ~50 个结果,e2 应该有 ~20 个结果,e1 应该有 ~30 个结果。 请注意,这些可能不完全是 50、20、30,因为 经验值与理论值不同...

【问题讨论】:

  • 如果 probabilitiesevents 输入确实是两个集合,如您所展示的,则无法将概率与事件匹配。
  • 你只是想生成n 随机数吗?
  • 查看 Eli Bendersky 在 weighted random sampling 上的页面,了解实现这一目标的多种方法。
  • 另见Python issue 18844,其中几个加权选择实现相互测试(预期将其中一个添加到random 模块)。

标签: python random generator


【解决方案1】:

Python 没有内置任何加权采样功能(NumPy/SciPy 有),但对于像这样一个非常简单的情况,这很容易:

import itertools
import random

probabilities = [0.3, 0.2, 0.5]
totals = list(itertools.accumulate(probabilities))

def sample():
    n = random.uniform(0, totals[-1])
    for i, total in enumerate(totals):
        if n <= total:
            return i

如果你没有 Python 3.2+,你就没有accumulate 函数;如果列表真的这么短,你可以用低效的单行来伪造它:

totals = [sum(probabilities[:i+1]) for i in range(len(probabilities))]

…或者你可以写一个显式循环,或者一个丑陋的reduce调用,或者从the docs复制等效的Python函数。


另外,请注意 random.uniform(0, totals[-1]) 只是写 random.random() 的一种更复杂的方式,如果你可以确定你的数字加起来等于 1.0。


一种快速测试方法:

>>> samples = [sample() for _ in range(100000)]
>>> samples.count(0)
29878
>>> samples.count(1)
19908
>>> samples.count(2)
50214

它们分别非常接近 100000 的 30%、20% 和 50%。

【讨论】:

  • 我试过这个,但它总是给出最后一个词的索引。这是为什么呢?
  • @user2812970:我只是将它复制并粘贴到我的解释器中(并添加了缺少的import random)并运行了 100K 次来测试它,它只给出了上一学期的地址大约一半时间,正是它应该的。我已经编辑了答案以显示测试。如果它真的总是给你2,要么你粘贴错了,要么你在代码的其他部分做错了,或者你应该立即去维加斯利用你的突变概率影响能力. :)
【解决方案2】:

假设我们有三个事件,每个事件的概率分别为 0.3、0.2 和 0.5。然后对于生成的每个样本,我们在 [0,1) 范围内生成一个数字,我们称之为“rand”。如果 "rand" random() 来完成,它确实生成了一个数字在 [0,1) 范围内。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-05-01
    • 2010-12-04
    • 2012-09-13
    • 1970-01-01
    • 2020-03-14
    • 2014-07-16
    • 2022-07-06
    • 1970-01-01
    相关资源
    最近更新 更多