webentwicklung-frage-antwort-db.com.de

Mumpy Shuffle multidimensionales Array nur Zeile für Zeile, Spaltenreihenfolge unverändert lassen

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]]
30
robert

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]])
25
Kasrâmvd

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.

19
Divakar

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)))
5
Janmejaya Nanda

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)')
1
Ben-Hur Cardoso

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.

0
TassosK