Dalam proyek ini, saya bertujuan untuk melakukan prediksi terhadap penumpang kapal Titanic yang selamat berdasarkan dataset yang berisi biodata mereka. Saya akan menggunakan algoritma Decision Tree dan Naive Bayes Classifier dalam supervised learning untuk menghasilkan prediksi apakah seorang penumpang akan selamat atau tidak berdasarkan informasi pada biodatanya. *** # Eksplorasi Data
Dataset Titanic yang digunakan berasal dari Kaggle. Data
tersebut digunakan untuk menganalisis dan melakukan prediksi terkait
kejadian di kapal Titanic.
#> Rows: 891
#> Columns: 12
#> $ PassengerId <int> 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17,…
#> $ Survived <int> 0, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 1, 0, 1, 0, 1…
#> $ Pclass <int> 3, 1, 3, 1, 3, 3, 1, 3, 3, 2, 3, 1, 3, 3, 3, 2, 3, 2, 3, 3…
#> $ Name <chr> "Braund, Mr. Owen Harris", "Cumings, Mrs. John Bradley (Fl…
#> $ Sex <chr> "male", "female", "female", "female", "male", "male", "mal…
#> $ Age <dbl> 22, 38, 26, 35, 35, NA, 54, 2, 27, 14, 4, 58, 20, 39, 14, …
#> $ SibSp <int> 1, 1, 0, 1, 0, 0, 0, 3, 0, 1, 1, 0, 0, 1, 0, 0, 4, 0, 1, 0…
#> $ Parch <int> 0, 0, 0, 0, 0, 0, 0, 1, 2, 0, 1, 0, 0, 5, 0, 0, 1, 0, 0, 0…
#> $ Ticket <chr> "A/5 21171", "PC 17599", "STON/O2. 3101282", "113803", "37…
#> $ Fare <dbl> 7.2500, 71.2833, 7.9250, 53.1000, 8.0500, 8.4583, 51.8625,…
#> $ Cabin <chr> "", "C85", "", "C123", "", "", "E46", "", "", "", "G6", "C…
#> $ Embarked <chr> "S", "C", "S", "S", "S", "Q", "S", "S", "S", "C", "S", "S"…
Survived (Survival): Kolom ini menunjukkan apakah
penumpang tersebut selamat atau tidak. Nilai 0 berarti tidak selamat,
sedangkan nilai 1 berarti selamat.
pclass (Ticket class): Kolom ini menunjukkan kelas
tiket yang dibeli oleh penumpang. Nilai 1 menandakan kelas tiket
pertama, nilai 2 menandakan kelas tiket kedua, dan nilai 3 menandakan
kelas tiket ketiga.
sex (Jenis kelamin): Kolom ini menunjukkan jenis
kelamin penumpang. Nilai “male” menandakan laki-laki, sedangkan nilai
“female” menandakan perempuan.
Age (Usia): Kolom ini menunjukkan usia penumpang
dalam tahun.
Sibsp (# of siblings/spouses aboard the Titanic):
Kolom ini menunjukkan jumlah saudara kandung atau pasangan yang juga
berada di kapal Titanic bersama penumpang.
Parch (# of parents/children aboard the Titanic):
Kolom ini menunjukkan jumlah orang tua atau anak yang juga berada di
kapal Titanic bersama penumpang.
Ticket (Nomor tiket): Kolom ini menunjukkan nomor
tiket penumpang.
Fare (Tarif penumpang): Kolom ini menunjukkan tarif
yang dibayarkan oleh penumpang.
Cabin (Nomor kabin): Kolom ini menunjukkan nomor
kabin tempat penumpang menginap di kapal Titanic.
Embarked (Pelabuhan Keberangkatan): Kolom ini
menunjukkan pelabuhan keberangkatan penumpang. Nilai “C” menandakan
Cherbourg, “Q” menandakan Queenstown, dan “S” menandakan
Southampton.
PassengerId : Id Penumpang
Name : Nama penumpang
Terdapat beberapa variabel yang tidak perlu digunakan seperti Name, PassengerId, Ticket dan Cabin. Dan terdapat beberapa variabel yang belum sesuai untuk tipe datanya , sehingga perlu diperbaiki:
titanic <-titanic %>%
select(-Name, -PassengerId, -Ticket, -Cabin) %>%
mutate(Survived = as.factor(Survived),
Pclass = as.factor(Pclass),
Sex = as.factor(Sex),
SibSp = as.factor(SibSp),
Parch = as.factor(Parch),
Embarked = as.factor(Embarked))
glimpse(titanic)#> Rows: 891
#> Columns: 8
#> $ Survived <fct> 0, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0…
#> $ Pclass <fct> 3, 1, 3, 1, 3, 3, 1, 3, 3, 2, 3, 1, 3, 3, 3, 2, 3, 2, 3, 3, 2…
#> $ Sex <fct> male, female, female, female, male, male, male, male, female,…
#> $ Age <dbl> 22, 38, 26, 35, 35, NA, 54, 2, 27, 14, 4, 58, 20, 39, 14, 55,…
#> $ SibSp <fct> 1, 1, 0, 1, 0, 0, 0, 3, 0, 1, 1, 0, 0, 1, 0, 0, 4, 0, 1, 0, 0…
#> $ Parch <fct> 0, 0, 0, 0, 0, 0, 0, 1, 2, 0, 1, 0, 0, 5, 0, 0, 1, 0, 0, 0, 0…
#> $ Fare <dbl> 7.2500, 71.2833, 7.9250, 53.1000, 8.0500, 8.4583, 51.8625, 21…
#> $ Embarked <fct> S, C, S, S, S, Q, S, S, S, C, S, S, S, S, S, S, Q, S, S, C, S…
#> Survived Pclass Sex Age SibSp Parch Fare Embarked
#> 0 0 0 177 0 0 0 0
Terdapat outlier pada dataset Titanic yaitu pada kolom
Age sehingga harus diatasi. Pada kolom Age
akan diatasi missing valuenya mengisi dengan nilai mean nya.
# Mengatasi missing value pada titanic_train kolom `Age`
mean_age <- mean(titanic$Age, na.rm = TRUE)
titanic$Age[is.na(titanic$Age)] <- mean_age#> Survived Pclass Sex Age SibSp Parch Fare Embarked
#> 0 0 0 0 0 0 0 0
Sudah tidak terdapat missing value pada dataset titanic
Sebelum melakukan pemodelan, perlu memperhatikan proporsi dari
variabel target yaitu Survived.
#>
#> 0 1
#> 0.6161616 0.3838384
#>
#> 0 1
#> 549 342
Jika dilihat dari proporsi kedua kelas masih balance, karena masih 62:38 (Imbalance itu ketika lebih besar dari 70:30), sehingga kita tidak terlalu membutuhkan pre-processing tambahan untuk menyeimbangkan proporsi antar dua kelas target variabel.
RNGkind(sample.kind = "Rounding")
set.seed(123)
# index sampling
index <- sample(x = nrow(titanic),
size = nrow(titanic)*0.8)
# splitting
titanic_train <- titanic[index, ]
titanic_test <- titanic[-index, ] Naive Bayes adalah salah satu metode klasifikasi yang didasari oleh
Bayes’ Theorem of Probability. Faktanya, teorema bayes sering digunakan
dalam kehidupan sehari-hari. Model Naive Bayes dapat dibuat dengan
menggunakan fungsi naiveBayes() library e1071. Pada analisis ini,
pertama kita akan membuat model dengan menggunakan
Naive Bayes. Pada pembuatan model akan menggunakan seluruh
prediktor pada dataset. Salah satu kelemahan dari naive bayes adalah
dapat terjadi scarcity, yaitu kondisi dimana suatu
predictor tidak hadir sama sekali di suatu kelas. Sehingga kita
menambahkan parameter laplace = 1.
#>
#> Naive Bayes Classifier for Discrete Predictors
#>
#> Call:
#> naiveBayes.default(x = X, y = Y, laplace = laplace)
#>
#> A-priori probabilities:
#> Y
#> 0 1
#> 0.6161616 0.3838384
#>
#> Conditional probabilities:
#> Pclass
#> Y 1 2 3
#> 0 0.1467391 0.1775362 0.6757246
#> 1 0.3971014 0.2550725 0.3478261
#>
#> Sex
#> Y female male
#> 0 0.1488203 0.8511797
#> 1 0.6802326 0.3197674
#>
#> Age
#> Y [,1] [,2]
#> 0 30.41510 12.45737
#> 1 28.54978 13.77250
#>
#> SibSp
#> Y 0 1 2 3 4 5
#> 0 0.71762590 0.17625899 0.02877698 0.02338129 0.02877698 0.01079137
#> 1 0.60458453 0.32378223 0.04011461 0.01432665 0.01146132 0.00286533
#> SibSp
#> Y 8
#> 0 0.01438849
#> 1 0.00286533
#>
#> Parch
#> Y 0 1 2 3 4 5
#> 0 0.802158273 0.097122302 0.073741007 0.005395683 0.008992806 0.008992806
#> 1 0.670487106 0.189111748 0.117478510 0.011461318 0.002865330 0.005730659
#> Parch
#> Y 6
#> 0 0.003597122
#> 1 0.002865330
#>
#> Fare
#> Y [,1] [,2]
#> 0 22.11789 31.38821
#> 1 48.39541 66.59700
#>
#> Embarked
#> Y C Q S
#> 0 0.001808318 0.137432188 0.086799277 0.773960217
#> 1 0.008670520 0.271676301 0.089595376 0.630057803
Lakukan predict dengan data test
Evaluasi hasil dengan confusion matrix
#> [,1] [,2]
#> [1,] 0 0
#> [2,] 0 130
🏥 Resiko
Kesimpulan: Metrics yang perlu diprioritaskan atau dievaluasi adalah Precision.
Dari output model klaisifikasi Naive Bayes terlihat bahwa tingkat akurasi model sebesar 77,65% dan Precision/Pos Pred Value sebesar 79,23%
Decision Tree merupakan tree-based model yang cukup sederhana dengan performa yang robust/powerful untuk prediksi. Decision Tree menghasilkan visualisasi berupa pohon keputusan yang dapat diinterpretasi dengan mudah.
Sebelumnya kita periksa proporsi dari data target kita.
#>
#> 0 1
#> 0.6081461 0.3918539
Apabila diperhatikan, proporsi titanic_train sebenarnya masih bisa dianggap balance. Namun kita bisa coba membuatnya lebih balance lagi sehingga proporsinya 50:50 menggunakan downsample.
library(caret)
RNGkind(sample.kind = "Rounding")
set.seed(100)
titanic_train <- downSample(
x = titanic_train %>% select(-Survived),
y = titanic_train$Survived,
yname = "Survived")Kekurangan utama dari Decision Tree adalah kecenderungannya untuk overfitting. Hal ini disebabkan kemampuannya yang dapat membagi data dengan sangat detail hingga mencapai tingkat leaf node yang hanya berisi satu observasi.Untuk mengatasi overfitting, teknik Pruning digunakan untuk memutuskan kapan harus menghentikan pembuatan cabang dalam pohon keputusan, sehingga menghasilkan pohon yang lebih sederhana dan general dalam mengenali pola, dan mencegah model menjadi terlalu khusus untuk data pelatihan saja.
Selanjutnya mari kita uji dataset menggunakan klasifikasi Decision Tree tanpa melakukan tuning model.
Setelah kita latih data train maka kita bisa gunakan langsung pada data test. Evaluasi performa model complex
# prediksi kelas di data test
pred_surv_pra_test <- predict(dt_model_pra,titanic_test,type = "response")
# confusion matrix data test
conf_matrix_dt_pra_test <- confusionMatrix(pred_surv_pra_test, titanic_test$Survived)
conf_matrix_dt_pra_test#> Confusion Matrix and Statistics
#>
#> Reference
#> Prediction 0 1
#> 0 108 17
#> 1 8 46
#>
#> Accuracy : 0.8603
#> 95% CI : (0.8008, 0.9075)
#> No Information Rate : 0.648
#> P-Value [Acc > NIR] : 0.0000000001466
#>
#> Kappa : 0.6835
#>
#> Mcnemar's Test P-Value : 0.1096
#>
#> Sensitivity : 0.9310
#> Specificity : 0.7302
#> Pos Pred Value : 0.8640
#> Neg Pred Value : 0.8519
#> Prevalence : 0.6480
#> Detection Rate : 0.6034
#> Detection Prevalence : 0.6983
#> Balanced Accuracy : 0.8306
#>
#> 'Positive' Class : 0
#>
# prediksi kelas di data train
pred_surv_pra_train <- predict(dt_model_pra, titanic_train, type="response")
# confusion matrix data train
conf_matrix_dt_pra_train <- confusionMatrix(pred_surv_pra_train, as.factor(titanic_train$Survived))
conf_matrix_dt_pra_train#> Confusion Matrix and Statistics
#>
#> Reference
#> Prediction 0 1
#> 0 245 79
#> 1 34 200
#>
#> Accuracy : 0.7975
#> 95% CI : (0.7617, 0.8301)
#> No Information Rate : 0.5
#> P-Value [Acc > NIR] : < 0.00000000000000022
#>
#> Kappa : 0.595
#>
#> Mcnemar's Test P-Value : 0.00003486
#>
#> Sensitivity : 0.8781
#> Specificity : 0.7168
#> Pos Pred Value : 0.7562
#> Neg Pred Value : 0.8547
#> Prevalence : 0.5000
#> Detection Rate : 0.4391
#> Detection Prevalence : 0.5806
#> Balanced Accuracy : 0.7975
#>
#> 'Positive' Class : 0
#>
🏥 Resiko
Kesimpulan: Metrics yang perlu diprioritaskan atau dievaluasi adalah Precision.
Untuk nilai Precision pada dt_model_pra : > Data train = 75.6% & Data test = 86.4%
Dan kita akan coba juga untuk melakukan tuning model dengan
mengatur parameter mincriterion = 0.90 dan
minsplit = 15.
library(partykit)
set.seed(100)
dt_model_pas <- ctree(formula = Survived~ .,
data = titanic,
control = ctree_control(mincriterion = 0.9,
minsplit = 15,
minbucket = 0))Setelah kita latih data train maka kita bisa gunakan langsung pada data test.
# prediksi kelas di data test
pred_surv_pas_test <- predict(dt_model_pas,titanic_test,type = "response")
# confusion matrix data test
conf_matrix_dt_pas_test <- confusionMatrix(pred_surv_pas_test, titanic_test$Survived)
conf_matrix_dt_pas_test#> Confusion Matrix and Statistics
#>
#> Reference
#> Prediction 0 1
#> 0 108 17
#> 1 8 46
#>
#> Accuracy : 0.8603
#> 95% CI : (0.8008, 0.9075)
#> No Information Rate : 0.648
#> P-Value [Acc > NIR] : 0.0000000001466
#>
#> Kappa : 0.6835
#>
#> Mcnemar's Test P-Value : 0.1096
#>
#> Sensitivity : 0.9310
#> Specificity : 0.7302
#> Pos Pred Value : 0.8640
#> Neg Pred Value : 0.8519
#> Prevalence : 0.6480
#> Detection Rate : 0.6034
#> Detection Prevalence : 0.6983
#> Balanced Accuracy : 0.8306
#>
#> 'Positive' Class : 0
#>
# prediksi kelas di data train
pred_surv_pas_train <- predict(dt_model_pas, titanic_train, type="response")
# confusion matrix data train
conf_matrix_dt_pas_train <- confusionMatrix(pred_surv_pas_train, titanic_train$Survived)
conf_matrix_dt_pas_train#> Confusion Matrix and Statistics
#>
#> Reference
#> Prediction 0 1
#> 0 245 79
#> 1 34 200
#>
#> Accuracy : 0.7975
#> 95% CI : (0.7617, 0.8301)
#> No Information Rate : 0.5
#> P-Value [Acc > NIR] : < 0.00000000000000022
#>
#> Kappa : 0.595
#>
#> Mcnemar's Test P-Value : 0.00003486
#>
#> Sensitivity : 0.8781
#> Specificity : 0.7168
#> Pos Pred Value : 0.7562
#> Neg Pred Value : 0.8547
#> Prevalence : 0.5000
#> Detection Rate : 0.4391
#> Detection Prevalence : 0.5806
#> Balanced Accuracy : 0.7975
#>
#> 'Positive' Class : 0
#>
Untuk nilai Precision pada dt_model_past : > Data train = 75.6% & Data test = 86.4%
Kesimpulan Dari hasil evaluasi performa model complex dan model tuning didapat bahwa tidak ada perubahan pada hasil nilai precision.
Jika kita bandingkan secara keseluruhan dengan mengurutkan dan mempertimbangkan nilai akurasi dan precision/Pos Pred Value dari yang tertinggi dan terendah bisa dilihat seperti dibawah ini :
#> Confusion Matrix and Statistics
#>
#> Reference
#> Prediction 0 1
#> 0 108 17
#> 1 8 46
#>
#> Accuracy : 0.8603
#> 95% CI : (0.8008, 0.9075)
#> No Information Rate : 0.648
#> P-Value [Acc > NIR] : 0.0000000001466
#>
#> Kappa : 0.6835
#>
#> Mcnemar's Test P-Value : 0.1096
#>
#> Sensitivity : 0.9310
#> Specificity : 0.7302
#> Pos Pred Value : 0.8640
#> Neg Pred Value : 0.8519
#> Prevalence : 0.6480
#> Detection Rate : 0.6034
#> Detection Prevalence : 0.6983
#> Balanced Accuracy : 0.8306
#>
#> 'Positive' Class : 0
#>
#> Confusion Matrix and Statistics
#>
#> Reference
#> Prediction 0 1
#> 0 103 27
#> 1 13 36
#>
#> Accuracy : 0.7765
#> 95% CI : (0.7084, 0.8353)
#> No Information Rate : 0.648
#> P-Value [Acc > NIR] : 0.0001365
#>
#> Kappa : 0.4839
#>
#> Mcnemar's Test P-Value : 0.0398326
#>
#> Sensitivity : 0.8879
#> Specificity : 0.5714
#> Pos Pred Value : 0.7923
#> Neg Pred Value : 0.7347
#> Prevalence : 0.6480
#> Detection Rate : 0.5754
#> Detection Prevalence : 0.7263
#> Balanced Accuracy : 0.7297
#>
#> 'Positive' Class : 0
#>
Berdasarkan urutan tingkat akurasi dan nilai recall, model klasifikasi Decision Tree adalah model terbaik. Dengan tingkat akurasi 86,03% dan Precision 86,40% sedangkan Naive Bayes (Acc = 77,65% Recall = 79,2%).