TL;DR
Algoritma k-means clustering ngelompokkan data lewat dua langkah yang diulang: masukkan tiap titik ke centroid terdekat, lalu geser centroid ke rata-rata anggotanya. Prosesnya berhenti waktu nggak ada titik yang pindah kelompok lagi. Jumlah klaster harus kamu tentuin sendiri di awal, biasanya lewat metode elbow atau silhouette score. K-means butuh fitur yang udah diskalakan kalau satuannya beda jauh.
Algoritma k-means clustering ngelompokkan data lewat dua langkah yang diulang terus: masukkan tiap titik ke centroid terdekat, lalu geser centroid ke rata-rata anggotanya. Berhenti waktu nggak ada titik yang pindah lagi.
Kedengeran sederhana, dan memang sederhana. Yang bikin orang bingung biasanya bukan algoritmanya, tapi cara nentuin jumlah klaster dan kapan harus menskalakan data.
Di bawah ini aku hitung tiga iterasi penuh pakai tangan dengan data 7 pelanggan warung, baru setelah itu ulang pakai Python.
K-means clustering adalah metode buat membagi data jadi sejumlah kelompok berdasarkan kemiripan nilainya. Huruf k mewakili jumlah kelompok yang kamu tentuin di awal. Tiap kelompok diwakili satu titik pusat bernama centroid, dan tiap baris data masuk ke centroid yang jaraknya paling dekat.
Metode ini masuk kelompok unsupervised, artinya datanya nggak punya label. Kelompok metode lain yang bisa jadi pembanding aku bahas di metode data mining.
Dua kolom: frekuensi belanja per bulan dan rata-rata nilai belanja dalam ratus ribu rupiah. Satuannya sengaja disamain biar hitungan manualnya bersih.
| Pelanggan | Frekuensi (x) | Belanja rata-rata (y) |
|---|---|---|
| P1 | 1 | 2 |
| P2 | 2 | 2 |
| P3 | 2 | 3 |
| P4 | 8 | 8 |
| P5 | 9 | 9 |
| P6 | 9 | 8 |
| P7 | 5 | 5 |
Nilai y = 2 berarti rata-rata belanja Rp 200.000, y = 9 berarti Rp 900.000.
Jarak yang dipakai Euclidean:
d = akar( (x1 - x2)^2 + (y1 - y2)^2 )
Aku sengaja pilih centroid awal yang jelek, yaitu P1 dan P2 yang letaknya bersebelahan. Tujuannya biar kamu lihat centroid beneran bergerak, bukan langsung benar di iterasi pertama.
C1 = (1, 2)
C2 = (2, 2)
| Titik | Jarak ke C1 | Jarak ke C2 | Masuk |
|---|---|---|---|
| P1 (1,2) | 0,00 | 1,00 | K1 |
| P2 (2,2) | 1,00 | 0,00 | K2 |
| P3 (2,3) | 1,41 | 1,00 | K2 |
| P4 (8,8) | 9,22 | 8,49 | K2 |
| P5 (9,9) | 10,63 | 9,90 | K2 |
| P6 (9,8) | 10,00 | 9,22 | K2 |
| P7 (5,5) | 5,00 | 4,24 | K2 |
Hasilnya timpang: K1 cuma isi 1 titik, K2 isi 6 titik. Sekarang geser centroid ke rata-rata anggota masing-masing.
C1 baru = (1, 2) -> anggotanya cuma P1, jadi nggak pindah
C2 baru = ((2+2+8+9+9+5)/6, (2+3+8+9+8+5)/6)
= (35/6, 35/6)
= (5,833 ; 5,833)
C1 = (1,000 ; 2,000)
C2 = (5,833 ; 5,833)
| Titik | Jarak ke C1 | Jarak ke C2 | Masuk | Status |
|---|---|---|---|---|
| P1 (1,2) | 0,00 | 6,17 | K1 | tetap |
| P2 (2,2) | 1,00 | 5,42 | K1 | pindah |
| P3 (2,3) | 1,41 | 4,77 | K1 | pindah |
| P4 (8,8) | 9,22 | 3,06 | K2 | tetap |
| P5 (9,9) | 10,63 | 4,48 | K2 | tetap |
| P6 (9,8) | 10,00 | 3,84 | K2 | tetap |
| P7 (5,5) | 5,00 | 1,18 | K2 | tetap |
Contoh hitungan buat P3 ke C2:
d = akar( (5,833 - 2)^2 + (5,833 - 3)^2 )
= akar( 3,833^2 + 2,833^2 )
= akar( 14,69 + 8,03 )
= akar( 22,72 ) = 4,77
Dua titik pindah kelompok. Centroid digeser lagi:
C1 baru = ((1+2+2)/3, (2+2+3)/3) = (1,667 ; 2,333)
C2 baru = ((8+9+9+5)/4, (8+9+8+5)/4) = (7,750 ; 7,500)
| Titik | Jarak ke C1 | Jarak ke C2 | Masuk |
|---|---|---|---|
| P1 (1,2) | 0,75 | 8,71 | K1 |
| P2 (2,2) | 0,47 | 7,96 | K1 |
| P3 (2,3) | 0,75 | 7,30 | K1 |
| P4 (8,8) | 8,50 | 0,56 | K2 |
| P5 (9,9) | 9,91 | 1,95 | K2 |
| P6 (9,8) | 9,27 | 1,35 | K2 |
| P7 (5,5) | 4,27 | 3,72 | K2 |
Nggak ada titik yang pindah, jadi prosesnya berhenti. Hasil akhirnya dua kelompok:
Perhatiin P7. Jaraknya ke dua centroid cuma beda 0,55, jadi dia titik paling rapuh. Kalau centroid awalnya beda sedikit, P7 bisa jatuh ke K1. Titik semacam ini yang perlu kamu cek ulang sebelum dipakai buat keputusan promo.
Nilai k harus kamu tentuin sebelum algoritmanya jalan. Dua cara yang paling sering dipakai:
Pakai dua-duanya. Elbow sering ngasih siku yang samar, dan silhouette bantu mutusin di antara dua kandidat yang mirip.
Satu pertimbangan yang jarang disebut: jumlah klaster juga harus bisa ditindaklanjuti. Kalau tim marketing cuma sanggup bikin 3 jenis promo, k = 8 nggak ada gunanya walau skornya paling tinggi.
import pandas as pd
from sklearn.cluster import KMeans
from sklearn.preprocessing import StandardScaler
from sklearn.metrics import silhouette_score
data = pd.DataFrame({
"pelanggan": ["P1","P2","P3","P4","P5","P6","P7"],
"frekuensi": [1, 2, 2, 8, 9, 9, 5],
"belanja": [2, 2, 3, 8, 9, 8, 5],
})
X = data[["frekuensi", "belanja"]]
model = KMeans(n_clusters=2, random_state=42)
data["klaster"] = model.fit_predict(X)
print(data)
print("Centroid:", model.cluster_centers_)
print("Inertia:", round(model.inertia_, 3))
print("Silhouette:", round(silhouette_score(X, data["klaster"]), 3))
Centroid yang keluar bakal sama dengan hitungan tangan tadi, yaitu sekitar (1,667 ; 2,333) dan (7,750 ; 7,500).
Buat nyari nilai k lewat elbow:
inertia = []
for k in range(1, 7):
km = KMeans(n_clusters=k, random_state=42).fit(X)
inertia.append(km.inertia_)
print(inertia)
Kalau kolommu punya satuan yang beda jauh, misalnya frekuensi 1 sampai 30 dan total belanja jutaan rupiah, skalakan dulu:
X_scaled = StandardScaler().fit_transform(X)
model = KMeans(n_clusters=3, random_state=42).fit(X_scaled)
Tanpa penskalaan, kolom rupiah bakal nguasain perhitungan jarak dan kolom frekuensi jadi nggak ngaruh sama sekali. Rincian parameter dan perilaku k-means++ ada di dokumentasi scikit-learn.
Dataset latihan ngulikdata toko_berkah punya 612 pelanggan dengan riwayat 6 bulan. Fitur yang dipakai tiga: jarak hari sejak transaksi terakhir, jumlah transaksi, dan total belanja.
Setelah penskalaan dan uji k dari 2 sampai 8, silhouette tertinggi jatuh di k = 3.
| Klaster | Jumlah pelanggan | Ciri | Tindakan |
|---|---|---|---|
| Rutin nilai kecil | 341 | Belanja 8 kali, rata-rata Rp 21.000 | Paket bundling harian |
| Pemborong bulanan | 127 | Belanja 2 kali, rata-rata Rp 214.000 | Pengingat tanggal gajian |
| Sudah lama hilang | 144 | Terakhir belanja 71 hari lalu | Pesan WhatsApp berisi voucher |
Yang menarik, kelompok pemborong bulanan cuma 21% dari jumlah pelanggan tapi nyumbang 46% omzet. Angka itu yang akhirnya ngubah prioritas promo pemilik toko.
Kalau kamu mau ngerti istilahnya lebih dulu, cek glosarium segmentasi.
Pakai metode elbow dan silhouette score bareng. Elbow nyari titik tempat penurunan inertia mulai melandai, silhouette ngukur kerapatan klaster dibanding jarak ke tetangganya.
Karena centroid awal dipilih acak. Isi parameter random_state dengan angka tetap kalau kamu butuh hasil yang sama persis tiap kali.
Perlu, kalau satuan kolommu beda jauh. K-means ngukur jarak, jadi kolom rupiah yang nilainya jutaan bakal menenggelamkan kolom frekuensi yang cuma satu digit.
K-means naruh pusat klaster di titik rata-rata, k-medoids naruh pusatnya di salah satu titik data asli. K-medoids lebih tahan sama nilai ekstrem.
Nggak langsung, soalnya rata-rata dari kategori nggak punya arti. Pakai k-prototypes, atau klaster pakai kolom angka saja lalu lihat sebaran kategorinya per klaster.
Dua langkah yang diulang, itu seluruh isi k-means: tempel titik ke centroid terdekat, geser centroid ke rata-rata. Sisanya cuma soal nyiapin data dan milih k.
Coba ulang hitungan tiga iterasi di atas pakai centroid awal yang beda, misalnya P1 dan P7. Kamu bakal lihat sendiri kenapa pilihan awal berpengaruh.
Lanjut baca: Algoritma C4.5 dan Decision Tree kalau datamu udah punya label dan kamu butuh model yang bisa dijelasin per aturan.
Mau praktek langsung? Mulai latihan SQL gratis
Latihan interaktif, langsung di browser.
Kolom datetime nyimpen tanggal, jam, hari, semuanya nempel jadi satu. Accessor .dt di pandas ngeluarin tiap bagian jadi kolom sendiri buat dianalisa.
Nama toko ketik campur huruf besar-kecil, spasi nyasar di ujung, atau kode produk nempel jadi satu. Accessor .str di pandas ngerapiin semua itu tanpa loop.
Model machine learning cuma ngerti angka, bukan teks kayak merah atau biru. get_dummies ngubah kolom kategori jadi kolom 0/1 dalam satu baris kode.