Machine Learning (ML) telah berkembang pesat dalam berbagai bidang, termasuk pengenalan pola, pemodelan prediktif, dan pengambilan keputusan berbasis data. Model pembelajaran mesin yang kompleks, seperti regresi linier berganda, regresi logistik, serta model berbasis jaringan saraf tiruan, sering kali menghadapi permasalahan yang berkaitan dengan overfitting—yakni kondisi di mana model belajar terlalu spesifik terhadap data pelatihan sehingga kehilangan kemampuan generalisasi pada data baru (Bishop, 2006).
Salah satu pendekatan utama untuk mengatasi overfitting adalah regularisasi, sebuah teknik yang menambahkan penalti pada kompleksitas model untuk mencegah koefisien atau parameter model menjadi terlalu besar. Regularisasi sangat penting terutama dalam situasi di mana jumlah fitur lebih besar dari jumlah observasi (high-dimensional data) atau ketika terdapat multikolinearitas antar prediktor (Hastie, Tibshirani, & Friedman, 2009). Regularisasi memungkinkan model tetap sederhana dan menghindari eksploitasi kebisingan (noise) dalam data yang dapat mengarah pada kesalahan prediksi yang besar.
Overfitting dalam ML terjadi ketika model sangat cocok terhadap data pelatihan, tetapi tidak mampu bekerja dengan baik pada data uji. Ini biasanya terjadi karena model terlalu kompleks dan menangkap pola acak dalam data yang seharusnya tidak digeneralisasi (Goodfellow, Bengio, & Courville, 2016). Dalam konteks bias-variance tradeoff, model dengan bias rendah dan varians tinggi cenderung mengalami overfitting, sementara model dengan bias tinggi dan varians rendah mengalami underfitting. Regularisasi bertujuan untuk mencapai keseimbangan antara bias dan varians dengan mengontrol kompleksitas model.
Dalam konteks ML, generalization performance merupakan aspek krusial karena model harus mampu membuat prediksi akurat pada data yang belum pernah dilihat sebelumnya. Regularisasi memastikan bahwa model tidak hanya cocok terhadap data pelatihan tetapi juga dapat bekerja dengan baik pada data uji atau data dunia nyata. Hal ini terutama berguna dalam high-dimensional data, seperti yang ditemukan dalam bioinformatika (Ng, 2004), keuangan (Friedman et al., 2010), dan pengenalan gambar (Krizhevsky, Sutskever, & Hinton, 2012).
Terdapat tiga metode regularasisasi yang umumnya digunakan yaitu Ridge Regression, Lasso Regression, dan Elastic Net.
Ridge Regression menambahkan penalti pada jumlah kuadrat dari koefisien regresi, yang secara matematis dinyatakan sebagai berikut:
\[\begin{equation} \min_{\beta} \sum_{i=1}^{n} (y_i - X_i\beta)^2 + \lambda \sum_{j=1}^{p} \beta_j^2 \label{eq:ridge} \end{equation}\]
Dimana \(\lambda\) adalah parameter regularisasi yang mengontrol tingkat penalti. Ridge Regression membantu menangani multikolinearitas dan memastikan koefisien tetap kecil tetapi tidak menjadi nol (Hoerl & Kennard, 1970). Lihat Persamaan \(\eqref{eq:ridge}\) untuk detail formulasi.
Lasso (Least Absolute Shrinkage and Selection Operator) menggunakan penalti berbasis norma L1:
\[\begin{equation} \min_{\beta} \sum_{i=1}^{n} (y_i - X_i\beta)^2 + \lambda \sum_{j=1}^{p} |\beta_j| \label{eq:lasso} \end{equation}\]
Regularisasi L1 menyebabkan beberapa koefisien regresi menjadi nol, sehingga Lasso dapat digunakan untuk seleksi fitur (Tibshirani, 1996). Lihat Persamaan \(\eqref{eq:lasso}\) untuk lebih jelasnya.
Elastic Net menggabungkan penalti L1 dan L2 untuk mengatasi kelemahan masing-masing metode. Regularisasi ini sangat bermanfaat dalam situasi di mana jumlah fitur lebih banyak daripada jumlah observasi (Zou & Hastie, 2005).
\[\begin{equation} \min_{\beta} \sum_{i=1}^{n} (y_i - X_i\beta)^2 + \lambda_1 \sum_{j=1}^{p} |\beta_j| + \lambda_2 \sum_{j=1}^{p} \beta_j^2 \label{eq:elasticnet} \end{equation}\]
Elastic Net sangat berguna ketika terdapat korelasi tinggi antara fitur-fitur dalam dataset. Persamaan \(\eqref{eq:elasticnet}\) menunjukkan formulasi matematisnya.
Ridge Regression adalah metode regresi yang menambahkan penalti L2 terhadap koefisien regresi (Hoerl & Kennard, 1970). Model regresi biasa didefinisikan sebagai:
\[\begin{equation} Y = X\beta + \epsilon \label{eq:regresi} \end{equation}\]
dengan \(X\) adalah matriks prediktor, \(\beta\) adalah vektor koefisien, dan \(\epsilon\) adalah error.
Tujuan dari ilustrasi ini adalah untuk menunjukkan bagaimana regularisasi Ridge Regression bekerja dalam mengontrol nilai koefisien regresi dengan menambahkan penalti terhadap besar koefisien. Dengan membandingkan Sum Squared Residual (SSR) dan SSR Ridge, kita dapat melihat pengaruh nilai lambda terhadap model.
Misalkan kita punya pengamatan berikut:
library(knitr)
library(dplyr)
library(ggplot2)
X <- c(2, 3, 4, 6)
Y <- c(4, 3.5, 4.5, 5)
beta_0_hat <- 3.07
beta_1_values <- seq(-0.2, 0.6, by = 0.1)
lambda_values <- c(0, 30, 40, 50, 60, 70)
ssr_values <- sapply(beta_1_values, function(beta_1) {
y_hat <- beta_0_hat + beta_1 * X # Prediksi model
sum((Y - y_hat) ^ 2) # SSR
})
ssr_df <- data.frame(Beta_1 = beta_1_values, SSR = ssr_values)
kable(ssr_df, caption = "Tabel Sum Squared Residual (SSR) untuk
Setiap $\\beta_1$", escape = FALSE)
| Beta_1 | SSR |
|---|---|
| -0.2 | 17.5996 |
| -0.1 | 11.5596 |
| 0.0 | 6.8196 |
| 0.1 | 3.3796 |
| 0.2 | 1.2396 |
| 0.3 | 0.3996 |
| 0.4 | 0.8596 |
| 0.5 | 2.6196 |
| 0.6 | 5.6796 |
ridge_results <- expand.grid(Beta_1 = beta_1_values, Lambda = lambda_values) %>%
mutate(SSR = rep(ssr_values, times = length(lambda_values)),
SSR_Ridge = SSR + Lambda * Beta_1^2)
kable(ridge_results, caption = "Tabel SSR Ridge untuk Berbagai
Nilai $\\lambda$", escape = FALSE)
| Beta_1 | Lambda | SSR | SSR_Ridge |
|---|---|---|---|
| -0.2 | 0 | 17.5996 | 17.5996 |
| -0.1 | 0 | 11.5596 | 11.5596 |
| 0.0 | 0 | 6.8196 | 6.8196 |
| 0.1 | 0 | 3.3796 | 3.3796 |
| 0.2 | 0 | 1.2396 | 1.2396 |
| 0.3 | 0 | 0.3996 | 0.3996 |
| 0.4 | 0 | 0.8596 | 0.8596 |
| 0.5 | 0 | 2.6196 | 2.6196 |
| 0.6 | 0 | 5.6796 | 5.6796 |
| -0.2 | 30 | 17.5996 | 18.7996 |
| -0.1 | 30 | 11.5596 | 11.8596 |
| 0.0 | 30 | 6.8196 | 6.8196 |
| 0.1 | 30 | 3.3796 | 3.6796 |
| 0.2 | 30 | 1.2396 | 2.4396 |
| 0.3 | 30 | 0.3996 | 3.0996 |
| 0.4 | 30 | 0.8596 | 5.6596 |
| 0.5 | 30 | 2.6196 | 10.1196 |
| 0.6 | 30 | 5.6796 | 16.4796 |
| -0.2 | 40 | 17.5996 | 19.1996 |
| -0.1 | 40 | 11.5596 | 11.9596 |
| 0.0 | 40 | 6.8196 | 6.8196 |
| 0.1 | 40 | 3.3796 | 3.7796 |
| 0.2 | 40 | 1.2396 | 2.8396 |
| 0.3 | 40 | 0.3996 | 3.9996 |
| 0.4 | 40 | 0.8596 | 7.2596 |
| 0.5 | 40 | 2.6196 | 12.6196 |
| 0.6 | 40 | 5.6796 | 20.0796 |
| -0.2 | 50 | 17.5996 | 19.5996 |
| -0.1 | 50 | 11.5596 | 12.0596 |
| 0.0 | 50 | 6.8196 | 6.8196 |
| 0.1 | 50 | 3.3796 | 3.8796 |
| 0.2 | 50 | 1.2396 | 3.2396 |
| 0.3 | 50 | 0.3996 | 4.8996 |
| 0.4 | 50 | 0.8596 | 8.8596 |
| 0.5 | 50 | 2.6196 | 15.1196 |
| 0.6 | 50 | 5.6796 | 23.6796 |
| -0.2 | 60 | 17.5996 | 19.9996 |
| -0.1 | 60 | 11.5596 | 12.1596 |
| 0.0 | 60 | 6.8196 | 6.8196 |
| 0.1 | 60 | 3.3796 | 3.9796 |
| 0.2 | 60 | 1.2396 | 3.6396 |
| 0.3 | 60 | 0.3996 | 5.7996 |
| 0.4 | 60 | 0.8596 | 10.4596 |
| 0.5 | 60 | 2.6196 | 17.6196 |
| 0.6 | 60 | 5.6796 | 27.2796 |
| -0.2 | 70 | 17.5996 | 20.3996 |
| -0.1 | 70 | 11.5596 | 12.2596 |
| 0.0 | 70 | 6.8196 | 6.8196 |
| 0.1 | 70 | 3.3796 | 4.0796 |
| 0.2 | 70 | 1.2396 | 4.0396 |
| 0.3 | 70 | 0.3996 | 6.6996 |
| 0.4 | 70 | 0.8596 | 12.0596 |
| 0.5 | 70 | 2.6196 | 20.1196 |
| 0.6 | 70 | 5.6796 | 30.8796 |
plot_data <- data.frame()
for (beta_1 in beta_1_values) {
y_pred <- beta_0_hat + beta_1 * X
temp_data <- data.frame(X, Y_pred = y_pred, Beta_1 = as.factor(beta_1))
plot_data <- rbind(plot_data, temp_data)
}
ggplot(plot_data, aes(x = X, y = Y_pred, color = factor(Beta_1))) +
geom_line(size=0.5) +
geom_point(data = data.frame(X, Y), aes(x = X, y = Y),
color = "black", size = 3) +
labs(title = expression("Perubahan Garis Regresi untuk Setiap"~beta[1]),
x = "X", y = "Y", color = expression(beta[1])) +
theme_bw()
ggplot(ridge_results, aes(x = Beta_1, y = SSR_Ridge, color = factor(Lambda))) +
geom_line(size=0.5) +
geom_point() +
labs(title = expression(beta[1] ~ " vs SSR
Ridge untuk Berbagai Nilai " ~ lambda),
x = expression(beta[1]), y = "SSR", color = expression(lambda)) +
theme_bw()
Plot ini menunjukkan bahwa nilai optimal untuk \(\beta_1\) tidak pernah mencapai nilai nol untuk semua nilai \(\lambda\) .
Fungsi yang diminimalkan dalam Ridge Regression adalah:
\[\begin{equation} J(\beta) = \sum_{i=1}^{n} (y_i - \hat{y}_i)^2 + \lambda \sum_{j=1}^{p} \beta_j^2. \label{eq:ridge1} \end{equation}\]
1. Mendefinisikan Fungsi Objektif
Fungsi yang diminimalkan dalam Ridge Regression adalah:
\[\begin{equation} J(\beta) = \sum_{i=1}^{n} (y_i - \hat{y}_i)^2 + \lambda \sum_{j=1}^{p} \beta_j^2. \label{eq:ridge3} \end{equation}\]
Karena dalam regresi linier,
\[\begin{equation} \hat{y} = X \beta, \label{eq:ridge4} \end{equation}\]
maka fungsi objektif dapat ditulis dalam bentuk matriks sebagai:
\[\begin{equation} J(\beta) = (y - X\beta)^T (y - X\beta) + \lambda \beta^T \beta. \label{eq:ridge5} \end{equation}\]
2. Mencari Turunan Pertama \(\frac{\partial J}{\partial \beta}\)
Menggunakan aturan turunan dalam aljabar matriks:
\[\begin{equation} \frac{\partial}{\partial \beta} (y - X\beta)^T (y - X\beta) = -2X^T(y - X\beta). \label{eq:ridge6} \end{equation}\]
Untuk regularisasi:
\[\begin{equation} \frac{\partial}{\partial \beta} \lambda \beta^T \beta = 2\lambda \beta. \label{eq:ridge7} \end{equation}\]
Sehingga, turunan pertama dari \(J(\beta)\) adalah:
\[\begin{equation} \frac{\partial J}{\partial \beta} = -2X^T(y - X\beta) + 2\lambda \beta. \label{eq:ridge8} \end{equation}\]
3. Menyamakan Turunan dengan Nol
Menyusun ulang persamaan: \[\begin{equation} X^T X\beta - X^T y + \lambda \beta = 0. \label{eq:ridge9} \end{equation}\]
Maka:
\[\begin{equation} (X^T X + \lambda I)\beta = X^T y. \label{eq:ridge10} \end{equation}\]
4. Solusi Estimasi Parameter \(\hat{\beta}\)
Mengalikan kedua sisi dengan invers matriks \((X^T X + \lambda I)^{-1}\):
\[\begin{equation} \hat{\beta} = (X^T X + \lambda I)^{-1} X^T y. \label{eq:ridge10} \end{equation}\]
Tujuan dari ilustrasi ini adalah untuk menunjukkan bagaimana Ridge Regression dapat menangani multicollinearity lebih baik dibandingkan OLS (Ordinary Least Squares) ketika terdapat korelasi tinggi antara variabel prediktor dalam dataset besar.
library(MASS)
library(glmnet)
library(ggplot2)
library(dplyr)
set.seed(123)
n <- 500 # Jumlah sampel
p <- 50 # Jumlah prediktor
# Membuat matriks kovarians dengan korelasi tinggi
Sigma <- matrix(0.9, nrow = p, ncol = p) + diag(0.1, p)
X <- mvrnorm(n, mu = rep(0, p), Sigma = Sigma) # Matriks prediktor
# Koefisien sebenarnya
beta_true <- runif(p, -2, 2)
y <- X %*% beta_true + rnorm(n, sd = 5) # Variabel respon
data <- data.frame(y, X)
# Model OLS
ols_model <- lm(y ~ ., data = data)
ols_coeff <- coef(ols_model)[-1] # Mengabaikan intercept
# Model Ridge Regression
x_matrix <- as.matrix(data[, -1])
y_vector <- data$y
ridge_model <- glmnet(x_matrix, y_vector, alpha = 0) # alpha = 0 untuk Ridge
cv_ridge <- cv.glmnet(x_matrix, y_vector, alpha = 0) # Cross-validation untuk lambda optimal
ridge_coeff <- coef(cv_ridge, s = "lambda.min")[-1] # Koefisien dengan lambda optimal
Plot Koefisien Ridge Regression terhadap \(\lambda\)
par(mfrow = c(1,1)) # Pastikan hanya ada satu plot dalam satu area
plot(ridge_model, xvar = "lambda", label = TRUE, cex.axis = 0.7, las = 2) # Menyesuaikan ukuran label
Interpretasi Plot Koefisien Ridge Regression terhadap Lambda
Shrinkage Koefisien saat Lambda Meningkat
Multicollinearity Terkendali
Lambda Besar vs. Lambda Kecil
Kesimpulan
Cross-Validation Ridge Regression
plot(cv_ridge)
Interpretasi Plot Cross-Validation Ridge Regression
Makna dari Plot Plot ini merupakan hasil cross-validation untuk memilih nilai lambda optimal dalam Ridge Regression. Sumbu x menunjukkan log(lambda), sedangkan sumbu y menunjukkan Mean Squared Error (MSE) untuk setiap nilai lambda yang diuji.
Pola yang Terlihat dalam Plot
Kesimpulan dari Plot - Pemilihan lambda optimal sangat penting untuk mendapatkan keseimbangan antara overfitting dan underfitting. - Lambda terlalu kecil → Model terlalu fleksibel, rawan overfitting. - Lambda terlalu besar → Model menjadi terlalu sederhana (underfitting). - Nilai optimal lambda dipilih berdasarkan titik MSE terendah, yang memberikan generalization terbaik terhadap data baru.
Plot Mean Squared Error untuk Berbagai \(\alpha\)
lambda_seq <- 10^seq(-5, 2, length.out = 100)
cv_fit_1 <- cv.glmnet(x_matrix, y_vector, alpha = 1, lambda = lambda_seq)
cv_fit_05 <- cv.glmnet(x_matrix, y_vector, alpha = 0.5, lambda = lambda_seq)
cv_fit_0 <- cv.glmnet(x_matrix, y_vector, alpha = 0, lambda = lambda_seq)
plot(log(cv_fit_1$lambda), cv_fit_1$cvm, col = "red", pch = 19,
xlab = "log(Lambda)", ylab = "Mean-Squared Error")
points(log(cv_fit_05$lambda), cv_fit_05$cvm, col = "gray", pch = 19)
points(log(cv_fit_0$lambda), cv_fit_0$cvm, col = "blue", pch = 19)
legend("topright", legend = c("alpha=1", "alpha=.5", "alpha 0"),
col = c("red", "gray", "blue"), pch = 19)
Interpretasi Plot Cross-Validation Elastic Net Regression
Makna dari Plot Plot ini menunjukkan hasil cross-validation untuk memilih nilai lambda optimal dalam Elastic Net Regression. Tiga garis berbeda menunjukkan hasil untuk alpha = 1 (Lasso, merah), alpha = 0.5 (Elastic Net, abu-abu), dan alpha = 0 (Ridge, biru).
Sumbu x menunjukkan log(lambda), sedangkan sumbu y menunjukkan Mean Squared Error (MSE) untuk setiap nilai lambda yang diuji.
Pola yang Terlihat dalam Plot
Kesimpulan dari Plot - Elastic Net (alpha = 0.5, abu-abu) memberikan kompromi antara Ridge dan Lasso, menghindari kelemahan masing-masing metode. - Pemilihan lambda optimal dilakukan dengan mencari titik MSE minimum pada masing-masing metode. - Lasso (alpha = 1) cocok untuk seleksi fitur, tetapi bisa menyebabkan peningkatan MSE lebih cepat saat lambda meningkat. - Ridge (alpha = 0) lebih stabil terhadap multicollinearity, tetapi tidak melakukan seleksi fitur.
Perbandingan Koefisien OLS vs Ridge
comparison <- data.frame(
Predictor = paste0("X", 1:p),
OLS = ols_coeff,
Ridge = ridge_coeff
)
comparison_long <- comparison %>% tidyr::pivot_longer(cols = c("OLS", "Ridge"),
names_to = "Model", values_to = "Coefficient")
# Visualisasi perbandingan koefisien
ggplot(comparison_long, aes(x = Predictor, y = Coefficient, fill = Model)) +
geom_bar(stat = "identity", position = "dodge") +
theme_minimal() +
labs(title = "Perbandingan Koefisien OLS vs Ridge Regression",
x = "Predictor",
y = "Estimated Coefficient") +
theme(axis.text.x = element_text(angle = 90, hjust = 1))
Interpretasi Hasil - Plot koefisien Ridge Regression terhadap lambda menunjukkan bagaimana koefisien regresi mengalami shrinkage seiring peningkatan lambda. - Plot Cross-Validation Ridge Regression membantu menentukan lambda optimal yang meminimalkan kesalahan prediksi. - Plot MSE untuk berbagai alpha menunjukkan bagaimana Lasso, Ridge, dan Elastic Net berperforma. - Model OLS menunjukkan koefisien yang sangat fluktuatif karena efek multicollinearity. - Ridge Regression menekan besar koefisien, membuat model lebih stabil dan mengurangi varians.
Kesimpulan Ketika terdapat multicollinearity, OLS menghasilkan koefisien yang tidak stabil. Sebaliknya, Ridge Regression memberikan solusi yang lebih robust dengan mengecilkan koefisien yang terlalu besar. Ini menunjukkan bagaimana regularisasi dapat meningkatkan stabilitas model dalam dataset dengan banyak prediktor yang berkorelasi tinggi.
Lasso Regression (Least Absolute Shrinkage and Selection Operator) adalah metode yang menggunakan penalti L1, yang memungkinkan beberapa koefisien regresi menjadi nol (Tibshirani, 1996):
\[\begin{equation} J(\beta) = \sum_{i=1}^{n} (y_i - \hat{y}_i)^2 + \lambda \sum_{j=1}^{p} |\beta_j|. \label{eq:Lasso1} \end{equation}\]
Lasso Regression (Least Absolute Shrinkage and Selection Operator) adalah metode regresi dengan regularisasi L1 yang memungkinkan beberapa koefisien regresi menjadi nol (Tibshirani, 1996). Fungsi objektif yang diminimalkan adalah:
\[\begin{equation} J(\beta) = \sum_{i=1}^{n} (y_i - \hat{y}_i)^2 + \lambda \sum_{j=1}^{p} |\beta_j|. \label{eq:Lasso2} \end{equation}\]
Karena dalam regresi linier,
\[\begin{equation} \hat{y} = X \beta, \label{eq:Lasso3} \end{equation}\]
maka fungsi objektif dapat ditulis ulang dalam bentuk matriks sebagai:
\[\begin{equation} J(\beta) = (y - X\beta)^T (y - X\beta) + \lambda \sum_{j=1}^{p} |\beta_j|. \label{eq:Lasso4} \end{equation}\]
Berbeda dengan Ridge Regression, Lasso Regression menggunakan penalti L1, yang tidak memiliki turunan yang mudah dihitung karena keberadaan fungsi nilai absolut. Mari kita hitung gradiennya secara komponen:
1. Turunan Pertama \(\frac{\partial J}{\partial \beta}\)
Turunan dari bagian pertama:
\[\begin{equation} \frac{\partial}{\partial \beta} (y - X\beta)^T (y - X\beta) = -2X^T(y - X\beta). \label{eq:Lasso5} \end{equation}\]
Turunan dari penalti L1 berbeda untuk setiap elemen \(\beta_j\):
\[\begin{equation} \frac{\partial}{\partial \beta_j} \lambda |\beta_j| = \lambda \cdot \text{sign}(\beta_j), \label{eq:Lasso6} \end{equation}\]
dengan:
\[\begin{equation} \text{sign}(\beta_j) = \begin{cases} 1, & \text{jika } \beta_j > 0 \\ -1, & \text{jika } \beta_j < 0 \\ 0, & \text{jika } \beta_j = 0 \end{cases}. \label{eq:Lasso7} \end{equation}\]
Sehingga, turunan pertama dari \(J(\beta)\) adalah:
\[\begin{equation} \frac{\partial J}{\partial \beta} = -2X^T(y - X\beta) + \lambda \cdot \text{sign}(\beta). \label{eq:Lasso8} \end{equation}\]
2. Menyamakan dengan Nol untuk Solusi Optimal
Menyusun ulang:
\[\begin{equation} X^T X\beta - X^T y + \frac{\lambda}{2} \text{sign}(\beta) = 0. \label{eq:Lasso1} \end{equation}\]
Karena fungsi nilai absolut tidak terdiferensiasi di \(\beta_j = 0\), solusi parameter harus ditemukan dengan metode numerik, seperti Coordinate Descent atau Least Angle Regression (LARS).
Algoritma Coordinate Descent sering digunakan untuk menghitung solusi Lasso. Langkah-langkahnya adalah:
Tujuan dari ilustrasi ini adalah untuk menunjukkan bagaimana regularisasi Lasso Regression bekerja dalam mengontrol nilai koefisien regresi dengan menambahkan penalti terhadap besar koefisien. Dengan membandingkan Sum Squared Residual (SSR) dan SSR Lasso, kita dapat melihat pengaruh nilai lambda terhadap model.
Misalkan kita punya pengamatan berikut:
X <- c(2, 3, 4, 6)
Y <- c(4, 3.5, 4.5, 5)
beta_0_hat <- 3.07
beta_1_values <- seq(-0.2, 0.6, by = 0.1)
lambda_values <- c(0, 30, 40, 50, 60, 70)
ssr_values <- sapply(beta_1_values, function(beta_1) {
y_hat <- beta_0_hat + beta_1 * X
sum((Y - y_hat) ^ 2)
})
ssr_df <- data.frame(Beta_1 = beta_1_values, SSR = ssr_values)
kable(ssr_df, caption = "Tabel Sum Squared Residual (SSR)
untuk Setiap $\\beta_1$", escape = FALSE)
| Beta_1 | SSR |
|---|---|
| -0.2 | 17.5996 |
| -0.1 | 11.5596 |
| 0.0 | 6.8196 |
| 0.1 | 3.3796 |
| 0.2 | 1.2396 |
| 0.3 | 0.3996 |
| 0.4 | 0.8596 |
| 0.5 | 2.6196 |
| 0.6 | 5.6796 |
lasso_results <- expand.grid(Beta_1 = beta_1_values, Lambda = lambda_values) %>%
mutate(SSR = rep(ssr_values, times = length(lambda_values)),
SSR_Lasso = SSR + Lambda * abs(Beta_1))
kable(lasso_results, caption = "Tabel SSR Lasso untuk Berbagai
Nilai $\\lambda$", escape = FALSE)
| Beta_1 | Lambda | SSR | SSR_Lasso |
|---|---|---|---|
| -0.2 | 0 | 17.5996 | 17.5996 |
| -0.1 | 0 | 11.5596 | 11.5596 |
| 0.0 | 0 | 6.8196 | 6.8196 |
| 0.1 | 0 | 3.3796 | 3.3796 |
| 0.2 | 0 | 1.2396 | 1.2396 |
| 0.3 | 0 | 0.3996 | 0.3996 |
| 0.4 | 0 | 0.8596 | 0.8596 |
| 0.5 | 0 | 2.6196 | 2.6196 |
| 0.6 | 0 | 5.6796 | 5.6796 |
| -0.2 | 30 | 17.5996 | 23.5996 |
| -0.1 | 30 | 11.5596 | 14.5596 |
| 0.0 | 30 | 6.8196 | 6.8196 |
| 0.1 | 30 | 3.3796 | 6.3796 |
| 0.2 | 30 | 1.2396 | 7.2396 |
| 0.3 | 30 | 0.3996 | 9.3996 |
| 0.4 | 30 | 0.8596 | 12.8596 |
| 0.5 | 30 | 2.6196 | 17.6196 |
| 0.6 | 30 | 5.6796 | 23.6796 |
| -0.2 | 40 | 17.5996 | 25.5996 |
| -0.1 | 40 | 11.5596 | 15.5596 |
| 0.0 | 40 | 6.8196 | 6.8196 |
| 0.1 | 40 | 3.3796 | 7.3796 |
| 0.2 | 40 | 1.2396 | 9.2396 |
| 0.3 | 40 | 0.3996 | 12.3996 |
| 0.4 | 40 | 0.8596 | 16.8596 |
| 0.5 | 40 | 2.6196 | 22.6196 |
| 0.6 | 40 | 5.6796 | 29.6796 |
| -0.2 | 50 | 17.5996 | 27.5996 |
| -0.1 | 50 | 11.5596 | 16.5596 |
| 0.0 | 50 | 6.8196 | 6.8196 |
| 0.1 | 50 | 3.3796 | 8.3796 |
| 0.2 | 50 | 1.2396 | 11.2396 |
| 0.3 | 50 | 0.3996 | 15.3996 |
| 0.4 | 50 | 0.8596 | 20.8596 |
| 0.5 | 50 | 2.6196 | 27.6196 |
| 0.6 | 50 | 5.6796 | 35.6796 |
| -0.2 | 60 | 17.5996 | 29.5996 |
| -0.1 | 60 | 11.5596 | 17.5596 |
| 0.0 | 60 | 6.8196 | 6.8196 |
| 0.1 | 60 | 3.3796 | 9.3796 |
| 0.2 | 60 | 1.2396 | 13.2396 |
| 0.3 | 60 | 0.3996 | 18.3996 |
| 0.4 | 60 | 0.8596 | 24.8596 |
| 0.5 | 60 | 2.6196 | 32.6196 |
| 0.6 | 60 | 5.6796 | 41.6796 |
| -0.2 | 70 | 17.5996 | 31.5996 |
| -0.1 | 70 | 11.5596 | 18.5596 |
| 0.0 | 70 | 6.8196 | 6.8196 |
| 0.1 | 70 | 3.3796 | 10.3796 |
| 0.2 | 70 | 1.2396 | 15.2396 |
| 0.3 | 70 | 0.3996 | 21.3996 |
| 0.4 | 70 | 0.8596 | 28.8596 |
| 0.5 | 70 | 2.6196 | 37.6196 |
| 0.6 | 70 | 5.6796 | 47.6796 |
plot_data <- data.frame()
for (beta_1 in beta_1_values) {
y_pred <- beta_0_hat + beta_1 * X
temp_data <- data.frame(X, Y_pred = y_pred, Beta_1 = as.factor(beta_1))
plot_data <- rbind(plot_data, temp_data)
}
ggplot(plot_data, aes(x = X, y = Y_pred, color = factor(Beta_1))) +
geom_line(size=0.5) +
geom_point(data = data.frame(X, Y), aes(x = X, y = Y),
color = "black", size = 3) +
labs(title = expression("Perubahan Garis Regresi untuk Setiap"~beta[1]),
x = "X", y = "Y", color = expression(beta[1])) +
theme_bw()
ggplot(lasso_results, aes(x = Beta_1, y = SSR_Lasso, color = factor(Lambda))) +
geom_line(size=0.5) +
geom_point() +
labs(title = expression(beta[1] ~ " vs SSR Lasso untuk
Berbagai Nilai " ~ lambda),
x = expression(beta[1]), y = "SSR", color = expression(lambda)) +
theme_bw()
Plot ini menunjukkan bahwa nilai optimal untuk \(\beta_1\) dapat mencapai nol untuk beberapa nilai \(\lambda\).
Lasso tidak memiliki solusi analitik seperti Ridge. Estimasi parameter dilakukan menggunakan Coordinate Descent Algorithm.
Tujuan Ilustrasi Tujuan dari ilustrasi ini adalah untuk menunjukkan bagaimana Lasso Regression dapat menangani multicollinearity lebih baik dibandingkan OLS (Ordinary Least Squares) ketika terdapat korelasi tinggi antara variabel prediktor dalam dataset besar.
Simulasi Data dengan Multicollinearity
library(MASS)
library(glmnet)
library(ggplot2)
library(dplyr)
set.seed(123)
n <- 500 # Jumlah sampel
p <- 50 # Jumlah prediktor
# Membuat matriks kovarians dengan korelasi tinggi
Sigma <- matrix(0.9, nrow = p, ncol = p) + diag(0.1, p)
X <- mvrnorm(n, mu = rep(0, p), Sigma = Sigma) # Matriks prediktor
# Koefisien sebenarnya
beta_true <- runif(p, -2, 2)
y <- X %*% beta_true + rnorm(n, sd = 5) # Variabel respon
data <- data.frame(y, X)
Estimasi Model OLS dan Lasso Regression
# Model OLS
ols_model <- lm(y ~ ., data = data)
ols_coeff <- coef(ols_model)[-1] # Mengabaikan intercept
# Model Lasso Regression
x_matrix <- as.matrix(data[, -1])
y_vector <- data$y
lasso_model <- glmnet(x_matrix, y_vector, alpha = 1) # alpha = 1 untuk Lasso
cv_lasso <- cv.glmnet(x_matrix, y_vector, alpha = 1) # Cross-validation untuk lambda optimal
lasso_coeff <- coef(cv_lasso, s = "lambda.min")[-1] # Koefisien dengan lambda optimal
Visualisasi Model Lasso Regression
Plot Koefisien Lasso Regression terhadap Lambda
par(mfrow = c(1,1)) # Pastikan hanya ada satu plot dalam satu area
plot(lasso_model, xvar = "lambda", label = TRUE, cex.axis = 0.7, las = 2) # Menyesuaikan ukuran label
Interpretasi Plot Koefisien Lasso Regression terhadap Lambda
Cross-Validation Lasso Regression
plot(cv_lasso)
Interpretasi Plot Cross-Validation Lasso Regression
Plot Mean Squared Error untuk Berbagai Alpha
lambda_seq <- 10^seq(-5, 2, length.out = 100)
cv_fit_1 <- cv.glmnet(x_matrix, y_vector, alpha = 1, lambda = lambda_seq)
cv_fit_05 <- cv.glmnet(x_matrix, y_vector, alpha = 0.5, lambda = lambda_seq)
cv_fit_0 <- cv.glmnet(x_matrix, y_vector, alpha = 0, lambda = lambda_seq)
plot(log(cv_fit_1$lambda), cv_fit_1$cvm, col = "red", pch = 19,
xlab = "log(Lambda)", ylab = "Mean-Squared Error")
points(log(cv_fit_05$lambda), cv_fit_05$cvm, col = "gray", pch = 19)
points(log(cv_fit_0$lambda), cv_fit_0$cvm, col = "blue", pch = 19)
legend("topright", legend = c("alpha=1 (Lasso)", "alpha=.5 (Elastic Net)",
"alpha 0 (Ridge)"), col = c("red", "gray", "blue"), pch = 19)
Interpretasi Perbandingan Alpha dalam Cross-Validation
Perbandingan Koefisien OLS vs Lasso
comparison <- data.frame(
Predictor = paste0("X", 1:p),
OLS = ols_coeff,
Lasso = lasso_coeff
)
comparison_long <- comparison %>% tidyr::pivot_longer(cols = c("OLS", "Lasso"),
names_to = "Model", values_to = "Coefficient")
# Visualisasi perbandingan koefisien
ggplot(comparison_long, aes(x = Predictor, y = Coefficient, fill = Model)) +
geom_bar(stat = "identity", position = "dodge") +
theme_minimal() +
labs(title = "Perbandingan Koefisien OLS vs Lasso Regression",
x = "Predictor",
y = "Estimated Coefficient") +
theme(axis.text.x = element_text(angle = 90, hjust = 1))
Kesimpulan
Elastic Net menggabungkan penalti L1 dan L2 dengan parameter keseimbangan \(\alpha\) (Zou & Hastie, 2005):
\[\begin{equation} J(\beta) = \sum_{i=1}^{n} (y_i - \hat{y}_i)^2 + \lambda_1 \sum_{j=1}^{p} |\beta_j| + \lambda_2 \sum_{j=1}^{p} \beta_j^2. \label{eq:Elastic1} \end{equation}\]
Elastic Net menggabungkan penalti L1 dan L2 dengan parameter keseimbangan \(\alpha\) (Zou & Hastie, 2005). Fungsi objektif yang diminimalkan adalah:
\[\begin{equation} J(\beta) = \sum_{i=1}^{n} (y_i - \hat{y}_i)^2 + \lambda_1 \sum_{j=1}^{p} |\beta_j| + \lambda_2 \sum_{j=1}^{p} \beta_j^2. \label{eq:ElasticNet2} \end{equation}\]
Karena dalam regresi linier,
\[\begin{equation} \hat{y} = X \beta, \label{eq:Elastic3} \end{equation}\]
maka fungsi objektif dapat ditulis ulang dalam bentuk matriks sebagai:
\[\begin{equation} J(\beta) = (y - X\beta)^T (y - X\beta) + \lambda_1 \sum_{j=1}^{p} |\beta_j| + \lambda_2 \beta^T \beta. \label{eq:Elastic4} \end{equation}\]
Elastic Net merupakan kombinasi dari Ridge dan Lasso, sehingga turunan pertamanya terdiri dari dua komponen.
1. Turunan Pertama \(\frac{\partial J}{\partial \beta}\)
Turunan dari bagian pertama:
\[\begin{equation} \frac{\partial}{\partial \beta} (y - X\beta)^T (y - X\beta) = -2X^T(y - X\beta). \label{eq:Elastic5} \end{equation}\]
Turunan dari penalti L1 berbeda untuk setiap elemen \(\beta_j\):
\[\begin{equation} \frac{\partial}{\partial \beta_j} \lambda_1 |\beta_j| = \lambda_1 \cdot \text{sign}(\beta_j), \label{eq:Elastic6} \end{equation}\]
dengan:
\[\begin{equation} \text{sign}(\beta_j) = \begin{cases} 1, & \text{jika } \beta_j > 0 \\ -1, & \text{jika } \beta_j < 0 \\ 0, & \text{jika } \beta_j = 0 \end{cases}. \end{equation}\]
Turunan dari penalti L2:
\[\begin{equation} \frac{\partial}{\partial \beta} \lambda_2 \beta^T \beta = 2\lambda_2 \beta. \label{eq:Elastic7} \end{equation}\]
Sehingga, turunan pertama dari \(J(\beta)\) adalah:
\[\begin{equation} \frac{\partial J}{\partial \beta} = -2X^T(y - X\beta) + \lambda_1 \cdot \text{sign}(\beta) + 2\lambda_2 \beta. \label{eq:Elastic8} \end{equation}\]
2. Menyamakan dengan Nol untuk Solusi Optimal
Menyusun ulang:
\[\begin{equation} X^T X\beta - X^T y + \frac{\lambda_1}{2} \text{sign}(\beta) + \lambda_2 \beta = 0. \label{eq:Elastic9} \end{equation}\]
Karena fungsi nilai absolut tidak terdiferensiasi di \(\beta_j = 0\), solusi parameter harus ditemukan dengan metode numerik seperti Coordinate Descent.
Algoritma Coordinate Descent sering digunakan untuk menghitung solusi Elastic Net. Langkah-langkahnya adalah:
Ilustrasi Elastic Net dalam Kehadiran Multicollinearity
Tujuan Ilustrasi Tujuan dari ilustrasi ini adalah untuk menunjukkan bagaimana Elastic Net Regression dapat menangani multicollinearity lebih baik dibandingkan OLS (Ordinary Least Squares) dengan menggabungkan keunggulan Lasso dan Ridge Regression.
Simulasi Data dengan Multicollinearity
library(MASS)
library(glmnet)
library(ggplot2)
library(dplyr)
set.seed(123)
n <- 500 # Jumlah sampel
p <- 50 # Jumlah prediktor
# Membuat matriks kovarians dengan korelasi tinggi
Sigma <- matrix(0.9, nrow = p, ncol = p) + diag(0.1, p)
X <- mvrnorm(n, mu = rep(0, p), Sigma = Sigma) # Matriks prediktor
# Koefisien sebenarnya
beta_true <- runif(p, -2, 2)
y <- X %*% beta_true + rnorm(n, sd = 5) # Variabel respon
data <- data.frame(y, X)
Estimasi Model OLS dan Elastic Net Regression
# Model OLS
ols_model <- lm(y ~ ., data = data)
ols_coeff <- coef(ols_model)[-1] # Mengabaikan intercept
# Model Elastic Net Regression
x_matrix <- as.matrix(data[, -1])
y_vector <- data$y
elastic_net_model <- glmnet(x_matrix, y_vector, alpha = 0.5) # alpha = 0.5 untuk Elastic Net
cv_elastic_net <- cv.glmnet(x_matrix, y_vector, alpha = 0.5) # Cross-validation untuk lambda optimal
elastic_net_coeff <- coef(cv_elastic_net, s = "lambda.min")[-1] # Koefisien dengan lambda optimal
Visualisasi Model Elastic Net Regression
Plot Koefisien Elastic Net Regression terhadap Lambda
par(mfrow = c(1,1)) # Pastikan hanya ada satu plot dalam satu area
plot(elastic_net_model,
xvar = "lambda", label = TRUE, cex.axis = 0.7, las = 2) # Menyesuaikan ukuran label
Interpretasi Plot Koefisien Elastic Net Regression terhadap Lambda
Cross-Validation Elastic Net Regression
plot(cv_elastic_net)
Interpretasi Plot Cross-Validation Elastic Net Regression
Plot Mean Squared Error untuk Berbagai Alpha
lambda_seq <- 10^seq(-5, 2, length.out = 100)
cv_fit_1 <- cv.glmnet(x_matrix, y_vector, alpha = 1, lambda = lambda_seq)
cv_fit_05 <- cv.glmnet(x_matrix, y_vector, alpha = 0.5, lambda = lambda_seq)
cv_fit_0 <- cv.glmnet(x_matrix, y_vector, alpha = 0, lambda = lambda_seq)
plot(log(cv_fit_1$lambda), cv_fit_1$cvm, col = "red", pch = 19,
xlab = "log(Lambda)", ylab = "Mean-Squared Error")
points(log(cv_fit_05$lambda), cv_fit_05$cvm, col = "gray", pch = 19)
points(log(cv_fit_0$lambda), cv_fit_0$cvm, col = "blue", pch = 19)
legend("topright", legend = c("alpha=1 (Lasso)", "alpha=.5 (Elastic Net)",
"alpha 0 (Ridge)"),
col = c("red", "gray", "blue"), pch = 19)
Interpretasi Perbandingan Alpha dalam Cross-Validation
Perbandingan Koefisien OLS vs Elastic Net
comparison <- data.frame(
Predictor = paste0("X", 1:p),
OLS = ols_coeff,
ElasticNet = elastic_net_coeff
)
comparison_long <- comparison %>%
tidyr::pivot_longer(cols = c("OLS", "ElasticNet"),
names_to = "Model", values_to = "Coefficient")
# Visualisasi perbandingan koefisien
ggplot(comparison_long, aes(x = Predictor, y = Coefficient, fill = Model)) +
geom_bar(stat = "identity", position = "dodge") +
theme_minimal() +
labs(title = "Perbandingan Koefisien OLS vs Elastic Net Regression",
x = "Predictor",
y = "Estimated Coefficient") +
theme(axis.text.x = element_text(angle = 90, hjust = 1))
Kesimpulan
Dalam dunia machine learning, kita jarang menemukan satu model yang bekerja sempurna untuk semua jenis data. Oleh karena itu, pendekatan ensemble modeling menjadi sangat penting. Ensemble modeling adalah metode yang menggabungkan beberapa model dasar (base learners) untuk menghasilkan model yang lebih kuat dan akurat. Tujuan utamanya adalah untuk meningkatkan performa prediksi, baik dalam konteks klasifikasi maupun regresi.
Tiga teknik ensemble yang paling umum adalah Bagging, Boosting, dan Stacking. Ketiganya memiliki pendekatan yang berbeda terhadap kombinasi model dan memiliki kelebihan masing-masing.
Ensemble learning adalah strategi dalam machine learning yang bertujuan menggabungkan prediksi dari beberapa model untuk meningkatkan akurasi dan generalisasi. Metode ini berfungsi dengan prinsip bahwa sekumpulan model yang berbeda (atau serupa) dapat mengompensasi kelemahan satu sama lain dan menghasilkan prediksi akhir yang lebih stabil.
Keuntungan Ensemble Learning:
Konsep Dasar
Bagging adalah metode ensemble yang bertujuan untuk mengurangi varians model. Teknik ini bekerja dengan membuat beberapa subset data dari dataset pelatihan asli menggunakan bootstrap sampling (sampel dengan pengembalian), kemudian melatih model pada setiap subset tersebut secara paralel. Prediksi akhir ditentukan dengan agregasi (rata-rata untuk regresi, voting untuk klasifikasi).
Langkah-langkah:
Buat beberapa sampel bootstrap dari data pelatihan.
Latih model (biasanya decision tree) pada masing-masing sampel.
Gabungkan prediksi dari semua model:
Voting mayoritas (klasifikasi)
Rata-rata (regresi)
Contoh: Random Forest
Random Forest adalah contoh terkenal dari metode Bagging yang menggunakan banyak decision tree dan rata-rata/voting sebagai agregator.
Implementasi di R
library(randomForest)
data(iris)
set.seed(123)
model_rf <- randomForest(Species ~ ., data = iris, ntree = 100)
print(model_rf)
##
## Call:
## randomForest(formula = Species ~ ., data = iris, ntree = 100)
## Type of random forest: classification
## Number of trees: 100
## No. of variables tried at each split: 2
##
## OOB estimate of error rate: 4.67%
## Confusion matrix:
## setosa versicolor virginica class.error
## setosa 50 0 0 0.00
## versicolor 0 47 3 0.06
## virginica 0 4 46 0.08
Konsep Dasar
Boosting adalah teknik ensemble yang bekerja secara berurutan. Model dibangun satu per satu, di mana setiap model baru mencoba memperbaiki kesalahan model sebelumnya. Tujuan utamanya adalah mengurangi bias model.
Jenis-Jenis Boosting:
AdaBoost
Gradient Boosting
XGBoost
LightGBM
Inti Proses Boosting:
Inisialisasi model dasar.
Hitung kesalahan dari prediksi model.
Tambahkan model baru yang fokus memperbaiki kesalahan.
Kombinasikan semua model dengan bobot tertentu.
Implementasi: Gradient Boosting
library(gbm)
data(mtcars)
set.seed(123)
boost_model <- gbm(
formula = mpg ~ .,
data = mtcars,
distribution = "gaussian",
n.trees = 100,
interaction.depth = 3,
shrinkage = 0.1,
bag.fraction = 1, # Gunakan seluruh data
n.minobsinnode = 5 # Kurangi dari default 10
)
summary(boost_model)
## var rel.inf
## cyl cyl 32.020538014
## wt wt 30.854244585
## hp hp 16.224242840
## disp disp 15.873942069
## drat drat 2.699074609
## qsec qsec 2.159667478
## gear gear 0.165308602
## carb carb 0.002981803
## vs vs 0.000000000
## am am 0.000000000
##Stacking
Konsep Dasar
Stacking adalah metode ensemble yang menggabungkan beberapa model prediksi (disebut base learners) dan memanfaatkan model meta untuk menggabungkan output dari base learners.
Langkah-langkah:
Latih beberapa model berbeda pada data pelatihan.
Gunakan prediksi model-model tersebut sebagai fitur baru.
Latih model meta (meta-learner) pada hasil prediksi tersebut.
Keuntungan:
Dapat memanfaatkan kekuatan berbagai algoritma
Sangat fleksibel dan sering digunakan dalam kompetisi data science
Implementasi di R dengan caretEnsemble
library(caret)
library(caretEnsemble)
# Subset 2-class data
iris2 <- iris[iris$Species != "setosa", ]
iris2$Species <- factor(iris2$Species)
set.seed(123)
control <- trainControl(method = "cv", number = 5, savePredictions = "final", classProbs = TRUE)
models <- caretList(
Species ~ ., data = iris2, trControl = control,
methodList = c("rpart", "knn", "nb")
)
stack_model <- caretStack(models, method = "glm")
summary(stack_model)
## The following models were ensembled: rpart, knn, nb
##
## Model Importance:
## rpart knn nb
## 0.0505 0.5201 0.4295
##
## Model accuracy:
## model_name metric value sd
## <char> <char> <num> <num>
## 1: ensemble ROC 0.984 0.008944272
## 2: rpart Accuracy 0.910 0.065192024
## 3: knn Accuracy 0.960 0.054772256
## 4: nb Accuracy 0.940 0.082158384
Perbandingan Bagging, Boosting, dan Stacking
| Aspek | Bagging | Boosting | Stacking |
|---|---|---|---|
| Tujuan | Mengurangi varians | Mengurangi bias | Kombinasi fleksibel dari model |
| Proses | Paralel | Berurutan | Gabungan + model meta |
| Toleransi outlier | Tinggi | Rendah | Sedang |
| Kompleksitas | Sedang | Tinggi | Tinggi |
| Contoh Algoritma | Random Forest | AdaBoost, XGBoost, LightGBM | Blending, stacking dengan meta |
Studi Kasus dan Evaluasi Model
Ensemble models sangat populer karena sering memberikan hasil yang lebih baik dibandingkan single model. Namun, perlu evaluasi dengan:
Cross-validation
Confusion matrix
AUC (Area Under Curve)
RMSE, MAE untuk regresi
Penutup
Ensemble learning merupakan teknik yang sangat kuat untuk meningkatkan performa model prediksi. Dengan memahami perbedaan dan penggunaan Bagging, Boosting, dan Stacking, praktisi data dapat memilih pendekatan yang paling tepat sesuai dengan masalah dan dataset yang dihadapi. Ketiganya memiliki kekuatan tersendiri dan seringkali menjadi solusi utama dalam dunia nyata maupun kompetisi data science.
Random Forest adalah algoritma machine learning berbasis decision tree yang termasuk dalam metode ensemble learning. Ia dikenal karena keandalannya, kemampuannya menangani dataset besar, dan performa prediksi yang sangat baik baik dalam tugas klasifikasi maupun regresi.
Tujuan dari dokumen ini adalah memberikan pemahaman mendalam tentang Random Forest, mencakup konsep teoretis, formulasi matematis, hingga implementasi praktis menggunakan bahasa pemrograman R.
Konsep Dasar Random Forest
Random Forest dibangun dengan prinsip bahwa kombinasi banyak decision tree (pohon keputusan) dapat menghasilkan model yang lebih stabil dan akurat. Model ini merupakan bentuk dari metode bagging (bootstrap aggregating), dengan penambahan seleksi acak fitur pada tiap node.
Kenapa Random?
Dalam Random Forest, “random” merujuk pada dua hal:
Bootstrap sampling: setiap pohon dilatih dengan subset acak dari data (dengan pengembalian).
Subsampling fitur: di setiap node dalam pohon, hanya subset fitur yang dipilih secara acak untuk split terbaik.
Misalkan:
Dataset pelatihan: \(\mathcal{D} = \{(x_i, y_i)\}_{i=1}^n\)
\(x_i \in \mathbb{R}^p\): fitur
\(y_i \in \{1,2,...,K\}\): target klasifikasi atau \(y_i \in \mathbb{R}\) untuk regresi
Jumlah pohon: \(B\)
\(h_b(x)\): prediksi dari pohon ke-\(b\)
Klasifikasi: \[ \hat{y}(x) = \text{mode}(h_1(x), h_2(x), ..., h_B(x)) \]
Regresi: \[ \hat{y}(x) = \frac{1}{B} \sum_{b=1}^B h_b(x) \]
Algoritma Random Forest
Untuk setiap \(b = 1\) hingga \(B\):
Ambil sampel bootstrap \(\mathcal{D}_b\) dari data pelatihan.
Bangun decision tree \(h_b\) dari \(\mathcal{D}_b\).
Di setiap node: pilih subset acak dari fitur (misal \(\sqrt{p}\)) dan pilih split terbaik.
Gabungkan semua prediksi:
Implementasi di R
Library dan Data
library(randomForest)
library(tidyverse)
data(iris)
str(iris)
## 'data.frame': 150 obs. of 5 variables:
## $ Sepal.Length: num 5.1 4.9 4.7 4.6 5 5.4 4.6 5 4.4 4.9 ...
## $ Sepal.Width : num 3.5 3 3.2 3.1 3.6 3.9 3.4 3.4 2.9 3.1 ...
## $ Petal.Length: num 1.4 1.4 1.3 1.5 1.4 1.7 1.4 1.5 1.4 1.5 ...
## $ Petal.Width : num 0.2 0.2 0.2 0.2 0.2 0.4 0.3 0.2 0.2 0.1 ...
## $ Species : Factor w/ 3 levels "setosa","versicolor",..: 1 1 1 1 1 1 1 1 1 1 ...
Pelatihan Model
set.seed(123)
rf_model <- randomForest(Species ~ ., data = iris, ntree = 100, mtry = 2, importance = TRUE)
print(rf_model)
##
## Call:
## randomForest(formula = Species ~ ., data = iris, ntree = 100, mtry = 2, importance = TRUE)
## Type of random forest: classification
## Number of trees: 100
## No. of variables tried at each split: 2
##
## OOB estimate of error rate: 4.67%
## Confusion matrix:
## setosa versicolor virginica class.error
## setosa 50 0 0 0.00
## versicolor 0 46 4 0.08
## virginica 0 3 47 0.06
Evaluasi Model
pred <- predict(rf_model, iris)
table(Predicted = pred, Actual = iris$Species)
## Actual
## Predicted setosa versicolor virginica
## setosa 50 0 0
## versicolor 0 50 0
## virginica 0 0 50
mean(pred == iris$Species)
## [1] 1
Out-of-Bag (OOB) Error
plot(rf_model, main = "OOB Error Rate")
Feature Importance
importance(rf_model)
## setosa versicolor virginica MeanDecreaseAccuracy
## Sepal.Length 2.334999 3.8525315 3.909442 5.331391
## Sepal.Width 1.873228 -0.2344981 2.931587 2.299106
## Petal.Length 9.062834 14.1250709 10.997897 13.197705
## Petal.Width 11.214854 14.2553890 16.251155 16.117169
## MeanDecreaseGini
## Sepal.Length 10.133410
## Sepal.Width 2.021934
## Petal.Length 39.955902
## Petal.Width 47.133554
varImpPlot(rf_model, main = "Feature Importance (MeanDecreaseGini)")
Eksperimen Sederhana: 3 Pohon
set.seed(42)
rf_small <- randomForest(Species ~ ., data = iris, ntree = 3, mtry = 2, keep.forest = TRUE)
predict(rf_small, iris, predict.all = TRUE)$individual[1:5, ]
## [,1] [,2] [,3]
## 1 "setosa" "setosa" "setosa"
## 2 "setosa" "setosa" "setosa"
## 3 "setosa" "setosa" "setosa"
## 4 "setosa" "setosa" "setosa"
## 5 "setosa" "setosa" "setosa"
Analisis Hasil
Berdasarkan feature importance, fitur yang paling berkontribusi terhadap prediksi adalah Petal.Width dan Petal.Length. Ini konsisten dengan analisis EDA sebelumnya pada data iris.
Penggunaan OOB error membantu dalam estimasi error tanpa memerlukan data validasi terpisah.
Kelebihan dan Kekurangan Random Forest
Kelebihan: - Akurasi tinggi
Tidak mudah overfitting
Dapat menangani data besar dan variabel dalam jumlah banyak
Dapat digunakan untuk klasifikasi maupun regresi
Memberikan feature importance
Kekurangan:
Sulit diinterpretasi (dibandingkan decision tree tunggal)
Waktu pelatihan relatif lebih lama
Model kompleks, tidak cocok untuk sistem real-time dengan latency ketat
Studi Kasus Singkat: Prediksi Spesies Bunga
Dengan data iris, kita bisa memanfaatkan Random Forest untuk memprediksi spesies bunga berdasarkan 4 fitur morfologi. Model ini memberikan akurasi tinggi bahkan tanpa tuning parameter secara mendalam.
Perbandingan dengan Algoritma Lain
| Algoritma | Akurasi | Interpretabilitas | Waktu Latih | Tahan Overfitting |
|---|---|---|---|---|
| Decision Tree | Sedang | Tinggi | Cepat | Tidak |
| Random Forest | Tinggi | Rendah | Sedang | Ya |
| Logistic Regression | Sedang | Sedang | Cepat | Tidak |
| KNN | Sedang | Rendah | Lambat (prediksi) | Tidak |
Tips dan Praktik Terbaik
Gunakan mtry yang optimal (gunakan
tuneRF untuk mencari)
Perhatikan jumlah ntree untuk menghindari
overfitting dan waktu komputasi
Gunakan importance = TRUE untuk interpretasi
fitur
Penutup
Random Forest merupakan model yang sangat powerful dan fleksibel. Ia cocok untuk sebagian besar kasus di dunia nyata karena sifatnya yang non-parametrik, robust, dan relatif mudah digunakan.
AdaBoost (Adaptive Boosting) adalah algoritma ensemble learning yang sangat populer dalam dunia machine learning, terutama untuk klasifikasi. Algoritma ini bekerja dengan cara membangun model-model lemah (weak learners), biasanya decision stump, secara berurutan dan memperkuat model sebelumnya dengan memberikan bobot lebih besar pada observasi yang sulit diklasifikasi.
Dokumen ini akan membahas teori dasar, formulasi matematis, dan implementasi AdaBoost menggunakan bahasa R.
Berbeda dengan Random Forest yang bersifat paralel, AdaBoost bekerja secara sekuensial. Setiap model berikutnya fokus untuk memperbaiki kesalahan yang dilakukan oleh model sebelumnya.
Intuisi Kerja AdaBoost
Awalnya, semua observasi diberi bobot sama.
Model pertama dilatih dan evaluasi error-nya.
Observasi yang salah diklasifikasikan akan mendapatkan bobot lebih tinggi.
Model selanjutnya dilatih pada data dengan bobot baru.
Proses diulang untuk sejumlah iterasi tertentu.
Misal kita memiliki data pelatihan \((x_1, y_1), ..., (x_n, y_n)\), dengan \(y_i \in \{-1, +1\}\).
Langkah Algoritma:
Load Libraries and Dataset
library(adabag)
library(caret)
library(ggplot2)
data(iris)
iris2 <- subset(iris, Species != "setosa")
iris2$Species <- factor(iris2$Species)
Train-Test Split
set.seed(123)
index <- createDataPartition(iris2$Species, p = 0.7, list = FALSE)
train <- iris2[index, ]
test <- iris2[-index, ]
Train AdaBoost Model
set.seed(123)
model_ada <- boosting(Species ~ ., data = train, boos = TRUE, mfinal = 10)
summary(model_ada)
## Length Class Mode
## formula 3 formula call
## trees 10 -none- list
## weights 10 -none- numeric
## votes 140 -none- numeric
## prob 140 -none- numeric
## class 70 -none- character
## importance 4 -none- numeric
## terms 3 terms call
## call 5 -none- call
Plot Decision Boundary
grid <- expand.grid(
Petal.Length = seq(min(iris2$Petal.Length), max(iris2$Petal.Length), length.out = 100),
Petal.Width = seq(min(iris2$Petal.Width), max(iris2$Petal.Width), length.out = 100)
)
grid$Sepal.Length <- mean(iris2$Sepal.Length)
grid$Sepal.Width <- mean(iris2$Sepal.Width)
# Predict on grid
grid_pred <- predict.boosting(model_ada, newdata = grid)
grid$pred <- as.factor(grid_pred$class)
# Plot
ggplot(train, aes(x = Petal.Length, y = Petal.Width, color = Species)) +
geom_point(size = 2) +
geom_tile(data = grid, aes(fill = pred), alpha = 0.2, color = NA) +
labs(title = "Decision Boundary AdaBoost", x = "Petal Length", y = "Petal Width") +
theme_minimal()
Evaluasi Model dan Interpretasi
pred_test <- predict.boosting(model_ada, newdata = test)
confusionMatrix(as.factor(pred_test$class), test$Species)
## Confusion Matrix and Statistics
##
## Reference
## Prediction versicolor virginica
## versicolor 14 1
## virginica 1 14
##
## Accuracy : 0.9333
## 95% CI : (0.7793, 0.9918)
## No Information Rate : 0.5
## P-Value [Acc > NIR] : 4.34e-07
##
## Kappa : 0.8667
##
## Mcnemar's Test P-Value : 1
##
## Sensitivity : 0.9333
## Specificity : 0.9333
## Pos Pred Value : 0.9333
## Neg Pred Value : 0.9333
## Prevalence : 0.5000
## Detection Rate : 0.4667
## Detection Prevalence : 0.5000
## Balanced Accuracy : 0.9333
##
## 'Positive' Class : versicolor
##
Interpretasi:
Plot Error vs Iterasi
errores <- errorevol(model_ada, newdata = test)
plot(errores$error, type = "b", main = "Test Error vs Iterasi", xlab = "Iterasi", ylab = "Test Error")
Prediksi Data Baru
new_obs <- data.frame(
Sepal.Length = 6.0,
Sepal.Width = 2.8,
Petal.Length = 5.0,
Petal.Width = 1.8
)
new_pred <- predict.boosting(model_ada, newdata = new_obs)
new_pred$class # hasil klasifikasi
## [1] "virginica"
new_pred$prob # probabilitas
## [,1] [,2]
## [1,] 0.1255672 0.8744328
AdaBoost meningkatkan akurasi dengan menggabungkan beberapa model lemah.
Penyesuaian bobot pada tiap iterasi memungkinkan fokus pada observasi sulit.
Implementasi di R sangat praktis menggunakan paket
adabag.
Cocok untuk klasifikasi binary dan dapat diperluas ke multiclass.
Untuk aplikasi lanjut, bisa digabungkan dengan metode pemilihan fitur atau digunakan dalam ensemble yang lebih besar.
Keunggulan dan Kelemahan AdaBoost
Keunggulan: - Adaptif terhadap error - Meningkatkan performa dari model-model lemah - Umumnya tidak overfitting jika noise tidak terlalu besar
Kelemahan: - Sensitif terhadap outlier - Membutuhkan waktu lebih lama jika iterasi besar - Kurang cocok untuk data sangat besar tanpa optimisasi
Perbandingan AdaBoost vs Random Forest
| Aspek | AdaBoost | Random Forest |
|---|---|---|
| Proses | Berurutan | Paralel |
| Fokus | Perbaiki kesalahan | Kurangi varians |
| Sensitivitas noise | Tinggi | Rendah |
| Interpretasi | Sedang | Rendah |
Tuning Parameter
iter: jumlah iterasi boostingnu: learning rate (biasanya 0 < nu ≤ 1)type: “discrete”, “real”, atau “gentle”Gunakan train() dari caret untuk tuning
otomatis.
Penutup
AdaBoost adalah teknik boosting yang sangat efisien dalam meningkatkan akurasi model klasifikasi. Implementasinya sederhana, dan dapat diterapkan ke banyak jenis data. Namun, penggunaannya harus memperhatikan outlier dan distribusi noise karena sifat algoritma yang adaptif.
Dalam materi ini, kita akan membahas tiga teknik boosting dalam machine learning:
Tujuan pembelajaran: - Memahami konsep dasar boosting. - Mengetahui bagaimana boosting bekerja dalam model regresi dan klasifikasi. - Mengimplementasikan ketiga metode menggunakan bahasa R.
Konsep Dasar Boosting
Boosting adalah metode ensemble learning yang membentuk model prediksi kuat dari banyak model lemah (weak learners), biasanya berupa decision tree sederhana (shallow trees).
Pendahuluan
Gradient Boosting adalah metode boosting yang sangat kuat dan fleksibel, digunakan baik untuk klasifikasi maupun regresi. Algoritma ini bekerja dengan membangun model secara berurutan, di mana setiap model baru mempelajari kesalahan residu dari model sebelumnya, menggunakan pendekatan gradient descent terhadap loss function.
Dokumen ini membahas teori dasar, formulasi matematis, serta implementasi Gradient Boosting menggunakan R.
Konsep Dasar Gradient Boosting
Gradient Boosting termasuk dalam metode boosting, yaitu teknik ensemble learning yang menggabungkan banyak model lemah untuk membentuk model prediksi yang kuat. Fokus utamanya adalah mengurangi bias dari model dengan cara iteratif.
Proses Umum:
Mulai dengan model awal (misalnya, prediksi rata-rata).
Hitung residual atau gradient loss function.
Fit model baru ke residual.
Update model prediksi dengan kombinasi model lama dan baru.
Ulangi proses ini hingga jumlah iterasi yang ditentukan.
Misalkan:
Dataset pelatihan: \(\mathcal{D} = \{(x_i, y_i)\}_{i=1}^n\)
Fungsi loss: \(L(y, F(x))\)
Prediksi awal: \(F_0(x) = \arg\min_c \sum L(y_i, c)\)
Untuk \(m = 1\) hingga \(M\):
\[ r_{im} = -\left[\frac{\partial L(y_i, F(x_i))}{\partial F(x_i)}\right]_{F(x)=F_{m-1}(x)} \]
Fit model \(h_m(x)\) ke \(r_{im}\)
Temukan langkah optimal \(\gamma_m\):
\[ \gamma_m = \arg\min_{\gamma} \sum L(y_i, F_{m-1}(x_i) + \gamma h_m(x_i)) \]
\[ F_m(x) = F_{m-1}(x) + \gamma_m h_m(x) \]
Implementasi di R
Library dan Data
library(gbm)
library(tidyverse)
data(mtcars)
Latih Model Gradient Boosting
set.seed(123)
gb_model <- gbm(
formula = mpg ~ .,
data = mtcars,
distribution = "gaussian",
n.trees = 100,
interaction.depth = 3,
shrinkage = 0.1,
bag.fraction = 1, # Gunakan seluruh data, hindari subsampling
n.minobsinnode = 3, # Kurangi minimum agar bisa training
cv.folds = 0 # Matikan CV, karena data terlalu kecil
)
Evaluasi Model
best_iter <- which.min(gb_model$train.error)
pred <- predict(gb_model, mtcars, n.trees = best_iter)
rmse <- sqrt(mean((mtcars$mpg - pred)^2))
cat("RMSE:", rmse)
## RMSE: 0.3054586
Visualisasi dan Interpretasi
plot(gb_model)
Eksperimen Learning Rate
set.seed(123)
gb_small_eta <- gbm(
formula = mpg ~ .,
data = mtcars,
distribution = "gaussian",
n.trees = 100,
interaction.depth = 3,
shrinkage = 0.01, # Lebih kecil
bag.fraction = 1, # Gunakan seluruh data
n.minobsinnode = 3 # Minimum node kecil agar training jalan
)
gb_large_eta <- gbm(
formula = mpg ~ .,
data = mtcars,
distribution = "gaussian",
n.trees = 100,
interaction.depth = 3,
shrinkage = 0.3, # learning rate besar
bag.fraction = 1, # gunakan seluruh data
n.minobsinnode = 3 # agar training bisa jalan
)
Evaluasi model
set.seed(123)
best_iter_large <- which.min(gb_large_eta$train.error)
pred_large <- predict(gb_large_eta, mtcars, n.trees = best_iter_large)
rmse_large <- sqrt(mean((mtcars$mpg - pred_large)^2))
cat("RMSE (eta = 0.3):", rmse_large)
## RMSE (eta = 0.3): 0.03880949
Kelebihan dan Kelemahan Gradient Boosting
Kelebihan:
Akurasi tinggi
Dapat menangani berbagai jenis loss function
Mendukung regularisasi
Kelemahan:
Proses pelatihan lambat (iteratif)
Sensitif terhadap outlier
Parameter tuning lebih rumit dibanding model ensemble lain
Perbandingan dengan Metode Lain
| Aspek | Gradient Boosting | Random Forest | AdaBoost |
|---|---|---|---|
| Proses | Berurutan (gradient) | Paralel | Berurutan (reweight) |
| Learning Rate | Ya | Tidak | Ya |
| Overfitting | Bisa terjadi | Lebih tahan | Bisa terjadi |
| Interpretasi | Sedang | Rendah | Sedang |
Tips dan Praktik Terbaik
Gunakan shrinkage kecil (0.01 - 0.1) dengan banyak pohon
Coba cv.folds untuk memilih n.trees
optimal
Gunakan early stopping untuk menghindari overfitting
Penutup
Gradient Boosting adalah salah satu algoritma prediksi yang sangat fleksibel dan akurat, namun membutuhkan perhatian khusus dalam tuning parameter. Ia cocok untuk data dengan kompleksitas tinggi dan cocok dalam banyak kompetisi data science.
Pendahuluan
Extreme Gradient Boosting (XGBoost) adalah salah satu algoritma boosting paling populer dan efisien. Dikenal karena kecepatannya, akurasinya, dan kemampuannya menangani data besar, XGBoost telah menjadi algoritma andalan dalam banyak kompetisi data science seperti Kaggle.
Dalam dokumen ini, kita akan membahas teori dasar, formulasi matematis, dan implementasi XGBoost menggunakan bahasa R.
Konsep Dasar XGBoost
XGBoost merupakan pengembangan dari Gradient Boosting yang mengintegrasikan beberapa peningkatan penting:
Regularisasi L1 dan L2
Penggunaan sparsity-aware
Paralelisasi dan pemangkasan pohon otomatis (pruning)
Kontrol overfitting dengan subsampling data dan kolom
Model Matematis
Tujuan utama XGBoost adalah meminimalkan fungsi objektif sebagai berikut:
\[ Obj = \sum_{i=1}^n l(y_i, \hat{y}_i) + \sum_{k=1}^K \Omega(f_k) \]
dengan:
\(l\): loss function (misalnya squared error)
\(\Omega(f_k) = \gamma T + \frac{1}{2} \lambda \|w\|^2\): regularisasi kompleksitas pohon
Untuk setiap iterasi:
\[ \hat{y}_i^{(t)} = \hat{y}_i^{(t-1)} + f_t(x_i) \]
XGBoost menggunakan Taylor expansion hingga orde ke-2 untuk mengaproksimasi loss function.
Implementasi di R
Library dan Data
library(xgboost)
data(iris)
iris_x <- as.matrix(iris[, -5])
iris_y <- as.numeric(iris$Species) - 1
dtrain <- xgb.DMatrix(data = iris_x, label = iris_y)
Latih Model XGBoost
params <- list(
objective = "multi:softprob",
num_class = 3,
eta = 0.1,
max_depth = 3,
eval_metric = "mlogloss"
)
set.seed(123)
xgb_model <- xgb.train(
params = params,
data = dtrain,
nrounds = 50,
verbose = 0
)
Evaluasi Model
pred <- predict(xgb_model, iris_x)
pred_labels <- max.col(matrix(pred, ncol = 3, byrow = TRUE)) - 1
table(Predicted = pred_labels, Actual = iris_y)
## Actual
## Predicted 0 1 2
## 0 50 0 0
## 1 0 50 0
## 2 0 0 50
mean(pred_labels == iris_y)
## [1] 1
Feature Importance
importance <- xgb.importance(model = xgb_model)
xgb.plot.importance(importance_matrix = importance)
Eksperimen Parameter
params2 <- list(
objective = "multi:softprob",
num_class = 3,
eta = 0.05,
max_depth = 5,
subsample = 0.7,
colsample_bytree = 0.8
)
Kelebihan dan Kelemahan XGBoost
Kelebihan:
Akurasi sangat tinggi
Efisien dan cepat (paralel)
Mendukung berbagai loss function
Mendukung regularisasi
Dapat menangani missing value
Kelemahan:
Kompleks untuk tuning parameter optimal
Interpretasi lebih sulit dibanding model sederhana
Perbandingan XGBoost dengan Metode Lain
| Aspek | XGBoost | Gradient Boosting | Random Forest |
|---|---|---|---|
| Paralelisasi | Ya | Tidak | Ya |
| Regularisasi | L1, L2 | Tidak eksplisit | Tidak eksplisit |
| Akurasi | Sangat tinggi | Tinggi | Tinggi |
| Waktu Latih | Cepat | Lambat | Sedang |
Tips dan Praktik Terbaik
Gunakan xgb.cv untuk mencari jumlah iterasi
optimal
Tuning parameter: eta, max_depth,
subsample, colsample_bytree
Gunakan early_stopping_rounds untuk menghindari
overfitting
Penutup
XGBoost adalah algoritma boosting yang sangat kuat dan telah menjadi andalan dalam berbagai aplikasi. Dengan regularisasi, kontrol overfitting, dan kemampuan skalabilitas, XGBoost menjadi pilihan utama untuk tugas klasifikasi dan regresi dengan data kompleks.
Referensi
Hastie, T., Tibshirani, R., & Friedman, J. (2009). The Elements of Statistical Learning. Springer.
Hoerl, A. E., & Kennard, R. W. (1970). Ridge regression: Biased estimation for nonorthogonal problems. Technometrics, 12(1), 55-67.
Tibshirani, R. (1996). Regression shrinkage and selection via the lasso. Journal of the Royal Statistical Society: Series B, 58(1), 267-288.
Zou, H., & Hastie, T. (2005). Regularization and variable selection via the elastic net. Journal of the Royal Statistical Society: Series B, 67(2), 301-320.