Jika saya memahami Anda dengan benar, Anda ingin mengambil sampel nilai dari distribusi multinomial dengan probabilitas sedemikian rupa sehingga , namun Anda ingin distribusinya terpotong sehingga untuk semua .p 1 , ... , p k Σ i x i = n a i ≤ x i ≤ b i x ix1, ... , xkhal1, ... , hlmk∑sayaxsaya= nSebuahsaya≤ xsaya≤ bsayaxsaya
Saya melihat tiga solusi (tidak seindah dalam kasus non-terpotong):
- Terima tolak. Sampel dari multinomial non-terpotong, terima sampel jika sesuai dengan batas pemotongan, jika tidak, tolak dan ulangi prosesnya. Ini cepat, tetapi bisa sangat tidak efisien.
rtrmnomReject <- function(R, n, p, a, b) {
x <- t(rmultinom(R, n, p))
x[apply(a <= x & x <= b, 1, all) & rowSums(x) == n, ]
}
- Simulasi langsung. Sampel dengan cara yang menyerupai proses penghasil data, yaitu sampel marmer tunggal dari guci acak dan ulangi proses ini sampai Anda mencicipi total kelereng, tetapi saat Anda menggunakan jumlah kelereng dari guci tertentu ( sudah sama dengan ) kemudian berhenti menggambar dari guci tersebut. Saya menerapkan ini dalam skrip di bawah ini.x i b inxsayabsaya
# single draw from truncated multinomial with a,b truncation points
rtrmnomDirect <- function(n, p, a, b) {
k <- length(p)
repeat {
pp <- p # reset pp
x <- numeric(k) # reset x
repeat {
if (sum(x<b) == 1) { # if only a single category is left
x[x<b] <- x[x<b] + n-sum(x) # fill this category with reminder
break
}
i <- sample.int(k, 1, prob = pp) # sample x[i]
x[i] <- x[i] + 1
if (x[i] == b[i]) pp[i] <- 0 # if x[i] is filled do
# not sample from it
if (sum(x) == n) break # if we picked n, stop
}
if (all(x >= a)) break # if all x>=a sample is valid
# otherwise reject
}
return(x)
}
- Algoritma Metropolis. Akhirnya, pendekatan ketiga dan paling efisien adalah menggunakan algoritma Metropolis . Algoritma ini diinisialisasi dengan menggunakan simulasi langsung (tetapi dapat diinisialisasi secara berbeda) untuk menggambar sampel pertama . Dalam langkah-langkah berikut secara iteratif: nilai proposal
diterima sebagai dengan probabilitas , jika tidak nilai diambil dalam itu tempatnya, di mana. Sebagai proposal saya menggunakan fungsi yang mengambil nilai dan secara acak membalik dari 0 ke jumlah kasus dan memindahkannya ke kategori lain. y = q ( X i - 1 ) X i f ( y ) / f ( X i - 1 ) X i - 1 f ( x ) ∝ ∏ i p x i i / x i ! q X i - 1X1y= q( Xi - 1)Xsayaf( y) / f( Xi - 1)Xi - 1f( x ) ∝ ∏sayahalxsayasaya/ xsaya!qXi - 1
step
# draw R values
# 'step' parameter defines magnitude of jumps
# for Meteropolis algorithm
# 'init' is a vector of values to start with
rtrmnomMetrop <- function(R, n, p, a, b,
step = 1,
init = rtrmnomDirect(n, p, a, b)) {
k <- length(p)
if (length(a)==1) a <- rep(a, k)
if (length(b)==1) b <- rep(b, k)
# approximate target log-density
lp <- log(p)
lf <- function(x) {
if(any(x < a) || any(x > b) || sum(x) != n)
return(-Inf)
sum(lp*x - lfactorial(x))
}
step <- max(2, step+1)
# proposal function
q <- function(x) {
idx <- sample.int(k, 2)
u <- sample.int(step, 1)-1
x[idx] <- x[idx] + c(-u, u)
x
}
tmp <- init
x <- matrix(nrow = R, ncol = k)
ar <- 0
for (i in 1:R) {
proposal <- q(tmp)
prob <- exp(lf(proposal) - lf(tmp))
if (runif(1) < prob) {
tmp <- proposal
ar <- ar + 1
}
x[i,] <- tmp
}
structure(x, acceptance.rate = ar/R, step = step-1)
}
Algoritme dimulai pada dan kemudian berkeliaran di berbagai wilayah distribusi. Ini jelas lebih cepat daripada yang sebelumnya, tetapi Anda harus ingat bahwa jika Anda akan menggunakannya untuk sampel sejumlah kecil kasus, maka Anda bisa berakhir dengan imbang yang dekat satu sama lain. Masalah lain adalah bahwa Anda perlu memutuskan tentang ukuran, yaitu seberapa besar lompatan yang harus dibuat oleh algoritma - terlalu kecil dapat menyebabkan bergerak lambat, terlalu besar dapat menyebabkan terlalu banyak proposal yang tidak valid dan menolaknya. Anda dapat melihat contoh penggunaannya di bawah ini. Pada plot Anda dapat melihat: kepadatan marginal di baris pertama, traceplots di baris kedua dan plot yang menunjukkan lompatan berikutnya untuk pasangan variabel.X1step
n <- 500
a <- 50
b <- 125
p <- c(1,5,2,4,3)/15
k <- length(p)
x <- rtrmnomMetrop(1e4, n, p, a, b, step = 15)
cmb <- combn(1:k, 2)
par.def <- par(mfrow=c(4,5), mar = c(2,2,2,2))
for (i in 1:k)
hist(x[,i], main = paste0("X",i))
for (i in 1:k)
plot(x[,i], main = paste0("X",i), type = "l", col = "lightblue")
for (i in 1:ncol(cmb))
plot(jitter(x[,cmb[1,i]]), jitter(x[,cmb[2,i]]),
type = "l", main = paste(paste0("X", cmb[,i]), collapse = ":"),
col = "gray")
par(par.def)
Masalah dengan pengambilan sampel dari distribusi ini adalah yang menggambarkan strategi pengambilan sampel yang sangat tidak efisien secara umum. Bayangkan bahwa dan , dan dekat dengan , dalam hal ini Anda ingin sampel ke kategori dengan probabilitas yang berbeda, tetapi berharap serupa frekuensi pada akhirnya. Dalam kasus ekstrem, bayangkan distribusi dua kategori di mana , dan ,a 1 = ⋯ = a k b 1 = ... b k a i b i p 1 » p 2 a 1 « a 2 b 1 « b 2hal1≠ ⋯ ≠ hlmkSebuah1= ⋯ = akb1= ... bkSebuahsayabsayahal1≫ hlm2Sebuah1≪ a2b1≪ b2, dalam kasus seperti itu Anda mengharapkan sesuatu peristiwa yang sangat langka terjadi (contoh kehidupan nyata dari distribusi tersebut adalah peneliti yang mengulangi pengambilan sampel sampai ia menemukan sampel yang konsisten dengan hipotesisnya, sehingga lebih berkaitan dengan kecurangan daripada pengambilan sampel acak) .
Distribusi jauh lebih bermasalah jika Anda mendefinisikannya sebagai Rukhin (2007, 2008) di mana Anda sampel kasus untuk setiap kategori, yaitu sampel secara proporsional ke .p in psayahalsaya
Rukhin, AL (2007). Statistik urutan normal dan jumlah variabel acak geometrik dalam masalah alokasi perawatan. Statistik & surat probabilitas, 77 (12), 1312-1321.
Rukhin, AL (2008). Menghentikan Aturan dalam Masalah Alokasi Seimbang: Distribusi Tepat dan Asimptotik. Analisis Sekuensial, 27 (3), 277-292.
x[i] >= a
. Bayangkan Anda melemparkan koin bias dengan probabilitas kepala = 0,9. Anda melempar koin sampai Anda mendapatkan setidaknya 10 kepala dan 10 ekor. Pada titik berhenti Anda akan memiliki rata-rata lebih banyak kepala daripada ekor. Mulai padax[1] = ... = x[k] = a
berarti Anda mengabaikan fakta bahwa titik awal masing-masingx[i]
berbeda karena berbedap[i]
.Ini adalah usaha saya dalam mencoba menerjemahkan kode R Tim ke Python. Karena saya menghabiskan waktu untuk memahami masalah ini dan mengkodekan algoritme dengan Python, saya berpikir untuk membagikannya di sini kalau-kalau ada orang yang tertarik.
Untuk implementasi lengkap dari kode ini, silakan lihat repositori Github saya di
https://github.com/mohsenkarimzadeh/sampling
sumber