1 Classification and Regression Tree (CART)

  • Also known as: Classification Tree or Decision Tree or Recursive Partition or Iterative Dichotomiser.

  • Kegunaan :

    • Mengidentifikasi variabel apa yang dapat dijadikan sebagai pembeda antar kelompok

    • Memprediksi keanggotaan kelompok suatu individu berdasarkan karakteristiknya.

  • Terapannya antara lain:

    • Marketing: Mengidentifikasi prospective customer (cross-sell, up-sell, new acquisition)

    • Risk: Credit scoring, menentukan apakah calon penerima kredit akan mampu bayar atau tidak.

    • Customer Relationship: churn analysis, menentukan customer yang berpotensi akan meninggalkan jasa/produk

    • Health: menentukan tingkat resiko penyakit, dll.

  • Metode lain yang setara kegunaannya Regresi Logistik, k-Nearest Neighbor, Discriminant Analysis, Support Vector Machine, Bayesian Classifier, dll.

2 Entropry dan Information Gain

  • Andaikan sebuah gugus data D berisi individu-individu dengan dua kelas yaitu kelas YES dan NO, dengan proporsi yang YES sebesar p, dan tentusaja (1 – p) lainnya tergolong kelas NO.

  • Entropi dari gugus data tersebut adalah \(E(D) = -p \ log_2(p) - (1-p) \ log_2 \ (1-p)\)

  • Gugus data yang seluruh amatannya dari kelas YES akan memiliki \(E(D) = 0\).

  • Gugus data yang seluruh amatannya dari kelas NO juga akan memiliki \(E(D) = 0\) .

  • Entropi ini adalah ukuran keheterogenan data (impurity).

  • Andaikan sebuah gugus data D dibagi menjadi beberapa kelompok, misalnya \(D_1, D_2, ..., D_k\) berdasarkan variabel prediktor \(V\).

  • Dari setiap Di bisa dihitung entropinya, yaitu \(E(D_i)\)

  • Information Gain adalah \(IG(D,V) = E(D)- \sum \limits_{i=1}^k {\frac {|D_i|} {|D|} E(D_i)}\)

  • Pemisahan yang menghasilkan kelompok-kelompok yang homogen -> memiliki information gain yang semakin besar.

3 Classification Tree

  • Mencari pemisah terbaik yang menyebabkan data hasil pemisahannya bersifat homogen kelasnya.

  • Tahap 1: Mencari pemisahan/penyekatan (splitting) terbaik di setiap variabel.

  • Tahap 2: Menentukan variabel terbaik untuk penyekatan.

  • Tahap 3: Melakukan penyekatan berdasarkan hasil dari Tahap 2, dan memeriksa apakah sudah waktunya menghentikan proses.

  • Kriteria Penghentian Proses Pemisahan

    • Simpul berisi amatan yang berasal dari satu kelas variabel respon

    • Simpul berisi amatan yang seluruh variabel prediktornya identik

    • Simpul berisi amatan yang kurang dari ukuran simpul minimal yang ditentukan di awal.

    • Kedalaman pohon sudah mencapai kedalaman maksimal

  • Prediksi Variabel Respon

    • Untuk setiap individu yang diketahui nilai-nilai variabel prediktor yang muncul pada pohon klasifikasi, kita dapat melakukan prediksi kelas variabel respon. Misalnya jika diketahui usia, jenis kelamin, apakah merokok, dan klasifikasi budget dari seseorang, maka kita dapat memprediksi apakah orang tersebut akan tertarik atau tidak.

    • Bagaimana caranya? Gunakan alur pencabangan yang ada pada pohon klasifikasi sampai berhenti di simpul akhir. Berdasarkan simpul akhir itulah kita prediksi dia masuk ke kategori apa.

Accuracy

Actual / Predicted Class 0 1
0 True Negative False Positive Actual Negative
1 False Negative True Positive Actual Positive
Predicted Negative Predicted Positive

Correct Rate = (True Positive + True Negative) / N

Sensitivity

Actual / Predicted Class 0 1
0
1 True Positive Actual Positive
Predicted Positive

SENSITIVITY adalah TRUE POSITIVE dibagi dengan N1. Jika cutoff nilai prediksi peluang yang digunakan kecil, maka individu cenderung akan diprediksi memiliki kategori 1 (YES). Sehingga pada saat nilai cutoff kecil, maka sensitivity ini akan besar (mendekati 100%). Secara umum nilai sensitivity ini akan menurun jika nilai cutoff ditingkatkan. Namun secara ideal kita menginginkan untuk berbagai nilai cutoff, model memiliki sensitivity yang tinggi.

Specificity

Actual / Predicted Class 0 1
0 True Negative Actual Negative
1
Predicted Negative

SPECIFICITY adalah TRUE NEGATIVE dibagi dengan N2 Tentu saja 1 – Specificity adalah 1 dikurangi nilai specificity-nya, atau diperoleh dari FALSE POSITIVE dibagi dengan N2. Jika cutoff nilai prediksi peluang yang digunakan kecil, maka individu cenderung akan diprediksi memiliki kategori 1 (YES). Sehingga pada saat nilai cutoff kecil, maka (1 – specificity) ini akan besar (mendekati 100%). Secara umum nilai (1 – specificity) ini akan menurun jika nilai cutoff ditingkatkan. Namun secara ideal kita menginginkan untuk berbagai nilai cutoff, model memiliki (1 – specificity) yang rendah.

ROC Curve

  • An ideal ROC curve is a vertical line from the origin to a sensitivity of 1, and then a horizontal line along sensitivity of 1 for all level of (1 – specificity).

  • ROC curve is usually used to compare competing model.

  • A numerical measure of how close the ROC curve match the ideal curve is computed by comparing the area under the curve to 1. It turns out the area is equal to the c statistic.

4 Kasus Klasifikasi Biner

Persiapan Data

library(caret)
## Loading required package: ggplot2
## Loading required package: lattice
library(rpart)
library(rpart.plot)
library(randomForest)
## randomForest 4.7-1.1
## Type rfNews() to see new features/changes/bug fixes.
## 
## Attaching package: 'randomForest'
## The following object is masked from 'package:ggplot2':
## 
##     margin
setwd("D:/Kuliah/Mat/TSA Kominfo/Praktikum")
data <- read.csv("4. galaxy_quasar_star.csv")
head(data, 15)
##     X  class      alpha      delta        u        g        r        i      i.1
## 1   0 GALAXY 135.689107 32.4946318 23.87882 22.27530 20.39501 19.16573 19.16573
## 2   1 GALAXY 144.826101 31.2741849 24.77759 22.83188 22.58444 21.16812 21.16812
## 3   2 GALAXY 142.188790 35.5824442 25.26307 22.66389 20.60976 19.34857 19.34857
## 4   3 GALAXY 338.741038 -0.4028276 22.13682 23.77656 21.61162 20.50454 20.50454
## 5   4 GALAXY 345.282593 21.1838656 19.43718 17.58028 16.49747 15.97711 15.97711
## 6   5    QSO 340.995121 20.5894763 23.48827 23.33776 21.32195 20.25615 20.25615
## 7   6    QSO  23.234926 11.4181876 21.46973 21.17624 20.92829 20.60826 20.60826
## 8   7 GALAXY   5.433176 12.0651860 22.24979 22.02172 20.34126 19.48794 19.48794
## 9   8 GALAXY 200.290475 47.1994023 24.40286 22.35669 20.61032 19.46490 19.46490
## 10  9   STAR  39.149691 28.1028416 21.74669 20.03493 19.17553 18.81823 18.81823
## 11 10 GALAXY 328.092076 18.2203105 25.77163 22.52042 20.63884 19.78071 19.78071
## 12 11 GALAXY 243.986637 25.7382804 23.76761 23.79969 20.98318 19.80745 19.80745
## 13 12   STAR 345.801874 32.6728679 23.17274 20.14496 19.41948 19.22034 19.22034
## 14 13 GALAXY 331.502030 10.0358020 20.82940 18.75091 17.51118 17.01631 17.01631
## 15 14 GALAXY 344.984770 -0.3526158 23.20911 22.79291 22.08589 21.86282 21.86282
##           z cam_col field_ID      redshift plate   MJD
## 1  18.79371       2       79  6.347936e-01  5812 56354
## 2  21.61427       5      119  7.791360e-01 10445 58158
## 3  18.94827       2      120  6.441945e-01  4576 55592
## 4  19.25010       3      214  9.323456e-01  9149 58039
## 5  15.54461       3      137  1.161227e-01  6121 56187
## 6  19.54544       3      110  1.424659e+00  5026 55855
## 7  20.42573       2      462  5.864546e-01 11069 58456
## 8  18.84999       2      346  4.770090e-01  6183 56210
## 9  18.95852       5      108  6.600120e-01  6625 56386
## 10 18.65422       4      122 -7.895373e-06  2444 54082
## 11 19.05765       3       27  4.595958e-01  5020 55852
## 12 19.45579       4      112  5.914091e-01  4727 55693
## 13 18.89359       2       38  7.182029e-05  6504 56540
## 14 16.62772       2      123  1.521936e-01  5065 55739
## 15 21.85120       3      255  8.181597e-01  9215 57682
# melihat daftar kategori pada kolom class
unique(data$class)
## [1] "GALAXY" "QSO"    "STAR"
# Untuk klasifikasi biner (STAR vs NON-STAR) maka kita akan menggabungkan kelas GALAXY dan QSO
#
data$class <- as.factor(ifelse(data$class=="STAR", "STAR", "NON-STAR"))   # dapat juga dijadikan angka 0 dan 1 saja (0: bukan STAR, 1: STAR)
# komposisi masing-masing kategori
table(data$class)
## 
## NON-STAR     STAR 
##    78406    21594

