Wie permutiert die transpose () -Methode von NumPy die Achsen eines Arrays?

81
In [28]: arr = np.arange(16).reshape((2, 2, 4))

In [29]: arr
Out[29]: 
array([[[ 0,  1,  2,  3],
        [ 4,  5,  6,  7]],

       [[ 8,  9, 10, 11],
        [12, 13, 14, 15]]])


In [32]: arr.transpose((1, 0, 2))
Out[32]: 
array([[[ 0,  1,  2,  3],
        [ 8,  9, 10, 11]],

       [[ 4,  5,  6,  7],
        [12, 13, 14, 15]]])

transpose()Was passiert, wenn wir der Funktion ein Tupel von ganzen Zahlen übergeben ?

Um genau zu sein, ist dies ein 3D-Array: Wie transformiert NumPy das Array, wenn ich das Tupel der Achsen passiere (1, 0 ,2)? Können Sie erklären, auf welche Zeile oder Spalte sich diese Ganzzahlen beziehen? Und was sind Achsnummern im Kontext von NumPy?

Frank Hu
quelle
2
0ist die erste Achse, 1ist die zweite, 2ist die dritte usw. Der axesParameter, transposeder die neue Reihenfolge bereitstellt, in der sie angeordnet werden sollen, in Ihrem Beispiel: zuerst die zweite, dann die erste, dann die dritte.
Jaime
In der 3D-Anzeige befinden sich Blöcke, Zeilen und Spalten. Ihre Transponierung hat die Reihenfolge der Blöcke und Zeilen geändert und die Spalten unverändert gelassen. Was früher die 2. Reihe des 1. Blocks war, wird zur 1. Reihe des 2. Blocks.
hpaulj

Antworten:

183

Um ein Array zu transponieren, tauscht NumPy einfach die Form- und Schrittinformationen für jede Achse aus. Hier sind die Schritte:

>>> arr.strides
(64, 32, 8)

>>> arr.transpose(1, 0, 2).strides
(32, 64, 8)

Beachten Sie, dass bei der Transponierungsoperation die Schritte für Achse 0 und Achse 1 vertauscht wurden. Die Längen dieser Achsen wurden ebenfalls vertauscht ( 2in diesem Beispiel sind beide Längen angegeben ).

Dazu müssen keine Daten kopiert werden. NumPy kann einfach die Darstellung des zugrunde liegenden Speichers ändern, um das neue Array zu erstellen.


Schritte visualisieren

Der Schrittwert gibt die Anzahl der Bytes an, die im Speicher zurückgelegt werden müssen, um den nächsten Wert einer Achse eines Arrays zu erreichen.

Unser 3D-Array arrsieht nun so aus (mit beschrifteten Achsen):

Geben Sie hier die Bildbeschreibung ein

Dieses Array wird in einem zusammenhängenden Speicherblock gespeichert . im wesentlichen ist es eindimensional. Um es als 3D-Objekt zu interpretieren, muss NumPy über eine bestimmte konstante Anzahl von Bytes springen, um sich entlang einer der drei Achsen zu bewegen:

Geben Sie hier die Bildbeschreibung ein

Da jede Ganzzahl 8 Byte Speicher belegt (wir verwenden den Int64-Typ), beträgt der Schrittwert für jede Dimension das 8-fache der Anzahl der Werte, die wir überspringen müssen. Um sich beispielsweise entlang der Achse 1 zu bewegen, werden vier Werte (32 Bytes) übersprungen, und um sich entlang der Achse 0 zu bewegen, müssen acht Werte (64 Bytes) übersprungen werden.

Wenn wir schreiben arr.transpose(1, 0, 2), tauschen wir die Achsen 0 und 1 aus. Das transponierte Array sieht folgendermaßen aus:

Geben Sie hier die Bildbeschreibung ein

Alles, was NumPy tun muss, ist, die Schrittinformationen für Achse 0 und Achse 1 auszutauschen (Achse 2 bleibt unverändert). Jetzt müssen wir weiter springen, um uns entlang der Achse 1 als entlang der Achse 0 zu bewegen:

Geben Sie hier die Bildbeschreibung ein

Dieses Grundkonzept funktioniert für jede Permutation der Achsen eines Arrays. Der eigentliche Code für die Transponierung ist in C geschrieben und befindet sich hier .

Alex Riley
quelle
6
@ Alex: danke! Die Figuren wurden mit draw.io erstellt .
Alex Riley
6

Wie in der Dokumentation erläutert :

Standardmäßig kehren Sie die Abmessungen um, andernfalls permutieren Sie die Achsen gemäß den angegebenen Werten.

