Perkalian Matriks

Aturan baris-demi-kolom dan pengaruh urutan.

Daftar isi

Perkalian matriks menggabungkan dua matriks menjadi satu matriks baru melalui aturan baris-demi-kolom, dan operasi ini menjadi inti banyak perhitungan pada machine learning serta grafika. Topik ini membahas aturan penghitungannya, syarat ukuran kedua matriks, dan alasan urutan perkalian tidak boleh ditukar. Setiap langkah dihitung secara manual, kemudian diverifikasi menggunakan NumPy. Setelah topik ini selesai, perkalian matriks dapat dikerjakan dengan tangan dan hasilnya dapat diperiksa ulang dalam kode.

Aturan baris-demi-kolom#

Elemen hasil perkalian dihitung dari satu baris matriks kiri dan satu kolom matriks kanan. Apabila AA berukuran m×nm \times n dan BB berukuran n×pn \times p, hasil C=ABC = AB berukuran m×pm \times p dengan setiap elemen mengikuti aturan berikut.

cij=ai1b1j+ai2b2j+⋯+ainbnj c_{ij} = a_{i1} b_{1j} + a_{i2} b_{2j} + \cdots + a_{in} b_{nj}

Setiap elemen cijc_{ij} merupakan perkalian titik (dot product) antara baris ke-ii dari AA dan kolom ke-jj dari BB, yaitu operasi yang sama dengan yang digunakan saat mengukur kemiripan dua vektor. Untuk membiasakan aturannya, dua matriks kecil berikut dihitung secara manual terlebih dahulu.

A=(123456),B=(789101112) A = \begin{pmatrix} 1 & 2 & 3 \\ 4 & 5 & 6 \end{pmatrix}, \qquad B = \begin{pmatrix} 7 & 8 \\ 9 & 10 \\ 11 & 12 \end{pmatrix}

Elemen c11c_{11} diperoleh dari baris pertama AA dan kolom pertama BB sebagaimana perhitungan berikut. Cara yang sama diterapkan pada tiga pasangan baris-kolom lainnya sehingga terkumpul empat elemen hasil.

c11=1×7+2×9+3×11=58 c_{11} = 1 \times 7 + 2 \times 9 + 3 \times 11 = 58

Syarat ukuran hasil#

Perkalian matriks hanya terdefinisi apabila banyak kolom matriks kiri sama dengan banyak baris matriks kanan. Aturan ukurannya ringkas, yaitu (m×n)(n×p)(m \times n)(n \times p) menghasilkan m×pm \times p, dan angka di tengah wajib sama karena angka itu menentukan banyaknya perkalian pada setiap elemen. Hasilnya mewarisi banyak baris dari matriks kiri dan banyak kolom dari matriks kanan. Apabila syarat itu dilanggar, NumPy menolak perhitungan dengan pesan error yang menyebut ketidakcocokan dimensi. Diagram berikut merangkum aturan tersebut.

A2×3×B3×2=hasil2 × 2dua angka ini harus sama
Aturan ukuran perkalian matriks pada contoh 2 × 3 dikali 3 × 2

Contoh pada bagian sebelumnya memenuhi aturan ini, yaitu 2×32 \times 3 dikali 3×23 \times 2 menghasilkan 2×22 \times 2. Kebalikannya juga terdefinisi karena 3×23 \times 2 dikali 2×32 \times 3 menghasilkan 3×33 \times 3, tetapi hasilnya berbeda ukuran dan berbeda isi. Kedua kemungkinan ini memperlihatkan pengaruh urutan secara nyata. Kasus lain yang mudah terlewat adalah perkalian vektor baris dengan vektor kolom yang menghasilkan matriks 1×11 \times 1, berbeda dari perkalian sebaliknya yang berukuran penuh.

Urutan menentukan hasil#

Perkalian matriks tidak komutatif, yaitu ABAB umumnya tidak sama dengan BABA. Ketidaksamaan ini muncul dalam dua bentuk, yaitu hasilnya berbeda ukuran sebagaimana pasangan AA dan BB di atas, atau berbeda isi meskipun ukurannya sama. Kasus kedua lebih mudah terlewat karena kedua perkalian tampak sah namun memberikan matriks yang berbeda. Pada transformasi geometri, memutar lalu menskalakan sebuah bentuk jarang memberikan hasil yang sama dengan menskalakan lalu memutar.

Kode berikut menghitung kedua urutan untuk kedua kasus, lalu menguji kesamaan dua hasil perkalian matriks persegi menggunakan np.allclose.

