W numpy
niektóre operacje wracają do formy, (R, 1)
ale niektóre powracają (R,)
. To sprawi, że mnożenie macierzy będzie bardziej nużące, ponieważ reshape
wymagane jest jawne . Na przykład, biorąc pod uwagę macierz M
, jeśli chcemy zrobić, numpy.dot(M[:,0], numpy.ones((1, R)))
gdzie R
jest liczba wierszy (oczywiście ten sam problem występuje również w kolumnach). Otrzymamy matrices are not aligned
błąd, ponieważ M[:,0]
jest w formie, (R,)
ale numpy.ones((1, R))
jest w formie (1, R)
.
Więc moje pytania to:
Jaka jest różnica między kształtem
(R, 1)
a(R,)
. Wiem dosłownie, że to lista liczb i lista list, gdzie cała lista zawiera tylko liczbę. Zastanawiam się, dlaczego nie zaprojektowaćnumpy
tak, aby sprzyjał kształtowi,(R, 1)
zamiast(R,)
ułatwiać mnożenie macierzy.Czy istnieją lepsze sposoby na powyższy przykład? Bez wyraźnego przekształcania w ten sposób:
numpy.dot(M[:,0].reshape(R, 1), numpy.ones((1, R)))
Odpowiedzi:
1. Znaczenie kształtów w NumPy
Piszesz: „Wiem dosłownie jest to lista liczb i lista list, gdzie cała lista zawiera tylko liczbę”, ale to trochę niepomocny sposób, aby o tym myśleć.
Najlepszym sposobem myślenia o tablicach NumPy jest to, że składają się one z dwóch części, bufora danych, który jest tylko blokiem surowych elementów oraz widoku opisującego sposób interpretacji bufora danych.
Na przykład, jeśli utworzymy tablicę 12 liczb całkowitych:
Następnie
a
składa się z bufora danych, ułożonego mniej więcej tak:oraz widok opisujący sposób interpretacji danych:
Tutaj kształt
(12,)
oznacza, że tablica jest indeksowana przez pojedynczy indeks, który biegnie od 0 do 11. Koncepcyjnie, jeśli oznaczymy ten pojedynczy indeksi
, tablicaa
wygląda następująco:Jeśli przekształcimy tablicę, nie zmieni to bufora danych. Zamiast tego tworzy nowy widok, który opisuje inny sposób interpretacji danych. Więc później:
tablica
b
ma taki sam bufor danych jaka
, ale teraz jest indeksowana przez dwa indeksy, które działają odpowiednio od 0 do 2 i od 0 do 3. Jeśli oznaczymy dwa indeksyi
ij
, tablicab
wygląda następująco:co oznacza że:
Widać, że drugi indeks zmienia się szybko, a pierwszy indeks zmienia się powoli. Jeśli wolisz, aby było odwrotnie, możesz określić
order
parametr:co powoduje tablicę indeksowaną w ten sposób:
co oznacza że:
Teraz powinno być jasne, co to znaczy, że tablica ma kształt o co najmniej jednym wymiarze wielkości 1. Po:
tablica
d
jest indeksowana przez dwa indeksy, z których pierwszy biegnie od 0 do 11, a drugi indeks zawsze wynosi 0:a więc:
Wymiar długości 1 jest „wolny” (w pewnym sensie), więc nic nie powstrzymuje cię przed pójściem do miasta:
podając tablicę indeksowaną w ten sposób:
a więc:
Zobacz dokumentację takie wewnętrzne NumPy aby uzyskać więcej informacji o tym, jak tablice zostały zaimplementowane.
2. Co robić?
Ponieważ
numpy.reshape
po prostu tworzy nowy widok, nie powinieneś się bać korzystania z niego w razie potrzeby. To właściwe narzędzie do użycia, gdy chcesz zindeksować tablicę w inny sposób.Jednak w długim obliczeniu zwykle możliwe jest ustawienie konstruowania tablic o „właściwym” kształcie, a tym samym zminimalizowanie liczby przekształceń i transpozycji. Ale nie widząc faktycznego kontekstu, który doprowadził do konieczności przekształcenia, trudno powiedzieć, co należy zmienić.
Przykład w twoim pytaniu to:
ale to nie jest realistyczne. Po pierwsze, to wyrażenie:
oblicza wynik prościej. Po drugie, czy naprawdę jest coś specjalnego w kolumnie 0? Być może tak naprawdę potrzebujesz:
źródło
newaxis
jeśli potrzebujesz innej osi, na przykłada[:, j, np.newaxis]
jest toj
kolumna tha
ia[np.newaxis, i]
jest toi
wiersz.(R, )
przypadku kształtndarray
jest krotką z pojedynczymi elementami, więc jest drukowany przez Python za pomocą przecinka. Bez dodatkowego przecinka byłby niejednoznaczny z wyrażeniem w nawiasach . Andarray
z jednym wymiarem może być traktowane jako wektor długości kolumnyR
. W tym(R, 1)
przypadku krotka ma dwa elementy, więc można ją traktować jako wektor wiersza (lub macierz o 1 rzędzie długościR
.Różnica między
(R,)
i(1,R)
to dosłownie liczba wskaźników, których należy użyć.ones((1,R))
to tablica 2-D, która ma tylko jeden wiersz.ones(R)
jest wektorem. Zasadniczo, jeśli nie ma sensu, aby zmienna miała więcej niż jeden wiersz / kolumnę, powinieneś użyć wektora, a nie macierzy o wymiarze singletonu.W konkretnym przypadku istnieje kilka opcji:
1) Po prostu przekształć drugi argument w wektor. Następujące działa dobrze:
2) Jeśli chcesz operacji typu Matlab, takich jak macierz, użyj klasy
matrix
zamiastndarray
. Wszystkie macierze są zmuszone do tworzenia tablic 2-D, a operator*
dokonuje mnożenia macierzy zamiast elementów (więc nie potrzebujesz kropki). Z mojego doświadczenia wynika, że jest to więcej kłopotów niż warte, ale może być fajnie, jeśli jesteś przyzwyczajony do Matlaba.źródło
matrix
zajęcia. Jaki problem mamatrix
klasa BTW?matrix
polega na tym, że jest on tylko 2D, a także dlatego, że przeciąża operatora „*”, funkcje napisane dlandarray
mogą się nie powieść, jeśli zostaną użyte namatrix
.Kształt jest krotką. Jeśli jest tylko jeden wymiar, kształt będzie miał jedną cyfrę i będzie pusty po przecinku. W przypadku wymiarów 2+ po wszystkich przecinkach pojawi się liczba.
źródło
Dla podstawowej klasy macierzy tablice 2d nie są bardziej specjalne niż tablice 1d lub 3d. Niektóre operacje zachowują wymiary, niektóre zmniejszają je, inne łączą, a nawet rozszerzają.
Inne wyrażenia, które dają tę samą tablicę
MATLAB zaczął od tylko tablic 2D. Nowsze wersje pozwalają na więcej wymiarów, ale zachowują dolną granicę 2. Ale wciąż musisz zwrócić uwagę na różnicę między macierzą wierszy a kolumną pierwszą, taką o kształcie
(1,3)
v(3,1)
. Jak często pisałeś[1,2,3].'
? Zamierzałem pisaćrow vector
icolumn vector
, ale z tym ograniczeniem 2d, w MATLAB-ie nie ma żadnych wektorów - przynajmniej nie w matematycznym znaczeniu wektora jako 1d.Czy przeglądałeś
np.atleast_2d
(także wersje _1d i _3d)?źródło
1) Powodem, dla którego nie preferuję kształtu
(R, 1)
ponad,(R,)
jest to, że niepotrzebnie komplikuje rzeczy. Poza tym, dlaczego lepiej byłoby mieć(R, 1)
domyślnie kształt dla wektora długości-R zamiast(1, R)
? Lepiej jest zachować prostotę i być wyraźnym, gdy potrzebujesz dodatkowych wymiarów.2) Na przykład, obliczasz produkt zewnętrzny, więc możesz to zrobić bez
reshape
połączenia, używającnp.outer
:źródło
M[:,0]
zasadniczo pobiera wszystkie wiersze z pierwszym elementem, więc sensowniej jest mieć(R, 1)
niż(1, R)
. 2) Nie zawsze można go zastąpićnp.outer
np. Kropką dla matrycy w kształcie (1, R), a następnie (R, 1).matrix
obiektu. 2) Faktycznie,np.outer
działa niezależnie od tego, czy kształty są(1, R)
,(R, 1)
lub kombinacja tych dwóch.Tutaj jest już wiele dobrych odpowiedzi. Ale dla mnie trudno było znaleźć jakiś przykład, w którym kształt lub tablica mogą złamać cały program.
Oto jeden z nich:
Błąd zakończy się niepowodzeniem:
ale jeśli dodamy
reshape
doa
:to działa poprawnie!
źródło