为python

时间:2016-09-19 21:35:12

标签: python probability

我理解问题标题含糊不清。我很抱歉。我有一个具有键的hashmap:value <string>:<list of lists>。对于给定列表,列表中的每个项具有相应的被选择概率。例如,hashmap中的一个项可能看起来像

"NP":[['A', 'B'], ['C', 'D', 'E'], ['F']]

我需要随机选择右侧的一个列表。每个列表都有自己的概率。以下是将在地图中生成上述项目的输入字符串。

3 NP A B
1 NP C D E
1 NP F

由于行NP A B旁边有3行,NP C D E旁边有1NP F1在它旁边,概率比为3:1:1,因此[A, B]有3/5的概率被选中,[C, D, E]有1/5被选中,[F相同。

我的问题是,我如何模拟这些概率?

在引入这些数字之前很简单,因为我可以计算列表的长度(在上面的示例中它将是3)然后选择0到len(list) - 1之间的随机数,包括{{1}然后从列表中选择该索引。为了模拟bernoulli随机变量,我知道可以检查random.randint()。但是只有你有2个案例才有效。我无法显式写if if语句来检查,因为列表可能包含if random.randint() < p个元素。

3 个答案:

答案 0 :(得分:0)

所以我解决这个问题的方法是创建一个范围从0total probability的稀疏表。在你的情况下,那是

0 -> 0
3 -> 1
4 -> 2

然后选择0到4之间的int,并选择最大值&gt; =所选值(换句话说,1映射到0,2映射到0,3映射到1)。价值&#39;在此映射中对应于原始字典中的子列表。那不应该采取任何额外的库。

答案 1 :(得分:0)

如果您的总体重仍然很小,这是一种粗略的方法:

>>> NP = [['A', 'B'], ['C', 'D', 'E'], ['F']]
>>> weights = (3,1,1)
>>> indx_list = [idx for idx,w in zip(range(len(NP)), weights) for _ in range(w)]
>>> indx_list
[0, 0, 0, 1, 2]
>>> import random
>>> random.choice([0, 0, 0, 1, 2])
1
>>> sample = [random.choice([idx for idx,w in zip(range(len(NP)), weights) for _ in range(w)]) for _ in range(1000)]
>>> from collections import Counter
>>> counts = Counter(sample)
>>> counts
Counter({0: 600, 2: 213, 1: 187})

答案 2 :(得分:0)

这是一个使用线性搜索的简单原型。唯一的依赖是 random.random()来获得[0,1)内的浮点数。

尽管采用了未经优化的方法,但在我的电脑上只需要0.25秒即可获得100,000个样本。但请记住,此性能取决于统计/概率向量。也可以通过预先分类来改进代码。

总的说法:检查this

代码

import random

""" Discrete-sampling """
def cum_sum(xs):
    cum_sum = []
    total = 0
    for i in xs:
        total += i
        cum_sum.append(total)
    total_sum = sum(cum_sum)
    return cum_sum, cum_sum[-1]

def discrete_sample(items, probs):
    cum_sum_, max_ = cum_sum(probs)
    random_val = random.random() * max_
    for ind, i in enumerate(items):
        if random_val < cum_sum_[ind]:
            return i
    return items[-1]  # fail-safe

def sample_from_dict(element, data, data_p):
    data_ = data[element]
    data_p_ = data_p[element]
    selection = discrete_sample(range(len(data_)), data_p_)
    return data_[selection]

""" Data """
data = {'NP': [['A', 'B'], ['C', 'D', 'E'], ['F']]}
data_p = {'NP': [3, 1, 1]}

""" Try it """
samples = []
for i in range(100000):
    samples.append(sample_from_dict('NP', data, data_p))

counts = [0, 0, 0]
for i in samples:
    if i == ['A', 'B']:
        counts[0] += 1
    elif i == ['C', 'D', 'E']:
        counts[1] += 1
    elif i == ['F']:
        counts[2] += 1

print(counts)

输出

[60130, 19867, 20003]