আমি এখানে বর্ণিত নীল অঞ্চল থেকে নমুনা তৈরি করতে চাই:
সাদাসিধা সমাধান ইউনিট স্কোয়ারে প্রত্যাখ্যান স্যাম্পলিং ব্যবহার করতে হয়, কিন্তু এই শুধুমাত্র একটি উপলব্ধ (~ 21.4%) দক্ষতা।
আমি আরও দক্ষতার সাথে নমুনা দেওয়ার কোন উপায় আছে?
আমি এখানে বর্ণিত নীল অঞ্চল থেকে নমুনা তৈরি করতে চাই:
সাদাসিধা সমাধান ইউনিট স্কোয়ারে প্রত্যাখ্যান স্যাম্পলিং ব্যবহার করতে হয়, কিন্তু এই শুধুমাত্র একটি উপলব্ধ (~ 21.4%) দক্ষতা।
আমি আরও দক্ষতার সাথে নমুনা দেওয়ার কোন উপায় আছে?
উত্তর:
প্রতি সেকেন্ডে দুই মিলিয়ন পয়েন্ট কি করবে?
বিতরণটি প্রতিসম হয়: আমাদের কেবলমাত্র পুরো বৃত্তের এক-অষ্টমীর জন্য বিতরণ কাজ করা দরকার এবং তারপরে এটি অন্যান্য অক্টেন্টগুলির চারপাশে অনুলিপি করুন। মেরু স্থানাঙ্ক , কোণের ক্রমবর্ধমান বণ্টনের Θ র্যান্ডম অবস্থানের জন্য ( এক্স , ওয়াই ) মূল্য এ θ ত্রিভুজ মধ্যে এলাকায় দেওয়া হয় ( 0 , 0 ) , ( 1 , 0 ) , ( 1 , ট্যান θ ) এবং বৃত্তের চাপটি থেকে প্রসারিত ( থেকে ( কোসাইন্ θ , পাপ θ ) । এটি এর সাথে আনুপাতিক
যেহেতু এর ঘনত্ব
আমরা এই ঘনত্ব থেকে নমুনা বলতে পারি, একটি প্রত্যাখ্যান পদ্ধতি (যা কার্যকারিতা ) ব্যবহার করে।
রশ্মীয় তুল্য এর শর্তাধীন ঘনত্ব সমানুপাতিক দ ঘ R মধ্যে R = 1 এবং দ = সেকেন্ড θ । এটি সিডিএফের একটি সহজ বিপরীতে নমুনা তৈরি করা যেতে পারে।
যদি আমরা স্বতন্ত্র নমুনা উত্পন্ন করি তবে কার্টেসিয়ান স্থানাঙ্কগুলিতে ( x i , y i ) নমুনা এই অকট্যান্টটিতে ফিরে রূপান্তর । নমুনাগুলি স্বতন্ত্র হওয়ায়, স্থানাঙ্কগুলি এলোমেলোভাবে অদলবদল করা হলে ইচ্ছানুসারে প্রথম চতুর্ভুজ থেকে একটি স্বতন্ত্র এলোমেলো নমুনা তৈরি করে। (এলোমেলোভাবে অদলবদলের জন্য কতগুলি বাস্তবায়ন হবে তা নির্ধারণ করতে কেবল একটি একক দ্বিপদী পরিবর্তনশীল তৈরি করতে হবে))
প্রত্যেকটি ধরনের উপলব্ধি , প্রয়োজন গড়, এক অভিন্ন variate উপর (জন্য আর ) প্লাস 1 / ( 8 π - 2 ) বার দুই অভিন্ন (জন্য variates Θ ) এবং (ফাস্ট) হিসাব অল্প পরিমাণ। এটা 4 / ( π - 4 ) ≈ 4.66 পয়েন্ট (যা, অবশ্যই, দুই স্থানাঙ্ক আছে) প্রতি variates। সম্পূর্ণ বিশদটি নীচের কোড উদাহরণে রয়েছে। এই চিত্রটি অর্ধ মিলিয়ন পয়েন্টের মধ্যে 10,000 টিরও বেশি প্লট করেছে।
এই R
কোডটি এখানে এই সিমুলেশন তৈরি করেছে এবং এটি টাইম করেছে।
n.sim <- 1e6
x.time <- system.time({
# Generate trial angles `theta`
theta <- sqrt(runif(n.sim)) * pi/4
# Rejection step.
theta <- theta[runif(n.sim) * 4 * theta <= pi * tan(theta)^2]
# Generate radial coordinates `r`.
n <- length(theta)
r <- sqrt(1 + runif(n) * tan(theta)^2)
# Convert to Cartesian coordinates.
# (The products will generate a full circle)
x <- r * cos(theta) #* c(1,1,-1,-1)
y <- r * sin(theta) #* c(1,-1,1,-1)
# Swap approximately half the coordinates.
k <- rbinom(1, n, 1/2)
if (k > 0) {
z <- y[1:k]
y[1:k] <- x[1:k]
x[1:k] <- z
}
})
message(signif(x.time[3] * 1e6/n, 2), " seconds per million points.")
#
# Plot the result to confirm.
#
plot(c(0,1), c(0,1), type="n", bty="n", asp=1, xlab="x", ylab="y")
rect(-1, -1, 1, 1, col="White", border="#00000040")
m <- sample.int(n, min(n, 1e4))
points(x[m],y[m], pch=19, cex=1/2, col="#0000e010")
আমি নীচের সমাধানটির প্রস্তাব দিচ্ছি, এটি এখন পর্যন্ত @ কার্ডিনাল, @ হুইবার এবং @ স্টেফান-কোলাসার দ্বারা অন্যান্য আত্মার তুলনায় সহজ, আরও দক্ষ এবং / বা কম্পিউটেশনালি সস্তা হওয়া উচিত।
এটি নিম্নলিখিত সহজ পদক্ষেপ জড়িত:
1) দুটি স্ট্যান্ডার্ড ইউনিফর্ম নমুনা আঁকুন:
2b) Swap and if .
3) Reject the sample if inside the unit circle (acceptance should be around 72%), i.e.:
The intuition behind this algorithm is shown in the figure.
Steps 2a and 2b can be merged into a single step:
2) Apply shear transformation and swap
The following code implements the algorithm above (and tests it using @whuber's code).
n.sim <- 1e6
x.time <- system.time({
# Draw two standard uniform samples
u_1 <- runif(n.sim)
u_2 <- runif(n.sim)
# Apply shear transformation and swap
tmp <- 1 + sqrt(2)/2 * pmin(u_1, u_2)
x <- tmp - u_2
y <- tmp - u_1
# Reject if inside circle
accept <- x^2 + y^2 > 1
x <- x[accept]
y <- y[accept]
n <- length(x)
})
message(signif(x.time[3] * 1e6/n, 2), " seconds per million points.")
#
# Plot the result to confirm.
#
plot(c(0,1), c(0,1), type="n", bty="n", asp=1, xlab="x", ylab="y")
rect(-1, -1, 1, 1, col="White", border="#00000040")
m <- sample.int(n, min(n, 1e4))
points(x[m],y[m], pch=19, cex=1/2, col="#0000e010")
Some quick tests yield the following results.
Algorithm /stats//a/258349 . Best of 3: 0.33 seconds per million points.
This algorithm. Best of 3: 0.18 seconds per million points.
Well, more efficiently can be done, but I sure hope you are not looking for faster.
The idea would be to sample an value first, with a density proportional to the length of the vertical blue slice above each value:
Wolfram helps you to integrate that:
So the cumulative distribution function would be this expression, scaled to integrate to 1 (i.e., divided by ).
Now, to generate your value, pick a random number , uniformly distributed between and . Then find such that . That is, we need to invert the CDF (inverse transform sampling). This can be done, but it's not easy. Nor fast.
Finally, given , pick a random that is uniformly distributed between and .
Below is R code. Note that I am pre-evaluating the CDF at a grid of values, and even then this takes quite a few minutes.
You can probably speed the CDF inversion up quite a bit if you invest some thinking. Then again, thinking hurts. I personally would go for rejection sampling, which is faster and far less error-prone, unless I had very good reasons not to.
epsilon <- 1e-6
xx <- seq(0,1,by=epsilon)
x.cdf <- function(x) x-(x*sqrt(1-x^2)+asin(x))/2
xx.cdf <- x.cdf(xx)/x.cdf(1)
nn <- 1e4
rr <- matrix(nrow=nn,ncol=2)
set.seed(1)
pb <- winProgressBar(max=nn)
for ( ii in 1:nn ) {
setWinProgressBar(pb,ii,paste(ii,"of",nn))
x <- max(xx[xx.cdf<runif(1)])
y <- runif(1,sqrt(1-x^2),1)
rr[ii,] <- c(x,y)
}
close(pb)
plot(rr,pch=19,cex=.3,xlab="",ylab="")