1 SVR

1.1 Teori

Support Vector Regression (SVR) merupakan pengembangan dari Support Vector Machine (SVM) yang digunakan untuk memodelkan hubungan antara variabel prediktor dan variabel target dalam bentuk regresi. Berbeda dengan metode regresi linear biasa yang meminimalkan keseluruhan kesalahan kuadrat, SVR memperkenalkan konsep margin toleransi kesalahan melalui epsilon-tube (ε-tube).

Epsilon-tube adalah pita selebar 2ε yang dibentuk di sekitar fungsi regresi. Selama nilai prediksi berada di dalam pita tersebut (±ε dari nilai aktual), kesalahan dianggap tidak signifikan dan tidak dikenakan penalti. Fokus SVR adalah meminimalkan kompleksitas model sambil menjaga kesalahan prediksi tetap dalam batas toleransi ini.

Fungsi regresi dalam SVR dituliskan sebagai:

\[ f(x) = w \cdot x + b \]

dengan tujuan meminimalkan norma \(||w||^2\) untuk menghasilkan model yang sederhana dan memiliki kemampuan generalisasi yang baik.

SVR menggunakan fungsi loss epsilon-insensitive, yaitu fungsi yang hanya memberikan penalti terhadap prediksi yang melampaui batas toleransi. Fungsi loss ini dapat dituliskan sebagai:

\[ L_{\varepsilon}(y, f(x)) = \begin{cases} 0, & \text{jika } |y - f(x)| \leq \varepsilon \\ |y - f(x)| - \varepsilon, & \text{jika } |y - f(x)| > \varepsilon \end{cases} \]

Support vectors adalah titik data yang berada di luar batas toleransi dan berkontribusi langsung terhadap pembentukan model. Titik-titik ini menentukan parameter akhir model dan menjadikan SVR lebih efisien karena hanya sejumlah kecil data yang benar-benar memengaruhi fungsi prediksi.

keunggulan SVR:

  • Robust terhadap noise: Tidak memberikan penalti pada kesalahan kecil sehingga lebih tahan terhadap fluktuasi data yang tidak signifikan.
  • Menghindari overfitting: Dengan memusatkan perhatian hanya pada data penting, model menjadi lebih sederhana dan tidak menyesuaikan seluruh data secara berlebihan.
  • Fleksibel: Dapat diaplikasikan pada hubungan linear maupun non-linear dengan bantuan fungsi kernel seperti linear, polynomial, dan radial basis function (RBF).

Pendekatan ini menjadikan SVR sebagai metode regresi yang efektif dan robust, khususnya pada data yang mengandung noise atau variasi kecil yang tidak relevan.

1.2 Library

# Load required libraries
library(MASS)        # untuk dataset Boston
library(e1071)       # untuk SVR
library(ggplot2)     # untuk plotting
library(caret)       # untuk evaluasi model
## Loading required package: lattice
library(gridExtra)   # untuk multiple plots
library(knitr)       # untuk tabel
## Warning: package 'knitr' was built under R version 4.4.3
library(corrplot)    # untuk correlation plot
## corrplot 0.94 loaded
library(dplyr)       # untuk data manipulation
## 
## Attaching package: 'dplyr'
## The following object is masked from 'package:gridExtra':
## 
##     combine
## The following object is masked from 'package:MASS':
## 
##     select
## The following objects are masked from 'package:stats':
## 
##     filter, lag
## The following objects are masked from 'package:base':
## 
##     intersect, setdiff, setequal, union
library(reshape2)    # untuk data reshaping

# Set seed untuk reproducibility
set.seed(123)

1.3 Eksplorasi Data

Dataset Boston Housing merupakan dataset klasik dalam analisis regresi yang berisi informasi tentang perumahan di kawasan Boston, Massachusetts. Data ini diperoleh dari arsip StatLib (http://lib.stat.cmu.edu/datasets/boston) dan pertama kali dipublikasikan oleh Harrison, D. dan Rubinfeld, D.L. pada tahun 1978.

Dataset terdiri dari 506 sampel dengan 13 variabel prediktor dan 1 variabel target:

  1. CRIM: Tingkat kriminalitas per kapita berdasarkan kota
  2. ZN: Proporsi lahan perumahan yang ditetapkan untuk lot di atas 25.000 sq.ft
  3. INDUS: Proporsi luas lahan non-retail bisnis per kota
  4. CHAS: Variabel dummy Charles River (1 jika berbatasan dengan sungai; 0 jika tidak)
  5. NOX: Konsentrasi oksida nitrat (bagian per 10 juta)
  6. RM: Rata-rata jumlah kamar per hunian
  7. AGE: Proporsi unit hunian yang dibangun sebelum tahun 1940
  8. DIS: Jarak tertimbang ke lima pusat kerja di Boston
  9. RAD: Indeks aksesibilitas ke jalan raya radial
  10. TAX: Nilai pajak properti penuh per $10.000
  11. PTRATIO: Rasio murid-guru berdasarkan kota
  12. B: 1000(Bk - 0.63)^2 dimana Bk adalah proporsi penduduk keturunan Afrika-Amerika berdasarkan kota
  13. LSTAT: Persentase status populasi yang lebih rendah

Variabel target: MEDV: Nilai median rumah yang ditempati pemilik dalam $1000

data(Boston)
head(Boston)
##      crim zn indus chas   nox    rm  age    dis rad tax ptratio  black lstat
## 1 0.00632 18  2.31    0 0.538 6.575 65.2 4.0900   1 296    15.3 396.90  4.98
## 2 0.02731  0  7.07    0 0.469 6.421 78.9 4.9671   2 242    17.8 396.90  9.14
## 3 0.02729  0  7.07    0 0.469 7.185 61.1 4.9671   2 242    17.8 392.83  4.03
## 4 0.03237  0  2.18    0 0.458 6.998 45.8 6.0622   3 222    18.7 394.63  2.94
## 5 0.06905  0  2.18    0 0.458 7.147 54.2 6.0622   3 222    18.7 396.90  5.33
## 6 0.02985  0  2.18    0 0.458 6.430 58.7 6.0622   3 222    18.7 394.12  5.21
##   medv
## 1 24.0
## 2 21.6
## 3 34.7
## 4 33.4
## 5 36.2
## 6 28.7
# Melihat struktur data
str(Boston)
## '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 ...
# Melihat dimensi data
dim(Boston)
## [1] 506  14
# Memeriksa nilai yang hilang
sum(is.na(Boston))
## [1] 0
# Ringkasan statistik data
summary(Boston)
##       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
# Histogram target variable (medv)
p1 <- ggplot(Boston, aes(x = medv)) +
  geom_histogram(bins = 30, fill = "skyblue", alpha = 0.7) +
  labs(title = "Distribusi Harga Rumah (medv)", x = "Median Value ($1000s)", y = "Frequency") +
  theme_bw()

# Boxplot untuk deteksi outlier
p2 <- ggplot(Boston, aes(y = medv)) +
  geom_boxplot(fill = "lightcoral", alpha = 0.7) +
  labs(title = "Boxplot Harga Rumah", y = "Median Value ($1000s)") +
  theme_bw()

grid.arrange(p1, p2, ncol = 2)

Distribusi dari variabel medv terlihat mengandung data pencilan

# Melihat korelasi variabel penjelas dengan target (medv)
correlation_matrix <- cor(Boston)
correlation_with_medv <- correlation_matrix[,"medv"]
correlation_data <- data.frame(
  Variabel = names(correlation_with_medv),
  Korelasi = correlation_with_medv
)
correlation_data <- correlation_data[order(abs(correlation_data$Korelasi), decreasing = TRUE), ]
kable(correlation_data, caption = "Korelasi Variabel dengan Target (medv)")
Korelasi Variabel dengan Target (medv)
Variabel Korelasi
medv medv 1.0000000
lstat lstat -0.7376627
rm rm 0.6953599
ptratio ptratio -0.5077867
indus indus -0.4837252
tax tax -0.4685359
nox nox -0.4273208
crim crim -0.3883046
rad rad -0.3816262
age age -0.3769546
zn zn 0.3604453
black black 0.3334608
dis dis 0.2499287
chas chas 0.1752602
  1. Variabel target (medv) memiliki rentang nilai antara 5 hingga 50
  2. Terdapat beberapa variabel yang memiliki korelasi kuat dengan variabel target, seperti:
    • lstat (korelasi negatif kuat: -0.738)
    • rm (korelasi positif kuat: 0.695)
    • ptratio (korelasi negatif sedang: -0.508)
# Scatter plot beberapa variabel penting vs medv
p1 <- ggplot(Boston, aes(x = lstat, y = medv)) +
  geom_point(alpha = 0.6) +
  geom_smooth(method = "lm", se = FALSE, color = "red") +
  labs(title = "LSTAT vs MEDV", x = "Status populasi yang lebih rendah (%)", y = "Nilai median rumah") +
  theme_bw()

p2 <- ggplot(Boston, aes(x = rm, y = medv)) +
  geom_point(alpha = 0.6) +
  geom_smooth(method = "lm", se = FALSE, color = "blue") +
  labs(title = "RM vs MEDV", x = "Rata-rata jumlah kamar per hunian", y = "Nilai median rumah") +
  theme_bw()

p3 <- ggplot(Boston, aes(x = ptratio, y = medv)) +
  geom_point(alpha = 0.6) +
  geom_smooth(method = "lm", se = FALSE, color = "green") +
  labs(title = "PTRATIO vs MEDV", x = "Rasio murid-guru berdasarkan kota", y = "Nilai median rumah") +
  theme_bw()

grid.arrange(p1, p2, p3, ncol = 2, nrow = 2)
## `geom_smooth()` using formula = 'y ~ x'
## `geom_smooth()` using formula = 'y ~ x'
## `geom_smooth()` using formula = 'y ~ x'

# Membagi data menjadi training (80%) dan testing (20%)
train_indices <- createDataPartition(Boston$medv, p = 0.8, list = FALSE)
train_data <- Boston[train_indices, ]
test_data <- Boston[-train_indices, ]

# Memeriksa dimensi data training dan testing
cat("Dimensi data training:", dim(train_data), "\n")
## Dimensi data training: 407 14
cat("Dimensi data testing:", dim(test_data))
## Dimensi data testing: 99 14

1.4 SVR Linear

# SVR Linear
svr_linear <- svm(medv ~ ., data = train_data, 
                  type = "eps-regression", 
                  kernel = "linear", 
                  cost = 1, 
                  epsilon = 0.1)

# Prediksi
pred_svr_linear_train <- predict(svr_linear, train_data)
pred_svr_linear_test <- predict(svr_linear, test_data)

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

1.5 SVR Non-linear (RBF Kernel)

# SVR dengan RBF kernel
svr_rbf <- svm(medv ~ ., data = train_data, 
               type = "eps-regression", 
               kernel = "radial", 
               cost = 10, 
               gamma = 0.1,
               epsilon = 0.1)

# Prediksi
pred_svr_rbf_train <- predict(svr_rbf, train_data)
pred_svr_rbf_test <- predict(svr_rbf, test_data)
summary(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

1.6 OLS

# Model OLS
ols_model <- lm(medv ~ ., data = train_data)

# Prediksi
pred_ols_train <- predict(ols_model, train_data)
pred_ols_test <- predict(ols_model, test_data)

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)  37.733617   5.619935   6.714 6.63e-11 ***
## crim         -0.093857   0.039157  -2.397 0.016999 *  
## zn            0.039436   0.015987   2.467 0.014062 *  
## indus        -0.012988   0.069595  -0.187 0.852059    
## chas          2.290187   0.940621   2.435 0.015346 *  
## nox         -17.130560   4.342272  -3.945 9.45e-05 ***
## rm            3.499219   0.451445   7.751 7.87e-14 ***
## age           0.009823   0.015510   0.633 0.526905    
## dis          -1.390769   0.230614  -6.031 3.77e-09 ***
## rad           0.330939   0.077135   4.290 2.25e-05 ***
## tax          -0.012386   0.004342  -2.852 0.004568 ** 
## ptratio      -0.960676   0.150307  -6.391 4.66e-10 ***
## black         0.009841   0.002935   3.353 0.000877 ***
## lstat        -0.562095   0.059180  -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

1.7 Perbandingan SVR dengan OLS

calculate_metrics <- function(actual, predicted) {
  rmse <- sqrt(mean((actual - predicted)^2))
  mae <- mean(abs(actual - predicted))
  r2 <- 1 - sum((actual - predicted)^2) / sum((actual - mean(actual))^2)
  
  return(c(RMSE = rmse, MAE = mae, R2 = r2))
}
# Evaluasi untuk 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 untuk 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)
  )
)

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
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 RBF
- RMSE dan MAE paling rendah.
- R² tertinggi (0.9671), menunjukkan kemampuan sangat baik dalam mempelajari pola dari data.
- Menunjukkan performa terbaik di antara ketiga model pada data training.

OLS (Ordinary Least Squares)
- R² sedikit lebih tinggi dari SVR Linear.
- MAE sedikit lebih besar dibanding SVR Linear.

SVR Linear
- MAE lebih kecil dari OLS, namun R² lebih rendah.
- Kurang mampu menangkap kompleksitas data dibanding SVR RBF.

Simpulan:
- SVR RBF secara signifikan mengungguli model lain pada data training.
- Model ini mampu menangkap pola kompleks secara efisien.

Data Testing:

SVR RBF
- RMSE dan MAE terendah di antara semua model.
- R² paling tinggi (0.9176), menunjukkan performa umum terbaik pada data yang belum pernah dilihat sebelumnya.

OLS (Ordinary Least Squares)
- R² sedikit lebih tinggi dari SVR Linear (0.7573 vs. 0.7470).
- Namun, memiliki MAE yang lebih besar, artinya rata-rata kesalahan prediksinya lebih tinggi.

SVR Linear
- Performa serupa dengan OLS.
- Namun, R² masih lebih rendah dibandingkan OLS, sehingga menjelaskan variasi data dengan sedikit kurang akurat.

Simpulan:
- SVR RBF tetap menjadi model terbaik pada data testing, dengan kemampuan generalisasi yang sangat baik terhadap data baru.
- Hal ini ditunjukkan oleh kombinasi RMSE & MAE yang rendah, serta R² yang tinggi.
- Selisih antara R² Training dan Testing tidak terlalu besar (sekitar 0.05 poin atau 5%), menandakan konsistensi performa.

