GİRİŞ

Titanic Spaceship
Titanic Spaceship

Öğrenci Adı Soyadı: Betül UÇAR

ÖDEV ÖZETİ

Bu ödevde 3 adet Makine Öğrenmesi modeli geliştirilerek Kaggle sitesinde bulunan Titanic Spaceship yarışmasına katılım sağlanacaktır. Titanic Spaceship yarışmasında bir uzay gemisindeki yolcuların özniteliklerinden faydalanılarak başka bir zaman boyutuna taşınıp taşınmadıklarının tahmini yapılması gerekmektedir. Yarışma sayfasında aşağıda bulunan öznitelikler ve açıklamaları verilmiştir: image.png

Ödevde verilen öznitelikler üzerinde önce bazı önişleme ve boş veriler için boşluk doldurma gibi işlemler yapılacaktır. Daha sonra bu veriler Random Forest, Logistic Regression ve k Nearest Neighbour modelleri üzerinde eğitilecektir. Doğruluğu en yüksek olan model, yarışmada verilen tüm test datası üzerinde test edilerek tahmin değerleri bir submission.csv dosyasına yazılacaktır. Son olarak bu dosya yarışmaya submit edilerek ekran görüntüsü eklenecektir.

ÖDEVE GİRİŞ

Öncelikle kullanılacak işlemler, modeller, grafikler için gerekli kütüphaneler library metodu kullanılarak projeye dahil edilir:

library(tidyverse) 
## ── 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(randomForest)
## randomForest 4.7-1.1
## Type rfNews() to see new features/changes/bug fixes.
## 
## Attaching package: 'randomForest'
## 
## The following object is masked from 'package:dplyr':
## 
##     combine
## 
## The following object is masked from 'package:ggplot2':
## 
##     margin
library(caret)
## Loading required package: lattice
## 
## Attaching package: 'caret'
## 
## The following object is masked from 'package:purrr':
## 
##     lift
library(e1071)

Daha sonra ödevde kullanılacak olan eğitim veri dosyası okunarak verinin ilk 5 satırı görüntülenir. Sonrasında veri incelenerek veri ile ilgili analiz, boşluk doldurma ve satır silme işlemleri gerçekleştirilecektir.

data_frame = read_csv("C:\\Project\\train.csv")
## Rows: 8693 Columns: 14
## ── Column specification ────────────────────────────────────────────────────────
## Delimiter: ","
## chr (5): PassengerId, HomePlanet, Cabin, Destination, Name
## dbl (6): Age, RoomService, FoodCourt, ShoppingMall, Spa, VRDeck
## lgl (3): CryoSleep, VIP, Transported
## 
## ℹ 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.
head(data_frame)
## # 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İ ANALİZİ VE EKSİK SATIRLARIN SİLİNMESİ

Yaş ve Harcamaları gösteren sütunlar

Yaş için boş değerleri yaş sütununun ortalamasını alarak doldurabiliriz. Harcamalar için ise eksik değerleri “0” olarak alabiliriz.

data_frame = data_frame %>% 
  mutate(Age= ifelse(is.na(Age),mean(Age, trim=0, na.rm=TRUE),Age),
         RoomService = ifelse(is.na(RoomService), 0, RoomService),
         FoodCourt = ifelse(is.na(FoodCourt), 0, FoodCourt),
         ShoppingMall = ifelse(is.na(ShoppingMall), 0, ShoppingMall),
         Spa = ifelse(is.na(Spa), 0, Spa),
         VRDeck = ifelse(is.na(VRDeck), 0, VRDeck)  
)

Eksik verisi bulunan toplam satır sayısı kontrol edilir:

1 - (nrow(drop_na(data_frame)) / nrow(data_frame))
## [1] 0.1304498

Eksik verisi olan satırları silmemiz modellerimizin eğitimini yüksek oranda etkilemeyecektir. Bu nedenle etkilemeyeceği düşünülen Name sütunu dışında eksik verisi olan satırlar silinecektir.

data_frame <- data_frame[!is.na(data_frame$HomePlanet),]
data_frame <- data_frame[!is.na(data_frame$CryoSleep),]
data_frame <- data_frame[!is.na(data_frame$Cabin),]
data_frame <- data_frame[!is.na(data_frame$Destination),]
data_frame <- data_frame[!is.na(data_frame$VIP),]
1 - (nrow(drop_na(data_frame)) / nrow(data_frame))
## [1] 0.02288004

Verideki eksik satırlar tekrar kontrol edilir.

