- Pengenalan Clustering
- Algoritma K-Means Langkah demi Langkah
- Implementasi Dasar K-Means dengan Scikit-learn
- Elbow Method โ Menentukan Jumlah Cluster Optimal
- Silhouette Score โ Evaluasi Kualitas Cluster
- Studi Kasus: Segmentasi Pelanggan
- Kelebihan, Kekurangan & Tips Praktis
- K-Means vs Algoritma Clustering Lainnya
- Quiz Pemahaman
1. Pengenalan Clustering
Clustering adalah teknik unsupervised learning yang bertujuan mengelompokkan data ke dalam beberapa kelompok (cluster) berdasarkan kemiripan fitur. Berbeda dengan supervised learning, clustering tidak memiliki label โ model harus menemukan struktur tersembunyi dalam data secara mandiri.
K-Means Clustering adalah salah satu algoritma clustering yang paling populer dan banyak digunakan. Algoritma ini mempartisi data menjadi K kelompok di mana setiap titik data termasuk ke cluster dengan centroid (pusat cluster) terdekat.
Kapan Menggunakan Clustering?
| Aplikasi | Deskripsi | Contoh Nyata |
|---|---|---|
| Segmentasi Pelanggan | Mengelompokkan pelanggan berdasarkan perilaku belanja | Pelanggan premium, reguler, hemat |
| Document Clustering | Mengelompokkan dokumen berdasarkan topik | Grup artikel berita per kategori |
| Image Segmentation | Memisahkan objek dalam gambar | Segmentasi citra medis |
| Deteksi Anomali | Menemukan data yang tidak lazim | Deteksi transaksi penipuan |
| Rekomendasi | Mengelompokkan pengguna serupa | Sistem rekomendasi film |
| Bioinformatika | Mengelompokkan gen dengan ekspresi serupa | Analisis ekspresi gen |
Visualisasi Konsep Clustering
Sebelum Clustering Sesudah Clustering (K=3)
โโโโโโโโโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโโโโโโโโ
โ ยท ยท ยท ยท โ โ โโโโ โณโณโณโณ โ
โ ยท ยท ยท ยท ยท โ โ โโโโโ โณโณโณโณโณ โ
โ ยท ยท ยท ยท โ โโโบ โ โโโโ โณโณโณโณ โ
โ ยท ยท ยท ยท ยท โ โ โกโกโกโก โณโณ โ
โ ยท ยท ยท ยท ยท โ โ โกโกโกโกโก โ
โ ยท ยท ยท ยท โ โ โกโกโกโก โ
โโโโโโโโโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโโโโโโโโ
Data tersebar tanpa pola 3 kelompok terbentuk:
yang jelas โ Cluster 1, โณ Cluster 2, โก Cluster 3
โ
= Centroid masing-masing cluster
2. Algoritma K-Means Langkah demi Langkah
Algoritma K-Means bekerja secara iteratif untuk mempartisi dataset menjadi K cluster non-overlapping. Setiap titik data dimiliki oleh tepat satu cluster. Berikut adalah langkah-langkah detailnya:
Langkah-Langkah Algoritma K-Means
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ ALGORITMA K-MEANS โ โ โ โ INPUT: Dataset X (n titik), Jumlah cluster K โ โ โ โ 1. INISIALISASI: Pilih K titik awal sebagai centroid โ โ Cโ, Cโ, ..., Cโ (random atau K-Means++) โ โ โ โ 2. ASSIGNMENT STEP: โ โ Untuk setiap titik data xแตข: โ โ Hitung jarak ke semua centroid โ โ Assign xแตข ke cluster dengan centroid terdekat โ โ cluster(xแตข) = argmin โxแตข - Cโโยฒ โ โ โ โ 3. UPDATE STEP: โ โ Untuk setiap cluster k: โ โ Hitung ulang centroid sebagai rata-rata semua titik โ โ Cโ = (1/|Sโ|) ฮฃ xแตข untuk semua xแตข โ cluster k โ โ โ โ 4. KONVERGENSI: โ โ Ulangi langkah 2-3 sampai: โ โ โข Centroid tidak berubah (atau perubahan < threshold) โ โ โข Atau mencapai maksimum iterasi โ โ โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Visualisasi Per Iterasi
Iterasi 0 (Inisialisasi) Iterasi 1 (Assign+Update) โโโโโโโโโโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโโโโโโโโโ โ ยท ยท โ A ยท โ โ โโ โ โ A โณโณโณ โ โ ยท ยท ยท ยท ยท โ โ โโโโ โณโณโณโณโณ โ โ ยท ยท ยท โ B ยท โ โ โโโ โณโ A โณโณ โ โ ยท ยท ยท ยท ยท ยท โ โ โกโกโกโกโก ยท โณ โ โ โ C ยท ยท ยท ยท ยท โ โ โกโกโ Bโกโก โ โ ยท ยท ยท ยท โ โ โกโกโก โกโกโกโ C โ โโโโโโโโโโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโโโโโโโโโ Iterasi 2 (Converged!) Centroid bergerak ke pusat โโโโโโโโโโโโโโโโโโโโโโโโ massa masing-masing cluster โ โโโโ โณโณโณโณ โ pada setiap iterasi. โ โโโโโ โณโณโณโณโณ โ โ โโโ โณโ Aโณโณ โ Jarak yang digunakan: โ โกโกโกโกโก โณ โ Euclidean: โ(ฮฃ(xแตข-yแตข)ยฒ) โ โกโกโ Bโกโก โ โ โกโกโก โกโกโ C โ โโโโโโโโโโโโโโโโโโโโโโโโ
Matematika di Balik K-Means
K-Means meminimalkan Within-Cluster Sum of Squares (WCSS), yaitu total jarak kuadrat dari setiap titik ke centroid cluster-nya:
WCSS = ฮฃโ ฮฃโแตขโCโ โxแตข - ฮผโโยฒ
Di mana:
- K = jumlah cluster
- Cโ = himpunan titik data dalam cluster ke-k
- ฮผโ = centroid (rata-rata) dari cluster ke-k
- โxแตข - ฮผโโยฒ = jarak Euclidean kuadrat dari titik xแตข ke centroid ฮผโ
3. Implementasi Dasar K-Means dengan Scikit-learn
Mari kita implementasikan K-Means dari nol dan menggunakan scikit-learn. Kita akan menggunakan dataset buatan yang mudah divisualisasikan.
K-Means dengan Dataset Buatan
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from sklearn.cluster import KMeans
from sklearn.datasets import make_blobs
from sklearn.preprocessing import StandardScaler
# === GENERATE DATASET ===
# Membuat dataset sintetis dengan 3 cluster
np.random.seed(42)
X, y_true = make_blobs(
n_samples=300, # 300 titik data
centers=4, # 4 pusat cluster asli
cluster_std=0.60, # Standar deviasi tiap cluster
random_state=42
)
print(f"Dataset shape: {X.shape}")
print(f"Fitur: 2 (x1, x2)")
print(f"Cluster asli: {len(np.unique(y_true))}")
# Visualisasi data asli (tanpa label)
plt.figure(figsize=(10, 5))
plt.subplot(1, 2, 1)
plt.scatter(X[:, 0], X[:, 1], s=30, alpha=0.7, c='gray')
plt.title('Data Asli (Tanpa Label)')
plt.xlabel('Fitur 1')
plt.ylabel('Fitur 2')
plt.grid(True, alpha=0.3)
# === TERAPKAN K-MEANS ===
kmeans = KMeans(
n_clusters=4, # Jumlah cluster
init='k-means++', # Inisialisasi cerdas
n_init=10, # Jalankan 10x, pilih terbaik
max_iter=300, # Maks iterasi
random_state=42
)
# Fit model
kmeans.fit(X)
# Hasil clustering
labels = kmeans.labels_ # Label cluster tiap titik
centroids = kmeans.cluster_centers_ # Koordinat centroid
inertia = kmeans.inertia_ # WCSS value
print(f"\nHasil Clustering:")
print(f" Jumlah cluster: {kmeans.n_clusters}")
print(f" Inertia (WCSS): {inertia:.2f}")
print(f" Iterasi: {kmeans.n_iter_}")
print(f"\nCentroid:")
for i, c in enumerate(centroids):
print(f" Cluster {i}: ({c[0]:.2f}, {c[1]:.2f})")
# Distribusi cluster
unique, counts = np.unique(labels, return_counts=True)
print(f"\nDistribusi cluster:")
for u, c in zip(unique, counts):
print(f" Cluster {u}: {c} titik ({c/len(X)*100:.1f}%)")
# Visualisasi hasil
plt.subplot(1, 2, 2)
colors = ['#FF6B6B', '#4ECDC4', '#45B7D1', '#96CEB4']
for i in range(4):
mask = labels == i
plt.scatter(X[mask, 0], X[mask, 1], s=30, alpha=0.7,
c=colors[i], label=f'Cluster {i}')
plt.scatter(centroids[:, 0], centroids[:, 1], s=200, c='black',
marker='โ
', edgecolors='white', linewidth=2,
label='Centroid', zorder=5)
plt.title(f'K-Means Clustering (K=4, Inertia={inertia:.0f})')
plt.xlabel('Fitur 1')
plt.ylabel('Fitur 2')
plt.legend()
plt.grid(True, alpha=0.3)
plt.tight_layout()
plt.show()
Prediksi Cluster untuk Data Baru
# Prediksi cluster untuk data baru
data_baru = np.array([
[0, 4], # Titik baru 1
[-3, -2], # Titik baru 2
[5, 2], # Titik baru 3
])
cluster_baru = kmeans.predict(data_baru)
jarak_centroid = kmeans.transform(data_baru) # Jarak ke semua centroid
print("Prediksi cluster data baru:")
for i, (point, cluster) in enumerate(zip(data_baru, cluster_baru)):
jarak = jarak_centroid[i]
print(f" Titik {point} โ Cluster {cluster}")
print(f" Jarak ke centroid: {[f'{d:.2f}' for d in jarak]}")
4. Elbow Method โ Menentukan Jumlah Cluster Optimal
Salah satu tantangan terbesar dalam K-Means adalah menentukan jumlah cluster (K) yang optimal. Terlalu sedikit cluster = underfitting, terlalu banyak = overfitting. Elbow Method adalah teknik populer untuk memilih K terbaik.
Cara Kerja Elbow Method
- Jalankan K-Means untuk berbagai nilai K (misal K=1 sampai K=10)
- Catat nilai Inertia (WCSS) untuk setiap K
- Plot K vs Inertia
- Cari "siku" (elbow) โ titik di mana penurunan inertia mulai melambat secara signifikan
- K pada titik siku adalah jumlah cluster optimal
Inertia (WCSS)
โ
โโ
โ โฒ
โ โฒ
โ โฒ
โ โฒ___ โ Titik "siku" (elbow)
โ โฒ____ Di sini K=3 atau K=4
โ โฒ___
โ โฒ______
โ โฒ_______________
โ
โโโโฌโโโฌโโโฌโโโฌโโโฌโโโฌโโโฌโโโฌโโโฌโโโฌโโโฌโโโโ K
1 2 3 4 5 6 7 8 9 10 11
Penjelasan:
โข K=1โ2โ3: Inertia turun DRAMATIS (cluster baru sangat membantu)
โข K=3โ4โ5: Inertia masih turun tapi MELAMBAT
โข K>5: Inertia hampir DATAR (tidak ada manfaat tambahan)
โข K optimal = titik di mana kurva mulai "melengkung"
Implementasi Elbow Method
import numpy as np
import matplotlib.pyplot as plt
from sklearn.cluster import KMeans
from sklearn.datasets import make_blobs
# Generate dataset
X, y_true = make_blobs(n_samples=300, centers=4, cluster_std=0.60, random_state=42)
# === ELBOW METHOD ===
K_range = range(1, 11)
inertias = []
for k in K_range:
kmeans = KMeans(n_clusters=k, init='k-means++', n_init=10, random_state=42)
kmeans.fit(X)
inertias.append(kmeans.inertia_)
print(f"K={k:2d} โ Inertia: {kmeans.inertia_:.2f}")
# Hitung penurunan persentase
print("\nPenurunan Inertia:")
for i in range(1, len(inertias)):
drop = (inertias[i-1] - inertias[i]) / inertias[i-1] * 100
print(f" K={i}โ{i+1}: {drop:.1f}% penurunan")
# Plot Elbow
plt.figure(figsize=(10, 6))
plt.plot(K_range, inertias, 'bo-', linewidth=2, markersize=8)
plt.fill_between(K_range, inertias, alpha=0.1, color='blue')
# Tandai elbow point
elbow_k = 4
elbow_idx = elbow_k - 1
plt.annotate(f'Elbow Point\nK={elbow_k}',
xy=(elbow_k, inertias[elbow_idx]),
xytext=(elbow_k + 1.5, inertias[elbow_idx] + 50),
fontsize=12, fontweight='bold', color='red',
arrowprops=dict(arrowstyle='->', color='red', lw=2))
plt.xlabel('Jumlah Cluster (K)', fontsize=12)
plt.ylabel('Inertia (WCSS)', fontsize=12)
plt.title('Elbow Method โ Menentukan K Optimal', fontsize=14)
plt.xticks(K_range)
plt.grid(True, alpha=0.3)
plt.tight_layout()
plt.show()
print(f"\nโ K optimal berdasarkan Elbow Method: {elbow_k}")
Elbow Method Automatis
# pip install kneed
from kneed import KneeLocator
# Deteksi elbow secara otomatis
kneedle = KneeLocator(
list(K_range),
inertias,
curve='convex', # Bentuk kurva (convex = cembung)
direction='decreasing' # Arah penurunan
)
optimal_k = kneedle.elbow
print(f"K optimal (otomatis): {optimal_k}")
print(f"Inertia pada K optimal: {inertias[optimal_k - 1]:.2f}")
# Plot dengan elbow yang ditandai otomatis
plt.figure(figsize=(10, 6))
plt.plot(K_range, inertias, 'bo-', linewidth=2, markersize=8)
kneedle.plot_knee() # Plot dari kneed library
plt.xlabel('Jumlah Cluster (K)')
plt.ylabel('Inertia (WCSS)')
plt.title(f'Elbow Method โ K Optimal = {optimal_k}')
plt.grid(True, alpha=0.3)
plt.show()
5. Silhouette Score โ Evaluasi Kualitas Cluster
Elbow Method kadang ambigu โ siku tidak selalu jelas. Silhouette Score adalah metrik alternatif yang mengukur seberapa baik setiap titik data "cocok" dengan cluster-nya dibandingkan cluster lain.
Rumus Silhouette Score
s(i) = (b(i) - a(i)) / max(a(i), b(i))
- a(i) = rata-rata jarak titik i ke semua titik lain dalam cluster yang sama (intra-cluster)
- b(i) = rata-rata jarak titik i ke semua titik dalam cluster terdekat lain (nearest-cluster)
- s(i) bernilai antara -1 dan +1
Silhouette Score Interpretasi:
+1 โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ Sempurna!
โ โ Titik sangat cocok
โ โ di cluster-nya
0 โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ Netral
โ โ Titik di batas 2 cluster
โ โ
-1 โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ Salah cluster!
โ โ Titik lebih dekat
โ โ ke cluster lain
Panduan Interpretasi:
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ 0.71 - 1.00 โ Struktur kuat, cluster bagus โ
โ 0.51 - 0.70 โ Struktur wajar โ
โ 0.26 - 0.50 โ Struktur lemah โ
โ < 0.25 โ Tidak ada struktur cluster โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Implementasi Silhouette Score
import numpy as np
import matplotlib.pyplot as plt
from sklearn.cluster import KMeans
from sklearn.datasets import make_blobs
from sklearn.metrics import silhouette_score, silhouette_samples
# Generate dataset
X, y_true = make_blobs(n_samples=300, centers=4, cluster_std=0.60, random_state=42)
# === SILHOUETTE SCORE UNTUK BERBAGAI K ===
K_range = range(2, 11)
sil_scores = []
for k in K_range:
kmeans = KMeans(n_clusters=k, init='k-means++', n_init=10, random_state=42)
labels = kmeans.fit_predict(X)
score = silhouette_score(X, labels)
sil_scores.append(score)
print(f"K={k:2d} โ Silhouette Score: {score:.4f}")
# Plot Silhouette Score vs K
plt.figure(figsize=(10, 6))
plt.plot(K_range, sil_scores, 'go-', linewidth=2, markersize=8)
plt.fill_between(K_range, sil_scores, alpha=0.1, color='green')
best_k = K_range[np.argmax(sil_scores)]
best_score = max(sil_scores)
plt.annotate(f'K Terbaik = {best_k}\nScore = {best_score:.3f}',
xy=(best_k, best_score),
xytext=(best_k + 1, best_score - 0.03),
fontsize=12, fontweight='bold', color='red',
arrowprops=dict(arrowstyle='->', color='red', lw=2))
plt.xlabel('Jumlah Cluster (K)', fontsize=12)
plt.ylabel('Silhouette Score', fontsize=12)
plt.title('Silhouette Score โ Menentukan K Optimal', fontsize=14)
plt.xticks(K_range)
plt.grid(True, alpha=0.3)
plt.tight_layout()
plt.show()
print(f"\nโ K optimal berdasarkan Silhouette: {best_k} (score: {best_score:.4f})")
Silhouette Plot per Cluster
import numpy as np
import matplotlib.pyplot as plt
from sklearn.cluster import KMeans
from sklearn.metrics import silhouette_samples, silhouette_score
# Fungsi untuk membuat silhouette plot
def plot_silhouette(X, n_clusters, ax):
kmeans = KMeans(n_clusters=n_clusters, init='k-means++',
n_init=10, random_state=42)
cluster_labels = kmeans.fit_predict(X)
sil_avg = silhouette_score(X, cluster_labels)
sample_sil_values = silhouette_samples(X, cluster_labels)
y_lower = 10
colors = plt.cm.Set2(np.linspace(0, 1, n_clusters))
for i in range(n_clusters):
ith_sil = sample_sil_values[cluster_labels == i]
ith_sil.sort()
size_cluster = ith_sil.shape[0]
y_upper = y_lower + size_cluster
ax.fill_betweenx(np.arange(y_lower, y_upper),
0, ith_sil,
facecolor=colors[i], edgecolor=colors[i],
alpha=0.7)
ax.text(-0.05, y_lower + 0.5 * size_cluster, str(i),
fontweight='bold', fontsize=11)
y_lower = y_upper + 10
ax.axvline(x=sil_avg, color='red', linestyle='--', linewidth=2,
label=f'Rata-rata = {sil_avg:.3f}')
ax.set_xlabel('Silhouette Coefficient')
ax.set_ylabel('Cluster')
ax.set_title(f'K = {n_clusters} (Avg Silhouette: {sil_avg:.3f})')
ax.legend()
# Plot untuk beberapa nilai K
fig, axes = plt.subplots(2, 2, figsize=(14, 10))
axes = axes.flatten()
for idx, k in enumerate([2, 3, 4, 5]):
plot_silhouette(X, k, axes[idx])
plt.suptitle('Silhouette Plot untuk Berbagai Nilai K', fontsize=14, y=1.02)
plt.tight_layout()
plt.show()
6. Studi Kasus: Segmentasi Pelanggan
Sekarang kita terapkan K-Means pada kasus nyata: segmentasi pelanggan berdasarkan perilaku belanja. Dataset yang kita gunakan adalah Mall Customer Segmentation โ dataset populer yang berisi data pelanggan pusat perbelanjaan.
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from sklearn.cluster import KMeans
from sklearn.preprocessing import StandardScaler
# === BUAT DATASET PELANGGAN ===
np.random.seed(42)
n = 200
data_pelanggan = pd.DataFrame({
'customer_id': range(1, n + 1),
'annual_income': np.concatenate([
np.random.normal(25, 5, 50), # Income rendah
np.random.normal(55, 8, 60), # Income menengah
np.random.normal(85, 10, 50), # Income tinggi
np.random.normal(45, 6, 40), # Income menengah-rendah
]).round(1),
'spending_score': np.concatenate([
np.random.normal(20, 8, 50), # Spending rendah
np.random.normal(50, 10, 60), # Spending menengah
np.random.normal(75, 8, 50), # Spending tinggi
np.random.normal(35, 7, 40), # Spending rendah-menengah
]).clip(1, 100).round(1),
'age': np.random.randint(18, 65, n),
})
print("Dataset Pelanggan:")
print(data_pelanggan.describe())
print(f"\nSample data:")
print(data_pelanggan.head(10))
# === PREPROCESSING ===
# Pilih fitur untuk clustering
fitur = ['annual_income', 'spending_score']
X_pelanggan = data_pelanggan[fitur].values
# Normalisasi (PENTING untuk K-Means!)
scaler = StandardScaler()
X_scaled = scaler.fit_transform(X_pelanggan)
print(f"\nData sebelum scaling:")
print(f" Mean: {X_pelanggan.mean(axis=0)}")
print(f" Std: {X_pelanggan.std(axis=0)}")
print(f"\nData setelah scaling:")
print(f" Mean: {X_scaled.mean(axis=0).round(4)}")
print(f" Std: {X_scaled.std(axis=0).round(4)}")
# === ELBOW METHOD ===
K_range = range(1, 11)
inertias = []
sil_scores = []
for k in K_range:
km = KMeans(n_clusters=k, init='k-means++', n_init=10, random_state=42)
km.fit(X_scaled)
inertias.append(km.inertia_)
if k >= 2:
from sklearn.metrics import silhouette_score
sil = silhouette_score(X_scaled, km.labels_)
sil_scores.append(sil)
print(f"K={k}: Inertia={km.inertia_:.1f}, Silhouette={sil:.3f}")
else:
print(f"K={k}: Inertia={km.inertia_:.1f}")
# Plot Elbow & Silhouette berdampingan
fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(14, 5))
ax1.plot(K_range, inertias, 'bo-', linewidth=2)
ax1.set_xlabel('K')
ax1.set_ylabel('Inertia')
ax1.set_title('Elbow Method')
ax1.grid(True, alpha=0.3)
ax2.plot(range(2, 11), sil_scores, 'go-', linewidth=2)
ax2.set_xlabel('K')
ax2.set_ylabel('Silhouette Score')
ax2.set_title('Silhouette Analysis')
ax2.grid(True, alpha=0.3)
plt.tight_layout()
plt.show()
# === CLUSTERING DENGAN K OPTIMAL ===
K_OPTIMAL = 5 # Berdasarkan elbow + silhouette
kmeans_final = KMeans(n_clusters=K_OPTIMAL, init='k-means++',
n_init=10, random_state=42)
data_pelanggan['cluster'] = kmeans_final.fit_predict(X_scaled)
# Profil setiap cluster
print(f"\n{'='*60}")
print(f"PROFIL CLUSTER (K={K_OPTIMAL})")
print(f"{'='*60}")
for i in range(K_OPTIMAL):
cluster_data = data_pelanggan[data_pelanggan['cluster'] == i]
print(f"\n--- Cluster {i} ({len(cluster_data)} pelanggan) ---")
print(f" Income rata-rata: ${cluster_data['annual_income'].mean():.1f}k")
print(f" Spending rata-rata: {cluster_data['spending_score'].mean():.1f}")
print(f" Usia rata-rata: {cluster_data['age'].mean():.0f} tahun")
# Visualisasi scatter plot berwarna cluster
plt.figure(figsize=(10, 8))
colors = ['#FF6B6B', '#4ECDC4', '#45B7D1', '#96CEB4', '#FFEAA7']
cluster_names = [
'Budget Conscious', 'Average Spenders', 'Premium Customers',
'High Income Low Spend', 'Young Big Spenders'
]
for i in range(K_OPTIMAL):
mask = data_pelanggan['cluster'] == i
plt.scatter(data_pelanggan[mask]['annual_income'],
data_pelanggan[mask]['spending_score'],
s=60, alpha=0.7, c=colors[i],
label=f'Cluster {i}: {cluster_names[i]}',
edgecolors='white', linewidth=0.5)
# Plot centroid
centroids_orig = scaler.inverse_transform(kmeans_final.cluster_centers_)
plt.scatter(centroids_orig[:, 0], centroids_orig[:, 1],
s=250, c='black', marker='โ
', edgecolors='white',
linewidth=2, label='Centroid', zorder=5)
plt.xlabel('Annual Income ($k)', fontsize=12)
plt.ylabel('Spending Score (1-100)', fontsize=12)
plt.title('Segmentasi Pelanggan โ K-Means Clustering', fontsize=14)
plt.legend(fontsize=9)
plt.grid(True, alpha=0.3)
plt.tight_layout()
plt.show()
7. Kelebihan, Kekurangan & Tips Praktis
Kelebihan K-Means
| Kelebihan | Penjelasan |
|---|---|
| Sederhana & Intuitif | Mudah dipahami dan diimplementasikan |
| Skalabel | Bekerja efisien untuk dataset besar (O(nยทKยทdยทi)) |
| Cepat | Konvergensi relatif cepat dibanding algoritma lain |
| Garansi Konvergensi | Dijamin konvergen (walau mungkin ke local minimum) |
| Mudah Diinterpretasi | Centroid memberikan "representasi" tiap cluster |
Kekurangan K-Means
| Kekurangan | Penjelasan | Solusi |
|---|---|---|
| Perlu K ditentukan di awal | Jumlah cluster harus ditentukan sebelumnya | Elbow method, Silhouette |
| Sensitif inisialisasi | Hasil bisa berbeda tergantung centroid awal | Gunakan k-means++, n_init |
| Asumsi cluster bulat | Mengasumsikan cluster berbentuk spherical | Gunakan DBSCAN/GMM |
| Sensitif outlier | Outlier bisa mempengaruhi centroid | Gunakan K-Medoids |
| Hanya cluster convex | Tidak bisa menemukan bentuk non-convex | Spectral clustering |
| Skala fitur berpengaruh | Fitur dengan skala besar mendominasi | Standarisasi (StandardScaler) |
Tips Praktis K-Means
- Selalu lakukan normalisasi/standarisasi โ K-Means berbasis jarak, skala fitur sangat berpengaruh
- Gunakan init='k-means++' โ Inisialisasi cerdas yang menghindari local minimum
- Set n_init=10 atau lebih โ Jalankan beberapa kali dengan inisialisasi berbeda
- Gunakan Elbow + Silhouette bersamaan โ Keduanya saling melengkapi
- Visualisasikan hasilnya โ Plot cluster dan centroid untuk validasi intuitif
- Cek distribusi cluster โ Cluster yang sangat timpang perlu investigasi
- Hapus outlier terlebih dahulu โ Outlier bisa mendistorsi centroid
8. K-Means vs Algoritma Clustering Lainnya
K-Means bukan satu-satunya algoritma clustering. Berikut perbandingan dengan beberapa alternatif populer:
Perbandingan Algoritma Clustering
| Aspek | K-Means | DBSCAN | Hierarchical | Gaussian Mixture |
|---|---|---|---|---|
| Input K? | โ Ya | โ Tidak | โ Tidak (cut tree) | โ Ya |
| Bentuk Cluster | Spherical | Arbitrary | Arbitrary | Elliptical |
| Handling Outlier | โ Buruk | โ Bagus | โ ๏ธ Sedang | โ ๏ธ Sedang |
| Skalabilitas | โ Sangat baik | โ ๏ธ Sedang | โ Lambat O(nยณ) | โ ๏ธ Sedang |
| Deterministik | โ Tidak | โ Ya | โ Ya | โ Tidak |
| Best For | Cluster bulat, data besar | Cluster arbitrary, noise | Eksplorasi hierarki | Cluster overlap |
Variasi K-Means
| Variasi | Perbedaan | Kegunaan |
|---|---|---|
| K-Means++ | Inisialisasi centroid lebih cerdas | Hindari local minimum |
| Mini-Batch K-Means | Gunakan mini-batch untuk update | Dataset sangat besar |
| K-Medoids (PAM) | Centroid = titik data aktual | Lebih robust terhadap outlier |
| Bisecting K-Means | Top-down: split satu cluster jadi dua | Hasil lebih stabil |
| Kernel K-Means | Gunakan kernel trick | Cluster non-linear |
Mini-Batch K-Means untuk Dataset Besar
import time
import numpy as np
from sklearn.cluster import KMeans, MiniBatchKMeans
from sklearn.datasets import make_blobs
# Dataset besar
X_big, y_big = make_blobs(n_samples=100000, centers=10,
cluster_std=1.0, random_state=42)
print(f"Dataset: {X_big.shape[0]} titik, {X_big.shape[1]} fitur")
# Bandingkan K-Means vs Mini-Batch
for name, Model in [('K-Means', KMeans), ('Mini-Batch K-Means', MiniBatchKMeans)]:
start = time.time()
model = Model(n_clusters=10, init='k-means++', n_init=3,
random_state=42, batch_size=1024 if name == 'Mini-Batch K-Means' else None)
model.fit(X_big)
elapsed = time.time() - start
print(f"\n{name}:")
print(f" Waktu: {elapsed:.2f} detik")
print(f" Inertia: {model.inertia_:.2f}")
print(f" Iterasi: {model.n_iter_}")
9. Quiz Pemahaman
Uji pemahaman kamu tentang K-Means Clustering dengan menjawab pertanyaan berikut:
๐ง Quiz: K-Means Clustering
1. Apa yang diukur oleh Inertia (WCSS) dalam K-Means?
2. Pada Elbow Method, titik "siku" menunjukkan:
3. Mengapa normalisasi/standarisasi PENTING sebelum K-Means?
4. Silhouette Score bernilai -1 sampai +1. Score 0.85 menunjukkan:
5. Apa keunggulan k-means++ dibanding inisialisasi random biasa?
- K-Means mengelompokkan data ke K cluster berdasarkan jarak ke centroid
- Elbow Method membantu menentukan K optimal dari plot Inertia vs K
- Silhouette Score mengukur kualitas clustering (range -1 sampai +1)
- Normalisasi sangat penting karena K-Means berbasis jarak
- k-means++ lebih baik dari inisialisasi random biasa
- K-Means cepat dan sederhana, tetapi asumsi cluster berbentuk spherical