2016-08-01 11 views
2

Ich möchte acht Zufallszahlen innerhalb eines Bereichs (0 bis Pi/8) generieren, addieren sie zusammen, nehmen Sie den Sinus dieser Summe, und danach N-mal, nimm das mittlere Ergebnis. Nach dem Skalieren bekomme ich die richtige Antwort, aber es ist zu langsam für N > 10^6, besonders wenn ich über N Versuche n_t = 25 mehr Male male! Ich bekomme derzeit diesen Code in etwa 12 Sekunden für N = 10^5 laufen, was bedeutet, dass es dauert 20 Minuten für N = 10^7, die nicht optimal scheint (es kann sein, ich weiß es nicht!).Optimierung der Generierung einer großen Anzahl von Zufallszahlen mit Python 3

Mein Code ist wie folgt:

import random 
import datetime 
from numpy import pi 
from numpy import sin 
import numpy 
t1 = datetime.datetime.now() 

def trial(N): 
    total = [] 
    uniform = numpy.random.uniform 
    append = total.append 
    for j in range(N): 
     sum = 0 
     for i in range (8): 
      sum+= uniform(0, pi/8) 
     append(sin(sum)) 
    return total 

N = 1000000 
n_t = 25 
total_squared = 0 
ans = [] 
for k in range (n_t): 
    total = trial(N) 
    f_mean = (numpy.sum(total))/N 
    ans.append(f_mean*((pi/8)**8)*1000000) 
sum_square = 0 
for e in ans: 
    sum_square += e**2 
sum = numpy.sum(ans) 
mean = sum/n_t 
variance = sum_square/n_t - mean**2 
s_d = variance**0.5 
print (mean, " ± ", s_d) 
t2 = datetime.datetime.now() 
print ("Execution time: %s" % (t2-t1)) 

Wenn jemand kann mir dabei helfen optimieren es wäre sehr willkommen!

Danke

+0

Was ist das Endziel? Wenn Sie nur einen Durchschnitt berechnen, sollten Sie eher rechnen als eine langwierige Simulation, bei der ohnehin ein statistischer Fehler auftritt. – Julien

+0

Sie möchten also 2 * Milliarden * Zufallszahlen generieren? Das wird sicherlich Zeit brauchen. – justhalf

+0

Vielleicht eine kleine Beschleunigung mit 'sum = numpy.sum (numpy.random.random_sample (8)) * pi_8' –

Antwort

5

Angesichts Ihrer Anforderung, das Ergebnis mit dieser Methode zu erhalten, np.sin(np.random.uniform(0,np.pi/8,size=(8,10**6,25)).sum(axis=0)).mean(axis=0) bekommt Sie Ihre 25 Studien ziemlich schnell ... Dies ist vollständig vektorisiert (und prägnant, das ist immer ein Bonus!), So bezweifle ich, dass Sie es besser machen könnten .. .

Erläuterung:

Du (8 x 10**6 x 25) ein großen zufälligen 3D-Array der Größe erzeugen. .sum(axis=0) erhalten Sie die Summe über die erste Dimension (8). np.sin(...) gilt elementweise. .mean(axis=0) erhalten Sie den Mittelwert über die erste verbleibende Dimension (10**6) und lassen Sie mit einem 1d Array der Länge (25) entsprechend Ihren Studien.

+0

Danke! Wie funktioniert das und wie setze ich das um? Tut mir leid, ich habe erst vor einer Woche begonnen, Python zu lernen, also habe ich nicht viel Ahnung, was ich mache! –

+0

was meinst du? Kopieren und Einfügen sollte funktionieren ... – Julien

+0

Damit wird zuerst alles im Speicher generiert, oder? Also wird es mindestens 8GB für N = 1e7 benötigen. Immer noch in einigen modernen Computern in Ordnung, aber es ist nicht so billig in Bezug auf Speicher. Netter Ansatz auf den Vektoren dort, obwohl. +1 – justhalf

1

Durch den zentralen Grenzwertsatz :), wird Ihre Zufallsvariable eng ein normales Gesetz folgen.

Die Summe der acht Uniformvariablen hat eine glockenförmige Verteilung über den Bereich [0, π]. Wenn ich recht habe, kann die Verteilung als B-Spline der Ordnung 8 dargestellt werden. Unter Verwendung des Sinus ergibt sich ein Wert im Bereich [0, 1]. Sie können die Erwartung μ und Varianz σ² durch einfache numerische Integration finden.

Verwenden Sie dann einen normalen Generator mit Mittelwert μ und Varianz σ²/N. Das wird augenblicklich im Vergleich sein.

+2

gut, wenn Sie für Mathe gehen nicht auf halbem Weg;) – Julien

+0

@JulienBernu: Ich halte nicht auf halbem Weg. Ich erzähle dem OP, wie er eine Zufallsvariable erzeugen kann, die dieselben Eigenschaften wie die aus 8N-Werten berechneten hat. Aber es ist immer noch ein zufälliger Wert. –

Verwandte Themen