Ich habe zwei numpy Arrays unterschiedlicher Form, aber mit der gleichen Länge (führende Dimension). Ich möchte jeden von ihnen so mischen, dass die entsprechenden Elemente weiterhin übereinstimmen - dh sie in Bezug auf ihre Leitindizes im Einklang mischen.
Dieser Code funktioniert und veranschaulicht meine Ziele:
def shuffle_in_unison(a, b):
assert len(a) == len(b)
shuffled_a = numpy.empty(a.shape, dtype=a.dtype)
shuffled_b = numpy.empty(b.shape, dtype=b.dtype)
permutation = numpy.random.permutation(len(a))
for old_index, new_index in enumerate(permutation):
shuffled_a[new_index] = a[old_index]
shuffled_b[new_index] = b[old_index]
return shuffled_a, shuffled_b
Beispielsweise:
>>> a = numpy.asarray([[1, 1], [2, 2], [3, 3]])
>>> b = numpy.asarray([1, 2, 3])
>>> shuffle_in_unison(a, b)
(array([[2, 2],
[1, 1],
[3, 3]]), array([2, 1, 3]))
Dies fühlt sich jedoch klobig, ineffizient und langsam an und erfordert das Erstellen einer Kopie der Arrays. Ich würde sie lieber an Ort und Stelle mischen, da sie ziemlich groß sind.
Gibt es einen besseren Weg, dies zu tun? Schnellere Ausführung und geringere Speichernutzung sind meine Hauptziele, aber eleganter Code wäre auch schön.
Ein anderer Gedanke, den ich hatte, war folgender:
def shuffle_in_unison_scary(a, b):
rng_state = numpy.random.get_state()
numpy.random.shuffle(a)
numpy.random.set_state(rng_state)
numpy.random.shuffle(b)
Das funktioniert ... aber es ist ein wenig beängstigend, da ich wenig Garantie dafür sehe, dass es weiterhin funktioniert - es sieht nicht so aus, als würde es zum Beispiel in der Numpy-Version garantiert überleben.
Antworten:
Ihre "beängstigende" Lösung erscheint mir nicht beängstigend. Das Aufrufen
shuffle()
von zwei Sequenzen gleicher Länge führt zu der gleichen Anzahl von Aufrufen des Zufallszahlengenerators, und dies sind die einzigen "zufälligen" Elemente im Zufallsalgorithmus. Durch Zurücksetzen des Status stellen Sie sicher, dass die Aufrufe des Zufallszahlengenerators beim zweiten Aufruf dieselben Ergebnisse liefernshuffle()
, sodass der gesamte Algorithmus dieselbe Permutation generiert.Wenn Ihnen dies nicht gefällt, besteht eine andere Lösung darin, Ihre Daten von Anfang an in einem Array statt in zwei zu speichern und zwei Ansichten in diesem einzelnen Array zu erstellen, um die beiden Arrays zu simulieren, die Sie jetzt haben. Sie können das einzelne Array zum Mischen und die Ansichten für alle anderen Zwecke verwenden.
Beispiel: Nehmen wir die Arrays an
a
undb
sehen folgendermaßen aus:Wir können jetzt ein einzelnes Array erstellen, das alle Daten enthält:
Jetzt erstellen wir Ansichten, die das Original simulieren
a
undb
:Die Daten von
a2
und werdenb2
mit geteiltc
. Verwenden Sie, um beide Arrays gleichzeitig zu mischennumpy.random.shuffle(c)
.Im Produktionscode würden Sie natürlich versuchen, das Erstellen des Originals zu vermeiden
a
undb
überhaupt und sofort zu erstellenc
,a2
undb2
.Diese Lösung könnte an den Fall angepasst werden
a
undb
unterschiedliche dtypen haben.quelle
numpy.random.shuffle()
beliebige veränderbare Sequenzen wie Python-Listen oder NumPy-Arrays verarbeitet werden. Die Arrayform spielt keine Rolle, nur die Länge der Sequenz. Dies ist sehr unwahrscheinlich , meiner Meinung nach ändern.Sie können die Array-Indizierung von NumPy verwenden :
Dies führt zur Erstellung separater unisono gemischter Arrays.
quelle
>>> t = timeit.Timer(stmt = "<function>(a,b)", setup = "import numpy as np; a,b = np.arange(4), np.arange(4*20).reshape((4,20))")>>> t.timeit()
38 Sekunden für die OP-Version und 27,5 Sekunden für meine Version für jeweils 1 Million Anrufe zu erhalten.a.shape
ist(31925, 405)
undb.shape
ist(31925,)
.Weitere Informationen finden Sie unter http://scikit-learn.org/stable/modules/generated/sklearn.utils.shuffle.html
quelle
Sehr einfache Lösung:
Die beiden Arrays x, y werden nun auf dieselbe Weise zufällig gemischt
quelle
James schrieb 2015 eine sklearn- Lösung, die hilfreich ist. Aber er fügte eine zufällige Zustandsvariable hinzu, die nicht benötigt wird. Im folgenden Code wird automatisch der Zufallszustand von numpy angenommen.
quelle
quelle
Mische eine beliebige Anzahl von Arrays an Ort und Stelle mit nur NumPy.
Und kann so verwendet werden
Ein paar Dinge zu beachten:
Nach dem Mischen können die Daten
np.split
je nach Anwendung mithilfe von Slices aufgeteilt oder mit Slices referenziert werden.quelle
RandomState
könnte außerhalb der Schleife verwendet werden. Siehe Adam Snaiders Antwortfor
Schleife getroffen werden muss, ist, ob der zufällige Zustand neu zugewiesen oder neu gesetzt werden soll. Da die Anzahl der Arrays, die an eine Mischfunktion übergeben werden, voraussichtlich gering ist, würde ich keinen Leistungsunterschied zwischen beiden erwarten. Aber ja, rstate könnte außerhalb der Schleife zugewiesen und bei jeder Iteration innerhalb der Schleife neu gesetzt werden.Sie können ein Array erstellen wie:
dann mische es:
Verwenden Sie dies jetzt als Argument für Ihre Arrays. Gleiche gemischte Argumente geben dieselben gemischten Vektoren zurück.
quelle
Eine Möglichkeit, das direkte Mischen für verbundene Listen durchzuführen, besteht darin, einen Startwert (der zufällig sein kann) und numpy.random.shuffle zum Mischen zu verwenden.
Das ist es. Dadurch werden sowohl a als auch b auf genau dieselbe Weise gemischt. Dies geschieht auch vor Ort, was immer von Vorteil ist.
BEARBEITEN, verwenden Sie nicht np.random.seed (), sondern verwenden Sie stattdessen np.random.RandomState
Wenn Sie es aufrufen, geben Sie einfach einen beliebigen Startwert ein, um den zufälligen Status zu füttern:
Ausgabe:
Bearbeiten: Code behoben, um den Zufallsstatus neu zu setzen
quelle
RandomState
ändert den Status beim ersten Anrufa
undb
wird nicht gleichzeitig gemischt.Es gibt eine bekannte Funktion, die damit umgehen kann:
Wenn Sie test_size auf 0 setzen, wird das Teilen vermieden und Sie erhalten gemischte Daten. Obwohl es normalerweise zum Teilen von Zug- und Testdaten verwendet wird, werden diese auch gemischt.
Aus der Dokumentation
quelle
Angenommen, wir haben zwei Arrays: a und b.
Wir können zuerst Zeilenindizes erhalten, indem wir die erste Dimension permutieren
Verwenden Sie dann die erweiterte Indizierung. Hier verwenden wir dieselben Indizes, um beide Arrays gleichzeitig zu mischen.
Dies entspricht
quelle
Wenn Sie das Kopieren von Arrays vermeiden möchten, würde ich vorschlagen, dass Sie anstelle einer Permutationsliste jedes Element im Array durchgehen und es zufällig an eine andere Position im Array tauschen
Dies implementiert den Knuth-Fisher-Yates-Shuffle-Algorithmus.
quelle
len(a)
durchreversed(range(1, len(a)))
. Aber es wird sowieso nicht sehr effizient sein.Dies scheint eine sehr einfache Lösung zu sein:
quelle
Mit einem Beispiel mache ich Folgendes:
quelle
combo = zip(images, labels); shuffle(combo); im, lab = zip(*combo)
nur langsamer. Da Sie Numpy sowieso verwenden, besteht eine noch viel schnellere Lösung darin, die Arrays mit Numpy zu komprimierencombo = np.c_[images, labels]
, zu mischen und erneut zu entpackenimages, labels = combo.T
. Unter der Annahme , dasslabels
undimages
sind eindimensionale Numpy Arrays die gleiche Länge zu beginnen, wird dies die schnellste Lösung leicht sein. Wenn sie mehrdimensional sind, siehe meine Antwort oben.Ich habe Pythons random.shuffle () erweitert, um ein zweites Argument zu nehmen:
Auf diese Weise kann ich sicher sein, dass das Mischen an Ort und Stelle erfolgt und die Funktion nicht allzu lang oder kompliziert ist.
quelle
Verwenden Sie einfach
numpy
...Führen Sie zuerst die beiden Eingabearrays 1D-Array mit Beschriftungen (y) und 2D-Array mit Daten (x) zusammen und mischen Sie sie mit der NumPy-
shuffle
Methode. Schließlich teilen Sie sie und kehren Sie zurück.quelle