6.13. Aljabar Linear#

Aljabar linear pada kamera adalah pekerjaan matriks kecil: rotasi 3x3 yang memadukan sampel IMU ke bingkai dunia, matriks kalibrasi yang memperbaiki lensa, pembaruan kovariansi-state filter Kalman, pemasangan polinomial yang persamaan normalnya menjadi penyelesaian linear kecil. Submodul numpy.linalg dan scipy.linalg mencakup skala tersebut dengan tepat.

Fungsi-fungsi tersebut tersebar di dua modul. Operasi perkalian matriks berada di tingkat atas numpy; dekomposisi dan invers matriks berada di bawah numpy.linalg; pemecah sistem linear khusus berada di bawah scipy.linalg. Perkalian matriks 2-kali-2, misalnya:

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. Apa yang tersedia#

  • dot() -- perkalian matriks atau vektor.

  • cross() -- perkalian silang vektor 3-D.

  • trace() -- jumlah elemen diagonal.

  • inv() -- invers matriks.

  • det() -- determinan.

  • cholesky() -- dekomposisi Cholesky (input simetris positif-definit).

  • eig() -- nilai eigen dan vektor eigen dari matriks simetris nyata.

  • norm() -- norma-2 dari vektor atau matriks.

  • qr() -- dekomposisi QR dengan mode='reduced' (default) atau mode='complete'.

  • solve_triangular() -- selesaikan A @ x = b ketika A segitiga.

  • cho_solve() -- selesaikan A @ x = b diberikan faktor Cholesky dari A.

6.13.2. dot, cross, trace#

dot() adalah cara penulisan perkalian matriks pada kamera. Operator @ yang disediakan numpy desktop untuk pekerjaan yang sama tidak diimplementasikan pada ndarray, sehingga setiap perkalian matriks-vektor, matriks-matriks, dan titik vektor melewati panggilan 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

Hasil dari dot() selalu bertipe dtype float. cross() adalah perkalian silang dua 3-vektor, trace() adalah jumlah diagonal utama dari matriks persegi.

6.13.3. inv dan 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))

Invers dihitung dengan eliminasi Gauss-Jordan, sehingga inv() memunculkan ValueError ketika matriks singular (entri diagonal menjadi nol selama eliminasi). Biaya RAM kira-kira dua kali ukuran input.

Determinan menggunakan eliminasi yang sama -- waktu eksekusinya pada dasarnya sama dengan invers.

Ketika tujuan aplikasi adalah menyelesaikan sistem linear, jangan membalik dan mengalikan -- lebih baik gunakan pemecah khusus di bawah. Keduanya lebih cepat dan lebih baik secara numerik.

6.13.4. cholesky#

Untuk matriks simetris positif-definit A, cholesky() mengembalikan L segitiga-bawah sehingga A = L @ L.T

a = np.array([[25, 15, -5],
              [15, 18,  0],
              [-5,  0, 11]])
L = np.linalg.cholesky(a)

Jika input tidak positif-definit atau tidak simetris, ValueError dimunculkan.

Faktor Cholesky adalah setengah pekerjaan dari faktorisasi LU dan merupakan titik awal yang tepat untuk masalah yang matriksnya diketahui simetris positif-definit (pembaruan kovariansi, persamaan normal dari pemasangan kuadrat terkecil).

6.13.5. eig#

eig() hanya bekerja pada matriks simetris nyata. Matriks non-simetris memunculkan ValueError. Fungsi ini mengembalikan tuple-2 (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)

Catatan:

  • Nilai eigen dikembalikan tanpa urutan tertentu. Terapkan sort() (dan permutasi yang sama pada vektor eigen melalui argsort()) ketika urutan yang terurut diperlukan.

  • Vektor eigen unik hanya hingga skalar tak-nol, sehingga tanda vektor eigen individual tidak didefinisikan secara unik. Dua eksekusi yang benar dapat menghasilkan vektor bertanda berlawanan; ini tidak berbahaya.

6.13.6. norm#

Norma Euclidean (Frobenius) dari vektor atau matriks:

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...

Kata kunci opsional axis= mengambil norma sepanjang satu sumbu alih-alih seluruh array.

6.13.7. qr#

qr() memfaktorkan matriks persegi panjang A (bentuk (M, N)) menjadi Q ortonormal dan R segitiga atas sehingga 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)

Dekomposisi diimplementasikan melalui rotasi Givens berurutan. Pilihan yang tepat untuk masalah kuadrat terkecil di mana matriks tidak simetris.

6.13.8. Menyelesaikan sistem#

Dua pemecah khusus di bawah ulab.scipy.linalg keduanya lebih cepat dan lebih akurat daripada np.dot(np.linalg.inv(A), b):

  • solve_triangular(a, b, lower=False)() -- selesaikan a @ x = b dengan asumsi a adalah segitiga:

    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)() -- diberikan faktor Cholesky L, selesaikan A @ x = b di mana A = L @ L.T

    L = np.linalg.cholesky(A)
    x = sp.linalg.cho_solve(L, b)
    

Gunakan ini alih-alih membalik kapan pun struktur A memungkinkan -- keduanya menghemat pekerjaan eliminasi dan invers eksplisit.

6.13.9. Menyelesaikan sistem linear kecil#

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

Masalah yang sama dapat diekspresikan dengan memfaktorkan A dan memanggil pemecah yang sesuai -- lebih cepat dan lebih akurat ketika A memiliki struktur yang tepat.

Untuk referensi lengkap tingkat argumen, lihat numpy.linalg --- Rutin Aljabar Linear dan scipy.linalg --- Rutin aljabar linear.