2017-04-20 4 views
1

のは、私たちは以下のようなリストを持っていると仮定しましょう:リストの各項目については
特定の確率に従ってリスト内のアイテムを選択する方法は?

list = [[A,10,3],[B,5,2],[C,8,1]] 

ソフトマックスで計算することができ選ばれる可能性があります。例えば最初の要素(A)のために、私たちは持っている:

from math import exp 

A_probability = exp(list[0][2]/list[0][1]/
        (exp(list[0][2]/list[0][1]) + 
         exp(list[1][2]/list[1][1]) + 
         exp(list[2][2]/list[2][1]))) 

をどのようにして、それぞれに計算された確率に従ってランダムにリスト内の項目を選択することができますか?

+1

可能重複http://stackoverflow.com/questions/4113307/pythonic-way-to-select-list-elements-with-different - 確率) – davedwards

+0

numpyを使用しても問題ありませんか? –

答えて

2

リスト内の各インデックス(たとえばdata)に対して、あらかじめ計算された確率リスト(たとえばprobs)があるとします。

また、probsdataは明らかに同じ長さを有していなければならないとprobsのエントリが1に加算非負数でなければなりません。

ランダムルーレットホイールとして知られているprobsに分布に従ってdataのインデックスを選択するニート単純な技術があります。 Pythonでは、私は信じて、これはによってrandを乗じて(1まで追加する必要はありません)非負の重みのリストに一般化することができることをこの

import random 

data = ['A', 'B', 'C', 'D'] 

probs = [0.2, 0.4, 0.3, 0.1] 

def roulette_wheel(probs): 
    rand = random.random() 
    for slot, prob in enumerate(probs): 
     rand -= prob 
     if rand < 0.0: 
      return slot 

ノートのように何とかなります用語sum(weights)。私は信じて、私は最初に、これまでのところ、パスカルのプログラミングについての本でこのかわいいアイデアを見ました。

編集

MadPhysicistは1つが、同じデータから繰り返し描画する必要がある場合、これは多くの効率化を図ることができるcommentで示唆したように。その場合、累積分布関数を事前に計算してから、インデックスのバイナリ検索を実行して、cumulative prob. <= rand ~ U(0, 1)とすることができます。 Pythonでは、これは例えば次のよう

from random import random 
from bisect import bisect_right 


def cdf(probs): 
    cdf = [] 
    total = 0.0 
    for p in probs: 
     total += p 
     cdf.append(total) 
    return cdf 


def roulette_wheel_bisect(cdf): 
    return bisect_right(cdf, random()) 

# compute cdf 
cumsum = cdf(probs) 

# randomly draw 10 indexes 
for i in range(0, 10): 
    print(roulette_wheel_bisect(cumsum)) 

免責条項のように何とかなります:私は貿易によってPythonプログラマじゃないので、上記のコードは一般的な考えを示して必要があります。実用にはあまり強くないかもしれません。可能ならば、よくテストされた標準ライブラリ、例えばnumpyを使用するべきです。

EDIT2

私はちょうどnumpyはあなたが必要な正確に何んnumpy.random.choiceを持っていることを学びました。例:

from numpy import random 

data = ['A', 'B', 'C', 'D'] 
probs = [0.2, 0.4, 0.3, 0.1] 

# randomly draw 10 list elements with replacement 
for i in range(0, 10): 
    print(random.choice(data, p=probs)) 
([異なる確率でリスト要素を選択するためのPython的な方法]の
+2

numpyを使うと、 'probs'を' np.cumsum'で前処理して、結果をバイナリ検索することができます。 –

+0

実際、あなたが気にしないなら、私はそれについての答えを投稿したいと思います。または、あなた自身でそれを含めることができます。 –

+0

@Mad Physicistあなたの答えを投稿してください、私は気にしません。私はPythonのプログラマーではない。ただここでおしゃべりしています:) –

関連する問題