Unterschiede zwischen numpy.random und random.random in Python


100

Ich habe ein großes Skript in Python. Ich habe mich im Code anderer Leute inspiriert und das numpy.randomModul für einige Dinge verwendet (zum Beispiel zum Erstellen eines Arrays von Zufallszahlen aus einer Binomialverteilung) und an anderen Stellen verwende ich das Modul random.random.

Kann mir bitte jemand die Hauptunterschiede zwischen den beiden erklären? Wenn ich mir die Doc-Webseite für jede der beiden anschaue, scheint es mir, dass es numpy.randomnur mehr Methoden gibt, aber ich bin mir nicht sicher, wie unterschiedlich die Erzeugung der Zufallszahlen ist.

Der Grund, warum ich frage, ist, dass ich mein Hauptprogramm für Debugging-Zwecke festlegen muss. Aber es funktioniert nur, wenn ich in allen Modulen, die ich importiere, denselben Zufallszahlengenerator verwende. Ist das richtig?

Außerdem habe ich hier in einem anderen Beitrag eine Diskussion über das NICHT-Verwenden gelesen numpy.random.seed(), aber ich habe nicht wirklich verstanden, warum dies eine so schlechte Idee war. Ich würde mich sehr freuen, wenn mir jemand erklären würde, warum dies der Fall ist.

Antworten:


120

Sie haben bereits viele richtige Beobachtungen gemacht!

Wenn Sie nicht beide Zufallsgeneratoren setzen möchten, ist es auf lange Sicht wahrscheinlich einfacher, den einen oder anderen Generator auszuwählen. Wenn Sie jedoch beide verwenden müssen, müssen Sie beide auch setzen, da sie unabhängig voneinander Zufallszahlen generieren.

Für numpy.random.seed()die Hauptschwierigkeit ist, dass es nicht Thread-sicher ist - das heißt, es ist nicht sicher zu verwenden , wenn Sie viele verschiedene Ausführungs - Threads , weil es an der Arbeit nicht gewährleistet ist , wenn zwei verschiedene Threads die Funktion zur gleichen Zeit ausgeführt werden . Wenn Sie keine Threads verwenden und vernünftigerweise erwarten können, dass Sie Ihr Programm in Zukunft nicht mehr auf diese Weise neu schreiben müssen, numpy.random.seed()sollte dies in Ordnung sein. Wenn Grund zu der Annahme besteht, dass Sie in Zukunft möglicherweise Threads benötigen, ist es auf lange Sicht viel sicherer, die vorgeschlagenen Schritte auszuführen und eine lokale Instanz der numpy.random.RandomKlasse zu erstellen . Soweit ich das beurteilen kann, random.random.seed()ist es threadsicher (oder zumindest habe ich keine gegenteiligen Beweise gefunden).

Die numpy.randomBibliothek enthält einige zusätzliche Wahrscheinlichkeitsverteilungen, die üblicherweise in der wissenschaftlichen Forschung verwendet werden, sowie einige praktische Funktionen zum Generieren von Arrays zufälliger Daten. Die random.randomBibliothek ist etwas leichter und sollte in Ordnung sein, wenn Sie keine wissenschaftliche Forschung oder andere Arbeiten in der Statistik betreiben.

Andernfalls verwenden beide die Mersenne-Twister-Sequenz , um ihre Zufallszahlen zu generieren, und sie sind beide vollständig deterministisch. Wenn Sie also einige wichtige Informationen kennen, können Sie mit absoluter Sicherheit vorhersagen, welche Zahl als nächstes kommt . Aus diesem Grund ist weder numpy.random noch random.random für ernsthafte kryptografische Zwecke geeignet . Da die Sequenz jedoch sehr lang ist, eignen sich beide gut zum Generieren von Zufallszahlen, wenn Sie sich keine Sorgen über Personen machen, die versuchen, Ihre Daten rückzuentwickeln. Dies ist auch der Grund für die Notwendigkeit, den Zufallswert zu setzen - wenn Sie jedes Mal an derselben Stelle beginnen, erhalten Sie immer die gleiche Folge von Zufallszahlen!

Als Randbemerkung, wenn Sie keine Verschlüsselungs Ebene Zufälligkeit benötigen, sollten Sie die Verwendung Geheimnisse Modul, oder so etwas wie Crypto.Random , wenn Sie eine Python - Version früher als Python 3.6 verwenden.


