it-swarm-eu.dev

Umwandlung einer einheitlichen Verteilung in eine Normalverteilung

Wie kann ich eine gleichmäßige Verteilung (wie die meisten Zufallszahlengeneratoren beispielsweise zwischen 0,0 und 1,0 produzieren) in eine Normalverteilung umwandeln? Was ist, wenn ich einen Mittelwert und eine Standardabweichung meiner Wahl haben möchte?

91
Terhorst

Der Ziggurat-Algorithmus ist dafür ziemlich effizient, obwohl die Box-Muller-Transformation von Grund auf einfacher zu implementieren ist (und nicht verrückt langsam).

46
Tyler

Es gibt viele Methoden:

  • Verwenden Sie nicht Box Muller. Vor allem, wenn Sie viele Gaußsche Zahlen zeichnen. Box Muller führt zu einem Ergebnis, das zwischen -6 und 6 liegt (bei doppelter Genauigkeit. Bei Schwimmern verschlechtert sich die Situation.). Und es ist wirklich weniger effizient als andere verfügbare Methoden.
  • Ziggurat ist in Ordnung, benötigt jedoch eine Tabellensuche (und einige plattformspezifische Anpassungen aufgrund von Problemen mit der Cachegröße).
  • Verhältnis der Uniformen ist mein Favorit, nur ein paar Additionen/Multiplikationen und ein Log 1/50 der Zeit (z. B. siehe dort ).
  • Invertieren Sie die CDF ist effizient (und wird übersehen, warum?), Stehen Ihnen schnelle Implementierungen zur Verfügung, wenn Sie Google suchen. Für Quasi-Zufallszahlen ist dies obligatorisch.
38
Alexandre C.

Wenn Sie die Verteilung einer Funktion auf eine andere ändern, müssen Sie die Umkehrung der gewünschten Funktion verwenden.

Mit anderen Worten, wenn Sie auf eine bestimmte Wahrscheinlichkeitsfunktion p(x) abzielen, erhalten Sie die Verteilung durch Integration über -> d(x) = Integral (p (x)) und verwenden deren Umkehrung : Inv (d (x)). Verwenden Sie nun die Zufallswahrscheinlichkeitsfunktion (die eine gleichmäßige Verteilung aufweist), und wenden Sie den Ergebniswert über die Funktion Inv (d (x)) an. Sie sollten Zufallswerte mit Verteilung entsprechend der von Ihnen gewählten Funktion erhalten.

Dies ist der generische mathematische Ansatz. Wenn Sie ihn verwenden, können Sie jetzt jede mögliche Wahrscheinlichkeits- oder Verteilungsfunktion auswählen, solange Sie eine inverse oder eine gute inverse Approximation haben.

Hoffe das hat geholfen und danke für die kleine Bemerkung über die Verwendung der Verteilung und nicht die Wahrscheinlichkeit selbst.

25
Adi

Hier ist eine Javascript-Implementierung unter Verwendung der Polarform der Box-Muller-Transformation.

/*
 * Returns member of set with a given mean and standard deviation
 * mean: mean
 * standard deviation: std_dev 
 */
function createMemberInNormalDistribution(mean,std_dev){
    return mean + (gaussRandom()*std_dev);
}

/*
 * Returns random number in normal distribution centering on 0.
 * ~95% of numbers returned should fall between -2 and 2
 * ie within two standard deviations
 */
function gaussRandom() {
    var u = 2*Math.random()-1;
    var v = 2*Math.random()-1;
    var r = u*u + v*v;
    /*if outside interval [0,1] start over*/
    if(r == 0 || r >= 1) return gaussRandom();

    var c = Math.sqrt(-2*Math.log(r)/r);
    return u*c;

    /* todo: optimize this algorithm by caching (v*c) 
     * and returning next time gaussRandom() is called.
     * left out for simplicity */
}
20
user5084

Verwenden Sie den zentralen Grenzwertsatz Wikipedia-EintragMathworld-Eintrag zu Ihrem Vorteil.

Generieren Sie n der gleichverteilten Zahlen, summieren Sie sie, subtrahieren Sie n * 0.5 und Sie erhalten eine annähernd Normalverteilung mit dem Mittelwert 0 und der Varianz gleich (1/12) * (1/sqrt(N)) (siehe Wikipedia über Uniformverteilungen für die letzte). 

n = 10 gibt Ihnen etwas halbes Anständiges schnell. Wenn Sie etwas mehr als die Hälfte der anständigen Lösung wünschen, wenden Sie sich an Tylers-Lösung (wie im wikipedia-Eintrag zu normalen Distributionen angegeben).

5
jilles de wit

Es scheint unglaublich, dass ich nach acht Jahren noch etwas hinzufügen könnte, aber für den Fall von Java möchte ich die Leser auf die Random.nextGaussian () - Methode verweisen, die eine Gaußsche Verteilung mit dem Mittelwert 0,0 und der Standardabweichung generiert 1.0 für Sie.

Eine einfache Addition und/oder Multiplikation ändert den Mittelwert und die Standardabweichung nach Ihren Bedürfnissen.

1
Pepijn Schmitz

