Chapter sebelumnya berakhir dengan satu pertanyaan yang menunggu jawaban: angka-angka seperti prior kelas dan peluang tiap kata di Naive Bayes — parameter model secara umum — dihitung dari mana? Jawaban paling berpengaruh dalam sejarah machine learning adalah maximum likelihood estimation (MLE): pilih parameter yang membuat data yang kita amati menjadi paling mungkin terjadi. Prinsip satu kalimat tersebut menjelaskan asal-usul np.mean, rumus least squares, fungsi loss MSE, hingga algoritme EM pada Gaussian Mixture Model. Chapter ini menurunkannya untuk distribusi Gaussian, membuktikan rumus analitiknya lewat grid search, lalu menunjukkan bahwa mean squared error yang sudah lama kita pakai ternyata MLE dengan derau Gaussian.
Peluang vs Likelihood: Satu Rumus, Dua Arah #
Kedua istilah itu memakai rumus yang sama, p(x | θ), tetapi dibaca dari arah berlawanan. Peluang memandang θ tetap dan x variabel: “jika rata-rata populasi 170 cm, apa peluang mengambil sampel dengan rata-rata 172 cm?” Likelihood membaliknya — x sudah diamati dan θ yang dijelajahi: “sampel sudah di tangan; untuk θ yang mana sampel ini paling wajar?” Notasinya L(θ | x) = p(x | θ), diperlakukan sebagai fungsi atas θ, dan MLE memilih puncaknya: θ̂ = argmax L(θ | x).
Bedanya bukan sekadar gaya menulis. Peluang menjumlah ke satu atas seluruh kemungkinan data; likelihood tidak menjumlah ke satu atas seluruh θ — likelihood bukan distribusi peluang atas parameter. Konsekuensinya praktis: nilai likelihood 0,0003 tidak bisa dibaca sebagai “peluang parameter benar adalah 0,03%”; yang bisa dibandingkan hanyalah likelihood antar-θ pada data yang sama.
Log-Likelihood: Perkalian yang Diubah Jadi Penjumlahan #
Sampel berisi banyak titik dianggap saling bebas, sehingga likelihoodnya adalah hasil kali ∏ p(xᵢ | θ). Untuk n = 80 titik Gaussian, hasil kali angka-angka sekitar 0,05 mudah jatuh ke orde 10⁻¹⁰⁰ — komputer sanggup menampungnya di kasus ini, tetapi pada model nyata dengan ribuan parameter angka semacam itu underflow ke nol. Solusinya standar di seluruh machine learning: bekerja di ranah logaritma.
log L(θ | x) = Σ log p(xᵢ | θ)Logaritma bersifat monoton naik, jadi θ yang memaksimalkan log-likelihood juga memaksimalkan likelihood. Perkalian berubah menjadi penjumlahan yang stabil secara numerik, dan untuk Gaussian suku-sukunya sederhana: -n/2 · log(2πσ²) - Σ(xᵢ-μ)²/(2σ²). Kebiasaan industri bahkan membalik tandanya: minimalkan negative log-likelihood (NLL) — bentuk inilah yang dikenal sebagai fungsi loss di banyak model.
Solusi Analitik untuk Gaussian #
Untuk Gaussian, puncak log-likelihood bisa dicari dengan turunan, bukan pencarian numerik. Turunan log-likelihood terhadap μ menghasilkan Σ(xᵢ - μ) = 0, sehingga μ̂ = (1/n) Σxᵢ — rata-rata sampel. Turunan terhadap σ² menghasilkan σ̂² = (1/n) Σ(xᵢ - μ̂)² — rata-rata simpangan kuadrat dengan pembagi n, bukan n-1. Dua fakta mengejutkan bagi yang pernah belajar statistika: rata-rata sampel yang selama ini kita anggap rumus deskriptif ternyata adalah MLE, dan np.std bawaan (pembagi n) adalah taksiran likelihood maksimum, sedangkan ddof=1 adalah koreksi bias untuk varians.
Praktik: Grid Search vs Rumus Tertutup #
Teori akan meyakinkan kalau bisa dibuktikan. Skrip berikut mengambil 80 tinggi sintetis dari N(170, 8²), lalu mengadu tiga hal: grid search μ terhadap fungsi log-likelihood yang kita tulis sendiri, rumus analitik np.mean, dan grid search σ terhadap rumus np.std. Bagian akhirnya membawa kita ke dunia regresi: menggeser kemiringan garis dari posisi least squares untuk melihat SSE dan log-likelihood bergerak berlawanan arah.
# Maximum likelihood estimation (MLE): likelihood, log-likelihood,
# solusi analitik Gaussian, dan hubungannya dengan least squares.
import numpy as np
# 1) Data sintetis: tinggi 80 mahasiswa ~ N(170, 8^2).
rng = np.random.default_rng(42)
n = 80
tinggi = rng.normal(170.0, 8.0, n)
# 2) Log-likelihood sampel Gaussian (murni NumPy, tanpa pustaka ML).
def log_likelihood(x, mu, sigma):
m = len(x)
return (-m / 2 * np.log(2 * np.pi * sigma ** 2)
- np.sum((x - mu) ** 2) / (2 * sigma ** 2))
# 3) Likelihood sebagai fungsi parameter: grid search untuk mu.
kandidat = np.linspace(166.0, 174.0, 41)
ll = np.array([log_likelihood(tinggi, m, 8.0) for m in kandidat])
print("=== Estimasi mu dengan grid search (sigma diketahui 8.0) ===")
print(f"argmax grid : mu = {kandidat[np.argmax(ll)]:.4f}")
print(f"np.mean(data) : mu = {tinggi.mean():.4f}")
print(f"selisih : {abs(kandidat[np.argmax(ll)] - tinggi.mean()):.4f}")
print(f"log-lik mu=170: {log_likelihood(tinggi, 170.0, 8.0):.3f}")
print(f"log-lik mu=178: {log_likelihood(tinggi, 178.0, 8.0):.3f}")
# 4) MLE dua parameter Gaussian: rumus analitik tertutup.
mu_hat = float(np.mean(tinggi))
sigma_mle = float(np.std(tinggi)) # pembagi n (ddof=0)
sigma_unbiased = float(np.std(tinggi, ddof=1)) # pembagi n-1
print("\n=== MLE dua parameter Gaussian (rumus analitik) ===")
print(f"mu_hat (rata-rata sampel) = {mu_hat:.4f}")
print(f"sigma_MLE, pembagi n = {sigma_mle:.4f}")
print(f"sigma sampel, pembagi n-1 = {sigma_unbiased:.4f}")
# 5) Verifikasi sigma lewat grid (mu tetap di mu_hat).
sig = np.linspace(5.0, 11.0, 61)
ll_sig = np.array([log_likelihood(tinggi, mu_hat, s) for s in sig])
print(f"argmax grid sigma = {sig[np.argmax(ll_sig)]:.4f} "
f"(rumus analitik {sigma_mle:.4f})")
# 6) MSE = MLE derau Gaussian: regresi harga rumah dari luas.
luas = rng.uniform(60, 120, n)
harga = 30 + 0.8 * luas + rng.normal(0, 6.0, n)
k, b = np.polyfit(luas, harga, deg=1)
def sse_slope(km):
return float(((harga - (km * luas + b)) ** 2).sum())
def profile_loglik(km):
s2 = sse_slope(km) / n
return -n / 2 * (np.log(2 * np.pi * s2) + 1)
print("\n=== MSE sebagai MLE: harga = k*luas + b + derau ===")
print(f"k least squares = {k:.4f}")
print(f"sigma_MLE derau = sqrt(SSE/n) = {np.sqrt(sse_slope(k) / n):.4f}")
print("geser kemiringan k: SSE naik, log-likelihood turun:")
for geser in (-0.10, -0.05, 0.0, 0.05, 0.10):
kg = k + geser
print(f" k={kg:.3f} SSE={sse_slope(kg):>9.2f} "
f"log-lik={profile_loglik(kg):>9.3f}")Output yang Dihasilkan:
=== Estimasi mu dengan grid search (sigma diketahui 8.0) ===
argmax grid : mu = 170.2000
np.mean(data) : mu = 170.2058
selisih : 0.0058
log-lik mu=170: -263.584
log-lik mu=178: -301.526
=== MLE dua parameter Gaussian (rumus analitik) ===
mu_hat (rata-rata sampel) = 170.2058
sigma_MLE, pembagi n = 6.1562
sigma sampel, pembagi n-1 = 6.1951
argmax grid sigma = 6.2000 (rumus analitik 6.1562)
=== MSE sebagai MLE: harga = k*luas + b + derau ===
k least squares = 0.7700
sigma_MLE derau = sqrt(SSE/n) = 5.8286
geser kemiringan k: SSE naik, log-likelihood turun:
k=0.670 SSE= 9194.15 log-lik= -303.287
k=0.720 SSE= 4336.88 log-lik= -273.230
k=0.770 SSE= 2717.79 log-lik= -254.537
k=0.820 SSE= 4336.88 log-lik= -273.230
k=0.870 SSE= 9194.15 log-lik= -303.287Mari kita bedah hasil eksekusinya:
- Baris 13–16 (fungsi log-likelihood): fungsi lima baris tersebut adalah seluruh “model” kita — suku pertama konstanta normalisasi kali
n, suku kedua adalah jumlah simpangan kuadrat. Perhatikan kemiripannya dengan SSE; kedekatan itu bukan kebetulan dan menjadi klimaks bagian akhir skrip. - Baris 20–27 (grid μ): dari 41 kandidat μ, puncak log-likelihood jatuh di 170,2000, hanya 0,0058 dari
np.mean= 170,2058 — selisihnya murni resolusi kisi (langkah 0,2). Log-likelihood di μ=170 (−263,584) dan μ=178 (−301,526) memperlihatkan bentuk kurva likelihood: rata-rata sampel memang parameternya yang paling menjelaskan data. - Baris 30–36 (rumus analitik):
np.meandannp.std(pembagi n) menghasilkan 170,2058 dan 6,1562; koreksi pembagi n−1 memberi 6,1951. Taksiran likelihood maksimum secara sistematis mengecilkan σ pada sampel kecil — harga yang dibayar karena μ juga ditaksir dari data yang sama. - Baris 39–42 (grid σ): puncak kisi kedua jatuh di 6,2000, konsisten dengan rumus 6,1562 pada resolusi kisi 0,1. Dua jalur berbeda — turunan analitik dan pencarian brute force — bertemu di parameter yang sama.
- Baris 45–47 dan 50–66 (regresi): garis least squares
k = 0,7700meminimalkan SSE = 2717,79 denganσ̂ = sqrt(SSE/n) = 5,8286. Menggeser kemiringan +0,05 atau −0,05 sama-sama menaikkan SSE ke 4336,88 dan menurunkan log-likelihood ke −273,230; geser ±0,10 menaikkan SSE ke 9194,15. Simetri kiri-kanan ini murni aljabar: dari titik optimum, pergeseran δ menambah δ²·Σx² pada SSE — bukti numerik bahwa meminimalkan SSE identik dengan memaksimalkan likelihood Gaussian.
Least Squares adalah MLE #
Hubungan pada bagian akhir skrip bisa ditulis sebagai satu kalimat: regresi least squares adalah MLE dengan asumsi derau Gaussian. Substitusikan model yᵢ = k·xᵢ + b + εᵢ dengan εᵢ ~ N(0, σ²) ke log-likelihood, semua suku yang mengandung parameter (k, b) terkumpul pada -Σ(yᵢ - k·xᵢ - b)²/(2σ²) — memaksimalkannya sama dengan meminimalkan SSE. Sesudahnya σ mengikuti lewat rumus tertutup σ̂² = SSE/n, persis baris 61 pada skrip.
Skema yang sama menjelaskan fungsi loss lain yang sudah kita temui di sepanjang Course ini:
| Fungsi loss | Asumsi probabilistik pada derau/label | Tempat kita menemukannya |
|---|---|---|
| MSE | Derau Gaussian pada target | Regresi linear, regresi polynomial |
| Log loss / cross-entropy | Distribusi kategori (Bernoulli/multinomial) | Regresi logistik, klasifikasi |
| MAE / L1 | Derau Laplace (ekor lebih tebal) | Regresi robust, Lasso |
Referensi Resmi #
- numpy.mean — NumPy Documentation — rata-rata sampel yang terbukti menjadi MLE parameter μ pada contoh di chapter ini.
- numpy.std — NumPy Documentation
— dokumentasi argumen
ddofdan perbedaan pembagi n vs n−1. - Linear Models — scikit-learn User Guide — keluarga model linear yang dilatih dengan least squares, padanan MLE derau Gaussian.