Wie wird mit einer herkömmlichen Programmiersprache aus einer Normalverteilung mit bekanntem Mittelwert und bekannter Varianz eine Stichprobe erstellt?


36

Ich hatte noch nie einen Statistikkurs und hoffe, dass ich hier an der richtigen Stelle nachfragen kann.

Angenommen, ich habe nur zwei Daten, die eine Normalverteilung beschreiben: den Mittelwert μ und die Varianz σ2 . Ich möchte einen Computer verwenden, um zufällig eine Stichprobe aus dieser Distribution zu ziehen, sodass ich diese beiden Statistiken respektiere.

Es ist ziemlich offensichtlich, dass ich mit dem Mittelwert umgehen kann, indem ich einfach auf 0 normiere: Addiere einfach μ zu jedem Sample, bevor du das Sample ausgibst. Aber ich verstehe nicht, wie man programmatisch Samples erzeugt, um zu respektieren σ2.

Mein Programm wird in einer konventionellen Programmiersprache sein; Ich habe keinen Zugriff auf statistische Pakete.


Hat Ihre Sprache einen Zufallsgenerator? Ist dieser Generator nur aus einer Gleichverteilung oder kann er auch aus einer Normalverteilung erzeugt werden?
ttnphns

@ttnphns: Fast jede Computersprache verfügt über einen Zufallsgenerator. Sie sind überwiegend einheitliche Generatoren in einem endlichen Bereich.
Fixee

Antworten:


33

Wenn Sie aus einer gegebenen Verteilung mit dem Mittelwert 0 und der Varianz 1 abtasten können, können Sie leicht aus einer Skalenorttransformation dieser Verteilung abtasten, die den Mittelwert und die Varianz σ 2 hat . Wenn x eine Stichprobe aus einer Verteilung von Mittelwert 0 und Varianz 1 ist, dann ist σ x + μ eine Stichprobe mit Mittelwert μ und Varianz σ 2 . Sie müssen die Variable also nur um die Standardabweichung σ (Quadratwurzel der Varianz) skalieren, bevor Sie den Mittelwert μ addieren .μσ2x

σx+μ
μσ2σμ

Wie Sie tatsächlich eine Simulation aus einer Normalverteilung mit Mittelwert 0 und Varianz 1 erhalten, ist eine andere Geschichte. Es macht Spaß und ist interessant zu wissen, wie man solche Dinge implementiert, aber ob Sie ein Statistikpaket oder eine Programmiersprache verwenden oder nicht, ich empfehle Ihnen, eine geeignete Funktion oder Bibliothek für die Zufallszahlengenerierung zu erhalten und zu verwenden. Wenn Sie Ratschläge zur Verwendung der Bibliothek benötigen, möchten Sie möglicherweise spezifische Informationen zu den von Ihnen verwendeten Programmiersprachen hinzufügen.

