Wie kann ich ein mehrdimensionales Array nur in Python zeilenweise mischen (also die Spalten nicht mischen)?.
Ich suche die effizienteste Lösung, weil meine Matrix sehr groß ist. Ist es auch möglich, dies auf dem ursprünglichen Array sehr effizient auszuführen (um Speicherplatz zu sparen)?
Beispiel:
import numpy as np
X = np.random.random((6, 2))
print(X)
Y = ???shuffle by row only not colls???
print(Y)
Was ich jetzt erwarte, ist eine Originalmatrix:
[[ 0.48252164 0.12013048]
[ 0.77254355 0.74382174]
[ 0.45174186 0.8782033 ]
[ 0.75623083 0.71763107]
[ 0.26809253 0.75144034]
[ 0.23442518 0.39031414]]
Die Ausgabe mischt die Zeilen nicht, z.
[[ 0.45174186 0.8782033 ]
[ 0.48252164 0.12013048]
[ 0.77254355 0.74382174]
[ 0.75623083 0.71763107]
[ 0.23442518 0.39031414]
[ 0.26809253 0.75144034]]
Dafür ist numpy.random.shuffle()
:
>>> X = np.random.random((6, 2))
>>> X
array([[ 0.9818058 , 0.67513579],
[ 0.82312674, 0.82768118],
[ 0.29468324, 0.59305925],
[ 0.25731731, 0.16676408],
[ 0.27402974, 0.55215778],
[ 0.44323485, 0.78779887]])
>>> np.random.shuffle(X)
>>> X
array([[ 0.9818058 , 0.67513579],
[ 0.44323485, 0.78779887],
[ 0.82312674, 0.82768118],
[ 0.29468324, 0.59305925],
[ 0.25731731, 0.16676408],
[ 0.27402974, 0.55215778]])
Sie können auch np.random.permutation
verwenden, um eine zufällige Permutation von Zeilenindizes zu generieren und dann mit np.take
mit axis=0
in die Zeilen von X
zu indexieren. Außerdem ermöglicht np.take
das Überschreiben des Eingabefeldes X
selbst mit der Option out=
, wodurch Speicherplatz gespart wird. Die Implementierung würde also so aussehen -
np.take(X,np.random.permutation(X.shape[0]),axis=0,out=X)
Probelauf -
In [23]: X
Out[23]:
array([[ 0.60511059, 0.75001599],
[ 0.30968339, 0.09162172],
[ 0.14673218, 0.09089028],
[ 0.31663128, 0.10000309],
[ 0.0957233 , 0.96210485],
[ 0.56843186, 0.36654023]])
In [24]: np.take(X,np.random.permutation(X.shape[0]),axis=0,out=X);
In [25]: X
Out[25]:
array([[ 0.14673218, 0.09089028],
[ 0.31663128, 0.10000309],
[ 0.30968339, 0.09162172],
[ 0.56843186, 0.36654023],
[ 0.0957233 , 0.96210485],
[ 0.60511059, 0.75001599]])
Zusätzliche Leistungssteigerung
Hier ist ein Trick, um np.random.permutation(X.shape[0])
mit np.argsort()
zu beschleunigen -
np.random.Rand(X.shape[0]).argsort()
Ergebnisse beschleunigen -
In [32]: X = np.random.random((6000, 2000))
In [33]: %timeit np.random.permutation(X.shape[0])
1000 loops, best of 3: 510 µs per loop
In [34]: %timeit np.random.Rand(X.shape[0]).argsort()
1000 loops, best of 3: 297 µs per loop
Somit könnte die Mischlösung zu - modifiziert werden.
np.take(X,np.random.Rand(X.shape[0]).argsort(),axis=0,out=X)
Laufzeitprüfungen -
Diese Tests umfassen die beiden in diesem Beitrag aufgelisteten Ansätze und np.shuffle
in @Kasramvd's solution
.
In [40]: X = np.random.random((6000, 2000))
In [41]: %timeit np.random.shuffle(X)
10 loops, best of 3: 25.2 ms per loop
In [42]: %timeit np.take(X,np.random.permutation(X.shape[0]),axis=0,out=X)
10 loops, best of 3: 53.3 ms per loop
In [43]: %timeit np.take(X,np.random.Rand(X.shape[0]).argsort(),axis=0,out=X)
10 loops, best of 3: 53.2 ms per loop
Es scheint also, dass die Verwendung dieser np.take
-basierten Systeme nur dann verwendet werden könnte, wenn der Speicher ein Problem ist oder die np.random.shuffle
-basierte Lösung den Weg zu gehen scheint.
Nach einem kleinen Experiment fand ich die meiste Speicher- und zeiteffiziente Methode, um Daten (reihenweise) von nd-array zu mischen, mischen den Index und erhalten die Daten aus dem gemischten Index
Rand_num2 = np.random.randint(5, size=(6000, 2000))
perm = np.arange(Rand_num2.shape[0])
np.random.shuffle(perm)
Rand_num2 = Rand_num2[perm]
ausführlicher
Hier benutze ich memory_profiler , um die Speicherauslastung und das eingebaute "time" -Modul von python zu finden, um die Zeit aufzuzeichnen und alle vorherigen Antworten zu vergleichen
def main():
# shuffle data itself
Rand_num = np.random.randint(5, size=(6000, 2000))
start = time.time()
np.random.shuffle(Rand_num)
print('Time for direct shuffle: {0}'.format((time.time() - start)))
# Shuffle index and get data from shuffled index
Rand_num2 = np.random.randint(5, size=(6000, 2000))
start = time.time()
perm = np.arange(Rand_num2.shape[0])
np.random.shuffle(perm)
Rand_num2 = Rand_num2[perm]
print('Time for shuffling index: {0}'.format((time.time() - start)))
# using np.take()
Rand_num3 = np.random.randint(5, size=(6000, 2000))
start = time.time()
np.take(Rand_num3, np.random.Rand(rand_num3.shape[0]).argsort(), axis=0, out=Rand_num3)
print("Time taken by np.take, {0}".format((time.time() - start)))
Ergebnis für Zeit
Time for direct shuffle: 0.03345608711242676 # 33.4msec
Time for shuffling index: 0.019818782806396484 # 19.8msec
Time taken by np.take, 0.06726956367492676 # 67.2msec
Speicherprofiler Ergebnis
Line # Mem usage Increment Line Contents
================================================
39 117.422 MiB 0.000 MiB @profile
40 def main():
41 # shuffle data itself
42 208.977 MiB 91.555 MiB Rand_num = np.random.randint(5, size=(6000, 2000))
43 208.977 MiB 0.000 MiB start = time.time()
44 208.977 MiB 0.000 MiB np.random.shuffle(Rand_num)
45 208.977 MiB 0.000 MiB print('Time for direct shuffle: {0}'.format((time.time() - start)))
46
47 # Shuffle index and get data from shuffled index
48 300.531 MiB 91.555 MiB Rand_num2 = np.random.randint(5, size=(6000, 2000))
49 300.531 MiB 0.000 MiB start = time.time()
50 300.535 MiB 0.004 MiB perm = np.arange(Rand_num2.shape[0])
51 300.539 MiB 0.004 MiB np.random.shuffle(perm)
52 300.539 MiB 0.000 MiB Rand_num2 = Rand_num2[perm]
53 300.539 MiB 0.000 MiB print('Time for shuffling index: {0}'.format((time.time() - start)))
54
55 # using np.take()
56 392.094 MiB 91.555 MiB Rand_num3 = np.random.randint(5, size=(6000, 2000))
57 392.094 MiB 0.000 MiB start = time.time()
58 392.242 MiB 0.148 MiB np.take(Rand_num3, np.random.Rand(rand_num3.shape[0]).argsort(), axis=0, out=Rand_num3)
59 392.242 MiB 0.000 MiB print("Time taken by np.take, {0}".format((time.time() - start)))
Sie können ein zweidimensionales Array by row mit der Funktion np.vectorize()
wie folgt mischen:
shuffle = np.vectorize(np.random.permutation, signature='(n)->(n)')
Ich habe eine Frage dazu (oder vielleicht ist es die Antwort). Nehmen wir an, wir haben ein numpy-Array X mit shape = (1000,60,11,1). Nehmen wir auch an, dass X ein Array von Bildern mit der Größe 60x11 und der Kanalnummer = ist 1 (60 x 11 x 1).
Was ist, wenn ich die Reihenfolge all dieser Bilder mischen möchte und dazu die Indizes von X mischen möchte?.
def shuffling( X):
indx=np.arange(len(X)) # create a array with indexes for X data
np.random.shuffle(indx)
X=X[indx]
return X
Wird es funktionieren? Aus meinem Wissen wird len (X) die größte Abmessungsgröße zurückgeben.