ÖZET

Öğrenci Ad Soyad: Nizami Farziyev

Ödevde Kaggle Titanic Spaceship yarışması için gerekli kod yazılacaktır. Titanic Spaceship veriseti çekilerek veri inceleyip ön işleme işlemleri gerçekleştirilecektir. Daha sonra 3 adet makine öğrenmesi modeli kullanılarak test verisinde test edilip modellerin doğruluk oranları hesaplanacaktır. En başarılı model tüm test verisi üzerinde uygulanıp tahminlerin bulunduğu csv dosyası yarışmaya submit edilip ekran görüntüsü bu dosyanın sonuna eklenecektir.

Öncelikle gerekli kütüphaneler yüklenir ve veri csv dosyasından okunur.

# İlgili kütüphaneler yüklenir:
library(tidyverse) # Veri işlemleri için kullanılacak kütüphane
## ── Attaching core tidyverse packages ──────────────────────── tidyverse 2.0.0 ──
## ✔ dplyr     1.1.4     ✔ readr     2.1.4
## ✔ forcats   1.0.0     ✔ stringr   1.5.1
## ✔ ggplot2   3.4.4     ✔ tibble    3.2.1
## ✔ lubridate 1.9.3     ✔ tidyr     1.3.0
## ✔ purrr     1.0.2     
## ── Conflicts ────────────────────────────────────────── tidyverse_conflicts() ──
## ✖ dplyr::filter() masks stats::filter()
## ✖ dplyr::lag()    masks stats::lag()
## ℹ Use the conflicted package (<http://conflicted.r-lib.org/>) to force all conflicts to become errors
library(caret) # Makine Öğrenmesi modelleri için kullanılacak kütüphane
## Loading required package: lattice
## 
## Attaching package: 'caret'
## 
## The following object is masked from 'package:purrr':
## 
##     lift
library(rpart) # Decision Tree algoritması için kullanılacak kütüphane
library(rpart.plot) # Decision Tree bastırmak için kullanılacak kütüphane
library(e1071) # Naive bayes algoritması için kullanılacak kütüphane 
#library(caTools) # Naive bayes algoritması için kullanılacak kütüphane 

VERİ İŞLEMLERİ

Veri Analizi

# Eğitim verisi ilgili csv dosyasından okunur
df = read_csv("C:\\Project\\train.csv",show_col_types = FALSE)
head(df)
## # A tibble: 6 × 14
##   PassengerId HomePlanet CryoSleep Cabin Destination     Age VIP   RoomService
##   <chr>       <chr>      <lgl>     <chr> <chr>         <dbl> <lgl>       <dbl>
## 1 0001_01     Europa     FALSE     B/0/P TRAPPIST-1e      39 FALSE           0
## 2 0002_01     Earth      FALSE     F/0/S TRAPPIST-1e      24 FALSE         109
## 3 0003_01     Europa     FALSE     A/0/S TRAPPIST-1e      58 TRUE           43
## 4 0003_02     Europa     FALSE     A/0/S TRAPPIST-1e      33 FALSE           0
## 5 0004_01     Earth      FALSE     F/1/S TRAPPIST-1e      16 FALSE         303
## 6 0005_01     Earth      FALSE     F/0/P PSO J318.5-22    44 FALSE           0
## # ℹ 6 more variables: FoodCourt <dbl>, ShoppingMall <dbl>, Spa <dbl>,
## #   VRDeck <dbl>, Name <chr>, Transported <lgl>

VERİ ALANLARI

Yolcu Kimliği:

  • PassengerId: Her yolcu için benzersiz bir kimlik numarası. Bir grup kodu (“xxxx”) ve grup büyüklüğü (“yy”) içermektedir. Örneğin, “ABC12_03” grubu “ABC12” ve 3 üyeyi temsil eder.

Seyahat Bilgileri:

  • HomePlanet: Yolcunun çıkış gezegeni (Dünya, Europa, Mars veya eksik değer).

  • Destination: Yolcunun iniş gezegeni (TRAPPIST-1e, 55 Cancri e veya Diğer).

  • CryoSleep: Yolcunun yolculuk boyunca dondurulmuş animasyon durumunda olup olmadığını belirtir (Doğru, Yanlış veya eksik değer).

  • Cabin: Yolcunun kabinini belirtir, formatı “katta/numara/yan” şeklindedir (örneğin, “A/23/P” için Kat A, Kabin 23, Port Taraf).

