KMeans mengelompokkan sampel di sekitar k buah pusat yang dicarinya sendiri, sehingga menjadi algoritma clustering yang sering digunakan sebagai titik tolak. Topik ini menjelaskan putaran algoritmanya, peran n_init dan random_state, makna inertia_ sebagai ukuran kompaknya klaster, cara memilih k melalui elbow dan silhouette, serta kelemahan yang melekat pada asumsinya. Setiap langkah diilustrasikan dengan kode yang dapat dijalankan ulang.
Algoritma dan inisialisasi#
KMeans bekerja melalui perulangan sederhana atas k buah pusat klaster. Langkahnya berurutan sebagai berikut.
- Pilih k pusat awal dari sampel data.
- Tetapkan setiap sampel ke pusat terdekatnya, sehingga terbentuk k klaster sementara.
- Geser setiap pusat ke rata-rata anggota klasternya.
- Ulangi langkah dua dan tiga sampai penugasan tidak berubah lagi.
Hasil akhirnya bergantung pada pusat awal yang dipilih pada langkah pertama. Pusat awal yang buruk dapat membuat algoritma terjebak pada solusi yang jauh dari optimal, sehingga scikit-learn menjalankan proses itu beberapa kali dengan inisialisasi berbeda dan menyimpan hasil dengan inertia terkecil. Inisialisasi bawaannya adalah k-means++, yaitu teknik pemilihan pusat awal yang menjauhkan satu pusat dari pusat lainnya. Parameter n_init mengatur banyaknya percobaan, dengan nilai default "auto" sejak versi 1.4, yang berarti satu percobaan untuk k-means++ dan sepuluh percobaan untuk init="random". Menetapkan random_state membuat urutan percobaan itu sama di setiap penjalanan, sehingga hasilnya dapat direproduksi.
Kualitas solusi dilaporkan melalui atribut inertia_, yaitu jumlah kuadrat jarak setiap sampel ke pusat klasternya:
dengan adalah pusat klaster tempat sampel ditugaskan. Inertia kecil berarti anggota tiap klaster rapat terhadap pusatnya, sehingga nilai ini digunakan scikit-learn untuk memilih hasil terbaik antarpercobaan.
Kode berikut menjalankan KMeans pada 600 sampel tiga klaster buatan make_blobs, lalu mencetak inertia, ukuran tiap klaster, dan letak pusatnya.
import numpy as np
from sklearn.datasets import make_blobs
from sklearn.cluster import KMeans
X, _ = make_blobs(n_samples=600, centers=3, cluster_std=1.5, random_state=42)
kmeans = KMeans(n_clusters=3, random_state=42, n_init=10).fit(X)
print("Inertia :", round(kmeans.inertia_, 1))
print("Ukuran tiap klaster:", np.bincount(kmeans.labels_))
print("Pusat klaster :")
for c in kmeans.cluster_centers_:
print(" ", np.round(c, 2))Inertia : 2612.0
Ukuran tiap klaster: [200 200 200]
Pusat klaster :
[-2.52 9.06]
[-6.58 -6.78]
[4.57 1.94]Tiga klaster hasil KMeans berukuran sama persis dengan klaster aslinya, dan tiga pusatnya tercetak pada koordinat rata-rata masing-masing kelompok. Nilai inertia 2612.0 hanya bermakna sebagai bilangan pembanding, karena satuannya bergantung pada skala fitur dan jumlah sampel.
Memilih k dengan elbow dan silhouette#
Nilai k jarang diketahui di depan, sehingga k harus dipilih dari data. Cara pertama adalah membandingkan inertia untuk rentang k, karena inertia selalu turun ketika k naik, dan titik ketika penurunan itu mulai mendatar disebut elbow, yakni siku pada grafik penurunan inertia. Cara kedua adalah menghitung silhouette, yakni skor antara -1 dan 1 yang menilai seberapa pas sebuah sampel berada di klasternya dibandingkan dengan klaster terdekat lainnya, lalu mengambil k dengan rata-rata skor tertinggi. Keduanya termasuk kriteria internal, yaitu kompaknya klaster dan keterpisahannya, karena keduanya dihitung tanpa label apa pun.
Kode berikut menyapu k dari 1 sampai 8 pada data empat klaster dan mencetak kedua ukurannya. Silhouette membutuhkan setidaknya dua klaster, sehingga baris k sama dengan 1 tidak memilikinya.
import numpy as np
from sklearn.datasets import make_blobs
from sklearn.cluster import KMeans
from sklearn.metrics import silhouette_score
X, _ = make_blobs(n_samples=600, centers=4, cluster_std=1.0, random_state=42)
print("k inertia silhouette")
for k in range(1, 9):
km = KMeans(n_clusters=k, random_state=42, n_init=10).fit(X)
if k == 1:
print(f"{k} {km.inertia_:8.1f} tidak terdefinisi")
else:
sil = silhouette_score(X, km.labels_)
print(f"{k} {km.inertia_:8.1f} {sil:.3f}")k inertia silhouette
1 39698.3 tidak terdefinisi
2 18637.9 0.591
3 4178.9 0.757
4 1160.3 0.788
5 1045.6 0.690
6 939.2 0.560
7 844.0 0.432
8 749.7 0.333Inertia turun tajam dari 39698.3 ke 1160.3 pada k 1 sampai 4, lalu hanya turun tipis sesudahnya, sehingga elbow-nya berada di k sama dengan 4. Silhouette mengikuti pola yang sama dan mencapai puncaknya di 0.788 pada k sama dengan 4. Kedua ukuran menunjuk nilai yang sama pada data ini, tetapi pada data nyata keduanya boleh berbeda, sehingga keputusan akhir tetap mempertimbangkan makna bisnis dari tiap kandidat k.
Kelemahan KMeans#
KMeans mengukur jarak Euclidean ke pusat, sehingga ia mengasumsikan klaster berbentuk bundar dan berukuran mirip. Asumsi itu dapat diuji dengan membuat tiga klaster yang sebarannya tidak sama, yaitu dua klaster sempit dan satu klaster lebar, lalu melihat hasil k=3 yang semestinya benar.
import numpy as np
from sklearn.datasets import make_blobs
from sklearn.cluster import KMeans
pusat = [(-8.0, 0.0), (0.0, 0.0), (6.0, 0.0)]
X, y = make_blobs(
n_samples=600, centers=pusat, cluster_std=[0.6, 0.6, 3.0], random_state=42
)
kmeans = KMeans(n_clusters=3, random_state=42, n_init=10).fit(X)
print("Ukuran sebenarnya :", np.bincount(y))
print("Ukuran hasil KMeans:", np.bincount(kmeans.labels_))
print("Pusat klaster hasil:")
for c in kmeans.cluster_centers_:
print(" ", np.round(c, 2))Ukuran sebenarnya : [200 200 200]
Ukuran hasil KMeans: [173 200 227]
Pusat klaster hasil:
[7.28 0.29]
[-8. 0.02]
[ 0.23 -0.06]Klaster lebar terbelah menjadi dua bagian, yaitu 173 anggota pada pusat 7.28 dan 27 anggota pada pusat 0.23, sedangkan dua klaster sempit menyatu pada pusat yang sama di 0.23. Pemecahan ini terjadi karena memotong klaster lebar memang menurunkan inertia, sehingga KMeans memilihnya meskipun kelompok sebenarnya ada tiga. Ukuran hasil 173, 200, dan 227 memperlihatkan kekeliruan itu langsung pada keluaran.
Kelemahan kedua bersifat umum untuk semua model berbasis jarak, yaitu sensitivitas terhadap skala fitur. Fitur dengan rentang terbesar mendominasi perhitungan jarak, sehingga penugasan klaster dapat ditentukan oleh satu fitur saja apabila skala fitur tidak disetarakan terlebih dahulu dengan StandardScaler.
Kesalahan umum#
Kesalahan pertama adalah memilih k hanya dengan melihat angka inertia terendah. Inertia terus turun sampai k sebanyak jumlah sampel, sehingga kriteria yang benar adalah lokasi elbow atau puncak silhouette, bukan nilai minimumnya.
Kesalahan kedua adalah membiarkan default berjalan tanpa pengaturan pada data dimensi tinggi. Inisialisasi k-means++ dengan n_init="auto" hanya menjalankan satu percobaan, sehingga hasil pada data padat dan berdimensi tinggi dapat beruntung atau tidak. Menetapkan n_init=10 bersama random_state memberi hasil yang lebih stabil dan tetap murah untuk dataset berukuran sedang.
Kesalahan ketiga adalah menerapkan KMeans pada bentuk klaster yang tidak bundar, misalnya dua lengkungan yang saling menyusup. Algoritma tetap menghasilkan k kelompok, tetapi batasnya memotong bentuk alami data, dan kekeliruan ini tidak terlihat dari inertia yang kecil.
Ringkasan#
- KMeans memutar empat langkah, yaitu pilih pusat awal, tetapkan anggota, geser pusat, dan ulangi sampai stabil, dengan hasil terbaik diambil dari beberapa percobaan berdasarkan inertia.
inertia_adalah jumlah kuadrat jarak sampel ke pusat klasternya dan menjadi ukuran kompaknya solusi.- k dipilih dari lokasi elbow pada penurunan inertia dan dari puncak silhouette, dan keduanya menunjuk k sama dengan 4 pada demonstrasi.
- KMeans mengasumsikan klaster bundar seukuran dan peka terhadap skala fitur, sehingga scaling dan pemeriksaan bentuk klaster menjadi bagian dari pekerjaannya.
Referensi#
- sklearn.cluster.KMeans — scikit-learn documentation
— Rujukan parameter
n_init,random_state, dan atributinertia_. - sklearn.metrics.silhouette_score — scikit-learn documentation — Definisi silhouette yang digunakan pada pemilihan k.
- 2.3. Clustering — scikit-learn documentation — Bagian KMeans pada user guide, termasuk keterbatasannya.
- sklearn.datasets.make_blobs — scikit-learn documentation
— Generator data klaster sintetis dengan
cluster_stdper klaster. - sklearn.preprocessing.StandardScaler — scikit-learn documentation — Penyetaraan skala fitur sebelum perhitungan jarak.