Norma dan jarak

Menghitung norma vektor dan jarak antar titik dengan linalg.norm.

Daftar isi

Norma menyatakan besar sebuah vektor, sedangkan jarak antar titik dinyatakan sebagai norma dari selisihnya, sehingga satu fungsi NumPy mencakup keduanya. Topik ini membahas perhitungan norma dengan np.linalg.norm, pemilihan jenis norma melalui parameter ord, jarak dua titik, perluasannya ke banyak titik dengan broadcasting, dan jebakan yang menyertainya. Setelah topik ini dipahami, pengukuran besar dan jarak pada data berdimensi banyak dapat ditulis secara ringkas dan benar.

Norma sebagai panjang vektor#

Norma yang paling umum adalah norma Euclidean, yaitu akar dari jumlah kuadrat seluruh elemen vektor. Notasinya dituliskan sebagai berikut.

∥v∥2=v12+v22+⋯+vn2 \lVert v \rVert_2 = \sqrt{v_1^2 + v_2^2 + \cdots + v_n^2}

Fungsi np.linalg.norm(v) menghitung norma tersebut secara bawaan, sehingga rumus akar dan kuadratnya tidak perlu ditulis manual.

python
import numpy as np

v = np.array([3.0, 4.0])
print(np.linalg.norm(v))
print(np.sqrt(v @ v))
text Keluaran
5.0
5.0

Baris kedua memperlihatkan jalan alternatif, yaitu v @ v yang menghasilkan jumlah kuadrat seluruh elemen, lalu diakarkan. Hasil keduanya identik, sehingga pilihan bentuknya hanya soal keterbacaan. Norma selalu bernilai tak negatif dan bernilai nol hanya untuk vektor nol, sehingga nilainya layak digunakan sebagai ukuran besar. Perhitungan norma muncul hampir di semua pekerjaan data, misalnya untuk meringkas selisih antara prediksi dan nilai sebenarnya menjadi satu angka yang mudah dibandingkan.

Memilih jenis norma dengan ord#

Parameter ord mengubah definisi besar yang digunakan fungsi norm, dan tiga nilai berikut adalah yang paling sering digunakan.

python
import numpy as np

v = np.array([3.0, -4.0])
print(np.linalg.norm(v, ord=1))
print(np.linalg.norm(v, ord=2))
print(np.linalg.norm(v, ord=np.inf))
text Keluaran
7.0
5.0
4.0
Nilai ordNama umumCara menghitungNilai pada [3, -4]
1norma L1jumlah nilai absolut semua elemen7.0
2norma L2 atau Euclideanakar jumlah kuadrat semua elemen5.0
np.infnorma maksimumnilai absolut terbesar4.0

Norma L1 menghitung panjang sepanjang sumbu koordinat, sehingga cocok ketika penyimpangan tiap komponen perlu dijumlahkan apa adanya. Norma L2 menghitung panjang garis lurus dan menjadi pilihan bawaan untuk jarak Euclidean. Norma maksimum mengukur komponen terburuk, sehingga berguna ketika satu komponen besar sudah cukup untuk menandai perbedaan. Tanpa argumen ord, fungsi norm memilih norma L2, sehingga kode tanpa parameter tersebut tetap benar untuk jarak biasa.

Jarak dua titik sebagai norma selisih#

Jarak Euclidean antara dua titik didefinisikan sebagai norma selisih keduanya, yaitu d(p,q)=∥p−q∥2d(p, q) = \lVert p - q \rVert_2. Terjemahan kodenya langsung, yaitu selisih kedua array dihitung terlebih dahulu, lalu dinormakan.

python
import numpy as np

p = np.array([2.0, 5.0])
q = np.array([6.0, 8.0])
d = np.linalg.norm(p - q)
print(d)
text Keluaran
5.0

Selisih p - q bernilai [-4. -3.], dan normanya membentuk tripel Pythagoras yang hasilnya 5.0. Pola ini bekerja untuk dimensi berapa pun tanpa mengubah kode, karena norma menjumlahkan kuadrat seluruh komponen selisihnya.

Pola yang sama diterapkan pada sekumpulan titik sekaligus dengan bantuan axis. Contoh berikut menghitung jarak tiga titik terhadap satu titik acuan, lalu mencari indeks titik terdekatnya.

python
import numpy as np

titik = np.array([[2.0, 5.0],
                  [6.0, 8.0],
                  [1.0, 1.0]])
asal = np.array([0.0, 0.0])
jarak = np.linalg.norm(titik - asal, axis=1)
print(np.round(jarak, 4))
print(np.argmin(jarak))
text Keluaran
[ 5.3852 10.      1.4142]
2

Argumen axis=1 menyatakan bahwa norma dihitung per baris, sehingga keluarannya berupa satu jarak untuk setiap titik. Pencarian titik terdekat kemudian cukup memanggil np.argmin atas deret jarak tersebut, yang mengembalikan indeks 2 untuk titik [1.0, 1.0].