Bearbeiten: Im Lichte der Kommentare, einiger anderer Antworten und der Tatsache, dass Fixee diese Antwort akzeptiert hat, werde ich einige Details dazu geben, wie man Transformationen von einheitlichen Variablen verwenden kann, um normale Variablen zu erzeugen.

  • Eine Methode, die bereits in einem Kommentar von VitalStatistix erwähnt wurde , ist die Box-Muller-Methode, die zwei unabhängige einheitliche Zufallsvariablen verwendet und zwei unabhängige normale Zufallsvariablen erzeugt. Eine ähnliche Methode, die die Berechnung von zwei transzendentalen Funktionen sin und cos auf Kosten einiger weiterer Simulationen vermeidet , wurde von francogrex als Antwort veröffentlicht .
  • Eine ganz allgemeine Methode ist die Transformation einer einheitlichen Zufallsvariablen durch die inverse Verteilungsfunktion. Wenn auf [ 0 , 1 ] gleichmäßig verteilt ist , dann ist ΦU[0,1] eine Standardnormalverteilung. Obwohl es keine explizite analytische Formel für Φ - 1 gibt , kann sie durch genaue numerische Näherungen berechnet werden. Die aktuelle Implementierung in R (zuletzt überprüft) verwendet diese Idee. Die Methode ist konzeptionell sehr einfach, erfordert jedoch eine genaue Implementierung von Φ - 1 , was wahrscheinlich nicht so verbreitet ist wie die (anderen) transzendentalen Funktionen
    Φ1(U)
    Φ1Φ1log , sin und cos .
  • In mehreren Antworten wird die Möglichkeit erwähnt, den zentralen Grenzwertsatz zu verwenden, um die Normalverteilung als Durchschnitt einheitlicher Zufallsvariablen anzunähern. Dies wird im Allgemeinen nicht empfohlen. Argumente wie die Übereinstimmung von Mittelwert 0 und Varianz 1 und Überlegungen zur Unterstützung der Verteilung sind nicht überzeugend. In Übung 2.3 in "Einführung in Monte-Carlo-Methoden mit R" von Christian P. Robert und George Casella wird dieser Generator als antiquiert und die Approximation als sehr schlecht bezeichnet .
  • Es gibt eine verwirrende Anzahl anderer Ideen. Kapitel 3 und insbesondere Abschnitt 3.4 in "The Art of Computer Programming" Vol. 2 von Donald E. Knuth ist eine klassische Referenz zur Zufallsgenerierung. Brian Ripley schrieb Computer Generation of Random Variables: Ein Tutorial , das nützlich sein kann. Das von Robert und Casella erwähnte Buch oder vielleicht Kapitel 2 in ihrem anderen Buch "Monte-Carlo-statistische Methoden" wird ebenfalls empfohlen.

Letztendlich ist eine korrekt implementierte Methode nicht besser als der verwendete einheitliche Pseudozufallszahlengenerator. Persönlich greife ich lieber auf Spezialbibliotheken zurück, die ich für vertrauenswürdig halte. Ich verlasse mich fast immer auf die in R implementierten Methoden, entweder direkt in R oder über die API in C / C ++. Natürlich ist dies nicht für alle eine Lösung, aber ich kenne andere Bibliotheken nicht gut genug, um Alternativen zu empfehlen.


(+1) Gute Antwort und Beratung für das OP.
Kardinal

18
Ich bin nicht sicher, ob ich hier einen unnötigen Kommentar mache, aber wenn Sie nur Zugriff auf einen einheitlichen Zufallszahlengenerator haben, können Sie die Box-Muller-Transformation verwenden , um unabhängige N (0,1) -Zufallszahlen zu generieren. Kurz gesagt, wenn U_1 und U_2 von der Gleichverteilung (0,1) unabhängig sind, gilt und
2log(U1)cos(2πU2)
werden als unabhängige N (0,1) Zufallsvariablen verteilt. Die Grundidee
2log(U1)sin(2πU2)
VitalStatistix

2
@Vital: Kein unnötiger Kommentar; ein guter. Die Box-Muller-Transformation ist wahrscheinlich die am einfachsten zu programmierende Transformation mit der geringsten Wahrscheinlichkeit, versehentlich etwas Schlechtes zu tun. Es ist nicht die schnellste , aber wettbewerbsfähig genug. Das heißt, die Verwendung einer etablierten Codebibliothek ist wahrscheinlich noch sicherer, zumal der Ort, an dem man am wahrscheinlichsten einen Fehltritt macht, darin besteht, wie die einheitlichen Zufallsvariateingaben erzeugt werden!
Kardinal

@Vital: Danke, das habe ich gesucht. Wenn Sie Ihren Kommentar in eine Antwort umwandeln möchten, würde ich ihn gerne unterstützen.
Fixee

1
@VitalStatistix, es ist ein guter Kommentar, und es scheint, dass dies das war, wonach das OP gesucht hat. Warum nicht eine Antwort daraus machen und vielleicht ein wenig näher auf die allgemeine Idee eingehen, Transformationen einheitlicher Zufallsvariablen zu verwenden? Ich habe aus dem Grund gezögert, den Cardinal erwähnt, weil ich nicht weiß, ob der standardmäßige Uniformgenerator aus einer beliebigen Sprache ein guter Generator ist.
NRH

10

