【发布时间】:2012-10-14 09:50:18
【问题描述】:
我正在寻找一个函数 weighted_sample 的合理定义,它不会只返回给定权重列表的一个随机索引(类似于
def weighted_choice(weights, random=random):
""" Given a list of weights [w_0, w_1, ..., w_n-1],
return an index i in range(n) with probability proportional to w_i. """
rnd = random.random() * sum(weights)
for i, w in enumerate(weights):
if w<0:
raise ValueError("Negative weight encountered.")
rnd -= w
if rnd < 0:
return i
raise ValueError("Sum of weights is not positive")
给出一个具有恒定权重的分类分布)但是其中的k 的随机样本,没有替换,就像random.sample 与random.choice 相比的行为。
正如weighted_choice可以写成
lambda weights: random.choice([val for val, cnt in enumerate(weights)
for i in range(cnt)])
weighted_sample 可以写成
lambda weights, k: random.sample([val for val, cnt in enumerate(weights)
for i in range(cnt)], k)
但我想要一个不需要我将权重分解为(可能很大)列表的解决方案。
编辑:如果有任何不错的算法可以返回直方图/频率列表(与参数weights 格式相同)而不是索引序列,那也将非常有用。
【问题讨论】:
-
谢谢,“堆”解决方案除了我正在寻找的一个小修改之外。 (我仍然需要正确理解它,但是在将
h[i].w = 0替换为h[i][2] -= 1和相关内容之后,这看起来不错。) -
相关:Data structure for loaded dice?。它提到了 O(n) 初始化,然后是每个骰子方法 O(1)。
-
@JFSebastian:只是远程相关,因为这里的重点是我正在寻找一个权重每一步都改变的解决方案,因为我“在绘制 没有 替换”,因此每个时间步都需要重新初始化数据结构,其中一个权重下降了一个。 (如果您知道如何使问题更清楚,请编辑。)