Pembagian Data

# Membagi data Latih dan Data Uji

library(caret)

set.seed(100)  # Untuk hasil yang dapat direproduksi

# Fungsi createDataPartition dari paket caret untuk membagi data
# dengan menghasilkan indeks data latih dan data uji
# data latih = 70%, # data uji = 30%
trainIndex <- createDataPartition(data$class, p = 0.70, list = FALSE, times = 1)

# Buat data latih dan data uji berdasarkan indeks yang dihasilkan
data.train <- data[trainIndex, ]
data.test <- data[-trainIndex, ]
# melihat komposisi setiap kelas pada data train dan test
cbind("train" = table(data.train$class), "test" = table(data.test$class))
##          train  test
## NON-STAR 54885 23521
## STAR     15116  6478

4.1 Model Regresi Logistik

Regresi Logistik (Biner) adalah metode statistik yang digunakan untuk memodelkan hubungan antara variabel independen (biasanya merupakan faktor-faktor prediktif atau fitur) dan variabel dependen yang bersifat biner (dua kategori, seperti ya/tidak, 1/0, sukses/gagal). Tujuan utama dari regresi logistik biner adalah untuk memprediksi probabilitas suatu kejadian dalam salah satu dari dua kategori tersebut.

Regresi logistik biner menggunakan fungsi logistik atau sigmoid untuk mengubah nilai-nilai dari variabel independen menjadi probabilitas dalam rentang 0 hingga 1. Model ini memperkirakan parameter-parameter yang menggambarkan sejauh mana setiap variabel independen mempengaruhi probabilitas kejadian kategori positif. Hasilnya adalah model yang dapat digunakan untuk memprediksi peluang atau probabilitas sukses atau kegagalan suatu kejadian berdasarkan faktor-faktor yang diberikan.

Model

options(warn = -1)  # Suppress all warnings

# model regresi logistik (biner) menggunakan fungsi glm
# dengan mengatur family="binomial"
model.rl <- glm(class ~ ., data=data.train, family="binomial")

summary(model.rl)
## 
## Call:
## glm(formula = class ~ ., family = "binomial", data = data.train)
## 
## Coefficients: (1 not defined because of singularities)
##               Estimate Std. Error    z value Pr(>|z|)    
## (Intercept) -9.003e+14  3.104e+07 -2.901e+07   <2e-16 ***
## X           -2.015e+08  8.801e+00 -2.289e+07   <2e-16 ***
## alpha       -3.436e+11  2.695e+03 -1.275e+08   <2e-16 ***
## delta       -2.118e+11  1.336e+04 -1.585e+07   <2e-16 ***
## u            2.626e+13  2.354e+05  1.116e+08   <2e-16 ***
## g           -1.857e+14  4.212e+05 -4.408e+08   <2e-16 ***
## r            4.694e+14  7.997e+05  5.870e+08   <2e-16 ***
## i           -2.106e+14  8.284e+05 -2.543e+08   <2e-16 ***
## i.1                 NA         NA         NA       NA    
## z            1.590e+14  3.139e+05  5.065e+08   <2e-16 ***
## cam_col      2.637e+13  1.603e+05  1.645e+08   <2e-16 ***
## field_ID    -2.412e+11  1.760e+03 -1.371e+08   <2e-16 ***
## redshift    -2.430e+15  4.099e+05 -5.930e+09   <2e-16 ***
## plate        2.275e+09  3.630e+02  6.267e+06   <2e-16 ***
## MJD         -6.769e+10  6.000e+02 -1.128e+08   <2e-16 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## (Dispersion parameter for binomial family taken to be 1)
## 
##     Null deviance:  73042  on 70000  degrees of freedom
## Residual deviance: 489977  on 69987  degrees of freedom
## AIC: 490005
## 
## Number of Fisher Scoring iterations: 25

Prediksi (Data Latih)

# Memprediksi data TRAIN
pred.train <- predict(model.rl, newdata = data.train, type="response")

# p <= 0.5 menjadi "NON-STAR" dan > 0,5 menjadi STAR
pred.train.label <- as.factor(ifelse(pred.train > 0.5, "STAR", "NON-STAR"))

# untuk membuat confusion Matrix
confusionMatrix(data = pred.train.label,
                reference = data.train$class,
                positive="STAR")
## Confusion Matrix and Statistics
## 
##           Reference
## Prediction NON-STAR  STAR
##   NON-STAR    53542  5454
##   STAR         1343  9662
##                                           
##                Accuracy : 0.9029          
##                  95% CI : (0.9007, 0.9051)
##     No Information Rate : 0.7841          
##     P-Value [Acc > NIR] : < 2.2e-16       
##                                           
##                   Kappa : 0.6819          
##                                           
##  Mcnemar's Test P-Value : < 2.2e-16       
##                                           
##             Sensitivity : 0.6392          
##             Specificity : 0.9755          
##          Pos Pred Value : 0.8780          
##          Neg Pred Value : 0.9076          
##              Prevalence : 0.2159          
##          Detection Rate : 0.1380          
##    Detection Prevalence : 0.1572          
##       Balanced Accuracy : 0.8074          
##                                           
##        'Positive' Class : STAR            
## 

Prediksi & Validasi (Data Uji)

Prediksi dan Evaluasi pada data uji diperlukan unutk mengetahui performa model yang sebenarnya ketika melakukan prediksi pada data baru (belum pernah dilihat model selama pelatihan).

# Memprediksi data TEST
pred.test <- predict(model.rl, newdata = data.test, type="response")

# p <= 0.5 menjadi "NON-STAR" dan > 0,5 menjadi STAR
pred.test.label <- factor(ifelse(pred.test > 0.5, "STAR", "NON-STAR"))
# library caret
# untuk membuat confusion Matrix
confusionMatrix(data = pred.test.label,
                reference = data.test$class,
                positive="STAR")
## Confusion Matrix and Statistics
## 
##           Reference
## Prediction NON-STAR  STAR
##   NON-STAR    22914  2465
##   STAR          607  4013
##                                          
##                Accuracy : 0.8976         
##                  95% CI : (0.8941, 0.901)
##     No Information Rate : 0.7841         
##     P-Value [Acc > NIR] : < 2.2e-16      
##                                          
##                   Kappa : 0.6625         
##                                          
##  Mcnemar's Test P-Value : < 2.2e-16      
##                                          
##             Sensitivity : 0.6195         
##             Specificity : 0.9742         
##          Pos Pred Value : 0.8686         
##          Neg Pred Value : 0.9029         
##              Prevalence : 0.2159         
##          Detection Rate : 0.1338         
##    Detection Prevalence : 0.1540         
##       Balanced Accuracy : 0.7968         
##                                          
##        'Positive' Class : STAR           
## 

Secara keseluruhan model regresi logistik memiliki akurasi yang baik yaitu 0.8105, atau model mampu memprediksi benar 81,05% dari total 29.999 data uji. Namun jika melihat dari nilai sensitivitas dan spesifisitas, masih terdapat ketidakseimbangan. Dapat dilihat bahwa model mampu dengan sangat baik menebak benar objek STAR yaitu sebesar 93,61% atau 6.064 dari 6.478 amatan. Namun model tidak terlalu baik dalam memprediksi kelas NON-STAR yaitu sebesar 78,41% saja atau 18.249 dari 23.521 amatan.

4.2 CART (Decission Tree)

Pemodelan CART (Classification and Regression Trees) adalah sebuah metode dalam data mining dan machine learning yang digunakan untuk menghasilkan model prediksi berdasarkan struktur pohon. Dalam pemodelan CART, data dipisahkan berdasarkan serangkaian keputusan biner yang dibuat berdasarkan fitur-fitur yang ada. Setiap pemisahan bertujuan untuk meminimalkan ketidakmurnian dalam setiap kelompok data yang dihasilkan. Pohon ini dapat digunakan baik untuk tugas klasifikasi (memisahkan data ke dalam kategori) maupun regresi (mengestimasi nilai berdasarkan variabel input). Pemodelan CART sering digunakan dalam berbagai aplikasi, termasuk pengambilan keputusan, analisis risiko, dan pemodelan prediktif. Metode ini memiliki keunggulan karena mudah diinterpretasikan, tetapi juga dapat menjadi kompleks jika tidak diatur dengan baik.

Model

model.cart <- rpart(class ~ ., data=data.train, method = "class")

