Tạo điểm hiệu quả giữa vòng tròn đơn vị và hình vuông đơn vị


17

Tôi muốn tạo các mẫu từ vùng màu xanh được xác định ở đây:

nhập mô tả hình ảnh ở đây

Giải pháp ngây thơ là sử dụng lấy mẫu từ chối trong ô vuông đơn vị, nhưng điều này chỉ cung cấp hiệu suất 1π/4 (~ 21,4%).

Có một số cách tôi có thể lấy mẫu hiệu quả hơn?


6
Gợi ý : Sử dụng tính đối xứng để tăng gấp đôi hiệu quả của bạn.
Đức hồng y

3
Ồ như: nếu giá trị là (0,0), điều này có thể được ánh xạ tới (1,1)? Tôi thích ý tưởng đó
Cam.Davidson.Pilon

@cardinal Không nên tăng gấp 4 lần hiệu quả? Bạn có thể lấy mẫu trong và sau đó phản chiếu nó qua trục x, trục y và gốc. [0,,1]×[0,,1]
Martin Krämer

1
@Martin: Trên bốn vùng đối xứng, bạn có sự chồng chéo, mà bạn phải giải quyết cẩn thận hơn.
Đức hồng y

3
@ Martin: Nếu tôi hiểu những gì bạn đang mô tả, mà không làm tăng hiệu quả ở tất cả . (Bạn đã tìm thấy một điểm và bây giờ biết ba điểm khác --- trong một khu vực có kích thước gấp bốn lần --- có hoặc không nằm trong đĩa đơn vị với xác suất một tùy theo liệu có. Điều đó có giúp ích gì không?) Điểm tăng hiệu quả là tăng xác suất chấp nhận cho mỗi ( x , y ) được tạo. Có lẽ tôi là người dày đặc? (x,y)(x,y)
Đức hồng y

Câu trả lời:


10

Hai triệu điểm mỗi giây sẽ làm gì?

Phân phối là đối xứng: chúng ta chỉ cần thực hiện phân phối cho một phần tám của vòng tròn đầy đủ và sau đó sao chép nó xung quanh các quãng tám khác. Trong tọa độ cực , phân phối tích lũy của góc Θ cho vị trí ngẫu nhiên ( X , Y ) theo giá trị θ được đưa ra bởi khu vực giữa tam giác ( 0 , 0 ) , ( 1 , 0 ) , ( 1 , tan θ ) và cung của vòng tròn kéo dài từ ((r,θ)Θ(X,Y)θ(0,0),(1,0),(1,tanθ) đến ( cos θ , tội lỗi θ ) . Do đó tỷ lệ thuận với(1,0)(cosθ,sinθ)

FΘ(θ)=Pr(Θθ)12tan(θ)θ2,

mật độ của nó là

fΘ(θ)=ddθFΘ(θ)tan2(θ).

Chúng tôi có thể lấy mẫu từ mật độ này bằng cách sử dụng phương pháp loại bỏ (có hiệu quả ).8/π254.6479%

Mật độ có điều kiện của tọa độ hướng tâm tỷ lệ thuận với giữa và . Điều đó có thể được lấy mẫu với sự đảo ngược dễ dàng của CDF.r d r r = 1 r = giây θRrdrr=1r=secθ

Nếu chúng ta tạo các mẫu độc lập , chuyển đổi trở lại tọa độ Cartesian lấy mẫu octant này. Bởi vì các mẫu là độc lập, việc hoán đổi tọa độ ngẫu nhiên tạo ra một mẫu ngẫu nhiên độc lập từ góc phần tư thứ nhất, như mong muốn. (Các giao dịch hoán đổi ngẫu nhiên yêu cầu chỉ tạo một biến Binomial duy nhất để xác định số lượng thực hiện để hoán đổi.)( x i , y i )(ri,θi)(xi,yi)

Trung bình, mỗi lần thực hiện yêu cầu, trung bình, một biến thiên đồng nhất (đối với ) cộng với hai lần thay đổi đồng nhất (đối với ) và một lượng nhỏ (nhanh) tính toán. Đó là biến thiên cho mỗi điểm (tất nhiên, có hai tọa độ). Chi tiết đầy đủ có trong ví dụ mã dưới đây. Con số này vẽ ra 10.000 trong số hơn nửa triệu điểm được tạo ra.R 1 / ( 8 π - 2 ) Θ 4 / ( π - 4 ) 4,66(X,Y)R1/(8π2)Θ4/(π4)4.66

Nhân vật

Đây là Rmã đã tạo ra mô phỏng này và hẹn giờ cho nó.

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
Tôi không hiểu câu này: "Bởi vì các mẫu là độc lập, hoán đổi hệ tọa độ mỗi mẫu thứ hai tạo ra một mẫu ngẫu nhiên độc lập từ góc phần tư thứ nhất, như mong muốn." Dường như với tôi, việc hoán đổi hệ tọa độ mỗi mẫu thứ hai tạo ra các mẫu phụ thuộc rất cao. Ví dụ, đối với tôi, việc triển khai mã của bạn tạo ra nửa triệu mẫu liên tiếp từ cùng một quãng tám?
A. Rex

7
Nói một cách chính xác, cách tiếp cận này không thực sự hiệu quả (đối với các điểm iid) vì nó tạo ra một số lượng mẫu giống hệt nhau trong hai quãng tám: Do đó, các điểm mẫu phụ thuộc. Bây giờ, nếu bạn lật các đồng xu không thiên vị để xác định quãng tám cho mỗi mẫu ...
hồng y

1
@Cardinal bạn đúng; Tôi sẽ khắc phục điều đó - mà không (không có triệu chứng) làm tăng số lượng biến thể ngẫu nhiên để tạo ra!
whuber

2
Nói một cách chính xác (và, một lần nữa, chỉ trong ý nghĩa lý thuyết thuần túy nhất), trong trường hợp mẫu hữu hạn, sửa đổi của bạn không yêu cầu thêm các biến thể ngẫu nhiên thống nhất bổ sung. Để dí dỏm: Từ phương sai ngẫu nhiên thống nhất đầu tiên, xây dựng chuỗi lật từ bit đầu tiên . Sau đó, sử dụng phần còn lại (lần ) làm tọa độ đầu tiên được tạo. 2 nn2n
Đức hồng y

2
@ Xi'an Tôi đã không thể có được một nghịch đảo thuận tiện tính toán. Tôi có thể làm tốt hơn một chút bằng cách từ chối lấy mẫu từ phân phối với mật độ tỷ lệ thuận với (hiệu quả là ), tại chi phí phải tính một arcsine. ( 4 - π ) / ( π - 2 ) 75 %2sin(θ)2(4π)/(π2)75%
whuber

13

Tôi đề xuất giải pháp sau đây, nên đơn giản hơn, hiệu quả hơn và / hoặc tính toán rẻ hơn so với các loại thuốc khác bằng @cardinal, @whuber và @ stephan-kolassa cho đến nay.

Nó bao gồm các bước đơn giản sau:

1) Vẽ hai mẫu thống nhất tiêu chuẩn:

