Support vector Machine (SVM) dengan mlr3

Gerry Alfa Dito1

Rahma Anisa2

Package

Silahkan install jika belum ada

install.packages("tidyverse")
install.packages("mlr3verse")
install.packages("e1071")

Memanggil Package

library(tidyverse)
library(mlr3verse)

Deskripsi singkat data

Tutorial kali ini akan menggunakan data yaitu German Credit. Berikut adalah informasi singkat mengenai data

This dataset classifies people described by a set of attributes as good or bad credit risks.

Author: Dr. Hans Hofmann Source: UCI - 1994 Please cite: Dua, D. and Graff, C. (2019). UCI Machine Learning Repository [http://archive.ics.uci.edu/ml]. Irvine, CA: University of California, School of Information and Computer Science.

Attribute description

  1. Status of existing checking account, in Deutsche Mark.
  2. Credit history (credits taken, paid back duly, delays, critical accounts)
  3. Purpose of the credit (car, television,…)
  4. Credit amount
  5. Status of savings account/bonds, in Deutsche Mark.
  6. Present employment, in number of years.
  7. Installment rate in percentage of disposable income
  8. Personal status (married, single,…) and sex
  9. Other debtors / guarantors
  10. Present residence since X years
  11. Property (e.g. real estate)
  12. Age in years
  13. Other installment plans (banks, stores)
  14. Housing (rent, own,…)
  15. Number of existing credits at this bank
  16. Job
  17. Number of people being liable to provide maintenance for
  18. Telephone (yes,no)
  19. Foreign worker (yes,no)
  20. Duration in months

data ini bisa diperoleh di link berikut ini https://www.openml.org/data/get_csv/31/dataset_31_credit-g.arff

Pemodelan SVM

Import data di R

data_credit <- read.csv("german_credit.csv",stringsAsFactors = TRUE)
glimpse(data_credit)
## Rows: 1,000
## Columns: 21
## $ checking_status        <fct> '<0', '0<=X<200', 'no checking', '<0', '<0',...
## $ duration               <int> 6, 48, 12, 42, 24, 36, 24, 36, 12, 30, 12, 4...
## $ credit_history         <fct> 'critical/other existing credit', 'existing ...
## $ purpose                <fct> radio/tv, radio/tv, education, furniture/equ...
## $ credit_amount          <int> 1169, 5951, 2096, 7882, 4870, 9055, 2835, 69...
## $ savings_status         <fct> 'no known savings', '<100', '<100', '<100', ...
## $ employment             <fct> '>=7', '1<=X<4', '4<=X<7', '4<=X<7', '1<=X<4...
## $ installment_commitment <int> 4, 2, 2, 2, 3, 2, 3, 2, 2, 4, 3, 3, 1, 4, 2,...
## $ personal_status        <fct> 'male single', 'female div/dep/mar', 'male s...
## $ other_parties          <fct> none, none, none, guarantor, none, none, non...
## $ residence_since        <int> 4, 2, 3, 4, 4, 4, 4, 2, 4, 2, 1, 4, 1, 4, 4,...
## $ property_magnitude     <fct> 'real estate', 'real estate', 'real estate',...
## $ age                    <int> 67, 22, 49, 45, 53, 35, 53, 35, 61, 28, 25, ...
## $ other_payment_plans    <fct> none, none, none, none, none, none, none, no...
## $ housing                <fct> own, own, own, 'for free', 'for free', 'for ...
## $ existing_credits       <int> 2, 1, 1, 1, 2, 1, 1, 1, 1, 2, 1, 1, 1, 2, 1,...
## $ job                    <fct> skilled, skilled, 'unskilled resident', skil...
## $ num_dependents         <int> 1, 1, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1,...
## $ own_telephone          <fct> yes, none, none, none, none, yes, none, yes,...
## $ foreign_worker         <fct> yes, yes, yes, yes, yes, yes, yes, yes, yes,...
## $ class                  <fct> good, bad, good, good, bad, good, good, good...

Khusus yang menggunakan R versi 4.00 keatas, argumen stringsAsFactors = TRUE disertakan agar data yang berbentuk string bisa berubah menjadi factor.

Import data ke ekosistem mlr3

Import data ke mlr3 bisa dilakukan dengan menggunakan fungsi TaskClassif$new atau TaskRegr$new yang berasal dari package mlr3. TaskClassif$new digunakan jika peubah respon kita berupa peubah biner atau multiclass, sedangkan TaskRegr$new digunakan jika responya berupa peubah numerik.

task_credit = TaskClassif$new(id="credit",backend = data_credit,
                                target = "class",positive ="good")

Argumen utama dalam fungsi TaskClassif$new adalah sebagai berikut:

  1. id yang merupakan nama dari task (bisa diisi dengan nama apapun)
  2. backend adalah data yang ingin dimodelkan dengan catatan peubah respon-nya harus berupa factor
  3. target adalah nama kolom yang dijadikan peubah respon
  4. positive adalah nama kelas positif dari peubah respon

Model SvM tidak bisa dijalankan jika terdapat prediktor dalam kategorik (factor), sehingga variabel-variabel tersebut harus diubah menjadi dummy variable. Dummy variable merupakan variable yang isinya hanya 0 dan 1. Hal ini bisa dilakukan dengan menggunakan fungsi po dengan argumen encode dan method="treatment"

# mendefinisikan fungsi untuk merubah variable kategorik menjadi variable dummy
onehot <- po("encode",method="treatment")
# extract data hasil dummy
data_credit_onehot <- onehot$train(input = list(task_credit))[[1]]$data()
glimpse(data_credit_onehot)
## Rows: 1,000
## Columns: 49
## $ class                                           <fct> good, bad, good, go...
## $ age                                             <int> 67, 22, 49, 45, 53,...
## $ credit_amount                                   <int> 1169, 5951, 2096, 7...
## $ duration                                        <int> 6, 48, 12, 42, 24, ...
## $ existing_credits                                <int> 2, 1, 1, 1, 2, 1, 1...
## $ installment_commitment                          <int> 4, 2, 2, 2, 3, 2, 3...
## $ num_dependents                                  <int> 1, 1, 2, 2, 2, 2, 1...
## $ residence_since                                 <int> 4, 2, 3, 4, 4, 4, 4...
## $ checking_status....200.                         <dbl> 0, 0, 0, 0, 0, 0, 0...
## $ checking_status..0..X.200.                      <dbl> 0, 1, 0, 0, 0, 0, 0...
## $ checking_status..no.checking.                   <dbl> 0, 0, 1, 0, 0, 1, 1...
## $ credit_history..critical.other.existing.credit. <dbl> 1, 0, 1, 0, 0, 0, 0...
## $ credit_history..delayed.previously.             <dbl> 0, 0, 0, 0, 1, 0, 0...
## $ credit_history..existing.paid.                  <dbl> 0, 1, 0, 1, 0, 1, 1...
## $ credit_history..no.credits.all.paid.            <dbl> 0, 0, 0, 0, 0, 0, 0...
## $ employment....7.                                <dbl> 1, 0, 0, 0, 0, 0, 1...
## $ employment..1..X.4.                             <dbl> 0, 1, 0, 0, 1, 1, 0...
## $ employment..4..X.7.                             <dbl> 0, 0, 1, 1, 0, 0, 0...
## $ employment.unemployed                           <dbl> 0, 0, 0, 0, 0, 0, 0...
## $ foreign_worker.yes                              <dbl> 1, 1, 1, 1, 1, 1, 1...
## $ housing.own                                     <dbl> 1, 1, 1, 0, 0, 0, 1...
## $ housing.rent                                    <dbl> 0, 0, 0, 0, 0, 0, 0...
## $ job..unemp.unskilled.non.res.                   <dbl> 0, 0, 0, 0, 0, 0, 0...
## $ job..unskilled.resident.                        <dbl> 0, 0, 1, 0, 0, 1, 0...
## $ job.skilled                                     <dbl> 1, 1, 0, 1, 1, 0, 1...
## $ other_parties.guarantor                         <dbl> 0, 0, 0, 1, 0, 0, 0...
## $ other_parties.none                              <dbl> 1, 1, 1, 0, 1, 1, 1...
## $ other_payment_plans.none                        <dbl> 1, 1, 1, 1, 1, 1, 1...
## $ other_payment_plans.stores                      <dbl> 0, 0, 0, 0, 0, 0, 0...
## $ own_telephone.yes                               <dbl> 1, 0, 0, 0, 0, 1, 0...
## $ personal_status..male.div.sep.                  <dbl> 0, 0, 0, 0, 0, 0, 0...
## $ personal_status..male.mar.wid.                  <dbl> 0, 0, 0, 0, 0, 0, 0...
## $ personal_status..male.single.                   <dbl> 1, 0, 1, 1, 1, 1, 1...
## $ property_magnitude..no.known.property.          <dbl> 0, 0, 0, 0, 1, 1, 0...
## $ property_magnitude..real.estate.                <dbl> 1, 1, 1, 0, 0, 0, 0...
## $ property_magnitude.car                          <dbl> 0, 0, 0, 0, 0, 0, 0...
## $ purpose..new.car.                               <dbl> 0, 0, 0, 0, 1, 0, 0...
## $ purpose..used.car.                              <dbl> 0, 0, 0, 0, 0, 0, 0...
## $ purpose.business                                <dbl> 0, 0, 0, 0, 0, 0, 0...
## $ purpose.education                               <dbl> 0, 0, 1, 0, 0, 1, 0...
## $ purpose.furniture.equipment                     <dbl> 0, 0, 0, 1, 0, 0, 1...
## $ purpose.other                                   <dbl> 0, 0, 0, 0, 0, 0, 0...
## $ purpose.radio.tv                                <dbl> 1, 1, 0, 0, 0, 0, 0...
## $ purpose.repairs                                 <dbl> 0, 0, 0, 0, 0, 0, 0...
## $ purpose.retraining                              <dbl> 0, 0, 0, 0, 0, 0, 0...
## $ savings_status....1000.                         <dbl> 0, 0, 0, 0, 0, 0, 0...
## $ savings_status..100..X.500.                     <dbl> 0, 0, 0, 0, 0, 0, 0...
## $ savings_status..500..X.1000.                    <dbl> 0, 0, 0, 0, 0, 0, 1...
## $ savings_status..no.known.savings.               <dbl> 1, 0, 0, 0, 0, 1, 0...
# import kembali ke mlr3
task_credit = TaskClassif$new(id="credit",backend = data_credit_onehot,
                                target = "class",positive ="good")

Menentukan model yang digunakan

Pada tahap ini fungsi yang digunakan adalah lrn yang memiliki argumen utama nama model yang ingin digunakan. Berikut adalah model-model yang akan digunakan beserta argumen di dalam fungsi lrn dan asal packagenya:

  1. SVM - "classif.svm" - library(e1071)

Sebagai catatan, untuk model-model yang digunakan dalam mlr3 berasal dari package-package lain sehingga package-package tersebut perlu install terlebih dahulu.

Argumen-argumen yang bisa dimasukkan pada "classif.naive_bayes" dan "classif.svm"adalah sebagai berikut.

as.data.table(lrn("classif.svm")$param_set)
##                  id    class lower upper                             levels
##  1:            type ParamFct    NA    NA C-classification,nu-classification
##  2:            cost ParamDbl     0   Inf                                   
##  3:              nu ParamDbl  -Inf   Inf                                   
##  4:          kernel ParamFct    NA    NA   linear,polynomial,radial,sigmoid
##  5:          degree ParamInt     1   Inf                                   
##  6:           coef0 ParamDbl  -Inf   Inf                                   
##  7:           gamma ParamDbl     0   Inf                                   
##  8:       cachesize ParamDbl  -Inf   Inf                                   
##  9:       tolerance ParamDbl     0   Inf                                   
## 10:       shrinking ParamLgl    NA    NA                         TRUE,FALSE
## 11:           cross ParamInt     0   Inf                                   
## 12:          fitted ParamLgl    NA    NA                         TRUE,FALSE
## 13:           scale ParamUty    NA    NA                                   
## 14:   class.weights ParamUty    NA    NA                                   
## 15: decision.values ParamLgl    NA    NA                         TRUE,FALSE
##     nlevels is_bounded special_vals          default storage_type    tags
##  1:       2       TRUE    <list[0]> C-classification    character   train
##  2:     Inf      FALSE    <list[0]>                1      numeric   train
##  3:     Inf      FALSE    <list[0]>              0.5      numeric   train
##  4:       4       TRUE    <list[0]>           radial    character   train
##  5:     Inf      FALSE    <list[0]>                3      integer   train
##  6:     Inf      FALSE    <list[0]>                0      numeric   train
##  7:     Inf      FALSE    <list[0]>   <NoDefault[3]>      numeric   train
##  8:     Inf      FALSE    <list[0]>               40      numeric   train
##  9:     Inf      FALSE    <list[0]>            0.001      numeric   train
## 10:       2       TRUE    <list[0]>             TRUE      logical   train
## 11:     Inf      FALSE    <list[0]>                0      integer   train
## 12:       2       TRUE    <list[0]>             TRUE      logical   train
## 13:     Inf      FALSE    <list[0]>             TRUE         list   train
## 14:     Inf      FALSE    <list[0]>                          list   train
## 15:       2       TRUE    <list[0]>            FALSE      logical predict

Keterangan untuk masing-masing argumen dapat melihat package asal kedua metode yaitu package e1071.

Pada tutorial ini kita akan membandingkan performa model SVM dengan berbagai macam kernel. Untuk menjalankan model svm dengan berbagai macam kernel kita bisa tulis seperti dibawah ini

model_svm_linear <- lrn("classif.svm",kernel="linear",id="svm.linear")
model_svm_polinomial <- lrn("classif.svm",kernel="polynomial",id="svm.polinomial")
model_svm_radial <- lrn("classif.svm",kernel="radial",id="svm.radial")
model_svm_sigmoid <-lrn("classif.svm",kernel="sigmoid",id="svm.sigmoid")

Menentukan cara pembagian data

Penentuan cara pembagian data bisa dilakukan dengan fungsi rsmp.

resample_credit_cv = rsmp("cv",folds=10)

Metode pembagian data yang dipilih disini adalah metode cross-validation dengan 10 folds atau lipatan. Setelah kedua hal ini sudah dilakukan, selanjutnya komparasi model bisa dilakukan

Komparasi model

Pada bagian ini kita akan melakukan komparasi model antar model yang sudah kita definisikan diatas. Langkah pertama yang kita lakukan adalah mengabungkan learner yang sudah kita definisikan diawal ke dalam list

learner_credit <- list(model_svm_linear,
                       model_svm_polinomial,
                       model_svm_radial,
                       model_svm_sigmoid)

Komparasi model bisa dilakukan dengan menggunakan fungsi benchmark_design dan benchmark. Fungsi benchmark_design digunakan untuk memasukan informasi-inforamsi yang dibutuhkan untuk komparasi, seperti data yang digunakan (tasks), model yang ingin dikomparasi (learners) dan metode pembagian data yang digunakan (resamplings).

design <- benchmark_grid(tasks = task_credit,
                         learners = learner_credit,
                         resamplings = resample_credit_cv 
                         )

Kemudian fungsi benchmark digunakan untuk menjalankan/ running komparasi model berdasarkan desain yang sudah dirancang.

bmr = benchmark(design,store_models = TRUE)
## INFO  [13:56:17.865] Benchmark with 40 resampling iterations 
## INFO  [13:56:18.229] Applying learner 'svm.radial' on task 'credit' (iter 10/10) 
## INFO  [13:56:18.632] Applying learner 'svm.sigmoid' on task 'credit' (iter 3/10) 
## INFO  [13:56:18.854] Applying learner 'svm.radial' on task 'credit' (iter 3/10) 
## INFO  [13:56:19.151] Applying learner 'svm.radial' on task 'credit' (iter 8/10) 
## INFO  [13:56:19.425] Applying learner 'svm.sigmoid' on task 'credit' (iter 7/10) 
## INFO  [13:56:19.645] Applying learner 'svm.linear' on task 'credit' (iter 4/10) 
## INFO  [13:56:19.990] Applying learner 'svm.linear' on task 'credit' (iter 6/10) 
## INFO  [13:56:20.318] Applying learner 'svm.linear' on task 'credit' (iter 2/10) 
## INFO  [13:56:20.588] Applying learner 'svm.polinomial' on task 'credit' (iter 5/10) 
## INFO  [13:56:20.862] Applying learner 'svm.linear' on task 'credit' (iter 3/10) 
## INFO  [13:56:21.126] Applying learner 'svm.sigmoid' on task 'credit' (iter 9/10) 
## INFO  [13:56:21.358] Applying learner 'svm.polinomial' on task 'credit' (iter 6/10) 
## INFO  [13:56:21.641] Applying learner 'svm.radial' on task 'credit' (iter 7/10) 
## INFO  [13:56:21.935] Applying learner 'svm.polinomial' on task 'credit' (iter 1/10) 
## INFO  [13:56:22.160] Applying learner 'svm.linear' on task 'credit' (iter 8/10) 
## INFO  [13:56:22.474] Applying learner 'svm.sigmoid' on task 'credit' (iter 8/10) 
## INFO  [13:56:22.641] Applying learner 'svm.radial' on task 'credit' (iter 4/10) 
## INFO  [13:56:22.828] Applying learner 'svm.polinomial' on task 'credit' (iter 3/10) 
## INFO  [13:56:22.994] Applying learner 'svm.linear' on task 'credit' (iter 10/10) 
## INFO  [13:56:23.171] Applying learner 'svm.polinomial' on task 'credit' (iter 10/10) 
## INFO  [13:56:23.334] Applying learner 'svm.linear' on task 'credit' (iter 7/10) 
## INFO  [13:56:23.526] Applying learner 'svm.sigmoid' on task 'credit' (iter 5/10) 
## INFO  [13:56:23.656] Applying learner 'svm.linear' on task 'credit' (iter 9/10) 
## INFO  [13:56:23.831] Applying learner 'svm.polinomial' on task 'credit' (iter 9/10) 
## INFO  [13:56:23.991] Applying learner 'svm.sigmoid' on task 'credit' (iter 2/10) 
## INFO  [13:56:24.127] Applying learner 'svm.sigmoid' on task 'credit' (iter 4/10) 
## INFO  [13:56:24.303] Applying learner 'svm.radial' on task 'credit' (iter 9/10) 
## INFO  [13:56:24.533] Applying learner 'svm.polinomial' on task 'credit' (iter 8/10) 
## INFO  [13:56:24.701] Applying learner 'svm.radial' on task 'credit' (iter 1/10) 
## INFO  [13:56:24.866] Applying learner 'svm.polinomial' on task 'credit' (iter 7/10) 
## INFO  [13:56:25.026] Applying learner 'svm.linear' on task 'credit' (iter 5/10) 
## INFO  [13:56:25.195] Applying learner 'svm.polinomial' on task 'credit' (iter 4/10) 
## INFO  [13:56:25.349] Applying learner 'svm.sigmoid' on task 'credit' (iter 1/10) 
## INFO  [13:56:25.483] Applying learner 'svm.linear' on task 'credit' (iter 1/10) 
## INFO  [13:56:25.697] Applying learner 'svm.radial' on task 'credit' (iter 6/10) 
## INFO  [13:56:25.949] Applying learner 'svm.sigmoid' on task 'credit' (iter 10/10) 
## INFO  [13:56:26.078] Applying learner 'svm.radial' on task 'credit' (iter 5/10) 
## INFO  [13:56:26.258] Applying learner 'svm.sigmoid' on task 'credit' (iter 6/10) 
## INFO  [13:56:26.386] Applying learner 'svm.polinomial' on task 'credit' (iter 2/10) 
## INFO  [13:56:26.546] Applying learner 'svm.radial' on task 'credit' (iter 2/10) 
## INFO  [13:56:26.726] Finished benchmark

Karena terdapat 4 model dan masing-masing model menjalankan 10-folds cross-validation maka iterasi yang dilakukan ada sebanyak 40 kali.

Hasil Komparasi model

Hasil komparasi model dapat berupa nilai-nilai ukuran kebaikan model yang ditentukan oleh pengguna.

result = bmr$aggregate(list(msr("classif.acc"),
                            msr("classif.bacc") # balanced accuracy
                            ,
                                msr("classif.sensitivity"),
                                msr("classif.specificity")
                                )
              )
result
##    nr      resample_result task_id     learner_id resampling_id iters
## 1:  1 <ResampleResult[21]>  credit     svm.linear            cv    10
## 2:  2 <ResampleResult[21]>  credit svm.polinomial            cv    10
## 3:  3 <ResampleResult[21]>  credit     svm.radial            cv    10
## 4:  4 <ResampleResult[21]>  credit    svm.sigmoid            cv    10
##    classif.acc classif.bacc classif.sensitivity classif.specificity
## 1:       0.746    0.6691705           0.8594021           0.4789389
## 2:       0.728    0.5685364           0.9646384           0.1724344
## 3:       0.755    0.6454081           0.9201139           0.3707022
## 4:       0.732    0.6320493           0.8831174           0.3809811