model.cart
## n= 70001 
## 
## node), split, n, loss, yval, (yprob)
##       * denotes terminal node
## 
## 1) root 70001 15116 NON-STAR (0.78406023 0.21593977)  
##   2) redshift>=0.004171235 54521     0 NON-STAR (1.00000000 0.00000000) *
##   3) redshift< 0.004171235 15480   364 STAR (0.02351421 0.97648579) *

Visualisasi Tree

Pada contoh dataset ini, menarik untuk dilihat bahwa proses pemisahan node hanya berlangsung 1 kali saja yaitu dengan peubah redshift. Hal ini menunjukkan, secara umum 1peubah ini sudah lebih dari cukup untuk menjelaskan tentang perbedaan antara kelas STAR dan NON-STAR.

rpart.plot(model.cart)

Prediksi & Validasi (Data Uji)

# Memprediksi data TEST
pred.test.cart <- predict(model.cart, newdata = data.test, type="class")

# Melihat prediksi pada 5 data.test yang pertama
head(pred.test.cart, 10)
##        1        2        6        9       12       14       18       19 
## NON-STAR NON-STAR NON-STAR NON-STAR NON-STAR NON-STAR NON-STAR     STAR 
##       21       22 
## NON-STAR     STAR 
## Levels: NON-STAR STAR
# untuk membuat confusion Matrix
confusionMatrix(data = pred.test.cart,
                reference = data.test$class)
## Confusion Matrix and Statistics
## 
##           Reference
## Prediction NON-STAR  STAR
##   NON-STAR    23369     0
##   STAR          152  6478
##                                           
##                Accuracy : 0.9949          
##                  95% CI : (0.9941, 0.9957)
##     No Information Rate : 0.7841          
##     P-Value [Acc > NIR] : < 2.2e-16       
##                                           
##                   Kappa : 0.9852          
##                                           
##  Mcnemar's Test P-Value : < 2.2e-16       
##                                           
##             Sensitivity : 0.9935          
##             Specificity : 1.0000          
##          Pos Pred Value : 1.0000          
##          Neg Pred Value : 0.9771          
##              Prevalence : 0.7841          
##          Detection Rate : 0.7790          
##    Detection Prevalence : 0.7790          
##       Balanced Accuracy : 0.9968          
##                                           
##        'Positive' Class : NON-STAR        
## 

Akurasi yang diperoleh dari model CART di atas sangat tinggi dan jauh lebih baik dibandingkan model Regresi Logistik dengan nilai mencapai 0.9949. Dengan kata lain model mampu memprediksi 99.49% kelas dari data uji. Dalam hal ini dari 29.999 jumlah amatan pada data uji, hanya 152 yang tidak tepat diprediksi.

4.3 RANDOM FOREST

Random Forest merupakan salah satu ensamble model berbasis pohon (Gabungan banyak pohon) yang sering kali memberikan performa model sangat baik bahkan dengan pengaturan default saja. Sebagai pembanding, berikut ini adalah model random forest dengan 100 pohon, untuk memodelkan permasalahan yang sama seperti model reghresi logistik di atas.

library(randomForest)

Model

Model random forest dapat dibuat dengan menggunakan fungsi randomForest dari package randomForest. Terdapat beberapa parameter yang dapat diatur meliputi ntree, mtry, nodesize, maxnodes dan lainnya. (Silahkan kunjungi dokumentasi untuk penjelasan masing-masing parameter)

model.rf <- randomForest(class ~ ., data = data.train, ntree = 100)
print(model.rf$confusion[,1:2])
##          NON-STAR  STAR
## NON-STAR    54731   154
## STAR            6 15110

Peubah Penting

model.rf$importance
##          MeanDecreaseGini
## X                62.33471
## alpha           229.14464
## delta           141.17664
## u               436.61084
## g               648.75209
## r               373.28329
## i               258.60143
## i.1             269.67543
## z               326.68492
## cam_col          28.75389
## field_ID         75.38800
## redshift      19116.47137
## plate           939.56202
## MJD             809.23468

Prediksi & Validasi (Data Uji)

predictions <- predict(model.rf, data.test)

Hasil prediksi dan validasi model raondom forest pada data uji menunjukkan performa yang sangat baik. Dimana akurasi yang dihasilkan jauh lebih baik dibandingkan model regresi logistik maupun CART. Nilai akurasi yang diperoleh adalah sebesar 0.99982, atau dengan kata lain model mampu memprediksi benar klasifikasi 99.87% dari data uji. Dapat dilihat melalui confussion matrix bahwa dari 29.999 data uji, hanya 133 observasi yang salah diprediksi.

Nilai Sensitivity dan spesifisity juga menunjukkan hasil yang sama, dimana berarti model mampu memprediksi sama baiknya dan lebih dari 99% baik itu untuk kelas STAR maupun NON-STAR.

# Evaluate the classification model
confusionMatrix(data = predictions,
                reference = data.test$class,
                positive="STAR")
## Confusion Matrix and Statistics
## 
##           Reference
## Prediction NON-STAR  STAR
##   NON-STAR    23462     1
##   STAR           59  6477
##                                           
##                Accuracy : 0.998           
##                  95% CI : (0.9974, 0.9985)
##     No Information Rate : 0.7841          
##     P-Value [Acc > NIR] : < 2.2e-16       
##                                           
##                   Kappa : 0.9941          
##                                           
##  Mcnemar's Test P-Value : 1.858e-13       
##                                           
##             Sensitivity : 0.9998          
##             Specificity : 0.9975          
##          Pos Pred Value : 0.9910          
##          Neg Pred Value : 1.0000          
##              Prevalence : 0.2159          
##          Detection Rate : 0.2159          
##    Detection Prevalence : 0.2179          
##       Balanced Accuracy : 0.9987          
##                                           
##        'Positive' Class : STAR            
## 

Tuning Hyperparameter

Tuning hyperparameter dalam pemodelan machine learning adalah proses yang penting untuk mengoptimalkan kinerja model. Proses ini melibatkan penyesuaian parameter-parameter yang tidak diperoleh dari model itu sendiri, tetapi memengaruhi cara model mempelajari pola dari data. Hyperparameter bisa mencakup berbagai aspek seperti larning rate pada XGBoost, kedalaman pohon dalam CART dan Random Forest, jumlah tetangga dalam algoritma k-Nearest Neighbors (KNN), dan banyak lagi.

Tujuan tuning hyperparameter adalah menemukan kombinasi nilai yang paling sesuai untuk hyperparameter-hyperparameter tersebut sehingga model dapat menghasilkan prediksi yang akurat dan generalisasi yang baik terhadap data yang belum pernah dilihat sebelumnya. Ini sering dilakukan melalui teknik Grid Search atau Random Search dan validasi silang, di mana berbagai nilai hyperparameter diuji pada data pelatihan, dan kinerja model diukur pada data validasi atau uji. Hasilnya adalah model yang dioptimalkan untuk tugas tertentu, yang dapat menghasilkan hasil yang lebih baik daripada model dengan hyperparameter default. Dengan tuning hyperparameter yang baik, kita dapat meningkatkan kemampuan model machine learning untuk menyelesaikan masalah dari berbagai domain seperti klasifikasi, regresi, atau pengenalan pola dengan tingkat akurasi yang lebih tinggi.

5 Kasus Klasifikasi Multikelas (Wine)

Persiapan Data

