Support Vector machine (SVM) untuk Model Klasifikasi

Cahya Alkahfi | sainsdata.id

Support Vector Machine (SVM) adalah salah satu algoritma pembelajaran mesin yang populer dan serbaguna untuk tugas klasifikasi dan regresi. Algoritma ini bekerja dengan mencari hyperplane terbaik yang memisahkan kelas-kelas dalam data. Dalam tutorial ini, kita akan fokus pada penggunaan SVM untuk tugas klasifikasi menggunakan bahasa pemrograman R.

Pada tutorial ini, kita akan menggunakan metapaket tidymodels untuk menangani setiap tahap pemodelan, mulai dari pra-pemrosesan data, pemodelan, evaluasi hingga tuning hyperparameter model. Pada tahap pemodelan, kita akan menggunakan engine dari paket kernlab. Oleh karena itu, kita perlu menginstal kedua paket tersebut untuk melanjutkan.

tidymodels adalah sekumpulan paket dalam R yang dirancang untuk memudahkan proses analisis data dan pembuatan model prediktif. Dengan menggunakan tidymodels, kita dapat melakukan semua langkah pemodelan secara sistematis dan konsisten, mulai dari membersihkan data hingga mengevaluasi performa model.

Pada tahap pemodelan, kernlab akan digunakan sebagai engine untuk membangun model SVM. kernlab menyediakan berbagai metode kernel dan SVM yang dapat disesuaikan dengan kebutuhan analisis kita. Penggunaan kernlab memungkinkan kita untuk melakukan pemodelan yang lebih fleksibel dan komprehensif.

Untuk memulai, pastikan anda telah menginstal kedua paket ini dengan perintah berikut:

# install.packages("tidymodels") # metapaket yang berisi berbagai paket untuk seluruh alur pemodelan
# install.packages("kernlabs")   # paket yang digunakan sebagai engine model svm pada tidymodels

library(tidymodels)
## Warning: package 'tidymodels' was built under R version 4.2.3
## ── Attaching packages ────────────────────────────────────── tidymodels 1.2.0 ──
## ✔ broom        1.0.5      ✔ recipes      1.0.10
## ✔ dials        1.2.1      ✔ rsample      1.2.1 
## ✔ dplyr        1.1.4      ✔ tibble       3.2.1 
## ✔ ggplot2      3.5.1      ✔ tidyr        1.3.1 
## ✔ infer        1.0.7      ✔ tune         1.2.1 
## ✔ modeldata    1.3.0      ✔ workflows    1.1.4 
## ✔ parsnip      1.2.1      ✔ workflowsets 1.1.0 
## ✔ purrr        1.0.2      ✔ yardstick    1.3.1
## Warning: package 'broom' was built under R version 4.2.3
## Warning: package 'dials' was built under R version 4.2.3
## Warning: package 'scales' was built under R version 4.2.3
## Warning: package 'dplyr' was built under R version 4.2.3
## Warning: package 'ggplot2' was built under R version 4.2.3
## Warning: package 'infer' was built under R version 4.2.3
## Warning: package 'modeldata' was built under R version 4.2.3
## Warning: package 'parsnip' was built under R version 4.2.3
## Warning: package 'purrr' was built under R version 4.2.3
## Warning: package 'recipes' was built under R version 4.2.3
## Warning: package 'rsample' was built under R version 4.2.3
## Warning: package 'tibble' was built under R version 4.2.3
## Warning: package 'tidyr' was built under R version 4.2.3
## Warning: package 'tune' was built under R version 4.2.3
## Warning: package 'workflows' was built under R version 4.2.3
## Warning: package 'workflowsets' was built under R version 4.2.3
## Warning: package 'yardstick' was built under R version 4.2.3
## ── Conflicts ───────────────────────────────────────── tidymodels_conflicts() ──
## ✖ purrr::discard() masks scales::discard()
## ✖ dplyr::filter()  masks stats::filter()
## ✖ dplyr::lag()     masks stats::lag()
## ✖ recipes::step()  masks stats::step()
## • Dig deeper into tidy modeling with R at https://www.tmwr.org

