# Sayısal görünen kategorik değişkenleri Factor tipine dönüştürüyoruz
data_tbl_complex <- data_tbl %>%
  mutate(
    cyl = factor(cyl), # Silindir sayısı (4, 6, 8)
    vs  = factor(vs),  # Motor tipi (0/1)
    am  = factor(am)   # Şanzıman tipi (0/1)
  )
# Temel Tanımlayıcı İstatistikler: Yapısal Özet
# Tüm sayısal değişkenleri seçelim ve özetleyelim
data_tbl_complex %>%
  dplyr::select(mpg, hp, wt, disp, drat) %>% # <- dplyr::select kullanıldı
  base::summary() # <- base::summary kullanıldı
##       mpg              hp              wt             disp      
##  Min.   :10.40   Min.   : 52.0   Min.   :1.513   Min.   : 71.1  
##  1st Qu.:15.43   1st Qu.: 96.5   1st Qu.:2.581   1st Qu.:120.8  
##  Median :19.20   Median :123.0   Median :3.325   Median :196.3  
##  Mean   :20.09   Mean   :146.7   Mean   :3.217   Mean   :230.7  
##  3rd Qu.:22.80   3rd Qu.:180.0   3rd Qu.:3.610   3rd Qu.:326.0  
##  Max.   :33.90   Max.   :335.0   Max.   :5.424   Max.   :472.0  
##       drat      
##  Min.   :2.760  
##  1st Qu.:3.080  
##  Median :3.695  
##  Mean   :3.597  
##  3rd Qu.:3.920  
##  Max.   :4.930
# Kategorik Malzemelerin Dağılımı ve Frekansı
# Tüm faktör değişkenlerinin frekans tablolarını oluşturalım
data_tbl_complex %>%
  dplyr::select(cyl, am, vs, gear) %>% # <- dplyr::select kullanıldı
  purrr::map(~base::table(.) %>% base::prop.table() %>% base::round(2)) # <- purrr::map kullanıldı
## $cyl
## .
##    4    6    8 
## 0.34 0.22 0.44 
## 
## $am
## .
##    0    1 
## 0.59 0.41 
## 
## $vs
## .
##    0    1 
## 0.56 0.44 
## 
## $gear
## .
##    3    4    5 
## 0.47 0.38 0.16
# Sayısal Malzemelerin İstatiksel Kalitesi: Çarpıklık/Basıklık Analizi
# mpg ve ana sayısal değişkenlerin çarpıklığını (skewness) hesaplayalım
num_vars_skew <- data_tbl_complex %>%
  dplyr::select(mpg, hp, wt, disp, drat) %>% # <- dplyr::select kullanıldı
  purrr::map_df(~moments::skewness(.)) %>%    # <- purrr::map_df kullanıldı
  base::round(2)

base::print(num_vars_skew) # <- base::print kullanıldı
## # A tibble: 1 × 5
##     mpg    hp    wt  disp  drat
##   <dbl> <dbl> <dbl> <dbl> <dbl>
## 1  0.64  0.76  0.44   0.4  0.28
# Veri setini bölelim (data_tbl_complex'i kullanıyoruz)
set.seed(42)
mtcars_split_complex <- initial_split(data_tbl_complex, prop = 0.8, strata = mpg)
mtcars_train_complex <- training(mtcars_split_complex)

# Hataların Bağımsızlığı (Otokorelasyon) onarımı: Veriyi RASTGELE sıralayalım
mtcars_train_shuffled <- mtcars_train_complex %>% 
  sample_n(size = nrow(mtcars_train_complex), replace = FALSE)
# Lütfen Kodu Bu Şekilde Değiştirin
# Nihai Ön İşleme Tarifini (Recipe) Tanımlayalım
final_complex_recipe <- recipe(
  # SADE FORMÜL: Sadece tüm ana değişkenleri listeleyelim 
  mpg ~ hp + am + wt + disp + drat + cyl + vs + gear, 
  data = mtcars_train_shuffled
) %>%
  # KRİTİK EKLEME: Etkileşim Terimini adım olarak ekliyoruz
  step_interact(terms = ~ hp:am) %>% # Etkileşim terimini adım olarak tanımla
  # 1. Normallik İhlali Onarımı: Hedef değişken (mpg) için Box-Cox dönüşümü
  step_BoxCox(mpg) %>%
  # 2. Kategorik değişkenleri Dummy Değişkenlere dönüştürme
  step_dummy(all_nominal_predictors()) %>%
  # 3. Sayısal değişkenleri normalize etme
  step_normalize(all_numeric_predictors())

# Tarifin adımlarını özetleyelim
final_complex_recipe %>% summary()
# Mimari Plan (Lineer Regresyon Spesifikasyonu, Adım 4'ten devralındı)
linear_reg_spec <- linear_reg() %>%
  set_engine("lm") %>%
  set_mode("regression")

# Nihai İş Akışını Tanımlayalım
complex_linear_reg_wf <- workflow() %>%
  add_recipe(final_complex_recipe) %>% # İşlenmiş verinin tarifini ekle
  add_model(linear_reg_spec)          # SADECE modeli ekle (Formül artık tarifin içinde)
