Prediksi Pasien Sakit Jantung Menggunakan Decision Tree
Decision Tree
Decision tree merupakan salah satu metode yang digunakan untuk melakukan prediksi data dimana target variabel yang digunakan berupa kategorikal data. Dalam artian decision tree dapat digunakan untuk melakukan klasifikasi. Dalam melakukan klasifikasi, decision tree akan menghasilkan rules yang membantu dalam menghasilkan hasil klasifikasi.
Dalam tutorial kali ini, kita akan belajar menggunakan decision tree dalam mengklasifikasikan orang yang tergolong Health atau Not Health menggunakan dataset heart disease seperti pada tutorial klasifikasi menggunakan Logistic Regression dan K-NN yang pernah dibuat sebelumnya.
Read Data
## 'data.frame': 303 obs. of 14 variables:
## $ ï..age : int 63 37 41 56 57 57 56 44 52 57 ...
## $ sex : int 1 1 0 1 0 1 0 1 1 1 ...
## $ cp : int 3 2 1 1 0 0 1 1 2 2 ...
## $ trestbps: int 145 130 130 120 120 140 140 120 172 150 ...
## $ chol : int 233 250 204 236 354 192 294 263 199 168 ...
## $ fbs : int 1 0 0 0 0 0 0 0 1 0 ...
## $ restecg : int 0 1 0 1 1 1 0 1 1 1 ...
## $ thalach : int 150 187 172 178 163 148 153 173 162 174 ...
## $ exang : int 0 0 0 0 1 0 0 0 0 0 ...
## $ oldpeak : num 2.3 3.5 1.4 0.8 0.6 0.4 1.3 0 0.5 1.6 ...
## $ slope : int 0 0 2 2 2 1 1 2 2 2 ...
## $ ca : int 0 0 0 0 0 0 0 0 0 0 ...
## $ thal : int 1 2 2 2 2 1 2 3 3 2 ...
## $ target : int 1 1 1 1 1 1 1 1 1 1 ...
library(dplyr)
heart <- heart %>%
mutate_if(is.integer, as.factor) %>%
mutate(sex = factor(sex, levels = c(0,1), labels = c("Female","Male")),
fbs =factor(fbs, levels = c(0,1), labels = c("False","True")),
exang = factor(exang, levels = c(0,1), labels = c("No","Yes")),
target = factor(target, levels = c(0,1),
labels = c("Health","Not Health")))
glimpse(heart)## Observations: 303
## Variables: 14
## $ ï..age <fct> 63, 37, 41, 56, 57, 57, 56, 44, 52, 57, 54, 48, 49, 64, 58...
## $ sex <fct> Male, Male, Female, Male, Female, Male, Female, Male, Male...
## $ cp <fct> 3, 2, 1, 1, 0, 0, 1, 1, 2, 2, 0, 2, 1, 3, 3, 2, 2, 3, 0, 3...
## $ trestbps <fct> 145, 130, 130, 120, 120, 140, 140, 120, 172, 150, 140, 130...
## $ chol <fct> 233, 250, 204, 236, 354, 192, 294, 263, 199, 168, 239, 275...
## $ fbs <fct> True, False, False, False, False, False, False, False, Tru...
## $ restecg <fct> 0, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1...
## $ thalach <fct> 150, 187, 172, 178, 163, 148, 153, 173, 162, 174, 160, 139...
## $ exang <fct> No, No, No, No, Yes, No, No, No, No, No, No, No, No, Yes, ...
## $ oldpeak <dbl> 2.3, 3.5, 1.4, 0.8, 0.6, 0.4, 1.3, 0.0, 0.5, 1.6, 1.2, 0.2...
## $ slope <fct> 0, 0, 2, 2, 2, 1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 1, 2, 0, 2, 2...
## $ ca <fct> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2...
## $ thal <fct> 1, 2, 2, 2, 2, 1, 2, 3, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2...
## $ target <fct> Not Health, Not Health, Not Health, Not Health, Not Health...
Checking Missing Value
## ï..age sex cp trestbps chol fbs restecg thalach
## 0 0 0 0 0 0 0 0
## exang oldpeak slope ca thal target
## 0 0 0 0 0 0
Tidak ada missing value dari data heart. ### Checking Variance
## integer(0)
nearZeroVar() digunakan untuk melakukan pengecekan apakah variasi dari data yang digunakan mendekati 0 atau tidak. Berdasarkan hasil output menunjukkan bahwa tidak ada data atua variabel yang memiliki variasi mendekati 0.
Split Train Test Dataset
set.seed(250)
intrain <- sample(nrow(heart),nrow(heart)*0.8)
heart_train <- heart[intrain, ]
heart_test <- heart[-intrain, ]Cek proporsi untuk masing-masing split data sudah memiliki proporsi klasifikasi yang seimbang atau belum.
##
## Health Not Health
## 0.4554455 0.5445545
##
## Health Not Health
## 0.4421488 0.5578512
##
## Health Not Health
## 0.5081967 0.4918033
Dari proporsi diatas, untuk test data memiliki proporsi yang cukup sama dari data awal dan data train.
Build Model
##
## Model formula:
## target ~ ï..age + sex + cp + trestbps + chol + fbs + restecg +
## thalach + exang + oldpeak + slope + ca + thal
##
## Fitted party:
## [1] root
## | [2] thal in 0, 1, 3
## | | [3] cp in 0: Health (n = 71, err = 12.7%)
## | | [4] cp in 1, 2, 3: Not Health (n = 34, err = 44.1%)
## | [5] thal in 2
## | | [6] ca in 0, 4
## | | | [7] oldpeak <= 1.5: Not Health (n = 87, err = 9.2%)
## | | | [8] oldpeak > 1.5: Not Health (n = 10, err = 40.0%)
## | | [9] ca in 1, 2, 3
## | | | [10] cp in 0: Health (n = 15, err = 13.3%)
## | | | [11] cp in 1, 2, 3: Not Health (n = 25, err = 20.0%)
##
## Number of inner nodes: 5
## Number of terminal nodes: 6
Berdasarkan hasil model decision tree yang tebentuk, root node adalah variabel thal. inner node yang terbentuk sebanyak 4. Ketika nilai thal = 0 dan 2 akan menyebabkan muncul rules baru yaitu ketika nilai cp = 0 dan cp = 1,2,3. Ketika nilai cp = 0, akan memuat rules baru lagi yaitu ketika nilai ca = 0, sebanyak 25 observasi diklasifikasikan sebagai Not Health dengan nilai error sebesar 24%. Sedangkan ketika nilai ca = 1,2,3 sebanyak 19 observasi diklasifikasikan sebagai Health dengan nilai error sebesar 15.8%. Sedangkan netika nilai cp = 1,2,3, sebanyak 98 observasi akan diklasifikasikan sebagai Health dengan nilai error sebesar 11.2%. Rules yang lainnya muncul yaitu ketika nilai thal = 1 dan 3 akan menghasilkan rules baru dengan kondisi cp = 0 dan cp = 1,2,3. Ketika nilai cp = 0, sebanyak 67 observasi diklasifikasikan sebagai Health dengan error 10.4% dan ketika cp = 1,2,3 sebanyak 33 observasi akan diklasifikasikan sebagai Health dengan error sebesar 48.5%.
Model Evaluation
Sebelum melakukan prediksi terhadap data test, kita lihat dulu evaluasi model ketika digunakan pada data train. Hal ini untuk mengecek apakah model yang dibuat overfit atau underfit.
pred_heart_train <- predict(heart_tree, heart_train)
confusionMatrix(pred_heart_train, heart_train$target, positive = "Not Health")## Confusion Matrix and Statistics
##
## Reference
## Prediction Health Not Health
## Health 75 11
## Not Health 32 124
##
## Accuracy : 0.8223
## 95% CI : (0.7682, 0.8683)
## No Information Rate : 0.5579
## P-Value [Acc > NIR] : < 2.2e-16
##
## Kappa : 0.6323
##
## Mcnemar's Test P-Value : 0.002289
##
## Sensitivity : 0.9185
## Specificity : 0.7009
## Pos Pred Value : 0.7949
## Neg Pred Value : 0.8721
## Prevalence : 0.5579
## Detection Rate : 0.5124
## Detection Prevalence : 0.6446
## Balanced Accuracy : 0.8097
##
## 'Positive' Class : Not Health
##
Dari hasil evaluasi model, kita akan gunakan nilai recall karena kita tidak ingin salah tebak orang yang sebenarnya Not Health kita prediksi Health. Nilai recall yang diperoleh sebesar 80.3%. Cukup tinggi. Selanjutnya coba menggunakan data test.
pred_heart_test <- predict(heart_tree, heart_test)
confusionMatrix(pred_heart_test, heart_test$target, positive = "Not Health")## Confusion Matrix and Statistics
##
## Reference
## Prediction Health Not Health
## Health 23 2
## Not Health 8 28
##
## Accuracy : 0.8361
## 95% CI : (0.7191, 0.9185)
## No Information Rate : 0.5082
## P-Value [Acc > NIR] : 9.418e-08
##
## Kappa : 0.6731
##
## Mcnemar's Test P-Value : 0.1138
##
## Sensitivity : 0.9333
## Specificity : 0.7419
## Pos Pred Value : 0.7778
## Neg Pred Value : 0.9200
## Prevalence : 0.4918
## Detection Rate : 0.4590
## Detection Prevalence : 0.5902
## Balanced Accuracy : 0.8376
##
## 'Positive' Class : Not Health
##
Saat model diinputkan untuk memprediksi data test, nilai sensitivitynya menjadi 66.7%. Untuk melakukan improve model, kita bisa melakukan resampling agar klasifikasi untuktarget variabel menjadi lebih stabil.
set.seed(250)
intrain <- sample(nrow(heart), nrow(heart)*0.8)
re_train <- heart[intrain,]
re_train <- upSample(re_train[,-14], re_train[,14], yname = "target" )
re_test <- heart[-intrain,]Selanjutnya kita cek proporsi dari data train dan test.
##
## Health Not Health
## 0.5 0.5
##
## Health Not Health
## 0.5081967 0.4918033
Setelah itu, kita buat model lagi dengan data train yang ada.
##
## Model formula:
## target ~ ï..age + sex + cp + trestbps + chol + fbs + restecg +
## thalach + exang + oldpeak + slope + ca + thal
##
## Fitted party:
## [1] root
## | [2] thal in 0, 1, 3
## | | [3] ca in 0, 4
## | | | [4] exang in No: Not Health (n = 32, err = 37.5%)
## | | | [5] exang in Yes: Health (n = 25, err = 16.0%)
## | | [6] ca in 1, 2, 3: Health (n = 67, err = 6.0%)
## | [7] thal in 2
## | | [8] ca in 0, 4: Not Health (n = 99, err = 14.1%)
## | | [9] ca in 1, 2, 3
## | | | [10] cp in 0: Health (n = 22, err = 9.1%)
## | | | [11] cp in 1, 2, 3: Not Health (n = 25, err = 20.0%)
##
## Number of inner nodes: 5
## Number of terminal nodes: 6
Berdasarkan plot model decision tree yang baru,
root node dimulai dari variael cp dan memiliki internal nodes sebanyak 7 dan menghasilkan terminal nodes sebanyak 8.
## Confusion Matrix and Statistics
##
## Reference
## Prediction Health Not Health
## Health 104 10
## Not Health 31 125
##
## Accuracy : 0.8481
## 95% CI : (0.7997, 0.8888)
## No Information Rate : 0.5
## P-Value [Acc > NIR] : < 2.2e-16
##
## Kappa : 0.6963
##
## Mcnemar's Test P-Value : 0.001787
##
## Sensitivity : 0.7704
## Specificity : 0.9259
## Pos Pred Value : 0.9123
## Neg Pred Value : 0.8013
## Prevalence : 0.5000
## Detection Rate : 0.3852
## Detection Prevalence : 0.4222
## Balanced Accuracy : 0.8481
##
## 'Positive' Class : Health
##
Hasil recall yang diperoleh yaitu sebesar 84.85% dan nilai accuracy nya juga 84.85%.
## Confusion Matrix and Statistics
##
## Reference
## Prediction Health Not Health
## Health 27 4
## Not Health 4 26
##
## Accuracy : 0.8689
## 95% CI : (0.7578, 0.9416)
## No Information Rate : 0.5082
## P-Value [Acc > NIR] : 3.114e-09
##
## Kappa : 0.7376
##
## Mcnemar's Test P-Value : 1
##
## Sensitivity : 0.8710
## Specificity : 0.8667
## Pos Pred Value : 0.8710
## Neg Pred Value : 0.8667
## Prevalence : 0.5082
## Detection Rate : 0.4426
## Detection Prevalence : 0.5082
## Balanced Accuracy : 0.8688
##
## 'Positive' Class : Health
##
Hasil dari recall yang diperoleh lebih tinggi dari pada ketika menggunakan data train yaitu sebesar 89.29% dan accuracy sebesar 80.33%. Dari proses resampling yang telah dilakukan ternyata mampu mengimprove model agar menghasilkan recall yang lebih baik. Artinya model decision tree yang dibuat sudah mampu digunakan untuk mengklasifikasikan target variabel yang diinginkan.
Conclusion
Kesimpulan yang dapat diambil yaitu :
- Ketika ingin melakukan klasifikasi terhadap suatu set data, cek terlebih dahulu apakah target variabel memiliki balance atau imbalance data.
- Jika terjadi imbalance data, lakukan resampling pada data train untuk mengimprove model atau bisa juga untuk mengatasi overfitting pada hasil prediksi yang dibuat.
- Model evaluation tidak melulu menggunakan nilai accuracy, tergantung pada bussiness case yang akan digunakan.