Bagaimana cara menghasilkan angka berdasarkan distribusi diskret arbitrer?
Misalnya, saya memiliki satu set angka yang ingin saya hasilkan. Katakanlah mereka diberi label dari 1-3 sebagai berikut.
1: 4%, 2: 50%, 3: 46%
Pada dasarnya, persentase adalah probabilitas bahwa mereka akan muncul di output dari generator nomor acak. Saya memiliki generator nomor acak yang akan menghasilkan distribusi seragam dalam interval [0, 1]. Apakah ada cara untuk melakukan ini?
Tidak ada batasan berapa banyak elemen yang bisa saya miliki, tetapi% akan bertambah hingga 100%.
distributions
FurtiveFelon
sumber
sumber
Jawaban:
Salah satu algoritma terbaik untuk pengambilan sampel dari distribusi diskrit adalah metode alias .
Metode alias (efisien) mengkompilasi struktur data dua dimensi untuk mempartisi persegi panjang ke dalam area yang proporsional dengan probabilitas.
Dalam skema ini dari situs direferensikan, persegi panjang dengan tinggi Unit telah dipartisi menjadi empat macam daerah - sebagai dibedakan oleh warna - dalam proporsi , 1 / 3 , 1 / 12 , dan 1 / 12 , di memesan sampel berulang kali dari distribusi diskrit dengan probabilitas ini. Strip vertikal memiliki lebar (unit) konstan. Masing-masing dibagi menjadi satu atau dua potong. Identitas potongan dan lokasi divisi vertikal disimpan dalam tabel yang dapat diakses melalui indeks kolom.1/2 1/3 1/12 1/12
Tabel dapat disampel dalam dua langkah sederhana (satu untuk setiap koordinat) yang membutuhkan hanya menghasilkan dua nilai seragam independen dan perhitungan . Ini meningkatkan pada perhitungan O ( log ( n ) ) yang diperlukan untuk membalikkan CDF diskrit seperti yang dijelaskan dalam balasan lain di sini.O(1) O(log(n))
sumber
Anda dapat melakukan ini dengan mudah di R, cukup tentukan ukuran yang Anda butuhkan:
sumber
Dalam contoh Anda, katakan Anda menggambar nilai Seragam pseudorandom Anda [0,1] dan menyebutnya U. Kemudian keluaran:
1 jika U <0,04
2 jika U> = 0,04 dan U <0,54
3 jika U> = 0,54
Jika% yang ditentukan adalah a, b, ..., cukup keluaran
nilai 1 jika U
nilai 2 jika U> = a dan U <(a + b)
dll.
Pada dasarnya, kami memetakan% ke dalam himpunan bagian dari [0,1], dan kami tahu probabilitas bahwa nilai acak seragam jatuh ke dalam rentang apa pun hanya panjang rentang itu. Menempatkan rentang dalam urutan tampaknya cara paling sederhana, jika tidak unik, untuk melakukannya. Ini dengan asumsi bahwa Anda hanya bertanya tentang distribusi diskrit; untuk yang berkelanjutan, dapat melakukan sesuatu seperti "sampel penolakan" ( entri Wikipedia ).
sumber
Misalkan ada hasil yang mungkin diskrit. Anda membagi interval [ 0 , 1 ] ke dalam sub-terminal berdasarkan pada fungsi massa probabilitas kumulatif, F , untuk memberikan interval yang dipartisi ( 0 , 1 )m [0,1] F (0,1)
di mana dan F ( 0 ) ≡ 0 . Dalam contoh Anda m = 3 danIj=(F(j−1),F(j)) F(0)≡0 m=3
karena dan F ( 2 ) = .54 dan F ( 3 ) = 1 .F(1)=.04 F(2)=.54 F(3)=1
Kemudian Anda dapat menghasilkan dengan distribusi F menggunakan algoritma berikut:X F
(1) menghasilkanU∼Uniform(0,1)
(2) Jika , maka X = j .U∈Ij X=j
TRUE
FALSE
FALSE
Perhatikan bahwa akan berada tepat pada salah satu interval I j karena mereka terpisah dan partisi [ 0 , 1 ] .U Ij [0,1]
sumber
min(which(u < cp))
? Sebaiknya hindari menghitung ulang jumlah kumulatif pada setiap panggilan juga. Dengan perhitungan itu, seluruh algoritma dikurangi menjadimin(which(runif(1) < cp))
. Atau lebih baik, karena OP meminta untuk menghasilkan angka ( jamak ), vektorkan sebagain<-10; apply(matrix(runif(n),1), 2, function(u) min(which(u < cp)))
.Salah satu algoritma sederhana adalah mulai dengan nomor acak seragam Anda dan dalam satu lingkaran pertama kurangi probabilitas pertama, jika hasilnya negatif maka Anda mengembalikan nilai pertama, jika masih positif maka Anda pergi ke iterasi berikutnya dan kurangi probabilitas berikutnya , periksa apakah negatif, dll.
Ini bagus karena jumlah nilai / probabilitas bisa tak terbatas tetapi Anda hanya perlu menghitung probabilitas ketika Anda mendekati angka-angka itu (untuk sesuatu seperti menghasilkan dari Poisson atau distribusi binomial negatif).
Jika Anda memiliki serangkaian probabilitas terbatas, tetapi akan menghasilkan banyak angka dari mereka maka akan lebih efisien untuk mengurutkan probabilitas sehingga Anda mengurangi yang pertama, kemudian yang ke-2 berikutnya dan seterusnya.
sumber
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.
sumber
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 ofN uniformly distributed random numbers within the interval [a,1) . Let r be a random number from [0,1) .
You can use this function to draw an ascending series(ai) of N uniformly distributed random numbers in [0,1). Here is an example with N=10 :
While drawing that ascending series(ai) of uniformly distributed numbers, iterate over the set of probabilities P which represents your arbitraty (yet finite) distribution. Let 0≤k<|P| be the iterator and pk∈P . After drawing ai , increment k zero or more times until ∑p0…pk>ai . Then add pk to your sample and move on with drawing ai+1 .
Example with the op's set{(1,0.04),(2,0.5),(3,0.46)} and sample size N=10 :
Sample:(1,2,2,2,2,3,3,3,3,3)
If you wonder about thenext function: It is the inverse of the probability that one of N uniformly distributed random numbers lies within the interval [a,x) with x≤1 .
sumber