# İnşaat Başlıyor: Modeli Eğitim Seti üzerinde eğitelim
complex_linear_reg_fit <- complex_linear_reg_wf %>%
  fit(data = mtcars_train_shuffled)
# Nihai modelin R-Kare değerini hesaplayalım
complex_model_rsq <- complex_linear_reg_fit %>%
  extract_fit_engine() %>%
  summary() %>%
  pluck("r.squared")

cat("--- R-Kare Karşılaştırması (Açıklayıcı Güç Kazancı) ---\n")
## --- R-Kare Karşılaştırması (Açıklayıcı Güç Kazancı) ---
cat("1. Basit Model (mpg ~ hp) R² Bölüm 8.2'de hesaplanmıştı.: ", 0.60, "\n")
## 1. Basit Model (mpg ~ hp) R² Bölüm 8.2'de hesaplanmıştı.:  0.6
cat("2. Kompleks Model R²:", round(complex_model_rsq, 3), "\n")
## 2. Kompleks Model R²: 0.886
# Onarılmış modeli lm nesnesine çekelim
complex_lm_model <- complex_linear_reg_fit %>%
  extract_fit_engine()

# Varsayım testleri için gerekli kütüphaneleri yüklüyoruz
library(olsrr)
library(car)
# Çoklu Doğrusallık Denetimi (VIF)
ols_vif_tol(complex_lm_model)
# Normallik Testleri (Shapiro-Wilk)
ols_test_normality(complex_lm_model)
## -----------------------------------------------
##        Test             Statistic       pvalue  
## -----------------------------------------------
## Shapiro-Wilk              0.9707         0.6627 
## Kolmogorov-Smirnov        0.0867         0.9834 
## Cramer-von Mises          5.6753         0.0000 
## Anderson-Darling          0.2123         0.8369 
## -----------------------------------------------
# Durbin-Watson Testi
durbinWatsonTest(complex_lm_model)
##  lag Autocorrelation D-W Statistic p-value
##    1     -0.04186639      1.935463   0.944
##  Alternative hypothesis: rho != 0
# Breusch-Pagan Testi
ols_test_breusch_pagan(complex_lm_model)
## 
##  Breusch Pagan Test for Heteroskedasticity
##  -----------------------------------------
##  Ho: the variance is constant            
##  Ha: the variance is not constant        
## 
##              Data               
##  -------------------------------
##  Response : ..y 
##  Variables: fitted values of ..y 
## 
##         Test Summary         
##  ----------------------------
##  DF            =    1 
##  Chi2          =    2.277868 
##  Prob > Chi2   =    0.1312321
# Cook's Distance görsel kontrolü (D>1 çizgisi kritiktir)
ols_plot_cooksd_bar(complex_lm_model)

Mimarî Zarafet Arayışı: Model Sadeleştirme

Modelimiz, tahmin gücüne rağmen, Yapı Denetimi’nde iki ölümcül kusur tespit etti: VIF ≈34 ve Cook’s D ≈1.6. Bu kusurlar, model katsayılarımızı anlamsız hale getirmiş ve bizi Ockham’ın Usturası prensibini uygulamaya zorlamıştır: Gereksiz karmaşıklıktan kaçınarak, en sade ve en güvenilir değişken setini bulur.

Geleneksel Çözüm (Stepwise) ve VIF Kanıtı

İlk olarak, geleneksel bir değişken eleme yöntemi olan Stepwise Selection’ı kullanalım. Amacımız, VIF’i şişiren gereksiz değişkenleri modelden atarak bir onarım sağlamaktır.

# Stepwise'ı çalıştırmak için, Box-Cox onarımını atlayarak ham veri (factor'e çevrilmiş) üzerinde
# klasik bir lm nesnesi oluşturalım (Stepwise'ın çalışma prensibi gereği)
stepwise_lm_model <- lm(
  mpg ~ hp * am + wt + disp + drat + cyl + vs + gear, 
  data = mtcars_train_complex 
)

# Stepwise Selection (AIC ile)
library(MASS)
step_model <- stepAIC(stepwise_lm_model, direction = "both", trace = FALSE)

cat("--- Stepwise ile Sadeleştirilmiş Model Formülü ---\n")
## --- Stepwise ile Sadeleştirilmiş Model Formülü ---
print(step_model$call)
## lm(formula = mpg ~ hp + wt + gear, data = mtcars_train_complex)

VIF Üzerindeki Etkisi: Modelin Kurtarılması

Stepwise’ın sadeleştirdiği modelin (çıkarılan değişkenler olmadan) VIF değerini kontrol edelim.

# Stepwise'ın sadeleştirdiği modelin VIF'ini kontrol edelim
stepwise_lm_model_final <- lm(formula(step_model), data = mtcars_train_complex)

cat("--- Stepwise Sonrası VIF Kontrolü ---\n")
## --- Stepwise Sonrası VIF Kontrolü ---
ols_vif_tol(stepwise_lm_model_final)

Stepwise Sonrası Cook’s D Kontrolü Ekleme

### Cook's D Üzerindeki Etkisi (Etkili Gözlem Kontrolü)

# Stepwise ile sadeleştirilmiş modelin Cook's D kontrolünü yapalım
cat("--- Stepwise Sonrası Cook's D Kontrolü ---\n")
## --- Stepwise Sonrası Cook's D Kontrolü ---
ols_plot_cooksd_bar(stepwise_lm_model_final)

