7

私は要素確率の配列を持っています[0.1, 0.2, 0.5, 0.2]。配列の合計は 1.0 になります。

プレーンな Python または numpy を使用して、確率に比例して要素を描画したいと思います。最初の要素は約 10%、2 番目の要素は 20%、3 番目の要素は 50% などです。「描画」は、描画された要素のインデックスを返す必要があります。

私はこれを思いついた:

def draw(probs):
    cumsum = numpy.cumsum(probs / sum(probs)) # sum up to 1.0, just in case
    return len(numpy.where(numpy.random.rand() >= cumsum)[0])

うまくいきますが、複雑すぎます。もっと良い方法があるはずです。ありがとう。

4

5 に答える 5

9
import numpy as np
def random_pick(choices, probs):
    '''
    >>> a = ['Hit', 'Out']
    >>> b = [.3, .7]
    >>> random_pick(a,b)
    '''
    cutoffs = np.cumsum(probs)
    idx = cutoffs.searchsorted(np.random.uniform(0, cutoffs[-1]))
    return choices[idx]

使い方:

In [22]: import numpy as np
In [23]: probs = [0.1, 0.2, 0.5, 0.2]

累積和を計算します。

In [24]: cutoffs = np.cumsum(probs)
In [25]: cutoffs
Out[25]: array([ 0.1,  0.3,  0.8,  1. ])

半開区間 で一様分布乱数を計算します[0, cutoffs[-1])

In [26]: np.random.uniform(0, cutoffs[-1])
Out[26]: 0.9723114393023948

searchsortedを使用して、乱数が挿入されるインデックスを見つけますcutoffs

In [27]: cutoffs.searchsorted(0.9723114393023948)
Out[27]: 3

choices[idx]を返しidxます。 はそのインデックスです。

于 2012-01-23T14:45:57.830 に答える
4

numpy で実装されていないカテゴリ分布からサンプリングしたい。ただし、多項分布はカテゴリ分布の一般化であり、その目的に使用できます。

>>> import numpy as np
>>> 
>>> def sampleCategory(p):
...     return np.flatnonzero( np.random.multinomial(1,p,1) )[0]
... 
>>> sampleCategory( [0.1,0.5,0.4] )
1
于 2012-09-07T14:53:09.887 に答える
0

numpy を使用したことはありませんが、以下のコード (python のみ) は、1 行で達成したことと同じことを行うと思います。あなたがそれを望む場合に備えて、私はここに置いています。

非常に c-ish に見えるので、非常に Pythonic ではないことをお詫びします。

weight_total は 1 になります。

def draw(probs)
    r = random.randrange(weight_total)
    running_total = 0
    for i, p in enumerate(probs)
        running_total += p
        if running_total > r:
            return i
于 2012-01-23T14:59:52.623 に答える
0

二分する

import bisect
import random
import numpy 
def draw(probs):
    cumsum=numpy.cumsum(probs/sum(probs))
    return bisect.bisect_left(cumsum, numpy.random.rand())

トリックを行う必要があります。

于 2012-01-23T17:12:42.007 に答える