library(caret)
library(rpart)
library(rpart.plot)
library(randomForest)
library(VGAM)
## Loading required package: stats4
## Loading required package: splines
## 
## Attaching package: 'VGAM'
## The following object is masked from 'package:caret':
## 
##     predictors
library(varImp)
## Loading required package: measures
## 
## Attaching package: 'measures'
## The following objects are masked from 'package:caret':
## 
##     MAE, RMSE
## Loading required package: party
## Loading required package: grid
## Loading required package: mvtnorm
## Loading required package: modeltools
## Loading required package: strucchange
## Loading required package: zoo
## 
## Attaching package: 'zoo'
## The following objects are masked from 'package:base':
## 
##     as.Date, as.Date.numeric
## Loading required package: sandwich
## 
## Attaching package: 'varImp'
## The following object is masked from 'package:caret':
## 
##     varImp
setwd("D:/Kuliah/Mat/TSA Kominfo/Praktikum")
data <- read.csv("4. wine_quality.csv")
head(data,15)
##    fixed.acidity volatile.acidity citric.acid residual.sugar chlorides
## 1            7.4            0.700        0.00            1.9     0.076
## 2            7.8            0.880        0.00            2.6     0.098
## 3            7.8            0.760        0.04            2.3     0.092
## 4           11.2            0.280        0.56            1.9     0.075
## 5            7.4            0.700        0.00            1.9     0.076
## 6            7.4            0.660        0.00            1.8     0.075
## 7            7.9            0.600        0.06            1.6     0.069
## 8            7.3            0.650        0.00            1.2     0.065
## 9            7.8            0.580        0.02            2.0     0.073
## 10           6.7            0.580        0.08            1.8     0.097
## 11           5.6            0.615        0.00            1.6     0.089
## 12           7.8            0.610        0.29            1.6     0.114
## 13           8.5            0.280        0.56            1.8     0.092
## 14           7.9            0.320        0.51            1.8     0.341
## 15           7.6            0.390        0.31            2.3     0.082
##    free.sulfur.dioxide total.sulfur.dioxide density   pH sulphates alcohol
## 1                   11                   34  0.9978 3.51      0.56     9.4
## 2                   25                   67  0.9968 3.20      0.68     9.8
## 3                   15                   54  0.9970 3.26      0.65     9.8
## 4                   17                   60  0.9980 3.16      0.58     9.8
## 5                   11                   34  0.9978 3.51      0.56     9.4
## 6                   13                   40  0.9978 3.51      0.56     9.4
## 7                   15                   59  0.9964 3.30      0.46     9.4
## 8                   15                   21  0.9946 3.39      0.47    10.0
## 9                    9                   18  0.9968 3.36      0.57     9.5
## 10                  15                   65  0.9959 3.28      0.54     9.2
## 11                  16                   59  0.9943 3.58      0.52     9.9
## 12                   9                   29  0.9974 3.26      1.56     9.1
## 13                  35                  103  0.9969 3.30      0.75    10.5
## 14                  17                   56  0.9969 3.04      1.08     9.2
## 15                  23                   71  0.9982 3.52      0.65     9.7
##    quality Id
## 1        5  0
## 2        5  1
## 3        5  2
## 4        6  3
## 5        5  4
## 6        5  5
## 7        5  6
## 8        7  7
## 9        7  8
## 10       5 10
## 11       5 12
## 12       5 13
## 13       7 16
## 14       6 19
## 15       5 21
str(data)
## 'data.frame':    1143 obs. of  13 variables:
##  $ fixed.acidity       : num  7.4 7.8 7.8 11.2 7.4 7.4 7.9 7.3 7.8 6.7 ...
##  $ volatile.acidity    : num  0.7 0.88 0.76 0.28 0.7 0.66 0.6 0.65 0.58 0.58 ...
##  $ citric.acid         : num  0 0 0.04 0.56 0 0 0.06 0 0.02 0.08 ...
##  $ residual.sugar      : num  1.9 2.6 2.3 1.9 1.9 1.8 1.6 1.2 2 1.8 ...
##  $ chlorides           : num  0.076 0.098 0.092 0.075 0.076 0.075 0.069 0.065 0.073 0.097 ...
##  $ free.sulfur.dioxide : num  11 25 15 17 11 13 15 15 9 15 ...
##  $ total.sulfur.dioxide: num  34 67 54 60 34 40 59 21 18 65 ...
##  $ density             : num  0.998 0.997 0.997 0.998 0.998 ...
##  $ pH                  : num  3.51 3.2 3.26 3.16 3.51 3.51 3.3 3.39 3.36 3.28 ...
##  $ sulphates           : num  0.56 0.68 0.65 0.58 0.56 0.56 0.46 0.47 0.57 0.54 ...
##  $ alcohol             : num  9.4 9.8 9.8 9.8 9.4 9.4 9.4 10 9.5 9.2 ...
##  $ quality             : int  5 5 5 6 5 5 5 7 7 5 ...
##  $ Id                  : int  0 1 2 3 4 5 6 7 8 10 ...
# terdapat kolom Id yang sepertinya hanya berupa indeks saja dan perlu dihapus

data$Id <- NULL
# melihat daftar kategori pada kolom class
unique(data$class)
## NULL
# melihat daftar kategori pada kolom class
unique(data$quality)
## [1] 5 6 7 4 8 3

Note : Karena objektif dari tulisan ini adalah membuat regresi logistik ordinal serta untuk menyederhanakan ukuran kelas maka ukuran quality akan diganti menggunakan 3 kategori yaitu LOW, STANDARD, HIGH dimana (misalkan):

  • LOW memiliki quality (3-5)

  • STANDARD memiliki quality (6)

  • HIGH memiliki quality (7-8)

# fungsi untuk membuat nilai quality berdasarkan numeriknya
quality.class <- function(quality.num) {
  if(quality.num < 6) return("LOW")
  else if(quality.num < 7) return("STANDARD")
  else return("HIGH")
}

# merubah data quality menjadi 3 kelas
# sekaligus mengubah tipe menjadi factor
data$quality <- factor(sapply(data$quality, quality.class), level=c("LOW", "STANDARD", "HIGH"))
# komposisi masing-masing kategori
table(data$quality)
## 
##      LOW STANDARD     HIGH 
##      522      462      159

Pembagian Data

Tahapan selanjutnya adalah pembagian dataset menjadi 2 bagian yaitu data latih dan data uji. Data latih akan digunakan untuk membangun model. Sementara data uji akan digunakan untuk evaluasi dan pengukuran performa model pada data baru (yang belum pernah dilihat model selama pelatihan).

# Membagi data Latih dan Data Uji

library(caret)

set.seed(100)  # Untuk menghasilkan nilai acak yang dapat direproduksi

# membagi data secara acak
# dengan menghasilkan indeks data latih dan data uji
# data latih = 70%, data uji = 30%
trainIndex <- createDataPartition(data$quality, p = 0.70, list = FALSE, times = 1)

# Buat data latih dan data uji berdasarkan indeks yang dihasilkan
data.train <- data[trainIndex, ]
data.test <- data[-trainIndex, ]
# melihat komposisi setiap kelas pada data train dan test
cbind("train" = table(data.train$quality), "test" = table(data.test$quality))
##          train test
## LOW        366  156
## STANDARD   324  138
## HIGH       112   47

Dari hasil pembagian tersebut diperoleh sejumlah data (70%) yang akan digunakan sebagai pembentukan model serta sebagian lainnya (30%) sebagai data untuk mengevaluasi model.

Dari output di atas, terlihat pula keterwakilan masing-masing kelas baik pada data latih maupun data uji.

5.1 Regresi Logistik Ordinal

Regresi Logistik ORDINAL (Ordinal Logistic Regression) adalah salah satu metode analisis statistik yang digunakan untuk memodelkan hubungan antara variabel independen (prediktor) dan variabel dependen yang terdiri dari lebih dari dua kategori atau kelas dimana terdapat urutan pada pada kelas-kelasnya. Ini adalah perluasan bentuk dari regresi logistik binomial, yang hanya digunakan untuk memodelkan variabel dependen dengan dua kategori (biner) serta regresi logistik multinomial, variabel dependen memiliki tiga atau lebih kategori memiliki urutan.

# menyembunyikan informasi warning
options(warn = -1)

library(VGAM)

# membuat model regresi logistik ordinal
# argumen familydi-set menjadi "propodds"
model.ord <- vglm(quality ~ ., data=data.train, family="propodds")

summary(model.ord)
## 
## Call:
## vglm(formula = quality ~ ., family = "propodds", data = data.train)
## 
## Coefficients: 
##                        Estimate Std. Error z value Pr(>|z|)    
## (Intercept):1         1.904e+02  9.813e+01   1.941  0.05231 .  
## (Intercept):2         1.875e+02  9.812e+01   1.910  0.05607 .  
## fixed.acidity         3.280e-01  1.219e-01   2.690  0.00714 ** 
## volatile.acidity     -2.938e+00  6.304e-01  -4.660 3.16e-06 ***
## citric.acid          -9.123e-01  7.187e-01  -1.269  0.20431    
## residual.sugar        1.194e-01  7.529e-02   1.586  0.11275    
## chlorides            -3.507e+00  1.946e+00  -1.802  0.07160 .  
## free.sulfur.dioxide   1.392e-02  1.012e-02   1.376  0.16885    
## total.sulfur.dioxide -1.043e-02  3.486e-03  -2.993  0.00276 ** 
## density              -2.024e+02  1.004e+02      NA       NA    
## pH                    2.879e-02  9.264e-01   0.031  0.97521    
## sulphates             3.059e+00  5.461e-01   5.601 2.13e-08 ***
## alcohol               8.544e-01  1.255e-01   6.807 9.97e-12 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Names of linear predictors: logitlink(P[Y>=2]), logitlink(P[Y>=3])
## 
## Residual deviance: 1221.579 on 1591 degrees of freedom
## 
## Log-likelihood: -610.7892 on 1591 degrees of freedom
## 
## Number of Fisher scoring iterations: 6 
## 
## Warning: Hauck-Donner effect detected in the following estimate(s):
## 'density'
## 
## 
## Exponentiated coefficients:
##        fixed.acidity     volatile.acidity          citric.acid 
##         1.388239e+00         5.296361e-02         4.015814e-01 
##       residual.sugar            chlorides  free.sulfur.dioxide 
##         1.126829e+00         2.998960e-02         1.014016e+00 
## total.sulfur.dioxide              density                   pH 
##         9.896192e-01         1.224241e-88         1.029208e+00 
##            sulphates              alcohol 
##         2.129687e+01         2.349905e+00

Prediksi (Data Latih)

# mendapatkan vektor kelas data
quality.name <- unique(data$quality)

