1. Giriş ve Amaç

Bu projede Spaceship Titanic veri seti üzerinde çalışıyorum. Amaç, uzay gemisindeki yolcuların alternatif bir boyuta nakledilip nakledilmediğini tahmin etmek.

Bu analiz için tidymodels ekosistemine ait araçları kullanarak üç farklı makine öğrenmesi modeli kuracağım. Bunlar lojistik regresyon, Random Forest ve XGBoost’tur.

Proje akışı şu şekildedir: Train verisini %75 (deneme_train) ve %25 (deneme_test) olarak ayırıp modelleri değerlendireceğim. En iyi modeli seçtikten sonra tüm train verisiyle yeniden eğitip Kaggle’a submission yapacağım. Tüm veri ön işleme adımları tidymodels recipe ile yapılacak.


2. Veri Setinin Tanıtımı

library(tidyverse)
library(tidymodels)
library(xgboost)
library(knitr)
library(ranger)
train_raw <- read_csv("train.csv", show_col_types = FALSE)
test_raw <- read_csv("test.csv", show_col_types = FALSE)

Veri setinin yapısına bakalım:

glimpse(train_raw)
## Rows: 8,693
## Columns: 14
## $ PassengerId  <chr> "0001_01", "0002_01", "0003_01", "0003_02", "0004_01", "0…
## $ HomePlanet   <chr> "Europa", "Earth", "Europa", "Europa", "Earth", "Earth", …
## $ CryoSleep    <lgl> FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, FA…
## $ Cabin        <chr> "B/0/P", "F/0/S", "A/0/S", "A/0/S", "F/1/S", "F/0/P", "F/…
## $ Destination  <chr> "TRAPPIST-1e", "TRAPPIST-1e", "TRAPPIST-1e", "TRAPPIST-1e…
## $ Age          <dbl> 39, 24, 58, 33, 16, 44, 26, 28, 35, 14, 34, 45, 32, 48, 2…
## $ VIP          <lgl> FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FA…
## $ RoomService  <dbl> 0, 109, 43, 0, 303, 0, 42, 0, 0, 0, 0, 39, 73, 719, 8, 32…
## $ FoodCourt    <dbl> 0, 9, 3576, 1283, 70, 483, 1539, 0, 785, 0, 0, 7295, 0, 1…
## $ ShoppingMall <dbl> 0, 25, 0, 371, 151, 0, 3, 0, 17, 0, NA, 589, 1123, 65, 12…
## $ Spa          <dbl> 0, 549, 6715, 3329, 565, 291, 0, 0, 216, 0, 0, 110, 0, 0,…
## $ VRDeck       <dbl> 0, 44, 49, 193, 2, 0, 0, NA, 0, 0, 0, 124, 113, 24, 7, 0,…
## $ Name         <chr> "Maham Ofracculy", "Juanna Vines", "Altark Susent", "Sola…
## $ Transported  <lgl> FALSE, TRUE, FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, …
glimpse(test_raw)
## Rows: 4,277
## Columns: 13
## $ PassengerId  <chr> "0013_01", "0018_01", "0019_01", "0021_01", "0023_01", "0…
## $ HomePlanet   <chr> "Earth", "Earth", "Europa", "Europa", "Earth", "Earth", "…
## $ CryoSleep    <lgl> TRUE, FALSE, TRUE, FALSE, FALSE, FALSE, TRUE, TRUE, TRUE,…
## $ Cabin        <chr> "G/3/S", "F/4/S", "C/0/S", "C/1/S", "F/5/S", "F/7/P", "B/…
## $ Destination  <chr> "TRAPPIST-1e", "TRAPPIST-1e", "55 Cancri e", "TRAPPIST-1e…
## $ Age          <dbl> 27, 19, 31, 38, 20, 31, 21, 20, 23, 24, 19, 45, 44, 46, 2…
## $ VIP          <lgl> FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, F…
## $ RoomService  <dbl> 0, 0, 0, 0, 10, 0, 0, 0, 0, 0, 339, 932, 0, 0, 0, 0, 2, 0…
## $ FoodCourt    <dbl> 0, 9, 0, 6652, 0, 1615, NA, 0, 0, 639, 3, 74, 1561, 0, 0,…
## $ ShoppingMall <dbl> 0, 0, 0, 0, 635, 263, 0, 0, 0, 0, 136, NA, 0, 0, 0, 0, 25…
## $ Spa          <dbl> 0, 2823, 0, 181, 0, 113, 0, 0, 0, 0, 237, 7, 14, 0, 1687,…
## $ VRDeck       <dbl> 0, 0, 0, 585, 0, 60, 0, 0, 0, 0, 0, 1010, 224, 0, 92, NA,…
## $ Name         <chr> "Nelly Carsoning", "Lerome Peckers", "Sabih Unhearfus", "…

