Support Vector Regression (SVR) adalah ekstensi dari Support Vector Machine untuk masalah regresi. SVR bekerja dengan prinsip: - Epsilon-tube (ε-tube): Zona toleransi di sekitar fungsi regresi dimana kesalahan dianggap nol - Support Vectors: Titik data yang berada di luar epsilon-tube atau tepat di batasnya - Kernel Trick: Memungkinkan SVR menangani hubungan nonlinear melalui transformasi ke ruang dimensi tinggi
Keunggulan SVR: - Robust terhadap outlier - Efektif untuk data dimensi tinggi - Menghindari overfitting melalui regularisasi
Fungsi regresi dalam SVR didefinisikan sebagai: \[ f(x) = \langle w, x \rangle + b \] Tujuan dari SVR adalah untuk meminimalkan fungsi objektif berikut: \[ \min_{w, b, \xi_i, \xi_i^*} \frac{1}{2} \|w\|^2 + C \sum_{i=1}^{n} (\xi_i + \xi_i^*) \] Dengan batasan:
\[ \left\{ \begin{array}{ll} y_i - \langle w, x_i \rangle - b \leq \varepsilon + \xi_i \\ \langle w, x_i \rangle + b - y_i \leq \varepsilon + \xi_i^* \\ \xi_i, \xi_i^* \geq 0 \end{array} \right. \] Jika kamu menggunakan kernel untuk regresi nonlinier, maka fungsi regresi diubah menjadi: \[ f(x) = \sum_{i=1}^{n} (\alpha_i - \alpha_i^*) K(x_i, x) + b \]
Untuk melakukan analisis SVR dan visualisasi, kita memuat beberapa package penting seperti MASS untuk dataset Boston, e1071 untuk SVR, caret untuk evaluasi model, serta ggplot2, gridExtra, dan corrplot untuk keperluan plotting. Library lain seperti dplyr dan reshape2 digunakan untuk manipulasi data.
Dataset Boston Housing dimuat ke dalam data frame df. Kita kemudian melihat struktur datanya untuk memahami tipe data dan variabel yang tersedia.
Bagian ini menampilkan ringkasan statistik dari dataset dan contoh beberapa baris data. Tujuannya adalah memberikan gambaran awal tentang distribusi variabel dan isi data yang akan dianalisis.
# Load library yang dibutuhin supaya semua jalan lancar
library(MASS) # Dataset Boston, data klasik yang sering dipake
library(e1071) # Support Vector Regression (SVR) buat modeling
library(ggplot2) # Untuk bikin plot yang kece
library(caret) # Evaluasi performa model
library(gridExtra) # Supaya bisa tampilkan banyak plot sekaligus
library(knitr) # Buat tabel yang rapi di output
library(corrplot) # Visualisasi korelasi antar variabel
library(dplyr) # Manipulasi data dengan cara yang mudah
library(reshape2) # Buat reshape data supaya gampang diolah
# Set seed supaya hasilnya bisa diulang-ulang dan konsisten
set.seed(123)
# Ambil dataset Boston Housing yang udah tersedia
data(Boston)
df <- Boston # Simpan data ke variabel df biar gampang dipake
# Cek struktur data, liat tipe dan isi tiap kolom
str(df)
## 'data.frame': 506 obs. of 14 variables:
## $ crim : num 0.00632 0.02731 0.02729 0.03237 0.06905 ...
## $ zn : num 18 0 0 0 0 0 12.5 12.5 12.5 12.5 ...
## $ indus : num 2.31 7.07 7.07 2.18 2.18 2.18 7.87 7.87 7.87 7.87 ...
## $ chas : int 0 0 0 0 0 0 0 0 0 0 ...
## $ nox : num 0.538 0.469 0.469 0.458 0.458 0.458 0.524 0.524 0.524 0.524 ...
## $ rm : num 6.58 6.42 7.18 7 7.15 ...
## $ age : num 65.2 78.9 61.1 45.8 54.2 58.7 66.6 96.1 100 85.9 ...
## $ dis : num 4.09 4.97 4.97 6.06 6.06 ...
## $ rad : int 1 2 2 3 3 3 5 5 5 5 ...
## $ tax : num 296 242 242 222 222 222 311 311 311 311 ...
## $ ptratio: num 15.3 17.8 17.8 18.7 18.7 18.7 15.2 15.2 15.2 15.2 ...
## $ black : num 397 397 393 395 397 ...
## $ lstat : num 4.98 9.14 4.03 2.94 5.33 ...
## $ medv : num 24 21.6 34.7 33.4 36.2 28.7 22.9 27.1 16.5 18.9 ...
# Ringkasan statistik dataset Boston
summary(df)
## crim zn indus chas
## Min. : 0.00632 Min. : 0.00 Min. : 0.46 Min. :0.00000
## 1st Qu.: 0.08205 1st Qu.: 0.00 1st Qu.: 5.19 1st Qu.:0.00000
## Median : 0.25651 Median : 0.00 Median : 9.69 Median :0.00000
## Mean : 3.61352 Mean : 11.36 Mean :11.14 Mean :0.06917
## 3rd Qu.: 3.67708 3rd Qu.: 12.50 3rd Qu.:18.10 3rd Qu.:0.00000
## Max. :88.97620 Max. :100.00 Max. :27.74 Max. :1.00000
## nox rm age dis
## Min. :0.3850 Min. :3.561 Min. : 2.90 Min. : 1.130
## 1st Qu.:0.4490 1st Qu.:5.886 1st Qu.: 45.02 1st Qu.: 2.100
## Median :0.5380 Median :6.208 Median : 77.50 Median : 3.207
## Mean :0.5547 Mean :6.285 Mean : 68.57 Mean : 3.795
## 3rd Qu.:0.6240 3rd Qu.:6.623 3rd Qu.: 94.08 3rd Qu.: 5.188
## Max. :0.8710 Max. :8.780 Max. :100.00 Max. :12.127
## rad tax ptratio black
## Min. : 1.000 Min. :187.0 Min. :12.60 Min. : 0.32
## 1st Qu.: 4.000 1st Qu.:279.0 1st Qu.:17.40 1st Qu.:375.38
## Median : 5.000 Median :330.0 Median :19.05 Median :391.44
## Mean : 9.549 Mean :408.2 Mean :18.46 Mean :356.67
## 3rd Qu.:24.000 3rd Qu.:666.0 3rd Qu.:20.20 3rd Qu.:396.23
## Max. :24.000 Max. :711.0 Max. :22.00 Max. :396.90
## lstat medv
## Min. : 1.73 Min. : 5.00
## 1st Qu.: 6.95 1st Qu.:17.02
## Median :11.36 Median :21.20
## Mean :12.65 Mean :22.53
## 3rd Qu.:16.95 3rd Qu.:25.00
## Max. :37.97 Max. :50.00
# Ini 6 baris pertama dari dataset Boston, biar gampang liat datanya
kable(head(df), caption = "Contoh 6 Baris Awal Dataset Boston Housing")
| crim | zn | indus | chas | nox | rm | age | dis | rad | tax | ptratio | black | lstat | medv |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0.00632 | 18 | 2.31 | 0 | 0.538 | 6.575 | 65.2 | 4.0900 | 1 | 296 | 15.3 | 396.90 | 4.98 | 24.0 |
| 0.02731 | 0 | 7.07 | 0 | 0.469 | 6.421 | 78.9 | 4.9671 | 2 | 242 | 17.8 | 396.90 | 9.14 | 21.6 |
| 0.02729 | 0 | 7.07 | 0 | 0.469 | 7.185 | 61.1 | 4.9671 | 2 | 242 | 17.8 | 392.83 | 4.03 | 34.7 |
| 0.03237 | 0 | 2.18 | 0 | 0.458 | 6.998 | 45.8 | 6.0622 | 3 | 222 | 18.7 | 394.63 | 2.94 | 33.4 |
| 0.06905 | 0 | 2.18 | 0 | 0.458 | 7.147 | 54.2 | 6.0622 | 3 | 222 | 18.7 | 396.90 | 5.33 | 36.2 |
| 0.02985 | 0 | 2.18 | 0 | 0.458 | 6.430 | 58.7 | 6.0622 | 3 | 222 | 18.7 | 394.12 | 5.21 | 28.7 |
Sebelum membuat model, kita melakukan eksplorasi data dengan visualisasi distribusi variabel target dan mendeteksi adanya outlier. Selain itu, kita juga melihat korelasi antar variabel dan hubungan scatter plot antara variabel independen penting dengan variabel target, untuk memahami pola dan potensi hubungan linier/nonlinier.
# Histogram untuk lihat sebaran harga rumah (medv)
p1 <- ggplot(df, aes(x = medv)) +
geom_histogram(bins = 30, fill = "#8E44AD", alpha = 0.8) +
labs(title = "Sebaran Harga Rumah (medv)",
x = "Median Value (ribu $)",
y = "Jumlah Data") +
theme_minimal(base_family = "sans")
# Boxplot buat cek outlier harga rumah
p2 <- ggplot(df, aes(y = medv)) +
geom_boxplot(fill = "#27AE60", alpha = 0.8) +
labs(title = "Boxplot Harga Rumah",
y = "Median Value (ribu $)") +
theme_minimal(base_family = "sans")
grid.arrange(p1, p2, ncol = 2)
# Matriks korelasi antar variabel
cor_matrix <- cor(df)
corrplot(cor_matrix, method = "square", type = "upper",
tl.cex = 0.9, # ukuran font label variabel
tl.col = "#34495E", # warna teks abu gelap
col = colorRampPalette(c("#F1C40F", "#2980B9"))(200), # gradasi kuning ke biru
title = "Matriks Korelasi Variabel Boston Housing",
mar = c(0,0,2,0)) # margin atas untuk title supaya rapih
lstat memiliki korelasi negatif yang kuat sebesar -0.738, rm menunjukkan
korelasi positif yang kuat sebesar 0.695, dan ptratio memiliki korelasi
negatif sedang dengan nilai -0.508. Nilai variabel target (medv) berada
dalam kisaran antara 5 hingga 50.
# Scatter plot beberapa variabel penting vs medv
p1 <- ggplot(df, aes(x = lstat, y = medv)) +
geom_point(alpha = 0.6) +
geom_smooth(method = "lm", se = FALSE, color = "#D35400") + # orange tua
labs(title = "LSTAT vs MEDV", x = "% Lower Status Population", y = "Median Value") +
theme_minimal(base_family = "sans")
p2 <- ggplot(df, aes(x = rm, y = medv)) +
geom_point(alpha = 0.6) +
geom_smooth(method = "lm", se = FALSE, color = "#2980B9") + # biru cerah
labs(title = "RM vs MEDV", x = "Average Rooms per Dwelling", y = "Median Value") +
theme_minimal(base_family = "sans")
p3 <- ggplot(df, aes(x = crim, y = medv)) +
geom_point(alpha = 0.6) +
geom_smooth(method = "lm", se = FALSE, color = "#27AE60") + # hijau segar
labs(title = "CRIM vs MEDV", x = "Crime Rate", y = "Median Value") +
theme_minimal(base_family = "sans")
p4 <- ggplot(df, aes(x = dis, y = medv)) +
geom_point(alpha = 0.6) +
geom_smooth(method = "lm", se = FALSE, color = "#8E44AD") + # ungu gelap
labs(title = "DIS vs MEDV", x = "Distance to Employment Centers", y = "Median Value") +
theme_minimal(base_family = "sans")
grid.arrange(p1, p2, p3, p4, ncol = 2, nrow = 2)
Pada tahap ini, kita memeriksa apakah ada nilai yang hilang (missing values) pada data. Selanjutnya, data distandarisasi agar semua fitur berada dalam skala yang sama. Setelah itu, data dibagi menjadi data pelatihan dan pengujian dengan proporsi 80:20 untuk proses validasi model.
# Cek apakah ada nilai yang hilang di setiap kolom
cat("Missing values per kolom:") # teks biru untuk header
## Missing values per kolom:
sapply(df, function(x) sum(is.na(x)))
## crim zn indus chas nox rm age dis rad tax
## 0 0 0 0 0 0 0 0 0 0
## ptratio black lstat medv
## 0 0 0 0
# Lakukan normalisasi data, kecuali kolom target (medv)
df_scaled <- df
df_scaled[, -ncol(df_scaled)] <- scale(df_scaled[, -ncol(df_scaled)])
# Bagi data menjadi training dan testing dengan rasio 80:20
train_index <- createDataPartition(df_scaled$medv, p = 0.8, list = FALSE)
train_data <- df_scaled[train_index, ]
test_data <- df_scaled[-train_index, ]
cat("Ukuran data training:", nrow(train_data), "\n")
## Ukuran data training: 407
cat("Ukuran data testing:", nrow(test_data), "\n")
## Ukuran data testing: 99
Kita membangun model Support Vector Regression dengan kernel linear menggunakan data pelatihan. Setelah model selesai, dilakukan prediksi pada data pelatihan dan pengujian, serta ringkasan model ditampilkan untuk memahami parameter yang digunakan.
# Bangun model SVR dengan kernel linear
svr_linear <- svm(medv ~ ., data = train_data,
type = "eps-regression",
kernel = "linear",
cost = 1,
epsilon = 0.1)
# Prediksi harga rumah di data training dan testing
pred_svr_linear_train <- predict(svr_linear, train_data)
pred_svr_linear_test <- predict(svr_linear, test_data)
cat("SVR Linear Model Summary:")
## SVR Linear Model Summary:
print(svr_linear)
##
## Call:
## svm(formula = medv ~ ., data = train_data, type = "eps-regression",
## kernel = "linear", cost = 1, epsilon = 0.1)
##
##
## Parameters:
## SVM-Type: eps-regression
## SVM-Kernel: linear
## cost: 1
## gamma: 0.07692308
## epsilon: 0.1
##
##
## Number of Support Vectors: 307
Di sini kita membangun model SVR dengan kernel radial basis function (RBF) yang dapat menangkap pola nonlinear. Model ini juga diprediksi pada data pelatihan dan pengujian, lalu ringkasan model disajikan.
# Bangun model SVR dengan kernel RBF
svr_rbf <- svm(medv ~ ., data = train_data,
type = "eps-regression",
kernel = "radial",
cost = 10,
gamma = 0.1,
epsilon = 0.1)
# Prediksi harga rumah pada data training dan testing
pred_svr_rbf_train <- predict(svr_rbf, train_data)
pred_svr_rbf_test <- predict(svr_rbf, test_data)
cat("SVR RBF Model Summary:")
## SVR RBF Model Summary:
print(svr_rbf)
##
## Call:
## svm(formula = medv ~ ., data = train_data, type = "eps-regression",
## kernel = "radial", cost = 10, gamma = 0.1, epsilon = 0.1)
##
##
## Parameters:
## SVM-Type: eps-regression
## SVM-Kernel: radial
## cost: 10
## gamma: 0.1
## epsilon: 0.1
##
##
## Number of Support Vectors: 277
Untuk perbandingan, kita buat model regresi linear menggunakan metode OLS. Model ini juga diprediksi dan dirangkum untuk membandingkan performanya dengan model SVR.
# Bangun model OLS sebagai pembanding
ols_model <- lm(medv ~ ., data = train_data)
# Prediksi nilai medv pada data training dan testing
pred_ols_train <- predict(ols_model, train_data)
pred_ols_test <- predict(ols_model, test_data)
cat("OLS Model Summary:")
## OLS Model Summary:
summary(ols_model)
##
## Call:
## lm(formula = medv ~ ., data = train_data)
##
## Residuals:
## Min 1Q Median 3Q Max
## -14.9550 -2.7996 -0.4647 1.7767 25.0993
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) 22.5130 0.2385 94.377 < 2e-16 ***
## crim -0.8073 0.3368 -2.397 0.016999 *
## zn 0.9197 0.3729 2.467 0.014062 *
## indus -0.0891 0.4774 -0.187 0.852059
## chas 0.5817 0.2389 2.435 0.015346 *
## nox -1.9850 0.5032 -3.945 9.45e-05 ***
## rm 2.4586 0.3172 7.751 7.87e-14 ***
## age 0.2765 0.4366 0.633 0.526905
## dis -2.9286 0.4856 -6.031 3.77e-09 ***
## rad 2.8816 0.6716 4.290 2.25e-05 ***
## tax -2.0875 0.7318 -2.852 0.004568 **
## ptratio -2.0798 0.3254 -6.391 4.66e-10 ***
## black 0.8984 0.2679 3.353 0.000877 ***
## lstat -4.0140 0.4226 -9.498 < 2e-16 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 4.801 on 393 degrees of freedom
## Multiple R-squared: 0.7346, Adjusted R-squared: 0.7258
## F-statistic: 83.68 on 13 and 393 DF, p-value: < 2.2e-16
Metrik evaluasi dihitung untuk ketiga model (SVR linear, SVR RBF, dan OLS) pada data pelatihan dan pengujian. Hasilnya disajikan dalam bentuk tabel untuk memudahkan perbandingan performa antar model.
# Fungsi hitung metrik evaluasi model
calculate_metrics <- function(actual, predicted) {
rmse <- sqrt(mean((actual - predicted)^2)) # Root Mean Squared Error
mae <- mean(abs(actual - predicted)) # Mean Absolute Error
r2 <- 1 - sum((actual - predicted)^2) / sum((actual - mean(actual))^2) # Koefisien Determinasi
return(c(RMSE = rmse, MAE = mae, R2 = r2))
}
# Evaluasi performa pada data training
train_metrics <- data.frame(
Model = c("SVR Linear", "SVR RBF", "OLS"),
rbind(
calculate_metrics(train_data$medv, pred_svr_linear_train),
calculate_metrics(train_data$medv, pred_svr_rbf_train),
calculate_metrics(train_data$medv, pred_ols_train)
)
)
# Evaluasi performa pada data testing
test_metrics <- data.frame(
Model = c("SVR Linear", "SVR RBF", "OLS"),
rbind(
calculate_metrics(test_data$medv, pred_svr_linear_test),
calculate_metrics(test_data$medv, pred_svr_rbf_test),
calculate_metrics(test_data$medv, pred_ols_test)
)
)
cat("Hasil Evaluasi pada Data Training:\n")
## Hasil Evaluasi pada Data Training:
kable(train_metrics, digits = 4, caption = "Metrik Evaluasi - Data Training")
| Model | RMSE | MAE | R2 |
|---|---|---|---|
| SVR Linear | 5.0158 | 3.0860 | 0.7000 |
| SVR RBF | 1.6612 | 1.0852 | 0.9671 |
| OLS | 4.7173 | 3.2781 | 0.7346 |
cat("\nHasil Evaluasi pada Data Testing:\n")
##
## Hasil Evaluasi pada Data Testing:
kable(test_metrics, digits = 4, caption = "Metrik Evaluasi - Data Testing")
| Model | RMSE | MAE | R2 |
|---|---|---|---|
| SVR Linear | 4.6854 | 3.1500 | 0.7470 |
| SVR RBF | 2.6743 | 1.9644 | 0.9176 |
| OLS | 4.5889 | 3.3655 | 0.7573 |
Data Training SVR dengan Kernel RBF - Memberikan nilai RMSE dan MAE terendah. - Memiliki nilai R² tertinggi (0.9671), menandakan kemampuan yang sangat baik dalam mempelajari pola dari data pelatihan. - Secara keseluruhan, menjadi model dengan performa terbaik di antara ketiganya pada data training.
OLS (Ordinary Least Squares) - Skor R² sedikit lebih tinggi dibandingkan SVR Linear. - Namun, nilai MAE sedikit lebih besar, menunjukkan kesalahan prediksi rata-rata yang lebih tinggi.
SVR Linear - MAE lebih rendah dibandingkan OLS, tetapi R²-nya lebih kecil. - Kurang mampu menangkap kerumitan hubungan dalam data dibanding SVR RBF.
Kesimpulan Training: 1. SVR RBF secara jelas menunjukkan keunggulan dibanding model lainnya pada data pelatihan. 2. Model ini efektif dalam mengenali pola-pola kompleks secara akurat.
Data Testing SVR dengan Kernel RBF - Menampilkan nilai RMSE dan MAE terendah dibanding semua model. - Meraih nilai R² tertinggi (0.9176), menunjukkan kinerja terbaik saat diuji pada data baru.
OLS - R² sedikit lebih baik daripada SVR Linear (0.7573 vs. 0.7470). - Namun, memiliki MAE yang lebih besar, menunjukkan rata-rata kesalahan prediksi yang lebih tinggi.
SVR Linear - Performa sebanding dengan OLS. - Meskipun begitu, nilai R² lebih rendah, yang berarti model ini menjelaskan variasi data dengan sedikit kurang akurat.
Kesimpulan Testing: 1. SVR RBF tetap menjadi model unggulan pada data pengujian, menunjukkan kemampuan generalisasi yang sangat baik. 2. Hal ini tercermin dari gabungan nilai RMSE dan MAE yang rendah serta R² yang tinggi. 3. Perbedaan R² antara data training dan testing tidak terlalu besar (sekitar 0.05 atau 5%), menandakan performa model yang stabil dan konsisten.
Plot actual vs predicted dibuat untuk setiap model pada data pengujian. Grafik ini membantu kita melihat sejauh mana prediksi model mendekati nilai sebenarnya dengan garis diagonal sebagai referensi ideal.
# Buat dataframe untuk plotting
plot_data_test <- data.frame(
Actual = test_data$medv,
SVR_Linear = pred_svr_linear_test,
SVR_RBF = pred_svr_rbf_test,
OLS = pred_ols_test
)
# Reshape data untuk ggplot
plot_data_melted <- melt(plot_data_test, id.vars = "Actual",
variable.name = "Model", value.name = "Predicted")
# Plot Actual vs Predicted
ggplot(plot_data_melted, aes(x = Actual, y = Predicted, color = Model)) +
geom_point(alpha = 0.7, size = 3) +
geom_abline(slope = 1, intercept = 0, linetype = "dashed", color = "gray40") +
facet_wrap(~Model, ncol = 3) +
labs(title = "Actual vs Predicted Values - Test Data",
x = "Actual Values", y = "Predicted Values") +
theme_bw(base_family = "sans") +
theme(
legend.position = "bottom",
plot.title = element_text(face = "bold", size = 14, color = "#2C3E50"),
axis.title = element_text(face = "bold", size = 12, color = "#34495E"),
legend.title = element_blank()
)
Plot residual terhadap nilai prediksi dibuat untuk melihat distribusi kesalahan prediksi dari masing-masing model. Residual yang tersebar acak dan mendekati nol menandakan model yang baik.
# Residual plots
residuals_data <- data.frame(
Predicted_SVR_Linear = pred_svr_linear_test,
Residuals_SVR_Linear = test_data$medv - pred_svr_linear_test,
Predicted_SVR_RBF = pred_svr_rbf_test,
Residuals_SVR_RBF = test_data$medv - pred_svr_rbf_test,
Predicted_OLS = pred_ols_test,
Residuals_OLS = test_data$medv - pred_ols_test
)
p1 <- ggplot(residuals_data, aes(x = Predicted_SVR_Linear, y = Residuals_SVR_Linear)) +
geom_point(alpha = 0.7, color = "#1F78B4") +
geom_hline(yintercept = 0, linetype = "dashed", color = "#E31A1C") +
labs(title = "SVR Linear - Residuals", x = "Predicted Values", y = "Residuals") +
theme_bw(base_family = "sans") +
theme(
plot.title = element_text(face = "bold", size = 13, color = "#2C3E50"),
axis.title = element_text(face = "bold", size = 11)
)
p2 <- ggplot(residuals_data, aes(x = Predicted_SVR_RBF, y = Residuals_SVR_RBF)) +
geom_point(alpha = 0.7, color = "#33A02C") +
geom_hline(yintercept = 0, linetype = "dashed", color = "#E31A1C") +
labs(title = "SVR RBF - Residuals", x = "Predicted Values", y = "Residuals") +
theme_bw(base_family = "sans") +
theme(
plot.title = element_text(face = "bold", size = 13, color = "#2C3E50"),
axis.title = element_text(face = "bold", size = 11)
)
p3 <- ggplot(residuals_data, aes(x = Predicted_OLS, y = Residuals_OLS)) +
geom_point(alpha = 0.7, color = "#FF7F00") +
geom_hline(yintercept = 0, linetype = "dashed", color = "#E31A1C") +
labs(title = "OLS - Residuals", x = "Predicted Values", y = "Residuals") +
theme_bw(base_family = "sans") +
theme(
plot.title = element_text(face = "bold", size = 13, color = "#2C3E50"),
axis.title = element_text(face = "bold", size = 11)
)
grid.arrange(p1, p2, p3, ncol = 3)
Untuk memperjelas konsep epsilon-tube dalam SVR, kita buat model SVR sederhana dengan satu variabel prediktor. Kemudian divisualisasikan prediksi bersama dengan zona epsilon di sekitar garis prediksi sebagai area toleransi kesalahan.
# Untuk visualisasi epsilon-tube, kita akan menggunakan subset 1 variabel saja
# Menggunakan lstat (% lower status) sebagai predictor tunggal
# Model SVR 1D
train_1d <- train_data[, c("lstat", "medv")]
test_1d <- test_data[, c("lstat", "medv")]
svr_1d_linear <- svm(medv ~ lstat, data = train_1d,
type = "eps-regression",
kernel = "linear",
cost = 1,
epsilon = 0.5)
svr_1d_rbf <- svm(medv ~ lstat, data = train_1d,
type = "eps-regression",
kernel = "radial",
cost = 10,
gamma = 0.1,
epsilon = 0.5)
# Prediksi untuk plotting
lstat_range <- seq(min(train_1d$lstat), max(train_1d$lstat), length.out = 100)
pred_data <- data.frame(lstat = lstat_range)
pred_1d_linear <- predict(svr_1d_linear, pred_data)
pred_1d_rbf <- predict(svr_1d_rbf, pred_data)
# Plot SVR Linear dengan epsilon-tube
p1 <- ggplot() +
geom_point(data = train_1d, aes(x = lstat, y = medv), alpha = 0.6, color = "#2C3E50") +
geom_line(data = data.frame(lstat = lstat_range, pred = pred_1d_linear),
aes(x = lstat, y = pred), color = "#1F78B4", size = 1) +
geom_ribbon(data = data.frame(lstat = lstat_range, pred = pred_1d_linear),
aes(x = lstat, ymin = pred - 0.5, ymax = pred + 0.5),
alpha = 0.3, fill = "#FFD54F") +
labs(title = "SVR Linear dengan Epsilon-Tube",
x = "LSTAT (scaled)", y = "MEDV",
subtitle = "Zona kuning = epsilon-tube (ε = 0.5)") +
theme_bw(base_family = "sans") +
theme(
plot.title = element_text(face = "bold", size = 14, color = "#34495E"),
plot.subtitle = element_text(size = 11, color = "#7F8C8D"),
axis.title = element_text(face = "bold", size = 12)
)
# Plot SVR RBF dengan epsilon-tube
p2 <- ggplot() +
geom_point(data = train_1d, aes(x = lstat, y = medv), alpha = 0.6, color = "#2C3E50") +
geom_line(data = data.frame(lstat = lstat_range, pred = pred_1d_rbf),
aes(x = lstat, y = pred), color = "#E63946", size = 1) +
geom_ribbon(data = data.frame(lstat = lstat_range, pred = pred_1d_rbf),
aes(x = lstat, ymin = pred - 0.5, ymax = pred + 0.5),
alpha = 0.3, fill = "#FFD54F") +
labs(title = "SVR RBF dengan Epsilon-Tube",
x = "LSTAT (scaled)", y = "MEDV",
subtitle = "Zona kuning = epsilon-tube (ε = 0.5)") +
theme_bw(base_family = "sans") +
theme(
plot.title = element_text(face = "bold", size = 14, color = "#34495E"),
plot.subtitle = element_text(size = 11, color = "#7F8C8D"),
axis.title = element_text(face = "bold", size = 12)
)
grid.arrange(p1, p2, ncol = 2)
Kesimpulan: - SVR dengan kernel RBF memberikan hasil visual yang lebih
baik karena mampu menangkap hubungan non-linear antara persentase
populasi berstatus sosial lebih rendah (LSTAT) dengan nilai median rumah
(MEDV). - Meskipun memiliki tingkat kompleksitas yang lebih tinggi
dibanding model linear, model RBF lebih sesuai untuk dataset ini karena
kemampuannya dalam menyesuaikan diri dengan pola data yang tidak
linier.
Kita coba berbagai nilai epsilon pada SVR RBF dan lihat pengaruhnya terhadap metrik evaluasi. Hal ini penting untuk memahami bagaimana toleransi kesalahan mempengaruhi performa model.
# Uji coba berbagai nilai epsilon pada model SVR dengan kernel RBF
epsilon_values <- c(0.01, 0.1, 0.5, 1.0, 2.0)
epsilon_results <- data.frame()
for (eps in epsilon_values) {
svr_temp <- svm(medv ~ ., data = train_data,
type = "eps-regression",
kernel = "radial",
cost = 10,
gamma = 0.1,
epsilon = eps)
pred_temp <- predict(svr_temp, test_data)
metrics_temp <- calculate_metrics(test_data$medv, pred_temp)
epsilon_results <- rbind(epsilon_results,
data.frame(Epsilon = eps,
RMSE = metrics_temp[1],
MAE = metrics_temp[2],
R2 = metrics_temp[3]))
}
kable(epsilon_results, digits = 4, caption = "Dampak Variasi Epsilon pada Performa Model")
| Epsilon | RMSE | MAE | R2 | |
|---|---|---|---|---|
| RMSE | 0.01 | 2.7857 | 2.0143 | 0.9106 |
| RMSE1 | 0.10 | 2.6743 | 1.9644 | 0.9176 |
| RMSE2 | 0.50 | 3.5178 | 2.5759 | 0.8574 |
| RMSE3 | 1.00 | 5.5122 | 4.6506 | 0.6498 |
| RMSE4 | 2.00 | 10.7648 | 9.6435 | -0.3356 |
# Visualisasi pengaruh nilai epsilon terhadap metrik RMSE dan R²
p1 <- ggplot(epsilon_results, aes(x = Epsilon, y = RMSE)) +
geom_line(color = "#1b9e77") + geom_point(color = "#1b9e77") +
labs(title = "Dampak Epsilon terhadap RMSE", x = "Nilai Epsilon", y = "RMSE") +
theme_bw()
p2 <- ggplot(epsilon_results, aes(x = Epsilon, y = R2)) +
geom_line(color = "#d95f02") + geom_point(color = "#d95f02") +
labs(title = "Dampak Epsilon terhadap Koefisien Determinasi (R²)",
x = "Nilai Epsilon", y = "R²") +
theme_bw()
grid.arrange(p1, p2, ncol = 2)
Jika nilai epsilon terlalu besar, model akan mengabaikan terlalu banyak
kesalahan kecil, sehingga menurunkan performa prediksi.
Sebaliknya, epsilon yang terlalu kecil membuat model terlalu sensitif terhadap data, menghasilkan jumlah support vector yang sangat banyak.
Nilai epsilon sebesar 0.1 terbukti memberikan keseimbangan yang baik antara kompleksitas model dan akurasi, sehingga menjadi pilihan yang optimal.
Berbagai nilai parameter cost diuji untuk mengevaluasi pengaruhnya terhadap kemampuan model dalam menghindari underfitting atau overfitting. Hasilnya divisualisasikan untuk memilih cost optimal.
# Uji pengaruh variasi nilai cost pada model SVR dengan kernel RBF
cost_values <- c(0.1, 1, 10, 100, 1000)
cost_results <- data.frame()
for (c_val in cost_values) {
svr_temp <- svm(medv ~ ., data = train_data,
type = "eps-regression",
kernel = "radial",
cost = c_val,
gamma = 0.1,
epsilon = 0.1)
pred_temp <- predict(svr_temp, test_data)
metrics_temp <- calculate_metrics(test_data$medv, pred_temp)
cost_results <- rbind(cost_results,
data.frame(Cost = c_val,
RMSE = metrics_temp[1],
MAE = metrics_temp[2],
R2 = metrics_temp[3]))
}
kable(cost_results, digits = 4, caption = "Dampak Variasi Cost pada Performa Model")
| Cost | RMSE | MAE | R2 | |
|---|---|---|---|---|
| RMSE | 1e-01 | 6.1386 | 3.5381 | 0.5657 |
| RMSE1 | 1e+00 | 3.8619 | 2.3528 | 0.8281 |
| RMSE2 | 1e+01 | 2.6743 | 1.9644 | 0.9176 |
| RMSE3 | 1e+02 | 3.4411 | 2.5219 | 0.8635 |
| RMSE4 | 1e+03 | 4.0788 | 2.9768 | 0.8083 |
# Visualisasi pengaruh cost terhadap RMSE dan R²
p1 <- ggplot(cost_results, aes(x = log10(Cost), y = RMSE)) +
geom_line(color = "#7570b3") + geom_point(color = "#7570b3") +
labs(title = "Dampak Cost terhadap RMSE", x = "log10(Cost)", y = "RMSE") +
theme_bw()
p2 <- ggplot(cost_results, aes(x = log10(Cost), y = R2)) +
geom_line(color = "#e7298a") + geom_point(color = "#e7298a") +
labs(title = "Dampak Cost terhadap Koefisien Determinasi (R²)",
x = "log10(Cost)", y = "R²") +
theme_bw()
grid.arrange(p1, p2, ncol = 2)
Ketika nilai Cost (C) terlalu kecil (misalnya C = 0.1), model cenderung
terlalu toleran terhadap kesalahan, yang dapat menyebabkan underfitting
atau ketidakmampuan model menangkap pola data dengan baik.
Sebaliknya, nilai C yang terlalu besar (seperti C = 1000) membuat model terlalu ketat terhadap kesalahan, sehingga berisiko mengalami overfitting karena terlalu menyesuaikan diri dengan data pelatihan.
Nilai C = 10 memberikan hasil terbaik, karena mampu menyeimbangkan antara fleksibilitas model dan akurasi prediksi.
Parameter gamma pada kernel RBF diuji dengan nilai berbeda untuk melihat bagaimana tingkat kompleksitas model berubah. Visualisasi hasil membantu menentukan nilai gamma yang terbaik.
# Test berbagai nilai gamma pada model SVR kernel RBF
gamma_values <- c(0.001, 0.01, 0.1, 1, 10)
gamma_results <- data.frame()
for (g_val in gamma_values) {
svr_temp <- svm(medv ~ ., data = train_data,
type = "eps-regression",
kernel = "radial",
cost = 10,
gamma = g_val,
epsilon = 0.1)
pred_temp <- predict(svr_temp, test_data)
metrics_temp <- calculate_metrics(test_data$medv, pred_temp)
gamma_results <- rbind(gamma_results,
data.frame(Gamma = g_val,
RMSE = metrics_temp[1],
MAE = metrics_temp[2],
R2 = metrics_temp[3]))
}
kable(gamma_results, digits = 4, caption = "Pengaruh Parameter Gamma")
| Gamma | RMSE | MAE | R2 | |
|---|---|---|---|---|
| RMSE | 1e-03 | 4.6989 | 3.1067 | 0.7455 |
| RMSE1 | 1e-02 | 3.7887 | 2.3406 | 0.8346 |
| RMSE2 | 1e-01 | 2.6743 | 1.9644 | 0.9176 |
| RMSE3 | 1e+00 | 4.7893 | 3.3144 | 0.7356 |
| RMSE4 | 1e+01 | 8.7717 | 6.2238 | 0.1132 |
# Plot pengaruh gamma terhadap RMSE dan R²
p1 <- ggplot(gamma_results, aes(x = log10(Gamma), y = RMSE)) +
geom_line(color = "#1b9e77") + geom_point(color = "#1b9e77") +
labs(title = "Pengaruh Gamma terhadap RMSE", x = "log10(Gamma)", y = "RMSE") +
theme_bw()
p2 <- ggplot(gamma_results, aes(x = log10(Gamma), y = R2)) +
geom_line(color = "#d95f02") + geom_point(color = "#d95f02") +
labs(title = "Pengaruh Gamma terhadap R²", x = "log10(Gamma)", y = "R²") +
theme_bw()
grid.arrange(p1, p2, ncol = 2)
Nilai gamma yang terlalu kecil menghasilkan kurva prediksi yang terlalu
halus atau datar, sehingga model kurang mampu menangkap pola data yang
kompleks (underfitting).
Sebaliknya, gamma yang terlalu besar membuat model terlalu sensitif terhadap data lokal, yang dapat menyebabkan overfitting karena model hanya menyesuaikan diri dengan data pelatihan.
Nilai gamma = 0.1 memberikan hasil paling optimal, karena cukup fleksibel untuk menangkap pola tanpa mengorbankan kemampuan generalisasi model.
Melakukan pencarian grid pada beberapa parameter sekaligus (cost, gamma, epsilon) untuk menemukan kombinasi yang memberikan performa terbaik pada data pelatihan. Parameter terbaik dan performanya kemudian ditampilkan.
# Grid search untuk menemukan parameter optimal SVR kernel RBF
tune_result <- tune(svm, medv ~ ., data = train_data,
type = "eps-regression",
kernel = "radial",
ranges = list(cost = c(1, 10, 100),
gamma = c(0.01, 0.1, 1),
epsilon = c(0.01, 0.1, 0.5)))
cat("Parameter Optimal:\n")
## Parameter Optimal:
print(tune_result$best.parameters)
## cost gamma epsilon
## 14 10 0.1 0.1
cat("\nPerformance Terbaik (MSE):\n")
##
## Performance Terbaik (MSE):
print(tune_result$best.performance)
## [1] 13.13684
# Model dengan parameter optimal
svr_optimal <- tune_result$best.model
# Prediksi dengan model optimal pada data testing
pred_optimal_test <- predict(svr_optimal, test_data)
# Hitung metrik evaluasi untuk model optimal
metrics_optimal <- calculate_metrics(test_data$medv, pred_optimal_test)
cat("\nMetrik Model Optimal:\n")
##
## Metrik Model Optimal:
print(metrics_optimal)
## RMSE MAE R2
## 2.6742851 1.9643708 0.9175722
Kombinasi parameter terbaik untuk model SVR dengan kernel radial (RBF) adalah epsilon = 0.1, cost = 10, dan gamma = 0.1. dimana, - Epsilon (ε): Mengatur lebar dari epsilon-tube di sekitar garis prediksi. Nilai epsilon yang terlalu kecil dapat membuat model terlalu sensitif terhadap data (overfitting), sedangkan nilai yang terlalu besar bisa menyebabkan model mengabaikan terlalu banyak kesalahan (underfitting). - Cost (C): Berfungsi sebagai parameter regularisasi yang mengatur kompromi antara kesederhanaan model dan akurasi terhadap data pelatihan. Nilai C yang rendah membuat model lebih toleran terhadap kesalahan, sedangkan nilai yang tinggi menekankan pada minimisasi error, namun berisiko overfitting. - Gamma (γ): Merupakan parameter dalam kernel RBF yang menentukan seberapa jauh pengaruh dari satu data training. Gamma yang besar membuat model fokus pada titik-titik data di sekitar, sedangkan gamma kecil menyebabkan pengaruh menyebar lebih luas.
Dari hasil yang diperoleh, dapat disimpulkan bahwa:
SVR sangat cocok digunakan untuk: - Memprediksi harga properti dengan tingkat akurasi yang tinggi. - Mengelola data yang memiliki outlier secara efektif. - Memodelkan hubungan nonlinear antara variabel input dan output.
Untuk dataset Boston Housing, disarankan: 1. Menggunakan SVR dengan kernel RBF guna mendapatkan performa terbaik. 2. Melakukan tuning parameter secara teliti untuk hasil yang optimal. 3. Menerapkan preprocessing pada data agar kualitas model meningkat. 4. Memantau potensi overfitting melalui teknik validasi silang.
# Ringkasan performa semua model
final_comparison <- data.frame(
Model = c("SVR Linear", "SVR RBF", "SVR Optimal", "OLS"),
RMSE = c(test_metrics$RMSE[1], test_metrics$RMSE[2], metrics_optimal[1], test_metrics$RMSE[3]),
MAE = c(test_metrics$MAE[1], test_metrics$MAE[2], metrics_optimal[2], test_metrics$MAE[3]),
R2 = c(test_metrics$R2[1], test_metrics$R2[2], metrics_optimal[3], test_metrics$R2[3])
)
kable(final_comparison, digits = 4, caption = "Ringkasan Performa Semua Model")
| Model | RMSE | MAE | R2 |
|---|---|---|---|
| SVR Linear | 4.6854 | 3.1500 | 0.7470 |
| SVR RBF | 2.6743 | 1.9644 | 0.9176 |
| SVR Optimal | 2.6743 | 1.9644 | 0.9176 |
| OLS | 4.5889 | 3.3655 | 0.7573 |
# Menampilkan model terbaik berdasarkan nilai R2
best_model_name <- final_comparison$Model[which.max(final_comparison$R2)]
cat("Model terbaik berdasarkan R² adalah:", best_model_name)
## Model terbaik berdasarkan R² adalah: SVR RBF
Analisis ini memperlihatkan bahwa SVR merupakan metode regresi yang efektif untuk data dengan pola yang kompleks. Pemilihan kernel serta penyesuaian parameter sangat berperan penting dalam mencapai performa terbaik model.