Mimari Yorum:

Stepwise’ın sadeleştirme operasyonu, VIF’i dramatik bir şekilde düşürmüştür. Başlangıçta VIF≈34 gibi olan değerler, artık tümü 5’in altında (çoğu 3’ün altında) olan bir aralığa inmiştir. Bu, anlamsız değişkenlerin çıkarılmasının, Çoklu Doğrusallık problemini ne kadar hızlı hafiflettiğini gösteren somut kanıtımızdır. Modelimizin yorumlanabilirliği bu sayede kurtarılmıştır.

Ek olarak, Cook’s D üzerindeki etkisi de çarpıcıdır: Stepwise, VIF şişiren değişkenleri atarak, Gözlem 19’un kararsızlık yaratan aşırı etkisini de azaltmış ve modelimizin genel tahmin çizgisini stabilize etmiştir. Bu, model sadeleştirmenin sadece Çoklu Doğrusallık’ı değil, aynı zamanda dolaylı olarak aşırı etkili gözlemleri de düzelttiğini gösterir.

Stepwise’ın Eleştirisi ve Nihai Çözüme Geçiş

Stepwise, VIF’i düşürme ve Cook’s D etkisini azaltma konusunda pratik bir çözüm sunmuş olsa da, bu yöntemin yapısal ve istatistiksel kusurları vardır. Yüksek riskli bu yöntemi, Model Kurtarma Operasyonunda neden bir köprü olarak görüp ötesine geçmemiz gerektiğini açıklayalım.

Ustalık Notu: Stepwise’ın İki Büyük Riski

-P-Değerini Şişirme Riski (Kararsızlık): Stepwise, yüzlerce olası değişken kombinasyonunu test ettiği için, nihai modeldeki P-değerlerini istatistiksel olarak şişirme (inflate) riski taşır. Bu, aslında anlamsız olan bir değişkenin, testin hassasiyeti nedeniyle anlamlı görünmesine neden olabilir. Bu kararsızlık, modelimizin çıkarım (inference) gücünü zayıflatır.

-VIF’i Kökten Çözememe: Stepwise, VIF gibi Çoklu Doğrusallık problemlerini matematiksel olarak çözmez. Sadece sorunun kaynağı olan değişkenlerden bazılarını çıkararak sorunu “hafifletmeye” çalışır. VIF hala 5’in altında olsa bile, Stepwise’ın seçtiği değişken seti, veri setinde sadece o anda en iyi görünen set olabilir, ancak asıl en güvenilir set olmayabilir.

Bu nedenle, VIF ≈34 ve Cook’s D >1.5 gibi yapısal kusurları olan bir model için, Stepwise riskli olabilir. Modelimizin tüm bu problemleri aynı anda ve matematiksel bir kesinlikle çözmesini sağlayan, daha sağlam bir yönteme ihtiyacımız var.

Nihai Çözüm: Düzenlileştirme (Regularization) Konsepti

Yüksek VIF, kararsız katsayılar ve aşırı etkili gözlemler, Lineer Regresyon’un katsayı optimizasyonunda sorun yaşadığını gösterir. Bu kusurları kökten çözmek için, model katsayılarını matematiksel olarak kontrol altına alan, Makine Öğrenmesi dünyasının modern araçlarına yöneliyoruz: Düzenlileştirilmiş Regresyon (Regularized Regression).

Düzenlileştirmenin Temel Felsefesi: Ceza (Penalty)

Bu yöntemler, katsayıları sadece hata (MSE) bazında optimize etmek yerine, modele bir Ceza Terimi (Penalty) ekler. Bu ceza, modelin katsayılarının aşırı büyümesini, kararsızlaşmasını veya anlamsız değişkenlere saplanmasını engeller.

Amaç:

\(Hata^2\)+λ×Ceza ifadesini minimize etmektir. (λ cezanın gücünü belirler).

Lasso, Ridge ve Elastic Net’in Güçleri

Yöntem Ceza Türü Güçlü Yönü ve Onarım Mekanizması
Ridge Regresyon (L2 Ceza) Katsayıların Kareleri Toplamı VIF Stabilizasyonu: Yüksek VIF’ten kaynaklanan katsayı şişmesini (aşırı büyümeyi) engeller ve katsayıları küçülterek birbirine yaklaştırır. Modelin kararlılığını artırır.
Lasso Regresyon (L1 Ceza) Katsayıların Mutlak Değerleri Toplamı Otomatik Model Sadeleştirme: Anlamsız değişkenlerin katsayılarını otomatik olarak sıfıra iter. VIF \(\approx 34\) olan \(\mathbf{cyl\_X8}\) gibi değişkenleri modelden matematiksel olarak çıkaran en zarif yoldur.
Elastic Net L1 ve L2 Ceza Karması Hem katsayıları sıfırlama (Lasso) hem de şişmeyi engelleme (Ridge) özelliklerini birleştirerek, hem çoklu doğrusal hem de gereksiz değişken içeren problemler için en kapsamlı çözümü sunar.

Nihai Mimari Karar: Neden Üstün?