Train veri seti 8,693 gözlem ve 14 değişken içermektedir. Test veri seti ise 4,277 gözlem ve 13 değişken içermektedir (Transported yok). Hedef değişken Transported’dır (True/False - yolcu nakledildi mi?).

Değişken Açıklamaları:

Değişken Açıklama Tür
PassengerId Yolcu kimlik numarası Karakter
HomePlanet Kalkış gezegeni (Europa, Earth, Mars) Kategorik
CryoSleep Dondurulmuş uyku modunda mı? Boolean
Cabin Kabin numarası (Deck/Num/Side) Karakter
Destination Varış noktası Kategorik
Age Yaş Sayısal
VIP VIP servisi var mı? Boolean
RoomService Oda servisi harcaması Sayısal
FoodCourt Yemek alanı harcaması Sayısal
ShoppingMall Alışveriş harcaması Sayısal
Spa Spa harcaması Sayısal
VRDeck VR harcaması Sayısal
Name Yolcu adı Karakter
Transported Nakledildi mi? (Hedef) Boolean

3. Veri Ön İşleme ve NA Analizi

3.1 Eksik Değer Analizi (Ham Veri)

train_na <- tibble(
  Degisken = names(train_raw),
  Eksik_Deger = colSums(is.na(train_raw)),
  Eksik_Oran = round(colSums(is.na(train_raw)) / nrow(train_raw) * 100, 2)
) %>%
  filter(Eksik_Deger > 0) %>%
  arrange(desc(Eksik_Deger))

kable(train_na, caption = "Train Verisinde Eksik Değerler")
Train Verisinde Eksik Değerler
Degisken Eksik_Deger Eksik_Oran
CryoSleep 217 2.50
ShoppingMall 208 2.39
VIP 203 2.34
HomePlanet 201 2.31
Name 200 2.30
Cabin 199 2.29
VRDeck 188 2.16
FoodCourt 183 2.11
Spa 183 2.11
Destination 182 2.09
RoomService 181 2.08
Age 179 2.06

Görüldüğü gibi birçok değişkende eksik değer var. Bu eksik değerleri tidymodels recipe ile dolduracağız.

3.2 Veri Hazırlığı (Recipe Öncesi)

Cabin değişkenini ayırıyoruz (recipe’de step_mutate yok, bu yüzden önceden):

# Hedef değişkeni faktöre çevir
train_raw <- train_raw %>%
  mutate(Transported = factor(ifelse(Transported, "Yes", "No"), 
                               levels = c("No", "Yes")))

# Cabin'i ayır (Deck/Num/Side)
train_raw <- train_raw %>%
  separate(Cabin, into = c("Deck", "CabinNum", "Side"), 
           sep = "/", remove = FALSE, fill = "right") %>%
  mutate(
    Deck = ifelse(Deck %in% c("A", "D", "T"), "Other", Deck),
    Deck = as.factor(Deck),
    CabinNum = as.numeric(CabinNum),
    Side = as.factor(Side),
    # Diğer kategorik değişkenler de factor olsun
    HomePlanet = as.factor(HomePlanet),
    CryoSleep = as.factor(CryoSleep),
    Destination = as.factor(Destination),
    VIP = as.factor(VIP)
  )

test_raw <- test_raw %>%
  separate(Cabin, into = c("Deck", "CabinNum", "Side"), 
           sep = "/", remove = FALSE, fill = "right") %>%
  mutate(
    Deck = ifelse(Deck %in% c("A", "D", "T"), "Other", Deck),
    Deck = as.factor(Deck),
    CabinNum = as.numeric(CabinNum),
    Side = as.factor(Side),
    HomePlanet = as.factor(HomePlanet),
    CryoSleep = as.factor(CryoSleep),
    Destination = as.factor(Destination),
    VIP = as.factor(VIP)
  )

