weighted_sample
与えられた重みのリストに対してランダムなインデックスを1つだけ返さない関数の合理的な定義を探しています(これは次のようになります)
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
、それも非常に便利です。