Yolcu Ayrıntıları:

  • Age: Yolcunun yaşı.

  • VIP: Yolculuğun VIP statüsünü belirtir (Doğru, Yanlış veya eksik değer).

  • Name: Yolcunun adı.

Gemide Harcama:

  • RoomService, FoodCourt, ShoppingMall, Spa, VRDeck: Yolculuk sırasında çeşitli faaliyetlere yapılan harcamalar (Dolar cinsinden).

Sonuç:

  • Transported: Yolcunun taşınıp taşınmadığını belirtir (Doğru veya Yanlış).

Veri İşlemleri

pass_id ve group_size sütunları

PassengerId sütunu hem yolcunun kimlik numarasını hem de grup büyüklüğünü temsil ettiği için bu sütunu pass_id ve group_size olarak 2 sütuna ayırabiliriz:

df2 <- df %>%
  separate(PassengerId, c("Pass_id","Group_size"),"_") %>%
  mutate(Group_size = as.numeric(Group_size)) 

deck ve size sütunları

Cabin sütunu kabin harfi, kabin numarası ve taraf bilgilerini içerdiği için bu sütunu 3’e ayırabiliriz.

df2 <- df2 %>%
  separate(Cabin,c("Deck","Number","Side"),"/") %>%
  mutate(Side = ifelse(Side == "P","Port","Starboard")) 
# istenmeyen öznitelikler çıkarılır
df2 = df2 %>% 
  select(-c(Name, VIP, RoomService, FoodCourt, ShoppingMall, Spa, VRDeck, Pass_id, Number, Age))

Eksik Veriler

Hangi verilerin eksik olduğu kontrol edilir:

# eksik verilerin kontrolü
na_prop = function(vec){
  sum(is.na(vec)) / length(vec)
}
lapply(df2[,1:ncol(df2)], na_prop)
## $Group_size
## [1] 0
## 
## $HomePlanet
## [1] 0.02312205
## 
## $CryoSleep
## [1] 0.02496261
## 
## $Deck
## [1] 0.02289198
## 
## $Side
## [1] 0.02289198
## 
## $Destination
## [1] 0.02093639
## 
## $Transported
## [1] 0

Herhangi bir sütundaki verisi eksik olan satırlar kontrol edilir:

# Herhangi bir verisi eksik olan satırlar
1 - (nrow(drop_na(df2)) / nrow(df2))
## [1] 0.08892212

Eksik veri olan öznitelikler basit bir şekilde aşağıdaki gibi doldurulur:

HomePlanet: “Mars”

Deck, Side, CryoSleep, Destination: Sütunda bulunan en sık görülen değer.

# mod almak için kullanılacak fonksiyon
find_mode <- function(x) {
  u <- unique(x)
  tab <- tabulate(match(x, u))
  u[tab == max(tab)]
}

# eksik verilerin sabit değerlerle veya mod metodu ile doldurulması
df2 = df2 %>% 
  mutate(HomePlanet = ifelse(is.na(HomePlanet), "Mars", HomePlanet), 
         Deck = ifelse(is.na(Deck), find_mode(df2$Deck), Deck),
         Side = ifelse(is.na(Side), find_mode(df2$Side), Side),
         CryoSleep = ifelse(is.na(CryoSleep), find_mode(df2$CryoSleep), CryoSleep),
         Destination = ifelse(is.na(Destination), find_mode(df2$Destination), Destination),
         #Age = ifelse(is.na(Age), find_mode(df2$Age),Age),
         Transported = as.factor(as.numeric(Transported))
)

Tekrar veri kontrol edilir ve herhangi bir satırdaki bir verinin eksik olmadığı görülür.

# Herhangi bir verisi eksik olan satırlar
1 - (nrow(drop_na(df2)) / nrow(df2))
## [1] 0

MAKİNE ÖĞRENMESİ

Öncelikle veri %80 eğitim %20 test verisi olacak şekilde 2’ye ayrılır:

# Eğitim için kullanılacak train ve test verilerinin birbirinden ayrılması
ix = sample(1:nrow(df2), 0.8 * nrow(df2))
train = df2[ix,]  
test = df2[-ix,]