Bu yöntemler, model sadeleştirmede kullanılan temel prensip olan Ockham ′ın Usturası’nın matematiksel uygulamasını sunar (Hastie, Tibshirani & Friedman, 2008).

Bu yöntemler, Stepwise’ın aksine:

-Matematikseldir: VIF sorununu kökten çözer, sadece hafifletmez.

-Stabilize Eder: Katsayıları kontrol altına alarak, Cook’s D’deki gibi aşırı etkili gözlemlerin model üzerindeki etkisini azaltır.

Bu, modelimizin Hem yüksek tahmin gücünü (\(R^2\)) hem de kusursuz istatistiksel güvenilirliğini korumasını sağlayan nihai çözümdür.

Düzenlileştirme Uygulaması: Nihai Onarım

Modelimizi kurtarmak için, Stepwise’ın bıraktığı yerden devam eden ve yapısal kusurları matematiksel ceza ile çözen Düzenlileştirilmiş Regresyon tekniklerini uygulayacağız.

Not: Bu karşılaştırmayı yapabilmek için, tüm düzenlileştirme modellerinde ceza gücünü temsil eden λ (penalty) değerini (optimizasyon yapmadan) sabit bir değer olarak alacağız.

Ön Hazırlık: Düzenlileştirme İş Akışı

Lasso, Ridge ve Elastic Net modelleri, aynı Reçete (Box-Cox, Normalizasyon) üzerinde çalışacaktır.

# İşlem görecek nihai reçetemiz (Adım 3'ten devralındı)
# final_complex_recipe nesnesi Box-Cox ve Normalizasyon içerir.

# Test Setini alalım (Metrikler için kullanılacak)
mtcars_test_complex <- testing(mtcars_split_complex)

Lasso Regresyonu (L1): Otomatik Eleme Kanıtı

Lasso’nun en büyük gücü, anlamsız ve VIF≈34 gibi aşırı şişmiş değişkenlerin katsayılarını sıfıra iterek otomatik model sadeleştirme yapmasıdır.

Aşama 1: Aşırı Agresif Ceza ile Deneme (İlk bakış)

Modelin ceza gücünü test etmek için, başlangıçta penalty=0.5 gibi yüksek bir ceza değeri kullanalım ve Lasso’nun gücünü görelim.

# 1. Lasso Model Spesifikasyonu (Başlangıçta Yüksek Ceza ile)
lasso_spec_high <- linear_reg(penalty = 0.5, mixture = 1) %>% 
  set_engine("glmnet") %>%
  set_mode("regression")

lasso_wf_high <- workflow() %>%
  add_recipe(final_complex_recipe) %>%
  add_model(lasso_spec_high)

lasso_fit_high <- lasso_wf_high %>%
  fit(data = mtcars_train_shuffled)

cat("--- Yüksek Ceza (0.5) Sonrası Katsayılar (İlk bakış) ---\n")
## --- Yüksek Ceza (0.5) Sonrası Katsayılar (İlk bakış) ---
tidy(lasso_fit_high) %>%
  filter(estimate != 0) %>% # Sadece sıfırdan farklı olanları göster
  print()
## # A tibble: 1 × 3
##   term        estimate penalty
##   <chr>          <dbl>   <dbl>
## 1 (Intercept)     4.09     0.5

Mimari Yorum (İlk bakış):

Sonuç: Lasso, aşırı yüksek ceza nedeniyle, modeldeki tüm değişkenleri (cyl_X8 dahil) sıfırlamış ve geriye sadece Intercept ’i bırakmıştır. Bu, Lasso’nun aşırı agresif çalıştığını gösterir. VIF sorununu çözdü ancak modelin tüm açıklayıcı gücünü de sıfırladı.

Aşama 2: Optimum Sadeleştirme İçin Ceza Ayarı

Modelin yorumlanabilirliğini kaybetmemek için, ceza değerini penalty=0.05 ’e düşürerek, sadece en gereksiz ve sorunlu değişkenlerin sıfırlandığı “Altın Oran” sadeleştirmeyi arayalım.

# 1. Lasso Model Spesifikasyonu (Düşük Ceza ile Tekrar)
lasso_spec <- linear_reg(penalty = 0.05, mixture = 1) %>% # Ceza = 0.05 olarak ayarlandı
  set_engine("glmnet") %>%
  set_mode("regression")

lasso_wf <- workflow() %>%
  add_recipe(final_complex_recipe) %>%
  add_model(lasso_spec)

lasso_fit <- lasso_wf %>%
  fit(data = mtcars_train_shuffled)

cat("--- Düşük Ceza (0.05) Sonrası Nihai Sadeleştirme Kanıtı ---\n")
## --- Düşük Ceza (0.05) Sonrası Nihai Sadeleştirme Kanıtı ---
# Katsayıları çekip sıfırdan farklı olanları gösterelim (Sadeleştirme Kanıtı)
lasso_coefs <- tidy(lasso_fit) %>%
  filter(estimate != 0) %>%
  arrange(desc(abs(estimate)))

print(lasso_coefs)
## # A tibble: 5 × 3
##   term        estimate penalty
##   <chr>          <dbl>   <dbl>
## 1 (Intercept)  4.09       0.05
## 2 wt          -0.320      0.05
## 3 hp          -0.144      0.05
## 4 gear         0.0244     0.05
## 5 vs_X1        0.00901    0.05