u1Unif(0,1)u2Unif(0,1).

2a) Áp dụng phép biến đổi cắt sau cho điểm (các điểm trong tam giác dưới bên phải được phản ánh cho tam giác phía trên bên trái và chúng sẽ là "un- phản ánh "trong 2b): min{u1,u2},max{u1,u2}

[xy]=[11]+[2212210][min{u1,u2}max{u1,u2}].

2b) Hoán đổi và nếu .xyu1>u2

3) Từ chối mẫu nếu bên trong vòng tròn đơn vị (mức chấp nhận phải ở khoảng 72%), tức là:

x2+y2<1.

Trực giác đằng sau thuật toán này được hiển thị trong hình. nhập mô tả hình ảnh ở đây

Bước 2a và 2b có thể được hợp nhất thành một bước duy nhất:

2) Áp dụng chuyển đổi cắt và hoán đổi

x=1+22min(u1,u2)u2y=1+22min(u1,u2)u1

Đoạn mã sau thực hiện thuật toán ở trên (và kiểm tra nó bằng mã @ whuber's).

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")

Một số xét nghiệm nhanh mang lại kết quả như sau.

Thuật toán /stats//a/258349 . Tốt nhất trong 3: 0,33 giây trên một triệu điểm.

Thuật toán này. Tốt nhất trong 3: 0,18 giây trên một triệu điểm.


3
+1 Thực hiện rất tốt! Cảm ơn bạn đã chia sẻ một giải pháp chu đáo, thông minh và đơn giản.
whuber

Ý tưởng tuyệt vời! Tôi đã suy nghĩ về một ánh xạ từ đơn vị vuông đến phần này, nhưng không nghĩ đến một ánh xạ không hoàn hảo và sau đó là một sơ đồ từ chối. Cảm ơn đã mở rộng tâm trí của tôi!
Cam.Davidson.Pilon

7

Vâng, hiệu quả hơn có thể được thực hiện, nhưng tôi chắc chắn hy vọng bạn không tìm kiếm nhanh hơn .

Ý tưởng sẽ là lấy mẫu một giá trị trước, với mật độ tỷ lệ thuận với chiều dài của lát màu xanh dọc trên mỗi giá trị :xx

f(x)=11x2.

Wolfram giúp bạn tích hợp điều đó :

0xf(y)dy=12x1x2+x12arcsinx.

Vì vậy, hàm phân phối tích lũy sẽ là biểu thức này, được chia tỷ lệ để tích hợp thành 1 (nghĩa là chia cho ).1 0 f ( y ) d yF01f(y)dy

Bây giờ, để tạo giá trị của bạn , hãy chọn một số ngẫu nhiên , được phân phối đồng đều giữa và . Sau đó tìm sao cho . Đó là, chúng ta cần đảo ngược CDF ( lấy mẫu biến đổi nghịch đảo ). Điều này có thể được thực hiện, nhưng nó không dễ dàng. Cũng không nhanh.t 0 1 x F ( x ) = txt01xF(x)=t

Cuối cùng, cho , chọn một ngẫu nhiên được phân phối đồng đều giữa và .y xy 11x21

Dưới đây là mã R. Lưu ý rằng tôi đang đánh giá trước CDF ở một lưới các giá trị , và thậm chí sau đó việc này mất khá nhiều phút.x

Bạn có thể có thể tăng tốc độ đảo ngược CDF lên một chút nếu bạn đầu tư một số suy nghĩ. Rồi lại suy nghĩ, đau lắm. Cá nhân tôi sẽ đi lấy mẫu từ chối, nhanh hơn và ít bị lỗi hơn, trừ khi tôi có lý do rất chính đáng để không.

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="")

randoms


Tôi tự hỏi nếu sử dụng đa thức Ch Quashev để xấp xỉ CDF sẽ cải thiện tốc độ đánh giá.
Sycorax nói phục hồi Monica

@Sycorax, không phải không có sửa đổi; xem ví dụ: điều trị chebfun của các điểm kỳ dị đại số ở các điểm cuối.
JM không phải là một thống kê
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.