Ödev kapsamında 3 adet makine öğrenmesi modeli kullanılacaktır: Decision Tree, kNN ve Naive Bayes. Doğruluğu en yüksek olan model Kaggle’daki test.csv dosyası üzerinde test edilerek submission.csv dosyası oluşturulup yarışmaya submit edilecektir.

Decision Tree Modeli

Karar Ağaçları, hem regresyon hem de sınıflandırma görevlerini gerçekleştirme yeteneğine sahip, denetimli öğrenme algoritmalarıdır. Bu algoritma, düğüm ve dallarla karakterizedir, her bir öznitelik üzerindeki testler düğümlerde temsil edilir, bu işlemin sonucu dallarda temsil edilir ve sınıf etiketleri yaprak düğümlerde temsil edilir. Bu nedenle, muhtemel sonuçları hesaplamak için çeşitli kararlar temel alan ağaç benzeri bir model kullanır. Bu tür ağaç tabanlı algoritmalar, yorumlaması ve kullanımı kolay olduğu için geniş bir şekilde kullanılan algoritmalar arasındadır. Bunun dışında, bu algoritma tarafından geliştirilen öngörü modellerinin iyi bir istikrar ve makul bir doğruluğa sahip olduğu gözlemlenmiştir, bu nedenle çok popülerdir.

Ödev kapsamında ilk algoritma olarak Decision Tree yani Karar Ağacı Modeli kullanılacaktır. Önce model train verisi ile eğitilir:

set.seed(20240115)

dec_tree <- rpart(Transported~., data = train)
prediction <- rpart.predict(dec_tree, newdata = test, type = 'vector') 

Oluşan karar ağacının test datası kullanarak doğruluğu hesaplanır:

cm <- table(prediction, test$Transported)
accuracy <- sum(diag(cm))/sum(cm)
accuracy
## [1] 0.7142036

kNN

K-En Yakın Komşular (KNN), hem regresyon hem de sınıflandırma görevleri için kullanılabilen bir denetimli makine öğrenme modelidir. Algoritma, verinin temel dağılımı hakkında herhangi bir varsayım yapmadığı anlamına gelen non-parametrik bir özellik taşır.

KNN algoritması, test veri kümesinin etiketlerini, eğitim veri kümesinin öznitelik uzayındaki en yakın komşularının etiketlerine bakarak tahmin eder. “K” en önemli hiperparametredir ve modelin performansını optimize etmek için ayarlanabilen bir değerdir.

Model kullanılırken k değeri modele parametre olarak verilir ve model eğitilir. Modelin eğitilme sürecinde 5 fold cross-validation kullanılacaktır.

# k parametresi
knn_tune = expand.grid(
  k = seq(1, 60, 2)
)

# modelin eğitimi
knn = train(Transported ~ .,
                 data = train,
                 method = "knn", 
                 trControl =  trainControl(method = "cv", number = 5),
                 tuneGrid = knn_tune
)

# modelin doğruluk oranı
preds = as.numeric(predict(knn, test, type = "raw"))-1
actual = test$Transported
mean(preds == actual)
## [1] 0.7096032

Naive Bayes

Naive Bayes, R Programlama dilinde kullanılan denetimli bir non-lineer sınıflandırma algoritmasıdır. Naive Bayes sınıflandırıcıları, özellikler veya değişkenler arasında güçlü (Naif) bağımsızlık varsayımları yaparak Bayes teoremini uygulayan basit olasılıksal sınıflandırıcıların bir ailesidir.

Veriler eğitildikten sonra bir confusion matrix hesaplanır. Confusion matrixe göre de modelin doğruluğu kontrol edilir.

set.seed(120)  