Cabin Sütunu

Veri ile ilgili modeli etkileyecek işlemler olup olmadığı kontrol edildiğinde, Cabin sütunu 3 adet veriden oluştuğu için bu verilerin her birinin ayrı kolon olabileceği görülmüştür. Cabin sütunu yarışma sayfasında belirtildiği gibi Deck, Num ve Sleep olarak 3 ayrı sütuna ayrılır:

data_frame <- data_frame %>%
  separate(Cabin,c("Deck","Num","Side"),"/") %>%
  mutate(Side = ifelse(Side == "P","Port","Starboard"),
        Transported = as.factor(as.numeric(Transported)),
        )

Veri ile ilgili işlemler tamamlandıktan sonra kullanılmayacak kolonlar veriden çıkarılır ve Makine Öğrenmesi aşamasına geçilir.

data_frame = data_frame %>% select(-c(PassengerId, Name, Num, VIP))
head(data_frame)
## # A tibble: 6 × 12
##   HomePlanet CryoSleep Deck  Side      Destination     Age RoomService FoodCourt
##   <chr>      <lgl>     <chr> <chr>     <chr>         <dbl>       <dbl>     <dbl>
## 1 Europa     FALSE     B     Port      TRAPPIST-1e      39           0         0
## 2 Earth      FALSE     F     Starboard TRAPPIST-1e      24         109         9
## 3 Europa     FALSE     A     Starboard TRAPPIST-1e      58          43      3576
## 4 Europa     FALSE     A     Starboard TRAPPIST-1e      33           0      1283
## 5 Earth      FALSE     F     Starboard TRAPPIST-1e      16         303        70
## 6 Earth      FALSE     F     Port      PSO J318.5-22    44           0       483
## # ℹ 4 more variables: ShoppingMall <dbl>, Spa <dbl>, VRDeck <dbl>,
## #   Transported <fct>

MODELLER

Modellerin eğitimi için train.csvden ve işlemler yapılmış olan veriseti 2’ye ayrılır. 4/5’i eğitim veriseti 1/5’i test veriseti olarak kullanılacaktır. Daha sonra Random Forest, kNN ve Logistic Regression modelleri geliştirilecektir.

i = sample(1:nrow(data_frame), 0.8 * nrow(data_frame))
train_data = data_frame[i,]  
test_data = data_frame[-i,]

1. RANDOM FOREST

Bir topluluk öğrenme yöntemi olan Random Forest (Rassal Orman) algoritması, sınıflandırma işlemi esnasında birden fazla karar ağacı üreterek sınıflandırma değerini yükseltmeyi hedefleyen bir algoritmadır.

Random Forest modeli eğitim verileri kullanılarak eğitilir.

random_forest_model <- randomForest(Transported ~ ., train_data,ntree=500)
summary(random_forest_model)
##                 Length Class  Mode     
## call                4  -none- call     
## type                1  -none- character
## predicted        6188  factor numeric  
## err.rate         1500  -none- numeric  
## confusion           6  -none- numeric  
## votes           12376  matrix numeric  
## oob.times        6188  -none- numeric  
## classes             2  -none- character
## importance         11  -none- numeric  
## importanceSD        0  -none- NULL     
## localImportance     0  -none- NULL     
## proximity           0  -none- NULL     
## ntree               1  -none- numeric  
## mtry                1  -none- numeric  
## forest             14  -none- list     
## y                6188  factor numeric  
## test                0  -none- NULL     
## inbag               0  -none- NULL     
## terms               3  terms  call

Test için ayrılmış veriler kullanılarak eğitilen Random Forest makine öğrenmesi modelinin başarım oranı hesaplanır.

RANDOM FOREST BAŞARIM ORANI(%)

100*mean(test_data$Transported==predict(random_forest_model,test_data))
## [1] 79.58656

2. LOGISTIC REGRESSION

Lojistik regresyon analizi sınıflama ve atama işlemi yapmaya yardımcı olan bir regresyon yöntemidir. Normal dağılım varsayımı, süreklilik varsayımı ön koşulu yoktur. Açıklayıcı değişkenlere göre cevap değişkeninin beklenen değerleri olasılık olarak elde edilen bir regresyon yöntemidir.

Eğitim verisi kullanılarak bir logistic regression modeli eğitilir.

logistic_regression_model = train(form = Transported ~ .,
                 data = train_data,
                 method = "glm",
                 family = 'binomial',
                 trControl = trainControl(method = "cv", number = 5)
)
## Warning: glm.fit: fitted probabilities numerically 0 or 1 occurred