Matriks jarak antar pasangan titik#

Jarak antar setiap pasangan titik diperoleh dengan pola yang sama, yaitu menyusun seluruh selisih berpasangan dengan broadcasting, lalu menormakan sumbu terakhirnya. Rincian aturan penyiarannya dibahas pada modul broadcasting, sehingga di sini hanya hasil akhirnya yang diperlihatkan.

python
import numpy as np

titik = np.array([[0.0, 0.0],
                  [3.0, 4.0],
                  [6.0, 8.0]])
selisih = titik[:, np.newaxis, :] - titik[np.newaxis, :, :]
matriks_jarak = np.linalg.norm(selisih, axis=-1)
print(matriks_jarak)
text Keluaran
[[ 0.  5. 10.]
 [ 5.  0.  5.]
 [10.  5.  0.]]

Keluarannya adalah matriks jarak berbentuk (3, 3), yaitu satu sel untuk setiap pasangan titik. Matriks ini selalu simetris dengan diagonal nol, karena jarak sebuah titik ke dirinya sendiri bernilai nol dan penukaran urutan pasangan tidak mengubah nilainya. Pola ini menggantikan dua perulangan bersarang dengan satu ekspresi, sehingga tetap ringkas ketika banyaknya titik bertambah. Matriks jarak juga menjadi masukan bagi banyak metode lanjutan, antara lain pengelompokan berbasis kedekatan dan pencarian tetangga terdekat.

Norma matriks#

Fungsi np.linalg.norm juga menerima array dua dimensi, dan tanpa argumen tambahan menghitung norma Frobenius, yaitu akar dari jumlah kuadrat seluruh elemennya.

python
import numpy as np

A = np.array([[1.0, 2.0],
              [3.0, 4.0]])
print(np.round(np.linalg.norm(A), 4))
text Keluaran
5.4772

Nilainya dihitung dari 12+22+32+42=30\sqrt{1^2 + 2^2 + 3^2 + 4^2} = \sqrt{30}. Kegunaan utama norma matriks adalah meringkas selisih dua matriks menjadi satu angka, misalnya besar kesalahan rekonstruksi pada dekomposisi SVD yang diukur dengan np.linalg.norm(A - A1). Perlu dicatat bahwa norma Frobenius berbeda dari norma maksimum baris atau kolom yang kadang muncul pada buku teks, sehingga bila definisi lain dibutuhkan, nilai ord yang sesuai harus dinyatakan secara eksplisit. Untuk kebanyakan keperluan pengukuran kesalahan, nilai bawaan Frobenius sudah memadai dan konsisten dengan kebiasaan umum NumPy.

Kesalahan umum#

Kesalahan pertama adalah memanggil norm pada array dua dimensi tanpa argumen axis sambil mengharapkan jarak per baris. Tanpa axis, fungsi ini menormakan seluruh array menjadi satu skalar Frobenius.

python
import numpy as np

titik = np.array([[2.0, 5.0],
                  [6.0, 8.0],
                  [1.0, 1.0]])
print(np.round(np.linalg.norm(titik), 4))
print(np.round(np.linalg.norm(titik, axis=1), 4))
text Keluaran
11.4455
[ 5.3852 10.      1.4142]

Nilai 11.4455 adalah besar seluruh array, bukan jarak satu titik mana pun, sedangkan pemanggilan dengan axis=1 menghasilkan tiga jarak yang dimaksud. Perbaikannya adalah selalu menyatakan axis ketika setiap baris atau kolom mewakili satu vektor tersendiri.

Kesalahan kedua adalah menyebut hasil ord=1 sebagai jarak lurus. Norma L1 dan L2 bernilai berbeda untuk vektor yang sama, seperti 7.0 berbanding 5.0 pada contoh di atas, sehingga menyebut keduanya dengan istilah yang sama menyesatkan pembaca kode maupun angka laporan yang dihasilkannya.

Kesalahan ketiga adalah mengandalkan norma untuk membandingkan arah. Norma membuang tanda seluruh komponennya, sehingga dua selisih yang berlawanan arah memiliki norma yang sama. Apabila arah penyimpangan penting, bandingkan array selisihnya secara langsung dan sisakan norma untuk besarnya saja.

Ringkasan#

  • np.linalg.norm(v) menghitung norma Euclidean secara bawaan, dan jarak dua titik ditulis sebagai np.linalg.norm(p - q).
  • Parameter ord memilih jenis norma, dengan 1 untuk jumlah nilai absolut, 2 untuk jarak lurus, dan np.inf untuk komponen terbesar.
  • axis menentukan arah perhitungan pada array dua dimensi, dan tanpa axis hasilnya adalah satu skalar norma Frobenius.
  • Matriks jarak berpasangan disusun dengan broadcasting selisih lalu dinormakan pada sumbu terakhir.

Referensi#