quality.name
## [1] LOW      STANDARD HIGH    
## Levels: LOW STANDARD HIGH
# Memprediksi data TRAIN dengan model regresi logistik multinomial
pred.train <- predict(model.ord, data.train, type="response")

# Melihat prediksi pada 5 data.train yang pertama
head(round(pred.train, 4), 5)
##      LOW STANDARD   HIGH
## 1 0.8273   0.1623 0.0104
## 2 0.7694   0.2157 0.0149
## 3 0.7384   0.2440 0.0176
## 4 0.3609   0.5570 0.0821
## 5 0.8273   0.1623 0.0104
# Mendapatkan label kelas berdasarkan nilai peluang yang terbesar
pred.train.cat <- factor(quality.name[max.col(pred.train)])

cat("\n\n")
# Melihat kelas hasil prediksi pada 5 data.train yang pertama
head(pred.train.cat, 5)
## [1] LOW      LOW      LOW      STANDARD LOW     
## Levels: LOW STANDARD HIGH
# membuat confusion Matrix
confusionMatrix(data = pred.train.cat,
                reference = data.train$quality)
## Confusion Matrix and Statistics
## 
##           Reference
## Prediction LOW STANDARD HIGH
##   LOW      281      111    3
##   STANDARD  83      196   64
##   HIGH       2       17   45
## 
## Overall Statistics
##                                           
##                Accuracy : 0.6509          
##                  95% CI : (0.6168, 0.6839)
##     No Information Rate : 0.4564          
##     P-Value [Acc > NIR] : < 2.2e-16       
##                                           
##                   Kappa : 0.4096          
##                                           
##  Mcnemar's Test P-Value : 6.629e-07       
## 
## Statistics by Class:
## 
##                      Class: LOW Class: STANDARD Class: HIGH
## Sensitivity              0.7678          0.6049     0.40179
## Specificity              0.7385          0.6925     0.97246
## Pos Pred Value           0.7114          0.5714     0.70313
## Neg Pred Value           0.7912          0.7211     0.90921
## Prevalence               0.4564          0.4040     0.13965
## Detection Rate           0.3504          0.2444     0.05611
## Detection Prevalence     0.4925          0.4277     0.07980
## Balanced Accuracy        0.7531          0.6487     0.68712

Prediksi & Evaluasi (Data Uji)

Prediksi dan Evaluasi pada data uji diperlukan unutk mengetahui performa model yang sebenarnya ketika melakukan prediksi pada data baru (belum pernah dilihat model selama pelatihan).

# Memprediksi data TEST
pred.test <- predict(model.ord, newdata = data.test, type="response")

# Melihat prediksi pada 5 data.test yang pertama
head(round(pred.test, 4), 5)
##       LOW STANDARD   HIGH
## 6  0.8164   0.1724 0.0112
## 11 0.7622   0.2223 0.0155
## 12 0.2149   0.6293 0.1558
## 13 0.3185   0.5839 0.0975
## 15 0.6489   0.3245 0.0266
pred.test.cat <- factor(quality.name[max.col(pred.test)])

cat("\n\n")
# Melihat kelas hasil prediksi pada 5 data.test yang pertama
head(pred.test.cat, 5)
## [1] LOW      LOW      STANDARD STANDARD LOW     
## Levels: LOW STANDARD HIGH

Output yang dihasilkan dari model regresi logistik ordinal adalah nilai peluang suatu amatan tersebut masuk ke setiap kelas. Misalkan pada output hasil prediksi 5 data uji pertama di atas, data uji pertama memiliki peluang masuk sebagai kelas LOW adalah sebesar 0.8164, peluangnya masuk sebagai kelas STANDARD adalah 0.1724 dan peluangnya untuk masuk sebagai kelas HIGH adalah sebesar 0.0112.

Dari hasil ini, maka data uji pertama ini akan diprediksi masuk sebagai kelas LOW karena peluangnya masuk pada kelas ini lebih besar dibandingkan peluang masuk kelas lainnya.

Proses yang sama juga berlaku untuk setiap data uji yang kita prediksi. Dimana data tersebut akan dimasukkan ke dalam kelas dimana peluangnya masuk ke dalam kelas tersebut adalah yang terbesar.

# untuk membuat confusion Matrix
confusionMatrix(data = pred.test.cat,
                reference = data.test$quality)
## Confusion Matrix and Statistics
## 
##           Reference
## Prediction LOW STANDARD HIGH
##   LOW      122       46    1
##   STANDARD  33       83   35
##   HIGH       1        9   11
## 
## Overall Statistics
##                                           
##                Accuracy : 0.6334          
##                  95% CI : (0.5798, 0.6847)
##     No Information Rate : 0.4575          
##     P-Value [Acc > NIR] : 4.91e-11        
##                                           
##                   Kappa : 0.374           
##                                           
##  Mcnemar's Test P-Value : 0.0005569       
## 
## Statistics by Class:
## 
##                      Class: LOW Class: STANDARD Class: HIGH
## Sensitivity              0.7821          0.6014     0.23404
## Specificity              0.7459          0.6650     0.96599
## Pos Pred Value           0.7219          0.5497     0.52381
## Neg Pred Value           0.8023          0.7105     0.88750
## Prevalence               0.4575          0.4047     0.13783
## Detection Rate           0.3578          0.2434     0.03226
## Detection Prevalence     0.4956          0.4428     0.06158
## Balanced Accuracy        0.7640          0.6332     0.60001

Berdasarkan hasil evaluasi model regresi logistik Ordinal pada data uji di atas, dapat dilihat bahwa model memiliki performa yang tidak cukup tinggi. Dimana, secara keseluruhan ACCURACY model mencapai 0.6334, atau dengan kata lain model mampu memprediksi dengan tepat 63,34% data yang berasal dari data uji. Secara lebih detail dapat dilihat pula nilai SENSITIVITY maupun SPESIFISITY yang relatif seimbang untuk kelas LOW dan STANDARD, namun pada Kelas HIGH nilainya sangat tidak seimbang, dimana nilai sensitivity hanya sebesar 0.23404. Model sesungguhnya tidak dapat memprediksi secara baik, data-data yang seharusnya masuk ke kelas HIGH. Dari 47 data dengan kelas HIGH hanya 11 saja yang diprediksi tepat, sementara sisanya sebanyak 36 salah diprediksi.

5.2 CART (Decission Tree)

Pemodelan CART (Classification and Regression Trees) adalah sebuah metode dalam data mining dan machine learning yang digunakan untuk menghasilkan model prediksi berdasarkan struktur pohon. Dalam pemodelan CART, data dipisahkan berdasarkan serangkaian keputusan biner yang dibuat berdasarkan fitur-fitur yang ada. Setiap pemisahan bertujuan untuk meminimalkan ketidakmurnian dalam setiap kelompok data yang dihasilkan. Pohon ini dapat digunakan baik untuk tugas klasifikasi (memisahkan data ke dalam kategori) maupun regresi (mengestimasi nilai berdasarkan variabel input). Pemodelan CART sering digunakan dalam berbagai aplikasi, termasuk pengambilan keputusan, analisis risiko, dan pemodelan prediktif. Metode ini memiliki keunggulan karena mudah diinterpretasikan, tetapi juga dapat menjadi kompleks jika tidak diatur dengan baik.

5.2.1 Tree 1 (Parameter Default)

Model

model.cart <- rpart(quality ~ ., data=data.train, method = "class")