Penyiapan Data

Pada tutorial ini, kita akan bekerja dengan Heart Disease Dataset. Dataset ini mencakup 918 observasi dan terdiri dari 11 variabel input atau fitur, yang mencakup tipe data numerik dan kategorikal. Variabel respon dalam dataset ini adalah HeartDisease, di mana nilai 0 menunjukkan kondisi normal dan nilai 1 menunjukkan adanya penyakit jantung.

Dataset ini memberikan gambaran yang komprehensif tentang berbagai faktor yang dapat mempengaruhi kesehatan jantung, dan dengan menggunakan teknik machine learning seperti SVM, kita akan mencoba membangun model yang dapat memprediksi risiko penyakit jantung berdasarkan fitur-fitur yang ada.

# memuat dataset
data <- read.csv('https://raw.githubusercontent.com/sainsdataid/dataset/main/heart.csv')

# merubah kolom respon menjadi factor
data$HeartDisease <- as.factor(data$HeartDisease)

str(data)
## 'data.frame':    918 obs. of  12 variables:
##  $ Age           : int  40 49 37 48 54 39 45 54 37 48 ...
##  $ Sex           : chr  "M" "F" "M" "F" ...
##  $ ChestPainType : chr  "ATA" "NAP" "ATA" "ASY" ...
##  $ RestingBP     : int  140 160 130 138 150 120 130 110 140 120 ...
##  $ Cholesterol   : int  289 180 283 214 195 339 237 208 207 284 ...
##  $ FastingBS     : int  0 0 0 0 0 0 0 0 0 0 ...
##  $ RestingECG    : chr  "Normal" "Normal" "ST" "Normal" ...
##  $ MaxHR         : int  172 156 98 108 122 170 170 142 130 120 ...
##  $ ExerciseAngina: chr  "N" "N" "N" "Y" ...
##  $ Oldpeak       : num  0 1 0 1.5 0 0 0 0 1.5 0 ...
##  $ ST_Slope      : chr  "Up" "Flat" "Up" "Flat" ...
##  $ HeartDisease  : Factor w/ 2 levels "0","1": 1 2 1 2 1 1 1 1 2 1 ...
table(data$HeartDisease)
## 
##   0   1 
## 410 508

Pra-pemrosesan Data

Tahapan pra-pemrosesan data bertujuan untuk menyiapkan data agar siap digunakan dalam pemodelan. Dalam bagian ini, kita akan melakukan dua proses utama: pembagian data dan standardisasi data.

Pembagian data adalah langkah penting yang memungkinkan model untuk dilatih dan dievaluasi menggunakan data yang berbeda. Dalam konteks ini, kita akan menggunakan fungsi initial_split dari paket rsample dalam tidymodels untuk membagi data. Model akan dilatih menggunakan 70 persen data dan 30 persen sisanya akan digunakan sebagai data uji.

Standardisasi data juga merupakan langkah penting, terutama dalam pemodelan SVM yang sangat bergantung pada jarak antara titik data. Perbedaan skala antar fitur dapat mempengaruhi performa model, sehingga perlu disesuaikan. Proses standardisasi akan membuat setiap fitur memiliki nilai rata-rata 0 dan standar deviasi 1. Di tidymodels, standardisasi dapat dilakukan menggunakan fungsi step_center dan step_scale dari paket recipe.

Jika terdapat pra-pemrosesan lainnya yang diperlukan seperti, penanganan missing value, penanganan outlier juga dapat ditambahkan pada fungsi recipe.

Berikut adalah langkah-langkahnya dalam kode R menggunakan tidymodels:

set.seed(111)

# membagi data latih dan data uji
data_split <- initial_split(data, prop = 0.7)
data_train <- training(data_split)
data_test <- testing(data_split)

# menyiapkan tahapan preprocessing
data_recipe <- recipe(HeartDisease ~ ., data = data_train) %>%
               step_center(all_numeric_predictors())  %>%          # standardisasi fitur (center + scale)
               step_scale(all_numeric_predictors())                # standardisasi fitur (center + scale)

