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.
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.
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.
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
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.
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.
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.
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.
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.
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(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.
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.
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.
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.
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 ntree, nodesize 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=3, ntree=200, nodesize=4 dan maxnodes=200.