Ich würde Box-Muller verwenden. Zwei Dinge dazu:

  1. Sie erhalten am Ende zwei Werte pro Iteration
    Normalerweise zwischenspeichern Sie einen Wert und geben den anderen zurück. Beim nächsten Aufruf eines Beispiels geben Sie den zwischengespeicherten Wert zurück.
  2. Box-Muller gibt einen Z-Score
    Sie müssen dann den Z-Score um die Standardabweichung skalieren und den Mittelwert hinzufügen, um den vollen Wert in der Normalverteilung zu erhalten.
1
hughdbrown

Das Standard-Python-Bibliotheksmodul random hat das, was Sie wollen:

normalvariate (mu, sigma)
Normalverteilung. mu ist der Mittelwert und Sigma ist die Standardabweichung.

Sehen Sie sich für den Algorithmus selbst die Funktion in random.py in der Python-Bibliothek an.

Der manuelle Eintrag ist hier

1

Wobei R1, R2 zufällige einheitliche Zahlen sind:

NORMALE VERTEILUNG mit SD von 1: sqrt (-2 * log (R1)) * cos (2 * pi * R2)

Das ist genau ... keine Notwendigkeit, all diese langsamen Schleifen zu machen!

1
Erik Aronesty

F Wie kann ich eine Gleichverteilung (wie die meisten Zufallszahlengeneratoren beispielsweise zwischen 0,0 und 1,0 produzieren) in eine Normalverteilung umwandeln?

  1. Für die Software-Implementierung kenne ich einige Zufallsgeneratornamen, die eine pseudo-einheitliche Zufallsfolge in [0,1] (Mersenne Twister, Linear Congruate Generator) enthalten. Nennen wir es U (x)

  2. Es gibt einen mathematischen Bereich, der Wahrscheinlichkeitstheorie genannt wird. Als Erstes: Wenn Sie r.v modellieren wollen. mit der Integralverteilung F können Sie dann einfach versuchen, F ^ -1 (U (x)) auszuwerten. In der Vorlesung wurde bewiesen, dass solche r.v. wird integrale Verteilung haben F.

  3. Schritt 2 kann angewendet werden, um rv ~ F ohne Verwendung von Zählmethoden zu erzeugen, wenn F ^ -1 ohne Probleme analytisch abgeleitet werden kann. (z. B. exp.distribution)

  4. Um die Normalverteilung zu modellieren, können Sie y1 * cos (y2) kubulieren, wobei y1 ~ in [0,2pi] einheitlich ist. und y2 ist die relei Verteilung.

F: Was ist, wenn ich einen Mittelwert und eine Standardabweichung meiner Wahl haben möchte?

Sie können Sigma * N (0,1) + m berechnen.

Es kann gezeigt werden, dass diese Verschiebung und Skalierung zu N (m, Sigma) führt.

0
bruziuz

Dies ist eine Matlab-Implementierung, die die polare Form der Box-Muller -Transformation verwendet:

Funktion randn_box_muller.m:

function [values] = randn_box_muller(n, mean, std_dev)
    if nargin == 1
       mean = 0;
       std_dev = 1;
    end

    r = gaussRandomN(n);
    values = r.*std_dev - mean;
end

function [values] = gaussRandomN(n)
    [u, v, r] = gaussRandomNValid(n);

    c = sqrt(-2*log(r)./r);
    values = u.*c;
end

function [u, v, r] = gaussRandomNValid(n)
    r = zeros(n, 1);
    u = zeros(n, 1);
    v = zeros(n, 1);

    filter = r==0 | r>=1;

    % if outside interval [0,1] start over
    while n ~= 0
        u(filter) = 2*Rand(n, 1)-1;
        v(filter) = 2*Rand(n, 1)-1;
        r(filter) = u(filter).*u(filter) + v(filter).*v(filter);

        filter = r==0 | r>=1;
        n = size(r(filter),1);
    end
end

Das Aufrufen von histfit(randn_box_muller(10000000),100); ist das Ergebnis:  Box-Muller Matlab Histfit

Offensichtlich ist es im Vergleich zum eingebauten Matlab randn wirklich ineffizient.

0
madx

Ich habe folgenden Code, der vielleicht helfen könnte:

set.seed(123)
n <- 1000
u <- runif(n) #creates U
x <- -log(u)
y <- runif(n, max=u*sqrt((2*exp(1))/pi)) #create Y
z <- ifelse (y < dnorm(x)/2, -x, NA)
z <- ifelse ((y > dnorm(x)/2) & (y < dnorm(x)), x, z)
z <- z[!is.na(z)]

Es ist auch einfacher, die implementierte Funktion rnorm () zu verwenden, da sie schneller ist als das Schreiben eines Zufallszahlengenerators für die Normalverteilung. Siehe den folgenden Code als Beweis

n <- length(z)
t0 <- Sys.time()
z <- rnorm(n)
t1 <- Sys.time()
t1-t0
0

Ich denke, Sie sollten dies in Excel versuchen: =norminv(Rand();0;1). Dies ergibt die Zufallszahlen, die normalerweise mit dem Nullmittelwert und der Unite-Varianz verteilt sein sollten. "0" kann mit einem beliebigen Wert geliefert werden, so dass die Zahlen den gewünschten Mittelwert haben. Wenn Sie "1" ändern, erhalten Sie die Varianz gleich dem Quadrat Ihrer Eingabe.

Zum Beispiel: =norminv(Rand();50;3) ergibt die normalverteilten Zahlen mit MEAN = 50 VARIANCE = 9.

0
Hippo