data_recipe
## 
## ── Recipe ──────────────────────────────────────────────────────────────────────
## 
## ── Inputs
## Number of variables by role
## outcome:    1
## predictor: 11
## 
## ── Operations
## • Centering for: all_numeric_predictors()
## • Scaling for: all_numeric_predictors()

Pemodelan SVM

Dalam ekosistem tidymodels, kita dapat menggunakan beberapa fungsi untuk membangun, men-tuning, dan mengevaluasi model SVM. Berikut adalah beberapa fungsi utama dan parameter dapat digunakan untuk model SVM di tidymodels:

svm_rbf: fungsi ini digunakan untuk membuat model SVM dengan kernel radial basis function (RBF). RBF adalah kernel yang sering digunakan karena fleksibilitasnya dalam menangani berbagai tipe data. Pada fungsi ini terdapat aprameter yang dapat diatur meliputi:

  • mode: Menentukan apakah model digunakan untuk klasifikasi ("classification") atau regresi ("regression").

  • cost: parameter cost berupa nilai positif dan berfungsi sebagai regularisasi yang mengontrol margin serta penalti kesalahan klasifikasi. Nilai yang lebih tinggi memberikan penalti yang lebih besar untuk kesalahan klasifikasi.

  • rbf_sigma: parameter rbf_sigma berupa nilai positif yang menentukan luas dari pengaruh satu titik data dan berhubungan dengan seberapa “lebar” kernel RBF.

svm_poly: fungsi ini digunakan untuk membuat model SVM menggunakan kernel polinomial. Parameter pada fungsi svm_poly yaitu:

  • mode

  • cost

  • degree: derajat polinomial yang digunakan (misal 2: kuadratik, 3: kubik, dan sebagainya)

  • scale_factor: (atau dikenal juga sebagai gamma dalam beberapa literatur) adalah parameter yang mengatur skala dari kernel polinomial yang menentukan seberapa besar kontribusi setiap fitur sebelum dipangkatkan.

svm_linear: fungsi ini digunakan untuk membuat SVM dengan kernel linier. Fungsi ini merupakan model SVM yang paling sederhana, dan dapat bekerja baik jika kelas data dapat terpisah dengan baik secara linier. Parameter pada fungsi svm_linear yaitu mode dan cost.

Di sini, kita akan menggunakan fungsi svm_rbf untuk membangun model SVM. Silahkan mengeksplorasi secara mandiri dua fungsi lainnya dan coba bandingkan hasilnya.

Pelatihan Model

Tahapan pelatihan di mulai dengan melakukan inisiasi model, misalkan menggunakan svm_rbf. Kita dapat menentukan nilai parameternya, sebagai contoh dengan cost=2 dan rbf_sigma=1. Pada bagian ini kita akan menggunakan nilai tersebut secara langsung, namun berikutnya nilai tersebut akan diperoleh berdasarkan proses tuning hyperparameter.

Selanjutnya, kita dapat membuat workflow pemodelan menggunakan fungsi workflow. Di sini, kita dapat menentukan langkah apa yang dilakukan pada proses pemodelan. Dalam hal ini, ada dua proses meliputi pra-pemrosesan data yang sudah didefinisikan sebelumnya dan tahapan pemodelan menggunakan model SVM.

# inisiasi model
svm_model <- svm_rbf(mode = "classification", cost = 2, rbf_sigma = 1) %>%
             set_engine("kernlab")

# membuat workflow model
svm_workflow <- workflow() %>%
                add_recipe(data_recipe) %>%
                add_model(svm_model)


# melatih model dengan data latih
svm_fit <- svm_workflow %>%
           fit(data = data_train)