# Modelin Naive Bayes yöntemi ile eğitilmesi
classifier_cl <- naiveBayes(Transported ~ ., data = train)
classifier_cl
## 
## Naive Bayes Classifier for Discrete Predictors
## 
## Call:
## naiveBayes.default(x = X, y = Y, laplace = laplace)
## 
## A-priori probabilities:
## Y
##        0        1 
## 0.501438 0.498562 
## 
## Conditional probabilities:
##    Group_size
## Y       [,1]     [,2]
##   0 1.456840 1.036795
##   1 1.581771 1.075560
## 
##    HomePlanet
## Y       Earth    Europa      Mars
##   0 0.6145684 0.1706338 0.2147978
##   1 0.4456302 0.3224690 0.2319008
## 
##    CryoSleep
## Y       FALSE      TRUE
##   0 0.8726699 0.1273301
##   1 0.4349582 0.5650418
## 
##    Deck
## Y             A           B           C           D           E           F
##   0 0.029251506 0.048465730 0.055635217 0.061657585 0.129624319 0.386865500
##   1 0.029708682 0.131814249 0.116238823 0.045860975 0.069224113 0.307470436
##    Deck
## Y             G           T
##   0 0.287353026 0.001147118
##   1 0.299682723 0.000000000
## 
##    Side
## Y        Port Starboard
##   0 0.5354173 0.4645827
##   1 0.4358235 0.5641765
## 
##    Destination
## Y   55 Cancri e PSO J318.5-22 TRAPPIST-1e
##   0  0.16260396    0.09262977  0.74476627
##   1  0.25093741    0.08941448  0.65964811
y_pred <- predict(classifier_cl, newdata = test)
 
# Confusion Matrix
cm <- table(test$Transported, y_pred)

 
# Modelin değerlendirilmesi
confusionMatrix(cm)
## Confusion Matrix and Statistics
## 
##    y_pred
##       0   1
##   0 615 213
##   1 303 608
##                                           
##                Accuracy : 0.7033          
##                  95% CI : (0.6812, 0.7247)
##     No Information Rate : 0.5279          
##     P-Value [Acc > NIR] : < 2.2e-16       
##                                           
##                   Kappa : 0.4081          
##                                           
##  Mcnemar's Test P-Value : 8.928e-05       
##                                           
##             Sensitivity : 0.6699          
##             Specificity : 0.7406          
##          Pos Pred Value : 0.7428          
##          Neg Pred Value : 0.6674          
##              Prevalence : 0.5279          
##          Detection Rate : 0.3537          
##    Detection Prevalence : 0.4761          
##       Balanced Accuracy : 0.7052          
##                                           
##        'Positive' Class : 0               
## 
# Doğruluk
accuracy <- sum(diag(cm))/sum(cm)
accuracy
## [1] 0.7032777

SONUÇ

En yüksek doğruluk oranının kNN modelinde alındığı görülmüştür. Bu model kullanılarak tüm test verisi üzerinde bu model kullanılarak prediction değerleri submission dosyasına yazılacaktır.

Öncelikle veri ile ilgili yapılan işlemler test.csv den alınan veriler için de yapılır.

test = read_csv("C:\\Project\\test.csv")
## Rows: 4277 Columns: 13
## ── Column specification ────────────────────────────────────────────────────────
## Delimiter: ","
## chr (5): PassengerId, HomePlanet, Cabin, Destination, Name
## dbl (6): Age, RoomService, FoodCourt, ShoppingMall, Spa, VRDeck
## lgl (2): CryoSleep, VIP
## 
## ℹ Use `spec()` to retrieve the full column specification for this data.
## ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
# Sütunların ayrılması
test_full <- test %>%
  separate(PassengerId, c("Pass_id","Group_size"),"_", remove=FALSE) %>%
  mutate(Group_size = as.numeric(Group_size)) 

 test_full <- test_full %>%
  separate(Cabin,c("Deck","Number","Side"),"/") %>%
  mutate(Side = ifelse(Side == "P","Port","Starboard")) 
# Eksik verilerin doldurulması
test_full = test_full %>% 
  mutate(HomePlanet = ifelse(is.na(HomePlanet), "Mars", HomePlanet), 
         Deck = ifelse(is.na(Deck), find_mode(df2$Deck), Deck),
         Side = ifelse(is.na(Side), find_mode(df2$Side), Side),
         CryoSleep = ifelse(is.na(CryoSleep), find_mode(df2$CryoSleep), CryoSleep),
         Destination = ifelse(is.na(Destination), find_mode(df2$Destination), Destination)
)
predictions = data.frame(PassengerId =test_full$PassengerId, Transported = str_to_title(as.logical(as.numeric(predict(knn, test_full))-1)))

write.csv(predictions, "submission.csv", row.names = FALSE)