Predict Survival on the Titanic - ML1
1 Introduction
Kecelakaan tenggelamnya kapal Titanic adalah salah satu kapal karam
yang paling terkenal dalam sejarah. Pada artikel ini akan dibangun model
prediktif yang dapat memprediksi orang dengan kriteria apa saja yang
lebih mungkin unutk selamat menggunakan data titanic.
Machine learning yang digunakan adalah Supervised
Learning (Logistic Regression dan
KNN).
2 Data Preparation
2.1 Importing Libraries
Langkah pertama adalah memanggil library yang akan
digunakan dalam pemodelan.
library(dplyr)
library(gtools)
library(gmodels)
library(scales)
library(tidymodels)
library(ggplot2)
library(caret)
library(plotly)
library(data.table)
library(GGally)
library(car)
library(gridExtra)
library(dplyr)
library(grid)
library(performance)
library(class)
library(tidyr)
library(tidyverse)
library(ggstatsplot)2.2 Importing Datasets
Selanjutnya, dilakukan import data Titanic dalam bentuk
CSV yang disimpan dalam data frame yang disimpan dengan
nama titanic_data.
#> '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 di atas memiliki 891 samples dan 12 variables. Variabel
PassengerId merupakan variabel dengan unique identifier
untuk setiap penumpang. Target variabel dalam case ini adalah
Survived. Selanjutnya perlu dilakukan perubahan tipe data
untuk variabel yang tidak sesuai.
2.3 Data Types
Variabel yang memiliki tipe data tidak sesuai akan mempengaruhi hasil pemodelan bahkan tidak bisa diproses dalam pemodelan.
titanic_data$Embarked <- as.factor(titanic_data$Embarked)
titanic_data$Sex <- as.factor(titanic_data$Sex)
titanic_data <- titanic_data %>%
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_data)#> 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
Sebelum melakukan pemodelan, kita harus memastikan bahwa data yang digunakan adalah dataset yang ada tidak memiliki data duplikat atau missing value agar dataset lebih useful
3.1 Duplicates
Pengecekan Duplikat data
#> [1] 0
Berdasarkan hasil pengecekan, data titanic_data tidak
memiliki data duplikat.
3.2 Missing Values
Selanjutnya yaitu melakukan pengecekan missing values. Missing values akan menyebabkan data tidak valid saat dilakukan pemodelan.
#> PassengerId Survived Pclass Name Sex Age
#> 0 0 0 0 0 177
#> SibSp Parch Ticket Fare Cabin Embarked
#> 0 0 0 0 0 0
Terdapat variabel yang memiliki missing values yaitu variabel
Age sebanyak 177, sehingga diperlukan handling missing
value karena bernilai numerik bisa kita ganti dengan missing values
dengan average dari age. Kemudian dilakukan recheck issing
values untuk seluruh variabel.
titanic_data$Age <- replace_na(titanic_data$Age, mean(titanic_data$Age,na.rm = TRUE))
missing_value <- colSums(is.na(x=titanic_data))
missing_value #> 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
Sebelum dilakukan pemodelan, perlu dilihat proporsi dari target
variabel yang dimiliki yaitu pada variabel Survived.
#>
#> Unsurvived Survived
#> 0.6161616 0.3838384
Jika dilihat dari proporsi kedua kelas, proporsi kedua kelas dianggap seimbang.
3.4 Splitting Train-Test
Selanjutnya dilakukan split data train dan test data dengan tujuan pada data train akan digunakan sebagai modeling, dan pada data test akan digukanan sebagai pengujian model.
set.seed(240899)
intrain <- sample(nrow(titanic_data), nrow(titanic_data)*0.7)
#Data Train 70%
titanic_train <- titanic_data[intrain,]
#Data Test 30%
titanic_test <- titanic_data[-intrain,]
titanic_data$Survived %>% levels()#> [1] "Unsurvived" "Survived"
4 Modelling
Setelah dilakukan preprocessing data, selanjutnya dilakukan pemodelan.
4.1 Regresi Logistik
Model regresi logistik digunakan fungsi glm(). Variabel
target yang digunakan adalah Survived dan variabel yang
mempengaruhi variabel target yaitu
(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) 3.7606944 0.5618316 6.694 0.0000000000218 ***
#> Pclass2nd -1.2473353 0.3571866 -3.492 0.000479 ***
#> Pclass3rd -2.2904511 0.3505713 -6.533 0.0000000000643 ***
#> Sexmale -2.7298749 0.2462760 -11.085 < 0.0000000000000002 ***
#> Age -0.0369936 0.0100334 -3.687 0.000227 ***
#> SibSp1 0.1038784 0.2640496 0.393 0.694021
#> SibSp2 -0.9966675 0.7978580 -1.249 0.211600
#> SibSp3 -2.4387885 0.8507388 -2.867 0.004148 **
#> SibSp4 -2.6887979 1.1860765 -2.267 0.023392 *
#> SibSp5 -15.9836479 955.0516710 -0.017 0.986647
#> SibSp8 -16.5147330 1058.0181271 -0.016 0.987546
#> Parch1 0.5487492 0.3580939 1.532 0.125419
#> Parch2 0.0618056 0.4436206 0.139 0.889197
#> Parch3 0.7090913 1.2075419 0.587 0.557057
#> Parch4 -16.0210805 1630.6221002 -0.010 0.992161
#> Parch5 -0.2734480 1.3838665 -0.198 0.843360
#> Parch6 -16.5716746 2399.5447443 -0.007 0.994490
#> Fare 0.0004735 0.0029334 0.161 0.871757
#> ---
#> 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: 533.57 on 605 degrees of freedom
#> AIC: 569.57
#>
#> Number of Fisher Scoring iterations: 15
Model Fitting
Pada model fitting, digunakan metode backward pada stepwise.
#> Start: AIC=569.57
#> Survived ~ Pclass + Sex + Age + SibSp + Parch + Fare
#>
#> Df Deviance AIC
#> - Parch 6 539.73 563.73
#> - Fare 1 533.60 567.60
#> <none> 533.57 569.57
#> - SibSp 6 555.68 579.68
#> - Age 1 548.16 582.16
#> - Pclass 2 579.45 611.45
#> - Sex 1 687.58 721.58
#>
#> Step: AIC=563.73
#> Survived ~ Pclass + Sex + Age + SibSp + Fare
#>
#> Df Deviance AIC
#> - Fare 1 539.73 561.73
#> <none> 539.73 563.73
#> - SibSp 6 564.81 576.81
#> - Age 1 559.86 581.86
#> - Pclass 2 592.65 612.65
#> - Sex 1 701.40 723.40
#>
#> Step: AIC=561.73
#> Survived ~ Pclass + Sex + Age + SibSp
#>
#> Df Deviance AIC
#> <none> 539.73 561.73
#> - SibSp 6 565.68 575.68
#> - Age 1 560.03 580.03
#> - Pclass 2 617.19 635.19
#> - Sex 1 701.95 721.95
#>
#> Call:
#> glm(formula = Survived ~ Pclass + Sex + Age + SibSp, family = "binomial",
#> data = titanic_train)
#>
#> Coefficients:
#> Estimate Std. Error z value Pr(>|z|)
#> (Intercept) 3.981265 0.490243 8.121 0.000000000000000462 ***
#> Pclass2nd -1.258289 0.317902 -3.958 0.000075546054397168 ***
#> Pclass3rd -2.372355 0.291978 -8.125 0.000000000000000447 ***
#> Sexmale -2.721734 0.239672 -11.356 < 0.0000000000000002 ***
#> Age -0.041350 0.009571 -4.320 0.000015578826383720 ***
#> SibSp1 0.172846 0.245809 0.703 0.48195
#> SibSp2 -0.881727 0.761128 -1.158 0.24668
#> SibSp3 -2.258307 0.815052 -2.771 0.00559 **
#> SibSp4 -2.688502 1.147360 -2.343 0.01912 *
#> SibSp5 -15.983849 956.847350 -0.017 0.98667
#> SibSp8 -16.428739 1057.640555 -0.016 0.98761
#> ---
#> 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: 539.73 on 612 degrees of freedom
#> AIC: 561.73
#>
#> Number of Fisher Scoring iterations: 15
Prediksi
Pada prediksi target, digunakan model_reglog2 yang
merupakan model hasil dari stepwise. Dalam hal ini, juga akan
dilihat 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. Pada
syntax dibawah, akan ditunjukkan ketika probabilitas data test lebih
dari 0,5 artinya penumpang Survived.
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
Model Evaluation
Pada model regresi logistik akan digunakan confusion matrix sebagai metriks evaluasi.
• 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 134 27
#> Survived 24 83
#>
#> Accuracy : 0.8097
#> 95% CI : (0.7575, 0.8549)
#> No Information Rate : 0.5896
#> P-Value [Acc > NIR] : 0.00000000000001228
#>
#> Kappa : 0.6052
#>
#> Mcnemar's Test P-Value : 0.7794
#>
#> Sensitivity : 0.7545
#> Specificity : 0.8481
#> Pos Pred Value : 0.7757
#> Neg Pred Value : 0.8323
#> Prevalence : 0.4104
#> Detection Rate : 0.3097
#> Detection Prevalence : 0.3993
#> Balanced Accuracy : 0.8013
#>
#> 'Positive' Class : Survived
#>
💡 Interpretasi Dari hasil confusion
matrix, model Regresi Logistik memiliki tingkat akurasi sebesar
80,97% (kemampuan menebak target Y). Kemampuan model Regresi Logistik
dalam memprediksi penumpang yang Survived yaitu sebesar
75,75% dan kemampuan model dalam memprediksi penumpang yang
Unsurvived yaitu sebesar 85,49%.
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
Langkah pertama dalam pemodelan menggunakan KNN adalah membuat variable dummy dari variabel kategori yang akan digunakan dalam klasifikasi
dmy <- dummyVars (" ~Survived+Pclass+Sex+SibSp+Parch", data = titanic_data)
dmy <- data.frame(predict(dmy, newdata = titanic_data))
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 ...
Setelah mengubah variabel kategory menjadi dummy, maka variabel dummy pada data seblumnya akan 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"
Selanjutnya membentuk data train dan test baru dari data
dmy yang telah terbentuk
Prediksi
Selanjutnya dilakukan prediksi dengan KNN
#> [1] 1 1 0 0 0 1 1 0 0 0 1 1 0 1 0 1 1 1 1 0 1 1 0 1 1 1 1 0 1 0 1 1 1 1 0 1 1
#> [38] 0 1 1 1 1 0 1 0 1 1 1 0 0 1 0 1 1 1 1 0 0 0 1 1 0 1 1 1 1 0 1 0 1 0 0 0 1
#> [75] 0 1 1 1 1 1 1 1 0 0 0 0 0 1 1 1 0 0 1 1 1 0 0 1 0 1 1 0 0 1 1 1 0 1 0 0 1
#> [112] 0 1 0 1 0 1 1 1 1 1 1 0 1 0 1 1 0 1 1 1 1 1 0 1 1 0 0 1 0 0 1 0 1 0 1 0 0
#> [149] 0 1 1 0 1 0 0 0 0 1 0 1 0 1 0 1 1 1 1 1 0 1 1 0 1 1 1 1 1 1 1 0 0 0 0 0 1
#> [186] 1 0 0 1 0 1 0 0 1 1 1 0 1 1 0 1 1 1 1 0 0 1 1 1 0 0 1 0 0 0 0 0 1 1 0 0 1
#> [223] 0 0 1 1 1 1 1 1 0 1 1 0 1 1 1 0 0 1 0 1 1 1 0 1 0 1 1 0 1 0 1 1 0 1 0 1 1
#> [260] 0 0 1 1 0 1 1 1 0
#> Levels: 0 1
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 Dari hasil confusion
matrix, model KNN memiliki tingkat akurasi sebesar 100% (kemampuan
menebak target Y). Kemampuan model KNN dalam memprediksi penumpang yang
Survived yaitu sebesar 98,63% dan kemampuan model dalam
memprediksi penumpang yang Unsurvived yaitu sebesar
100%.
5 Model Evaluation : Logistic Regression vs KNN
Langkah terakhir yaitu membandingkan efektifitas model dari Regresi Logistik dan KNN untuk mendapatkan model terbaik.
#*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.810 0.755 0.848 0.776
#*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.848 1
Dari hasil perbandingan evaluasi model, kemampuan model KNN lebih
unggul dari sisi Accuracy, Recall, dan
Precision dari model Regresi Logistik, sedangkan dari sisi
Specificity kedua model memiliki nilai yang sama. Hal ini
menunjukkan bahwa model KNN lebih baik dalam meprediksi penumpang
Kapal Titanic yang akan Survived maupun
Unsurvived.
6 Conclusion
Pada kasus prediksi penumpang Kapal Titanic yang Survived
atau Unsurvived, kedua model yang digunakan yaitu KNN dan
Regresi Logistik memiliki akurasi yang tinggi. Namun, berdasarkan
Confusion Matriks, KNN lebih mampu memprediksi secara akurat
dibanding Regresi Logistik. Jika kita ingin memaksimalkan jumlah hasil
positif dan negatif yang benar, kita dapat menggunakan
accuracy. Namun, jika tujuan utama adalah melihat
klasifikasi positif, maka yang digunakan adalah precision,
sehingga prioritas metriks yang digunakan adalah
precision.