Bayangkan tiga struk belanja dari toko yang sama. Struk pertama: 2 kg gula dan 1 kg kopi, total Rp35000. Struk kedua: 1 kg gula dan 3 kg kopi, total Rp60000. Struk ketiga: 3 kg gula dan 2 kg kopi, total Rp70000. Dua harga yang tidak diketahui, tetapi tiga persamaan — sistem overdetermined seperti ini hampir selalu tidak punya solusi eksak, karena tiga syarat harus dipenuhi dua angka sekaligus.
Least squares menawarkan kompromi yang terukur: cari harga yang membuat jumlah kuadrat selisih (galat) sekecil mungkin. Metode ini bukan sekadar perbaikan: metode inilah fondasi regresi linear. NumPy menyediakannya lewat np.linalg.lstsq, dan bab ini membedah keempat nilai kembaliannya, makna residuals, serta kaitannya dengan pemodelan linear.
Sistem Overdetermined dan np.linalg.lstsq #
Kita terjemahkan cerita struk belanja menjadi matriks A (3x2) dan vektor b (3 elemen), lalu panggil lstsq:
import numpy as np
A = np.array([[2.0, 1.0],
[1.0, 3.0],
[3.0, 2.0]])
b = np.array([35000.0, 60000.0, 70000.0])
x, residuals, rank, sv = np.linalg.lstsq(A, b, rcond=None)
print(x)
print(residuals)
print(A @ x - b)
print(rank)
print(sv)Output yang Dihasilkan:
[11400. 16400.]
[26999999.99999998]
[ 4200. 600. -3000.]
2
[5. 1.73205081]Bedah baris demi baris:
- Baris 3-5 (
A): setiap baris adalah satu struk —[jumlah gula, jumlah kopi]. - Baris 6 (
b): total belanja tiap struk. - Baris 7:
lstsqmengembalikan empat nilai sekaligus;rcond=Nonememakai ambang default dan meniadakan peringatan versi lama. - Baris 8 (
x): solusi kompromi[11400. 16400.]— dugaan harga gula Rp11400 dan kopi Rp16400. Harga ini tidak memenuhi ketiga struk, dan memang tidak dijanjikan demikian. - Baris 9 (
residuals): jumlah kuadrat galat (SSE). Nilai matematisnya 27000000; digit belakang yang sedikit menyimpang adalah jejak aritmetika float — tema yang ditutup pada Chapter Stabilitas Numerik. - Baris 10 (
A @ x - b): galat tiap struk:+4200,+600,-3000. Kuadratkan dan jumlahkan, hasilnya persis nilai diresiduals. - Baris 11 (
rank): rankAadalah2— kedua kolom bebas, sehingga solusi kompromi tunggal. - Baris 12 (
sv): nilai singularAyang terurut menurun, pratinjau bahwalstsqbekerja di atas SVD.
| Nilai kembali | Bentuk | Arti |
|---|---|---|
x | (n,) | solusi least squares |
residuals | (1,) | jumlah kuadrat galat (SSE) |
rank | skalar | rank matriks A |
sv | (n,) | nilai singular A terurut menurun |
Residuals: Penanda Ada Tidaknya Solusi Eksak #
Bentuk array residuals membawa informasi yang mudah terlewat: sistem punya solusi eksak atau tidak. Kita bandingkan dengan sistem yang konsisten — cukup dua struk pertama, dua persamaan untuk dua harga:
import numpy as np
A2 = np.array([[2.0, 1.0],
[1.0, 3.0]])
b2 = np.array([35000.0, 60000.0])
x2, res2, rank2, sv2 = np.linalg.lstsq(A2, b2, rcond=None)
print(x2)
print(res2.shape)
print(res2)Output yang Dihasilkan:
[ 9000. 17000.]
(0,)
[]- Baris 3-4 (
A2): hanya dua baris pertama dariAsebelumnya — sistem persegi 2x2. - Baris 6:
lstsqtetap bisa dipakai; ia menyelesaikan sistem persis maupun overdetermined. - Baris 7 (
x2): solusi[9000. 17000.]memenuhi kedua persamaan persis:2·9000 + 17000 = 35000dan9000 + 3·17000 = 60000. - Baris 8 (
res2.shape):(0,)— array residuals kosong. - Baris 9 (
res2):[], bukan0.0. Ketika solusi eksak ada,lstsqsama sekali tidak menghitung galat.
Regresi Linear sebagai Least Squares #
Model linear y = ax + b pada setiap titik data menghasilkan satu persamaan: a·x_i + b = y_i. Susun semua persamaan itu menjadi sistem X @ [a, b] = y, dan regresi linear berubah menjadi least squares biasa:
import numpy as np
x = np.array([1.0, 2.0, 3.0, 4.0, 5.0])
y = np.array([2.2, 3.8, 6.1, 7.9, 10.0])
X = np.column_stack([x, np.ones_like(x)])
print(X)
a, b = np.linalg.lstsq(X, y, rcond=None)[0]
print(a, b)
x_baru = np.array([6.0, 7.0])
prediksi = a * x_baru + b
print(prediksi)Output yang Dihasilkan:
[[1. 1.]
[2. 1.]
[3. 1.]
[4. 1.]
[5. 1.]]
1.97 0.08999999999999965
[11.91 13.88]- Baris 3-4: data pengamatan —
xjumlah poster promosi,ypenjualan dalam juta rupiah, lima hari. - Baris 5 (
X = np.column_stack(...)): susun design matrix: kolom pertama berisix, kolom kedua berisi konstanta 1. Kolom satu inilah yang membawa intersepb. - Baris 6 (
print(X)): bentuk(5, 2)— lima persamaan, dua parameter, persis pola overdetermined di awal bab. - Baris 7:
X @ [a, b]menghasilkana·x + b·1untuk setiap baris;lstsqmencari pasangan[a, b]terbaik, dan[0]mengambil elemen pertama tuple hasil. - Baris 8: kemiringan
a = 1.97dan intersepb ≈ 0.09. Model terpasang: penjualan ≈ 0.09 juta rupiah + 1.97 juta rupiah per poster. - Baris 10-11: prediksi untuk
xbaru dihitung langsung dari rumus model:a * x_baru + bmenghasilkan[11.91 13.88].
Pola design matrix ini meluas bebas: tambah satu kolom untuk setiap fitur, dan lstsq tetap mengembalikan satu koefisien per kolom. Berbeda dengan jalan pintas inv(X.T @ X) @ X.T @ y, fungsi lstsq menghitung lewat SVD sehingga tetap stabil pada data yang kurang kondisi baik — perbandingan dua jalur perhitungan semacam ini dibahas tuntas pada Chapter Decompositions dan Stabilitas Numerik.