model.cart
## n= 802 
## 
## node), split, n, loss, yval, (yprob)
##       * denotes terminal node
## 
##   1) root 802 436 LOW (0.45635910 0.40399002 0.13965087)  
##     2) alcohol< 10.55 483 181 LOW (0.62525880 0.34161491 0.03312629)  
##       4) sulphates< 0.595 234  58 LOW (0.75213675 0.23504274 0.01282051) *
##       5) sulphates>=0.595 249 123 LOW (0.50602410 0.44176707 0.05220884)  
##        10) total.sulfur.dioxide>=81.5 41   7 LOW (0.82926829 0.17073171 0.00000000) *
##        11) total.sulfur.dioxide< 81.5 208 105 STANDARD (0.44230769 0.49519231 0.06250000)  
##          22) volatile.acidity>=0.6125 55  19 LOW (0.65454545 0.32727273 0.01818182) *
##          23) volatile.acidity< 0.6125 153  68 STANDARD (0.36601307 0.55555556 0.07843137)  
##            46) alcohol< 9.75 79  39 LOW (0.50632911 0.46835443 0.02531646)  
##              92) free.sulfur.dioxide< 5.5 12   2 LOW (0.83333333 0.16666667 0.00000000) *
##              93) free.sulfur.dioxide>=5.5 67  32 STANDARD (0.44776119 0.52238806 0.02985075)  
##               186) total.sulfur.dioxide>=38.5 32  12 LOW (0.62500000 0.37500000 0.00000000) *
##               187) total.sulfur.dioxide< 38.5 35  12 STANDARD (0.28571429 0.65714286 0.05714286) *
##            47) alcohol>=9.75 74  26 STANDARD (0.21621622 0.64864865 0.13513514) *
##     3) alcohol>=10.55 319 160 STANDARD (0.20062696 0.49843260 0.30094044)  
##       6) volatile.acidity>=0.425 174  72 STANDARD (0.26436782 0.58620690 0.14942529)  
##        12) sulphates< 0.585 52  24 LOW (0.53846154 0.42307692 0.03846154)  
##          24) density>=0.995505 17   3 LOW (0.82352941 0.17647059 0.00000000) *
##          25) density< 0.995505 35  16 STANDARD (0.40000000 0.54285714 0.05714286) *
##        13) sulphates>=0.585 122  42 STANDARD (0.14754098 0.65573770 0.19672131) *
##       7) volatile.acidity< 0.425 145  75 HIGH (0.12413793 0.39310345 0.48275862)  
##        14) density>=0.99554 68  34 STANDARD (0.17647059 0.50000000 0.32352941)  
##          28) pH>=3.215 45  18 STANDARD (0.22222222 0.60000000 0.17777778) *
##          29) pH< 3.215 23   9 HIGH (0.08695652 0.30434783 0.60869565)  
##            58) sulphates< 0.62 7   2 STANDARD (0.28571429 0.71428571 0.00000000) *
##            59) sulphates>=0.62 16   2 HIGH (0.00000000 0.12500000 0.87500000) *
##        15) density< 0.99554 77  29 HIGH (0.07792208 0.29870130 0.62337662) *
model.cart$cptable
##           CP nsplit rel error    xerror       xstd
## 1 0.21788991      0 1.0000000 1.0000000 0.03235267
## 2 0.02981651      1 0.7821101 0.7844037 0.03212316
## 3 0.02752294      2 0.7522936 0.7935780 0.03216968
## 4 0.02217125      3 0.7247706 0.8165138 0.03227147
## 5 0.01605505      6 0.6582569 0.8050459 0.03222316
## 6 0.01376147      7 0.6422018 0.7798165 0.03209865
## 7 0.01223242      8 0.6284404 0.7752294 0.03207330
## 8 0.01146789     11 0.5917431 0.7545872 0.03194882
## 9 0.01000000     13 0.5688073 0.7614679 0.03199221

Visualisasi Tree

rpart.plot(model.cart)

Peubah Penting

Peubah penting merujuk pada sejauh mana setiap peubah (fitur) yang digunakan dalam model memiliki dampak terhadap akurasi prediksi. Model CART maupun model berbasis pohon lainnya seperti Random Forest, kita dapat melihat berapa banyak masing-masing peubah berkontribusi dalam mengurangi kesalahan prediksi dengan mengukur nilai peubah penting ini.

Dalam model berbasis pohon, untuk mengukur pentingnya suatu peuibah dapat menggunakan metrik seperti pengurangan GINI impurity atau peningkatan Mean Decrease Accuracy (MDA). Peubah yang memiliki dampak besar dalam mengurangi impuritas atau meningkatkan akurasi model akan dianggap penting. Dengan mengidentifikasi variabel penting, kita dapat fokus pada fitur-fitur yang paling relevan dalam membuat prediksi yang lebih baik dan dapat mengurangi overfitting dengan menghilangkan fitur yang kurang penting. Dengan demikian, Random Forest membantu dalam pemilihan fitur yang efektif dan memperbaiki kualitas prediksi.

# mengecek ukuran kepentingan setiap peubah
print(model.cart$variable.importance)
##              alcohol            sulphates              density 
##            63.939455            37.605937            37.404823 
##     volatile.acidity        fixed.acidity          citric.acid 
##            33.770739            19.432873            19.088066 
##            chlorides total.sulfur.dioxide                   pH 
##            17.436656            16.846343            12.659974 
##  free.sulfur.dioxide       residual.sugar 
##             7.977359             5.663947

Prediksi & Evaluasi (Data Uji)

# Memprediksi data TEST
pred.test.cart <- predict(model.cart, newdata = data.test, type="class")

# Melihat prediksi pada 5 data.test yang pertama
head(pred.test.cart, 10)
##        6       11       12       13       15       18       25       26 
##      LOW      LOW STANDARD      LOW      LOW      LOW      LOW      LOW 
##       33       35 
## STANDARD      LOW 
## Levels: LOW STANDARD HIGH
# untuk membuat confusion Matrix
confusionMatrix(data = pred.test.cart,
                reference = data.test$quality)
## Confusion Matrix and Statistics
## 
##           Reference
## Prediction LOW STANDARD HIGH
##   LOW      125       51    3
##   STANDARD  29       70   30
##   HIGH       2       17   14
## 
## Overall Statistics
##                                           
##                Accuracy : 0.6129          
##                  95% CI : (0.5589, 0.6649)
##     No Information Rate : 0.4575          
##     P-Value [Acc > NIR] : 5.91e-09        
##                                           
##                   Kappa : 0.3477          
##                                           
##  Mcnemar's Test P-Value : 0.01992         
## 
## Statistics by Class:
## 
##                      Class: LOW Class: STANDARD Class: HIGH
## Sensitivity              0.8013          0.5072     0.29787
## Specificity              0.7081          0.7094     0.93537
## Pos Pred Value           0.6983          0.5426     0.42424
## Neg Pred Value           0.8086          0.6792     0.89286
## Prevalence               0.4575          0.4047     0.13783
## Detection Rate           0.3666          0.2053     0.04106
## Detection Prevalence     0.5249          0.3783     0.09677
## Balanced Accuracy        0.7547          0.6083     0.61662

Nilai akurasi yang dihasilkan model dapat dikatakan tidak terlalu baik yaitu 0.6129. Artinya model hanya mampu memprediksi benar sekitar 61.29% kelas pada data uji. Khususnya pada kelas HIGH, performa model dapat dikatakan buruk. Model hanya mampu memprediksi benar sebanyak 29.79% amatan yang seharusnya merupakan kelas HIGH, atau kurang dari 1/3 saja.

5.2.2 Tree 2 (Parameter Custom)

Model

Di dalam fungsi rpart terdapat berbagai parameter yang dapat diatur dalam proses pembentukan model.Perubahan nilai-nilai pada parameternya akan memhasilkan model yang berbeda pula. Oleh karena itu penentuan parameter yang tepat tentunya dapat menghasilkan model yang optimal.

# rpart.control : mengatur nilai parameter model (lihat : ?rpart.control)
control = rpart.control(minsplit = 10, cp = 0.01, maxdepth = 10)

model.cart.2 <- rpart(quality ~ ., data=data.train, method = "class", control = control)

model.cart.2
## n= 802 
## 
## node), split, n, loss, yval, (yprob)
##       * denotes terminal node
## 
##  1) root 802 436 LOW (0.45635910 0.40399002 0.13965087)  
##    2) alcohol< 10.55 483 181 LOW (0.62525880 0.34161491 0.03312629)  
##      4) sulphates< 0.595 234  58 LOW (0.75213675 0.23504274 0.01282051) *
##      5) sulphates>=0.595 249 123 LOW (0.50602410 0.44176707 0.05220884)  
##       10) total.sulfur.dioxide>=81.5 41   7 LOW (0.82926829 0.17073171 0.00000000) *
##       11) total.sulfur.dioxide< 81.5 208 105 STANDARD (0.44230769 0.49519231 0.06250000)  
##         22) volatile.acidity>=0.6125 55  19 LOW (0.65454545 0.32727273 0.01818182) *
##         23) volatile.acidity< 0.6125 153  68 STANDARD (0.36601307 0.55555556 0.07843137) *
##    3) alcohol>=10.55 319 160 STANDARD (0.20062696 0.49843260 0.30094044)  
##      6) volatile.acidity>=0.425 174  72 STANDARD (0.26436782 0.58620690 0.14942529)  
##       12) sulphates< 0.585 52  24 LOW (0.53846154 0.42307692 0.03846154)  
##         24) density>=0.995505 17   3 LOW (0.82352941 0.17647059 0.00000000) *
##         25) density< 0.995505 35  16 STANDARD (0.40000000 0.54285714 0.05714286) *
##       13) sulphates>=0.585 122  42 STANDARD (0.14754098 0.65573770 0.19672131)  
##         26) total.sulfur.dioxide>=73 13   7 LOW (0.46153846 0.15384615 0.38461538)  
##           52) sulphates< 0.795 8   2 LOW (0.75000000 0.25000000 0.00000000) *
##           53) sulphates>=0.795 5   0 HIGH (0.00000000 0.00000000 1.00000000) *
##         27) total.sulfur.dioxide< 73 109  31 STANDARD (0.11009174 0.71559633 0.17431193) *
##      7) volatile.acidity< 0.425 145  75 HIGH (0.12413793 0.39310345 0.48275862)  
##       14) density>=0.99554 68  34 STANDARD (0.17647059 0.50000000 0.32352941)  
##         28) pH>=3.215 45  18 STANDARD (0.22222222 0.60000000 0.17777778) *
##         29) pH< 3.215 23   9 HIGH (0.08695652 0.30434783 0.60869565)  
##           58) sulphates< 0.62 7   2 STANDARD (0.28571429 0.71428571 0.00000000) *
##           59) sulphates>=0.62 16   2 HIGH (0.00000000 0.12500000 0.87500000) *
##       15) density< 0.99554 77  29 HIGH (0.07792208 0.29870130 0.62337662) *

