web-dev-qa-db-ja.com

SciPyまたはNumPyを使用して指定された重みで離散確率変数を生成する

対応する(指定された)確率に基づいて指定されたランダムな値の配列を生成できる単純な関数を探しています。 float値を生成するためにのみ必要ですが、なぜスカラーを生成できないのかわかりません。既存の関数からこれを構築する多くの方法を考えることができますが、おそらく明らかなSciPyまたはNumPy関数を見逃したと思います。

例えば。:

>>> values = [1.1, 2.2, 3.3]
>>> probabilities = [0.2, 0.5, 0.3]
>>> print some_function(values, probabilities, size=10)
(2.2, 1.1, 3.3, 3.3, 2.2, 2.2, 1.1, 2.2, 3.3, 2.2)

注:scipy.stats.rv_discreteが見つかりましたが、その仕組みがわかりません。具体的には、これ(以下)が何を意味するのか、何をすべきかがわかりません。

numargs = generic.numargs
[ <shape(s)> ] = ['Replace with resonable value', ]*numargs

Rv_discreteを使用する必要がある場合、簡単な例と上記の「形状」ステートメントの説明を教えてください。

41
TimY

離散分布からの描画は、numpyに直接組み込まれます。この関数は random.choice (numpyドキュメントの離散分布を参照せずに見つけるのが難しい)と呼ばれます。

elements = [1.1, 2.2, 3.3]
probabilities = [0.2, 0.5, 0.3]
np.random.choice(elements, 10, p=probabilities)
56
goebbe

これは、NumPyのdigitizeaccumulate、およびrandom_sampleを使用する、重み付けされた値を返す、短くて比較的単純な関数です。

import numpy as np
from numpy.random import random_sample

def weighted_values(values, probabilities, size):
    bins = np.add.accumulate(probabilities)
    return values[np.digitize(random_sample(size), bins)]

values = np.array([1.1, 2.2, 3.3])
probabilities = np.array([0.2, 0.5, 0.3])

print weighted_values(values, probabilities, 10)
#Sample output:
[ 2.2  2.2  1.1  2.2  2.2  3.3  3.3  2.2  3.3  3.3]

それはこのように動作します:

  1. 最初にaccumulateを使用して、ビンを作成します。
  2. 次に、0を使用して、一連の乱数(1random_sampleの間)を作成します
  3. digitizeを使用して、これらの数値がどのビンに入るかを確認します。
  4. そして、対応する値を返します。
25
fraxel

あなたは良い方向に向かっていました:組み込みのscipy.stats.rv_discrete()は離散確率変数を全く直接作成します。仕組みは次のとおりです。

_>>> from scipy.stats import rv_discrete  

>>> values = numpy.array([1.1, 2.2, 3.3])
>>> probabilities = [0.2, 0.5, 0.3]

>>> distrib = rv_discrete(values=(range(len(values)), probabilities))  # This defines a Scipy probability distribution

>>> distrib.rvs(size=10)  # 10 samples from range(len(values))
array([1, 2, 0, 2, 2, 0, 2, 1, 0, 2])

>>> values[_]  # Conversion to specific discrete values (the fact that values is a NumPy array is used for the indexing)
[2.2, 3.3, 1.1, 3.3, 3.3, 1.1, 3.3, 2.2, 1.1, 3.3]
_

したがって、上記の分布distribは、valuesリストからindexesを返します。

より一般的には、rv_discrete()values=(…,…)引数の最初の要素でinteger値のシーケンスを取り、この場合これらの値を返します。特定の(浮動)値に変換する必要はありません。以下に例を示します。

_>>> values = [10, 20, 30]
>>> probabilities = [0.2, 0.5, 0.3]
>>> distrib = rv_discrete(values=(values, probabilities))
>>> distrib.rvs(size=10)
array([20, 20, 20, 20, 20, 20, 20, 30, 20, 20])
_

ここで、(整数)入力値は目的の確率で直接返されます。

15
Eric O Lebigot

Lea 、純粋なPython離散確率分布専用のパッケージ)を使用することもできます。

>>> distrib = Lea.fromValFreqs((1.1,2),(2.2,5),(3.3,3))
>>> distrib
1.1 : 2/10
2.2 : 5/10
3.3 : 3/10
>>> distrib.random(10)
(2.2, 2.2, 1.1, 2.2, 2.2, 2.2, 1.1, 3.3, 1.1, 3.3)

ほら!

4
Pierre Denis

最も簡単なDIYの方法は、確率を累積分布にまとめることです。この方法では、ユニット間隔を元の確率に等しい長さのサブ間隔に分割します。ここで、[0,1)で一様な単一の乱数を生成し、どの間隔で着陸するかを確認します。

3
ev-br