Chciałbym wygenerować próbki z zdefiniowanego tutaj niebieskiego regionu:
Naiwnym rozwiązaniem jest stosowanie próbkowania odrzucania w jednostce kwadratowej, ale zapewnia to jedynie wydajność (~ 21,4%).
Czy jest jakiś sposób na bardziej efektywne próbkowanie?
probability
sampling
monte-carlo
random-generation
Cam.Davidson.Pilon
źródło
źródło
Odpowiedzi:
Czy zrobią to dwa miliony punktów na sekundę?
Rozkład jest symetryczny: musimy tylko opracować rozkład dla jednej ósmej pełnego koła, a następnie skopiować go wokół innych oktantów. We współrzędnych biegunowych skumulowany rozkład kąta Θ dla losowej lokalizacji ( X , Y ) przy wartości θ jest określony przez obszar między trójkątem ( 0( r , θ) Θ (X,Y) θ i łuk koła rozciągający się od (( 0 , 0 ) , ( 1 , 0 ) ,(1,tanθ) do ( cos θ , sin θ ) . Jest zatem proporcjonalny do( 1 , 0 ) (cosθ ,sinθ )
stąd jego gęstość jest
Możemy próbkować z tej gęstości, stosując, powiedzmy, metodę odrzucania (która ma wydajność ).8 / π- 2 ≈ 54,6479 %
Gęstość warunkowa współrzędnej promieniowej jest proporcjonalna do r d r między r = 1 i rR r dr r = 1 . Można to próbkować przez łatwą inwersję CDF.r = sekθ
Jeśli wygenerujemy niezależne próbki , konwersja z powrotem do współrzędnych kartezjańskich ( x i( rja, θja) próbki tego oktant. Ponieważ próbki są niezależne, losowa zamiana współrzędnych tworzy niezależną losową próbkę z pierwszej ćwiartki, zgodnie z potrzebami. (Swapy losowe wymagają wygenerowania tylko jednej zmiennej dwumianowej, aby określić liczbę realizacji do zamiany).( xja, yja)
Każda taka realizacja wymaga średnio jednej zmiany jednolitej (dla R ) plus 1 / ( 8 π - 2 ) razy dwóch zmian jednolitej (dla Θ ) i niewielkiej ilości (szybkiego) obliczenia. To 4 / ( π - 4 ) ≈ 4,66 zmienna na punkt (który oczywiście ma dwie współrzędne). Pełne szczegóły znajdują się w poniższym przykładzie kodu. Ta liczba przedstawia 10 000 z ponad pół miliona wygenerowanych punktów.( X, Y) R 1 / ( 8 π- 2 ) Θ 4 / ( π- 4 ) ≈ 4,66
Oto
R
kod, który wyprodukował tę symulację i dokonał jej pomiaru czasu.źródło
Proponuję następujące rozwiązanie, które powinno być prostsze, wydajniejsze i / lub tańsze obliczeniowo niż inne południowe firmy @cardinal, @whuber i @ stephan-kolassa.
Obejmuje następujące proste kroki:
1) Narysuj dwie standardowe jednolite próbki:
2a) Zastosuj następującą transformację ścinania do punktu (punkty w prawym dolnym trójkącie są odzwierciedlone w lewym górnym trójkącie i będą „nieodbite” w 2b): [ x y ] = [ 1 1 ] + [ √min{u1,u2},max{u1,u2}
2b) Zamień i y, jeśli u 1 > u 2x y u1> u2) .
3) Odrzuć próbkę, jeśli znajduje się w okręgu jednostkowym (akceptacja powinna wynosić około 72%), tj .:
Intuicja tego algorytmu pokazano na rysunku.
Kroki 2a i 2b można połączyć w jeden krok:
2) Zastosuj transformację ścinającą i zamień
Poniższy kod implementuje powyższy algorytm (i testuje go przy użyciu kodu @ whuber).
Niektóre szybkie testy dają następujące wyniki.
Algorytm /stats//a/258349 . Najlepsze 3: 0,33 sekundy na milion punktów.
Ten algorytm Najlepsze 3: 0,18 sekundy na milion punktów.
źródło
Dobrze, bardziej efektywnie można to zrobić, ale mam nadzieję, że nie szukasz szybszego .
Pomysł polegałby na próbkowaniux wartość pierwsza, o gęstości proporcjonalnej do długości pionowego niebieskiego wycinka nad każdym x wartość:
Wolfram pomaga zintegrować, że :
Więc funkcja skumulowanego rozkładufa byłoby to wyrażenie skalowane w celu integracji do 1 (tzn. podzielone przez ∫10fa( y) dy ).
Teraz wygeneruj swójx wartość, wybierz liczbę losową t , równomiernie rozmieszczone między 0 i 1 . Następnie znajdźx takie, że fa( x ) = t . Oznacza to, że musimy odwrócić CDF ( próbkowanie z transformacją odwrotną ). Można to zrobić, ale nie jest to łatwe. Ani szybko.
Wreszcie podanex wybierz losowy y który jest równomiernie rozmieszczony między 1 - x2)-----√ i 1 .
Poniżej znajduje się kod R. Zauważ, że wstępnie oceniam CDF na poziomiex wartości, a nawet wtedy zajmuje to kilka minut.
Prawdopodobnie możesz znacznie przyspieszyć inwersję CDF, jeśli zainwestujesz trochę myślenia. Z drugiej strony myślenie boli. Osobiście wybrałbym próbkowanie odrzucania, które jest szybsze i znacznie mniej podatne na błędy, chyba że mam bardzo dobre powody, aby tego nie robić .
źródło