Visualisasi Tree

rpart.plot(model.cart.2)

Peubah Penting

print(model.cart.2$variable.importance)
##              alcohol            sulphates              density 
##            62.020729            41.881963            40.404823 
##     volatile.acidity        fixed.acidity            chlorides 
##            36.634350            20.745366            19.675237 
##          citric.acid total.sulfur.dioxide                   pH 
##            19.002748            17.314750            12.659974 
##       residual.sugar  free.sulfur.dioxide 
##             5.296363             2.094507
# mengecek ukuran kepentingan setiap peubah
dotchart(sort(model.cart.2$variable.importance, decreasing = F), color="darkred")

Prediksi & Validasi (Data Uji)

# Memprediksi data TEST
pred.test.cart.2 <- predict(model.cart.2, newdata = data.test, type="class")

# Melihat prediksi pada 5 data.test yang pertama
head(pred.test.cart.2, 10)
##        6       11       12       13       15       18       25       26 
##      LOW      LOW STANDARD      LOW STANDARD STANDARD      LOW      LOW 
##       33       35 
## STANDARD      LOW 
## Levels: LOW STANDARD HIGH
# untuk membuat confusion Matrix
confusionMatrix(data = pred.test.cart.2,
                reference = data.test$quality)
## Confusion Matrix and Statistics
## 
##           Reference
## Prediction LOW STANDARD HIGH
##   LOW      119       41    4
##   STANDARD  35       80   27
##   HIGH       2       17   16
## 
## Overall Statistics
##                                           
##                Accuracy : 0.6305          
##                  95% CI : (0.5768, 0.6819)
##     No Information Rate : 0.4575          
##     P-Value [Acc > NIR] : 1.01e-10        
##                                           
##                   Kappa : 0.3814          
##                                           
##  Mcnemar's Test P-Value : 0.3322          
## 
## Statistics by Class:
## 
##                      Class: LOW Class: STANDARD Class: HIGH
## Sensitivity              0.7628          0.5797     0.34043
## Specificity              0.7568          0.6946     0.93537
## Pos Pred Value           0.7256          0.5634     0.45714
## Neg Pred Value           0.7910          0.7085     0.89869
## Prevalence               0.4575          0.4047     0.13783
## Detection Rate           0.3490          0.2346     0.04692
## Detection Prevalence     0.4809          0.4164     0.10264
## Balanced Accuracy        0.7598          0.6371     0.63790

Nilai akurasi model CART ini sedikit lebih baik dibandingkan model pertama yaitu sebesar 0.6305. Dengan kata lain, model mampu memprediksi benar 63.05% dari data uji. Namun jika dilihat berdasarkan nilai sensitivitas dan spesifisitas, khususnya pada kelas HIGH, model masih sangat buruk dimana model hanya mampu memprediksi secara tepat sebesar 34,04% amatan yang seharusnya masuk pada kelas HIGH.

5.2.3 Tree 3 (Pruned)

Model

# Melihat split dan nilai cp
plotcp(model.cart.2)

printcp(model.cart.2)
## 
## Classification tree:
## rpart(formula = quality ~ ., data = data.train, method = "class", 
##     control = control)
## 
## Variables actually used in tree construction:
## [1] alcohol              density              pH                  
## [4] sulphates            total.sulfur.dioxide volatile.acidity    
## 
## Root node error: 436/802 = 0.54364
## 
## n= 802 
## 
##         CP nsplit rel error  xerror     xstd
## 1 0.217890      0   1.00000 1.00000 0.032353
## 2 0.029817      1   0.78211 0.81422 0.032262
## 3 0.027523      2   0.75229 0.78670 0.032135
## 4 0.022171      3   0.72477 0.79128 0.032158
## 5 0.016055      6   0.65826 0.80046 0.032202
## 6 0.013761      7   0.64220 0.77294 0.032060
## 7 0.011468      8   0.62844 0.76147 0.031992
## 8 0.010321     10   0.60550 0.75229 0.031934
## 9 0.010000     12   0.58486 0.74771 0.031904
# melihat nilai cp yang menghasilkan error terkecil
model.cart.2$cptable[which.min(model.cart.2$cptable[,"xerror"]),"CP"]
## [1] 0.01
bestcp <- model.cart$cptable[which.min(model.cart$cptable[,"xerror"]),"CP"]

# membuat model berdasarkan nilai cp terbaik
model.cart.pruned <- prune(model.cart, cp = bestcp)

Visualisasi Tree

rpart.plot(model.cart.pruned)

Prediksi dan Validasi (Data Uji)

# Memprediksi data TEST
pred.test.cart.pruned <- predict(model.cart.pruned, newdata = data.test, type="class")

# Melihat prediksi pada 5 data.test yang pertama
head(pred.test.cart.pruned, 10)
##        6       11       12       13       15       18       25       26 
##      LOW      LOW STANDARD      LOW      LOW      LOW      LOW      LOW 
##       33       35 
##      LOW      LOW 
## Levels: LOW STANDARD HIGH
# untuk membuat confusion Matrix
confusionMatrix(data = pred.test.cart.pruned,
                reference = data.test$quality)
## Confusion Matrix and Statistics
## 
##           Reference
## Prediction LOW STANDARD HIGH
##   LOW      130       57    3
##   STANDARD  24       62   29
##   HIGH       2       19   15
## 
## Overall Statistics
##                                          
##                Accuracy : 0.607          
##                  95% CI : (0.553, 0.6592)
##     No Information Rate : 0.4575         
##     P-Value [Acc > NIR] : 2.083e-08      
##                                          
##                   Kappa : 0.3385         
##                                          
##  Mcnemar's Test P-Value : 0.001289       
## 
## Statistics by Class:
## 
##                      Class: LOW Class: STANDARD Class: HIGH
## Sensitivity              0.8333          0.4493     0.31915
## Specificity              0.6757          0.7389     0.92857
## Pos Pred Value           0.6842          0.5391     0.41667
## Neg Pred Value           0.8278          0.6637     0.89508
## Prevalence               0.4575          0.4047     0.13783
## Detection Rate           0.3812          0.1818     0.04399
## Detection Prevalence     0.5572          0.3372     0.10557
## Balanced Accuracy        0.7545          0.5941     0.62386

Berdasarkan hasil di atas, model hasil pruned ternyata tidak memberikan performa yang baik pada data uji. Bahkan jika melihat nilai akurasi maka model hasi prune memiliki nilai yang lebih rendah dibandingkan dua model pohon sebelumnya.

5.2.4 Ensemble Tree

Ensemble tree merupakan model-model yang memanfaatkan gabungan banyak pohon dengan tujuan menghasilkan model yang lebih baik dan tidak overfit. Beberapa model berbasis pohon yang populer digunakan dalam machine learning misalnya Random Forest, Boosting, Gradient Boosting dan sebagainya. Terdapat pula pengembangan dari model-model tersebut seperti Extra Trees, Double Random Forest, Rotation Forest dan Extremly Gradient Boosting (XGBoost).

Random Forest

Random Forest merupakan salah satu ensamble model berbasis pohon yang sering kali memberikan performa model sangat baik bahkan dengan pengaturan default saja. Sebagai pembanding, berikut ini adalah model random forest dengan 100 pohon, untuk memodelkan permasalahan yang sama seperti model reghresi logistik di atas.

Model

model.rf <- randomForest(quality ~ ., data = data.train, ntree = 100)
#  Confussion matrix pada data latih
print(model.rf$confusion)
##          LOW STANDARD HIGH class.error
## LOW      283       76    7   0.2267760
## STANDARD 109      193   22   0.4043210
## HIGH       7       43   62   0.4464286

Peubah Penting

model.rf$importance
##                      MeanDecreaseGini
## fixed.acidity                35.26980
## volatile.acidity             54.85717
## citric.acid                  34.88482
## residual.sugar               30.44848
## chlorides                    37.95327
## free.sulfur.dioxide          30.99271
## total.sulfur.dioxide         42.56644
## density                      44.60592
## pH                           37.78631
## sulphates                    57.81704
## alcohol                      80.29563
# visualisasi peubah penting model random forest
varImpPlot(model.rf, color="darkred")

Prediksi & Validasi (Data Uji)

# memprediksi data uji dengan model random forest
predictions <- predict(model.rf, data.test)
# Evaluate the classification model
confusionMatrix(data = predictions,
                reference = data.test$quality)