4. Train–Test Ayrımı

set.seed(123)
data_split <- initial_split(train_raw, prop = 0.75, strata = Transported)
deneme_train <- training(data_split)
deneme_test <- testing(data_split)

tibble(
  Veri_Seti = c("Deneme Train", "Deneme Test"),
  Satir_Sayisi = c(nrow(deneme_train), nrow(deneme_test)),
  Oran = c("75%", "25%")
) %>% kable(caption = "Train-Test Ayrımı")
Train-Test Ayrımı
Veri_Seti Satir_Sayisi Oran
Deneme Train 6519 75%
Deneme Test 2174 25%

Stratifikasyon: Transported değişkenine göre stratified sampling yapıldı, böylece her iki sette de sınıf dağılımı korundu.


5. Recipe (Tüm Ön İşleme Burada)

Tüm veri ön işleme adımlarını tidymodels recipe ile yapıyoruz:

model_rec <- recipe(Transported ~ ., data = deneme_train) %>%
  # Gereksiz kolonları çıkar
  step_rm(PassengerId, Name, Cabin) %>%
  
  # Character kolonları factor'e çevir (XGBoost için kritik!)
  step_string2factor(all_nominal_predictors()) %>%
  
  # Eksik değerleri doldur
  step_impute_mode(all_nominal_predictors()) %>%
  step_impute_median(all_numeric_predictors()) %>%
  
  # Kategorik değişkenleri dummy'e çevir
  step_dummy(all_nominal_predictors()) %>%
  
  # Sıfır varyanslı kolonları çıkar (dummy sonrası)
  step_zv(all_predictors())

# Recipe'yi hazırla ve veriyi dönüştür
prep_rec <- prep(model_rec)
train_baked <- bake(prep_rec, new_data = NULL)
test_baked <- bake(prep_rec, new_data = deneme_test)

5.1 Eksik Değer Kontrolü (Recipe Sonrası)

tibble(
  Veri_Seti = c("Deneme Train (recipe sonrası)", "Deneme Test (recipe sonrası)"),
  Toplam_NA = c(sum(is.na(train_baked)), sum(is.na(test_baked))),
  Satir_Sayisi = c(nrow(train_baked), nrow(test_baked)),
  Sutun_Sayisi = c(ncol(train_baked), ncol(test_baked))
) %>% kable(caption = "Recipe Sonrası Veri Durumu")
Recipe Sonrası Veri Durumu
Veri_Seti Toplam_NA Satir_Sayisi Sutun_Sayisi
Deneme Train (recipe sonrası) 0 6519 20
Deneme Test (recipe sonrası) 0 2174 20

Recipe sonrası hiçbir eksik değer kalmadı.


6. Modeller ve Teorik Açıklamalar

Bu bölümde üç farklı model kuracağım ve her birinin teorik temelini açıklayacağım.

6.1 Lojistik Regresyon

Teorik Açıklama

Lojistik regresyon, binary sınıflandırma problemleri için kullanılan parametrik bir istatistiksel yöntemdir. Doğrusal regresyonun bir uzantısıdır ancak çıktıyı [0,1] aralığına sıkıştırmak için lojistik (sigmoid) fonksiyonu kullanır:

\[P(Y=1|X) = \frac{1}{1 + e^{-(\beta_0 + \beta_1X_1 + ... + \beta_pX_p)}}\]

Lojistik regresyon yorumlanabilir bir yöntemdir ve katsayılar odds ratio’ya çevrilebilir. Hızlı eğitim sağlar ve düşük varyans nedeniyle overfitting riski azdır. Baseline model olarak kullanılması uygundur. Ancak doğrusal olmayan ilişkileri yakalayamaz ve feature engineering gerektirir. Kompleks etkileşimleri modellemekte de yetersizdir.

logistic_spec <- logistic_reg() %>%
  set_engine("glm") %>%
  set_mode("classification")

logistic_wf <- workflow() %>%
  add_recipe(model_rec) %>%
  add_model(logistic_spec)

logistic_fit <- fit(logistic_wf, deneme_train)

6.2 Random Forest

Teorik Açıklama