14
Als entfernter verwandte Note, dann ist es manchmal neccesary verwenden weder , da die Mersenne - Twister nicht zufälligen Sequenzen der Entropie ausreichend produziert für Kryptographie (und einige ungewöhnliche wissenschaftliche Zwecke). In diesen seltenen Fällen benötigen Sie häufig Crypto.Random , das OS-spezifische Entropiequellen verwenden kann, um nicht deterministische Zufallssequenzen von viel höherer Qualität zu generieren, als sie random.randomallein verfügbar sind . Normalerweise brauchen Sie das aber nicht.
SingleNegationElimination

Danke Hannnele. Ihre Erkenntnisse waren wirklich sehr nützlich! Es stellt sich heraus, dass ich nicht NUR einen einzigen Zufallszahlengenerator verwenden kann (der numpy sein muss, da zufällig keine Binomialverteilungen erzeugt), weil Teile meines Programms ein anderes Programm aufrufen, das zufällig verwendet. Ich werde die beiden Generatoren säen müssen.
Laura

2
"Wenn Sie wissen, welche Nummer Sie jetzt haben, können Sie mit absoluter Sicherheit vorhersagen, welche Nummer als nächstes kommt." Ich denke, diese Aussage bedarf möglicherweise einer Klarstellung. Gemeint ist, dass Sie, wenn Sie den internen Zustand des Generators kennen, die Sequenz reproduzieren können - was Sie tun, wenn Sie den Generator säen. Wenn eine einzelne Zahl vom Generator ausgegeben wird, können Sie die nächste Zahl nicht vorhersagen. Die Periode ist so groß, dass Sie wahrscheinlich eine lange Folge von Zahlen benötigen würden, bevor Sie berechnen könnten, wo Sie sich in der Pseudozufallsfolge befinden, und somit die nächste vorhersagen könnten.
Kaushik Ghose

12

Aus Python für die Datenanalysenumpy.random ergänzt das Modul den Python randommit Funktionen zum effizienten Generieren ganzer Arrays von Stichprobenwerten aus vielen Arten von Wahrscheinlichkeitsverteilungen.

Im Gegensatz dazu tastet das in Python integrierte randomModul jeweils nur einen Wert ab, während numpy.randomsehr große Samples schneller generiert werden können. Mit der IPython Magic-Funktion %timeitkann man sehen, welches Modul schneller arbeitet:

In [1]: from random import normalvariate
In [2]: N = 1000000

In [3]: %timeit samples = [normalvariate(0, 1) for _ in xrange(N)]
1 loop, best of 3: 963 ms per loop

In [4]: %timeit np.random.normal(size=N)
10 loops, best of 3: 38.5 ms per loop

1
Nicht der Fall für andere Methoden. im Vergleich np.random.randint(2)zu random.randrange(2)und NumPy war langsamer . NumPy: 1,25 us und Random: 891 ns. Und auch die gleiche Beziehung für np.random.rand()und random.random().
Shayan Amani

3

Die Quelle des Seeds und das verwendete Verteilungsprofil wirken sich auf die Ausgaben aus. Wenn Sie nach kryptografischer Zufälligkeit suchen, werden beim Seeding von os.urandom () nahezu echte zufällige Bytes vom Geräte-Chatter (dh Ethernet oder Festplatte) (dh /) abgerufen. dev / random auf BSD)

Dadurch wird vermieden, dass Sie einen Startwert angeben und so deterministische Zufallszahlen generieren. Die zufälligen Aufrufe ermöglichen es Ihnen dann jedoch, die Zahlen an eine Verteilung anzupassen (was ich als wissenschaftliche Zufälligkeit bezeichne - schließlich ist alles, was Sie wollen, eine Glockenkurvenverteilung von Zufallszahlen. Numpy ist am besten darin, dies zu untersuchen.

Also ja, bleiben Sie bei einem Generator, aber entscheiden Sie, welchen Zufall Sie wollen - zufällig, aber definitiv aus einer Verteilungskurve oder so zufällig, wie Sie es ohne ein Quantengerät bekommen können.


Vielen Dank Paul, deine Antwort war wirklich nützlich! Ich suche keine kryptografische Zufälligkeit, ich mache mathematische Modellierung und Pseudozufallszahlen sind genug für mich. Es stellt sich heraus, dass ich mich nicht wie gewünscht an einen Generator halten kann, da ich numpy für die Binomialverteilung benötige und mein Programm ein anderes Programm aufruft, das zufällig verwendet :(
Laura
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.