python perkalian_matriks.py
import numpy as np

A = np.array([
    [1, 2, 3],
    [4, 5, 6],
])   # ukuran 2x3
B = np.array([
    [ 7,  8],
    [ 9, 10],
    [11, 12],
])   # ukuran 3x2

C = A @ B   # perkalian matriks: baris A dikali kolom B
print("Hasil A @ B:")
print(C)
print(f"c[0, 0] = {A[0, 0]}*{B[0, 0]} + {A[0, 1]}*{B[1, 0]} + {A[0, 2]}*{B[2, 0]} = {C[0, 0]}")
print(f"ukuran A@B : {C.shape}")

D = B @ A   # urutan dibalik
print("Hasil B @ A:")
print(D)
print(f"ukuran B@A : {D.shape}")

# dua matriks persegi berukuran sama pun tetap tidak komutatif
P = np.array([
    [0, 1],
    [1, 0],
])   # penukar baris dan kolom
S = np.array([
    [2, 0],
    [0, 5],
])   # penskalaan

print(f"P @ S:\n{P @ S}")
print(f"S @ P:\n{S @ P}")
print(f"P @ S sama dengan S @ P ? {np.allclose(P @ S, S @ P)}")
text Keluaran
Hasil A @ B:
[[ 58  64]
 [139 154]]
c[0, 0] = 1*7 + 2*9 + 3*11 = 58
ukuran A@B : (2, 2)
Hasil B @ A:
[[ 39  54  69]
 [ 49  68  87]
 [ 59  82 105]]
ukuran B@A : (3, 3)
P @ S:
[[0 5]
 [2 0]]
S @ P:
[[0 2]
 [5 0]]
P @ S sama dengan S @ P ? False

Keluaran menegaskan dua hal sekaligus. Perkalian A @ B menghasilkan matriks 2×22 \times 2 dengan c11=58c_{11} = 58 yang sama dengan perhitungan manual, sedangkan B @ A menghasilkan matriks 3×33 \times 3 yang isinya sama sekali berbeda. Pada pasangan matriks persegi, P @ S dan S @ P sama-sama berukuran 2×22 \times 2, tetapi np.allclose mengembalikan False karena posisi angka 2 dan 5 saling bertukar. Urutan perkalian matriks dengan demikian menjadi bagian dari maknanya, bukan sekadar gaya penulisan.

Di mana hal ini ditemui dalam kode#

Perkalian matriks menjadi operasi inti pada pustaka machine learning dan perenderan grafik, sehingga bentuknya muncul jauh melampaui contoh kecil di atas. Perangkat keras bahkan dirancang khusus agar perkalian ini berjalan cepat pada ukuran besar. Beberapa tempat yang mudah dikenali adalah sebagai berikut:

  • Setiap lapisan neural network mengalikan masukannya dengan matriks bobot, dan beberapa lapisan berurutan berarti perkalian matriks yang berantai.
  • Prediksi model linear untuk banyak sampel sekaligus ditulis sebagai perkalian matriks data dengan vektor bobot, satu operasi untuk seluruh sampel.
  • Komposisi dua rotasi kamera pada aplikasi tiga dimensi dinyatakan sebagai perkalian dua matriks rotasi, dan menukar urutannya menghasilkan arah pandang akhir yang berbeda.
  • Perkalian dua matriks n×nn \times n versi naif memerlukan sekitar n3n^3 perkalian bilangan, dan itu menjadi alasan ukuran matriks selalu diperhatikan pada kode yang sensitif terhadap waktu.

Ketidakkomutatifan pada butir ketiga berlawanan dengan intuisi sehari-hari. Kamera yang diputar ke kiri lalu ke atas tidak menempuh jalur yang sama dengan diputar ke atas lalu ke kiri, dan perkalian matriks merekam perbedaan itu secara tepat. Karena itu, menulis urutan transformasi dalam komentar kode membantu saat hasil akhir tidak sesuai dugaan.

Ringkasan#

  • Elemen cijc_{ij} hasil perkalian dihitung sebagai perkalian titik antara baris ke-ii matriks kiri dan kolom ke-jj matriks kanan.
  • Syarat ukurannya (m×n)(n×p)=(m×p)(m \times n)(n \times p) = (m \times p), dan pelanggarannya ditolak NumPy sebagai error dimensi.
  • Perkalian matriks tidak komutatif, sehingga ABAB dan BABA dapat berbeda ukuran maupun berbeda isi.
  • Operator @ adalah perkalian matriks pada NumPy, sedangkan * tetap berarti perkalian per elemen.

Referensi#