print(svm_fit)
## ══ Workflow [trained] ══════════════════════════════════════════════════════════
## Preprocessor: Recipe
## Model: svm_rbf()
## 
## ── Preprocessor ────────────────────────────────────────────────────────────────
## 2 Recipe Steps
## 
## • step_center()
## • step_scale()
## 
## ── Model ───────────────────────────────────────────────────────────────────────
## Support Vector Machine object of class "ksvm" 
## 
## SV type: C-svc  (classification) 
##  parameter : cost C = 2 
## 
## Gaussian Radial Basis kernel function. 
##  Hyperparameter : sigma =  1 
## 
## Number of Support Vectors : 591 
## 
## Objective Function Value : -235.4691 
## Training error : 0.001558 
## Probability model included.

Evaluasi Model

Model yang diperoleh selanjutnya digunakan untuk memprediksi data uji sekaligus mengevaluasi hasil model tersebut. Pada contoh dibawah ini, kita menggunakan metrik accuracy sebagai ukuran kinerja model.

Hasil di bawah ini menunjukkan kinerja model SVM pada data uji. Nilai akurasi yang didapatkan adalah sebesar 0,819 atau secara umum model mampu memprediksi benar sekitar 81,9 persen data uji. Jika diperlukan, kita juga dapat menampilkan confusion matrix, atau metrik-metrik lainnya dalam pemodelan klasifikasi.

# memprediksi data uji
svm_preds <- predict(svm_fit, data_test, type = "class") %>%
  bind_cols(data_test)

print(svm_preds)
## # A tibble: 276 × 13
##    .pred_class   Age Sex   ChestPainType RestingBP Cholesterol FastingBS
##    <fct>       <int> <chr> <chr>             <int>       <int>     <int>
##  1 0              40 M     ATA                 140         289         0
##  2 1              49 F     NAP                 160         180         0
##  3 0              45 F     ATA                 130         237         0
##  4 1              38 M     ASY                 110         196         0
##  5 0              43 F     TA                  100         223         0
##  6 0              49 F     ATA                 124         201         0
##  7 1              44 M     ATA                 150         288         0
##  8 0              52 M     ATA                 120         284         0
##  9 1              53 F     ATA                 113         468         0
## 10 1              54 M     ASY                 125         224         0
## # ℹ 266 more rows
## # ℹ 6 more variables: RestingECG <chr>, MaxHR <int>, ExerciseAngina <chr>,
## #   Oldpeak <dbl>, ST_Slope <chr>, HeartDisease <fct>
# menghitung metrik akurasi
svm_metrics <- svm_preds %>%
  metrics(truth = HeartDisease, estimate = .pred_class)

print(svm_metrics)
## # A tibble: 2 × 3
##   .metric  .estimator .estimate
##   <chr>    <chr>          <dbl>
## 1 accuracy binary         0.819
## 2 kap      binary         0.617
# menghitung confusion matrix
cm <- svm_preds %>%
  conf_mat(truth = HeartDisease, estimate = .pred_class)

print(cm)
##           Truth
## Prediction   0   1
##          0  78  11
##          1  39 148
# Menghitung metrik lainnya (jika diperlukan)
# (balanced accuracy, precision, recall, F1-score)
svm_metrics_oth <- svm_preds %>%
  summarise(
    Precision = precision_vec(truth = HeartDisease, estimate = .pred_class),
    Recall = recall_vec(truth = HeartDisease, estimate = .pred_class),
    Bal_Accuracy = bal_accuracy_vec(truth = HeartDisease, estimate = .pred_class),
    F1_Score = f_meas_vec(truth = HeartDisease, estimate = .pred_class)
  )

print(svm_metrics_oth)
## # A tibble: 1 × 4
##   Precision Recall Bal_Accuracy F1_Score
##       <dbl>  <dbl>        <dbl>    <dbl>
## 1     0.876  0.667        0.799    0.757

Tuning Hyperparameter

Model sebelumnya dibangun dengan menetapkan secara langsung nilai parameternya. Untuk mencari model yang lebih baik kita dapat melakukan tuning hyperparameter seperti Grid Search, Random Search atau teknik lainnya. Pada contoh ini kita akan menggunakan teknik Random Search. Random Search bekerja dengan mencoba berbagai kombinasi berbagai nilai parameter yang diberikan sebanyak jumlah tertentu, misalkan 50 kali atau 100 kali. Semakin banyak percobaan, maka semakin besar kemungkinan memperoleh model yang lebih baik, namun tentunya semakin lama juga waktu pencarian yang dibutuhkan.

