任意の離散分布に基づいて数値を生成するにはどうすればよいですか?
たとえば、生成したい数字のセットがあります。次のように1〜3のラベルが付けられているとします。
1:4%、2:50%、3:46%
基本的に、パーセンテージは、乱数ジェネレーターからの出力に現れる確率です。区間[0、1]で均一な分布を生成する疑似乱数ジェネレーターがあります。これを行う方法はありますか?
持つことができる要素の数に制限はありませんが、%は100%になります。
任意の離散分布に基づいて数値を生成するにはどうすればよいですか?
たとえば、生成したい数字のセットがあります。次のように1〜3のラベルが付けられているとします。
1:4%、2:50%、3:46%
基本的に、パーセンテージは、乱数ジェネレーターからの出力に現れる確率です。区間[0、1]で均一な分布を生成する疑似乱数ジェネレーターがあります。これを行う方法はありますか?
持つことができる要素の数に制限はありませんが、%は100%になります。
回答:
離散分布からのサンプリングに最適なアルゴリズムの1つは、エイリアスメソッドです。
エイリアスメソッドは、2次元データ構造を(効率的に)事前計算して、確率に比例する領域に長方形を分割します。
色によって区別されるよう- -参照サイトからこの概略図では、ユニットの高さの矩形領域は4種類に区分された割合で、1 / 3、1 / 12、及び1 / 12、でこれらの確率で離散分布から繰り返しサンプリングするため。垂直ストリップの幅は一定(単位)です。それぞれが1つまたは2つの部分に分割されます。ピースのIDと垂直分割の位置は、列インデックスを介してアクセス可能なテーブルに保存されます。
テーブルは2つの単純なステップ(各座標に1つ)でサンプリングでき、2つの独立した均一値と計算のみを生成する必要があります。これにより、他の応答で説明されているように、離散CDFを反転するために必要なO (log (n ))計算が改善されます。
Rでこれを簡単に行うことができます。必要なサイズを指定するだけです。
sample(x=c(1,2,3), size=1000, replace=TRUE, prob=c(.04,.50,.46))
あなたの例では、疑似ランダムUniform [0,1]値を描画し、それをUと呼びます。次に出力します:
U <0.04の場合は1
U> = 0.04およびU <0.54の場合は2
U> = 0.54の場合は3
指定された%がa、b、...の場合、単に出力
Uの場合、値1
U> = aおよびU <(a + b)の場合、値2
等
基本的に、%を[0,1]のサブセットにマッピングしており、一様なランダム値が任意の範囲に入る確率は、その範囲の長さであることがわかります。範囲を整理することは、一意ではないにしても、最も簡単な方法のようです。これは、離散分布についてのみ質問していることを前提としています。継続的に、「拒否サンプリング」(ウィキペディアエントリ)のようなことができます。
個の個別の結果が考えられます。もし間隔分ける[ 0 、1 ]累積確率質量関数に基づいてサブインターバルに、F、分配与える(0 、1 )間隔を
及びF (0 )≡ 0。あなたの例では、m = 3および
以来、、およびF (2 )= 0.54、およびF (3 )= 1。
次に、次のアルゴリズムを使用して、分布Fでを生成できます。
(1)を生成
(2)もし次に、X = J。
TRUE
FALSE
FALSE
注意正確に一つの間隔になりますIのJ彼らは互いに素とパーティションなので、[ 0 、1 ]。
min(which(u < cp))
? It would be good to avoid recomputing the cumulative sum on each call, too. With that precomputed, the entire algorithm is reduced to min(which(runif(1) < cp))
. Or better, because the OP asks to generate numbers (plural), vectorize it as n<-10; apply(matrix(runif(n),1), 2, function(u) min(which(u < cp)))
.
One simple algorithm is to start with your uniform random number and in a loop first subtract off the first probability, if the result is negative then you return the first value, if still positive then you go to the next iteration and subtract off the next probability, check if negative, etc.
This is nice in that the number of values/probabilities can be infinite but you only need to calculate the probabilities when you get close to those numbers (for something like generating from a Poisson or negative binomial distribution).
If you have a finite set of probabilities, but will be generating many numbers from them then it could be more efficient to sort the probabilities so that you subtract the largest first, then the 2nd largest next and so forth.
First of all, let me draw your attention to a python library with ready-to-use classes for either integer or floating point random number generation that follow arbitrary distribution.
Generally speaking there are several approaches to this problem. Some are linear in time, but require large memory storage, some run in O(n log(n)) time. Some are optimized for integer numbers and some are defined for circular histograms (for example: generating random time spots during a day). In the above mentioned library I used this paper for integer number cases and this recipe for floating point numbers. It (still) lacks circular histogram support and is generally messy, but it works well.
I had the same problem. Given a set where each item has a probability and whose items' probabilities sum up to one, I wanted to draw a sample efficiently, i.e. without sorting anything and without repeatedly iterating over the set.
The following function draws the lowest of uniformly distributed random numbers within the interval . Let be a random number from .
You can use this function to draw an ascending series of uniformly distributed random numbers in [0,1). Here is an example with :
While drawing that ascending series of uniformly distributed numbers, iterate over the set of probabilities which represents your arbitraty (yet finite) distribution. Let be the iterator and . After drawing , increment zero or more times until . Then add to your sample and move on with drawing .
Example with the op's set and sample size :
i a_i k Sum Draw 0 0.031 0 0.04 1 1 0.200 1 0.54 2 2 0.236 1 0.54 2 3 0.402 1 0.54 2 4 0.488 1 0.54 2 5 0.589 2 1.0 3 6 0.625 2 1.0 3 7 0.638 2 1.0 3 8 0.738 2 1.0 3 9 0.942 2 1.0 3
Sample:
If you wonder about the function: It is the inverse of the probability that one of uniformly distributed random numbers lies within the interval with .