我理解问题标题含糊不清。我很抱歉。我有一个具有键的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
旁边有1
,NP F
有1
在它旁边,概率比为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
个元素。
答案 0 :(得分:0)
所以我解决这个问题的方法是创建一个范围从0
到total 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]