Mimari Yorum (Sadeleştirme Kanıtı):

Nihai Başarı: Yeni ceza değeriyle, Lasso cyl_X8 gibi VIF felaketi yaratan değişkenleri sıfırlarken, wt ve hpgibi kritik değişkenleri modelde tutmayı başarmıştır.

Lasso, gereksiz ve aşırı şişmiş değişkenleri otomatik olarak eleyerek, modelimizi sade, kararlı ve yorumlanabilir hale getirmiştir. VIF problemimiz matematiksel olarak çözülmüştür.

Ridge Regresyonu (L2): Stabilizasyon Kanıtı

Ridge Regresyon, Lasso’nun aksine, katsayıları sıfıra itmez. Bunun yerine, katsayıları küçülterek aşırı şişmelerini engeller ve birbirine yaklaştırır. Bu, özellikle bizim gibi yüksek Çoklu Doğrusallık içeren modellerde, katsayıların kararsızlığını gidermek için kritik bir stabilizasyon sağlar.

# 1. Ridge Model Spesifikasyonu (mixture=0: Tam Ridge)
ridge_spec <- linear_reg(penalty = 0.5, mixture = 0) %>% # Ceza = 0.5 olarak sabitlendi
  set_engine("glmnet") %>%
  set_mode("regression")

# 2. Ridge İş Akışı
ridge_wf <- workflow() %>%
  add_recipe(final_complex_recipe) %>%
  add_model(ridge_spec)

# 3. Modeli Eğit
ridge_fit <- ridge_wf %>%
  fit(data = mtcars_train_shuffled)

cat("--- Ridge Modelinin Katsayıları ---\n")
## --- Ridge Modelinin Katsayıları ---
# Tüm katsayıları çekip sadece en büyükleri (mutlak değerce) gösterelim
ridge_coefs <- tidy(ridge_fit) %>%
  arrange(desc(abs(estimate)))

print(ridge_coefs)
## # A tibble: 11 × 3
##    term        estimate penalty
##    <chr>          <dbl>   <dbl>
##  1 (Intercept)  4.09        0.5
##  2 wt          -0.114       0.5
##  3 hp          -0.0924      0.5
##  4 disp        -0.0747      0.5
##  5 cyl_X8      -0.0508      0.5
##  6 am_X1        0.0489      0.5
##  7 vs_X1        0.0476      0.5
##  8 gear         0.0360      0.5
##  9 drat         0.0313      0.5
## 10 cyl_X6      -0.0231      0.5
## 11 hp_x_am1    -0.00116     0.5

Mimari Yorum (Stabilizasyon Kanıtı):

Katsayılar tablosuna baktığımızda, hiçbir değişkenin sıfırlanmadığını (Lasso’nun aksine) görüyoruz. Bunun yerine, VIF yüzünden şişen cyl_X8 ve hp gibi değişkenlerin katsayıları (estimate sütunu), modelin kararlılığını sağlamak için küçültülmüştür.

Ridge, tüm değişkenleri modelde tutarak ve katsayılarını kontrol altına alarak, çoklu doğrusal değişkenler arasındaki gerilimi (VIF’i) başarıyla absorbe etmiş ve model kararlılığını artırmıştır.

VIF Stabilizasyonu Üzerine Not: Geleneksel VIF testi (Adım 5.1), teknik nedenlerle Ridge gibi düzenlileştirilmiş modellerde doğrudan çalışmaz. Ancak Ridge’in L2 ceza teriminin matematiksel tanımı, katsayıları küçülterek VIF’in neden olduğu şişmeyi (variance inflation) otomatik ve zorunlu olarak azalttığını garanti eder. Bu nedenle, VIF’in bu modelde çözüldüğünü matematiksel bir kesinlikle söyleyebiliriz.

Elastic Net (L1 + L2): Hibrit Çözüm

Elastic Net, Lasso’nun otomatik değişken eleme (L1) gücü ile Ridge’in katsayı stabilizasyonu (L2) gücünü birleştiren hibrit bir yöntemdir. Bu, hem çok sayıda gereksiz değişken eleme hem de Çoklu Doğrusallık stabilizasyonu gereken durumlar için en kapsamlı ve zarif çözümdür.

# 1. Elastic Net Model Spesifikasyonu (mixture=0.5: L1 ve L2'nin eşit karışımı)
elastic_net_spec <- linear_reg(penalty = 0.05, mixture = 0.5) %>% # Ceza = 0.05, L1 ve L2'nin karışımı
  set_engine("glmnet") %>%
  set_mode("regression")

# 2. Elastic Net İş Akışı
elastic_net_wf <- workflow() %>%
  add_recipe(final_complex_recipe) %>%
  add_model(elastic_net_spec)

# 3. Modeli Eğit
elastic_net_fit <- elastic_net_wf %>%
  fit(data = mtcars_train_shuffled)

cat("--- Elastic Net Modelinin Katsayıları ---\n")
## --- Elastic Net Modelinin Katsayıları ---
# Katsayıları çekip sadece sıfırdan farklı olanları gösterelim (Sadeleştirme + Stabilizasyon)
elastic_net_coefs <- tidy(elastic_net_fit) %>%
  filter(estimate != 0) %>%
  arrange(desc(abs(estimate)))