1.8 Plot Residual Model

# 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.6) +
  geom_hline(yintercept = 0, linetype = "dashed", color = "red") +
  labs(title = "SVR Linear - Residuals", x = "Predicted Values", y = "Residuals") +
  theme_bw()

p2 <- ggplot(residuals_data, aes(x = Predicted_SVR_RBF, y = Residuals_SVR_RBF)) +
  geom_point(alpha = 0.6) +
  geom_hline(yintercept = 0, linetype = "dashed", color = "red") +
  labs(title = "SVR RBF - Residuals", x = "Predicted Values", y = "Residuals") +
  theme_bw()

p3 <- ggplot(residuals_data, aes(x = Predicted_OLS, y = Residuals_OLS)) +
  geom_point(alpha = 0.6) +
  geom_hline(yintercept = 0, linetype = "dashed", color = "red") +
  labs(title = "OLS - Residuals", x = "Predicted Values", y = "Residuals") +
  theme_bw()

grid.arrange(p1, p2, p3, ncol = 3)

1.9 Aktual vs Prediksi

# 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.6, size = 2) +
  geom_abline(slope = 1, intercept = 0, linetype = "dashed", color = "black") +
  facet_wrap(~Model, ncol = 3) +
  labs(title = "Actual vs Predicted Values - Test Data", 
       x = "Actual Values", y = "Predicted Values") +
  theme_bw() +
  theme(legend.position = "bottom")

1.10 Visualisasi Epsilon-Tube dan Support Vector(1D)

# Menggunakan lstat 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, 
                     gamma = 0.07692308,
                     epsilon = 0.5)

svr_1d_rbf <- svm(medv ~ lstat, data = train_1d, 
                  type = "eps-regression", 
                  kernel = "radial", 
                  cost = 10, 
                  gamma = 0.1,
                  epsilon = 0.1)

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


# Identifikasi support vectors
sv_indices_linear <- svr_1d_linear$index
sv_indices_rbf <- svr_1d_rbf$index

