Verwenden Sie eine Ansicht und erhalten Sie freie Laufzeit! Erweitern Sie generische n-dim
Arrays aufn+1-dim
In NumPy eingeführt1.10.0
, können wir nutzen, numpy.broadcast_to
um einfach eine 3D
Ansicht in das 2D
Eingabearray zu generieren . Der Vorteil wäre kein zusätzlicher Speicheraufwand und praktisch freie Laufzeit. Dies ist in Fällen wichtig, in denen die Arrays groß sind und wir mit Ansichten arbeiten können. Dies würde auch bei generischen n-dim
Fällen funktionieren .
Ich würde das Wort stack
anstelle von verwenden copy
, da die Leser es möglicherweise mit dem Kopieren von Arrays verwechseln, die Speicherkopien erstellen.
Stapel entlang der ersten Achse
Wenn wir Eingaben arr
entlang der ersten Achse stapeln möchten , wäre die Lösung np.broadcast_to
zum Erstellen einer 3D
Ansicht:
np.broadcast_to(arr,(3,)+arr.shape) # N = 3 here
Stapel entlang der dritten / letzten Achse
Um Eingaben arr
entlang der dritten Achse zu stapeln , wäre die Lösung zum Erstellen einer 3D
Ansicht:
np.broadcast_to(arr[...,None],arr.shape+(3,))
Wenn wir tatsächlich eine Speicherkopie benötigen, können wir diese jederzeit anhängen .copy()
. Daher wären die Lösungen -
np.broadcast_to(arr,(3,)+arr.shape).copy()
np.broadcast_to(arr[...,None],arr.shape+(3,)).copy()
So funktioniert das Stapeln für die beiden Fälle, die mit ihren Forminformationen für einen Beispielfall angezeigt werden:
# Create a sample input array of shape (4,5)
In [55]: arr = np.random.rand(4,5)
# Stack along first axis
In [56]: np.broadcast_to(arr,(3,)+arr.shape).shape
Out[56]: (3, 4, 5)
# Stack along third axis
In [57]: np.broadcast_to(arr[...,None],arr.shape+(3,)).shape
Out[57]: (4, 5, 3)
Dieselben Lösungen würden funktionieren, um eine n-dim
Eingabe zu erweitern und die n+1-dim
Ausgabe entlang der ersten und letzten Achse anzuzeigen. Lassen Sie uns einige Fälle mit höherer Dunkelheit untersuchen -
3D-Eingabefall:
In [58]: arr = np.random.rand(4,5,6)
# Stack along first axis
In [59]: np.broadcast_to(arr,(3,)+arr.shape).shape
Out[59]: (3, 4, 5, 6)
# Stack along last axis
In [60]: np.broadcast_to(arr[...,None],arr.shape+(3,)).shape
Out[60]: (4, 5, 6, 3)
4D Eingangsfall:
In [61]: arr = np.random.rand(4,5,6,7)
# Stack along first axis
In [62]: np.broadcast_to(arr,(3,)+arr.shape).shape
Out[62]: (3, 4, 5, 6, 7)
# Stack along last axis
In [63]: np.broadcast_to(arr[...,None],arr.shape+(3,)).shape
Out[63]: (4, 5, 6, 7, 3)
und so weiter.
Timings
Lassen Sie uns einen großen Beispielfall verwenden 2D
und die Timings abrufen und überprüfen, ob die Ausgabe a ist view
.
# Sample input array
In [19]: arr = np.random.rand(1000,1000)
Lassen Sie uns beweisen, dass die vorgeschlagene Lösung tatsächlich eine Ansicht ist. Wir werden das Stapeln entlang der ersten Achse verwenden (die Ergebnisse für das Stapeln entlang der dritten Achse wären sehr ähnlich) -
In [22]: np.shares_memory(arr, np.broadcast_to(arr,(3,)+arr.shape))
Out[22]: True
Lassen Sie uns das Timing zeigen, dass es praktisch kostenlos ist -
In [20]: %timeit np.broadcast_to(arr,(3,)+arr.shape)
100000 loops, best of 3: 3.56 µs per loop
In [21]: %timeit np.broadcast_to(arr,(3000,)+arr.shape)
100000 loops, best of 3: 3.51 µs per loop
Eine Ansicht zu sein, N
von 3
zu 3000
ändern, hat nichts an Timings geändert und beide sind an Timing-Einheiten vernachlässigbar. Daher effizient sowohl im Speicher als auch in der Leistung!
b[:,:,0]
,b[:,:,1]
undb[:,:,2]
. Jedes Slice der dritten Dimension ist eine Kopie des ursprünglichen 2D-Arrays. Das ist nicht so offensichtlich, wenn man es nur ansiehtprint(b)
.