Random Forest, birden fazla karar ağacının tahminlerini birleştiren bir ensemble (topluluk öğrenmesi) yöntemidir. Her ağaç bootstrap sampling ile rastgele seçilmiş örnekler üzerinde eğitilir. Her düğümde rastgele seçilmiş özellikler arasından en iyisi kullanılır ve final tahmin tüm ağaçların oylamasıyla yapılır (classification için majority voting).

Random Forest overfitting’e karşı dayanıklıdır (bagging sayesinde) ve non-linear ilişkileri yakalayabilir. Feature importance sağlar ve hiperparametre ayarına az duyarlıdır. Ancak yorumlanabilirliği düşüktür, eğitim süresi uzun olabilir ve büyük veri setlerinde memory-intensive olabilir.

Modelde mtry = 5 (her split’te rastgele seçilen değişken sayısı), trees = 500 (toplam ağaç sayısı) ve min_n = 10 (terminal düğümdeki minimum gözlem sayısı) hiperparametreleri kullanılmıştır.

rf_spec <- rand_forest(
  mtry = 5,
  trees = 500,
  min_n = 10
) %>%
  set_engine("ranger") %>%
  set_mode("classification")

rf_wf <- workflow() %>%
  add_recipe(model_rec) %>%
  add_model(rf_spec)

rf_fit <- fit(rf_wf, deneme_train)

6.3 XGBoost

Teorik Açıklama

XGBoost (Extreme Gradient Boosting), gradient boosting algoritmasının optimize edilmiş bir implementasyonudur. Random Forest’tan farklı olarak ağaçlar sıralı olarak eklenir (parallel değil). Her yeni ağaç, önceki ağaçların hatalarını düzeltmeye odaklanır. Gradient descent ile loss fonksiyonu minimize edilir ve regularization (L1/L2) ile overfitting önlenir.

XGBoost Kaggle yarışmalarında en başarılı algoritmalardan biridir. Yüksek prediction accuracy sağlar ve missing value handling built-in özelliğine sahiptir. Regularization ile overfitting kontrolü yapar. Ancak hiperparametre tuning zahmetlidir, sequential training nedeniyle paralelize edilemez ve yorumlanabilirliği düşüktür.

Modelde trees = 500 (boosting iterasyon sayısı), tree_depth = 6 (maksimum ağaç derinliği), min_n = 10 (split için minimum gözlem) ve learn_rate = 0.05 (learning rate/shrinkage) hiperparametreleri kullanılmıştır.

xgb_spec <- boost_tree(
  trees = 500,
  tree_depth = 6,
  min_n = 10,
  learn_rate = 0.05
) %>%
  set_engine("xgboost") %>%
  set_mode("classification")

xgb_wf <- workflow() %>%
  add_recipe(model_rec) %>%
  add_model(xgb_spec)

xgb_fit <- fit(xgb_wf, deneme_train)

7. Model Değerlendirme

Şimdi üç modeli de deneme_test üzerinde değerlendireceğim.

logistic_pred <- predict(logistic_fit, deneme_test) %>%
  bind_cols(predict(logistic_fit, deneme_test, type = "prob")) %>%
  bind_cols(select(deneme_test, Transported))

rf_pred <- predict(rf_fit, deneme_test) %>%
  bind_cols(predict(rf_fit, deneme_test, type = "prob")) %>%
  bind_cols(select(deneme_test, Transported))

xgb_pred <- predict(xgb_fit, deneme_test) %>%
  bind_cols(predict(xgb_fit, deneme_test, type = "prob")) %>%
  bind_cols(select(deneme_test, Transported))

7.1 Confusion Matrix

cm_logistic <- conf_mat(logistic_pred, truth = Transported, estimate = .pred_class)
cm_rf <- conf_mat(rf_pred, truth = Transported, estimate = .pred_class)
cm_xgb <- conf_mat(xgb_pred, truth = Transported, estimate = .pred_class)

Lojistik Regresyon Confusion Matrix:

cm_logistic
##           Truth
## Prediction  No Yes
##        No  841 194
##        Yes 238 901

Random Forest Confusion Matrix:

cm_rf
##           Truth
## Prediction  No Yes
##        No  856 179
##        Yes 223 916

XGBoost Confusion Matrix:

cm_xgb
##           Truth
## Prediction  No Yes
##        No  874 194
##        Yes 205 901

7.2 Performans Metrikleri