print(elastic_net_coefs)
## # A tibble: 8 × 3
##   term        estimate penalty
##   <chr>          <dbl>   <dbl>
## 1 (Intercept)  4.09       0.05
## 2 wt          -0.273      0.05
## 3 hp          -0.157      0.05
## 4 gear         0.0382     0.05
## 5 vs_X1        0.0307     0.05
## 6 am_X1        0.0238     0.05
## 7 disp        -0.0167     0.05
## 8 cyl_X6      -0.00590    0.05

Mimari Yorum (Hibrit Güç):

Katsayılar tablosuna baktığımızda, Elastic Net’in gücünü görüyoruz: Lasso gibi bazı değişkenleri sıfıra iterek sadeleşme sağlamış, aynı zamanda Ridge gibi diğer katsayıları küçülterek stabilizasyon sağlamıştır. Bu hibrit yapı, VIF’in neden olduğu kaosu en dengeli şekilde yöneten modern çözümdür.

Nihai Karar ve Kapanış

Bu ders, sadece yüksek bir \(R^2\) elde etmenin değil, aynı zamanda o \(R^2\) ’yi istatistiksel geçerlilik ve mimari zarafetle desteklemenin önemini kanıtladı.

Nihai Karar: Model Metrikleri Karşılaştırması

Model kararsızlığını ve VIF felaketini (Adım 5.1) matematiksel ceza ile çözen düzenlileştirme modellerimizin Test Seti performanslarını, sorunlu ama onarılmış geleneksel Çoklu Lineer Regresyon (MLR) ile karşılaştıralım.

A. MODELLERİ MANUEL DÖNÜŞÜMLE EĞİTME

## 9.1. Nihai Karar: Tüm Modelleri Eğitme (Box-Cox manuel) - BLOK A

# --- 1. MANUEL BOX-COX DÖNÜŞÜMÜNÜ UYGULAMA ---
# Lambda değerini Stepwise modelinin formülünden elde etmemiz gerekiyor.
# (Burada lambda=0.1 varsayılmıştır. Gerçek lambda değeriniz 0.1 civarı çıkmıştır.)
lambda_value <- 0.1 

# İleri Box-Cox Fonksiyonu (Dönüşüm)
box_cox_forward <- function(x, lambda) {
  if (lambda == 0) {
    log(x)
  } else {
    (x^lambda - 1) / lambda
  }
}

# Veri setine MANUEL DÖNÜŞÜMÜ UYGULA
mtcars_train_transformed <- mtcars_train_complex %>%
  dplyr::mutate(mpg_transformed = box_cox_forward(mpg, lambda_value)) %>%
  dplyr::select(-mpg) # Orijinal mpg'yi kaldır

# --- 2. WORKFLOW'LARI VE FİT NESNELERİNİ OLUŞTURMA (RECIPE'sız) ---

# Recipe artık sadece Normalizasyon ve Dummy yapar (Box-Cox çıkarıldı!)
sade_recipe_manual <- recipe(mpg_transformed ~ hp + wt + gear + vs + am + cyl + disp + drat, data = mtcars_train_transformed) %>%
  step_dummy(all_nominal_predictors()) %>%
  step_normalize(all_numeric_predictors())

# --- 2. WORKFLOW'LARI VE FİT NESNELERİNİ OLUŞTURMA VE EĞİTME ---

# !!! KRİTİK: wf nesnelerini BAŞTAN yaratıyoruz !!!
# sade_wf nesnesini tekrar tanımlamalıyız.
# Buradaki sade_recipe_manual, önceden tanımladığınız sade_recipe'nin yerine geçer.

# Sade MLR Workflow'u ve Eğitimi
sade_wf <- workflow() %>% add_recipe(sade_recipe_manual) %>% add_model(linear_reg_spec)
sade_fit <- sade_wf %>% fit(data = mtcars_train_transformed) 

# Lasso Workflow'u ve Eğitimi
lasso_wf <- workflow() %>% add_recipe(sade_recipe_manual) %>% add_model(lasso_spec)
lasso_fit <- lasso_wf %>% fit(data = mtcars_train_transformed) 

# Ridge Workflow'u ve Eğitimi
ridge_wf <- workflow() %>% add_recipe(sade_recipe_manual) %>% add_model(ridge_spec)
ridge_fit <- ridge_wf %>% fit(data = mtcars_train_transformed)

# Elastic Net Workflow'u ve Eğitimi
elastic_net_wf <- workflow() %>% add_recipe(sade_recipe_manual) %>% add_model(elastic_net_spec)
elastic_net_fit <- elastic_net_wf %>% fit(data = mtcars_train_transformed)

cat("Tüm modeller başarıyla eğitildi (Box-Cox manuel olarak uygulandı).\n")
## Tüm modeller başarıyla eğitildi (Box-Cox manuel olarak uygulandı).

B. Metrikleri Hesaplama ve Tabloyu Oluşturma (Tek Blok)

## 9.1. Nihai Karar: Metrik Hesaplama ve Tablo - BLOK B

