Chapter sebelumnya ditutup dengan janji: begitu model menjadi campuran, MLE tidak lagi punya rumus tertutup dan kita membutuhkan prosedur iteratif. Chapter ini menepati janji itu lewat Gaussian Mixture Model (GMM) — model generatif yang menyatakan data sebagai campuran beberapa distribusi normal, dilatih dengan algoritme expectation-maximization (EM). Kita kembali bertemu 180 pelanggan toko ritel dari Chapter k-Means Clustering, tetapi dengan dua perbaikan besar: klaster boleh berbentuk elips dengan ukuran berbeda, dan keanggotaan tidak lagi hitam-putih melainkan soft assignment berupa probabilitas.
Campuran Gaussian: Distribusi Berlapis #
Ide dasarnya satu kalimat: setiap titik data dianggap dihasilkan oleh proses dua langkah — pilih satu komponen k dengan peluang w_k, lalu ambil sampel dari Gaussian N(μ_k, Σ_k) milik komponen tersebut. Distribusi hasilnya adalah campuran berlapis:
p(x) = Σ_k w_k · N(x | μ_k, Σ_k)Bobot w_k berjumlah satu dan menyatakan porsi tiap komponen; rata-rata μ_k dan kovarians Σ_k membentuk dan orientasi tiap gumpalan. Karena kovarians berupa matriks penuh, satu komponen bisa berupa elips miring yang lebarnya berbeda di tiap arah — kontras dengan k-Means yang hanya mengenal jarak lurus ke titik pusat. Atribut model scikit-learn memetakan langsung ke notasi tersebut: weights_, means_, dan covariances_.
EM: E-step dan M-step #
EM mengulang dua langkah yang saling mengisi sampai log-likelihood berhenti naik. E-step (expectation) menjawab pertanyaan tersembunyi: untuk tiap titik xₙ, seberapa besar tanggung jawab tiap komponen atas titik itu? Nilai tanggung jawab (responsibility) dihitung dengan aturan Bayes:
r(n,k) = w_k · N(xₙ | μ_k, Σ_k) / Σ_j w_j · N(xₙ | μ_j, Σ_j)M-step (maximization) kemudian memperbarui parameter dengan tanggung jawab tersebut sebagai bobot: rata-rata komponen menjadi rata-rata tertimbang seluruh titik, kovarians mengikuti simpangan tertimbangnya, dan bobot komponen menjadi total tanggung jawab dibagi jumlah titik. Parameternya kini saling bergantung — rata-rata baru mengubah tanggung jawab, tanggung jawab baru mengubah rata-rata — jadi solusi analitik satu kali tidak berlaku; iterasi bergantian inilah jalan keluarnya.
covariance_type: Empat Pilihan Bentuk #
Parameter covariance_type mengatur seberapa bebas matriks kovarians tiap komponen. Pilihan ini langsung menentukan jumlah parameter bebas — pada data dengan banyak fitur, bedanya besar.
| Tipe | Bentuk klaster | Parameter per komponen (d fitur) | Kapan dipakai |
|---|---|---|---|
full | Elips miring bebas | d² + d | Data cukup banyak, bentuk bebas |
tied | Elips miring sama untuk semua | d² + d (dibagi bersama) | Komponen sejenis, hemat parameter |
diag | Elips sejajar sumbu | d | Kompatibel fitur independen, data sedang |
spherical | Bulat, radius bebas | 1 | Data kecil, mirip k-Means tapi lunak |
Chapter ini memakai full agar kontras dengan k-Means terlihat maksimal; keempat pilihan tersedia di GaussianMixture dengan argumen yang sama.
Praktik: Soft Assignment dan Verifikasi Rumus #
Skrip berikut melatih GMM pada 180 pelanggan (fitur kunjungan bulanan dan rata-rata belanja, sama seperti Chapter k-Means Clustering, kini dengan sebaran segmen yang berbeda agar saling tumpang tindih), membaca ketiga atribut parameter, menguji predict_proba pada tiga titik, lalu memverifikasi rumus responsibility secara manual dengan scipy.stats.multivariate_normal.
# Gaussian Mixture Model: soft clustering, EM, dan pemilihan k via BIC/AIC.
# Kisah: 180 pelanggan toko ritel, dua fitur, tiga segmen yang tumpang tindih.
import numpy as np
from scipy import stats
from sklearn.datasets import make_blobs
from sklearn.mixture import GaussianMixture
# 1) Data sintetis: tiga segmen dengan sebaran berbeda agar saling tumpang tindih.
PUSAT_SEG = [[2.0, 2.0], [7.0, 4.0], [5.0, 9.0]]
X, y_asli = make_blobs(
n_samples=180, centers=PUSAT_SEG, cluster_std=[0.8, 1.2, 1.8],
random_state=42,
)
# 2) Latih GMM: k=3, kovarians penuh, EM dijalankan dari 5 inisialisasi.
gmm = GaussianMixture(
n_components=3, covariance_type="full", n_init=5, random_state=42
).fit(X)
print("Parameter hasil EM:")
print(f" bobot komponen : {gmm.weights_.round(3).tolist()}")
for c in range(3):
mu = gmm.means_[c]
cov_diag = np.diag(gmm.covariances_[c])
print(f" komponen {c}: mean ({mu[0]:.3f}, {mu[1]:.3f}) "
f"kovarians diag {np.round(cov_diag, 3).tolist()}")
# 3) Soft assignment: predict_proba untuk tiga pelanggan pilihan.
titik_uji = np.array([[2.0, 2.0], [6.0, 6.5], [9.0, 9.0]])
proba = gmm.predict_proba(titik_uji)
print("\nRespons (probabilitas keanggotaan) tiga titik:")
nama_titik = ["pusat segmen A", "di antara segmen", "tepi segmen longgar"]
for nama, x, p in zip(nama_titik, titik_uji, proba):
print(f" ({x[0]:.1f}, {x[1]:.1f}) {nama:>17}: "
f"[{p[0]:.3f}, {p[1]:.3f}, {p[2]:.3f}]")
# 4) Verifikasi rumus: r_k = w_k N(x|mu_k,S_k) / sum_j w_j N(x|mu_j,S_j).
dens = np.array([
gmm.weights_[k]
* stats.multivariate_normal(gmm.means_[k], gmm.covariances_[k]).pdf(titik_uji)
for k in range(3)
]).T
manual = dens / dens.sum(axis=1, keepdims=True)
print(f"\nSelisih maks vs rumus manual: {np.max(np.abs(manual - proba)):.2e}")
# 5) Titik ambigu vs tegas pada seluruh data: ambang soft assignment.
proba_semua = gmm.predict_proba(X)
maks = proba_semua.max(axis=1)
print(f"\npelanggan ambigu (respons maks < 0.80): {(maks < 0.80).sum()} dari {len(X)}")
print(f"pelanggan tegas (respons maks > 0.95): {(maks > 0.95).sum()} dari {len(X)}")
# 6) Pemilihan k dengan BIC dan AIC: k = 1..6.
print("\n k BIC AIC")
bic_list, aic_list = [], []
for k in range(1, 7):
g = GaussianMixture(
n_components=k, covariance_type="full", n_init=5, random_state=42
).fit(X)
bic_list.append(g.bic(X))
aic_list.append(g.aic(X))
print(f"{k:>2} {g.bic(X):>10.1f} {g.aic(X):>9.1f}")
print(f"k terbaik menurut BIC: {int(np.argmin(bic_list)) + 1}")
print(f"k terbaik menurut AIC: {int(np.argmin(aic_list)) + 1}")
# 7) Log-kepadatan tiap titik: pintu masuk ke skor anomali.
print("\nLog-kepadatan (score_samples) tiga titik uji:")
for x, ld in zip(titik_uji, gmm.score_samples(titik_uji)):
print(f" ({x[0]:.1f}, {x[1]:.1f}): {ld:.3f}")Output yang Dihasilkan:
Parameter hasil EM:
bobot komponen : [0.344, 0.333, 0.323]
komponen 0: mean (7.003, 4.246) kovarians diag [1.258, 1.52]
komponen 1: mean (1.899, 1.973) kovarians diag [0.478, 0.605]
komponen 2: mean (5.140, 8.907) kovarians diag [2.875, 1.781]
Respons (probabilitas keanggotaan) tiga titik:
(2.0, 2.0) pusat segmen A: [0.000, 1.000, 0.000]
(6.0, 6.5) di antara segmen: [0.600, 0.000, 0.400]
(9.0, 9.0) tepi segmen longgar: [0.003, 0.000, 0.997]
Selisih maks vs rumus manual: 3.33e-16
pelanggan ambigu (respons maks < 0.80): 2 dari 180
pelanggan tegas (respons maks > 0.95): 170 dari 180
k BIC AIC
1 1746.3 1730.3
2 1570.3 1535.2
3 1552.9 1498.6
4 1568.4 1495.0
5 1592.3 1499.7
6 1614.2 1502.5
k terbaik menurut BIC: 3
k terbaik menurut AIC: 4
Log-kepadatan (score_samples) tiga titik uji:
(2.0, 2.0): -2.325
(6.0, 6.5): -4.817
(9.0, 9.0): -6.407Mari kita bedah hasil eksekusinya:
- Baris 21–27 (atribut parameter): bobot
[0.344, 0.333, 0.323]nyaris merata — masuk akal karena tiap segmen berisi 60 pelanggan. Rata-rata komponen (1,899; 1,973), (7,003; 4,246), dan (5,140; 8,907) berdekatan dengan pusat segmen yang ditanam. Diagonal kovarians memperlihatkan asimetri yang tidak bisa ditangkap k-Means: komponen 1 rapat (diag 0,478; 0,605) sedangkan komponen 2 melebar (diag 2,875; 1,781) — cermin daricluster_std0,8 vs 1,8. - Baris 30–36 (soft assignment): titik (2,0; 2,0) di jantung segmen A mendapat responsibility [0,000; 1,000; 0,000]. Bintang demonstrasi ada di (6,0; 6,5): responsibility [0,600; 0,000; 0,400] — pelanggan itu 60% milik komponen 0 dan 40% milik komponen 2, jenis keputusan yang tidak bisa diberikan label keras k-Means.
- Baris 39–45 (verifikasi rumus):
densmenghitungw_k · N(x | μ_k, Σ_k)per komponen denganscipy.stats.multivariate_normal, lalu dinormalkan per baris. Selisih maksimum terhadappredict_probahanya 3,33e-16 — batas presisi float;predict_probaGMM adalah rumus Bayes yang kita tulis sendiri. - Baris 48–51 (ambigu vs tegas): dari 180 pelanggan, 170 pelanggan memiliki responsibility maksimum di atas 0,95 dan hanya 2 pelanggan berada di zona abu-abu di bawah 0,80. Data kita memang tidak terlalu tumpang tindih; pada data nyata dengan segmen bercampur, baris seperti ini menjadi alat ukur berapa banyak pelanggan yang layak ditinjau manual.
- Baris 56–64 (BIC/AIC): BIC mencapai minimum di k=3 (1552,9) — tepat jumlah segmen yang ditanam — sedangkan AIC memilih k=4 (1495,0). Pembahasannya ada di bagian berikutnya.
- Baris 67–69 (log-kepadatan):
score_samplesmemberi log-kepadatan model pada tiap titik: −2,325 di pusat segmen, −6,407 di tepi. Titik dengan kepadatan sangat rendah adalah kandidat anomali — jembatan menuju Section Anomaly Detection di lanjutan Course ini.
Memilih k dengan BIC dan AIC #
Kedua kriteria menyeimbangkan kecocokan model dengan jumlah parameternya, keduanya dihitung dari log-likelihood maksimum yang sama:
AIC = -2·loglik + 2p BIC = -2·loglik + p·ln(n)dengan p jumlah parameter bebas dan n jumlah data. AIC menghukum tiap parameter dengan konstanta 2; BIC menghukumnya dengan ln(n) — pada n = 180 hukuman itu sekitar 5,2 per parameter, jauh lebih berat. Konsekuensinya terlihat telak pada output kita: k=4 memang menaikkan log-likelihood (AIC turun ke 1495,0), tetapi enam parameter tambahannya membuat BIC naik ke 1568,4. BIC memilih 3 — sesuai kebenaran generator — AIC memilih 4 — model tambahannya membelah segmen longgar menjadi dua. Tidak ada yang “salah” di sini: AIC memang dikenal condong memilih model lebih besar, dan praktikum seperti ini melatih mata kita membaca hasil keduanya secara berdampingan.
GMM menutup satu lembar penting: kini kita sanggup membangun distribusi atas data itu sendiri. Namun di seluruh Course ini keluaran yang paling sering kita konsumsi adalah predict_proba dari classifier — dan angka-angka itu punya masalah tersendiri yang belum pernah kita ukur: apakah 0,8 dari model benar-benar berarti 80%? Chapter penutup section ini, Kalibrasi Probabilitas Model, mengajari cara mengukur dan memperbaiki kesesuaian tersebut.
Referensi Resmi #
- Gaussian Mixture Models — scikit-learn User Guide — penjelasan resmi GMM, algoritme EM, pilihan kovarians, dan pemilihan model.
- sklearn.mixture.GaussianMixture — API Reference
— dokumentasi parameter
covariance_type,n_init, atributweights_/means_/covariances_, dan metodebic/aic. - scipy.stats.multivariate_normal — SciPy Documentation — distribusi normal multivariat yang dipakai pada verifikasi rumus responsibility.