Skip to content

NumPy: Aggiungere nuove dimensioni a ndarray (np.newaxis, np.expand_dims)

Python

È possibile aggiungere nuove dimensioni a un array NumPy ndarray (= decomprimere un array NumPy) con np.newaxis, np.expand_dims() e np.reshape() (o il metodo reshape() di ndarray).

np.expand_dims() è simile a torch.unsqueeze() in PyTorch. Si noti che np.unsqueeze() non è fornito.

In questo articolo vengono descritti i seguenti contenuti.

  • Vieni a usare np.newaxis
    • np.newaxis è Nessuno
    • Aggiungi nuove dimensioni con np.newaxis
    • Controlla la trasmissione con np.newaxis
  • Aggiungi una nuova dimensione con np.expand_dims()
  • np.reshape()

Puoi usare il metodo np.reshape() o reshape() di ndarray non solo per aggiungere dimensioni ma anche per cambiare forma.

È possibile utilizzare np.squeeze() per rimuovere le dimensioni di dimensione 1.

Vieni a usare np.newaxis

np.newaxis è Nessuno

np.newaxis è un alias per Nessuno.

import numpy as np

print(np.newaxis is None)
# True

Viene solo dato un alias per rendere più facile da capire. Se sostituisci np.newaxis nel codice di esempio seguente con None, funziona allo stesso modo.

Aggiungi nuove dimensioni con np.newaxis

L’utilizzo di np.newaxis all’interno di [] aggiunge una nuova dimensione di dimensione 1 in quella posizione.

a = np.arange(6).reshape(2, 3)
print(a)
# [[0 1 2]
#  [3 4 5]]

print(a.shape)
# (2, 3)

print(a[:, :, np.newaxis])
# [[[0]
#   [1]
#   [2]]
# 
#  [[3]
#   [4]
#   [5]]]

print(a[:, :, np.newaxis].shape)
# (2, 3, 1)
print(a[:, np.newaxis, :])
# [[[0 1 2]]
# 
#  [[3 4 5]]]

print(a[:, np.newaxis, :].shape)
# (2, 1, 3)
print(a[np.newaxis, :, :])
# [[[0 1 2]
#   [3 4 5]]]

print(a[np.newaxis, :, :].shape)
# (1, 2, 3)

Il finale: in [] può essere omesso.

print(a[:, np.newaxis])
# [[[0 1 2]]
# 
#  [[3 4 5]]]

print(a[:, np.newaxis].shape)
# (2, 1, 3)
print(a[np.newaxis])
# [[[0 1 2]
#   [3 4 5]]]

print(a[np.newaxis].shape)
# (1, 2, 3)

Consecutivo : può essere sostituito con …. Se vuoi aggiungere una nuova dimensione all’ultima dimensione di ndarray, che ha molte dimensioni, è più facile da usare ….

print(a[..., np.newaxis])
# [[[0]
#   [1]
#   [2]]
# 
#  [[3]
#   [4]
#   [5]]]

print(a[..., np.newaxis].shape)
# (2, 3, 1)

Puoi utilizzare più np.newaxis contemporaneamente. Vengono aggiunte più dimensioni.

print(a[np.newaxis, :, np.newaxis, :, np.newaxis])
# [[[[[0]
#     [1]
#     [2]]]
# 
# 
#   [[[3]
#     [4]
#     [5]]]]]

print(a[np.newaxis, :, np.newaxis, :, np.newaxis].shape)
# (1, 2, 1, 3, 1)

L’aggiunta di una dimensione tramite np.newaxis aggiunge una vista dell’oggetto originale. Perché l’oggetto originale e l’oggetto di visualizzazione la memoria, la modifica di un elemento modifica l’altro elemento.

a_newaxis = a[:, :, np.newaxis]

print(np.shares_memory(a, a_newaxis))
# True

Controlla la trasmissione con np.newaxis

Nel funzionamento di due array NumPy, vengono automaticamente rimodellati nella stessa forma della trasmissione.

a = np.zeros(27, dtype=np.int).reshape(3, 3, 3)
print(a)
# [[[0 0 0]
#   [0 0 0]
#   [0 0 0]]
# 
#  [[0 0 0]
#   [0 0 0]
#   [0 0 0]]
# 
#  [[0 0 0]
#   [0 0 0]
#   [0 0 0]]]

print(a.shape)
# (3, 3, 3)

b = np.arange(9).reshape(3, 3)
print(b)
# [[0 1 2]
#  [3 4 5]
#  [6 7 8]]

print(b.shape)
# (3, 3)

print(a + b)
# [[[0 1 2]
#   [3 4 5]
#   [6 7 8]]
# 
#  [[0 1 2]
#   [3 4 5]
#   [6 7 8]]
# 
#  [[0 1 2]
#   [3 4 5]
#   [6 7 8]]]

Nella trasmissione, una nuova dimensione viene aggiunta all’inizio dell’array con un numero di dimensioni inferiore.

Se aggiungi una nuova dimensione all’inizio con np.newaxis, il risultato sarà lo stesso come se fosse stata automaticamente convertita dalla trasmissione.

print(b[np.newaxis, :, :].shape)
# (1, 3, 3)

print(a + b[np.newaxis, :, :])
# [[[0 1 2]
#   [3 4 5]
#   [6 7 8]]
# 
#  [[0 1 2]
#   [3 4 5]
#   [6 7 8]]
# 
#  [[0 1 2]
#   [3 4 5]
#   [6 7 8]]]

La modifica della posizione da aggiungere risultati diversi.

print(b[:, np.newaxis, :].shape)
# (3, 1, 3)

print(a + b[:, np.newaxis, :])
# [[[0 1 2]
#   [0 1 2]
#   [0 1 2]]
# 
#  [[3 4 5]
#   [3 4 5]
#   [3 4 5]]
# 
#  [[6 7 8]
#   [6 7 8]
#   [6 7 8]]]
print(b[:, :, np.newaxis].shape)
# (3, 3, 1)

print(a + b[:, :, np.newaxis])
# [[[0 0 0]
#   [1 1 1]
#   [2 2 2]]
# 
#  [[3 3 3]
#   [4 4 4]
#   [5 5 5]]
# 
#  [[6 6 6]
#   [7 7 7]
#   [8 8 8]]]

Ad esempio, se desideri aggiungere o sottrarre array di immagini a colori (forma:(height, width, color)) and monochromatic image (shape: (height, width)), it is impossible to broadcast the image as it is, but adding a new dimension at the end of the monochromatic image works well.

Aggiungi una nuova dimensione con np.expand_dims()

Puoi anche aggiungere una nuova dimensione a un array NumPy con np.expand_dims().

Specificare il ndarray originale nel primo argomento e la posizione per aggiungere la dimensione nel secondo asse degli argomenti.

a = np.arange(6).reshape(2, 3)
print(a)
# [[0 1 2]
#  [3 4 5]]

print(np.expand_dims(a, 0))
# [[[0 1 2]
#   [3 4 5]]]

print(np.expand_dims(a, 0).shape)
# (1, 2, 3)

È possibile inserire una nuova quota in qualsiasi posizione come segue:

print(np.expand_dims(a, 0).shape)
# (1, 2, 3)

print(np.expand_dims(a, 1).shape)
# (2, 1, 3)

print(np.expand_dims(a, 2).shape)
# (2, 3, 1)

È possibile specificare un valore negativo per il secondo asse degli argomenti. -1 corrisponde all’ultima dimensione ed è possibile specificare la posizione da dietro.

print(np.expand_dims(a, -1).shape)
# (2, 3, 1)

print(np.expand_dims(a, -2).shape)
# (2, 1, 3)

print(np.expand_dims(a, -3).shape)
# (1, 2, 3)

In NumPy 1.17, la specifica di un valore come asse > a.ndim o asse < -a.ndim – 1 nel secondo argomento asse non provoca un errore e la dimensione viene aggiunta alla fine o all’inizio.

Tuttavia, come dice il messaggio di avviso, causerà un errore in futuro, quindi evitarlo.

print(np.expand_dims(a, 3).shape)
# (2, 3, 1)
# 
# /usr/local/lib/python3.7/site-packages/ipykernel_launcher.py:1: DeprecationWarning: Both axis > a.ndim and axis < -a.ndim - 1 are deprecated and will raise an AxisError in the future.
#   """Entry point for launching an IPython kernel.

print(np.expand_dims(a, -4).shape)
# (2, 1, 3)
# 
# /usr/local/lib/python3.7/site-packages/ipykernel_launcher.py:1: DeprecationWarning: Both axis > a.ndim and axis < -a.ndim - 1 are deprecated and will raise an AxisError in the future.
#   """Entry point for launching an IPython kernel.

È possibile specificare solo valori interni nel secondo asse degli argomenti. È impossibile aggiungere più dimensioni contemporaneamente specificando più posizioni con elenco o tupla.

# print(np.expand_dims(a, (0, 1)).shape)
# TypeError: '>' not supported between instances of 'tuple' and 'int'

Vieni con np.newaxis, np.expand_dims() richiede una vista.

a_expand_dims = np.expand_dims(a, 0)

print(np.shares_memory(a, a_expand_dims))
# True

Naturalmente, puoi controllare la trasmissione aggiungendo una nuova dimensione con np.expand_dims() come nell’esempio di np.newaxis sopra.

np.reshape()

Puoi rimodellare ndarray con il metodo np.reshape() o reshape() di ndarray. Vedere il seguente articolo per i dettagli.

Se si specifica una forma con una nuova dimensione da reshape(), il risultato è, ovviamente, lo stesso di quando si utilizza np.newaxis o np.expand_dims().

a = np.arange(6).reshape(2, 3)
print(a)
# [[0 1 2]
#  [3 4 5]]

print(a.shape)
# (2, 3)

print(a[np.newaxis])
# [[[0 1 2]
#   [3 4 5]]]

print(a[np.newaxis].shape)
# (1, 2, 3)

print(np.expand_dims(a, 0))
# [[[0 1 2]
#   [3 4 5]]]

print(np.expand_dims(a, 0).shape)
# (1, 2, 3)

print(a.reshape(1, 2, 3))
# [[[0 1 2]
#   [3 4 5]]]

print(a.reshape(1, 2, 3).shape)
# (1, 2, 3)

Come puoi vedere dall’esempio sopra, l’uso di np.newaxis e np.expand_dims() ha il vantaggio di non dover specificare la dimensione della dimensione originale.

Anche con reshape(), se si desidera una dimensione all’inizio fine, non è necessario aggiungere specificatamente alla dimensione decomprimendo con *.

print(a.reshape(1, *a.shape))
# [[[0 1 2]
#   [3 4 5]]]

print(a.reshape(1, *a.shape).shape)
# (1, 2, 3)