hesapla_metrikler <- function(pred_df, model_adi) {
  tibble(
    Model = model_adi,
    Accuracy = accuracy(pred_df, truth = Transported, estimate = .pred_class)$.estimate,
    Precision = precision(pred_df, truth = Transported, estimate = .pred_class, 
                         event_level = "second")$.estimate,
    Recall = recall(pred_df, truth = Transported, estimate = .pred_class, 
                    event_level = "second")$.estimate,
    F1 = f_meas(pred_df, truth = Transported, estimate = .pred_class, 
                event_level = "second")$.estimate,
    ROC_AUC = roc_auc(pred_df, truth = Transported, .pred_Yes, 
                      event_level = "second")$.estimate
  )
}

metrikler <- bind_rows(
  hesapla_metrikler(logistic_pred, "Lojistik Regresyon"),
  hesapla_metrikler(rf_pred, "Random Forest"),
  hesapla_metrikler(xgb_pred, "XGBoost")
)

kable(metrikler, digits = 4, caption = "Model Performans Karşılaştırması")
Model Performans Karşılaştırması
Model Accuracy Precision Recall F1 ROC_AUC
Lojistik Regresyon 0.8013 0.7910 0.8228 0.8066 0.8864
Random Forest 0.8151 0.8042 0.8365 0.8201 0.9049
XGBoost 0.8165 0.8146 0.8228 0.8187 0.9067

Metrik Açıklamaları:

Metrik Açıklama Formül
Accuracy Doğru tahminlerin toplam gözleme oranı (TP + TN) / (TP + TN + FP + FN)
Precision Pozitif tahmin edilenlerin gerçekten pozitif olma oranı TP / (TP + FP)
Recall Gerçek pozitiflerin yakalanma oranı TP / (TP + FN)
F1 Precision ve Recall’un harmonik ortalaması 2 × (Precision × Recall) / (Precision + Recall)
ROC-AUC Sınıfları ayırma gücü (1’e yakın = daha iyi) ROC eğrisi altındaki alan

7.3 ROC Eğrileri

roc_logistic <- roc_curve(logistic_pred, truth = Transported, .pred_Yes, 
                          event_level = "second") %>%
  mutate(Model = "Lojistik Regresyon")

roc_rf <- roc_curve(rf_pred, truth = Transported, .pred_Yes, 
                    event_level = "second") %>%
  mutate(Model = "Random Forest")

roc_xgb <- roc_curve(xgb_pred, truth = Transported, .pred_Yes, 
                     event_level = "second") %>%
  mutate(Model = "XGBoost")

roc_all <- bind_rows(roc_logistic, roc_rf, roc_xgb)

ggplot(roc_all, aes(x = 1 - specificity, y = sensitivity, color = Model)) +
  geom_line(linewidth = 1.2) +
  geom_abline(linetype = "dashed", color = "gray50") +
  labs(
    title = "ROC Eğrileri Karşılaştırması",
    subtitle = "Yüksek AUC değeri daha iyi model performansını gösterir",
    x = "1 - Specificity (False Positive Rate)",
    y = "Sensitivity (True Positive Rate)"
  ) +
  theme_minimal() +
  theme(
    legend.position = "bottom",
    plot.title = element_text(size = 14, face = "bold"),
    plot.subtitle = element_text(size = 11)
  ) +
  scale_color_brewer(palette = "Set1")


7.4 Model Karşılaştırma Grafiği

metrikler_long <- metrikler %>%
  pivot_longer(cols = -Model, names_to = "Metrik", values_to = "Deger")

ggplot(metrikler_long, aes(x = Metrik, y = Deger, fill = Model)) +
  geom_col(position = "dodge", width = 0.7) +
  geom_text(aes(label = round(Deger, 3)), 
            position = position_dodge(width = 0.7), 
            vjust = -0.5, size = 3) +
  labs(
    title = "Model Performans Karşılaştırması",
    subtitle = "Tüm metrikler için yüksek değer daha iyidir",
    y = "Değer",
    x = "Metrik"
  ) +
  theme_minimal() +
  theme(
    legend.position = "bottom",
    plot.title = element_text(size = 14, face = "bold")
  ) +
  scale_fill_brewer(palette = "Set2") +
  ylim(0, 1.05)


8. Final Modeller ve Kaggle Submission

