Bab 3: Algoritma Pembelajaran Mesin Klasik

🎯 Hasil Pembelajaran (Learning Outcomes)

Setelah mempelajari bab ini, Anda akan mampu:

  1. Memahami prinsip kerja algoritma ML klasik: regresi linier, logistik, tree-based models, SVM, dan KNN
  2. Menjelaskan konsep regularisasi (L1/L2) dan cara mencegah overfitting
  3. Membandingkan kelebihan dan kelemahan berbagai algoritma untuk use case yang berbeda
  4. Menerapkan algoritma klasik menggunakan scikit-learn dengan hyperparameter tuning
  5. Evaluasi model menggunakan confusion matrix, precision, recall, F1-score, dan cross-validation
  6. Pilih algoritma yang tepat berdasarkan karakteristik data dan business requirements

3.1 Pengantar: Fondasi ML Modern

Algoritma pembelajaran mesin klasik membentuk tulang punggung praktik machine learning modern. Meskipun deep learning mendapat banyak perhatian, algoritma klasik tetap menjadi pilihan utama untuk:

  • Datasets berukuran kecil hingga menengah (ribuan hingga ratusan ribu baris)
  • Interpretabilitas tinggi (perlu menjelaskan keputusan model)
  • Kecepatan pelatihan (perlu model cepat dan efisien)
  • Produksi (stabilitas, reproducibility, maintenance yang mudah)

Bab ini membahas algoritma klasik yang paling praktis dan sering digunakan dalam industri.

3.2 Pembelajaran Mesin Linier

3.2.1 Regresi Linier Sederhana

Regresi linier adalah algoritma paling dasar dalam machine learning. Model memprediksi nilai target sebagai kombinasi linier dari fitur input.

Formula Matematika:

\[\hat{y} = w_0 + w_1 x_1 + w_2 x_2 + ... + w_n x_n\]

Dimana:

  • \(\hat{y}\) = prediksi
  • \(w_0\) = bias (intercept)
  • \(w_i\) = bobot (weight) untuk fitur \(i\)
  • \(x_i\) = nilai fitur \(i\)

Contoh: Prediksi Harga Rumah

Code
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from sklearn.linear_model import LinearRegression
from sklearn.metrics import mean_squared_error, r2_score

# Data rumah sederhana
data = {
    'Luas (m²)': [100, 150, 200, 250, 300, 350, 400],
    'Harga (Juta)': [0.5, 0.8, 1.2, 1.5, 2.0, 2.3, 2.8]
}

X = np.array(data['Luas (m²)']).reshape(-1, 1)
y = np.array(data['Harga (Juta)'])

# Latih model regresi linier
model = LinearRegression()
model.fit(X, y)

print(f"Koefisien (slope): {model.coef_[0]:.4f}")
print(f"Intercept (bias): {model.intercept_:.4f}")
print(f"R² Score: {r2_score(y, model.predict(X)):.4f}")

# Prediksi untuk rumah 350 m²
harga_prediksi = model.predict([[350]])
print(f"\nPrediksi harga rumah 350 m²: {harga_prediksi[0]:.2f} juta")

3.2.2 Regresi Logistik

Meskipun namanya “regresi”, logistic regression adalah algoritma klasifikasi yang memprediksi probabilitas kelas.

Konsep Kunci:

  • Menggunakan fungsi sigmoid untuk mengubah output linier menjadi probabilitas (0-1)
  • Ideal untuk masalah klasifikasi biner
  • Output dapat diinterpretasi sebagai probabilitas

Formula:

\[P(y=1|x) = \frac{1}{1 + e^{-(w_0 + w_1 x_1 + ... + w_n x_n)}}\]

Code
from sklearn.linear_model import LogisticRegression
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score, classification_report

# Load Iris dataset
iris = load_iris()
X = iris.data[:, [0, 3]]  # Gunakan sepal length dan petal width
y = (iris.target == 2).astype(int)  # Klasifikasi: Virginica vs Others

X_train, X_test, y_train, y_test = train_test_split(
    X, y, test_size=0.2, random_state=42
)

# Latih logistic regression
log_reg = LogisticRegression(random_state=42, max_iter=1000)
log_reg.fit(X_train, y_train)

# Evaluasi
y_pred = log_reg.predict(X_test)
print(f"Akurasi: {accuracy_score(y_test, y_pred):.4f}")
print(f"\nClassification Report:\n{classification_report(y_test, y_pred)}")

# Prediksi probabilitas
prob = log_reg.predict_proba(X_test[:3])
print(f"\nProbabilitas prediksi 3 sampel pertama:\n{prob}")

3.2.3 Regularisasi: Ridge dan Lasso

Overfitting terjadi ketika model belajar noise dalam data. Regularisasi menambahkan penalty pada bobot besar untuk mencegah overfitting.

Ridge Regression (L2):

  • Menambah penalty proporsional dengan kuadrat bobot
  • Semua bobot berkurang tapi tidak ada yang menjadi nol
  • Formula: Loss = MSE + λ × Σ(w²)

Lasso Regression (L1):

  • Menambah penalty proporsional dengan nilai absolut bobot
  • Beberapa bobot bisa menjadi nol (feature selection otomatis)
  • Formula: Loss = MSE + λ × Σ|w|
Code
from sklearn.linear_model import Ridge, Lasso
from sklearn.preprocessing import StandardScaler
from sklearn.datasets import make_regression

# Buat dataset regresi
X, y = make_regression(n_samples=200, n_features=20, n_informative=10,
                       noise=10, random_state=42)

X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)

# Standardisasi fitur (penting untuk regularisasi)
scaler = StandardScaler()
X_train_scaled = scaler.fit_transform(X_train)
X_test_scaled = scaler.transform(X_test)

# Ridge Regression
ridge = Ridge(alpha=1.0)
ridge.fit(X_train_scaled, y_train)
ridge_r2 = r2_score(y_test, ridge.predict(X_test_scaled))

# Lasso Regression
lasso = Lasso(alpha=0.1)
lasso.fit(X_train_scaled, y_train)
lasso_r2 = r2_score(y_test, lasso.predict(X_test_scaled))

print(f"Ridge R² Score: {ridge_r2:.4f}")
print(f"Lasso R² Score: {lasso_r2:.4f}")
print(f"\nBobot Lasso (perhatikan nilai 0):\n{lasso.coef_[:10]}")

3.3 Model Berbasis Pohon (Tree-Based Models)

3.3.1 Decision Trees (Pohon Keputusan)

Decision trees membuat keputusan dengan cara membagi data berdasarkan fitur yang paling informatif.

Kelebihan:

  • Mudah diinterpretasi (bisa divisualisasi)
  • Tidak memerlukan scaling fitur
  • Bisa menangani relasi nonlinier
  • Bisa digunakan untuk klasifikasi dan regresi

Kelemahan:

  • Cenderung overfit
  • Tidak stabil (perubahan kecil data bisa mengubah pohon banyak)
  • Performa lebih rendah dari ensemble methods
Code
from sklearn.tree import DecisionTreeClassifier, plot_tree
from sklearn.datasets import load_iris

# Load data
iris = load_iris()
X = iris.data[:, [0, 1]]  # 2 fitur untuk visualisasi mudah
y = iris.target

# Latih decision tree
dt = DecisionTreeClassifier(max_depth=3, random_state=42)
dt.fit(X, y)

print(f"Akurasi Training: {dt.score(X, y):.4f}")
print(f"Jumlah leaf nodes: {dt.get_n_leaves()}")

# Buat contoh prediksi
sample = [[5.5, 3.0]]
prediction = dt.predict(sample)
prediction_proba = dt.predict_proba(sample)

print(f"\nPrediksi untuk [Sepal Length=5.5, Sepal Width=3.0]:")
print(f"  Class: {iris.target_names[prediction[0]]}")
print(f"  Probabilitas: {prediction_proba[0]}")

Hyperparameter Penting:

  • max_depth: Kedalaman maksimal pohon (kontrol overfitting)
  • min_samples_split: Sampel minimum untuk split
  • min_samples_leaf: Sampel minimum di leaf
  • max_features: Jumlah fitur untuk setiap split

3.3.2 Random Forest

Random Forest adalah ensemble method yang menggabungkan banyak decision trees.

Cara Kerja:

  1. Buat banyak decision trees dengan bootstrap samples
  2. Setiap tree menggunakan random subset fitur
  3. Agregasi prediksi semua trees (voting untuk klasifikasi, rata-rata untuk regresi)

Kelebihan dibanding Decision Tree:

  • Lebih akurat (ensemble mengurangi variance)
  • Lebih stabil
  • Mengurangi overfitting
  • Bisa estimate feature importance
Code
from sklearn.ensemble import RandomForestClassifier
from sklearn.datasets import make_classification

# Buat dataset
X, y = make_classification(n_samples=500, n_features=20, n_informative=10,
                           n_classes=2, random_state=42)

X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)

# Latih Random Forest
rf = RandomForestClassifier(n_estimators=100, random_state=42, n_jobs=-1)
rf.fit(X_train, y_train)

# Evaluasi
train_acc = rf.score(X_train, y_train)
test_acc = rf.score(X_test, y_test)

print(f"Training Accuracy: {train_acc:.4f}")
print(f"Test Accuracy: {test_acc:.4f}")

# Feature Importance
feature_importance = rf.feature_importances_
top_features = np.argsort(feature_importance)[-5:]

print(f"\nTop 5 Fitur Terpenting:")
for i, idx in enumerate(top_features[::-1], 1):
    print(f"  {i}. Feature {idx}: {feature_importance[idx]:.4f}")

3.4 Support Vector Machines (SVM)

SVM mencari hyperplane yang memaksimalkan margin antara kelas.

Konsep Kunci:

  • Margin: Jarak antara hyperplane dan data points terdekat
  • Support Vectors: Data points yang menentukan margin
  • Kernel: Transformasi nonlinier untuk data yang tidak linearly separable

Kernel Populer:

  • Linear: \(K(x_i, x_j) = x_i \cdot x_j\)
  • RBF (Radial Basis Function): \(K(x_i, x_j) = \exp(-\gamma ||x_i - x_j||^2)\)
  • Polynomial: \(K(x_i, x_j) = (x_i \cdot x_j + c)^d\)
Code
from sklearn.svm import SVC
from sklearn.datasets import load_breast_cancer
from sklearn.preprocessing import StandardScaler
from sklearn.metrics import accuracy_score, confusion_matrix

# Load data
cancer = load_breast_cancer()
X = cancer.data
y = cancer.target

X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)

# Standardisasi (PENTING untuk SVM)
scaler = StandardScaler()
X_train_scaled = scaler.fit_transform(X_train)
X_test_scaled = scaler.transform(X_test)

# SVM dengan RBF kernel
svm = SVC(kernel='rbf', C=1.0, gamma='scale', random_state=42)
svm.fit(X_train_scaled, y_train)

# Evaluasi
train_acc = svm.score(X_train_scaled, y_train)
test_acc = svm.score(X_test_scaled, y_test)
y_pred = svm.predict(X_test_scaled)

print(f"Training Accuracy: {train_acc:.4f}")
print(f"Test Accuracy: {test_acc:.4f}")
print(f"\nConfusion Matrix:\n{confusion_matrix(y_test, y_pred)}")
print(f"\nJumlah Support Vectors: {len(svm.support_vectors_)}")

Hyperparameter Tuning:

  • C: Regularisasi parameter (C besar = kurang regularisasi)
  • gamma: Kontrol jangkauan kernel RBF
  • kernel: Jenis kernel (linear, rbf, poly, sigmoid)

3.5 K-Nearest Neighbors (KNN)

KNN adalah algoritma instance-based learning yang paling sederhana: prediksi didasarkan pada k neighbors terdekat.

Algoritma:

  1. Hitung jarak antara sampel query dan semua training samples
  2. Ambil k sampel terdekat
  3. Untuk klasifikasi: voting mayoritas
  4. Untuk regresi: rata-rata nilai

Metrik Jarak Populer:

  • Euclidean: \(d = \sqrt{\sum (x_i - y_i)^2}\)
  • Manhattan: \(d = \sum |x_i - y_i|\)
  • Minkowski: \(d = (\sum |x_i - y_i|^p)^{1/p}\)
Code
from sklearn.neighbors import KNeighborsClassifier
from sklearn.datasets import load_wine

# Load data
wine = load_wine()
X = wine.data
y = wine.target

X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)

# Standardisasi (penting karena KNN berbasis jarak)
scaler = StandardScaler()
X_train_scaled = scaler.fit_transform(X_train)
X_test_scaled = scaler.transform(X_test)

# KNN dengan k=5
knn = KNeighborsClassifier(n_neighbors=5)
knn.fit(X_train_scaled, y_train)

# Evaluasi untuk berbagai k
k_values = [1, 3, 5, 7, 9, 15]
accuracies = []

for k in k_values:
    knn_k = KNeighborsClassifier(n_neighbors=k)
    knn_k.fit(X_train_scaled, y_train)
    acc = knn_k.score(X_test_scaled, y_test)
    accuracies.append(acc)
    print(f"k={k:2d}: Akurasi = {acc:.4f}")

best_k = k_values[np.argmax(accuracies)]
print(f"\nk optimal: {best_k} dengan akurasi {max(accuracies):.4f}")

Kelemahan KNN:

  • Lambat saat prediksi (perlu hitung jarak ke semua training samples)
  • Boros memori (menyimpan semua training data)
  • Sensitif terhadap fitur yang tidak relevan
  • Curse of dimensionality (performa buruk di high-dimensional spaces)

3.6 Unsupervised Learning: Clustering

3.6.1 K-Means Clustering

K-Means mengelompokkan data ke k cluster berdasarkan kesamaan.

Algoritma:

  1. Inisialisasi k cluster centers secara random
  2. Assign setiap point ke cluster terdekat
  3. Update cluster center sebagai rata-rata points di cluster
  4. Ulangi hingga converge
Code
from sklearn.cluster import KMeans
from sklearn.datasets import make_blobs

# Buat data dengan 3 clusters alami
X, y_true = make_blobs(n_samples=300, centers=3, n_features=2, random_state=42)

# K-Means
kmeans = KMeans(n_clusters=3, n_init=10, random_state=42)
kmeans.fit(X)

# Evaluasi dengan Silhouette Score
from sklearn.metrics import silhouette_score
silhouette_avg = silhouette_score(X, kmeans.labels_)

print(f"Silhouette Score: {silhouette_avg:.4f}")
print(f"Cluster Centers:\n{kmeans.cluster_centers_}")
print(f"Inertia (sum of squared distances): {kmeans.inertia_:.2f}")

# Prediksi untuk sampel baru
new_point = [[0, 0]]
cluster_pred = kmeans.predict(new_point)
print(f"\nSampel {new_point[0]} diprediksi cluster: {cluster_pred[0]}")

Elbow Method untuk menentukan k optimal:

Code
# Test berbagai nilai k
inertias = []
k_range = range(1, 11)

for k in k_range:
    km = KMeans(n_clusters=k, n_init=10, random_state=42)
    km.fit(X)
    inertias.append(km.inertia_)

# Cari "elbow" point
print("k-Inertia pairs:")
for k, inertia in zip(k_range, inertias):
    print(f"k={k:2d}: {inertia:.2f}")

3.6.2 Hierarchical Clustering

Hierarchical clustering membangun dendogram yang menunjukkan relasi hierarchis antar clusters.

Code
from sklearn.cluster import AgglomerativeClustering
from scipy.cluster.hierarchy import dendrogram, linkage
import matplotlib.pyplot as plt

# Sample data lebih kecil untuk dendrogram
X_small = X[:50]

# Hierarchical Clustering
hierarchical = AgglomerativeClustering(n_clusters=3, linkage='ward')
labels = hierarchical.fit_predict(X_small)

print(f"Hierarchical Clustering Labels: {np.unique(labels)}")
print(f"Cluster distribution: {np.bincount(labels)}")

3.7 Model Comparison Framework

Untuk memilih algoritma yang tepat, kita perlu membandingkan dengan fair.

3.7.1 Confusion Matrix dan Metrics

Confusion Matrix
                Predicted
                Negative  Positive
Actual Negative    TN       FP
       Positive    FN       TP
  • TP (True Positive): Prediksi positif, aktual positif ✓
  • TN (True Negative): Prediksi negatif, aktual negatif ✓
  • FP (False Positive): Prediksi positif, aktual negatif ✗
  • FN (False Negative): Prediksi negatif, aktual positif ✗

Metrics dari Confusion Matrix:

  • Accuracy: \((TP + TN) / (TP + TN + FP + FN)\) - Proporsi prediksi benar
  • Precision: \(TP / (TP + FP)\) - Dari prediksi positif, berapa yang benar?
  • Recall (Sensitivity): \(TP / (TP + FN)\) - Dari kasus positif aktual, berapa yang terdeteksi?
  • F1-Score: \(2 \times \frac{Precision \times Recall}{Precision + Recall}\) - Harmonic mean precision dan recall
Code
from sklearn.metrics import (confusion_matrix, accuracy_score, precision_score,
                            recall_score, f1_score, roc_curve, auc)

# Contoh: Prediksi penyakit (biner)
y_true = [0, 1, 1, 0, 1, 1, 0, 0, 1, 0]
y_pred = [0, 1, 1, 0, 1, 0, 0, 0, 1, 1]

# Confusion Matrix
cm = confusion_matrix(y_true, y_pred)
tn, fp, fn, tp = cm.ravel()

print(f"Confusion Matrix:")
print(f"  TN={tn}, FP={fp}")
print(f"  FN={fn}, TP={tp}")

# Metrics
print(f"\nMetrics:")
print(f"  Accuracy:  {accuracy_score(y_true, y_pred):.4f}")
print(f"  Precision: {precision_score(y_true, y_pred):.4f}")
print(f"  Recall:    {recall_score(y_true, y_pred):.4f}")
print(f"  F1-Score:  {f1_score(y_true, y_pred):.4f}")

3.7.2 Cross-Validation

Cross-validation memberikan estimasi performa yang lebih reliable dengan menggunakan data lebih efisien.

Code
from sklearn.model_selection import cross_val_score
from sklearn.ensemble import RandomForestClassifier
from sklearn.datasets import load_iris

# Data
iris = load_iris()
X, y = iris.data, iris.target

# 5-Fold Cross-Validation
rf = RandomForestClassifier(n_estimators=100, random_state=42)
cv_scores = cross_val_score(rf, X, y, cv=5, scoring='accuracy')

print(f"Cross-validation scores: {cv_scores}")
print(f"Mean CV Score: {cv_scores.mean():.4f} (+/- {cv_scores.std():.4f})")

3.7.3 Model Selection Strategy

Code
from sklearn.model_selection import cross_validate
from sklearn.linear_model import LogisticRegression
from sklearn.ensemble import RandomForestClassifier
from sklearn.svm import SVC
from sklearn.neighbors import KNeighborsClassifier
import pandas as pd

# Prepare data
X, y = make_classification(n_samples=500, n_features=20, n_informative=10,
                          n_classes=2, random_state=42)

# Models to compare
models = {
    'Logistic Regression': LogisticRegression(max_iter=1000),
    'Random Forest': RandomForestClassifier(n_estimators=100),
    'SVM': SVC(kernel='rbf'),
    'KNN': KNeighborsClassifier(n_neighbors=5)
}

# Cross-validation untuk semua models
results = {}

for name, model in models.items():
    scores = cross_val_score(model, X, y, cv=5, scoring='accuracy')
    results[name] = {'Mean': scores.mean(), 'Std': scores.std(), 'Scores': scores}

# Display results
results_df = pd.DataFrame({
    'Model': list(results.keys()),
    'Mean Accuracy': [v['Mean'] for v in results.values()],
    'Std Dev': [v['Std'] for v in results.values()]
})

results_df = results_df.sort_values('Mean Accuracy', ascending=False)
print("\nModel Comparison Results:")
print(results_df.to_string(index=False))

3.8 Kapan Menggunakan Algoritma Mana?

Panduan Pemilihan Algoritma

Regresi Linier / Logistic Regression:

  • Data linear atau hampir linear
  • Interpretabilitas penting
  • Dataset kecil hingga menengah
  • Training speed penting

Decision Trees / Random Forest:

  • Hubungan nonlinier
  • Feature importance penting
  • Data mixed (numeric + categorical)
  • Feature scaling tidak diperlukan

SVM:

  • Data high-dimensional
  • Margin classification penting
  • Kernel methods untuk nonlinier
  • Small to medium datasets

KNN:

  • Local decision boundaries
  • Dataset kecil
  • Training speed bukan prioritas
  • Feature scaling diperlukan

K-Means:

  • Exploratory data analysis
  • Customer segmentation
  • Image compression
  • Clustering tanpa label

3.9 Review Questions

Pertanyaan Konseptual:

  1. Jelaskan perbedaan antara regularisasi L1 dan L2. Kapan masing-masing lebih baik?

  2. Mengapa Decision Tree cenderung overfit? Bagaimana Random Forest mengatasi ini?

  3. Apa kelemahan utama KNN dan bagaimana cara mengatasinya?

  4. Dalam confusion matrix, jika kita concern dengan false positives (FP), metric apa yang harus kita maksimalkan?

  5. Random Forest dan Gradient Boosting sama-sama ensemble methods. Apa perbedaan cara mereka menggabungkan models?

Pertanyaan Praktis:

  1. Anda memiliki dataset dengan 10,000 samples dan 500 features. Algorithm mana yang paling cocok: Linear Regression, SVM dengan RBF kernel, atau KNN dengan k=5? Jelaskan reasoning Anda.

  2. Saat menggunakan SVM dengan dataset Anda, akurasi training = 100% tapi test accuracy = 60%. Apa yang mungkin terjadi dan bagaimana mengatasinya?

  3. Jelaskan mengapa feature scaling WAJIB untuk SVM dan KNN, tapi tidak diperlukan untuk Decision Trees. Berikan contoh numerik jika perlu.

  4. Anda telah melatih Random Forest dengan 100 trees, dan feature importance menunjukkan bahwa 80% importance terkonsentrasi pada 5 fitur saja. Apa implikasinya dan bagaimana Anda menindaklanjuti?

  5. Bandingkan kompleksitas komputasi (training time dan prediction time) antara Logistic Regression, SVM, dan KNN. Algoritma mana yang paling cepat untuk data besar?

3.10 Hands-On Exercise

Klasifikasi Dataset Iris:

Gunakan dataset iris dan bandingkan 4 algoritma (Logistic Regression, Decision Tree, Random Forest, SVM) dengan: 1. 5-fold cross-validation 2. Hitung precision, recall, F1-score untuk setiap model 3. Pilih model terbaik dengan alasan yang jelas 4. Tuning hyperparameter model terbaik untuk meningkatkan performa

Tips:

  • Standardisasi fitur sebelum SVM dan Logistic Regression
  • Gunakan GridSearchCV untuk hyperparameter tuning
  • Visualisasi confusion matrix untuk setiap model

🎯 Key Takeaways

Algoritma klasik tetap menjadi pilihan utama untuk small-medium datasets dengan interpretability requirements

Regularisasi (L1/L2) adalah teknik essential untuk mencegah overfitting pada model linier

Tree-based models (Decision Trees, Random Forest) tidak memerlukan feature scaling dan bisa handle nonlinear relationships

SVM sangat powerful untuk high-dimensional data dengan proper kernel selection dan hyperparameter tuning

KNN simple tapi lambat untuk prediction; scaling dan dimensionality reduction sangat penting

Metrics selection (accuracy, precision, recall, F1) harus disesuaikan dengan business requirements dan class imbalance

Cross-validation memberikan estimasi performa yang lebih reliable daripada single train-test split

Model selection harus mempertimbangkan: data size, dimensionality, interpretability needs, dan computational constraints