## Confusion Matrix and Statistics
## 
##           Reference
## Prediction LOW STANDARD HIGH
##   LOW      129       40    0
##   STANDARD  26       87   22
##   HIGH       1       11   25
## 
## Overall Statistics
##                                           
##                Accuracy : 0.7067          
##                  95% CI : (0.6553, 0.7545)
##     No Information Rate : 0.4575          
##     P-Value [Acc > NIR] : < 2e-16         
##                                           
##                   Kappa : 0.5097          
##                                           
##  Mcnemar's Test P-Value : 0.05416         
## 
## Statistics by Class:
## 
##                      Class: LOW Class: STANDARD Class: HIGH
## Sensitivity              0.8269          0.6304     0.53191
## Specificity              0.7838          0.7635     0.95918
## Pos Pred Value           0.7633          0.6444     0.67568
## Neg Pred Value           0.8430          0.7524     0.92763
## Prevalence               0.4575          0.4047     0.13783
## Detection Rate           0.3783          0.2551     0.07331
## Detection Prevalence     0.4956          0.3959     0.10850
## Balanced Accuracy        0.8054          0.6970     0.74555

Berdasarkan hasil evaluasi model random forest pada data uji di atas, dapat dilihat bahwa model random forest memiliki performa yang jauh lebih baik dibandingkan model regresi logistik ordinal. Nilai tersebut diperoleh dengan pengaturan default saja pada fungsi randomForest, kecuali jumlah pohon yang kita diatur sebanyak 100 pohon.

Secara keseluruhan ACCURACY model mencapai 0.7126, dengan kata lain model mampu memprediksi dengan tepat 71.26% data yang berasal dari data uji. Secara lebih detail dapat dilihat pula nilai SENSITIVITY maupun SPESIFISITY yang relatif seimbang khususnya untuk kelas LOW dan STANDARD. Adapun pada kelas HIGH, walaupun terlihat perbedaan yang besar dimana nilai SENSITIVITY hanya 0.5957, yaitu dari 47 data dengan kelas HIGH 28 diprediksi dengan tepat dan 19 lainnya diprediksi salah.

Namun secara umum hasil ini jauh lebih baik dibandingkan pada model sebelumnya yaitu 0.23404.

5.2.5 Tuning Hyperparameter (Pengayaan)

Tuning hyperparameter dalam pemodelan machine learning adalah proses yang penting untuk mengoptimalkan kinerja model. Proses ini melibatkan penyesuaian parameter-parameter yang tidak diperoleh dari model itu sendiri, tetapi memengaruhi cara model mempelajari pola dari data. Hyperparameter bisa mencakup berbagai aspek seperti larning rate pada XGBoost, kedalaman pohon dalam CART dan Random Forest, jumlah tetangga dalam algoritma k-Nearest Neighbors (KNN), dan banyak lagi.

Tujuan tuning hyperparameter adalah menemukan kombinasi nilai yang paling sesuai untuk hyperparameter-hyperparameter tersebut sehingga model dapat menghasilkan prediksi yang akurat dan generalisasi yang baik terhadap data yang belum pernah dilihat sebelumnya. Ini sering dilakukan melalui teknik Grid Search atau Random Search dan validasi silang, di mana berbagai nilai hyperparameter diuji pada data pelatihan, dan kinerja model diukur pada data validasi atau uji. Hasilnya adalah model yang dioptimalkan untuk tugas tertentu, yang dapat menghasilkan hasil yang lebih baik daripada model dengan hyperparameter default. Dengan tuning hyperparameter yang baik, kita dapat meningkatkan kemampuan model machine learning untuk menyelesaikan masalah dari berbagai domain seperti klasifikasi, regresi, atau pengenalan pola dengan tingkat akurasi yang lebih tinggi.

Random Forest

Tuning hyperparameter model pada bahasa R dapat dilakukan menggunakan fungsi train dengan mengatur parameter menggunakan fungsi trainControl. Sayangnya, pada model randomforest yang menggunakan fungsi randomForest dari package randomForest, parameter yang dapat diatur dilakukan tuning (gridsearch) HANYA mtry (jumlah peubah untuk memilih split terbaik) saja. Oleh karena itu, pada contoh berikut ini kita akan membuat fungsi secara MANUAL untuk melakukan iterasi dari berbagai nilai hyperparameter pada model random forest. Parameter yang akan diatur yaitu ntreenodesize dan maxnodes.

Grid Search CV

Pada setiap iterasi, akan dibangun model random forest berdasarkan kombinasi nilai hyperparameter yang diberikan serta menyimpan nilai akurasinya (pada data latih). Selanjutnya akan dicari model yang memiliki akurasi tertinggi dan dipilih sebagai model terbaik. Hasil yang diperoleh selanjutnya digunakan untuk memprediksi data uji serta mengukur performa model yang sebenarnya.

(proses ini akan memakan waktu yang panjang)

Model

# Membuat fungsi untuk menangani pelatihan model dengan berbagai nilai parameter
rf.tune <- function(ntree, nodesize, maxnodes, tunegrid, control, seed=123) {

  modellist <- list()

  param.grid = expand.grid(ntree, nodesize, maxnodes)
  names = c("ntree", "nodesize", "maxnodes")

  param.grid <- setNames(param.grid, names)
  best.accuracy <- 0.0

  best.model <- list("model"=NULL, "ntree"=NULL, "nodesize"=NULL, "maxnodes"=NULL, "accuracy"=0.0)

  # melakukan iterasi secara manual untuk setiap kombinasi hiperparameter
  for (i in 1:nrow(param.grid)){
    nt = param.grid[i, "ntree"]
    ns = param.grid[i, "nodesize"]
    mn = param.grid[i, "maxnodes"]

    set.seed(seed)

    # membangun model dengan pengaturan parameter tertentu (sesuai iterasi)
    fit <- train(quality ~ ., data=data.train, method="rf", metric="Accuracy",
                          tuneGrid=tunegrid, trControl=control,
                          ntree=nt, nodesize=ns, maxnodes=mn)

    # melaukan prediksi data test
    pred.test <- predict(fit, data.test)

    # Menghitung akurasi pda data uji
    accuracy <- mean(pred.test == data.test$quality)

    # jika akurasi lebih baik, maka simpan sebagai model terbaik
    if(accuracy > best.accuracy){
        best.model$model = fit
        best.model$ntree = nt
        best.model$nodesize = ns
        best.model$maxnodes = mn
        best.model$accuracy = accuracy
    }

  }

  # mengembalikan hasil model dan parameter terbaik
  return (best.model)
}


# Contoh penerapan
# Manual Search
control <- trainControl(method="repeatedcv", number=5, repeats=5, search="grid", allowParallel = T)

tunegrid <- expand.grid(.mtry=c(3, 4))
ntree.list <- c(50, 100, 200)
nodesize.list <- 1:4
maxnodes.list <- c(100, 200, NULL)      # NULL: Tidak dibatasi (jumlah akan bergantung pada nodesize)

best.model <- rf.tune(ntree.list, nodesize.list, maxnodes.list, tunegrid, control, seed = 123)

best.model
## $model
## Random Forest 
## 
## 802 samples
##  11 predictor
##   3 classes: 'LOW', 'STANDARD', 'HIGH' 
## 
## No pre-processing
## Resampling: Cross-Validated (5 fold, repeated 5 times) 
## Summary of sample sizes: 642, 643, 640, 642, 641, 642, ... 
## Resampling results across tuning parameters:
## 
##   mtry  Accuracy   Kappa    
##   3     0.6680403  0.4450173
##   4     0.6658306  0.4426199
## 
## Accuracy was used to select the optimal model using the largest value.
## The final value used for the model was mtry = 3.
## 
## $ntree
## [1] 200
## 
## $nodesize
## [1] 4
## 
## $maxnodes
## [1] 200
## 
## $accuracy
## [1] 0.7243402

Prediksi & Evaluasi (Data Test)

pred.test <- predict(best.model$model , data.test)

head(pred.test, 10)
##  [1] LOW      LOW      LOW      LOW      STANDARD STANDARD LOW      LOW     
##  [9] LOW      LOW     
## Levels: LOW STANDARD HIGH
confusionMatrix(pred.test, data.test$quality)
## Confusion Matrix and Statistics
## 
##           Reference
## Prediction LOW STANDARD HIGH
##   LOW      128       35    3
##   STANDARD  26       95   21
##   HIGH       2        8   23
## 
## Overall Statistics
##                                           
##                Accuracy : 0.7214          
##                  95% CI : (0.6706, 0.7684)
##     No Information Rate : 0.4575          
##     P-Value [Acc > NIR] : < 2e-16         
##                                           
##                   Kappa : 0.5321          
##                                           
##  Mcnemar's Test P-Value : 0.06139         
## 
## Statistics by Class:
## 
##                      Class: LOW Class: STANDARD Class: HIGH
## Sensitivity              0.8205          0.6884     0.48936
## Specificity              0.7946          0.7685     0.96599
## Pos Pred Value           0.7711          0.6690     0.69697
## Neg Pred Value           0.8400          0.7839     0.92208
## Prevalence               0.4575          0.4047     0.13783
## Detection Rate           0.3754          0.2786     0.06745
## Detection Prevalence     0.4868          0.4164     0.09677
## Balanced Accuracy        0.8076          0.7284     0.72767

Berdasarkan hasil grid search diperoleh model random forest terbaik dengan akurasi 0.7214. Pengaturan hiperparameter yang digunakan yaitu mtry=3ntree=200nodesize=4 dan maxnodes=200.