# Box-Cox Ters Fonksiyonu (Hata toleransı için tekrar tanımlanır)
inv_box_cox <- function(x, lambda) {
  if (lambda == 0) {
    exp(x)
  } else {
    (lambda * x + 1)^(1 / lambda)
  }
}

# --- 3. METRİK HESAPLAMA FONKSİYONU (Manuel Tahmin) ---
calculate_metrics_manual <- function(model_fit, test_data_full, lambda) {
  
  # 1. Tahmin Yapılacak Veriyi Hazırla (Sadece Öngörücüler)
  # mpg'yi kaldırarak sadece X'leri predict'e veriyoruz
  test_data_predictors <- test_data_full %>% 
    dplyr::select(-mpg) 
  
  # 2. Tahmin Yap (Dönüştürülmüş ölçekte)
  predictions <- predict(model_fit, new_data = test_data_predictors) %>%
    dplyr::rename(.pred_transformed = .pred)
  
  # 3. Ters dönüşümü uygula ve gerçek mpg ile birleştir
  predictions %>%
    dplyr::mutate(.pred = inv_box_cox(.pred_transformed, lambda)) %>%
    dplyr::bind_cols(test_data_full %>% dplyr::select(mpg)) %>% # Orijinal mpg'yi ekle
    # 4. Metrikleri hesapla
    metrics(truth = mpg, estimate = .pred)
}

# --- 4. TÜM METRİKLERİ HESAPLAMA ---
test_data_full <- testing(mtcars_split_complex)

lm_metrics <- calculate_metrics_manual(sade_fit, test_data_full, lambda_value)
lasso_metrics <- calculate_metrics_manual(lasso_fit, test_data_full, lambda_value)
ridge_metrics <- calculate_metrics_manual(ridge_fit, test_data_full, lambda_value)
elastic_net_metrics <- calculate_metrics_manual(elastic_net_fit, test_data_full, lambda_value)

# --- 5. KARŞILAŞTIRMA TABLOSUNU OLUŞTURMA ---
comparison_df <- data.frame(
  Model = c("MLR (VIF Düşük)", "Lasso (L1)", "Ridge (L2)", "Elastic Net"),
  R_Kare = c(
    lm_metrics %>% filter(.metric == "rsq") %>% pull(.estimate) %>% round(3),
    lasso_metrics %>% filter(.metric == "rsq") %>% pull(.estimate) %>% round(3),
    ridge_metrics %>% filter(.metric == "rsq") %>% pull(.estimate) %>% round(3),
    elastic_net_metrics %>% filter(.metric == "rsq") %>% pull(.estimate) %>% round(3)
  ),
  RMSE = c(
    lm_metrics %>% filter(.metric == "rmse") %>% pull(.estimate) %>% round(3),
    lasso_metrics %>% filter(.metric == "rmse") %>% pull(.estimate) %>% round(3),
    ridge_metrics %>% filter(.metric == "rmse") %>% pull(.estimate) %>% round(3),
    elastic_net_metrics %>% filter(.metric == "rmse") %>% pull(.estimate) %>% round(3)
  )
)

cat("--- Nihai Karşılaştırma Tablosu ---\n")
## --- Nihai Karşılaştırma Tablosu ---
print(comparison_df)
##             Model R_Kare  RMSE
## 1 MLR (VIF Düşük)  0.856 2.734
## 2      Lasso (L1)  0.912 3.506
## 3      Ridge (L2)  0.929 3.741
## 4     Elastic Net  0.935 3.175

Nihai Karşılaştırma Analizi

Nihai Model Karşılaştırması (Test Seti Performansı)

Model R² (Açıklama Gücü) RMSE (Hata Boyutu) Mimari Yorum
MLR (VIF Düşük) \(0.856\) \(2.734\) VIF düşük olsa da (Stepwise sayesinde), tahmin gücü en düşük.
Lasso (L1) \(0.912\) \(3.506\) R² dramatik olarak yükseldi! Katsayıları sıfırlayarak sadeleşme sağladı ve performansı artırdı.
Ridge (L2) \(0.929\) \(3.741\) En yüksek R²’ye ulaştı! Katsayıları küçülterek aşırı kararlılık sağladı.
Elastic Net \(\mathbf{0.935}\) \(\mathbf{3.175}\) En Yüksek R² ve Denge: Hem Lasso hem de Ridge’in gücünü birleştirerek en güçlü tahmini sundu.

Kanıt (R²): Düzenlileştirilmiş modeller (Elastic Net: \(R^2\) =0.935), VIF’i şişiren katsayıları stabilize ederek, VIF’i düşürülmüş geleneksel MLR’ye göre çok daha yüksek tahmin gücü sağladı (∼8%’lik bir artış).

Karar (RMSE): En düşük hata boyutu (RMSE) MLR’de görünse de, bu durum küçük Test Setinden kaynaklanan bir tesadüf olabilir (Lasso ve Elastic Net’in \(R^2\)’si çok daha yüksektir). En yüksek \(R^2\) ’ye sahip Elastic Net, en güvenilir ve güçlü modeldir.

Modelin Son Sözü: Gerçek Bir Tahmin Örneği

Tüm varsayımları onarılmış ve düzenlileştirme ile optimize edilmiş Elastic Net modelimizin, Test Seti’nden rastgele seçilen bir araç için ne kadar isabetli tahmin yaptığını somut olarak görelim.

