ฉันพยายามเขียนโปรแกรมใน R ที่จำลองตัวเลขสุ่มหลอกจากการแจกจ่ายด้วยฟังก์ชันการแจกแจงสะสม:
โดยที่
ฉันพยายามสุ่มตัวอย่างการแปลงผกผัน แต่การผกผันดูเหมือนจะไม่สามารถแก้ไขได้ ฉันจะดีใจถ้าคุณสามารถแนะนำวิธีแก้ปัญหานี้
ฉันพยายามเขียนโปรแกรมใน R ที่จำลองตัวเลขสุ่มหลอกจากการแจกจ่ายด้วยฟังก์ชันการแจกแจงสะสม:
โดยที่
ฉันพยายามสุ่มตัวอย่างการแปลงผกผัน แต่การผกผันดูเหมือนจะไม่สามารถแก้ไขได้ ฉันจะดีใจถ้าคุณสามารถแนะนำวิธีแก้ปัญหานี้
คำตอบ:
มีวิธีแก้ปัญหาที่ตรงไปตรงมา (และถ้าฉันเพิ่ม, สง่างาม) สำหรับแบบฝึกหัดนี้: ตั้งแต่จะปรากฏขึ้นเหมือนผลิตภัณฑ์ของการแจกแจงการอยู่รอดสอง:
รหัส R ที่เกี่ยวข้องนั้นง่ายอย่างที่ได้รับ
x=pmin(rexp(n,a),rexp(n,b/(p+1))^(1/(p+1))) #simulating an n-sample
และเร็วกว่าการแปลง pdf และการปฏิเสธการปฏิเสธแน่นอน:
> n=1e6
> system.time(results <- Vectorize(simulate,"prob")(runif(n)))
utilisateur système écoulé
89.060 0.072 89.124
> system.time(x <- simuF(n,1,2,3))
utilisateur système écoulé
1.080 0.020 1.103
> system.time(x <- pmin(rexp(n,a),rexp(n,b/(p+1))^(1/(p+1))))
utilisateur système écoulé
0.160 0.000 0.163
ด้วยขนาดที่พอดีอย่างน่าประหลาดใจ:
คุณสามารถแก้ไขการแปลงผกผันเป็นตัวเลขได้เสมอ
ด้านล่างนี้ฉันทำการค้นหาแบบแบ่งส่วนแบบง่ายมาก สำหรับความน่าจะใส่ให้ (ผมใช้ตั้งแต่คุณมีในสูตรของคุณ) ผมเริ่มต้นด้วยและ 1 แล้วฉันเป็นสองเท่าจนกว่า Q สุดท้ายผมซ้ำแบ่งครึ่งช่วงจนกว่าความยาวสั้นกว่าและจุดกลางตอบสนองQ
ECDF เหมาะกับของคุณดีพอสำหรับการเลือกและและมันเร็วพอสมควร คุณสามารถเพิ่มความเร็วได้โดยใช้การปรับให้เหมาะสมของนิวตันแทนการค้นหาแบบแบ่งส่วนอย่างง่าย
aa <- 2
bb <- 1
pp <- 0.1
cdf <- function(x) 1-exp(-aa*x-bb*x^(pp+1)/(pp+1))
simulate <- function(prob,epsilon=1e-5) {
left <- 0
right <- 1
while ( cdf(right) < prob ) right <- 2*right
while ( right-left>epsilon ) {
middle <- mean(c(left,right))
value_middle <- cdf(middle)
if ( value_middle < prob ) left <- middle else right <- middle
}
mean(c(left,right))
}
set.seed(1)
results <- Vectorize(simulate,"prob")(runif(10000))
hist(results)
xx <- seq(0,max(results),by=.01)
plot(ecdf(results))
lines(xx,cdf(xx),col="red")
มีความซับซ้อนค่อนข้างถ้าการแก้ปัญหาโดยตรงโดยการยอมรับ - ปฏิเสธ ก่อนอื่นความแตกต่างอย่างง่ายแสดงให้เห็นว่าไฟล์ pdf ของการแจกแจงคือ
วินาทีตั้งแต่
เรามีขอบเขตบน
ประการที่สามพิจารณาเทอมที่สองในใช้การเปลี่ยนแปลงของตัวแปรคือ1)} จากนั้น
คือ Jacobian แห่งการเปลี่ยนแปลงของตัวแปร ถ้า
ดังนั้นการเรนเดอร์ R ของอัลกอริทึม accept-reject จึงเป็นเช่นนั้น
simuF <- function(a,b,p){
reepeat=TRUE
while (reepeat){
if (runif(1)<.5) x=rexp(1,a) else
x=rexp(1,b/(p+1))^(1/(p+1))
reepeat=(runif(1)>(a+b*x^p)*exp(-a*x-b*x^(p+1)/(p+1))/
(a*exp(-a*x)+b*x^p*exp(-b*x^(p+1)/(p+1))))}
return(x)}
และสำหรับตัวอย่าง n:
simuF <- function(n,a,b,p){
sampl=NULL
while (length(sampl)<n){
x=u=sample(0:1,n,rep=TRUE)
x[u==0]=rexp(sum(u==0),b/(p+1))^(1/(p+1))
x[u==1]=rexp(sum(u==1),a)
sampl=c(sampl,x[runif(n)<(a+b*x^p)*exp(-a*x-b*x^(p+1)/(p+1))/
(a*exp(-a*x)+b*x^p*exp(-b*x^(p+1)/(p+1)))])
}
return(sampl[1:n])}
นี่คือภาพประกอบสำหรับ a = 1, b = 2, p = 3: