Jak działa numpy.newaxis i kiedy go używać?

206

Kiedy próbuję

numpy.newaxis

wynik daje mi 2-wymiarową ramkę wykresu z osią X od 0 do 1. Jednak gdy próbuję użyć numpy.newaxisdo wycięcia wektora,

vector[0:4,]
[ 0.04965172  0.04979645  0.04994022  0.05008303]
vector[:, np.newaxis][0:4,]
[[ 0.04965172]
[ 0.04979645]
[ 0.04994022]
[ 0.05008303]]

Czy to to samo, z wyjątkiem tego, że zmienia wektor wierszowy na wektor kolumnowy?

Ogólnie rzecz biorąc, jaki jest pożytek numpy.newaxisi w jakich okolicznościach powinniśmy go używać?

Yue Harriet Huang
źródło
2
except that it changes a row vector to a column vector? Pierwszy przykład nie jest wektorem wierszowym. To jest koncepcja Matlab. W Pythonie jest to tylko 1-wymiarowy wektor bez koncepcji wiersza lub kolumny. Wektory wierszowe lub kolumnowe są 2-wymiarowe, tak jak w drugim przykładzie
endolit

Odpowiedzi:

375

Mówiąc najprościej, numpy.newaxissłuży do zwiększenia wymiaru istniejącej tablicy o jeden dodatkowy wymiar , gdy zostanie użyty raz . A zatem,

  • Macierz 1D stanie się macierzą 2D

  • Tablica 2D stanie się tablicą 3D

  • Tablica 3D stanie się tablicą 4D

  • Tablica 4D stanie się tablicą 5D

i tak dalej..

Oto wizualna ilustracja, która przedstawia promocję macierzy 1D na tablice 2D.

wizualizacja newaxis canva


Scenariusz 1 : np.newaxismoże się przydać, gdy chcesz jawnie przekonwertować tablicę 1D na wektor wierszowy lub wektor kolumnowy , jak pokazano na powyższym obrazku.

Przykład:

# 1D array
In [7]: arr = np.arange(4)
In [8]: arr.shape
Out[8]: (4,)

# make it as row vector by inserting an axis along first dimension
In [9]: row_vec = arr[np.newaxis, :]     # arr[None, :]
In [10]: row_vec.shape
Out[10]: (1, 4)

# make it as column vector by inserting an axis along second dimension
In [11]: col_vec = arr[:, np.newaxis]     # arr[:, None]
In [12]: col_vec.shape
Out[12]: (4, 1)

Scenariusz-2 : Gdy chcemy wykorzystać emisję numpy jako część jakiejś operacji, na przykład podczas dodawania niektórych tablic.

Przykład:

Powiedzmy, że chcesz dodać następujące dwie tablice:

 x1 = np.array([1, 2, 3, 4, 5])
 x2 = np.array([5, 4, 3])

Jeśli spróbujesz dodać je po prostu w ten sposób, NumPy podniesie następujące wartości ValueError:

ValueError: operands could not be broadcast together with shapes (5,) (3,)

W tej sytuacji możesz użyć, np.newaxisaby zwiększyć wymiar jednej z tablic, aby NumPy mógł rozgłaszać .

In [2]: x1_new = x1[:, np.newaxis]    # x1[:, None]
# now, the shape of x1_new is (5, 1)
# array([[1],
#        [2],
#        [3],
#        [4],
#        [5]])

Teraz dodaj:

In [3]: x1_new + x2
Out[3]:
array([[ 6,  5,  4],
       [ 7,  6,  5],
       [ 8,  7,  6],
       [ 9,  8,  7],
       [10,  9,  8]])

Alternatywnie możesz również dodać nową oś do tablicy x2:

In [6]: x2_new = x2[:, np.newaxis]    # x2[:, None]
In [7]: x2_new     # shape is (3, 1)
Out[7]: 
array([[5],
       [4],
       [3]])

Teraz dodaj:

In [8]: x1 + x2_new
Out[8]: 
array([[ 6,  7,  8,  9, 10],
       [ 5,  6,  7,  8,  9],
       [ 4,  5,  6,  7,  8]])

Uwaga : Zauważ, że otrzymujemy ten sam wynik w obu przypadkach (ale jeden jest transpozycją drugiego).


Scenariusz 3 : jest podobny do scenariusza 1. Ale możesz użyć np.newaxiswięcej niż jeden raz, aby promować tablicę do wyższych wymiarów. Taka operacja jest czasami potrzebna w przypadku tablic wyższego rzędu ( tj. Tensorów ).

Przykład:

In [124]: arr = np.arange(5*5).reshape(5,5)

In [125]: arr.shape
Out[125]: (5, 5)

# promoting 2D array to a 5D array
In [126]: arr_5D = arr[np.newaxis, ..., np.newaxis, np.newaxis]    # arr[None, ..., None, None]

In [127]: arr_5D.shape
Out[127]: (1, 5, 5, 1, 1)

Alternatywnie możesz użyć numpy.expand_dimsintuicyjnego axiskwarg.

# adding new axes at 1st, 4th, and last dimension of the resulting array
In [131]: newaxes = (0, 3, -1)
In [132]: arr_5D = np.expand_dims(arr, axis=newaxes)
In [133]: arr_5D.shape
Out[133]: (1, 5, 5, 1, 1)

Więcej informacji na temat np.newaxis vs np.reshape

newaxis jest również nazywany pseudoindeksem, który umożliwia tymczasowe dodanie osi do multiarray.

np.newaxisużywa operatora wycinania, aby odtworzyć tablicę, jednocześnie numpy.reshapezmieniając jej kształt na żądany układ (zakładając, że wymiary są zgodne; I to musi się reshapewydarzyć).

Przykład

In [13]: A = np.ones((3,4,5,6))
In [14]: B = np.ones((4,6))
In [15]: (A + B[:, np.newaxis, :]).shape     # B[:, None, :]
Out[15]: (3, 4, 5, 6)

W powyższym przykładzie wstawiliśmy tymczasową oś między pierwszą a drugą osią B(do wykorzystania nadawania). Brakująca oś jest tutaj wypełniana za pomocą, np.newaxisaby operacja nadawania działała.


Wskazówka ogólna : możesz również użyćNonezamiastnp.newaxis; W rzeczywistości są to te same obiekty .

In [13]: np.newaxis is None
Out[13]: True

PS Zobacz także tę świetną odpowiedź: newaxis vs zmiana kształtu, aby dodać wymiary

kmario23
źródło
3
Jaki typ operacji to x1_new + x2? Jest to dla mnie dziwne, ponieważ pomyślałem, że dwie macierze można dodać tylko wtedy, gdy mają te same wymiary (lub jeśli jedna z nich jest w rzeczywistości tylko skalarem).
Stephen
2
@Stephen Jak również wspomniałem w odpowiedzi, dzieje się tak z powodu transmisji NumPy.
kmario23
2
To niesamowite wytłumaczenie
Valdrinium,
2
@valdrinit cieszę się, że jest to pomocne dla Ciebie :)
kmario23
1
@ kmario23 Rzeczywiście, przypisanie jest ukryte w ostatnim zdaniu artykułu, nic dziwnego, że go nie widziałem. Uważam to za granicę plagiatu, nawet przy takiej atrybucji. W mojej książce kopiowanie słowo w słowo jest dopuszczalne tylko wtedy, gdy ten sam autor publikuje na różnych platformach. Spodziewałem się czegoś lepszego od Medium.
Chiraz BenAbdelkader
34

Co to jest np.newaxis?

To np.newaxistylko alias dla stałej Pythona None, co oznacza, że ​​wszędzie tam, gdzie używasz, np.newaxismożesz również użyć None:

>>> np.newaxis is None
True

Jest to po prostu bardziej opisowe, jeśli czytasz kod, który używa np.newaxiszamiast None.

Jak używać np.newaxis?

np.newaxisGeneralnie stosuje się do krojenia. Wskazuje, że chcesz dodać dodatkowy wymiar do tablicy. Pozycja np.newaxisreprezentuje miejsce, w którym chcę dodać wymiary.

>>> import numpy as np
>>> a = np.arange(10)
>>> a
array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
>>> a.shape
(10,)

W pierwszym przykładzie wykorzystuję wszystkie elementy z pierwszego wymiaru i dodaję drugi wymiar:

>>> a[:, np.newaxis]
array([[0],
       [1],
       [2],
       [3],
       [4],
       [5],
       [6],
       [7],
       [8],
       [9]])
>>> a[:, np.newaxis].shape
(10, 1)

Drugi przykład dodaje wymiar jako pierwszy wymiar, a następnie wykorzystuje wszystkie elementy z pierwszego wymiaru oryginalnej tablicy jako elementy w drugim wymiarze tablicy wyników:

>>> a[np.newaxis, :]  # The output has 2 [] pairs!
array([[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]])
>>> a[np.newaxis, :].shape
(1, 10)

Podobnie możesz użyć wielu, np.newaxisaby dodać wiele wymiarów:

>>> a[np.newaxis, :, np.newaxis]  # note the 3 [] pairs in the output
array([[[0],
        [1],
        [2],
        [3],
        [4],
        [5],
        [6],
        [7],
        [8],
        [9]]])
>>> a[np.newaxis, :, np.newaxis].shape
(1, 10, 1)

Czy istnieją alternatywy dla np.newaxis?

W NumPy jest jeszcze jedna bardzo podobna funkcjonalność: np.expand_dimsktórej można również użyć do wstawienia jednego wymiaru:

>>> np.expand_dims(a, 1)  # like a[:, np.newaxis]
>>> np.expand_dims(a, 0)  # like a[np.newaxis, :]

Ale biorąc pod uwagę, że po prostu wstawia 1s do, shapemożesz również reshapetablicę, aby dodać te wymiary:

>>> a.reshape(a.shape + (1,))  # like a[:, np.newaxis]
>>> a.reshape((1,) + a.shape)  # like a[np.newaxis, :]

W większości przypadków np.newaxisjest to najłatwiejszy sposób dodawania wymiarów, ale dobrze jest znać alternatywy.

Kiedy używać np.newaxis?

W kilku kontekstach przydatne jest dodawanie wymiarów:

  • Jeśli dane powinny mieć określoną liczbę wymiarów. Na przykład, jeśli chcesz użyć matplotlib.pyplot.imshowdo wyświetlenia tablicy 1D.

  • Jeśli chcesz, aby NumPy rozgłaszał tablice. Dodając wymiar można na przykład uzyskać różnicę pomiędzy wszystkimi elementami jednej tablicy: a - a[:, np.newaxis]. Działa to, ponieważ operacje NumPy są transmitowane, zaczynając od ostatniego wymiaru 1 .

  • Aby dodać niezbędny wymiar, aby NumPy mógł rozgłaszać tablice. To działa, ponieważ każdy wymiar długość-1 jest po prostu transmitowany do długości odpowiedniego wymiaru 1 drugiej tablicy.


1 Jeśli chcesz przeczytać więcej o zasadach nadawania, dokumentacja NumPy na ten temat jest bardzo dobra. Zawiera również przykład z np.newaxis:

>>> a = np.array([0.0, 10.0, 20.0, 30.0])
>>> b = np.array([1.0, 2.0, 3.0])
>>> a[:, np.newaxis] + b
array([[  1.,   2.,   3.],
       [ 11.,  12.,  13.],
       [ 21.,  22.,  23.],
       [ 31.,  32.,  33.]])
MSeifert
źródło
Nie widzę różnicy między drugim i trzecim przypadkiem użycia; oboje chcą pozwolić NumPy na rozgłaszanie tablicy w ramach jakiejś operacji. Jeśli nie, pomocne byłoby dodanie przykładu dla trzeciego przypadku użycia, aby wyjaśnić sprawę.
Chiraz BenAbdelkader
@ChirazBenAbdelkader Tak, różnica nie jest tak wyraźna. Nie jestem pewien, czy powinienem usunąć trzeci punkt, czy też połączyć go z drugim.
MSeifert
10

Zacząłeś od jednowymiarowej listy liczb. Kiedyś użyłeś numpy.newaxis, przekształciłeś go w dwuwymiarową macierz, składającą się z czterech rzędów po jednej kolumnie każdy.

Możesz następnie użyć tej macierzy do mnożenia macierzy lub zaangażować ją w budowę większej macierzy 4 xn.

Kevin
źródło
5

newaxisobiekt w krotce wyboru służy do rozszerzenia wymiarów wynikowego wyboru o jeden wymiar długości jednostki .

To nie tylko konwersja macierzy wierszy na macierz kolumn.

Rozważ poniższy przykład:

In [1]:x1 = np.arange(1,10).reshape(3,3)
       print(x1)
Out[1]: array([[1, 2, 3],
               [4, 5, 6],
               [7, 8, 9]])

Teraz dodajmy nowy wymiar do naszych danych,

In [2]:x1_new = x1[:,np.newaxis]
       print(x1_new)
Out[2]:array([[[1, 2, 3]],

              [[4, 5, 6]],

              [[7, 8, 9]]])

Możesz zobaczyć, że newaxisdodał tutaj dodatkowy wymiar, x1 miał wymiar (3,3), a X1_new ma wymiar (3,1,3).

Jak nasz nowy wymiar umożliwia nam różne operacje:

In [3]:x2 = np.arange(11,20).reshape(3,3)
       print(x2)
Out[3]:array([[11, 12, 13],
              [14, 15, 16],
              [17, 18, 19]]) 

Dodając x1_new i x2, otrzymujemy:

In [4]:x1_new+x2
Out[4]:array([[[12, 14, 16],
               [15, 17, 19],
               [18, 20, 22]],

              [[15, 17, 19],
               [18, 20, 22],
               [21, 23, 25]],

              [[18, 20, 22],
               [21, 23, 25],
               [24, 26, 28]]])

Zatem newaxisnie chodzi tylko o konwersję macierzy wierszy na kolumny. Zwiększa rozmiar matrycy, dzięki czemu możemy na niej wykonywać więcej operacji.

harsh hundiwala
źródło
1
To nie tylko macierz, działa z każdą ndarrayterminologią NumPy.
kmario23