Sie können also einen optionalen Parameter übergeben axes, der die neue Reihenfolge der Dimensionen definiert.

Beispiel: Transponieren der ersten beiden Dimensionen eines RGB-VGA-Pixel-Arrays:

 >>> x = np.ones((480, 640, 3))
 >>> np.transpose(x, (1, 0, 2)).shape
 (640, 480, 3)
Falko
quelle
1
Hallo, danke für deine Antwort. Ich kann dieses Problem jedoch immer noch nicht verstehen, wie Sie sehen können, ist die Form von arr (2,2,4) und arr.transpose (1,0,2) ebenfalls (2,2,4). Dies ist ein 3-D-Array. Wie transformiere ich das Array, wenn ich (1,0,2) übergebe? Können Sie erklären, auf welche Zeile oder Spalte sich das 1,0,2 bezieht? Und was sind Achsnummern in Bezug auf Numpy?
Frank Hu
1
@FrankHu visualisieren im 3D-Raum, also ist hier die Drehung der x-, y-Achse passiert. (1,0,2) wurde von (0,1,2) transponiert, so dass die ersten 2 Achsen geschaltet werden. 0 ist die Indexnummer der Achse. Sagen
wir
5

In C-Notation wäre Ihr Array:

int arr[2][2][4]

Dies ist ein 3D-Array mit 2 2D-Arrays. Jedes dieser 2D-Arrays hat 2 1D-Arrays, jedes dieser 1D-Arrays hat 4 Elemente.

Sie haben also drei Dimensionen. Die Achsen sind 0, 1, 2 mit den Größen 2, 2, 4. Genau so behandelt numpy die Achsen eines N-dimensionalen Arrays.

So arr.transpose((1, 0, 2))würde die Achse 1 und legen Sie sie in Position 0, 0 Achse und legen Sie sie in Position 1 und Achse 2 und lassen Sie ihn in Position 2. Sie effektiv die Achsen Permutation:

0 -\/-> 0
1 -/\-> 1
2 ----> 2

Mit anderen Worten 1 -> 0, 0 -> 1, 2 -> 2. Die Zielachsen sind immer in Ordnung. Sie müssen also nur die Quellachsen angeben. Lesen Sie das Tupel in dieser Reihenfolge ab : (1, 0, 2).

In diesem Fall sind Ihre neuen Array-Dimensionen wieder da [2][2][4], nur weil die Achsen 0 und 1 dieselbe Größe hatten (2).

Interessanter ist eine Transponierung, mit (2, 1, 0)der Sie eine Reihe von erhalten [4][2][2].

0 -\ /--> 0
1 --X---> 1
2 -/ \--> 2

Mit anderen Worten 2 -> 0, 1 -> 1, 0 -> 2. Lesen Sie das Tupel in dieser Reihenfolge ab : (2, 1, 0).

>>> arr.transpose((2,1,0))
array([[[ 0,  8],
        [ 4, 12]],

       [[ 1,  9],
        [ 5, 13]],

       [[ 2, 10],
        [ 6, 14]],

       [[ 3, 11],
        [ 7, 15]]])

Sie endeten mit einem int[4][2][2].

Sie werden wahrscheinlich besser verstehen, wenn alle Dimensionen unterschiedlich groß sind, sodass Sie sehen können, wohin die einzelnen Achsen führen.

Warum ist das erste innere Element [0, 8]? Denn wenn Sie Ihr 3D-Array als zwei Blatt Papier visualisieren 0und 8aneinandergereiht sind, eins auf einem Papier und eins auf dem anderen Papier, beide oben links. Durch das Transponieren (2, 1, 0)möchten Sie, dass die Richtung von Papier zu Papier jetzt von links nach rechts entlang des Papiers und die Richtung von links nach rechts von Papier zu Papier verläuft. Sie hatten 4 Elemente von links nach rechts, jetzt haben Sie stattdessen vier Zettel. Und Sie hatten 2 Papiere, also haben Sie jetzt 2 Elemente, die von links nach rechts gehen.

Entschuldigung für die schreckliche ASCII-Kunst. ¯\_(ツ)_/¯

Robert B.
quelle
Habe ich Recht, wenn ich denke, dass das Tupel, dem Sie geben, transpose()keine mathematische Permutation ist oder so? Es ist buchstäblich nur eine Anweisung, die besagt: "Lass die Achsen jetzt in diesen Positionen sein"? Zum Beispiel, weil .transpose(p, q, r, s)Sie sagen "Achse pals 0., qals 1., rals 2. und sals 3. setzen"? Oder anders gesehen b = a.transpose(axes)heißt b.shape == tuple(a.shape[i] for i in axes)?
Tim
Die Idee, die Achse mit ASCII-Kunst zu tauschen, verdeutlicht mein Verständnis. Vielen Dank
K_inverse
0