Finalisasi Workflow Model

Dari hasil di atas, kita dapat membuat workflow menggunakan model terbaik yang telah diperoleh. Adapun langkah-langkahnya sama seperti sebelumnya. Hasil evaluasi model pada data uji menunjukkan kinerja yang jauh lebih baik dibandingkan sebelumnya dengan akurasi sebesar 0,884. Berdasarkan confusion matrix juga dapat dilihat bahwa kemampuan model memprediksi relatif lebih baik, khususnya pada kelas 0.

# Finalisasi alur kerja dengan hyperparameter terbaik
final_svm_workflow <- finalize_workflow(
  svm_tune_workflow,
  svm_best
)

# Latih model dengan data latih
best_fit <- final_svm_workflow %>% 
            fit(data = data_train)

# Evaluasi model dengan data uji
best_preds <- predict(best_fit, data_test) %>%
  bind_cols(data_test)

svm_metrics_best <- best_preds %>%
  metrics(truth = HeartDisease, estimate = .pred_class)

print(svm_metrics_best)
## # A tibble: 2 × 3
##   .metric  .estimator .estimate
##   <chr>    <chr>          <dbl>
## 1 accuracy binary         0.884
## 2 kap      binary         0.763
# buat confusion matrix
cm_best <- best_preds %>%
  conf_mat(truth = HeartDisease, estimate = .pred_class)

print(cm_best)
##           Truth
## Prediction   0   1
##          0 101  16
##          1  16 143

Persistensi Model

Setelah kita selesai melatih model dan melakukan proses tuning hyperparameter, penting untuk menyimpan model yang telah dilatih sehingga dapat digunakan kembali atau didistribusikan tanpa perlu melatih ulang atau dikenal sebagai persistensi model. Di R, kita dapat menyimpan objek model menggunakan fungsi saveRDS dan memuatnya kembali dengan readRDS. Model yang sudah dimuat selanjutnya dapat kita gunakan kembali, misalkan untuk memprediksi data baru.

Pada contoh berikut, terdapat 2 data baru dan akan dilakukan prediksi kondisi keduanya apakah Normal atau kemungkinan mengalami heart Desease.

# contoh menyimpan model ke dalam file .rds
saveRDS(best_fit, file = "final_model.rds")


# contoh membuka model dari file .rds
loaded_final_model <- readRDS(file = "final_model.rds")


# Prediksi data baru menggunakan model
data_1 = data.frame(Age=38, 
              Sex="F", 
              ChestPainType="ASY",
              RestingBP=105,
              Cholesterol=50,
              FastingBS=1,
              RestingECG="Normal",
              MaxHR=166,
              ExerciseAngina="N",
              Oldpeak=2.8,
              ST_Slope="Up")

data_2 = data.frame(Age=29, 
              Sex="M", 
              ChestPainType="ATA",
              RestingBP=120,
              Cholesterol=243,
              FastingBS=0,
              RestingECG="Normal",
              MaxHR=160,
              ExerciseAngina="N",
              Oldpeak=0.0,
              ST_Slope="Up")

data_baru = data.frame(rbind(data_1, data_2))


predictions <- predict(loaded_final_model, data_baru) %>%
  bind_cols(data_baru)

predictions
## # A tibble: 2 × 12
##   .pred_class   Age Sex   ChestPainType RestingBP Cholesterol FastingBS
##   <fct>       <dbl> <chr> <chr>             <dbl>       <dbl>     <dbl>
## 1 1              38 F     ASY                 105          50         1
## 2 0              29 M     ATA                 120         243         0
## # ℹ 5 more variables: RestingECG <chr>, MaxHR <dbl>, ExerciseAngina <chr>,
## #   Oldpeak <dbl>, ST_Slope <chr>

Selamat mencoba!!!

sumber: Support Vector machine (SVM) untuk Model Klasifikasi dengan R