support_vectors_linear <- train_1d[sv_indices_linear, ]
support_vectors_rbf <- train_1d[sv_indices_rbf, ]


# Fungsi untuk membuat plot SVR dengan support vectors
create_svr_plot <- function(train_data, lstat_range, predictions, support_vectors, 
                           title, color, epsilon = 0.1) {
support_vectors_linear <- train_1d[sv_indices_linear, ]
support_vectors_rbf <- train_1d[sv_indices_rbf, ]
  
  plot_data <- data.frame(lstat = lstat_range, pred = predictions)
  
  p <- ggplot() +
    # Data points
    geom_point(data = train_data, aes(x = lstat, y = medv), 
               alpha = 0.6, size = 1, color = "gray50") +
    
    # Support vectors (highlighted)
    geom_point(data = support_vectors, aes(x = lstat, y = medv), 
               color = color, size = 1, shape = 21, fill = "white", stroke = 2) +
    
    # Epsilon-tube (zona toleransi)
    geom_ribbon(data = plot_data, 
                aes(x = lstat, ymin = pred - epsilon, ymax = pred + epsilon), 
                alpha = 0.2, fill = "yellow") +
    
    # Batas atas epsilon-tube
    geom_line(data = plot_data, 
              aes(x = lstat, y = pred + epsilon), 
              color = color, linetype = "dashed", alpha = 0.7) +
    
    # Batas bawah epsilon-tube
    geom_line(data = plot_data, 
              aes(x = lstat, y = pred - epsilon), 
              color = color, linetype = "dashed", alpha = 0.7) +
    
    # Regression line
    geom_line(data = plot_data, 
              aes(x = lstat, y = pred), 
              color = color, size = 1.2) +
    
    labs(title = title, 
         x = "LSTAT", 
         y = "MEDV",
         subtitle = paste("ε-tube (ε =", epsilon, "), Support Vectors:", nrow(support_vectors))) +
    
    theme_minimal() +
    theme(plot.title = element_text(size = 14, face = "bold"),
          plot.subtitle = element_text(size = 11),
          axis.title = element_text(size = 11),
          axis.text = element_text(size = 10),
          panel.grid.minor = element_blank(),
          plot.margin = unit(c(0.5, 0.5, 0.5, 0.5), "cm"))
  
  return(p)
}

# Buat plot untuk SVR Linear
p1 <- create_svr_plot(train_1d, lstat_range, pred_1d_linear, support_vectors_linear, 
                      "SVR Linear dengan Epsilon-Tube", "blue")
## Warning: Using `size` aesthetic for lines was deprecated in ggplot2 3.4.0.
## ℹ Please use `linewidth` instead.
## This warning is displayed once every 8 hours.
## Call `lifecycle::last_lifecycle_warnings()` to see where this warning was
## generated.
# Buat plot untuk SVR RBF
p2 <- create_svr_plot(train_1d, lstat_range, pred_1d_rbf, support_vectors_rbf, 
                      "SVR RBF dengan Epsilon-Tube", "red")

# Tampilkan plot dengan layout yang lebih baik
grid.arrange(p1, p2, ncol = 2, nrow = 1)

SVR Linear:

  • Kernel linear dengan ε = 0.1 menghasilkan 142 support vectors

  • Menunjukkan hubungan linear negatif antara LSTAT dan MEDV

  • Model sederhana dengan garis regresi lurus

SVR RBF:

  • Kernel RBF dengan ε = 0.1 menghasilkan 346 support vectors

  • Menangkap pola non-linear dalam data dengan kurva yang fleksibel

  • Lebih kompleks namun mengikuti distribusi data dengan lebih baik

Simpulan:

SVR RBF menunjukkan performa visual yang lebih baik karena dapat menangkap hubungan non-linear antara Persentase status populasi yang lebih rendah (LSTAT) dan nilai median rumah (MEDV). Model RBF lebih sesuai untuk dataset ini meskipun memiliki kompleksitas yang lebih tinggi dibanding model linear.

1.11 Parameter Epsilon, Cost(C), dan Gamma

1.11.1 epsilon

