6.13. Doğrusal cebir¶
Bir kamerada doğrusal cebir, küçük matris işidir: bir IMU örneğini dünya çerçevesine kaynaştıran bir 3x3 döndürme, bir merceği düzelten bir kalibrasyon matrisi, bir Kalman filtresinin durum-kovaryans güncellemesi, normal denklemleri minik bir doğrusal çözüm olarak çıkan bir polinom uydurma. numpy.linalg ve scipy.linalg alt modülleri tam olarak bu ölçeği kapsar.
Fonksiyonlar iki modülde yer alır. Matris-çarpım işlemleri numpy üst düzeyinde bulunur; ayrıştırmalar ve matris tersi numpy.linalg altındadır; özel doğrusal-sistem çözücüleri ise scipy.linalg altındadır. Örneğin, 2’ye 2 bir matris çarpımı:
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. Neler mevcut¶
dot()– matris veya vektör çarpımı.cross()– 3 boyutlu vektör çapraz çarpımı.trace()– köşegenin toplamı.inv()– matris tersi.det()– determinant.cholesky()– Cholesky ayrıştırması (simetrik pozitif tanımlı girdi).eig()– bir gerçek simetrik matrisin özdeğerleri ve özvektörleri.norm()– bir vektör veya matrisin 2-normu.qr()–mode='reduced'(varsayılan) veyamode='complete'ile QR ayrıştırması.solve_triangular()–Aüçgensel olduğundaA @ x = b‘yi çözer.cho_solve()–A‘nın bir Cholesky çarpanı verildiğindeA @ x = b‘yi çözer.
6.13.2. dot, cross, trace¶
dot(), matris çarpımının kamerada nasıl yazıldığıdır. Masaüstü numpy‘nın aynı iş için sağladığı @ operatörü ndarray üzerinde uygulanmamıştır; bu nedenle her matris-vektör, matris-matris ve vektör nokta çarpımı dot() çağrısı üzerinden gerçekleşir:
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
dot()‘un sonucu her zaman float dtype’ındadır. cross() iki 3-vektörün çapraz çarpımıdır, trace() ise bir kare matrisin ana köşegeninin toplamıdır.
6.13.3. inv ve 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))
Ters, Gauss-Jordan eliminasyonu ile hesaplanır; bu nedenle inv(), matris tekil olduğunda (eliminasyon sırasında bir köşegen girdisi sıfır olduğunda) ValueError yükseltir. RAM maliyeti kabaca girdinin boyutunun iki katıdır.
Determinant aynı eliminasyonu yeniden kullanır – çalışma süresi esasen tersinkiyle aynıdır.
Uygulamanın amacı bir doğrusal sistemi çözmek olduğunda, tersini alıp çarpmayın – bunun yerine aşağıdaki özel çözücüleri tercih edin. İkisi de hem daha hızlıdır hem de sayısal olarak daha iyi davranır.
6.13.4. cholesky¶
Simetrik pozitif tanımlı bir A matrisi için cholesky(), A = L @ L.T olacak şekilde alt üçgensel bir L döndürür:
a = np.array([[25, 15, -5],
[15, 18, 0],
[-5, 0, 11]])
L = np.linalg.cholesky(a)
Girdi pozitif tanımlı veya simetrik değilse, ValueError yükseltilir.
Cholesky çarpanı, bir LU çarpanlamasının yarısı kadar iş yükündedir ve matrisinin simetrik pozitif tanımlı olduğu bilinen herhangi bir problem (kovaryans güncellemeleri, en küçük kareler uydurmasından gelen normal denklemler) için doğru başlangıç noktasıdır.
6.13.5. eig¶
eig() yalnızca gerçek simetrik matrisler üzerinde çalışır. Simetrik olmayan matrisler ValueError yükseltir. Bir 2’li demet (eigenvalues, eigenvectors) döndürür:
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)
Notlar:
Özdeğerler belirli bir sırada gelmez. Sıralı bir düzen önemli olduğunda
sort()(veargsort()aracılığıyla aynı permütasyonu özvektörlere) uygulayın.Bir özvektör yalnızca sıfır olmayan bir skalere kadar benzersizdir; bu nedenle tek tek özvektörlerin işareti benzersiz olarak tanımlı değildir. İki doğru çalışma, zıt işaretli vektörler üretebilir; bu zararsızdır.
6.13.6. norm¶
Bir vektör veya matrisin Öklid (Frobenius) normu:
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...
İsteğe bağlı axis= anahtar sözcüğü, normu tüm dizi üzerinde değil, tek bir eksen boyunca alır.
6.13.7. qr¶
qr(), dikdörtgen bir A matrisini ((M, N) şeklinde) A == Q @ R olacak şekilde bir ortonormal Q ve bir üst üçgensel R‘ye çarpanlarına ayırı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)
Ayrıştırma, ardışık Givens döndürmeleri aracılığıyla uygulanır. Matrisin simetrik olmadığı en küçük kareler problemleri için doğru seçimdir.
6.13.8. Sistemleri çözme¶
ulab.scipy.linalg altındaki iki özel çözücü, np.dot(np.linalg.inv(A), b)‘den hem daha hızlı hem de daha doğrudur:
solve_triangular(a, b, lower=False)()–a‘nın üçgensel olduğunu varsayaraka @ x = b‘yi çözer: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)()– bir Cholesky çarpanıLverildiğinde,A = L @ L.Tolduğu yerdeA @ x = b‘yi çözer:L = np.linalg.cholesky(A) x = sp.linalg.cho_solve(L, b)
A‘nın yapısı izin verdiğinde, tersini almak yerine bunlara başvurun – bunlar hem eliminasyon işinden hem de açık tersten tasarruf sağlar.
6.13.9. Küçük bir doğrusal sistemi çözme¶
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
Aynı problem, A‘yı çarpanlarına ayırarak ve uygun çözücüyü çağırarak ifade edilebilir – A doğru yapıya sahip olduğunda daha hızlı ve daha doğrudur.
Tam argüman düzeyinde başvuru için bkz. numpy.linalg — Lineer cebir rutinleri ve scipy.linalg — Lineer cebir rutinleri.