Dies ist wirklich ein Kommentar zu Michael Lews Antwort und Fixees Kommentar, wird aber als Antwort gepostet, da ich auf dieser Site nicht den Ruf habe, einen Kommentar abzugeben.

[0,1]61

E[i=112Xi]=i=112E[Xi]=12×12=6
var[i=112Xi]=i=112var[Xi]=12×112=1.
i=112Xi610/12 to get the desired unit variance. It is also worth remembering that i=112Xi6 can take on values only in the range [6,6] and thus extreme (very low-probability) values differing from the mean by more than 6 standard deviations will never occur. This is often a problem in simulations of computer and communication systems where such very low probability events are of much interest.

5

In addition to the answer by NRH, if you still have no means to generate random samples from a "standard normal distribution" N(0,1), below is a good and simple way (since you mention you don't have a statistical package, the functions below should be available in most standard programming languages).

1. Generate u and v as two uniformly distributed random numbers in the range from -1 to 1 by
u = 2 r1 - 1 and v = 2 r2 - 1

2.calculate w = u^2 + v^2 if w > 1 the go back to 1

3.return u*z and y= v*z with z= sqrt(-2ln(w)/w) A sample code would look like this:

u = 2 * random() - 1;
v = 2 * random() - 1;
w = pow(u, 2) + pow(v, 2);
if (w < 1) {
    z = sqrt((-2 * log(w)) / w);
    x = u * z;
    y = v * z;
    }

then use what MHR has suggested above to obtain the random deviates from N(mu, sigma^2).


When I posted my answer above I didn't notice that @vitalStatistix gave you the Box-Muller Transform algorithm. The one I give above is also as good I suppose.
francogrex

2
Could you please explain the reason for generating normal variates from uniform distribution (other than from an algorithmic perspective) and not just using the pdf of a Gaussian/Normal distribution directly? Or is it totally wrong?
Arun

4
@Arun One reason: The Marsaglia's polar method is useful when you only have a RNG that generates uniform deviates.
chl

1
@Arun it is the easiest way. You can also generate from the pdf directly using for example the "acceptance rejection" method. I posted for you a simple example on my site (because not enough space in the comment box here).
francogrex

4

The normal distribution emerges when one adds together a lot of random values of similar distribution (similar to each other, I mean). If you add together ten or more uniformly distributed random values then the sum is very nearly normally distributed. (Add more than ten if you want it to be even more normal, but ten is enough for almost all purposes.)

Say that your uniform random values are uniformly distributed between 0 and 1. The sum will then be between 0 and 10. Subtract 5 from the sum and the mean of the resulting distribution will be 0. Now you divide the result by the standard deviation of the (near) normal distribution and multiply the result by the desired standard deviation. Unfortunately I'm not sure what the standard deviation of the sum of ten uniform random deviates is, but if we are lucky someone will tell us in a comment!

I prefer to talk to students about the normal distribution in these terms because the utility of the assumption of a normal distribution in many systems stems entirely from the property that the sums of many random influences leads to a normal distribution.


You are using the Central Limit Thm here (that a bunch of iid random variables sum to a normal random variable). I didn't consider this because I thought it would be too slow, but you say 10 is sufficient?! This is better than computing a log and a sin/cos and a sqrt!
Fixee

Also, the mean of the uniform r.v. on [0,1] is 0.5 with variance 1/12. If you sum 10 of these you get a mean of 5 and variance 10/12 = 5/6.
Fixee

1
From a pedagogical standpoint this method provides for a nice, useful discussion and demonstration. However, I would strongly discourage anyone from using this approach in practice.
cardinal

1
@Fixee: You need to be sure and balance the computation of log, sin, cos and the square-root against the generation of additional uniform random variates. For example, Intel CPUs have all four of these functions as built-in operations performed in hardware. The square-root is a fundamental "arithmetic" operation according to the IEEE 754 standards.
cardinal

1
@Michael: Declaring it gives the "right" distribution is a bit of a stretch, particularly since the approximating distribution has compact support and, in many applications, one does care about how efficiently the variates can be generated. :) The point is there are several much better options available. But, I still think it provides something useful pedagogically.
cardinal
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.