Bab 8 ~4 jam
Unsupervised Learning
Temukan struktur tersembunyi dalam data tanpa label — melalui clustering dan reduksi dimensi.
8.1 Clustering K-Means
K-Means mempartisi data ke dalam K cluster dengan meminimalkan jumlah kuadrat dalam-cluster. Sederhana, cepat, tapi perlu menentukan K.
min Σᵢ Σⱼ ||xⱼ - μᵢ||² di mana μᵢ adalah centroid cluster i
from sklearn.cluster import KMeans
from sklearn.metrics import silhouette_score
# Cari K optimal dengan metode elbow
inertias = []
silhouettes = []
K_range = range(2, 11)
for k in K_range:
km = KMeans(n_clusters=k, n_init=10, random_state=42)
labels = km.fit_predict(X_scaled)
inertias.append(km.inertia_)
silhouettes.append(silhouette_score(X_scaled, labels))
# Plot kurva elbow
plt.plot(K_range, inertias, 'bo-')
plt.xlabel('K'); plt.ylabel('Inersia')
# Model final
km_final = KMeans(n_clusters=4, n_init=10, random_state=42)
df['cluster'] = km_final.fit_predict(X_scaled)
Keterbatasan: K-Means mengasumsikan cluster berbentuk bulat dengan ukuran serupa. Kesulitan dengan bentuk tidak reguler, kepadatan berbeda, dan data berdimensi tinggi. Selalu scaling fitur terlebih dahulu.
8.2 Clustering Hierarkis
Membangun pohon cluster (dendrogram). Tidak perlu menentukan K — potong pohon pada level yang diinginkan.
from sklearn.cluster import AgglomerativeClustering
from scipy.cluster.hierarchy import dendrogram, linkage
# Dendrogram (gunakan subset untuk keterbacaan)
Z = linkage(X_scaled[:100], method='ward')
plt.figure(figsize=(12, 5))
dendrogram(Z, leaf_rotation=90)
# Agglomerative clustering
agg = AgglomerativeClustering(n_clusters=4, linkage='ward')
labels = agg.fit_predict(X_scaled)
# Opsi linkage: 'ward', 'complete', 'average', 'single'
8.3 DBSCAN
Clustering berbasis kepadatan yang bisa menemukan cluster berbentuk apa saja dan mengidentifikasi titik noise. Tidak perlu menentukan K.
from sklearn.cluster import DBSCAN
# eps = radius tetangga, min_samples = titik minimum
dbscan = DBSCAN(eps=0.5, min_samples=5)
labels = dbscan.fit_predict(X_scaled)
n_clusters = len(set(labels)) - (1 if -1 in labels else 0)
n_noise = list(labels).count(-1)
print(f"Cluster: {n_clusters}, Noise: {n_noise}")
Memilih eps: Gunakan grafik k-distance — plot jarak ke tetangga ke-k untuk setiap titik (k = min_samples). Carilah "siku" sebagai nilai eps.
8.4 Analisis Komponen Utama (PCA)
PCA menemukan arah ortogonal varians maksimum. Ini adalah metode go-to untuk reduksi dimensi.
from sklearn.decomposition import PCA
# Fit PCA
pca = PCA(n_components=0.95) # Pertahankan 95% varians
X_pca = pca.fit_transform(X_scaled)
print(f"Komponen: {pca.n_components_}")
print(f"Varians yang dijelaskan: {pca.explained_variance_ratio_}")
# Scree plot
pca_full = PCA().fit(X_scaled)
plt.plot(range(1, len(pca_full.explained_variance_ratio_)+1),
np.cumsum(pca_full.explained_variance_ratio_), 'bo-')
plt.axhline(y=0.95, color='r', linestyle='--')
plt.xlabel('Komponen'); plt.ylabel('Varians Kumulatif')
Kapan menggunakan PCA: Sebelum K-Means (kurangi noise), untuk visualisasi (2-3 komponen), untuk mempercepat algoritma, atau menghapus multikolinearitas. Selalu scaling terlebih dahulu — PCA berbasis varians.
8.5 t-SNE & UMAP
Reduksi dimensi non-linier untuk visualisasi. Mempertahankan struktur lokal dengan baik tapi tidak cocok sebagai langkah preprocessing.
from sklearn.manifold import TSNE
# t-SNE (selalu kurangi dimensi dulu dengan PCA!)
X_pca_50 = PCA(n_components=50).fit_transform(X_scaled)
tsne = TSNE(n_components=2, perplexity=30, random_state=42)
X_tsne = tsne.fit_transform(X_pca_50)
plt.scatter(X_tsne[:, 0], X_tsne[:, 1], c=labels, cmap='viridis', alpha=0.6)
# UMAP (pip install umap-learn)
import umap
reducer = umap.UMAP(n_neighbors=15, min_dist=0.1, random_state=42)
X_umap = reducer.fit_transform(X_scaled)
Peringatan: t-SNE/UMAP hanya untuk visualisasi. Jarak dan ukuran cluster di plot 2D tidak bermakna. Jangan pernah menarik kesimpulan kuantitatif dari geometri plot.
Latihan: Pada dataset digit MNIST, bandingkan K-Means, hierarkis, dan DBSCAN. Visualisasikan dengan t-SNE. Algoritma mana yang paling baik menangkap 10 kelas digit?