6.13. Linearna algebra¶
Linearna algebra na kameri rad je s malim matricama: 3x3 rotacija koja stapa IMU uzorak u svjetski okvir, kalibracijska matrica koja ispravlja leću, ažuriranje kovarijance stanja Kalmanova filtra, polinomijalna prilagodba čije normalne jednadžbe izlaze kao maleno linearno rješavanje. Podmoduli numpy.linalg i scipy.linalg pokrivaju upravo tu razinu.
Funkcije se nalaze u dvama modulima. Operacije matričnog umnoška na su najvišoj razini modula numpy; dekompozicije i inverz matrice nalaze se pod numpy.linalg; namjenski rješavači linearnih sustava nalaze se pod scipy.linalg. Množenje 2-sa-2 matrice, primjerice:
from ulab import numpy as np
A = np.array([[1, 2], [3, 4]], dtype=np.float)
B = np.array([[5, 6], [7, 8]], dtype=np.float)
np.dot(A, B)
# array([[19.0, 22.0],
# [43.0, 50.0]])
6.13.1. Što je dostupno¶
dot()– matrični ili vektorski umnožak.cross()– vektorski (kros) umnožak u 3-D.trace()– suma dijagonale.inv()– inverz matrice.det()– determinanta.cholesky()– Choleskyjeva dekompozicija (simetričan pozitivno definitan ulaz).eig()– svojstvene vrijednosti i svojstveni vektori realne simetrične matrice.norm()– 2-norma vektora ili matrice.qr()– QR dekompozicija smode='reduced'(zadano) ilimode='complete'.solve_triangular()– rješavaA @ x = bkada jeAtrokutasta.cho_solve()– rješavaA @ x = buz zadani Choleskyjev faktor matriceA.
6.13.2. dot, cross, trace¶
dot() način je na koji se na kameri zapisuje matrično množenje. Operator @ koji stolni numpy pruža za isti posao nije implementiran na ndarray, pa svaki matrično-vektorski, matrično-matrični i vektorski skalarni umnožak ide kroz poziv dot()
a = np.array([1, 2, 3])
b = np.array([4, 5, 6])
np.dot(a, b) # 32.0 (scalar product)
np.cross(a, b) # array([-3.0, 6.0, -3.0])
m = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
np.dot(m, a) # matrix-vector product
np.dot(m, m) # matrix-matrix product
np.trace(m) # 1 + 5 + 9 = 15.0
Rezultat poziva dot() uvijek je dtype-a float. cross() vektorski je umnožak dvaju 3-vektora, a trace() suma glavne dijagonale kvadratne matrice.
6.13.3. inv i det¶
m = np.array([[1, 2, 3, 4],
[4, 5, 6, 4],
[7, 9, 9, 4],
[3, 4, 5, 6]])
print(np.linalg.inv(m))
print(np.linalg.det(m))
Inverz se računa Gauss-Jordanovom eliminacijom, pa inv() podiže ValueError kada je matrica singularna (dijagonalni unos postane nula tijekom eliminacije). Trošak RAM-a otprilike je dvostruka veličina ulaza.
Determinanta ponovno koristi istu eliminaciju – vrijeme izvođenja u biti je isto kao za inverz.
Kada je cilj aplikacije riješiti linearni sustav, nemojte invertirati i množiti – radije upotrijebite namjenske rješavače u nastavku. Oba su brža i numerički se bolje ponašaju.
6.13.4. cholesky¶
Za simetričnu pozitivno definitnu matricu A, cholesky() vraća donje-trokutastu L takvu da je A = L @ L.T
a = np.array([[25, 15, -5],
[15, 18, 0],
[-5, 0, 11]])
L = np.linalg.cholesky(a)
Ako ulaz nije pozitivno definitan ili nije simetričan, podiže se ValueError.
Choleskyjev faktor upola je posla LU faktorizacije i prava je polazna točka za svaki problem čija je matrica poznato simetrična pozitivno definitna (ažuriranja kovarijance, normalne jednadžbe iz prilagodbe metodom najmanjih kvadrata).
6.13.5. eig¶
eig() radi samo na realnim simetričnim matricama. Nesimetrične matrice podižu ValueError. Vraća 2-torku (eigenvalues, eigenvectors)
a = np.array([[1, 2, 1, 4],
[2, 5, 3, 5],
[1, 3, 6, 1],
[4, 5, 1, 7]], dtype=np.uint8)
x, y = np.linalg.eig(a)
Napomene:
Svojstvene vrijednosti vraćaju se bez određenog redoslijeda. Primijenite
sort()(te istu permutaciju na svojstvene vektore putemargsort()) kada je sortiran redoslijed bitan.Svojstveni vektor jedinstven je samo do nenul skalara, pa predznak pojedinačnih svojstvenih vektora nije jedinstveno određen. Dva ispravna izvođenja mogu proizvesti vektore suprotnog predznaka; to je bezopasno.
6.13.6. norm¶
Euklidska (Frobeniusova) norma vektora ili matrice:
v = np.array([1, 2, 3, 4, 5])
m = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
np.linalg.norm(v) # 7.416...
np.linalg.norm(m) # 16.881...
Neobavezna ključna riječ axis= uzima normu duž jedne osi umjesto nad cijelim poljem.
6.13.7. qr¶
qr() faktorizira pravokutnu matricu A (oblik (M, N)) u ortonormalnu Q i gornje-trokutastu R takve da je A == Q @ R
A = np.arange(6).reshape((3, 2))
q, r = np.linalg.qr(A)
# mode='reduced' (default): q is (3, 2), r is (2, 2)
q, r = np.linalg.qr(A, mode='complete')
# q is (3, 3), r is (3, 2)
Dekompozicija je implementirana putem uzastopnih Givensovih rotacija. Pravi izbor za probleme najmanjih kvadrata gdje matrica nije simetrična.
6.13.8. Rješavanje sustava¶
Dva namjenska rješavača pod ulab.scipy.linalg i brža su i točnija od np.dot(np.linalg.inv(A), b):
solve_triangular(a, b, lower=False)()– rješavaa @ x = bpretpostavljajući da jeatrokutasta:A = np.array([[3, 0, 0, 0], [2, 1, 0, 0], [1, 0, 1, 0], [1, 2, 1, 8]]) b = np.array([4, 2, 4, 2]) x = sp.linalg.solve_triangular(A, b, lower=True)
cho_solve(L, b)()– uz zadani Choleskyjev faktorL, rješavaA @ x = bgdje jeA = L @ L.TL = np.linalg.cholesky(A) x = sp.linalg.cho_solve(L, b)
Posegnite za ovima umjesto invertiranja kad god struktura matrice A to dopušta – štede posao eliminacije i eksplicitni inverz.
6.13.9. Rješavanje malog linearnog sustava¶
A = np.array([[3, 0, 1, 1],
[0, 1, 0, 2],
[1, 0, 1, 1],
[1, 2, 1, 8]])
b = np.array([4, 2, 4, 2])
x = np.dot(np.linalg.inv(A), b)
print(x)
print(np.dot(A, x)) # should equal b
Isti se problem može izraziti faktorizacijom matrice A i pozivom odgovarajućeg rješavača – brže i točnije kada A ima pravu strukturu.
Za potpunu referencu na razini argumenata pogledajte numpy.linalg — Rutine linearne algebre i scipy.linalg — Rutine linearne algebre.