Usa una visualizzazione e ottieni runtime gratuito! Estendi n-dimarray generici an+1-dim
Introdotto in NumPy1.10.0 , possiamo sfruttare numpy.broadcast_toper generare semplicemente una 3Dvista 2Dnell'array di input. Il vantaggio sarebbe l'assenza di sovraccarico di memoria aggiuntivo e il runtime praticamente gratuito. Ciò sarebbe essenziale nei casi in cui gli array sono grandi e possiamo lavorare con le visualizzazioni. Inoltre, questo funzionerebbe con n-dimcasi generici .
Userei la parola stackal posto di copy, poiché i lettori potrebbero confonderla con la copia di array che crea copie di memoria.
Impila lungo il primo asse
Se vogliamo impilare l'input arrlungo il primo asse, la soluzione con cui np.broadcast_tocreare la 3Dvista sarebbe:
np.broadcast_to(arr,(3,)+arr.shape) # N = 3 here
Impila lungo il terzo / ultimo asse
Per impilare l'input arrlungo il terzo asse, la soluzione per creare la 3Dvista sarebbe:
np.broadcast_to(arr[...,None],arr.shape+(3,))
Se abbiamo effettivamente bisogno di una copia in memoria, possiamo sempre aggiungerla .copy()lì. Quindi, le soluzioni sarebbero:
np.broadcast_to(arr,(3,)+arr.shape).copy()
np.broadcast_to(arr[...,None],arr.shape+(3,)).copy()
Ecco come funziona l'impilamento per i due casi, mostrato con le informazioni sulla forma per un caso campione:
# 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)
Le stesse soluzioni funzionerebbero per estendere un n-diminput per n+1-dimvisualizzare l'output lungo il primo e l'ultimo asse. Esploriamo alcuni casi più scuri -
Caso di input 3D:
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)
Caso di input 4D:
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)
e così via.
Tempistiche
Usiamo un 2Dcaso campione di grandi dimensioni, otteniamo i tempi e verifichiamo che l'output sia un file view.
# Sample input array
In [19]: arr = np.random.rand(1000,1000)
Dimostriamo che la soluzione proposta è davvero una vista. Useremo lo stacking lungo il primo asse (i risultati sarebbero molto simili per lo stacking lungo il terzo asse) -
In [22]: np.shares_memory(arr, np.broadcast_to(arr,(3,)+arr.shape))
Out[22]: True
Prendiamo i tempi per dimostrare che è praticamente gratuito -
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
Essendo una vista, aumentando Nda 3a 3000non cambia nulla sui tempi ed entrambi sono trascurabili sulle unità di temporizzazione. Quindi, efficiente sia sulla memoria che sulle prestazioni!
b[:,:,0],b[:,:,1]eb[:,:,2]. Ogni fetta di terza dimensione è una copia della matrice 2D originale. Questo non è così ovvio solo a guardarloprint(b).