Wie erstelle ich Zahlen basierend auf einer beliebigen diskreten Verteilung?
Zum Beispiel habe ich eine Reihe von Zahlen, die ich generieren möchte. Angenommen, sie sind wie folgt mit 1-3 gekennzeichnet.
1: 4%, 2: 50%, 3: 46%
Grundsätzlich handelt es sich bei den Prozentsätzen um Wahrscheinlichkeiten, mit denen sie in der Ausgabe des Zufallszahlengenerators erscheinen. Ich habe einen Pesudorandom-Zahlengenerator, der eine gleichmäßige Verteilung im Intervall [0, 1] erzeugt. Gibt es eine Möglichkeit, dies zu tun?
Es gibt keine Grenzen für die Anzahl der Elemente, die ich haben kann, aber die% summieren sich zu 100%.
distributions
FurtiveFelon
quelle
quelle
Antworten:
Einer der besten Algorithmen zum Abtasten aus einer diskreten Verteilung ist die Alias-Methode .
Die Alias-Methode berechnet (effizient) eine zweidimensionale Datenstruktur vor, um ein Rechteck in Bereiche zu unterteilen, die proportional zu den Wahrscheinlichkeiten sind.
In diesem schematischen vom referenzierten Seite hat ein Rechteck von Einheitshöhe in vier Arten von Bereichen partitioniert worden - wie durch Farbe unterscheidet - in den Verhältnissen , 1 / 3 , 1 / 12 und 1 / 12 , in um mit diesen Wahrscheinlichkeiten wiederholt aus einer diskreten Verteilung abzutasten. Die vertikalen Streifen haben eine konstante (Einheits-) Breite. Jedes ist in nur ein oder zwei Teile unterteilt. Die Identitäten der Teile und die Positionen der vertikalen Unterteilungen werden in Tabellen gespeichert, auf die über den Spaltenindex zugegriffen werden kann.1 / 2 1/3 1/12 1/12
Die Tabelle kann in zwei einfachen Schritten abgetastet werden (einer für jede Koordinate), wobei nur zwei unabhängige einheitliche Werte und eine -Berechnung generiert werden müssen. Dies verbessert die O ( log ( n ) ) - Berechnung, die zum Invertieren der diskreten CDF erforderlich ist, wie in anderen Antworten hier beschrieben.O(1) O(log(n))
quelle
Sie können dies einfach in R tun, geben Sie einfach die Größe an, die Sie benötigen:
quelle
Nehmen wir in Ihrem Beispiel an, Sie zeichnen Ihren pseudozufälligen Uniform-Wert [0,1] und nennen ihn U. Dann geben Sie Folgendes aus:
1, wenn U <0,04
2 wenn U> = 0,04 und U <0,54
3 wenn U> = 0,54
Wenn die angegebenen% a, b, ... sind, einfach ausgeben
Wert 1, wenn U
Wert 2, wenn U> = a und U <(a + b)
etc.
Im Wesentlichen bilden wir das% in Teilmengen von [0,1] ab, und wir wissen, dass die Wahrscheinlichkeit, dass ein einheitlicher Zufallswert in einen beliebigen Bereich fällt, einfach die Länge dieses Bereichs ist. Das Ordnen der Bereiche scheint die einfachste, wenn nicht die einzige Möglichkeit zu sein. Dies setzt voraus, dass Sie nur nach diskreten Verteilungen fragen. für Dauerbetrieb kann man so etwas wie "Rejection Sampling" machen ( Wikipedia-Eintrag ).
quelle
TRUE
FALSE
FALSE
quelle
min(which(u < cp))
? Es wäre gut zu vermeiden, die kumulierte Summe auch bei jedem Anruf neu zu berechnen. Mit dieser Vorberechnung wird der gesamte Algorithmus auf reduziertmin(which(runif(1) < cp))
. Oder besser, weil das OP fordert, Zahlen ( Plural ) zu generieren , vektorisieren Sie es alsn<-10; apply(matrix(runif(n),1), 2, function(u) min(which(u < cp)))
.Ein einfacher Algorithmus besteht darin, mit Ihrer einheitlichen Zufallszahl zu beginnen und in einer Schleife zuerst die erste Wahrscheinlichkeit abzuziehen. Wenn das Ergebnis negativ ist, geben Sie den ersten Wert zurück, wenn es immer noch positiv ist, gehen Sie zur nächsten Iteration und subtrahieren die nächste Wahrscheinlichkeit , prüfe ob negativ usw.
Das ist insofern schön, als die Anzahl der Werte / Wahrscheinlichkeiten unendlich sein kann, aber Sie müssen die Wahrscheinlichkeiten nur berechnen, wenn Sie sich diesen Zahlen nähern (zum Beispiel wenn Sie aus einer Poisson-Verteilung oder einer negativen Binomialverteilung generieren).
Wenn Sie eine endliche Menge von Wahrscheinlichkeiten haben, aber viele Zahlen daraus generieren, ist es möglicherweise effizienter, die Wahrscheinlichkeiten so zu sortieren, dass Sie zuerst die größte, dann die zweitgrößte subtrahieren und so weiter.
quelle
Lassen Sie mich zunächst Ihre Aufmerksamkeit auf eine Python-Bibliothek mit gebrauchsfertigen Klassen für die Generierung von Ganzzahl- oder Gleitkommazahlen lenken, die einer beliebigen Verteilung folgen.
Generell gibt es verschiedene Ansätze für dieses Problem. Einige sind zeitlich linear, erfordern jedoch einen großen Speicher, andere werden in der Zeit 0 (n log (n)) ausgeführt. Einige sind für ganzzahlige Zahlen optimiert, andere für kreisförmige Histogramme (zum Beispiel: Erzeugen zufälliger Zeitpunkte während eines Tages). In der oben genannten Bibliothek habe ich dieses Papier für Ganzzahlfälle und dieses Rezept für Gleitkommazahlen verwendet. Es fehlt (noch) die Unterstützung für kreisförmige Histogramme und es ist im Allgemeinen chaotisch, aber es funktioniert gut.
quelle
Ich hatte das gleiche problem Bei einer Menge, bei der jedes Element eine Wahrscheinlichkeit hat und deren Wahrscheinlichkeit eins ergibt, wollte ich eine Stichprobe effizient zeichnen, dh ohne etwas zu sortieren und ohne die Menge wiederholt zu durchlaufen .
quelle