Es scheint, dass die Frage und das Beispiel aus dem Buch Python for Data Analysis von Wes McKinney stammen. Diese Funktion von transposewird in Kapitel 4.1 erwähnt. Transponieren von Arrays und Vertauschen von Achsen .

transposeAkzeptiert für höherdimensionale Arrays ein Tupel von Achsnummern, um die Achsen zu permutieren (für zusätzliche Gedankenbiegung).

Hier bedeutet "permutieren" "neu anordnen", also die Reihenfolge der Achsen neu anordnen.

Die Zahlen in .transpose(1, 0, 2)bestimmen, wie die Reihenfolge der Achsen im Vergleich zum Original geändert wird. Mit verwenden .transpose(1, 0, 2)wir "Ändern Sie die 1. Axt mit der 2 .." Wenn wir verwenden .transpose(0, 1, 2), bleibt das Array gleich, da nichts geändert werden muss. Dies ist die Standardreihenfolge.

Das Beispiel im Buch mit einem (2, 2, 4)Array mit einer Größe ist nicht sehr klar, da die 1. und 2. Achse dieselbe Größe haben. Das Endergebnis scheint sich also nur durch die Neuordnung der Zeilen arr[0, 1]und zu ändern arr[1, 0].

Wenn wir ein anderes Beispiel mit einem dreidimensionalen Array versuchen, wobei jede Dimension eine andere Größe hat, wird der Umlagerungsteil klarer.

In [2]: x = np.arange(24).reshape(2, 3, 4)

In [3]: x
Out[3]: 
array([[[ 0,  1,  2,  3],
        [ 4,  5,  6,  7],
        [ 8,  9, 10, 11]],

       [[12, 13, 14, 15],
        [16, 17, 18, 19],
        [20, 21, 22, 23]]])

In [4]: x.transpose(1, 0, 2)
Out[4]: 
array([[[ 0,  1,  2,  3],
        [12, 13, 14, 15]],

       [[ 4,  5,  6,  7],
        [16, 17, 18, 19]],

       [[ 8,  9, 10, 11],
        [20, 21, 22, 23]]])

Hier sind die ursprünglichen Arraygrößen (2, 3, 4). Wir haben den 1. und 2. geändert, damit er (3, 2, 4)größer wird. Wenn wir genauer hinschauen, um zu sehen, wie die Umlagerung genau passiert ist; Zahlenfelder scheinen sich in einem bestimmten Muster geändert zu haben. Unter Verwendung der Papieranalogie von @ RobertB hätten wir jetzt ein Array der Größe 3x2x4 , wenn wir die 2 Zahlenblöcke nehmen und jedes auf Blätter schreiben und dann eine Zeile von jedem Blatt nehmen würden, um eine Dimension des Arrays zu konstruieren Zählen von der äußersten bis zur innersten Schicht.

[ 0,  1,  2,  3] \ [12, 13, 14, 15]

[ 4,  5,  6,  7] \ [16, 17, 18, 19]

[ 8,  9, 10, 11] \ [20, 21, 22, 23]

Es könnte eine gute Idee sein, mit Arrays unterschiedlicher Größe zu spielen und verschiedene Achsen zu ändern, um eine bessere Vorstellung davon zu erhalten, wie es funktioniert.

Ayşe Nur
quelle
-3

Um a.transpose () zusammenzufassen [i, j, k] = a [k, j, i]

a = np.array( range(24), int).reshape((2,3,4))
a.shape gives (2,3,4)
a.transpose().shape gives (4,3,2)  shape tuple is reversed.

Wenn ein Tupelparameter übergeben wird, werden die Achsen entsprechend dem Tupel permutiert. Zum Beispiel

a = np.array (Bereich (24), int) .form ((2,3,4))

a [i, j, k] ist gleich a.transponieren ((2,0,1)) [k, i, j]

Achse 0 belegt den 2. Platz

Achse 1 belegt den 3. Platz

Achse 2 Geschichten 1. Platz

Natürlich müssen wir darauf achten, dass die Werte im Tupelparameter, die zur Transponierung übergeben werden, eindeutig und im Bereich (Anzahl der Achsen) sind.

Raghu Ram
quelle
Sie haben die Frage des OP nicht beantwortet. Dies passiert, wenn Sie mit den angegebenen Achsen transponieren .
Robert B
Antwort auf die Frage hinzugefügt, wenn Achsen angegeben sind.
Raghu Ram