假设有一个概率列表:
P = [0.10, 0.25, 0.60, 0.05]
我可以确保P中所有变量的总和始终为1。
如何编写一个函数,根据列表中的值随机返回一个有效索引?换句话说,在这种特定输入情况下,我希望它返回0
的概率为10%,返回1
的概率为25%,返回2
的概率为60%,返回3
的概率为5%。
假设有一个概率列表:
P = [0.10, 0.25, 0.60, 0.05]
我可以确保P中所有变量的总和始终为1。
如何编写一个函数,根据列表中的值随机返回一个有效索引?换句话说,在这种特定输入情况下,我希望它返回0
的概率为10%,返回1
的概率为25%,返回2
的概率为60%,返回3
的概率为5%。
你可以通过numpy轻松实现这一点。它有一个choice函数,接受概率参数。
np.random.choice(
['pooh', 'rabbit', 'piglet', 'Christopher'],
5,
p=[0.5, 0.1, 0.1, 0.3]
)
numpy
有些过头了,特别是如果脚本除了标准库之外没有其他依赖。 - salezicafrom bisect import bisect
from random import random
P = [0.10,0.25,0.60,0.05]
cdf = [P[0]]
for i in xrange(1, len(P)):
cdf.append(cdf[-1] + P[i])
random_ind = bisect(cdf,random())
rs = [bisect(cdf, random()) for i in xrange(20)]
产出
[2, 2, 3, 2, 2, 1, 2, 2, 2, 1, 2, 1, 2, 1, 2, 1, 2, 2, 2, 2]
(结果将会有所不同,这是正常的)。当然,对于可能索引如此之少的情况,二分搜索相当不必要,但对于可能索引更多的情况则绝对是推荐使用的。
嗯,有趣,那怎么样...
生成一个0到1之间的数字。
遍历列表,用每个项目的概率减去你的数字。
选择在减法后将你的数字降至0或以下的项目。
这很简单,是O(n)的,应该能够工作 :)
import numpy as np
pvals = [0.10,0.25,0.60,0.05]
ind = np.where(np.random.multinomial(1,pvals))[0][0]
import random
probs = [0.1, 0.25, 0.6, 0.05]
r = random.random()
index = 0
while(r >= 0 and index < len(probs)):
r -= probs[index]
index += 1
print index - 1
从Python 3.6 开始,random
模块中有一个名为 choices
的方法(注意末尾的 's')。
引用官方文档:
random.choices(population, weights=None, *, cum_weights=None, k=1) 返回从总体中带有重复的 k 个元素的列表
因此,解决方案如下:
>> choices(['option1', 'option2', 'option3', 'option4'], [0.10, 0.25, 0.60, 0.05])
random.choices
(注意末尾的's')可以允许提交相对权重。 - Nickrandom.choices
的信息编辑到顶部回答中会更好,因为接口基本相同。 - Karl Knechtel