Ефективно створюйте точки між одиничним колом та одиницею квадрата


17

Я б хотів генерувати зразки з блакитної області, визначеної тут:

введіть тут опис зображення

Наївним рішенням є використання відбору проб відхилення в одиничному квадраті, але це забезпечує лише ефективність (~ 21,4%).1π/4

Чи є якийсь спосіб я можу зробити вибірку більш ефективно?


6
Підказка : Використовуйте симетрію, щоб трівіально подвоїти ефективність.
кардинал

3
О як: якщо значення дорівнює (0,0), це можна відобразити в (1,1)? Мені подобається ця ідея
Cam.Davidson.Pilon

@cardinal Чи не повинен це 4 рази ефективність? Ви можете взяти вибірку в а потім відобразити її по осі x, y-осі та походження. [0,,1]×[0,,1]
Мартін Кремер

1
@Martin: У чотирьох симетричних областях у вас перекриття, з якими вам доведеться поводитися більш ретельно.
кардинал

3
@Martin: Якщо я зрозуміти , що ви описуєте, що ні призводить до підвищення ефективності на всіх . (Ви знайшли одну точку, і тепер знаєте три інші --- в області, що в чотири рази перевищує розмір ---, які або роблять, або не лежать в одиничному диску з імовірністю один відповідно до того, чи робить. це допомагає?) Точка підвищення ефективності полягає у збільшенні ймовірності прийняття для кожного ( x , y ) породженого. Можливо, я той, хто щільний? (x,y)(x,y)
кардинал

Відповіді:


10

Зроблять два мільйони очок за секунду?

Розподіл симетричний: нам потрібно лише розробити розподіл на одну восьму повного кола, а потім скопіювати його навколо інших октантів. У полярних координатах кумулятивний розподіл кута Θ для випадкового розташування ( X , Y ) при значенні θ задається площею між трикутником ( 0 , 0 ) , ( 1 , 0 ) , ( 1 , tan θ ) і дуга кола, що проходить від ((r,θ)Θ(X,Y)θ(0,0),(1,0),(1,tanθ) до ( cos θ , sin θ ) . Таким чином, він пропорційний(1,0)(cosθ,sinθ)

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

звідки його щільність

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

Ми можемо взяти вибірку з цієї щільності, використовуючи, скажімо, метод відкидання (який має ефективність ).8/π254.6479%

Умовна щільність радіальної координати пропорційна r d r між r = 1 та r = sec θ . Це можна пробити за допомогою легкої інверсії CDF.Rrdrr=1r=secθ

Якщо ми генеруємо незалежні зразки , перетворення назад до декартових координат ( x i , y i ) вибірки цього октанта. Оскільки вибірки є незалежними, випадкове зміна координат створює незалежну випадкову вибірку з першого квадранта, як бажано. (Випадкові свопи вимагають генерування лише однієї біноміальної змінної, щоб визначити, скільки реалізується для заміни.)(ri,θi)(xi,yi)

Кожна така реалізація вимагає, в середньому, однієї рівномірної змінної (для R ) плюс 1 / ( 8 π - 2 ) разів двох рівномірних змінних (для Θ ) і невеликої кількості (швидкого) обчислення. Це 4 / ( π - 4 ) 4,66 змінних на точку (що, звичайно, має дві координати). Повна інформація наведена в прикладі коду нижче. Ця цифра відображає 10 000 з більш ніж півмільйона отриманих балів.(X,Y)R1/(8π2)Θ4/(π4)4.66

Малюнок

Ось 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
Я не розумію цього речення: "Оскільки вибірки є незалежними, систематично змінюючи координати, кожен другий зразок виробляє незалежну випадкову вибірку з першого квадранта за бажанням". Мені здається, що систематично міняючи координати, кожен другий зразок виробляє високозалежні вибірки. Наприклад, мені здається, що ваша реалізація в коді генерує півмільйона зразків поспіль з одного октанта?
А. Рекс

7
Власне кажучи, такий підхід не дуже працює (для балів в iid), оскільки він генерує однакову кількість зразків у двох октантах: Таким чином, точки вибірки залежать. Тепер, якщо ви перегортаєте неупереджені монети, щоб визначити октант для кожного зразка ...
кардинал

1
@Cardinal ви маєте рацію; Я це виправлю - без (асимптотично) збільшення кількості випадкових змінних для генерації!
whuber

2
Власне кажучи (і, знову ж таки, лише в чистому теоретичному сенсі), у випадку кінцевої вибірки ваша модифікація не потребує додаткових рівномірних випадкових величин. На розум: З першої рівномірної випадкової величини побудуйте гортаючу послідовність з перших біт. Потім використовуйте решту (раз 2 n ) в якості першої згенерованої координати. n2n
кардинал

2
@ Xi'an мені не вдалося отримати зручно обчислену інверсію. Я можу зробити трохи краще, відкинувши вибірку від розподілу з щільністю, пропорційною (ефективність ( 4 - π ) / ( π - 2 ) 75 % ), ціною необхідності обчислити аркусин . 2sin(θ)2(4π)/(π2)75%
whuber

13

Я пропоную наступне рішення, яке повинно бути простішим, ефективнішим та / або обчислювально дешевшим, ніж інші соуси від @cardinal, @whuber та @ stephan-kolassa поки що.

Він включає наступні прості кроки:

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

min{u1,u2},max{u1,u2}

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

xyu1>u2

x2+y2<1.

Інтуїція, що стоїть за цим алгоритмом, показана на малюнку. enter image description here

Кроки 2a та 2b можна об'єднати в один крок:

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

Наступний код реалізує алгоритм, наведений вище (і тестує його за допомогою коду @ whuber).

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

Деякі швидкі тести дають такі результати.

Алгоритм /stats//a/258349 . Найкраще 3: 0,33 секунди на мільйон очок.

Цей алгоритм. Найкраще 3: 0,18 секунди на мільйон очок.


3
+1 Дуже добре! Дякуємо, що поділилися продуманим, розумним та простим рішенням.
whuber

Чудова ідея! Я думав про відображення від одиниці кв до цієї частини, але не думав про недосконале відображення, а потім про схему відхилення. Дякую за те, що я розширив свою думку!
Cam.Davidson.Pilon

7

Що ж, ефективніше можна зробити, але я впевнений, що ви швидше не шукаєте .

xx

f(x)=11x2.

Wolfram допомагає вам інтегрувати це :

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

F01f(y)dy

xt01xF(x)=t

Нарешті, дано х, виберіть випадковий у що рівномірно розподілено між собою 1-х2 і 1.

Нижче наведено код R. Зауважте, що я попередньо оцінював CDF в сітціх значення, і навіть тоді це займає досить декількох хвилин.

Напевно, ви можете трохи прискорити інверсію CDF, якщо вкладете трохи думок. Потім знову мислення боляче. Я особисто хотів би взяти вибірку відхилень, що швидше і набагато менш схильне до помилок, якщо б у мене не було дуже вагомих причин цього не робити.

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


Цікаво, чи використання поліномів Чебишева для наближення CDF покращило б швидкість оцінки.
Sycorax каже, що повернеться до Моніки

@Sycorax, не без модифікацій; див., наприклад, хебфун-лікування алгебраїчних особливостей у кінцевих точках.
JM не є статистиком
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.