Penjelasan Teoretis SVR

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 \]

Memuat Library dan Dataset & Ringkasan Statistik dan Tampilan Awal Data

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")
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

Eksplorasi Data Awal

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)

Pra-pemrosesan Data

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

Model Building

Model SVR Linear

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

Model SVR Nonlinear (RBF Kernel)

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

Model OLS (Ordinary Least Squares)

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

Evaluasi Model

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")
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")
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.

Visualisasi Model

Actual vs Predicted

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()
  )

Residual Plots

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)

Visualisasi Epsilon-Tube (Model 1D)

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.

Eksplorasi Parameter

Parameter Epsilon

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")
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.

Parameter Cost (C)

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")
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

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")
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.

Tuning Parameter Optimal

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.

Interpretasi dan Kesimpulan

Perbandingan Model

Dari hasil yang diperoleh, dapat disimpulkan bahwa:

  1. Kinerja Model:
  • SVR dengan kernel RBF menunjukkan kemampuan terbaik dalam menangkap pola nonlinear pada data.
  • SVR linear memberikan hasil yang cukup baik dan sebanding dengan model OLS untuk data dengan pola linear.
  • Model OLS tetap menjadi tolok ukur dasar dalam evaluasi performa model regresi.
  1. Dampak Parameter:
  • Epsilon (ε) menentukan lebar dari epsilon-tube; nilai kecil cenderung menyebabkan model overfit, sementara nilai besar dapat membuat model kurang sensitif.
  • Cost (C) mengatur keseimbangan antara kompleksitas model dan toleransi terhadap kesalahan prediksi.
  • Gamma (γ) pada kernel RBF mempengaruhi jangkauan pengaruh tiap data pelatihan dalam pembentukan model.

Kegunaan Praktis

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.

Saran

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")
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.