# Test berbagai nilai epsilon
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 = "Pengaruh Parameter Epsilon")
Pengaruh Parameter Epsilon
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
  • Nilai epsilon terlalu besar menyebabkan model mengabaikan banyak error → performa turun.

  • Nilai terlalu kecil menghasilkan terlalu banyak support vector.

  • Nilai optimal: ε = 0.1 memberikan keseimbangan terbaik.

# Test berbagai nilai cost
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 = "Pengaruh Parameter Cost")
Pengaruh Parameter Cost
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
# Plot pengaruh cost
p1 <- ggplot(cost_results, aes(x = log10(Cost), y = RMSE)) +
  geom_line(color = "blue") + geom_point(color = "blue") +
  labs(title = "Pengaruh Cost terhadap RMSE", x = "log10(Cost)") + theme_bw()

p2 <- ggplot(cost_results, aes(x = log10(Cost), y = R2)) +
  geom_line(color = "red") + geom_point(color = "red") +
  labs(title = "Pengaruh Cost terhadap R²", x = "log10(Cost)") + theme_bw()

grid.arrange(p1, p2, ncol = 2)

  • Cost kecil (C = 0.1) → model underfitting.

  • Cost besar (C = 1000) → model overfitting.

  • Nilai optimal: C = 10.

# Test berbagai nilai gamma
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
p1 <- ggplot(gamma_results, aes(x = log10(Gamma), y = RMSE)) +
  geom_line(color = "blue") + geom_point(color = "blue") +
  labs(title = "Pengaruh Gamma terhadap RMSE", x = "log10(Gamma)") +
  theme_bw()

p2 <- ggplot(gamma_results, aes(x = log10(Gamma), y = R2)) +
  geom_line(color = "red") + geom_point(color = "red") +
  labs(title = bquote("Pengaruh Gamma terhadap" ~ R^2), x = "log10(Gamma)") +
  theme_bw()

grid.arrange(p1, p2, ncol = 2)

  • Gamma kecil → kurva terlalu rata (underfitting).

  • Gamma besar → terlalu fokus pada data lokal (overfitting).

  • Nilai optimal: 0.1.

1.12 Parameter Optimal

# Grid search untuk parameter optimal
tune_result <- tune(svm, medv ~ ., data = train_data,
                   type = "eps-regression",
                   kernel = "radial",
                   ranges = list(cost = c(0.1, 1, 10, 100, 1000),
                               gamma = c(0.001, 0.01, 0.1, 1, 10),
                               epsilon = c(0.01, 0.1, 0.5, 1.0, 2.0)))

print(tune_result$best.parameters)
##    cost gamma epsilon
## 35 1000  0.01     0.1

Pengaruh Parameter:

  • Parameter terbaik untuk model SVR-Radial Kernel adalah epsilon(0.1), cost(10), dan gamma (0.1)

  • Epsilon (ε): Parameter yang mengontrol lebar epsilon-tube. Nilai yang terlalu kecil dapat menyebabkan overfitting,sedangkan nilai yang terlalu besar dapat menyebabkan underfitting

  • Cost (C): Parameter regularisasi yang mengontrol trade-off antara kompleksitas model dan toleransi error

  • Gamma (γ): Parameter kernel RBF yang mengontrol pengaruh setiap training example

# Model dengan parameter optimal
svr_optimal <- tune_result$best.model
pred_optimal_test <- predict(svr_optimal, test_data)
metrics_optimal <- calculate_metrics(test_data$medv, pred_optimal_test)

print(metrics_optimal)
##      RMSE       MAE        R2 
## 3.0475110 2.1058878 0.8929594

Simpulan:

  1. SVR RBF umumnya memberikan performa terbaik dalam menangkap pola nonlinear dalam data

  2. Model SVR dengan parameter optimal ini sangat cocok digunakan untuk memprediksi harga median properti (medv) pada dataset yang digunakan. Dengan tingkat akurasi yang tinggi, model ini dapat diandalkan untuk analisis prediksi harga properti dalam konteks serupa, sehingga dapat membantu pengambil keputusan, misalnya developer properti atau analis pasar real estate, dalam menentukan strategi harga dan investasi. Selain itu, model ini dapat dikembangkan atau diadaptasi untuk dataset lain dengan karakteristik yang mirip guna meningkatkan efisiensi dan efektivitas prediksi harga properti di berbagai wilayah.