Şimdi üç modeli de tüm train verisiyle yeniden eğitip gerçek test setinde tahmin yapacağım.

8.1 Tüm Train Verisiyle Model Eğitimi

final_rec <- recipe(Transported ~ ., data = train_raw) %>%
  step_rm(PassengerId, Name, Cabin) %>%
  # Character kolonları factor'e çevir
  step_string2factor(all_nominal_predictors()) %>%
  step_impute_mode(all_nominal_predictors()) %>%
  step_impute_median(all_numeric_predictors()) %>%
  step_dummy(all_nominal_predictors()) %>%
  step_zv(all_predictors())
# Lojistik Regresyon
logistic_wf_final <- workflow() %>%
  add_recipe(final_rec) %>%
  add_model(logistic_spec)
logistic_final <- fit(logistic_wf_final, train_raw)

# Random Forest
rf_wf_final <- workflow() %>%
  add_recipe(final_rec) %>%
  add_model(rf_spec)
rf_final <- fit(rf_wf_final, train_raw)

# XGBoost
xgb_wf_final <- workflow() %>%
  add_recipe(final_rec) %>%
  add_model(xgb_spec)
xgb_final <- fit(xgb_wf_final, train_raw)

Tüm modeller tüm train verisiyle başarıyla eğitildi.


8.2 Test Verisi Tahminleri ve Submission Dosyaları

pred_logistic_final <- predict(logistic_final, test_raw)
pred_rf_final <- predict(rf_final, test_raw)
pred_xgb_final <- predict(xgb_final, test_raw)

# Yes/No -> True/False formatına çevir
convert_pred <- function(pred) {
  ifelse(pred$.pred_class == "Yes", "True", "False")
}

submission_logistic <- tibble(
  PassengerId = test_raw$PassengerId,
  Transported = convert_pred(pred_logistic_final)
)

submission_rf <- tibble(
  PassengerId = test_raw$PassengerId,
  Transported = convert_pred(pred_rf_final)
)

submission_xgb <- tibble(
  PassengerId = test_raw$PassengerId,
  Transported = convert_pred(pred_xgb_final)
)

# Dosyaları kaydet
write_csv(submission_logistic, "submission_logistic.csv")
write_csv(submission_rf, "submission_rf.csv")
write_csv(submission_xgb, "submission_xgb.csv")

Oluşturulan dosyalar:

  • submission_logistic.csv
  • submission_rf.csv
  • submission_xgb.csv

İlk 5 tahmin (Lojistik Regresyon):

head(submission_logistic, 5)
## # A tibble: 5 × 2
##   PassengerId Transported
##   <chr>       <chr>      
## 1 0013_01     True       
## 2 0018_01     False      
## 3 0019_01     True       
## 4 0021_01     True       
## 5 0023_01     True

8.3 Kaggle Submission Sonucu

Aşağıda, model tahminlerinin Kaggle platformuna yüklenmesi sonucunda elde edilen skor yer almaktadır.

Kaggle Sonucu
Kaggle Sonucu

9. Genel Değerlendirme

Bu projede Spaceship Titanic veri seti üzerinde üç farklı sınıflandırma modeli kurdum ve karşılaştırdım:

9.1 Temel Bulgular

Ensemble yöntemler (Random Forest ve XGBoost) genelde lojistik regresyondan daha iyi performans gösterdi. ROC-AUC metriği açısından en yüksek skoru XGBoost elde etti. Accuracy değerleri %79-82 aralığında gerçekleşti.

Veri ön işleme açısından Cabin değişkenini Deck, CabinNum ve Side olarak ayırmak faydalı oldu. Eksik değerler recipe içinde kategorik için mode, sayısal için median ile dolduruldu. Tüm preprocessing tidymodels recipe ile yapıldı.

Değerlendirme metrikleri ile ilgili olarak confusion matrix ile modellerin hata türleri analiz edildi. ROC-AUC modellerin sınıf ayırma gücünü gösterdi ve F1 score precision-recall dengesini değerlendirdi.

9.2 Öğrendiklerim

Tidymodels ekosistemi model kurma ve değerlendirme süreçlerini tutarlı bir şekilde yönetmemi sağladı. Recipe pattern veri ön işleme adımlarını tekrar üretilebilir hale getirdi. Ensemble yöntemler karmaşık ilişkileri yakalamada daha başarılı oldu.