04 โ Unsupervised Learning
Estimasi: 4 jam Tujuan: Clustering dan dimensionality reduction. Penting untuk EDA dan embedding visualization di LLM nanti.
Kenapa Materi Ini Penting?
Unsupervised learning = ML tanpa label. Real world, sebagian besar data tidak ber-label. Customer database tidak ada kolom "segment", log server tidak ada kolom "anomaly", word embedding di LLM tidak ada kolom "kategori". Unsupervised learning yang menemukan struktur tersembunyi di data mentah.
Untuk GenAI bootcamp, ini krusial karena: word embedding 768D dari BERT/GPT tidak bisa di-visualize langsung. PCA/t-SNE/UMAP yang akan kamu pakai untuk explore embedding space, debug model, dan present hasil ke stakeholder. Clustering juga sering dipakai untuk grouping document yang mirip (RAG retrieval), customer segmentation, dan anomaly detection di production model.
flowchart TD
A["๐ Unsupervised<br/>Learning"] --> B["๐ฏ Clustering"]
A --> C["๐ Dimensionality<br/>Reduction"]
A --> D["๐ Anomaly<br/>Detection"]
B --> B1["K-Means"]
B --> B2["DBSCAN"]
B --> B3["Hierarchical"]
C --> C1["PCA (linear)"]
C --> C2["t-SNE / UMAP<br/>(non-linear)"]
D --> D1["Isolation Forest"]
D --> D2["DBSCAN noise"]
Bagian 1 โ K-Means Clustering
Analogi: Mengelompokkan Piring Berdasarkan Kemiripan
Bayangkan kamu punya 100 piring di meja, mau bagi jadi 3 kelompok berdasarkan kemiripan ukuran/warna. Caranya:
- Tunjuk 3 piring random sebagai "patokan" tiap kelompok
- Tiap piring lain bergabung ke kelompok dengan patokan terdekat
- Hitung patokan baru = rata-rata kelompok
- Ulangi sampai patokan tidak berubah
K-Means persis itu. K = jumlah kelompok yang kamu pilih, centroid = patokan.
Cara Membaca Diagram:
- Kiri ke kanan: alur 1 iterasi K-Means
- Loop balik dari "Centroid berubah?" โ ulang sampai konvergen
Walkthrough Step-by-Step:
- Init: pilih K titik random sebagai centroid awal
- Assign: tiap titik bergabung ke cluster centroid terdekat
- Update: hitung centroid baru = mean tiap cluster
- Cek: kalau centroid berubah โ ulang assign + update
- Konvergen: centroid stabil โ selesai
Analogi Sehari-hari: Mengelompokkan piring kotor. Mulai dari 3 tumpukan random, tiap piring pindah ke tumpukan paling mirip, geser pusat tumpukan ke tengah, ulangi sampai stabil.
Diagram statis Mermaid sebagai fallback:
flowchart TD
A["๐ฒ Random initialize<br/>K centroid"] --> B["๐ Assign tiap titik<br/>ke centroid terdekat"]
B --> C["๐ Update centroid =<br/>mean cluster"]
C --> D{"Centroid<br/>berubah?"}
D -->|Ya| B
D -->|Tidak| E["โ
Konvergen"]
style E fill:#d4f4dd
Konsep
- Pilih K (jumlah cluster)
- Random initialize K centroid
- Assign tiap titik ke centroid terdekat
- Update centroid = mean dari assigned points
- Repeat sampai konvergen
Pakai
from sklearn.cluster import KMeans
from sklearn.datasets import make_blobs
from sklearn.preprocessing import StandardScaler
import matplotlib.pyplot as plt
# Generate data
X, _ = make_blobs(n_samples=300, centers=4, cluster_std=0.6, random_state=42)
X = StandardScaler().fit_transform(X)
# Pilih K
model = KMeans(n_clusters=4, random_state=42, n_init=10)
model.fit(X)
# Cluster labels
labels = model.labels_
# Centroids
centroids = model.cluster_centers_
# Visualisasi
plt.scatter(X[:, 0], X[:, 1], c=labels, cmap="viridis")
plt.scatter(centroids[:, 0], centroids[:, 1], c="red", marker="X", s=200)
plt.show()
# Predict cluster untuk data baru
# new_labels = model.predict(X_new)
Pilih K Optimal: Elbow Method
inertias = []
for k in range(1, 11):
model = KMeans(n_clusters=k, random_state=42, n_init=10)
model.fit(X)
inertias.append(model.inertia_)
plt.plot(range(1, 11), inertias, marker="o")
plt.xlabel("K")
plt.ylabel("Inertia")
plt.show()
Cari "elbow" โ titik dimana penurunan inertia mulai mendatar.
Silhouette Score
from sklearn.metrics import silhouette_score
scores = []
for k in range(2, 11):
model = KMeans(n_clusters=k, random_state=42, n_init=10)
labels = model.fit_predict(X)
scores.append(silhouette_score(X, labels))
plt.plot(range(2, 11), scores, marker="o")
Tertinggi = K optimal.
Pros & Cons
โ Simple, fast, scalable โ Asumsi cluster bulat, butuh K, sensitif outlier
Bagian 2 โ DBSCAN
Density-based clustering โ tidak butuh K, handle outlier sebagai noise.
Analogi: Pesta di Taman
Bayangkan orang-orang di taman. Yang ngumpul rapat = satu pesta (cluster). Yang sendirian jauh-jauh = bukan pesta (noise/outlier). DBSCAN cari "pusat keramaian" berdasarkan density, bukan jumlah cluster fix. Cocok untuk cluster bentuk tidak beraturan (mirip bulan sabit) yang K-Means gagal.
Cara Membaca Diagram:
- Kiri ke kanan: klasifikasi tiap titik
- Tiga kategori: core (rame tetangga), border (dekat core), noise (sendirian)
- Cluster terbentuk dari core points yang terhubung
Walkthrough Step-by-Step:
- Pilih titik random
- Hitung tetangga dalam radius
eps - Kalau tetangga โฅ
min_samplesโ core point - Kalau tidak, cek apakah reachable dari core โ border point, kalau tidak โ noise (-1)
- Gabungkan core points yang terhubung jadi 1 cluster
Analogi Sehari-hari: Lampu jalan yang menyala di malam hari. Lampu rame berdekatan = "kawasan ramai" (cluster). Lampu sendirian di hutan = anomali (noise).
Diagram statis Mermaid sebagai fallback:
flowchart LR
A["๐ Titik random"] --> B{"Tetangga dalam<br/>radius eps โฅ min_samples?"}
B -->|Ya| C["๐ข Core point"]
B -->|Tidak| D{"Reachable dari<br/>core point?"}
D -->|Ya| E["๐ก Border point"]
D -->|Tidak| F["โซ Noise (-1)"]
C --> G["๐ฆ Form cluster<br/>dengan core points<br/>terhubung"]
E --> G
from sklearn.cluster import DBSCAN
model = DBSCAN(eps=0.5, min_samples=5)
labels = model.fit_predict(X)
# label = -1 berarti noise
Hyperparameter
epsโ radius neighborhoodmin_samplesโ min titik untuk jadi core point
Pros & Cons
โ Tidak butuh K, handle noise, cluster bentuk apapun โ Sensitif ke eps, slow di high-dim
Bagian 3 โ Hierarchical Clustering
Bikin dendogram โ pohon hierarki cluster.
from scipy.cluster.hierarchy import dendrogram, linkage
from scipy.cluster.hierarchy import fcluster
# Build linkage matrix
Z = linkage(X, method="ward")
# Plot dendogram
plt.figure(figsize=(15, 6))
dendrogram(Z)
plt.show()
# Cut dendogram untuk dapat cluster
labels = fcluster(Z, t=3, criterion="maxclust") # 3 cluster
Methods
singleโ min distancecompleteโ max distanceaverageโ average distancewardโ variance minimization (paling populer)
Bagian 4 โ PCA (Dimensionality Reduction)
Principal Component Analysis โ reduce dimension dengan mempertahankan variance maksimal.
Analogi: Kompresi Foto JPEG
Foto resolusi tinggi (12 megapixel) bisa di-kompres ke 2 megapixel tanpa kehilangan banyak detail visual karena banyak pixel redundant. PCA persis itu untuk data: cari "axis utama" yang menangkap variance terbesar, buang axis yang variance-nya kecil (redundant). Hasil: data lebih ringkas tapi info penting tetap.
Cara Membaca Diagram:
- Kiri: data high-dim (e.g., 768D embedding)
- Tengah: hitung covariance + eigendecomposition โ cari principal component
- Kanan: project ke top-K component โ low-dim data
Walkthrough Step-by-Step:
- Standardize data (mean=0, std=1)
- Hitung covariance matrix antar fitur
- Eigendecomposition โ dapat eigenvectors (PC) + eigenvalues (variance per PC)
- Sort PC berdasarkan eigenvalue (PC1 paling banyak variance)
- Pilih top-K PC yang variance kumulatifnya 95%
- Project data ke top-K PC โ reduced dimension
Analogi Sehari-hari: Foto orang dari arah depan vs samping. Foto depan menangkap variance bentuk wajah lebih banyak. PCA otomatis cari "sudut pandang" terbaik yang menampilkan paling banyak detail.
Diagram statis Mermaid sebagai fallback:
flowchart LR
A["๐ Data 768D<br/>(misal embedding)"] --> B["๐ Hitung covariance<br/>matrix"]
B --> C["๐ Eigendecomposition<br/>cari principal components"]
C --> D["๐ Sort by variance<br/>(PC1 > PC2 > ...)"]
D --> E["โ๏ธ Ambil top-K<br/>component"]
E --> F["๐ฏ Project ke<br/>dimensi rendah"]
F --> G["๐ Data 50D<br/>(95% variance kept)"]
style G fill:#d4f4dd
from sklearn.decomposition import PCA
from sklearn.datasets import load_digits
from sklearn.preprocessing import StandardScaler
import matplotlib.pyplot as plt
# Load digits (8x8 = 64D)
digits = load_digits()
X = StandardScaler().fit_transform(digits.data)
y = digits.target
# Reduce ke 2D untuk visualisasi
pca = PCA(n_components=2)
X_2d = pca.fit_transform(X)
# Explained variance
print(pca.explained_variance_ratio_)
# [0.65, 0.20] โ 65% variance di PC1, 20% di PC2
# Total variance preserved
print(pca.explained_variance_ratio_.sum()) # 0.85 (85%)
# Visualisasi
plt.scatter(X_2d[:, 0], X_2d[:, 1], c=y, cmap="tab10", alpha=0.7)
plt.colorbar()
plt.xlabel("PC1")
plt.ylabel("PC2")
plt.show()
Visualisasi
plt.scatter(X_2d[:, 0], X_2d[:, 1], c=y, cmap="viridis")
plt.xlabel("PC1")
plt.ylabel("PC2")
plt.show()
Use Case
- Reduce dim sebelum modeling (kurangi feature)
- Visualisasi high-dim data
- Noise reduction
Konteks LLM: word embedding 768D bisa di-PCA ke 2D untuk visualisasi (mirip TensorBoard projector).
Bagian 5 โ t-SNE & UMAP
PCA = linear. Untuk visualisasi non-linear, pakai t-SNE atau UMAP.
t-SNE
from sklearn.manifold import TSNE
tsne = TSNE(n_components=2, perplexity=30, random_state=42)
X_tsne = tsne.fit_transform(X)
UMAP (Lebih Cepat)
# pip install umap-learn
import umap
reducer = umap.UMAP(n_components=2, random_state=42)
X_umap = reducer.fit_transform(X)
Aturan:
- PCA โ fast, linear
- t-SNE โ bagus visualisasi, lambat di big data
- UMAP โ bagus visualisasi, lebih cepat dari t-SNE
Untuk modeling (bukan viz), prefer PCA.
Tabel Komparasi Algoritma Unsupervised
| Algoritma | Tipe | Butuh K? | Handle Noise? | Bentuk Cluster | Speed | Best For |
|---|---|---|---|---|---|---|
| K-Means | Clustering | โ Ya | โ Tidak | Bulat | โกโกโก | Cluster sederhana, dataset besar |
| DBSCAN | Clustering | โ Tidak | โ Ya (-1) | Bebas | โกโก | Anomaly, cluster bentuk aneh |
| Hierarchical | Clustering | โ Tidak | โ Tidak | Bebas | โก | Dendogram, eksplorasi struktur |
| PCA | Dim Reduction | - | - | Linear | โกโกโก | Modeling, kompresi |
| t-SNE | Dim Reduction | - | - | Non-linear | ๐ | Visualisasi 2D/3D |
| UMAP | Dim Reduction | - | - | Non-linear | โกโก | Visualisasi cepat, embedding |
Bagian 6 โ Aplikasi Praktis
1. Customer Segmentation
# Data: pelanggan dengan fitur (recency, frequency, monetary)
kmeans = KMeans(n_clusters=4, random_state=42)
df["segment"] = kmeans.fit_predict(df[features])
# Analisis tiap segment
df.groupby("segment")[features].mean()
2. Image Compression
from sklearn.cluster import KMeans
# Image as array of pixels
pixels = image.reshape(-1, 3)
kmeans = KMeans(n_clusters=16)
kmeans.fit(pixels)
compressed = kmeans.cluster_centers_[kmeans.labels_].reshape(image.shape)
3. Anomaly Detection
from sklearn.ensemble import IsolationForest
model = IsolationForest(contamination=0.05)
labels = model.fit_predict(X)
# label = -1 โ outlier
Common Mistakes & FAQ
Common Mistakes
flowchart TD
A["โ ๏ธ Common Mistakes"] --> B["๐ Lupa scaling<br/>sebelum K-Means/PCA"]
A --> C["๐ฒ K dipilih<br/>tanpa elbow/silhouette"]
A --> D["๐ t-SNE pakai<br/>raw 768D (lambat)"]
A --> E["๐ PCA tanpa lihat<br/>explained_variance"]
A --> F["๐ Membandingkan cluster<br/>label numerik (1=2?)"]
style A fill:#ffe0e0
1. Lupa Scaling
K-Means dan PCA berbasis jarak/variance. Feature dengan range besar mendominasi. Selalu StandardScaler() dulu.
2. Pilih K Sembarangan
K-Means butuh K. Jangan tebak. Pakai elbow method + silhouette score. Kombinasi keduanya lebih reliable.
3. t-SNE di Raw High-Dim
t-SNE langsung di 768D embedding sangat lambat. Best practice: PCA dulu ke 50D, lalu t-SNE/UMAP ke 2D.
4. Cluster Label = Numerik Berarti Apa?
Label cluster (0, 1, 2) tidak berurutan. Cluster 0 dan cluster 2 tidak lebih jauh dari cluster 0 dan cluster 1. Jangan treat sebagai ordinal.
5. PCA tanpa Cek Variance
PCA(n_components=2) tapi cuma 30% variance ter-preserve = 70% info hilang. Cek explained_variance_ratio_.cumsum() dulu untuk pilih n_components yang masuk akal (biasanya 95%).
FAQ
Q: K-Means atau DBSCAN? A: K-Means kalau cluster relatif bulat dan tahu kira-kira K. DBSCAN kalau bentuk cluster aneh atau ada outlier.
Q: Berapa K yang harus saya pilih? A: Tidak ada jawaban "benar". Pakai domain knowledge + elbow + silhouette. Kalau bisnis bilang "kami mau 4 segment customer", ya K=4.
Q: PCA atau autoencoder? A: PCA cepat dan linear. Autoencoder neural network, bisa non-linear tapi butuh tuning. Untuk start, PCA cukup.
Q: Apakah unsupervised butuh evaluasi? A: Lebih sulit dari supervised. Untuk clustering: silhouette score, davies-bouldin, atau evaluasi domain (apakah cluster masuk akal bisnis). Untuk dim reduction: explained variance untuk PCA, kvalidasi visual untuk t-SNE/UMAP.
Q: Cluster hasil saya tidak masuk akal? A: Cek scaling, cek K, cek apakah feature relevan. Kadang cluster yang "tidak masuk akal" justru insight berharga.
Cek Pemahaman
- Tahu cara kerja K-Means iteratively?
- Bisa pakai elbow + silhouette untuk pilih K?
- Tahu kapan pakai DBSCAN vs K-Means?
- Bisa PCA + interpretasi explained variance?
- Tahu beda PCA, t-SNE, UMAP?
- Tahu pentingnya scaling sebelum K-Means/PCA?
Challenge 5.4
Challenge 1 โ Iris Clustering
from sklearn.datasets import load_iris
data = load_iris()
X = data.data
y = data.target
- K-Means dengan K=3
- Bandingkan label dengan true label (pakai adjusted_rand_score)
- PCA ke 2D, scatter plot dengan true label vs cluster label
- Eksperimen K dari 2-10, plot elbow
Challenge 2 โ Customer Segmentation
Dataset Kaggle "Mall Customer Segmentation":
- Fitur: age, income, spending score
- Find optimal K
- Cluster + interpret tiap segment
- Visualisasi 3D (matplotlib
Axes3D)
Challenge 3 โ High-Dim Visualization
Dataset MNIST (subset 1000):
- Original 784D
- PCA ke 50D
- t-SNE ke 2D
- Plot dengan warna per digit
Selanjutnya: 05-feature-engineering.md