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
.::include_graphics("img/titanic.jfif") knitr
<- read.csv("data_input/titanic.csv")
data 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
$Age[is.na(data$Age)] <- mean(data$Age, na.rm=TRUE) data
# 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
<- sample(x = nrow(data),
index size = nrow(data)*0.7)
# splitting
<- data[index, ]
data_train <- data[-index, ] data_test
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.
<- glm(formula = Survived ~ ., family = "binomial",
model_all data = data_train)
library(MASS)
<- step(model_all, direction = "both") model_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
$aic model_all
#> [1] 589.6416
$aic model_both
#> [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
.
$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_test1:10, c("pred_data", "Survived")] data_test[
library(caret)
<- confusionMatrix(data = data_test$pred_data, reference = data_test$Survived)
confusion_matrix <- confusion_matrix$overall["Accuracy"]
accuracy <- confusion_matrix$byClass["Pos Pred Value"]
precision <- confusion_matrix$byClass["Sensitivity"]
recall <- confusion_matrix$byClass["F1"] f1_score
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[, c("Survived", "Age", "Fare")]
data_num 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)
<- sample(x = nrow(data_num), size = nrow(data_num) * 0.8)
index <- data_num[index, ]
data_num_train <- data_num[-index, ] data_num_test
<- data_num_train %>% select_if(is.numeric)
data_num_train_x <- data_num_test %>% select_if(is.numeric)
data_num_test_x <- data_num_train[,"Survived"]
data_num_train_y <- data_num_test[,"Survived"] data_num_test_y
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.
<- scale(x = data_num_train_x)
data_num_train_xs <- scale(x = data_num_test_x,
data_num_test_xs center = attr(data_num_train_xs, "scaled:center"),
scale = attr(data_num_train_xs, "scaled:scale"))
# Find Optimal k
<- sqrt(nrow(data_num_train_xs))
optimal_k cat("Optimal k:", optimal_k, "\n")
#> Optimal k: 26.68333
<- knn(train = data_num_train_xs,
knn_model test = data_num_test_xs,
cl = data_num_train_y,
k = optimal_k)
<- confusionMatrix(data = knn_model,
confusion_matrix_knn 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
<- data.frame(Accuracy = confusion_matrix$overall["Accuracy"],
eval_logit Recall = confusion_matrix$byClass["Sensitivity"],
Specificity = confusion_matrix$byClass["Specificity"],
Precision = confusion_matrix$byClass["Pos Pred Value"])
# Evaluasi Model K-NN
<- data.frame(Accuracy = confusion_matrix_knn$overall["Accuracy"],
eval_knn Recall = confusion_matrix_knn$byClass["Sensitivity"],
Specificity = confusion_matrix_knn$byClass["Specificity"],
Precision = confusion_matrix_knn$byClass["Pos Pred Value"])
eval_logit
eval_knn
Insight :
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.