Laporan ini bertujuan untuk melakukan analisis klasifikasi menggunakan dataset Titanic dengan tujuan memprediksi kelangsungan hidup penumpang. Dalam laporan ini, model Logistic Regression dan K-Nearest Neighbors (KNN) digunakan, dan langkah-langkah yang dijelaskan mencakup pemrosesan data, pemilihan fitur, pengembangan model, evaluasi performa, serta interpretasi hasil dan perbandingan antara kedua model.
Dalam laporan ini, saya menggunakan dua model yang populer, yaitu
K-Nearest Neighbors (KNN) dan
Regresi Logistik, untuk memprediksi kelangsungan hidup
penumpang pada dataset Titanic. KNN adalah metode non-parametrik yang
mencari k-neighbors terdekat untuk mengklasifikasikan data, sementara
Regresi Logistik memprediksi probabilitas berdasarkan variabel
input.
survived.survived.knitr::include_graphics("img/titanic.jfif")data <- read.csv("data_input/titanic.csv")
glimpse(data)#> 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"…
Metadata :
PassengerId: Nomor identifikasi unik untuk setiap
penumpang.Survived: Menunjukkan apakah penumpang selamat (1) atau
tidak selamat (0).Pclass: Kelas tiket penumpang, dengan nilai 1, 2, atau
3, yang mencerminkan kelas sosial * ekonomi :(1: kelas
atas, 2: kelas menengah, 3: kelas bawah).Name: Nama lengkap penumpang.Sex: Jenis kelamin penumpang (male: pria, female:
wanita).Age: Usia penumpang dalam tahun.SibSp: Jumlah saudara kandung atau pasangan yang juga
ikut dalam kapal.Parch: Jumlah orang tua atau anak yang juga ikut dalam
kapal.Ticket: Nomor tiket penumpang.Fare: Tarif pembayaran penumpang.Cabin: Nomor kabin penumpang.Embarked: Pelabuhan tempat penumpang naik kapal (C:
Cherbourg, Q: Queenstown, S: Southampton).Ubah tipe data dan hapus kolom yang tidak perlu
data <- data %>%
select(-c(Name, PassengerId, Ticket, Cabin)) %>%
mutate(Survived = as.factor(Survived),
Pclass = as.factor(Pclass),
Sex = as.factor(Sex),
Embarked = as.factor(Embarked))
head(data)summary(data)#> Survived Pclass Sex Age SibSp Parch
#> 0:549 1:216 female:314 Min. : 0.42 Min. :0.000 Min. :0.0000
#> 1:342 2:184 male :577 1st Qu.:20.12 1st Qu.:0.000 1st Qu.:0.0000
#> 3:491 Median :28.00 Median :0.000 Median :0.0000
#> Mean :29.70 Mean :0.523 Mean :0.3816
#> 3rd Qu.:38.00 3rd Qu.:1.000 3rd Qu.:0.0000
#> Max. :80.00 Max. :8.000 Max. :6.0000
#> NA's :177
#> Fare Embarked
#> Min. : 0.00 : 2
#> 1st Qu.: 7.91 C:168
#> Median : 14.45 Q: 77
#> Mean : 32.20 S:644
#> 3rd Qu.: 31.00
#> Max. :512.33
#>
Diperoleh Insight :
Terdapat 549 penumpang yang tidak selamat (0) dan 342 penumpang yang selamat (1).
Terdapat 216 penumpang kelas 1, 184 penumpang kelas 2, dan 491 penumpang kelas 3.
*mTerdapat 577 penumpang laki-laki (0) dan 314 penumpang perempuan (1).
Rentang usia penumpang berkisar antara 0.42 tahun hingga 80 tahun. Rata-rata usia penumpang adalah 29.7 tahun.
Mayoritas penumpang tidak memiliki saudara atau pasangan yang ikut (0), diikuti oleh 209 penumpang dengan 1 saudara atau pasangan.
Mayoritas penumpang tidak memiliki orangtua atau anak yang ikut (0), diikuti oleh 118 penumpang dengan 1 orangtua atau anak.
Tarif tiket berkisar antara 0 hingga 512.33. Rata-rata tarif tiket adalah 32.2.
Mayoritas penumpang (644) naik kapal dari pelabuhan Southampton (S), diikuti oleh 168 penumpang dari pelabuhan Cherbourg (C) dan 77 penumpang dari pelabuhan Queenstown (Q).
prop.table(table(data$Survived))#>
#> 0 1
#> 0.6161616 0.3838384
Setelah itu, dilakukan penanganan missing value pada kolom Age dengan mengisi nilai yang hilang menggunakan rata-rata usia. Hal ini dilakukan agar dataset menjadi lebih lengkap dan tidak ada missing value yang mengganggu proses analisis.
colSums(is.na(data))#> Survived Pclass Sex Age SibSp Parch Fare Embarked
#> 0 0 0 177 0 0 0 0
# Mengisi nilai yang hilang dalam kolom Age dengan rata-rata usia
data$Age[is.na(data$Age)] <- mean(data$Age, na.rm=TRUE)# Menampilkan diagram batang untuk variabel Sex
barplot(table(data$Sex), main="Gender Distribution", xlab="Sex", ylab="Count")# Menampilkan boxplot untuk variabel Age
boxplot(data$Age, main="Boxplot of Age", ylab="Age")# Visualisasi distribusi variabel
hist(data$Age)Selanjutnya, dilakukan pembuatan model menggunakan Regresi Logistik dan KNN.
RNGkind(sample.kind = "Rounding")
set.seed(123)
# index sampling
index <- sample(x = nrow(data),
size = nrow(data)*0.7)
# splitting
data_train <- data[index, ]
data_test <- data[-index, ] Selanjutnya, dilakukan pembuatan model menggunakan Regresi Logistik dan KNN. Data dibagi menjadi data training dan data testing menggunakan cross-validation. Pada model Regresi Logistik, dilakukan fitting model menggunakan fungsi glm() dan dilakukan pemilihan fitur menggunakan metode stepwise. Hasil evaluasi model ditampilkan berdasarkan akurasi, presisi, recall, dan F1-score.
model_all <- glm(formula = Survived ~ ., family = "binomial",
data = data_train)library(MASS)
model_both <- step(model_all, direction = "both")#> Start: AIC=589.64
#> Survived ~ Pclass + Sex + Age + SibSp + Parch + Fare + Embarked
#>
#> Df Deviance AIC
#> - Embarked 3 570.87 586.87
#> - Parch 1 567.73 587.73
#> <none> 567.64 589.64
#> - Fare 1 570.14 590.14
#> - SibSp 1 573.31 593.31
#> - Age 1 580.04 600.04
#> - Pclass 2 592.90 610.90
#> - Sex 1 716.57 736.57
#>
#> Step: AIC=586.87
#> Survived ~ Pclass + Sex + Age + SibSp + Parch + Fare
#>
#> Df Deviance AIC
#> - Parch 1 571.10 585.10
#> <none> 570.87 586.87
#> - Fare 1 574.42 588.42
#> + Embarked 3 567.64 589.64
#> - SibSp 1 577.56 591.56
#> - Age 1 583.27 597.27
#> - Pclass 2 595.69 607.69
#> - Sex 1 732.67 746.67
#>
#> Step: AIC=585.1
#> Survived ~ Pclass + Sex + Age + SibSp + Fare
#>
#> Df Deviance AIC
#> <none> 571.10 585.10
#> - Fare 1 574.42 586.42
#> + Parch 1 570.87 586.87
#> + Embarked 3 567.73 587.73
#> - SibSp 1 579.65 591.65
#> - Age 1 583.35 595.35
#> - Pclass 2 596.73 606.73
#> - Sex 1 735.31 747.31
model_all$aic#> [1] 589.6416
model_both$aic#> [1] 585.1033
AIC menggambarkan banyaknya informasi yang hilang dari suatu model.
Semakin kecil AIC, semakin sedikit informasi yang hilang. Dari hasi
diatas, diketahui bahwa nilai AIC model_both lebih kecil
dibandingkan dengan model_all.
data_test$prob_bw <- predict(model_both, type = "response", newdata = data_test)data_test$pred_data <- factor(ifelse(data_test$prob_bw > 0.5, 1,0))
data_test[1:10, c("pred_data", "Survived")]library(caret)
confusion_matrix <- confusionMatrix(data = data_test$pred_data, reference = data_test$Survived)
accuracy <- confusion_matrix$overall["Accuracy"]
precision <- confusion_matrix$byClass["Pos Pred Value"]
recall <- confusion_matrix$byClass["Sensitivity"]
f1_score <- confusion_matrix$byClass["F1"]cat("Accuracy:", accuracy, "\n")#> Accuracy: 0.7910448
cat("Precision:", precision, "\n")#> Precision: 0.8245614
cat("Recall:", recall, "\n")#> Recall: 0.8443114
cat("F1 Score:", f1_score, "\n")#> F1 Score: 0.8343195
exp(model_both$coefficients) %>%
data.frame()Kemudian, dilakukan pula pembuatan model KNN. Pada tahap ini, dilakukan pemfilteran prediktor numeric dan pengecekan proporsi kelas. Data juga disajikan dalam bentuk summary untuk memahami range nilai variabel prediktor. Data training dan data testing dihasilkan dengan melakukan cross-validation.
library(class)
library(caret)
glimpse(data)#> 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.00000, 38.00000, 26.00000, 35.00000, 35.00000, 29.69912, 5…
#> $ SibSp <int> 1, 1, 0, 1, 0, 0, 0, 3, 0, 1, 1, 0, 0, 1, 0, 0, 4, 0, 1, 0, 0…
#> $ Parch <int> 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…
data_num <- data[, c("Survived", "Age", "Fare")]
head(data_num)prop.table(table(data_num$Survived))#>
#> 0 1
#> 0.6161616 0.3838384
summary(data_num)#> Survived Age Fare
#> 0:549 Min. : 0.42 Min. : 0.00
#> 1:342 1st Qu.:22.00 1st Qu.: 7.91
#> Median :29.70 Median : 14.45
#> Mean :29.70 Mean : 32.20
#> 3rd Qu.:35.00 3rd Qu.: 31.00
#> Max. :80.00 Max. :512.33
set.seed(123)
index <- sample(x = nrow(data_num), size = nrow(data_num) * 0.8)
data_num_train <- data_num[index, ]
data_num_test <- data_num[-index, ]data_num_train_x <- data_num_train %>% select_if(is.numeric)
data_num_test_x <- data_num_test %>% select_if(is.numeric)
data_num_train_y <- data_num_train[,"Survived"]
data_num_test_y <- data_num_test[,"Survived"]Sebelum proses pelatihan model KNN, dilakukan pre-processing dengan melakukan scaling data menggunakan fungsi scale(). Kemudian, dilakukan pencarian nilai k optimal menggunakan rumus optimal_k <- sqrt(nrow(data_num_train_xs)). Model KNN dilatih dan diuji menggunakan fungsi knn(), dan hasil evaluasi model ditampilkan berdasarkan akurasi, presisi, recall, dan F1-score.
data_num_train_xs <- scale(x = data_num_train_x)
data_num_test_xs <- scale(x = data_num_test_x,
center = attr(data_num_train_xs, "scaled:center"),
scale = attr(data_num_train_xs, "scaled:scale"))# Find Optimal k
optimal_k <- sqrt(nrow(data_num_train_xs))
cat("Optimal k:", optimal_k, "\n")#> Optimal k: 26.68333
knn_model <- knn(train = data_num_train_xs,
test = data_num_test_xs,
cl = data_num_train_y,
k = optimal_k)confusion_matrix_knn <- confusionMatrix(data = knn_model,
reference = data_num_test_y,
positive = "1")cat("KNN Model Performance\n")#> KNN Model Performance
cat("Accuracy:", confusion_matrix_knn$overall["Accuracy"], "\n")#> Accuracy: 0.6927374
cat("Precision:", confusion_matrix_knn$byClass["Pos Pred Value"], "\n")#> Precision: 0.5769231
cat("Recall:", confusion_matrix_knn$byClass["Sensitivity"], "\n")#> Recall: 0.4761905
cat("F1 Score:", confusion_matrix_knn$byClass["F1"], "\n")#> F1 Score: 0.5217391
Terakhir, dilakukan perbandingan hasil evaluasi antara model Regresi Logistik dan KNN. Evaluasi model untuk masing-masing model ditampilkan dalam bentuk data frame yang berisi nilai akurasi, recall, spesifisitas, dan presisi.
# Evaluasi Model Logistic Regression
eval_logit <- data.frame(Accuracy = confusion_matrix$overall["Accuracy"],
Recall = confusion_matrix$byClass["Sensitivity"],
Specificity = confusion_matrix$byClass["Specificity"],
Precision = confusion_matrix$byClass["Pos Pred Value"])
# Evaluasi Model K-NN
eval_knn <- data.frame(Accuracy = confusion_matrix_knn$overall["Accuracy"],
Recall = confusion_matrix_knn$byClass["Sensitivity"],
Specificity = confusion_matrix_knn$byClass["Specificity"],
Precision = confusion_matrix_knn$byClass["Pos Pred Value"])
eval_logiteval_knnInsight :
Berdasarkan nilai Recall, model Regresi Logistik memiliki nilai Recall yang lebih tinggi (0.8443114) dibandingkan dengan model K-NN (0.4761905). Ini menunjukkan bahwa model Regresi Logistik memiliki kemampuan yang lebih baik dalam memprediksi penumpang yang sebenarnya selamat sebagai tidak selamat.
Jadi, dari hasil evaluasi tersebut, dapat disimpulkan bahwa menggunakan metode Regresi Logistik lebih disarankan untuk memprediksi penumpang yang sebenarnya selamat sebagai tidak selamat dengan nilai Recall yang lebih tinggi.
Dalam analisis klasifikasi menggunakan model Regresi Logistik dan K-NN untuk memprediksi kelangsungan hidup penumpang Titanic, hasil evaluasi menunjukkan bahwa model Regresi Logistik memiliki kinerja yang lebih baik dalam memprediksi penumpang yang sebenarnya selamat sebagai tidak selamat, dengan nilai Recall yang lebih tinggi dibandingkan dengan model K-NN. Pada kasus ini, Recall menjadi metrik yang diprioritaskan karena risiko yang paling concern adalah terjadinya False Negative, yaitu penumpang yang sebenarnya selamat namun diprediksi sebagai tidak selamat.
Oleh karena itu, metrik terbaik yang dapat digunakan untuk
mengevaluasi performa model adalah Recall.
Recall mengukur kemampuan model dalam mengidentifikasi
penumpang yang sebenarnya selamat sebagai tidak selamat.
Dalam laporan ini, saya telah melakukan analisis untuk meningkatkan performa model. Beberapa langkah yang saya ambil meliputi:
Pemilihan Nilai K Optimum pada Model KNN
Perbandingan antara Model Regresi Logistik dan KNN
Dengan menerapkan pemilihan nilai K optimum pada model KNN dan melakukan perbandingan antara model Regresi Logistik dan KNN, langkah-langkah ini dapat membantu meningkatkan performa model dan memberikan wawasan tentang model mana yang paling sesuai untuk dataset Titanic.
Berdasarkan evaluasi yang dilakukan, dapat disimpulkan bahwa model Regresi Logistik memiliki kinerja yang lebih baik dalam memprediksi penumpang yang sebenarnya selamat sebagai tidak selamat. Hal ini ditunjukkan oleh nilai recall yang lebih tinggi pada model Regresi Logistik dibandingkan dengan model KNN.
Dalam penutup laporan, disarankan untuk menggunakan model Regresi Logistik sebagai model yang lebih optimal untuk memprediksi kelangsungan hidup penumpang Titanic berdasarkan evaluasi performa yang telah dilakukan.
Dengan demikian, laporan ini memberikan gambaran tentang proses analisis klasifikasi menggunakan dataset Titanic, pemilihan model, evaluasi performa, serta saran model yang disarankan untuk digunakan.