Unsupervised Learning

4 jam11 min baca
Tujuan

Clustering dan dimensionality reduction. Penting untuk EDA dan **embedding visualization** di LLM nanti.

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:

  1. Tunjuk 3 piring random sebagai "patokan" tiap kelompok
  2. Tiap piring lain bergabung ke kelompok dengan patokan terdekat
  3. Hitung patokan baru = rata-rata kelompok
  4. 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:

  1. Init: pilih K titik random sebagai centroid awal
  2. Assign: tiap titik bergabung ke cluster centroid terdekat
  3. Update: hitung centroid baru = mean tiap cluster
  4. Cek: kalau centroid berubah โ†’ ulang assign + update
  5. 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

  1. Pilih K (jumlah cluster)
  2. Random initialize K centroid
  3. Assign tiap titik ke centroid terdekat
  4. Update centroid = mean dari assigned points
  5. 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:

  1. Pilih titik random
  2. Hitung tetangga dalam radius eps
  3. Kalau tetangga โ‰ฅ min_samples โ†’ core point
  4. Kalau tidak, cek apakah reachable dari core โ†’ border point, kalau tidak โ†’ noise (-1)
  5. 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 neighborhood
  • min_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 distance
  • complete โ€” max distance
  • average โ€” average distance
  • ward โ€” 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:

  1. Standardize data (mean=0, std=1)
  2. Hitung covariance matrix antar fitur
  3. Eigendecomposition โ†’ dapat eigenvectors (PC) + eigenvalues (variance per PC)
  4. Sort PC berdasarkan eigenvalue (PC1 paling banyak variance)
  5. Pilih top-K PC yang variance kumulatifnya 95%
  6. 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
  1. K-Means dengan K=3
  2. Bandingkan label dengan true label (pakai adjusted_rand_score)
  3. PCA ke 2D, scatter plot dengan true label vs cluster label
  4. Eksperimen K dari 2-10, plot elbow

Challenge 2 โ€” Customer Segmentation

Dataset Kaggle "Mall Customer Segmentation":

  1. Fitur: age, income, spending score
  2. Find optimal K
  3. Cluster + interpret tiap segment
  4. Visualisasi 3D (matplotlib Axes3D)

Challenge 3 โ€” High-Dim Visualization

Dataset MNIST (subset 1000):

  1. Original 784D
  2. PCA ke 50D
  3. t-SNE ke 2D
  4. Plot dengan warna per digit

Selanjutnya: 05-feature-engineering.md