Öğrenci Adı Soyadı: Betül UÇAR
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: 
Ö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.
Ö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>
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>
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,]
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
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
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_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: