1 Pendahuluan

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.

  • Target : Tingkat Kjeahatan survived.
  • Prediktor : Semua variabel, kecuali survived.
knitr::include_graphics("img/titanic.jfif")

1.1 Deskripsi Kolom

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).

2 EDA & Data Wrangling

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

2.1 Cek Missing Value

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)

2.2 Visual Basic

# 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)

3 Membuat Model (Modelling)

Selanjutnya, dilakukan pembuatan model menggunakan Regresi Logistik dan KNN.

3.1 Cross Validation

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, ] 

3.2 Logistic Regression

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)

3.2.1 Model Fitting

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.

3.2.2 Prediksi

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")]

3.2.3 Evaluasi Performa Model

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"]

3.2.4 Menampilkan hasil evaluasi

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

3.2.5 Model Interpretation

exp(model_both$coefficients) %>%
  data.frame()

3.3 K-Nearest Neighbour (KNN)

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…

3.3.1 Filter prediktor numeric

data_num <- data[, c("Survived", "Age", "Fare")]
head(data_num)

3.3.2 Cek proporsi kelas

prop.table(table(data_num$Survived))
#> 
#>         0         1 
#> 0.6161616 0.3838384

4 Cek Range Nilai Variable Prediktor

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

4.0.1 Cross Validation

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, ]

4.0.2 Pre-processing

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"]

4.0.3 Scaling Data

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

4.0.4 KNN Model Training and Prediction

knn_model <- knn(train = data_num_train_xs,
                 test = data_num_test_xs,
                 cl = data_num_train_y,
                 k = optimal_k)

4.0.5 Model Evaluation

confusion_matrix_knn <- confusionMatrix(data = knn_model,
                                        reference = data_num_test_y,
                                        positive = "1")

4.0.6 Menampilkan Hasil Evaluasi

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

4.1 Model Evaluation Logistic Regression & KNN

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_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.

5 Penutup

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.

5.1 Saran :

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.

5.2 Kesimpulan

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.