Machine Learning Model: Titanic Survival Prediction
1 Introduction
Kecelakaan tenggelamnya kapal Titanic adalah salah satu peristiwa kapal karam paling terkenal dalam sejarah. Dalam kejadian kapal tenggelam, terdapat beberapa kelompok orang yang memiliki peluang lebih besar untuk selamat dibandingkan lainnya. Artikel ini akan membahas pembuatan model prediktif yang bertujuan untuk memprediksi kriteria orang yang lebih mungkin selamat, dengan menggunakan data titanic. Algoritma yang digunakan termasuk dalam kategori Supervised Learning, yaitu Logistic Regression dan KNN.
2 Data Preparation
2.1 Importing Libraries
library(dplyr)
library(gtools)
library(gmodels)
library(ggplot2)
library(class)
library(tidyr)
library(tidyverse)
library(caret)
library(plotly)
library(data.table)
library(GGally)
library(car)
library(scales)
library(tidymodels)
library(gridExtra)
library(ggstatsplot)
library(dplyr)
library(grid)
library(performance)2.2 Importing Datasets
#> 'data.frame': 891 obs. of 12 variables:
#> $ PassengerId: int 1 2 3 4 5 6 7 8 9 10 ...
#> $ Survived : int 0 1 1 1 0 0 0 0 1 1 ...
#> $ Pclass : int 3 1 3 1 3 3 1 3 3 2 ...
#> $ Name : chr "Braund, Mr. Owen Harris" "Cumings, Mrs. John Bradley (Florence Briggs Thayer)" "Heikkinen, Miss. Laina" "Futrelle, Mrs. Jacques Heath (Lily May Peel)" ...
#> $ Sex : chr "male" "female" "female" "female" ...
#> $ Age : num 22 38 26 35 35 NA 54 2 27 14 ...
#> $ SibSp : int 1 1 0 1 0 0 0 3 0 1 ...
#> $ Parch : int 0 0 0 0 0 0 0 1 2 0 ...
#> $ Ticket : chr "A/5 21171" "PC 17599" "STON/O2. 3101282" "113803" ...
#> $ Fare : num 7.25 71.28 7.92 53.1 8.05 ...
#> $ Cabin : chr "" "C85" "" "C123" ...
#> $ Embarked : chr "S" "C" "S" "S" ...
Data Dictionary : - PassengerId` : ID Penumpang - Survived :
Survived/Not Survived - Pclass : Ticket class - Name : Nama Penumpang -
Sex : Jenis Kelamin - Age : Usia - SibSp : Total Saudara di
Titanic
- Parch : Total Orang Tua di Titanic - Ticket : No Tiket - Fare : Harga
Tiket - Cabin : No Cabin - Embarked : Pelabuhan Keberangkatan
Target variabel = Survived
Beberapa tipe data variable perlu disesuaikan
2.3 Data Types
titanic$Sex <- as.factor(titanic$Sex)
titanic$Embarked <- as.factor(titanic$Embarked)
titanic <- titanic %>%
mutate_if(is.integer, as.factor) %>%
mutate(Survived = factor(Survived, levels = c(0,1), labels = c("Unsurvived","Survived")),
Pclass = factor(Pclass, levels = c(1,2,3), labels = c("1st","2nd","3rd")))
glimpse(titanic)#> Rows: 891
#> Columns: 12
#> $ PassengerId <fct> 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17,…
#> $ Survived <fct> Unsurvived, Survived, Survived, Survived, Unsurvived, Unsu…
#> $ Pclass <fct> 3rd, 1st, 3rd, 1st, 3rd, 3rd, 1st, 3rd, 3rd, 2nd, 3rd, 1st…
#> $ Name <chr> "Braund, Mr. Owen Harris", "Cumings, Mrs. John Bradley (Fl…
#> $ Sex <fct> male, female, female, female, male, male, male, male, fema…
#> $ Age <dbl> 22, 38, 26, 35, 35, NA, 54, 2, 27, 14, 4, 58, 20, 39, 14, …
#> $ SibSp <fct> 1, 1, 0, 1, 0, 0, 0, 3, 0, 1, 1, 0, 0, 1, 0, 0, 4, 0, 1, 0…
#> $ Parch <fct> 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 <fct> S, C, S, S, S, Q, S, S, S, C, S, S, S, S, S, S, Q, S, S, C…
3 Exploratory Data Analysis
3.1 Duplicates
Cek data duplikat.
#> [1] 0
data titanic tidak memiliki data duplikat.
3.2 Missing Values
Cek Missing Values
#> PassengerId Survived Pclass Name Sex Age
#> 0 0 0 0 0 177
#> SibSp Parch Ticket Fare Cabin Embarked
#> 0 0 0 0 0 0
Variabel Age memiliki missing values, sehingga
diperlukan penanganan dengan mengganti missing values dengan 0. Kemudian
cek ulang missing values
#> PassengerId Survived Pclass Name Sex Age
#> 0 0 0 0 0 0
#> SibSp Parch Ticket Fare Cabin Embarked
#> 0 0 0 0 0 0
3.3 Proporsi Data
Cek proporsi target variabel Survived
#>
#> Unsurvived Survived
#> 0.6161616 0.3838384
Proporsi kedua kelas dianggap seimbang.
3.4 Splitting Train-Test
Split data train dan test data data train = modeling data test = pengujian model.
set.seed(240899)
intrain <- sample(nrow(titanic), nrow(titanic)*0.7)
titanic_train <- titanic[intrain,]
titanic_test <- titanic[-intrain,]
titanic$Survived %>% levels()#> [1] "Unsurvived" "Survived"
4 Modelling
4.1 Regresi Logistik
Target = Survived Feature =
(Pclass,Sex,Age,SibSp,Parch,Fare).
Model
model_reglog <- glm(formula = Survived ~ Pclass + Sex + Age + SibSp + Parch + Fare, family = "binomial", data = titanic_train)
summary(model_reglog)#>
#> Call:
#> glm(formula = Survived ~ Pclass + Sex + Age + SibSp + Parch +
#> Fare, family = "binomial", data = titanic_train)
#>
#> Coefficients:
#> Estimate Std. Error z value Pr(>|z|)
#> (Intercept) 2.789737 0.426583 6.540 0.0000000000616 ***
#> Pclass2nd -0.979791 0.339809 -2.883 0.00393 **
#> Pclass3rd -2.078434 0.339411 -6.124 0.0000000009146 ***
#> Sexmale -2.707333 0.243196 -11.132 < 0.0000000000000002 ***
#> Age -0.016869 0.006602 -2.555 0.01061 *
#> SibSp1 0.153371 0.262814 0.584 0.55951
#> SibSp2 -0.858049 0.783718 -1.095 0.27358
#> SibSp3 -2.241771 0.845861 -2.650 0.00804 **
#> SibSp4 -2.341555 1.181785 -1.981 0.04755 *
#> SibSp5 -15.760423 948.195900 -0.017 0.98674
#> SibSp8 -17.126501 1056.732286 -0.016 0.98707
#> Parch1 0.734393 0.349506 2.101 0.03562 *
#> Parch2 0.297595 0.434749 0.685 0.49365
#> Parch3 0.617524 1.204792 0.513 0.60826
#> Parch4 -16.356561 1654.307691 -0.010 0.99211
#> Parch5 -0.359054 1.383369 -0.260 0.79521
#> Parch6 -16.753315 2399.544744 -0.007 0.99443
#> Fare 0.001023 0.002924 0.350 0.72657
#> ---
#> Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
#>
#> (Dispersion parameter for binomial family taken to be 1)
#>
#> Null deviance: 822.63 on 622 degrees of freedom
#> Residual deviance: 541.47 on 605 degrees of freedom
#> AIC: 577.47
#>
#> Number of Fisher Scoring iterations: 15
Model Fitting
Model fitting menggunakan metode backward pada stepwise.
#> Start: AIC=577.47
#> Survived ~ Pclass + Sex + Age + SibSp + Parch + Fare
#>
#> Df Deviance AIC
#> - Parch 6 550.79 574.79
#> - Fare 1 541.60 575.60
#> <none> 541.47 577.47
#> - Age 1 548.16 582.16
#> - SibSp 6 562.62 586.62
#> - Pclass 2 582.12 614.12
#> - Sex 1 696.27 730.27
#>
#> Step: AIC=574.79
#> Survived ~ Pclass + Sex + Age + SibSp + Fare
#>
#> Df Deviance AIC
#> - Fare 1 550.87 572.87
#> <none> 550.79 574.79
#> - Age 1 559.86 581.86
#> - SibSp 6 572.12 584.12
#> - Pclass 2 597.78 617.78
#> - Sex 1 715.53 737.53
#>
#> Step: AIC=572.87
#> Survived ~ Pclass + Sex + Age + SibSp
#>
#> Df Deviance AIC
#> <none> 550.87 572.87
#> - Age 1 560.03 580.03
#> - SibSp 6 572.46 582.46
#> - Pclass 2 620.11 638.11
#> - Sex 1 716.61 736.61
#>
#> Call:
#> glm(formula = Survived ~ Pclass + Sex + Age + SibSp, family = "binomial",
#> data = titanic_train)
#>
#> Coefficients:
#> Estimate Std. Error z value Pr(>|z|)
#> (Intercept) 2.992931 0.365827 8.181 0.000000000000000281 ***
#> Pclass2nd -0.979911 0.299434 -3.273 0.00107 **
#> Pclass3rd -2.191961 0.283721 -7.726 0.000000000000011118 ***
#> Sexmale -2.711808 0.236272 -11.477 < 0.0000000000000002 ***
#> Age -0.019222 0.006452 -2.979 0.00289 **
#> SibSp1 0.265525 0.244871 1.084 0.27821
#> SibSp2 -0.636717 0.736430 -0.865 0.38726
#> SibSp3 -1.790595 0.792588 -2.259 0.02387 *
#> SibSp4 -2.062606 1.130946 -1.824 0.06818 .
#> SibSp5 -15.470634 948.466255 -0.016 0.98699
#> SibSp8 -16.843135 1054.506286 -0.016 0.98726
#> ---
#> Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
#>
#> (Dispersion parameter for binomial family taken to be 1)
#>
#> Null deviance: 822.63 on 622 degrees of freedom
#> Residual deviance: 550.87 on 612 degrees of freedom
#> AIC: 572.87
#>
#> Number of Fisher Scoring iterations: 15
Prediksi
Prediksi target menggunakan hasil dari stepwise. Cek sebaran peluang dari hasil prediksi data
titanic_test$prob_titanic <- predict(model_reglog2, type = "response", newdata = titanic_test)
ggplot(titanic_test, aes(x=prob_titanic)) + geom_density(lwd=0.5) +
labs(title = "Distribution of Probability Predict Data") + theme_minimal()
Pada grafik di atas, dapat dilihat bahwa hasil prediksi yang dilakukan
lebih condong ke arah 0 yang artinya Unsurvived
titanic_test$pred_titanic <- factor(ifelse(titanic_test$prob_titanic > 0.5, "Survived","Unsurvived"))
titanic_test[1:10, c("pred_titanic","Survived")]#> pred_titanic Survived
#> 5 Unsurvived Unsurvived
#> 7 Unsurvived Unsurvived
#> 9 Survived Survived
#> 16 Survived Survived
#> 37 Unsurvived Survived
#> 38 Unsurvived Unsurvived
#> 39 Unsurvived Unsurvived
#> 44 Survived Survived
#> 45 Survived Survived
#> 48 Survived Survived
hasil probabilitas data test lebih dari 0,5 artinya penumpang Survived.
Model Evaluation
Pada model regresi logistik akan digunakan confusion matrix sebagai metriks evaluasi.
📌 Keterangan • Re-call/Sensitivity = dari semua data aktual yang positif, seberapa mampu proporsi model saya menebak benar. • Specificity = dari semua data aktual yang negatif, seberapa mampu proporsi model saya menebak yang benar. • Accuracy = seberapa mampu model saya menebak dengan benar target Y. • Precision = dari semua hasil prediksi, seberapa mampu model saya dapat menebak benar kelas positif.
library(caret)
log_conf <- confusionMatrix(titanic_test$pred_titanic, titanic_test$Survived, positive = "Survived")
log_conf#> Confusion Matrix and Statistics
#>
#> Reference
#> Prediction Unsurvived Survived
#> Unsurvived 133 27
#> Survived 25 83
#>
#> Accuracy : 0.806
#> 95% CI : (0.7535, 0.8516)
#> No Information Rate : 0.5896
#> P-Value [Acc > NIR] : 0.00000000000003612
#>
#> Kappa : 0.598
#>
#> Mcnemar's Test P-Value : 0.8897
#>
#> Sensitivity : 0.7545
#> Specificity : 0.8418
#> Pos Pred Value : 0.7685
#> Neg Pred Value : 0.8313
#> Prevalence : 0.4104
#> Detection Rate : 0.3097
#> Detection Prevalence : 0.4030
#> Balanced Accuracy : 0.7982
#>
#> 'Positive' Class : Survived
#>
💡 Interpretasi
Berikut hasil confusion matrix Akurasi model : 80,6%
Kemampuan model mem-proyeksi penumpang Survived : 75,5%
Kemampuan model mem-proyeksi penumpang `Unsurvived : 84,2%.
4.1 KNN
Algoritma k-Nearest Neighbor (KNN) adalah salah satu algoritma dalam
supervised learning yang mengklasifikasikan objek baru berdasarkan
mayoritas dari kategori k terdekat. Algoritma ini bekerja
dengan mencari kategori terdekat dari data yang baru diberikan
berdasarkan jarak euclidean atau jarak manhattan.
Pre-Processing Data
membuat variable dummy dari variabel kategori
dmy <- dummyVars (" ~Survived+Pclass+Sex+SibSp+Parch", data = titanic)
dmy <- data.frame(predict(dmy, newdata = titanic))
str(dmy)#> 'data.frame': 891 obs. of 21 variables:
#> $ Survived.Unsurvived: num 1 0 0 0 1 1 1 1 0 0 ...
#> $ Survived.Survived : num 0 1 1 1 0 0 0 0 1 1 ...
#> $ Pclass.1st : num 0 1 0 1 0 0 1 0 0 0 ...
#> $ Pclass.2nd : num 0 0 0 0 0 0 0 0 0 1 ...
#> $ Pclass.3rd : num 1 0 1 0 1 1 0 1 1 0 ...
#> $ Sex.female : num 0 1 1 1 0 0 0 0 1 1 ...
#> $ Sex.male : num 1 0 0 0 1 1 1 1 0 0 ...
#> $ SibSp.0 : num 0 0 1 0 1 1 1 0 1 0 ...
#> $ SibSp.1 : num 1 1 0 1 0 0 0 0 0 1 ...
#> $ SibSp.2 : num 0 0 0 0 0 0 0 0 0 0 ...
#> $ SibSp.3 : num 0 0 0 0 0 0 0 1 0 0 ...
#> $ SibSp.4 : num 0 0 0 0 0 0 0 0 0 0 ...
#> $ SibSp.5 : num 0 0 0 0 0 0 0 0 0 0 ...
#> $ SibSp.8 : num 0 0 0 0 0 0 0 0 0 0 ...
#> $ Parch.0 : num 1 1 1 1 1 1 1 0 0 1 ...
#> $ Parch.1 : num 0 0 0 0 0 0 0 1 0 0 ...
#> $ Parch.2 : num 0 0 0 0 0 0 0 0 1 0 ...
#> $ Parch.3 : num 0 0 0 0 0 0 0 0 0 0 ...
#> $ Parch.4 : num 0 0 0 0 0 0 0 0 0 0 ...
#> $ Parch.5 : num 0 0 0 0 0 0 0 0 0 0 ...
#> $ Parch.6 : num 0 0 0 0 0 0 0 0 0 0 ...
variabel dummy pada data seblumnya dihapus.
#> [1] "Survived.Unsurvived" "Survived.Survived" "Pclass.1st"
#> [4] "Pclass.2nd" "Pclass.3rd" "Sex.female"
#> [7] "Sex.male" "SibSp.0" "SibSp.1"
#> [10] "SibSp.2" "SibSp.3" "SibSp.4"
#> [13] "SibSp.5" "SibSp.8" "Parch.0"
#> [16] "Parch.1" "Parch.2" "Parch.3"
#> [19] "Parch.4" "Parch.5" "Parch.6"
Membagi data train dan test baru dari data dmy yang
telah terbentuk
Prediksi
Selanjutnya dilakukan prediksi dengan KNN
Model Evaluation
Selanjutnya akan dibuat confusion matrix dari hasil prediksi KNN
#> Confusion Matrix and Statistics
#>
#> Reference
#> Prediction 0 1
#> 0 110 0
#> 1 0 158
#>
#> Accuracy : 1
#> 95% CI : (0.9863, 1)
#> No Information Rate : 0.5896
#> P-Value [Acc > NIR] : < 0.00000000000000022
#>
#> Kappa : 1
#>
#> Mcnemar's Test P-Value : NA
#>
#> Sensitivity : 1.0000
#> Specificity : 1.0000
#> Pos Pred Value : 1.0000
#> Neg Pred Value : 1.0000
#> Prevalence : 0.5896
#> Detection Rate : 0.5896
#> Detection Prevalence : 0.5896
#> Balanced Accuracy : 1.0000
#>
#> 'Positive' Class : 1
#>
💡 Interpretasi
Berikut hasil confusion matrix Akurasi model KNN :
92,16%
Kemampuan model mem-prediksi penumpang Survived : 84,5%
Kemampuan model mem-prediksi penumpang Unsurvived :
97,5%
5 Model Evaluation : Logistic Regression vs KNN
Perbandingan efektifitas model dari Regresi Logistik dan KNN
#*Model Evaluation Logit*
eval_logit <- data_frame(Accuracy = log_conf$overall[1],
Recall = log_conf$byClass[1],
Specificity = log_conf$byClass[2],
Precision = log_conf$byClass[3])
print("Model Evaluation Logit")#> [1] "Model Evaluation Logit"
#> # A tibble: 1 × 4
#> Accuracy Recall Specificity Precision
#> <dbl> <dbl> <dbl> <dbl>
#> 1 0.806 0.755 0.842 0.769
#*Model Evaluation KNN*
eval_knn <- data_frame(Accuracy = pred_knn_conf$overall[1],
Recall = pred_knn_conf$byClass[1],
Specificity = log_conf$byClass[2],
Precision = pred_knn_conf$byClass[3])
print("Model Evaluation KNN")#> [1] "Model Evaluation KNN"
#> # A tibble: 1 × 4
#> Accuracy Recall Specificity Precision
#> <dbl> <dbl> <dbl> <dbl>
#> 1 1 1 0.842 1
Berdasarkan hasil perbandingan evaluasi kedua model, model KNN lebih
baik berdasarkan Accuracy, Recall, dan
Precision. Sedangkan berdasarkan Specificity
kedua model memiliki nilai yang sama. Dapat disimpulkan model KNN lebih
unggul dalam memprediksi Survived maupun Unsurvived
penumpang kapal Titanic.
6 Conclusion
Dalam kasus prediksi penumpang Kapal Titanic yang Survived atau Unsurvived, kedua model yang digunakan, yaitu KNN dan Regresi Logistik, menunjukkan akurasi yang tinggi. Namun, berdasarkan Confusion Matrix, KNN lebih unggul dalam memberikan prediksi yang lebih akurat dibandingkan dengan Regresi Logistik.
Jika tujuan analisis adalah memaksimalkan jumlah prediksi benar untuk
kategori positif maupun negatif, maka metrik yang sesuai untuk digunakan
adalah accuracy. Namun, jika fokus utama adalah pada
klasifikasi kategori positif, maka metrik yang menjadi prioritas adalah
precision. Selain itu, dalam situasi di mana kesalahan
dalam mengidentifikasi kategori tertentu memiliki dampak yang
signifikan, pemilihan metrik seperti F1-score juga dapat
dipertimbangkan agar hasil prediksi lebih relevan dengan kebutuhan
analisis.