2017-01-15 5 views
4

描画された曲線から得られる確率密度関数で乱数を生成したいと考えています。下の2つはカーブの下に同じ領域を持ちますが、異なる特性を持つ乱数のリストを生成する必要があります。任意の確率密度関数から乱数を生成する

enter image description here

私の直感は、一つの方法は、それが曲線をサンプリングして、範囲内の通常のランダムを行う範囲を選択するnp.random.choiceを養うために、それらの矩形の領域を使用することで行うことになるということですその長方形の範囲の

enter image description here

これはそれを行うには非常に効率的な方法のように感じることはありません。それを行う "正しい"方法がありますか?

私は実際にそれをやってで亀裂を持っていた:

import matplotlib.pyplot as plt 
import numpy as np 

areas = [4.397498, 4.417111, 4.538467, 4.735034, 4.990129, 5.292455, 5.633938, 
     6.008574, 6.41175, 5.888393, 2.861898, 2.347887, 2.459234, 2.494357, 
     2.502986, 2.511614, 2.520243, 2.528872, 2.537501, 2.546129, 7.223747, 
     7.223747, 2.448148, 1.978746, 1.750221, 1.659351, 1.669999] 
divisons = [0.0, 0.037037, 0.074074, 0.111111, 0.148148, 0.185185, 0.222222, 
      0.259259, 0.296296, 0.333333, 0.37037, 0.407407, 0.444444, 0.481481, 
      0.518519, 0.555556, 0.592593, 0.62963, 0.666667, 0.703704, 0.740741, 
      0.777778, 0.814815, 0.851852, 0.888889, 0.925926, 0.962963, 1.0] 
weights = [a/sum(areas) for a in areas] 
indexes = np.random.choice(range(len(areas)), 50000, p=weights) 
samples = [] 
for i in indexes: 
    samples.append(np.random.uniform(divisons[i], divisons[i+1])) 

binwidth = 0.02 
binSize = np.arange(min(samples), max(samples) + binwidth, binwidth) 
plt.hist(samples, bins=binSize) 
plt.xlim(xmax=1) 
plt.show() 

enter image description here

の方法が動作しているようですが、少し重いです!

+0

を言っていますか?または、実際にカーブ上の点の座標を表す数値を持っていますか? – BrenBarn

+0

どちらでもかまいません。それはイメージファイルである可能性がありますが、描画される可能性が高くなります。タッチスクリーン上のsvgまたは何らかのインキングなもの。 – Ben

+0

SVGはイメージファイルです。それが画面上に描かれている場合、あなたのプログラムはそれにどのようにアクセスしていますか?私は、あなたのプログラムがどのように作られているのかというデータ*フォーマット*が何であるかを尋ねています。 – BrenBarn

答えて

2

rv_continuousscipy.statsです。簡単な方法は、rv_continuousのスプラインのコレクションを使って、それらのpdfの1つを近似することです。実際には、このことでpdfかcdfのどちらかを定義することで擬似乱数を生成することができます。あなたのケースでは

3

ユーザーが引かれたラインを持っているので、ヒストグラムベースのアプローチは間違いなく最も簡単になるように、それはそうです。

しかし、あなたはその分布から乱数を生成しようとしているだけなので、正規化されたy値(すべてのピクセルのy位置を合計し、合計で割る)を以下の関数のprobability_distributionとして直接使うことができますユーザーが描画したピクセル数のサイズの配列を取得するだけです。

from numpy.random import choice 
pde = choice(list_of_candidates, number_of_items_to_pick, p=probability_distribution) 

probability_distribution(正規化された画素のY値)list_of_candidatesのと同じ順序(関連x値)のシーケンスです。キーワードreplace = Falseを使用して、描画されたアイテムが置き換えられないように動作を変更することもできます。

see numpy docs here

これは、あなたが実際にはPDEに一致する乱数を描く、全体PDEが発生していないので、はるかに高速である必要があります。

EDIT:あなたのアップデートは堅実なアプローチのようです。 pdeを生成したい場合は、numba(http://numba.pydata.org)を調べてforループをベクトル化することを検討してください。

関連する問題