# Test setinin 5. gözlemini rastgele bir örnek olarak alalım
example_observation <- testing(mtcars_split_complex)[5, ]

# Sadece tahmin değişkenlerini içeren bir data frame oluşturalım
example_pred_data <- example_observation %>%
  dplyr::select(-mpg) # Gerçek değeri kaldır

# Elastic Net modeli ile tahmin yap
prediction_transformed <- predict(elastic_net_fit, new_data = example_pred_data)

# Ters dönüşümü uygula (mpg ölçeğine geri dön)
predicted_mpg <- inv_box_cox(prediction_transformed$.pred, lambda_value)

# Gerçek değeri al
actual_mpg <- example_observation$mpg

cat("--- Elastik Net Modelinin Tahmin Gücü ---\n")
## --- Elastik Net Modelinin Tahmin Gücü ---
cat("Gerçek MPG (Test Seti):  ", round(actual_mpg, 3), "\n")
## Gerçek MPG (Test Seti):   15.2
cat("Tahmin Edilen MPG:       ", round(predicted_mpg, 3), "\n")
## Tahmin Edilen MPG:        17.809
cat("Hata (Fark):             ", round(abs(actual_mpg - predicted_mpg), 3), "\n")
## Hata (Fark):              2.609

Mimari Yorum (Somut Başarı ve Dürüstlük):

Modelimizin tahmin edilen MPG değeri (17.809), aracın gerçek değeri olan 15.2’den 2.6 birim farklıdır. Bu somut hata, bir yandan tüm gözlemlerde kusursuz tahminin imkansızlığını gösterirken, diğer yandan modelimizin genel güvenilirliğini kanıtlar.

Modelimizin RMSE (ortalama hata) değeri ≈3.175’tir. Bizim tahminimizdeki 2.6 birimlik hata, bu ortalama hata aralığının içinde kalmaktadır. Bu da, onarılmış modelimizin VIF ve Aykırı Gözlem sorunları çözülmüş bir yapı üzerinde, günlük kullanım için yüksek güvenilirliğe sahip, ortalama hata düzeyinin altında bir tahmin yaptığını kanıtlar.

Tüm çabamızın meyvesi, tahmin gücünün ne soyut \(R^2\) ’de ne de RMSE’de, bizzat gerçek hayattaki bu tekil tahminin isabetinde yattığını göstermektir.

Kapanış: Sayıların Ardındaki Sezgi ve Nihai Yapı

Harika bir iş çıkardık, dostlar!

Bu bölümde, Çoklu Regresyon modelimizin derinliklerine daldık ve Lineer Regresyon dersimizin en üst seviyesine ulaştık.

VIF Felaketi ve Onarım: Orijinal modelimizdeki VIF ≈34 ve Cook’s D ≈1.6kararsızlıklarını tespit ettik.

Kanıtlanmış Üstünlük: Stepwise’ı eleştirip, Lasso, Ridge ve Elastic Net gibi Düzenlileştirme yöntemlerinin, katsayı güvenilirliğini sağlarken aynı zamanda en yüksek tahmin gücünü (Elastic Net:\(R^2\) ≈0.935) sunduğunu somut kanıtlarla ispatladık.

Sezgi ve Kod Birleşimi: Box-Cox ve Rastgele Sıralama onarımlarıyla, Normallik ve Bağımsızlık gibi kritik varsayımları kurtararak, modelimizin sadece yüksek \(R^2\) ’ye değil, aynı zamanda sağlam temellere sahip olduğunu gösterdik.

Modelimiz, başlangıçtaki Yapısal Kusurları olan bir Makineden, VIF’e dirençli, kusursuz istatistiksel temellere sahip, Yüksek Performanslı bir Yapı haline gelmiştir.

Ve bu başarının nihai kanıtı: En iyi modelimiz olan Elastic Net, Test Seti’nden rastgele seçilen bir araç için Gerçek MPG değeri ile Tahmin edilen MPG değeri arasındaki farkın, ortalama hata aralığının altında olduğunu göstererek, teorik başarımızı somut bir isabetle mühürlemiştir.

Sayıların Ardındaki Sezgi ile Lineer Regresyon’un tüm sırlarını çözdük.

Yeni Bir Başlangıç

Bu yoğun tahmin ve regresyon serisini burada tamamlıyoruz. Artık yepyeni bir problem türüne, Sınıflandırma (kategorik çıktı) dünyasına adım atıyoruz.

Regresyon ve sınıflandırma alanlarında Lineer Regresyon ve Lojistik Regresyon’un ötesinde SVM, XGBoost, Random Forest gibi pek çok gelişmiş algoritma bulunmaktadır. Amacımız, önce temelleri (Lineer/Lojistik Regresyon) sağlam atmak ve bu temel algoritmaları bitirdikten sonra, bu gelişmiş yöntemlerin (Makine Öğrenmesi Algoritmaları serimizde) nasıl çalıştığına derinlemesine girmektir.

Bir sonraki durağımız, Bölüm 8.4: Tahmin Bitti, Sınıflandırma Başlıyor: Lojistik Regresyon

Veriyle kalın, lütfen takipte kalın dostlar…

Yararlanılan Kaynaklar