## Warning: glm.fit: fitted probabilities numerically 0 or 1 occurred

## Warning: glm.fit: fitted probabilities numerically 0 or 1 occurred

## Warning: glm.fit: fitted probabilities numerically 0 or 1 occurred

## Warning: glm.fit: fitted probabilities numerically 0 or 1 occurred

## Warning: glm.fit: fitted probabilities numerically 0 or 1 occurred

Daha sonra eğitilen regresyon modeli test için ayrılmış veriler kullanılarak test edilir ve başarım oranı hesaplanır.

LOGISTIC REGRESSION BAŞARIM ORANI(%)

100 * mean(test_data$Transported == as.numeric(predict(logistic_regression_model, test_data, type = "raw"))-1)
## [1] 78.22997

3. k EN YAKIN KOMŞULUK ALGORİTMASI (kNN)

KNN en basit anlamı ile içerisinde tahmin edilecek değerin bağımsız değişkenlerinin oluşturduğu vektörün en yakın komşularının hangi sınıfta yoğun olduğu bilgisi üzerinden sınıfını tahmin etmeye dayanır.

KNN (K-Nearest Neighbors) Algoritması iki temel değer üzerinden tahmin yapar;

Distance (Uzaklık): Tahmin edilecek noktanın diğer noktalara uzaklığı hesaplanır. Bunun için Minkowski uzaklık hesaplama fonksiyonu kullanılır.

K (komuşuluk sayısı): En yakın kaç komşu üzerinden hesaplama yapılacağını söyleriz. K değeri sonucu direkt etkileyecektir. K 1 olursa overfit etme olasılığı çok yüksek olacaktır. Çok büyük olursa da çok genel sonuçlar verecektir. Bu sebeple optimum K değerini tahmin etmek problemin asıl konusu olarak karşımızda durmaktadır. K değerinin önemini aşağıdaki grafik çok güzel bir şekilde göstermektedir. Eğer K=3 ( düz çizginin olduğu yer) seçersek sınıflandırma algoritması ? işareti ile gösterilen noktayı, kırmızı üçgen sınıfı olarak tanımlayacaktır. Fakat K=5 (kesikli çizginin olduğu alan) seçersek sınıflandırma algoritması, aynı noktayı mavi kare sınıfı olarak tanımlayacaktır.

knn
knn
knn_model = train(Transported ~ .,
                 data = train_data,
                 method = "knn", 
                 trControl =  trainControl(method = "cv", number = 5),
                 tuneGrid = expand.grid(k=seq(2,60,2))
)

Eğitim verileri kullanılarak bir k-nearest neighbour modeli eğitilir ve test verileri kullanılarak test edilir. Test verileri ile tahminler edildikten sonra modelin başarım oranı hesaplanır.

KNN BAŞARIM ORANI(%)

100 * mean(test_data$Transported == as.numeric(predict(knn_model, test_data, type = "raw"))-1)
## [1] 78.55297

En iyi başarım oranı Random Forest algoritmasında alındığı için Kaggle yarışmasında bu model kullanılacaktır. Yarışmaya katılmak için öncelikle test.csv dosyası okunarak veri işlemleri bu veri için tekrar yapılır.

full_test_data = read_csv("C:\\Project\\test.csv", show_col_types = FALSE)

full_test_data = full_test_data %>% 
  mutate(Age= ifelse(is.na(Age),mean(Age, trim=0, na.rm=TRUE),Age),
         RoomService = ifelse(is.na(RoomService), 0, RoomService),
         FoodCourt = ifelse(is.na(FoodCourt), 0, FoodCourt),
         ShoppingMall = ifelse(is.na(ShoppingMall), 0, ShoppingMall),
         Spa = ifelse(is.na(Spa), 0, Spa),
         VRDeck = ifelse(is.na(VRDeck), 0, VRDeck)  
)


full_test_data <- full_test_data %>%
  separate(Cabin,c("Deck","Num","Side"),"/") %>%
  mutate(Side = ifelse(Side == "P","Port","Starboard")
        )
predictions = data.frame(PassengerId = full_test_data$PassengerId, Transported = str_to_title(as.logical(as.numeric(predict(random_forest_model, full_test_data))-1)))

Son olarak Kaggle yarışmasına submit etmek için submission.csv dosyası oluşturulur ve yarışmaya gönderilir.

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

Yarışmaya gönderildikten sonra başarım oranı aşağıdaki gibi hesaplanmıştır: