library(ggplot2)

# Kendi Sigmoid fonksiyonumuzu tanımlayalım
sigmoid <- function(z) {
  return(1 / (1 + exp(-z)))
}

# Geniş bir 'z' değeri aralığı oluşturalım
z_values <- seq(-10, 10, length.out = 500)

# Sigmoid fonksiyonunu 'z' değerlerine uygulayalım
prob_values <- sigmoid(z_values)

# Veriyi bir data frame'e dönüştürelim (ggplot2 için en iyisi)
sigmoid_df <- data.frame(z = z_values, probability = prob_values)

# ggplot2 ile Sigmoid fonksiyonunu çizelim
ggplot(sigmoid_df, aes(x = z, y = probability)) +
  geom_line(color = "darkblue", size = 1) +
  geom_hline(yintercept = 0.5, linetype = "dashed", color = "red") +
  geom_vline(xintercept = 0, linetype = "dashed", color = "red") +
  labs(title = "Sigmoid (Lojistik) Fonksiyonu",
       x = "Lineer Kombinasyon (z)",
       y = "Olasılık P(Y=1|X)") +
  theme_minimal() +
  scale_y_continuous(limits = c(0, 1), breaks = seq(0, 1, 0.1)) +
  annotate("text", x = 5, y = 0.9, label = "z arttıkça P(Y=1|X) 1'e yaklaşır", color = "darkgreen") +
  annotate("text", x = -5, y = 0.1, label = "z azaldıkça P(Y=1|X) 0'a yaklaşır", color = "darkgreen") +
  annotate("text", x = 2, y = 0.55, label = "Eşik Noktası: z=0 ise P=0.5", color = "darkred", hjust = 0)
## Warning: Using `size` aesthetic for lines was deprecated in ggplot2 3.4.0.
## ℹ Please use `linewidth` instead.
## This warning is displayed once every 8 hours.
## Call `lifecycle::last_lifecycle_warnings()` to see where this warning was
## generated.

# Gerekli kütüphaneleri yükleyelim (ggplot2 zaten yüklü varsayalım)
# library(ggplot2)

# Rasgelelik için sabitleme
set.seed(42)

# Sentetik veri seti oluşturalım
# Bağımsız değişken (örneğin, ders çalışma süresi)
x <- runif(100, min = 0, max = 10) # 0 ile 10 saat arasında çalışma süresi

# Bağımlı değişken (örneğin, sınavı geçme/kalma)
# z = -3 + 0.6 * x (basit bir lineer kombinasyon)
# Bu z'yi sigmoid'e sokarak olasılık hesaplayalım
linear_combination_z <- -3 + 0.6 * x + rnorm(100, mean = 0, sd = 1) # Biraz gürültü ekleyelim
simulated_prob <- sigmoid(linear_combination_z)

# Olasılıklara göre ikili çıktıyı belirleyelim (örneğin, 0.5 eşiği ile)
y <- ifelse(simulated_prob > 0.5, 1, 0)

# Veri çerçevesini oluşturalım
df_sim <- data.frame(study_hours = x, pass_exam = as.factor(y)) # 'y'yi faktör olarak tanımla

# Verinin ilk birkaç satırını görelim
head(df_sim)
# Lojistik Regresyon modelini kuralım
# family="binomial", ikili bağımlı değişkenler için Lojistik Regresyon kullanır
model_logit <- glm(pass_exam ~ study_hours, data = df_sim, family = "binomial")

# Modelin özetini görüntüleyelim
summary(model_logit)
## 
## Call:
## glm(formula = pass_exam ~ study_hours, family = "binomial", data = df_sim)
## 
## Coefficients:
##             Estimate Std. Error z value Pr(>|z|)    
## (Intercept)  -5.0052     1.0283  -4.868 1.13e-06 ***
## study_hours   0.9883     0.1877   5.265 1.40e-07 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## (Dispersion parameter for binomial family taken to be 1)
## 
##     Null deviance: 138.269  on 99  degrees of freedom
## Residual deviance:  61.869  on 98  degrees of freedom
## AIC: 65.869
## 
## Number of Fisher Scoring iterations: 6
# Tahmin edilen olasılıkları modelden alalım
df_sim$predicted_prob <- predict(model_logit, type = "response")

# Karar eşiği (genellikle 0.5) kullanarak sınıflandırma yapalım
df_sim$predicted_class <- ifelse(df_sim$predicted_prob > 0.5, "1", "0")

# Orijinal 'pass_exam' değişkenini sayısal hale getirelim ki plot'ta sürekli görünebilsin
df_sim$pass_exam_numeric <- as.numeric(as.character(df_sim$pass_exam))

# ggplot2 ile sonuçları görselleştirelim
ggplot(df_sim, aes(x = study_hours, y = pass_exam_numeric)) +
  geom_point(aes(color = as.factor(pass_exam)), alpha = 0.7, size = 3) +
  geom_line(aes(y = predicted_prob), color = "darkblue", size = 1, linetype = "solid") + # Sigmoid eğrisi
  geom_hline(yintercept = 0.5, linetype = "dashed", color = "red") + # Karar sınırı
  labs(title = "Lojistik Regresyon Modeli: Sınavı Geçme Olasılığı",
       x = "Çalışma Saatleri",
       y = "Sınavı Geçme Olasılığı (Tahmin Edilen)",
       color = "Sınav Sonucu (Gerçek)") +
  scale_y_continuous(breaks = c(0, 0.5, 1), labels = c("0 (Kalma)", "0.5 (Eşik)", "1 (Geçme)")) +
  scale_color_manual(values = c("0" = "orange", "1" = "darkgreen")) +
  theme_minimal() +
  # Karar sınırının çalışma saatleri karşılığını da işaretleyelim
  annotate("text", x = 8, y = 0.6, label = "Sigmoid Olasılık Eğrisi", color = "darkblue", hjust = 0) +
  annotate("text", x = 8, y = 0.45, label = "Karar Sınırı (P=0.5)", color = "red", hjust = 0)

8.4.4. Maksimum Olabilirlik Tahmini (Maximum Likelihood Estimation - MLE)

Sevgili Dostlar,

Lojistik Regresyon modelimizin denklemini kurduk ve R’da glm() fonksiyonu ile sentetik veri setimiz üzerinde bir model oluşturduk. R, summary(model_logit) çıktısında bize (Intercept) (β0) ve study_hours (β1) için katsayı tahminleri sundu. Peki, bu katsayıları hangi prensibe göre belirledi?

Lineer Regresyon’da kullandığımız En Küçük Kareler (Ordinary Least Squares - OLS) yöntemi, tahmin edilen sürekli değer ile gerçek değer arasındaki hatanın kareleri toplamını minimize etmeye odaklanıyordu. Ancak Lojistik Regresyon’da, çıktımız bir olasılık olduğu ve “Varsayımlar” bölümünde gördüğümüz gibi hatalar normal dağılmadığı için OLS uygun bir yöntem değildir.

Bunun yerine, istatistiksel çıkarımın temel taşlarından biri olan çok daha genel ve güçlü bir yöntem kullanırız: Maksimum Olabilirlik Tahmini (Maximum Likelihood Estimation - MLE).

MLE’nin temel mantığı, OLS’den farklı bir soru sorar. OLS “Hataları en aza indiren çizgi hangisidir?” diye sorarken, MLE şu soruyu sorar:

Elimizdeki veriye (örneğin, kimin sınavı geçtiği, kimin kaldığı) bakarak, bu gözlemlenen sonuçları ortaya çıkarma olasılığını en yüksek yapan model parametreleri (β katsayıları) hangileridir? Yani MLE, eldeki veriyi en iyi “açıklayan” parametre setini bulmaya çalışır. Model, olası tüm β0 ve β1 kombinasyonlarını dener ve bizim veri setimizdeki “geçti/kaldı” etiketlerini en olası kılan kombinasyonu seçer.

Bu süreçte, model matematiksel olarak bir “Olabilirlik Fonksiyonu” (Likelihood Function), L(β∣veri), kurar. Bu fonksiyon, belirli β katsayıları verildiğinde, gözlemlediğimiz verinin (tüm Y değerlerinin) ortaya çıkma olasılığını temsil eder. MLE’nin amacı, bu fonksiyonun değerini maksimize edecek βkatsayılarını bulmaktır. Matematiksel kolaylık sağlaması ve sayısal kararlılığı artırması için genellikle bu fonksiyonun logaritması alınır (Log-Likelihood, ℓ(β∣veri) ve bu değer maksimize edilir.

Neyse ki, “Veri Mimarı” olarak bu karmaşık optimizasyon sürecini manuel olarak yapmak zorunda değiliz. R’daki glm() fonksiyonu, bu işi (genellikle “Iteratively Reweighted Least Squares - IRLS” gibi sayısal yöntemler kullanarak) bizim için arka planda verimli bir şekilde halleder. Bölüm 8.5’de pratik uygulama ile konu daha da pekişecektir.

Akademik Referans: Maksimum Olabilirlik Tahmini kavramı, modern istatistiğin temel taşlarından biridir ve bu yöntemin temelleri, büyük istatistikçi Ronald A. Fisher tarafından 1920’lerde atılmıştır (Fisher, 1922). Lojistik Regresyon’un MLE ile çözümlenmesi, bu teorinin en yaygın ve pratik uygulamalarından biridir.

Bir önceki adımda çalıştırdığımız summary(model_logit) komutundan elde ettiğimiz katsayılar (Coefficients bölümündeki Estimate değerleri), işte bu MLE sürecinin sonunda bulunan ve sentetik veri setimizdeki “geçme/kalma” sonuçlarını en olası kılan değerlerdir.

8.4.5. Karar Sınırı (Decision Boundary)

Sevgili Dostlar,

Önceki adımlarda Lojistik Regresyon modelimizi kurduk ve bu modelin bize her bir study_hours değeri için 0 ile 1 arasında bir “sınavı geçme olasılığı” (predicted_prob) verdiğini gördük. Bu olasılıklar harika, ancak genellikle nihai bir karara ihtiyacımız vardır: “geçti” (1) veya “kaldı” (0).

İşte bu noktada karar sınırı (decision boundary) veya eşik değeri (threshold) devreye girer. Bu, olasılıkları somut sınıflara atamak için kullandığımız basit bir kuraldır. En yaygın ve sezgisel eşik değeri 0.5’tir. Kural şöyledir:

  • Eğer modelin tahmin ettiği olasılık > 0.5 ise, öğrenciyi “geçti” (1) olarak sınıflandır.

  • Eğer modelin tahmin ettiği olasılık <= 0.5 ise, öğrenciyi “kaldı” (0) olarak sınıflandır.

Sigmoid eğrimizi hatırlarsanız, olasılığın tam olarak 0.5 olduğu nokta, lineer kombinasyon olan z’nin 0’a eşit olduğu yerdir. Yani karar sınırımız,\[ z = \beta_0 + \beta_1 x_1 = 0\]

denkleminin çözüldüğü noktadır. Bu, modelin “kararsız” kaldığı, her iki sonuca da eşit olasılık verdiği yerdir.

Karar Sınırını Hesaplama ve Görselleştirme

Bölüm 8.4.3’te oluşturduğumuz model_logit’i kullanarak, bu karar sınırının tam olarak hangi study_hours değerine karşılık geldiğini hesaplayabiliriz.

Yukarıdaki denklemi study_hours (x1) için çözersek:

Şimdi R’da modelimizin katsayılarını (coef(model_logit)) kullanarak bu değeri bulalım ve daha önceki grafiğimize bu sınırı ekleyerek görselleştirelim.

# Rasgelelik için sabitleme
set.seed(42)

# Model katsayılarını alalım
coefficients <- coef(model_logit)
beta_0 <- coefficients[1] # Intercept
beta_1 <- coefficients[2] # study_hours

# Karar sınırını hesaplayalım
decision_boundary_hours <- -beta_0 / beta_1

# Hesaplanan değeri yazdıralım
print(paste("Karar Sınırı (P=0.5) için gereken çalışma saati:", round(decision_boundary_hours, 2)))
## [1] "Karar Sınırı (P=0.5) için gereken çalışma saati: 5.06"
# Bir önceki bölümde oluşturduğumuz grafiği tekrar çizelim
# Bu sefer hesapladığımız dikey karar sınırını ekleyerek
ggplot(df_sim, aes(x = study_hours, y = pass_exam_numeric)) +
  geom_point(aes(color = as.factor(pass_exam)), alpha = 0.7, size = 3) +
  geom_line(aes(y = predicted_prob), color = "darkblue", size = 1, linetype = "solid") +
  geom_hline(yintercept = 0.5, linetype = "dashed", color = "red") +
  # Hesapladığımız dikey karar sınırını ekliyoruz
  geom_vline(xintercept = decision_boundary_hours, linetype = "dotted", color = "purple", size = 1) +
  labs(title = "Lojistik Regresyon Modeli: Karar Sınırı ile Birlikte",
       x = "Çalışma Saatleri",
       y = "Sınavı Geçme Olasılığı",
       color = "Gerçek Sınav Sonucu") +
  scale_y_continuous(breaks = c(0, 0.5, 1), labels = c("0 (Kalma)", "0.5 (Eşik)", "1 (Geçme)")) +
  scale_color_manual(values = c("0" = "orange", "1" = "darkgreen")) +
  theme_minimal() +
  annotate("text", x = 8, y = 0.6, label = "Sigmoid Olasılık Eğrisi", color = "darkblue", hjust = 0) +
  annotate("text", x = decision_boundary_hours + 0.1, y = 0.2, 
           label = paste("Karar Sınırı\n~", round(decision_boundary_hours, 2), "saat"), 
           color = "purple", hjust = 0)

Görselleştirme Yorumu:

Yukarıdaki kodun çıktısı, modelimizin “geçme” ve “kalma” kararları arasında ayrım yaptığı noktayı bize sayısal olarak verir. (Not: set.seed(42) kullandığımız için bu değer herkeste yaklaşık olarak 5.1 saat civarında çıkacaktır).

Grafiğe eklediğimiz yeni mor noktalı çizgi, işte bu karar sınırını temsil eder. Bu çizginin anlamı şudur:

Bu modelimize göre, yaklaşık 5.1 saatten az çalışan bir öğrencinin sınavı geçme olasılığı 0.5’ten düşüktür ve bu nedenle “kaldı” (0) olarak sınıflandırılır.

Yaklaşık 5.1 saatten fazla çalışan bir öğrencinin sınavı geçme olasılığı ise 0.5’ten yüksektir ve “geçti” (1) olarak sınıflandırılır.

Bu, modelimizin olasılık tahminlerini nasıl somut eyleme geçirilebilir kararlara dönüştürdüğünün mükemmel bir gösterimidir.

Önemli Not:

0.5 eşiği en yaygın başlangıç noktası olsa da, her zaman en iyisi olmayabilir. Örneğin, bir hastalık teşhis modelinde, hiçbir hastayı kaçırmamak için (yani “false negative” sayısını azaltmak için) eşiği 0.3’e çekmek daha mantıklı olabilir. Eşik değerinin seçimi, problemin bağlamına bağlıdır ve bu konuyu daha sonra ROC eğrileri gibi model değerlendirme metriklerini incelerken tekrar ele alacağız.

8.4.6. Katsayıların Yorumlanması: Olasılık Oranları (Odds Ratios)

Sevgili Dostlar,

Modelimizi kurduk, parametrelerini öğrendik ve bir karar sınırı belirledik. Şimdi summary(model_logit) çıktısındaki katsayılara (Coefficients) tekrar bakalım. study_hours için elde ettiğimiz katsayı (yaklaşık 0.99), ne anlama geliyor? “Çalışılan her saat, geçme olasılığını 0.99 artırır” diyemeyiz!

Bu büyük bir yanılgı olur, çünkü Lojistik Regresyon’un yapısı gereği, katsayılar olasılığı değil, log-odds (logit) adı verilen bir dönüşümü lineer olarak etkiler. Bu, yorumlanabilirliği zorlaştırır. Ancak neyse ki, bu katsayıları son derece sezgisel bir formata dönüştürmenin bir yolu var: Odds Ratios.

Peki o zaman bir önceki summary() tablosu ne işe yarıyordu?

Usta Notu: İki Tablo, İki Farklı Görev - “Dedektif” ve “Tercüman”

Bir Lojistik Regresyon modelinin çıktısını analiz ederken, aslında iki temel soruyu cevaplamaya çalışırız. Bu iki soru için iki farklı tabloya bakarız:

Soru: “Bir etki var mı, yok mu?” - Cevap summary() Tablosunda (Dedektif)

summary() çıktısındaki p-değerleri (Pr(>|z|)) ve anlamlılık yıldızları (***), bizim “Dedektif”imizdir. Bu tablonun görevi, hangi değişkenlerin sonuç üzerinde istatistiksel olarak anlamlı bir etkiye sahip olduğunu tespit etmektir. Bir p-değerinin 0.05’ten küçük olması, bize o etkinin tesadüfi olmadığını söyler.

Soru: “Bu etkinin büyüklüğü ve yönü nedir?” - Cevap exp(coef()) Tablosunda (Tercüman)

Anlamlı bir etki bulduktan sonra, bu etkinin ne kadar büyük ve ne anlama geldiğini yorumlamak için katsayıların üssünü alırız (exp()). Bu tablo bizim “Tercüman”ımızdır. Bize “… odds’u X kat artırır/azaltır” gibi sezgisel ve pratik yorumlar yapma imkanı verir. İş Akışı: Önce “Dedektif” ile anlamlı değişkenleri buluruz, sonra “Tercüman” ile bu değişkenlerin hikayesini anlatırız.

Bu önemli notu verdikten sonra Odds Ratios anlatımına devam edelim dostlar

Odds Ratios’u anlamak için iki adımı takip edelim:

Adım 1: Olasılıktan “Odds”a Geçiş

“Odds” (olasılık oranı), bir olayın gerçekleşme olasılığının, gerçekleşmeme olasılığına oranıdır.

\[ \text{Odds} = \frac{P(\text{olay})}{1 - P(\text{olay})} \]

Bir atın kazanma olasılığı %80 (P=0.8) ise, kaybetme olasılığı %20’dir (1−P=0.2). Odds = 0.8/0.2= 4 . Yani, atın kazanma odds’u “4’e 1”dir. Bir olayın gerçekleşme olasılığı %50 (P=0.5) ise, Odds = 0.5/0.5= 1. Olayın gerçekleşme ve gerçekleşmeme ihtimali eşittir

Adım 2: “Odds”dan “Odds Ratio”ya Geçiş

İşte sihirli kısım burası. Lojistik Regresyon’daki bir katsayının (β1) üssünü alırsak (yani exp(β₁)), Odds Ratio’yu elde ederiz.

Odds Ratio (OR), bağımsız değişkendeki (örneğin study_hours) bir birimlik artışın, başarı (Y=1) “odds”unu kaç kat değiştirdiğini gösteren bir çarpandır.

  • Eğer OR > 1 ise, bağımsız değişken arttıkça olayın gerçekleşme odds’u artar.

  • Eğer OR < 1 ise, bağımsız değişken arttıkça olayın gerçekleşme odds’u azalır.

  • Eğer OR = 1 ise, bağımsız değişkenin olayın odds’u üzerinde bir etkisi yoktur.

Katsayıları Odds Ratio’ya Dönüştürme ve Yorumlama

Şimdi model_logit modelimizdeki katsayıları alıp exp() fonksiyonu ile Odds Ratio’larına dönüştürelim.

# Modelin katsayılarını tekrar görelim (bunlar log-odds)
print("Model Katsayıları (Log-Odds):")
## [1] "Model Katsayıları (Log-Odds):"
coef(model_logit)
## (Intercept) study_hours 
##  -5.0052002   0.9882559
# Katsayıların üssünü alarak Odds Ratio'ları hesaplayalım
print("Odds Ratiolar:")
## [1] "Odds Ratiolar:"
exp(coef(model_logit))
## (Intercept) study_hours 
## 0.006702999 2.686544865

Çıktı Yorumu:

Yukarıdaki kodun çıktısını yorumlayalım (sonuçlar set.seed(42) kullandığımız için tutarlıdır):

(Intercept) (~0.0067): Bu, study_hours sıfır olduğunda, bir öğrencinin sınavı geçme odds’udur. Yani, hiç çalışmayan bir öğrencinin sınavı geçme odds’u, kalma odds’unun sadece %0.67’si kadardır. Bu, oldukça düşük bir başlangıç noktasıdır.

study_hours (~2.69): Bu en önemli değerdir! Yorumu şudur: Çalışma süresindeki her 1 saatlik artış, sınavı geçme olasılık oranını (odds) yaklaşık 2.69 katına çıkarmaktadır. Bu, artık doğrusal (“… kadar artar”) değil, çarpımsal (“… katına çıkar”) bir ilişkidir. Bir saat daha fazla çalışan birinin sınavı geçme odds’u, çalışmayana göre 2.69 kat daha yüksektir.

Güven Aralıkları ile Yorumu Güçlendirme

Bir önceki adımda bulduğumuz ~2.69’luk Odds Ratio değeri sadece bir nokta tahminidir. Bu etkinin istatistiksel olarak ne kadar güvenilir olduğunu görmek için Odds Ratio’nun güven aralıklarına bakabiliriz.

# Odds Ratio'lar için %95 güven aralıklarını hesaplayalım
exp(confint(model_logit))
## Waiting for profiling to be done...
##                    2.5 %     97.5 %
## (Intercept) 0.0006451692 0.03867389
## study_hours 1.9539509782 4.12855438

Güven Aralığı Yorumu:

study_hours için %95 güven aralığı, çıktıda da gördüğümüz gibi, yaklaşık (1.95, 4.13) aralığındadır.Bunun anlamı şudur:

Biz %95 eminiz ki, çalışma süresindeki her 1 saatlik artışın gerçek Odds Ratio’su 1.95 ile 4.13 arasındadır.

En önemlisi, bu aralık 1’i içermiyor. Bu da study_hours değişkeninin, sınavı geçme odds’u üzerinde istatistiksel olarak anlamlı ve pozitif bir etkisi olduğunu güçlü bir şekilde teyit eder.

Ustalın Notları

Önemli Not1:

Güven Aralığı ve “1” Sayısının Anlamı

Odds Ratio’ları yorumlarken, 1 sayısı “etkisizlik noktasıdır”. Çünkü bir değişkenin Odds Ratio’su tam olarak 1 ise, o değişkenin sonuç üzerinde hiçbir etkisi yok demektir (odds’u 1 ile çarpmak bir şeyi değiştirmez).

Güven aralığı ise, bizim “güvenilir tahmin aralığımızdır”. Bu aralığın “1” sayısıyla olan ilişkisine bakarak bir etkinin anlamlı olup olmadığına karar veririz:

  • Aralık tamamen 1’in üzerindeyse (örn: [1.95, 4.13]): Etki, istatistiksel olarak anlamlı ve pozitiftir (artırıcıdır). “Etkisizlik” seçeneği masada değildir.

  • Aralık tamamen 1’in altındaysa (örn: [0.4, 0.8]): Etki, istatistiksel olarak anlamlı ve negatiftir (azaltıcıdır).

  • Aralık 1’i içeriyorsa (örn: [0.7, 1.5]): Etki, istatistiksel olarak anlamlı değildir. Çünkü “etkisizlik” (1 sayısı) hala bizim güvenilir tahmin aralığımızın içindedir, yani makul bir olasılıktır.

Önemli Not2:

Peki, Neden %95 yerine %2.5 ve %97.5 yazıyor? Bu, %95’lik bir güven aralığının standart istatistiksel gösterimidir.

Bir güven aralığı, bir olasılık dağılımının ortasındaki %95’lik alanı kapsar. Bunu yapmak için, dağılımın en alt (%2.5) ve en üst (%2.5) kısımları dışarıda bırakılır. Dolayısıyla, çıktıda gördüğünüz %2.5 aralığın alt sınırını, %97.5 ise aralığın üst sınırını temsil eder. Bu iki persentil değeri arasındaki mesafe (97.5 - 2.5), tam olarak %95’lik aralığın kendisidir.

8.4.7. Model Değerlendirme Metrikleri

Sevgili Dostlar,

Bir Lojistik Regresyon modeli kurduk ve katsayılarını yorumladık. Ancak bu model, gerçek dünyada ne kadar iyi tahminler yapıyor? Öğrencilerin geçme/kalma durumlarını ne kadar isabetli öngörüyor? Bu soruları yanıtlamak için bir dizi değerlendirme metriği kullanırız.

Karışıklık Matrisi (Confusion Matrix)

Sınıflandırma modellerini değerlendirmenin temel taşı Karışıklık Matrisi’dir. Bu matris, modelimizin tahminlerinin gerçek değerlerle ne kadar örtüştüğünü gösteren basit bir 2x2 tablodur.

Matrisin dört temel bileşeni vardır:

-True Positive (TP - Gerçek Pozitif): Model “geçti” dedi, öğrenci gerçekten de geçti. (Doğru tahmin)

-True Negative (TN - Gerçek Negatif): Model “kaldı” dedi, öğrenci gerçekten de kaldı. (Doğru tahmin)

-False Positive (FP - Yanlış Pozitif): Model “geçti” dedi, ama öğrenci aslında kaldı. (Tip I Hata)

-False Negative (FN - Yanlış Negatif): Model “kaldı” dedi, ama öğrenci aslında geçti. (Tip II Hata)

Karışıklık Matrisi Oluşturma

R’da bu matrisi ve ilgili metrikleri kolayca oluşturmak için caret paketi harika bir araçtır. Önce bu paketi yükleyip kütüphanemize çağıralım, ardından 0.5 eşiğine göre yaptığımız sınıflandırmaları (predicted_class) gerçek değerlerle (pass_exam) karşılaştıralım.

(Not: caret paketi yüklü değilse, önce install.packages(“caret”) komutu ile yüklemeniz gerekir.)

# Gerekli kütüphaneyi yükleyelim
library(caret)
## Loading required package: lattice
# Önemli: confusionMatrix fonksiyonu için hem tahminlerin hem de gerçek değerlerin
# aynı seviyelere sahip faktörler olması gerekir.
# Gerçek değerler: df_sim$pass_exam (zaten faktör)
# Tahmin edilen değerler: df_sim$predicted_class (karakter, faktöre çevirelim)
df_sim$predicted_class <- as.factor(df_sim$predicted_class)

# Karışıklık Matrisini oluşturalım
# Not: 'positive' argümanı ile hangi sınıfın "pozitif" olduğunu belirtiyoruz.
# Bu, Sensitivity ve Precision gibi metriklerin doğru hesaplanması için önemlidir.
confusionMatrix(data = df_sim$predicted_class, 
                reference = df_sim$pass_exam, 
                positive = "1")
## Confusion Matrix and Statistics
## 
##           Reference
## Prediction  0  1
##          0 39  6
##          1  8 47
##                                           
##                Accuracy : 0.86            
##                  95% CI : (0.7763, 0.9213)
##     No Information Rate : 0.53            
##     P-Value [Acc > NIR] : 2.677e-12       
##                                           
##                   Kappa : 0.7183          
##                                           
##  Mcnemar's Test P-Value : 0.7893          
##                                           
##             Sensitivity : 0.8868          
##             Specificity : 0.8298          
##          Pos Pred Value : 0.8545          
##          Neg Pred Value : 0.8667          
##              Prevalence : 0.5300          
##          Detection Rate : 0.4700          
##    Detection Prevalence : 0.5500          
##       Balanced Accuracy : 0.8583          
##                                           
##        'Positive' Class : 1               
## 

Çıktı Yorumu:

Yukarıdaki kodun çıktısı bize hem karışıklık matrisini hem de bir dizi önemli metriği verir:

-Confusion Matrix Tablosu: Burada TP, TN, FP ve FN değerlerini ham sayılar olarak görürsünüz.

-Accuracy (Doğruluk): (TP + TN) / Toplam. Genel olarak tahminlerimizin yüzde kaçının doğru olduğunu söyler. Bizim modelimiz için oldukça yüksek (örneğin %86) çıkacaktır. Ancak dikkat! Dengesiz veri setlerinde (örneğin, %95’i “kaldı”, %5’i “geçti” olan bir durumda) doğruluk yanıltıcı olabilir.

-Sensitivity (Duyarlılık, Recall): TP / (TP + FN). Gerçekte “geçen” (Pozitif) öğrencilerin yüzde kaçını doğru tespit edebildik? Modelimizin pozitif sınıfı yakalama gücüdür.

-Specificity (Özgüllük): TN / (TN + FP). Gerçekte “kalan” (Negatif) öğrencilerin yüzde kaçını doğru tespit edebildik? Modelimizin negatif sınıfı yakalama gücüdür.

-Precision (Kesinlik): TP / (TP + FP). Modelimizin “geçti” olarak etiketlediği öğrencilerin gerçekte yüzde kaçı geçti? Modelimizin pozitif tahminlerinin kalitesidir.

-F1 Score: Precision ve Recall metriklerinin harmonik ortalamasıdır. Bu iki metrik arasında bir denge aradığımızda (ikisi de bizim için önemliyse) F1 skoruna bakarız.

Eşik Değerinden Bağımsız Değerlendirme: ROC Eğrisi ve AUC

Karışıklık matrisi, 0.5 gibi tek bir eşik değerine bağlıdır. Peki ya en iyi eşik 0.6 veya 0.4 ise? Modelin genel ayrım gücünü, tüm olası eşik değerleri üzerinden değerlendirmek için ROC Eğrisi (Receiver Operating Characteristic Curve) kullanılır.

ROC eğrisi, farklı eşik değerleri için Duyarlılık (Sensitivity, True Positive Rate) ile 1 - Özgüllük (False Positive Rate) arasındaki ilişkiyi gösteren bir grafiktir.

Eğri ne kadar sol üst köşeye yakınsa, model o kadar iyidir.

Sol alttan sağ üste giden 45 derecelik çizgi, rastgele tahmini (yazı tura atmayı) temsil eder.

AUC (Area Under the Curve - Eğrinin Altındaki Alan) ise ROC eğrisinin altında kalan alanı ölçen tek bir sayıdır.

-AUC = 1: Mükemmel model.

-AUC = 0.5: Rastgele model (işe yaramaz).

-AUC > 0.7: Genellikle kabul edilebilir bir model olarak görülür.

-AUC > 0.8: İyi bir model olarak görülür.

-AUC > 0.9: Mükemmel bir model olarak görülür.

ROC Eğrisi Çizme ve AUC Hesaplama

Bu analizi yapmak için pROC paketi son derece kullanışlıdır.

(Not: pROC paketi yüklü değilse, önce install.packages(“pROC”) komutu ile yüklemeniz gerekir.)

# Gerekli kütüphaneyi yükleyelim
library(pROC)
## Type 'citation("pROC")' for a citation.
## 
## Attaching package: 'pROC'
## The following objects are masked from 'package:stats':
## 
##     cov, smooth, var
# ROC eğrisi nesnesini oluşturalım
# Not: roc() fonksiyonuna gerçek değerleri (response) ve
# modelin tahmin ettiği olasılıkları (predictor) veririz.
roc_obj <- roc(response = df_sim$pass_exam, predictor = df_sim$predicted_prob)
## Setting levels: control = 0, case = 1
## Setting direction: controls < cases
# ROC eğrisini çizelim
plot(roc_obj, main = "ROC Eğrisi", print.auc = TRUE, col = "darkblue")

# AUC değerini ayrıca hesaplayıp yazdıralım
auc_value <- auc(roc_obj)
print(paste("Eğrinin Altındaki Alan (AUC):", round(auc_value, 4)))
## [1] "Eğrinin Altındaki Alan (AUC): 0.9426"

Görselleştirme ve AUC Yorumu:

Grafikteki mavi eğri, bizim modelimizin performansını gösterir. Rastgele tahmin çizgisinin (genellikle kesikli gösterilir) oldukça üzerinde olduğunu göreceksiniz.

AUC değeri çıktıda yazacaktır (örneğin ~0.94). Bu değer, modelimizin son derece iyi bir ayrım gücüne sahip olduğunu gösterir.

AUC’nin sezgisel bir yorumu şudur: Veri setinden rastgele seçilen “geçen” bir öğrenci ile “kalan” bir öğrenciyi aldığımızda, modelimizin “geçen” öğrenciye daha yüksek bir geçme olasılığı atama ihtimali %94’tür.

8.4.8. Çok Sınıflı Lojistik Regresyon (Multinomial Logistic Regression)

Sevgili Dostlar,

Şimdiye kadar Lojistik Regresyon’u hep ikili (binary) bir bağımlı değişken için kullandık. “Şanslı’nın Kartları” metaforumuzda sonuç ya “kazanma” ya da “kaybetme” idi. Ancak gerçek dünyadaki sınıflandırma problemleri her zaman iki kategoriyle sınırlı değildir.

Peki ya bir müşteri anketinde, bir ürün için müşterinin tepkisi “Beğendi”, “Beğenmedi” ve “Nötr” şeklinde üç kategoriye ayrılıyorsa? Veya “Şanslı’nın Kartları” oyununda “Kazanma”, “Kaybetme” ve “Berabere Kalma” gibi üç olası sonuç varsa?

Bu gibi durumlar için Lojistik Regresyon’un bir uzantısı olan Çok Sınıflı (Multinomial) Lojistik Regresyon kullanılır.

Sigmoid’den Softmax’e

İkili Lojistik Regresyon’un kalbinde, çıktıyı 0 ile 1 arasına sıkıştıran Sigmoid fonksiyonu vardı. Bu fonksiyon, bir olayın olma olasılığını (P(Y=1)) veriyordu, olmama olasılığı ise otomatikman 1−P(Y=1) oluyordu.

İkiden fazla kategori olduğunda ise tek bir olasılık hesaplamak yeterli değildir. Her bir kategori için ayrı bir olasılık hesaplamamız gerekir ve bu olasılıkların toplamı 1 olmalıdır. Örneğin:

P(Kazanma)+P(Kaybetme)+P(Berabere Kalma)=1

İşte bu noktada Sigmoid fonksiyonunun genelleştirilmiş bir versiyonu olan Softmax fonksiyonu devreye girer.

Softmax fonksiyonu, modelden gelen birden çok lineer tahmini (\(z_1, z_2, \dots, z_k\)) alır ve bunları, toplamları 1 olan bir olasılık dağılımına dönüştürür.

Nasıl Çalışır? (Sezgisel Anlatım)

Multinomial Lojistik Regresyon, kategorilerden birini referans (baseline) olarak seçer. Örneğin, “Berabere Kalma”yı referans alalım. Model daha sonra, diğer her bir kategorinin bu referans kategoriye göre log-odds’unu hesaplayan ayrı denklemler öğrenir:

-Birinci Denklem: “Kazanma”nın “Berabere Kalma”ya göre log-odds’unu modeller.

-İkinci Denklem: “Kaybetme”nin “Berabere Kalma”ya göre log-odds’unu modeller.

Bu denklemlerden elde edilen skorlar daha sonra Softmax fonksiyonuna verilir ve bu fonksiyon bize her bir sonuç (“Kazanma”, “Kaybetme”, “Berabere Kalma”) için nihai olasılıkları verir.

Önemli Not:

Bu yöntem, kategoriler arasında doğal bir sıralama olmadığı zaman kullanılır. Eğer “kötü” < “orta” < “iyi” gibi bir sıralama olsaydı, o zaman Sıralı (Ordinal) Lojistik Regresyon adı verilen farklı bir teknik kullanılırdı.

iris Veri Seti ile Basit Bir Örnek

Bu konsepti somutlaştırmak için R’daki meşhur iris veri setini kullanalım. Bu veri setinin amacı, çiçeklerin taç ve çanak yapraklarının uzunluk ve genişliğine (Sepal.Length, Sepal.Width, Petal.Length, Petal.Width) bakarak, çiçeğin hangi türe (Species) ait olduğunu tahmin etmektir. Bağımlı değişkenimiz olan Species’in üç kategorisi vardır: setosa, versicolor ve virginica.

R’da bu tür modelleri kurmak için genellikle nnet paketindeki multinom() fonksiyonu kullanılır.

(Not: nnet paketi yüklü değilse, önce install.packages(“nnet”) komutu ile yüklemeniz gerekir.)

# Gerekli kütüphaneyi yükleyelim
library(nnet)

# iris veri setini yükleyelim (R'da hazır bulunur)
data(iris)

# Modeli kuralım: Species ~ . formülü, 'Species' değişkenini diğer tüm 
# değişkenleri kullanarak tahmin et demektir.
multinom_model <- multinom(Species ~ ., data = iris)
## # weights:  18 (10 variable)
## initial  value 164.791843 
## iter  10 value 16.177348
## iter  20 value 7.111438
## iter  30 value 6.182999
## iter  40 value 5.984028
## iter  50 value 5.961278
## iter  60 value 5.954900
## iter  70 value 5.951851
## iter  80 value 5.950343
## iter  90 value 5.949904
## iter 100 value 5.949867
## final  value 5.949867 
## stopped after 100 iterations
# Modelin özetini görelim
summary(multinom_model)
## Call:
## multinom(formula = Species ~ ., data = iris)
## 
## Coefficients:
##            (Intercept) Sepal.Length Sepal.Width Petal.Length Petal.Width
## versicolor    18.69037    -5.458424   -8.707401     14.24477   -3.097684
## virginica    -23.83628    -7.923634  -15.370769     23.65978   15.135301
## 
## Std. Errors:
##            (Intercept) Sepal.Length Sepal.Width Petal.Length Petal.Width
## versicolor    34.97116     89.89215    157.0415     60.19170    45.48852
## virginica     35.76649     89.91153    157.1196     60.46753    45.93406
## 
## Residual Deviance: 11.89973 
## AIC: 31.89973

Çıktı Yorumu :

summary() komutunun çıktısı, ikili modelden biraz daha karmaşıktır. İki ana bölüm göreceksiniz:

-Coefficients (Katsayılar):

Çıktıda versicolor ve virginica için ayrı katsayı setleri olduğunu fark edeceksiniz. Neden setosa yok? Çünkü multinom() fonksiyonu, alfabetik olarak ilk kategori olan setosa’yı referans kategori olarak seçmiştir.versicolor bölümündeki katsayılar, bir çiçeğin setosa yerine versicolor olma log-odds’unu nasıl etkilediğini gösterir.virginica bölümündeki katsayılar ise, bir çiçeğin setosa yerine virginica olma log-odds’unu nasıl etkilediğini gösterir.

-Standard Errors (Standart Hatalar):

Her bir katsayının standart hatasını gösterir.

Bu model sayesinde, artık yeni bir çiçeğin ölçümlerini verdiğimizde, predict() fonksiyonu bize o çiçeğin setosa, versicolor ve virginica olma olasılıklarını ayrı ayrı verecektir (ve bu üç olasılığın toplamı 1 olacaktır).

Modeli Kullanarak Yeni Bir Çiçek İçin Tahmin Yapma

Modelimizin asıl gücü, yeni bir çiçeğin ölçümlerini aldığımızda onun türünü tahmin edebilmesidir. Diyelim ki sahada ölçümleri aşağıdaki gibi olan yeni bir çiçek bulduk. Şimdi predict() fonksiyonunu kullanarak bu çiçeğin türünü tahmin edelim.

# Yeni bir çiçek için ölçümleri bir data frame olarak oluşturalım
yeni_cicek <- data.frame(
  Sepal.Length = 6.0,
  Sepal.Width = 3.0,
  Petal.Length = 5.0,
  Petal.Width = 1.8
)

# 1. Her bir sınıf için olasılıkları tahmin edelim
#    type = "probs" argümanı bize olasılık dağılımını verir
tahmini_olasiliklar <- predict(multinom_model, newdata = yeni_cicek, type = "probs")
print("Tahmini Olasılıklar:")
## [1] "Tahmini Olasılıklar:"
print(tahmini_olasiliklar)
##       setosa   versicolor    virginica 
## 6.104126e-13 7.001863e-02 9.299814e-01
# 2. En olası sınıfı doğrudan tahmin edelim
#    type = "class" (veya varsayılan) bize en yüksek olasılıklı sınıfı verir
tahmini_sinif <- predict(multinom_model, newdata = yeni_cicek, type = "class")
print("Nihai Sınıf Tahmini:")
## [1] "Nihai Sınıf Tahmini:"
print(tahmini_sinif)
## [1] virginica
## Levels: setosa versicolor virginica

Karşımıza gelen çıktılara tekrar tek tek bakalım.

Bu tablo, modelimizin yeni_cicek için yaptığı olasılık tahminlerinin dağılımını gösterir. Gelin bu bilimsel gösterimleri anlaşılır yüzdelere çevirelim:

setosa: 6.104126e-13: Bu, 0’dan sonra 12 sıfırın geldiği (0.0000000000006…) inanılmaz küçük bir sayıdır. Modelimize göre, bu çiçeğin setosa olma olasılığı neredeyse sıfırdır.

versicolor: 7.001863e-02: Bu, 0.0700… anlamına gelir. Modelimize göre, bu çiçeğin versicolor olma olasılığı yaklaşık %7.0’dir.

virginica: 9.299814e-01: Bu, 0.9299… anlamına gelir. Modelimize göre, bu çiçeğin virginica olma olasılığı yaklaşık %93.0’tür.

Dostlara Not: Dikkat ederseniz, bu üç olasılığın toplamı 1’e eşittir (0 + 0.07 + 0.93 = 1). Bu, teoride bahsettiğimiz Softmax fonksiyonunun görevidir: Her bir kategori için bir olasılık skoru üretir ve bu skorların toplamının 1 olmasını garanti eder.

Bu çıktı, modelin son ve net kararıdır. Peki bu karara nasıl vardı? Çok basit:

Model, bir önceki adımda hesapladığı olasılıklara bakar ve en yüksek olasılığa sahip olan sınıfı nihai tahmin olarak seçer.

%93.0 (virginica) > %7.0 (versicolor) > %0 (setosa)

En yüksek olasılık virginica türüne ait olduğu için, modelimizin bu yeni çiçek için nihai ve kesin tahmini “virginica” olur.

Bu sayede, bir botanikçi sahada yeni bir çiçek bulduğunda, ölçümlerini modelimize girerek çiçeğin türü hakkında sadece bir “tahmin” değil, aynı zamanda bu tahminden ne kadar emin olduğuna dair bir olasılık dağılımı da elde edebilir. Bu, teorinin pratiğe dökülmüş en güçlü halidir.

8.4.9. Lojistik Regresyon’un Avantajları ve Sınırlılıkları

Sevgili Dostlar,

Lojistik Regresyon’un derinliklerine yaptığımız bu yolculuğun sonuna yaklaşırken, bu modelin genel bir değerlendirmesini yapalım. “Machine Learning Academy”deki her araç gibi, Lojistik Regresyon’un da güçlü olduğu alanlar ve dikkatli kullanılması gereken durumlar vardır.

Lojistik Regresyon’un Avantajları (Neden Kullanmalıyız?)

-Yorumlanabilirlik (Interpretability): Bu, Lojistik Regresyon’un en büyük gücüdür. Özellikle Odds Ratio’lar sayesinde, her bir bağımsız değişkenin sonuç üzerindeki etkisini nicel olarak (“… kat daha fazla odds”) ve sezgisel olarak anlamak mümkündür. Bu özellik, modelin “siyah kutu” olmasını engeller ve özellikle finans, tıp gibi regüle edilen sektörlerde kararların arkasındaki “neden”i açıklamak için paha biçilmezdir.

-Basitlik ve Verimlilik: Lojistik Regresyon, matematiksel olarak zarif bir modeldir. Eğitimi hızlıdır ve büyük veri setlerinde bile (milyonlarca satır) rahatlıkla çalışabilir. Yeni başlayanlar için anlaşılması ve uygulanması en kolay sınıflandırma algoritmalarından biridir.

-Olasılık Tahmini Sunması: Model, sadece “evet/hayır” gibi kesin bir sınıflandırma yapmakla kalmaz, aynı zamanda her bir sınıf için bir olasılık skoru üretir. Bu, bize modelin tahmininden ne kadar “emin” olduğu hakkında değerli bir bilgi verir. Bu olasılıkları, belirlediğimiz iş hedeflerine göre farklı eşik değerleri ile kullanarak modelin davranışını ayarlayabiliriz.

-İyi Bir “Baseline” Modeli Olması: Karmaşık bir sınıflandırma problemine başlarken, ilk olarak basit bir Lojistik Regresyon modeli kurmak her zaman iyi bir fikirdir. Bu model, size problem hakkında hızlı bir şekilde temel bilgiler sunar ve daha karmaşık modellerin (örneğin, Random Forest veya Neural Networks) performansını karşılaştırabileceğiniz bir referans noktası (baseline) oluşturur.

Lojistik Regresyon’un Sınırlılıkları (Nelere Dikkat Etmeliyiz?)

-Doğrusal Karar Sınırı Varsayımı: Lojistik Regresyon, temelinde lineer bir modeldir. Bu, sınıfları ayırmak için doğrusal bir karar sınırı (tek değişkenli durumda bir nokta, iki değişkende bir çizgi, çok değişkende bir hiper-düzlem) olduğunu varsaydığı anlamına gelir. Eğer verinizdeki sınıflar arasında karmaşık, doğrusal olmayan ilişkiler varsa (örneğin, iç içe geçmiş halkalar gibi), Lojistik Regresyon bu ilişkileri yakalamakta başarısız olacaktır.

-Bağımsız Değişkenler Arasında İlişki Olmaması Beklentisi: Model, bağımsız değişkenler arasında yüksek korelasyon (yani çoklu doğrusallık - multicollinearity) olmamasını tercih eder. Yüksek korelasyon, katsayı tahminlerini istikrarsızlaştırabilir ve yorumlanmasını zorlaştırabilir.

-Aşırı Uyuma (Overfitting) Eğilimi: Özellikle çok sayıda bağımsız değişkenin olduğu ancak gözlem sayısının az olduğu durumlarda, Lojistik Regresyon da diğer modeller gibi aşırı uyuma (overfitting) eğilimi gösterebilir. Bu, modelin eğitim verisini “ezberleyip” yeni verilerde kötü performans göstermesi anlamına gelir. (Bu durumu engellemek için regülarizasyon gibi ileri teknikler mevcuttur).

-Kapsamlı Özellik Mühendisliği Gerektirebilir: Modelin doğrusal yapısı nedeniyle, karmaşık ilişkileri yakalamak için genellikle manuel olarak özellik mühendisliği (feature engineering) yapmanız gerekir. Örneğin, değişkenlerin etkileşimlerini (x1 * x2) veya polinom terimlerini (x1^2) modele elle eklemeniz gerekebilir.

Akademik Referans: Lojistik Regresyon’un temel varsayımları ve bu varsayımların ihlal edilmesi durumunda ortaya çıkabilecek sorunlar hakkında derinlemesine bir analiz için Hosmer & Lemeshow (2000) klasik bir kaynaktır.

Lojistik Regresyon ile Karar Vermenin Gücü

Sevgili “Veri Mimarı” dostlarım,

“Machine Learning Academy”deki bu yolculuğumuzda, sayısal tahminlerin dünyasından çıkıp kategorik kararların kritik dünyasına, Lojistik Regresyon ile güçlü bir adım attık.

Lineer Regresyon’un olasılık tahminindeki yetersizliklerinden yola çıkarak başladık. Kalbinde yatan zarif Sigmoid fonksiyonu ile tanıştık ve bu “S” şeklindeki eğrinin, lineer bir denklemin çıktısını nasıl anlamlı bir olasılığa dönüştürdüğünü gördük. Modelin parametrelerini Maksimum Olabilirlik Tahmini (MLE) gibi güçlü bir istatistiksel prensiple nasıl “öğrendiğini” anladık.

En önemlisi, bu modelin bir “siyah kutu” olmadığını keşfettik. Odds Ratio’lar aracılığıyla katsayıları yorumlayarak, bağımsız değişkenlerin sonuç üzerindeki etkisini “bir saat daha fazla çalışmak, geçme odds’unu X kat artırır” gibi sezgisel ve güçlü çıkarımlara dönüştürebildik. Son olarak, Karışıklık Matrisi, AUC gibi metriklerle modelimizin başarısını objektif bir şekilde ölçmeyi öğrendik.

Lojistik Regresyon, yorumlanabilirliği, hızı ve basitliği sayesinde, özellikle tıp, finans ve sosyal bilimler gibi “neden” sorusunun “ne” sorusu kadar önemli olduğu alanlarda vazgeçilmez bir araçtır. Karmaşık modeller için mükemmel bir başlangıç noktası ve çoğu zaman şaşırtıcı derecede güçlü bir çözümdür.

Artık teorik temellerimizi tamamladığımıza göre, bu bilgiyi alıp gerçek bir probleme uygulama zamanı. Bir sonraki bölümde, ISLR::Default veri setini kullanarak bir müşterinin kredi kartı borcunu ödeyip ödeyemeyeceğini tahmin edecek, baştan sona bir Lojistik Regresyon projesi inşa edeceğiz.

Hazırsanız, Veri Mimarı şapkalarımızı takalım ve konumuzu pekişterecek bir çalışma yapalım.

Bölüm 8.5: Pratik Uygulama: ISLR::Default Veri Seti ile Müşteri Temerrüt Riski Tahmini

Sevgili Dostlar,

Lojistik Regresyon’un teorik derinliklerinde yaptığımız yolculuğu tamamladık. Şimdi, bu bilgileri alıp gerçek bir probleme uygulama zamanı. Bu bölümde, bir bankanın karşılaştığı en temel sorulardan birini modelleyeceğiz: “Bir müşterinin kredi kartı borcunu ödemeyip temerrüde düşme olasılığı nedir?”

Bu soruyu yanıtlamak için, “An Introduction to Statistical Learning” kitabının R paketi olan ISLR içinde yer alan meşhur Default veri setini kullanacağız (James, Witten, Hastie, & Tibshirani, 2008). Bu veri seti, temiz yapısı ve anlaşılır değişkenleri ile Lojistik Regresyon’u öğrenmek için mükemmel bir örnektir.

Adım 1: Kurulum ve Veriyi Keşfetme

İlk olarak, gerekli paketleri yükleyip kütüphanemize çağıralım ve veri setimize ilk bakışı atalım.

(Not: Gerekli paketler (ISLR, dplyr, caret, pROC) yüklü değilse, önce install.packages(“paket_adi”) komutu ile yüklemeniz gerekir.)

# Gerekli paketleri yükleyelim
library(ISLR)       # Default veri seti için
library(dplyr)      # Veri manipülasyonu için
## 
## Attaching package: 'dplyr'
## The following objects are masked from 'package:stats':
## 
##     filter, lag
## The following objects are masked from 'package:base':
## 
##     intersect, setdiff, setequal, union
library(caret)      # Confusion Matrix için
library(pROC)       # ROC/AUC için

# Veri setini çalışma alanına yükleyelim
data("Default")

# Veri setinin yapısını inceleyelim
str(Default)
## 'data.frame':    10000 obs. of  4 variables:
##  $ default: Factor w/ 2 levels "No","Yes": 1 1 1 1 1 1 1 1 1 1 ...
##  $ student: Factor w/ 2 levels "No","Yes": 1 2 1 1 1 2 1 2 1 1 ...
##  $ balance: num  730 817 1074 529 786 ...
##  $ income : num  44362 12106 31767 35704 38463 ...
# Veri setinin özet istatistiklerine bakalım
summary(Default)
##  default    student       balance           income     
##  No :9667   No :7056   Min.   :   0.0   Min.   :  772  
##  Yes: 333   Yes:2944   1st Qu.: 481.7   1st Qu.:21340  
##                        Median : 823.6   Median :34553  
##                        Mean   : 835.4   Mean   :33517  
##                        3rd Qu.:1166.3   3rd Qu.:43808  
##                        Max.   :2654.3   Max.   :73554

Veri Seti Yorumu:

Veri setimiz 10,000 gözlem ve 4 değişkenden oluşuyor.

-default: Bağımlı değişkenimiz. Müşterinin temerrüde düşüp düşmediğini gösteren bir faktör (“No”, “Yes”).

-student: Bağımsız değişken. Müşterinin öğrenci olup olmadığını gösteren bir faktör (“No”, “Yes”).

-balance: Bağımsız değişken. Müşterinin aylık ortalama kart bakiyesi.

-income: Bağımsız değişken. Müşterinin yıllık geliri.

summary() çıktısında, temerrüde düşenlerin (“Yes”: 333) düşmeyenlere (“No”: 9667) göre çok daha az olduğunu görüyoruz. Bu, dengesiz (imbalanced) bir veri setidir ve model değerlendirme aşamasında Accuracy metriğine neden dikkatle yaklaşmamız gerektiğini bize şimdiden söylüyor.

Adım 2: Modeli Oluşturma

Şimdi, glm() fonksiyonunu kullanarak Lojistik Regresyon modelimizi kuralım. default durumunu, diğer tüm değişkenleri (student, balance, income) kullanarak tahmin etmeye çalışacağız.

# Lojistik Regresyon modelini kuralım
# formül: default ~ .  (default'u diğer tüm değişkenlere göre modelle)
model_default <- glm(default ~ ., data = Default, family = "binomial")

# Modelin özetini görüntüleyelim
summary(model_default)
## 
## Call:
## glm(formula = default ~ ., family = "binomial", data = Default)
## 
## Coefficients:
##               Estimate Std. Error z value Pr(>|z|)    
## (Intercept) -1.087e+01  4.923e-01 -22.080  < 2e-16 ***
## studentYes  -6.468e-01  2.363e-01  -2.738  0.00619 ** 
## balance      5.737e-03  2.319e-04  24.738  < 2e-16 ***
## income       3.033e-06  8.203e-06   0.370  0.71152    
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## (Dispersion parameter for binomial family taken to be 1)
## 
##     Null deviance: 2920.6  on 9999  degrees of freedom
## Residual deviance: 1571.5  on 9996  degrees of freedom
## AIC: 1579.5
## 
## Number of Fisher Scoring iterations: 8

Adım 3.1: Modeli Yorumlama

summary() çıktısı, modelimizin kalbini oluşturur. Şimdi bu çıktıyı adım adım yorumlayalım.

Katsayılar (Coefficients) Yorumu:

balance ve studentYes değişkenlerinin p-değerleri (Pr(>|z|)) çok küçüktür (genellikle < 2e-16). Bu, her iki değişkenin de temerrüt olasılığı üzerinde istatistiksel olarak anlamlı bir etkiye sahip olduğunu gösterir.

income değişkeninin p-değeri ise daha büyüktür (örn: ~0.71). Bu da, bakiye ve öğrenci durumu kontrol edildiğinde, gelirin tek başına anlamlı bir belirleyici olmadığını düşündürür.

balance’ın katsayısı pozitiftir. Bu, kart bakiyesi arttıkça, temerrüde düşme log-odds’unun da arttığı anlamına gelir. Bu son derece mantıklı bir bulgudur.

Odds Ratios Yorumu:

Bölüm 8.4.6’da öğrendiğimiz gibi, şimdi bu katsayıları exp() ile Odds Ratio’lara çevirerek daha sezgisel yorumlar yapalım.

# Katsayıları Odds Ratio'lara çevirelim
exp(coef(model_default))
##  (Intercept)   studentYes      balance       income 
## 1.903854e-05 5.237317e-01 1.005753e+00 1.000003e+00
# Odds Ratio'lar için %95 güven aralıklarına da bakalım
exp(confint(model_default))
## Waiting for profiling to be done...
##                    2.5 %       97.5 %
## (Intercept) 7.074481e-06 0.0000487808
## studentYes  3.298827e-01 0.8334223982
## balance     1.005309e+00 1.0062238757
## income      9.999870e-01 1.0000191246

Odds Ratio Çıktı Yorumu:

-balance:

balance için %95 güven aralığı (1.0053, 1.0062)’dir.

Anlamı: Biz %95 eminiz ki, bakiyedeki her 1 dolarlık artışın temerrüde düşme odds’u üzerindeki gerçek çarpım etkisi 1.0053 ile 1.0062 arasındadır.

Sonuç: Bu aralık 1’i içermediği için, bakiyenin temerrüt riski üzerinde istatistiksel olarak anlamlı ve pozitif bir etkisi olduğunu güçlü bir şekilde teyit ediyoruz.

-studentYes:

studentYes için %95 güven aralığı (0.33, 0.83)’tür.

Anlamı: Bakiye ve gelir sabitken, öğrenci olmanın temerrüde düşme odds’u üzerindeki gerçek çarpım etkisinin 0.33 ile 0.83 arasında olduğundan %95 eminiz. Yani, öğrenci olmak odds’u en az %17, en çok %67 oranında düşürmektedir.

Peki, %17 ve %67 sayılarına nasıl ulaştık?

Veri Mimarı Notu: Odds Ratio’dan Yüzdesel Değişime Nasıl Geçilir?

Bir Odds Ratio’nun (OR) yüzde olarak ne kadar artış veya azalışa denk geldiğini bulmak için şu basit formülü kullanırız:

Yüzdesel Değişim = (OR - 1) * 100

Bu formül, etkinin “1” (etkisizlik noktası) etrafında ne kadar değiştiğini bize söyler. Şimdi bu formülü güven aralığımızın sınırlarına uygulayalım:

Alt Sınır (OR = 0.33):

(0.33 - 1) * 100 = -67%. Bu, odds’larda en fazla %67’lik bir azalış anlamına gelir.

Üst Sınır (OR = 0.83):

(0.83 - 1) * 100 = -17%. Bu da odds’larda en az %17’lik bir azalış anlamına gelir.

Anlamı: Yukarıdaki hesaba dayanarak, bakiye ve gelir sabitken, öğrenci olmanın temerrüde düşme odds’u üzerindeki gerçek çarpım etkisinin 0.33 ile 0.83 arasında olduğundan %95 eminiz. Diğer bir deyişle, öğrenci olmak odds’u en az %17, en çok %67 oranında düşürmektedir.

Sonuç: Bu aralık da 1’i içermediğinden, öğrenci olmanın (diğer değişkenler sabitken) temerrüt riski üzerinde istatistiksel olarak anlamlı ve negatif bir etkisi olduğunu görüyoruz.

-income:

income için %95 güven aralığı (0.999987, 1.000019)’dur.

Anlamı: Gelirdeki her 1 dolarlık artışın odds üzerindeki çarpım etkisinin bu aralıkta olmasından %95 eminiz.

Sonuç: Bu güven aralığı 1 değerini içerdiği için, modelimizdeki diğer değişkenler (özellikle balance) kontrol edildiğinde, gelirin temerrüt riski üzerinde istatistiksel olarak anlamlı bir etkisi olmadığı sonucuna varıyoruz. Bu bulgu, daha önce summary() çıktısında gördüğümüz yüksek p-değerini de mükemmel bir şekilde doğrulamaktadır.

Adım 3.2: Modelin Görselleştirilmesi

Sayısal sonuçları yorumladıktan sonra, modelimizin ne öğrendiğini görsel olarak teyit etmek son derece aydınlatıcıdır. Modelimizin en güçlü belirleyicisi olan balance (bakiye) değişkenine karşı temerrüt olasılığını bir Sigmoid eğrisi olarak çizdirelim. Ayrıca, student (öğrenci) olmanın bu ilişkiyi nasıl etkilediğini de aynı grafikte gösterelim.

# 1. Tahminler için pürüzsüz bir veri çerçevesi oluşturalım.
#    'balance' için min'den max'a bir dizi değer oluşturuyoruz.
#    'income'ı ortalama değerinde sabit tutuyoruz.
#    'student' için hem "Yes" hem de "No" durumlarını hazırlıyoruz.
balance_range <- range(Default$balance)
new_data_grid <- expand.grid(
  balance = seq(balance_range[1], balance_range[2], length.out = 200),
  income = mean(Default$income),
  student = c("Yes", "No")
)

# 2. Bu yeni veri çerçevesi için olasılıkları tahmin edelim.
new_data_grid$predicted_prob <- predict(model_default, newdata = new_data_grid, type = "response")

# 3. Grafiği oluşturalım
ggplot(Default, aes(x = balance, y = as.numeric(default) - 1)) +
  # Gerçek veri noktalarını gösterelim. Jitter, noktaların yığılmasını engeller.
  geom_jitter(aes(color = default), width = 0, height = 0.05, alpha = 0.1) +
  
  # Modelin tahmin ettiği Sigmoid eğrilerini (öğrenciler ve olmayanlar için ayrı ayrı) çizelim.
  geom_line(data = new_data_grid, aes(y = predicted_prob, linetype = student), color = "darkblue", size = 1) +
  
  labs(
    title = "Kredi Kartı Bakiyesine Göre Temerrüt Olasılığı",
    x = "Aylık Ortalama Bakiye ($)",
    y = "Temerrüt Olasılığı",
    color = "Gerçek Durum",
    linetype = "Müşteri Tipi"
  ) +
  scale_y_continuous(breaks = c(0, 0.5, 1), labels = c("0 (Temerrüt Yok)", "0.5 (Eşik)", "1 (Temerrüt Var)")) +
  scale_color_manual(values = c("No" = "darkorange", "Yes" = "midnightblue")) +
  theme_minimal() +
  guides(color = guide_legend(override.aes = list(alpha = 1))) # Lejanttaki noktaları görünür yap

Görselleştirme Yorumu:

Bu grafik, modelimizin tüm sayısal çıktılarını tek bir karede özetliyor:

-Genel Trend: Beklendiği gibi, balance (bakiye) arttıkça, temerrüde düşme olasılığı da keskin bir “S” eğrisi çizerek artıyor. Düşük bakiyelerde olasılık sıfıra yakınken, yüksek bakiyelerde bire yaklaşıyor.

Öğrenci Etkisi (İki Ayrı Çizgi): Grafikte iki adet mavi Sigmoid eğrisi görüyoruz. Lejantta belirtildiği gibi:

Düz Çizgi: Öğrenciler (student = “Yes”) için temerrüt olasılığını gösterir.

Kesikli Çizgi: Öğrenci Olmayanlar (student = “No”) için temerrüt olasılığını gösterir.

En Önemli Çıkarım: Grafiği dikkatlice incelediğimizde, aynı bakiye seviyesinde, öğrenciler için olan düz çizginin, öğrenci olmayanlar için olan kesikli çizginin her zaman daha aşağısında olduğunu görüyoruz. Bu, Odds Ratio yorumumuzu görsel olarak %100 doğrulamaktadır: Bakiye ve gelir sabitken, öğrenciler gerçekten de daha düşük bir temerrüt riskine sahiptir.

Gerçek Verinin Dağılımı: Arka plandaki soluk turuncu (No) ve mavi (Yes) noktalar, gerçek veri setimizdeki 10,000 müşteriyi temsil eder. geom_jitter kullandığımız için, noktaların y=0 ve y=1 çizgileri etrafında ne kadar yoğunlaştığını görebiliriz. Temerrüde düşenlerin (y=1’deki mavi noktalar) genellikle daha yüksek bakiyelere sahip olduğu açıkça görülmektedir.

Bu görselleştirme, modelimizin sadece istatistiksel olarak anlamlı değil, aynı zamanda mantıklı ve yorumlanabilir bir ilişki öğrendiğinin en güçlü kanıtıdır.

Adım 4: Modeli Değerlendirme

Modelimiz anlamlı sonuçlar üretiyor gibi görünüyor. Peki, tahminleri ne kadar isabetli?

Karışıklık Matrisi (Confusion Matrix):

Önce modelin olasılık tahminlerini alalım, sonra 0.5 eşiği ile bunları “Yes”/“No” sınıflarına atayalım ve bir Karışıklık Matrisi oluşturalım.

# 1. Olasılıkları tahmin et
predicted_probs <- predict(model_default, type = "response")

# 2. 0.5 eşiğine göre sınıflandırma yap
predicted_class <- ifelse(predicted_probs > 0.5, "Yes", "No")
predicted_class <- as.factor(predicted_class)

# 3. Karışıklık Matrisi oluştur
#    Pozitif sınıfımız "Yes" (temerrüde düşenler)
confusionMatrix(data = predicted_class, reference = Default$default, positive = "Yes")
## Confusion Matrix and Statistics
## 
##           Reference
## Prediction   No  Yes
##        No  9627  228
##        Yes   40  105
##                                           
##                Accuracy : 0.9732          
##                  95% CI : (0.9698, 0.9763)
##     No Information Rate : 0.9667          
##     P-Value [Acc > NIR] : 0.0001044       
##                                           
##                   Kappa : 0.4278          
##                                           
##  Mcnemar's Test P-Value : < 2.2e-16       
##                                           
##             Sensitivity : 0.3153          
##             Specificity : 0.9959          
##          Pos Pred Value : 0.7241          
##          Neg Pred Value : 0.9769          
##              Prevalence : 0.0333          
##          Detection Rate : 0.0105          
##    Detection Prevalence : 0.0145          
##       Balanced Accuracy : 0.6556          
##                                           
##        'Positive' Class : Yes             
## 

Confusion Matrix Yorumu:

Yukarıdaki kodun çıktısı bize hem karışıklık matrisini hem de bir dizi önemli metriği verir. Şimdi bu gerçek değerleri yorumlayalım:

-Accuracy (0.9732 veya ~%97.3): Model genel olarak vakaların %97.3’ünde doğru tahmin yapıyor. Ama veri setimiz dengesiz olduğu için bu metrik tek başına yeterli değil ve hatta yanıltıcı olabilir! Nedenini diğer metrikler gösterecek.

-Sensitivity (Recall) (0.3153 veya ~%31.5): Bu, bu problemdeki en kritik metriktir! “Gerçekte temerrüde düşenlerin (Reference: Yes) yüzde kaçını yakalayabildik (Prediction: Yes)?” sorusunu cevaplar. %31.5 değeri son derece düşüktür.

Sayısal Anlamı: Matrise bakarsak, gerçekte temerrüde düşen toplam 333 kişi (228 FN + 105 TP) var. Modelimiz bunlardan sadece 105’ini doğru bir şekilde “temerrüt” olarak etiketleyebilmiş, ancak 228 tanesini “temerrüt etmeyecek” diyerek gözden kaçırmıştır!

-Specificity (0.9959 veya ~%99.6): “Gerçekte temerrüde düşmeyenlerin (Reference: No) yüzde kaçını doğru bildik (Prediction: No)?” sorusunu cevaplar. Bu değerin çok yüksek olması, modelimizin temerrüde düşmeyenleri tanımakta mükemmel olduğunu gösterir. Zaten Accuracy’nin yüksek çıkmasının sebebi de budur.

-Precision (Pos Pred Value) (0.7241 veya ~%72.4): “Modelimiz ‘temerrüt’ (Prediction: Yes) dediğinde ne kadar haklı?” sorusunu cevaplar. Yani, modelin “riskli” olarak işaretlediği müşterilerin yaklaşık %72.4’ü gerçekten de risklidir.

Sonuç: Modelimiz temerrüde düşmeyenleri çok iyi tanıyor, ancak asıl hedefimiz olan temerrüde düşenleri büyük ölçüde gözden kaçırıyor. Bir banka için, riskli müşterilerin üçte ikisinden fazlasını (228 / 333) tespit edemeyen bir model, pratik olarak kabul edilemez bir risktir. Bu durum, bir sonraki adımda göreceğimiz gibi, modelin kendisinin kötü olmasından çok, bizim seçtiğimiz 0.5’lik eşik değerinin bu problem için yanlış olduğunu göstermektedir.

ROC Eğrisi ve AUC:

Modelin genel ayrım gücünü eşikten bağımsız olarak ölçelim.

# ROC nesnesini oluşturalım
roc_obj <- roc(response = Default$default, predictor = predicted_probs)
## Setting levels: control = No, case = Yes
## Setting direction: controls < cases
# ROC eğrisini çizelim ve AUC değerini yazdıralım
plot(roc_obj, main = "ROC Curve for Default Model", print.auc = TRUE)

AUC Yorumu:

AUC değeri çok yüksek çıkacaktır (örn: ~0.95). Bu, karışıklık matrisindeki düşük Sensitivity ile çelişiyor gibi görünebilir. Anlamı şudur:

Modelimizin ayrım gücü (yani bir temerrütçüye, temerrüt etmeyenden daha yüksek bir olasılık atama yeteneği) mükemmele yakındır.

Sorun modelin kendisinde değil, bizim seçtiğimiz 0.5’lik eşik değerindedir. Düşük Sensitivity problemini çözmek için bu eşiği düşürmemiz gerekir.

Genel Sonuç

Bu pratik uygulama bize Lojistik Regresyon’un tüm adımlarını göstermekle kalmadı, aynı zamanda “Veri Mimarı” olarak kritik düşünmenin önemini de vurguladı:

  • Lojistik Regresyon, değişkenlerin etkisini yorumlamak için harika bir araçtır.

  • Accuracy gibi tek bir metriğe asla güvenmemeliyiz, özellikle dengesiz verilerde.

  • Modelin olasılıklarını ve problemin bağlamını anlayarak, Sensitivity ve Specificity arasında doğru dengeyi kuracak eşik değerini ayarlamak, modelin pratik değerini belirleyen en önemli adımdır.

Adım 5: Eşik Değerini Optimize Etme (Teoriden Pratiğe)

Önceki adımda kritik bir sorun tespit ettik: Modelimizin AUC değeri çok yüksek olmasına rağmen, 0.5’lik standart eşik değeriyle Sensitivity (temerrüt edenleri yakalama oranı) kabul edilemez derecede düşüktü. Bu, modelin kötü olduğu anlamına gelmez; sadece bizim karar kuralımızın iş hedefimizle (riskli müşterileri tespit etmek) uyumsuz olduğu anlamına gelir.

Peki, en “iyi” eşik değerini nasıl bulabiliriz? Cevap, “en iyi”nin ne anlama geldiğine bağlıdır. Genellikle Sensitivity ve Specificity arasında bir denge kurmaya çalışırız. pROC paketi, bu dengeyi bulmak için bize harika araçlar sunar.

ROC eğrisi üzerinde, Sensitivity ve Specificity’nin toplamını maksimize eden noktayı “en uygun” eşik olarak seçebiliriz.

# roc_obj nesnemiz zaten bir önceki adımdan mevcut

# En uygun eşiği bulalım
# coords() fonksiyonu, ROC eğrisi üzerindeki tüm eşik ve metrik değerlerini verir
# "best" metodu, Sensitivity ve Specificity'nin toplamını maksimize eden noktayı bulur
best_threshold <- coords(roc_obj, "best", ret = "threshold")

# Bulunan en iyi eşik değerini yazdıralım
print(paste("En Uygun Eşik Değeri:", best_threshold$threshold))
## [1] "En Uygun Eşik Değeri: 0.0312087564288532"
# Şimdi bu YENİ eşik değeri ile sınıflandırmayı tekrar yapalım
yeni_predicted_class <- ifelse(predicted_probs > best_threshold$threshold, "Yes", "No")
yeni_predicted_class <- as.factor(yeni_predicted_class)

# YENİ karışıklık matrisini oluşturalım
confusionMatrix(data = yeni_predicted_class, reference = Default$default, positive = "Yes")
## Confusion Matrix and Statistics
## 
##           Reference
## Prediction   No  Yes
##        No  8325   32
##        Yes 1342  301
##                                           
##                Accuracy : 0.8626          
##                  95% CI : (0.8557, 0.8693)
##     No Information Rate : 0.9667          
##     P-Value [Acc > NIR] : 1               
##                                           
##                   Kappa : 0.2639          
##                                           
##  Mcnemar's Test P-Value : <2e-16          
##                                           
##             Sensitivity : 0.9039          
##             Specificity : 0.8612          
##          Pos Pred Value : 0.1832          
##          Neg Pred Value : 0.9962          
##              Prevalence : 0.0333          
##          Detection Rate : 0.0301          
##    Detection Prevalence : 0.1643          
##       Balanced Accuracy : 0.8825          
##                                           
##        'Positive' Class : Yes             
## 

Yeni Sonuçların Yorumlanması:

Yukarıdaki kod, ROC eğrisi üzerinde Sensitivity ve Specificity’nin toplamını maksimize eden noktanın eşik değerinin yaklaşık 0.031 olduğunu gösterdi. Bu, standart 0.5 değerinden çok çok daha düşük bir eşiktir. Bu yeni ve optimize edilmiş eşik değeriyle oluşturduğumuz ikinci Karışıklık Matrisi’ni ilk matrisle karşılaştırdığımızda gördüğümüz tablo, modelimizin gerçek gücünü ortaya koyuyor:

-Sensitivity (Recall) (0.9039 veya ~%90.4): Dramatik bir şekilde arttı! 0.5 eşiği ile sadece %31.5’ini yakalayabildiğimiz riskli müşterilerin, şimdi %90.4’ünü doğru bir şekilde tespit edebiliyoruz.

Sayısal Anlamı: Matrise bakarsak, gerçekte temerrüde düşen 333 kişiden (32 FN + 301 TP) artık 301 tanesini doğru tahmin ediyoruz. Kaçırdığımız riskli müşteri sayısı 228’den sadece 32’ye düştü!

-Specificity (0.8612 veya ~%86.1): Beklendiği gibi düştü. Riskli müşterileri daha iyi yakalamak uğruna, artık daha fazla sayıda “temiz” müşteriyi yanlışlıkla “riskli” olarak etiketliyoruz. Yanlış alarm (False Positive) sayısı 40’tan 1342’ye yükseldi. Bu, yaptığımız takasın bedelidir.

-Accuracy (0.8626 veya ~%86.3): Genel doğruluk oranı, Specificity’deki düşüş nedeniyle %97.3’ten %86.3’e düştü. Ama bu problemde Accuracy’nin bizim için en önemli metrik olmadığını artık biliyoruz.

Nihai Karar ve İş Çıkarımı

Bu son adım bize, bir makine öğrenmesi modelinin değerinin, sadece istatistiksel çıktılarından değil, bu çıktıların iş hedeflerine uygun bir karar kuralına dönüştürülmesinden geldiğini kanıtladı.

Standart 0.5 eşiği ile başladık ve bu kuralın “riskli müşterileri kaçırmamak” olan ana hedefimize hizmet etmediğini gördük. ROC eğrisini kullanarak eşiğimizi 0.031’e optimize ettiğimizde, Specificity’den bir miktar feragat ederek (yani daha fazla yanlış alarmı ve dolayısıyla bu müşterileri inceleme maliyetini göze alarak), Sensitivity’yi (risk yakalama oranını) banka için kabul edilebilir ve güçlü bir seviyeye çıkardık.

Bir “Veri Mimarı” olarak, bu dengeyi kurmak ve iş birimlerine şu şekilde bir sunum yapmak bizim görevimizdir:

“Geliştirdiğimiz Lojistik Regresyon modeli, riskli müşterileri tespit etmede çok başarılı. Eğer karar eşiğimizi %3.1 olarak belirlersek, temerrüde düşecek müşterilerin %90’ından fazlasını önceden yakalayabiliriz. Bunun karşılığında, aslında borcunu ödeyecek olan müşterilerin yaklaşık %14’ünü de (1 - Specificity) yanlışlıkla ‘riskli’ olarak işaretlemiş olacağız. Bu grubun ek bir incelemeden geçirilmesi gerekecektir. Bu iş riski ve operasyonel maliyet dengesi, kurumumuz için kabul edilebilir mi?”

Bu son analizle, Lojistik Regresyon bölümünü sadece bir algoritmayı anlatarak değil, aynı zamanda gerçek bir iş problemine nasıl çözüm odaklı yaklaşıldığını göstererek tamamlamış oluyoruz.

Derinlemesine Bakış: Lojistik Regresyon’un Perde Arkası: Optimizasyon

Sevgili Dostlar,

Bu bölümde, R’a glm() komutunu verdiğimizde, bilgisayarın o sihirli katsayıları bulmak için perde arkasında hangi karmaşık matematiksel dansı yaptığını inceleyeceğiz. Bu, Lojistik Regresyon’u bir “kara kutu” olmaktan tamamen çıkaracak ileri düzey bir konudur.

Zirveyi Bulmak

Bölüm 8.4.4’te, Lojistik Regresyon’un Maksimum Olabilirlik Tahmini (MLE) prensibiyle çalıştığını öğrendik. Bu, matematiksel olarak, Log-Olabilirlik Fonksiyonu adını verdiğimiz çok boyutlu bir “dağın” en tepe noktasını bulmak anlamına gelir.

Eğer bu fonksiyon basit olsaydı, türevini alıp sıfıra eşitleyerek zirveyi kalemle kağıtla bulabilirdik. Ancak Lojistik Regresyon’un Log-Olabilirlik fonksiyonu bunun için fazla karmaşıktır. Bu yüzden bilgisayarlar, zirveye adım adım tırmanan akıllı optimizasyon algoritmaları kullanır.

R’ın Çözümü: Newton-Raphson ve IRLS

R’daki glm() fonksiyonunun kullandığı temel algoritma, Newton-Raphson (NR) yönteminin çok şık bir uygulamasıdır.

Newton-Raphson Sezgisel Anlatımı:

Dağın zirvesine tırmandığınızı hayal edin. Herhangi bir noktada durduğunuzda, zirveye en hızlı nasıl gideceğinizi bulmak için iki bilgiye ihtiyacınız vardır:

-Yolun Eğimi (Gradyan - Birinci Türev): Şu an hangi yöne doğru en dik yokuş var?

-Yolun Kavisi (Hessian - İkinci Türev): Bu yokuş ileride daha da dikleşiyor mu, yoksa düzleşiyor mu? Newton-Raphson, bu iki bilgiyi de (eğim ve kavis) kullanarak, bir sonraki adımda tam olarak nereye basması gerektiğini hesaplayan süper-akıllı bir dağcı gibidir. Bu sayede zirveye çok hızlı bir şekilde (kuadratik yakınsama ile) ulaşır.

IRLS (Iteratively Reweighted Least Squares):

Lojistik Regresyon için Newton-Raphson algoritması, Yinelemeli Olarak Yeniden Ağırlıklandırılmış En Küçük Kareler (IRLS) adı verilen bir yönteme dönüşür. Bu ismin her bir kelimesi aslında süreci anlatır:

-Yinelemeli (Iterative): Algoritma, zirveye ulaşana kadar tekrar tekrar adımlar atar.

Yeniden Ağırlıklandırılmış (Reweighted): Her adımda, gözlemlere modelin o anki tahminlerine göre farklı “ağırlıklar” verilir. İşte burası, algoritmanın en karşı-sezgisel ama en zeki kısmıdır:

IRLS algoritmasındaki ağırlıklar, ağırlık = p * (1 - p) formülüyle hesaplanır; burada p modelin tahmin ettiği olasılıktır. Bu formül, olasılık 0.5’e yaklaştıkça maksimum değerini alır.

Anlamı: Algoritma, modelin en “kararsız” olduğu, yani tahminin 0.5’e yakın olduğu sınır çizgisine en yakın gözlemlere en yüksek ağırlığı verir. Sezgisel olarak bunun nedeni, karar sınırının en doğru yere yerleştirilmesi için en fazla bilginin bu “bıçak sırtı” noktalardan gelmesidir. Modelin zaten emin olduğu (p’nin 0 veya 1’e yakın olduğu) noktalar, sınırın yerini belirlemede daha az rol oynar.

-En Küçük Kareler (Least Squares): Her adımda, aslında Lineer Regresyon’dakine çok benzeyen “ağırlıklandırılmış” bir en küçük kareler problemini çözer. Yani glm(), her adımda akıllıca ağırlıklar atayarak bir dizi mini-Lineer Regresyon problemi çözerek Lojistik Regresyon’un zirvesine tırmanır.

Alternatif Yaklaşım: Quasi-Newton (BFGS)

Newton-Raphson çok hızlı olsa da, o “kavis” bilgisini (Hessian matrisi) hesaplamak, özellikle yüzlerce veya binlerce değişken olduğunda çok maliyetli olabilir.

İşte bu noktada Quasi-Newton (Yarı-Newton) yöntemleri devreye girer. Bu yöntemlerin en ünlüsü BFGS’tir.

-Temel Fikri: Hessian matrisini her adımda tam olarak hesaplamak yerine, bir önceki adımdaki eğim bilgilerini kullanarak onu akıllıca “tahmin etmeye” çalışır.

Bu yaklaşım, hız ve hesaplama maliyeti arasında mükemmel bir denge kurar. Bu yüzden Python’daki scikit-learn gibi birçok modern makine öğrenmesi kütüphanesinde, Lojistik Regresyon için varsayılan çözücü (solver) genellikle lbfgs’tir (BFGS’nin bellek-verimli bir versiyonu).

Bu Teknik Detaylar Neden Önemli?

-“Convergence Error” (Yakınsama Hatası): Bazen modeliniz eğitilirken bu hata ile karşılaşırsınız. Bu, algoritmanın dağın zirvesini bulamadığı anlamına gelir. Algoritmaların nasıl çalıştığını bilmek, bu hatanın nedenini (örneğin, verideki ayrışma problemleri) anlamanıza ve çözmenize yardımcı olur.

-Bilinçli Araç Seçimi: Farklı kütüphaneler size farklı solver (çözücü) seçenekleri sunduğunda, artık rastgele seçim yapmazsınız. Veri setinizin büyüklüğüne ve değişken sayısına göre Newton-Raphson tabanlı bir çözücünün mü yoksa BFGS gibi bir Quasi-Newton yönteminin mi daha verimli olacağına dair bilinçli bir karar verebilirsiniz.

-Kara Kutunun Ötesi: Bu bilgi, sizi sadece bir kütüphane “kullanıcısı” olmaktan çıkarıp, araçlarının nasıl çalıştığını anlayan bir “uzman” konumuna yükseltir.

Bu derinlemesine bakışla, Lojistik Regresyon hakkındaki kapsamlı analizimizi tamamlamış bulunuyoruz. Artık bu temel ve güçlü modeli her yönüyle tanıyorsunuz.

Bir Veri Mimarının Araç Çantasındaki Yeni Güç

Sevgili Dostlar,

Lojistik Regresyon üzerine çıktığımız bu kapsamlı yolculuğun sonuna geldik. Birlikte, basit bir sınıflandırma algoritmasının ne kadar derin bir teorik temele ve ne kadar güçlü bir pratik değere sahip olabileceğini keşfettik.

Sadece bir .fit() komutunu çalıştırmanın ötesine geçtik. Lineer Regresyon’un neden yetersiz kaldığını anladık, Sigmoid fonksiyonu ile olasılık dünyasına adım attık ve Maksimum Olabilirlik Tahmini (MLE)’nin felsefesini kavradık. Bir modelin “kara kutu” olmadığını, Odds Ratio’lar aracılığıyla bize anlamlı hikayeler anlattığını gördük.

En önemlisi, bir modelin başarısının Accuracy gibi tek bir rakamdan ibaret olmadığını öğrendik. Karışıklık Matrisi’ni yorumlayarak, Sensitivity ve Specificity arasındaki kritik dengeyi anladık. Ve belki de en değerli dersimiz, modelin istatistiksel çıktısını alıp, iş hedefimize uygun optimum eşik değerini bularak onu gerçek bir iş çözümüne dönüştürmek oldu.

Artık sizler, sadece Lojistik Regresyon’u “kullanan” değil, aynı zamanda onu yorumlayan, eleştiren ve optimize eden birer “Veri Mimarı”sınız.

Peki, sırada ne var?

Şimdiye kadar, sınıfları ayırmak için matematiksel bir denklem kuran, “model tabanlı” bir yaklaşım öğrendik. Peki ya problem bu kadar net bir denklemle çözülemiyorsa? Ya sınıfları ayırmak için bir “çizgi” çekmek yerine, bir noktanın “komşularına” bakarak karar vermek daha mantıklıysa?

Bir sonraki bölümümüzde, makine öğrenmesinin bambaşka bir felsefesine sahip olan, son derece sezgisel ama bir o kadar da güçlü K-En Yakın Komşu (K-Nearest Neighbors - KNN) algoritmasını keşfe çıkacağız. Denklem kurmanın olmadığı, sadece “mesafe” ve “komşuluk” kavramlarının olduğu bu heyecan verici dünyaya hazır olun dostlar.

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

Kaynakça

Bu bölümü hazırlarken, istatistik ve makine öğrenmesi alanındaki birçok temel eserden ve R topluluğunun değerli katkılarından faydalandık. İşte bu yolculukta bize rehberlik eden ana kaynakların bir listesi:

  • Fisher, R. A. (1922). On the mathematical foundations of theoretical statistics. Philosophical Transactions of the Royal Society of London. Series A, Containing Papers of a Mathematical or Physical Character, 222(594-604), 309–368. (Maksimum Olabilirlik Tahmini’nin temelini atan klasik makale).

  • Hosmer, D. W., Jr., & Lemeshow, S. (2000). Applied logistic regression(2nd ed.). John Wiley & Sons. (Lojistik Regresyon üzerine yazılmış en kapsamlı ve standart başvuru kaynaklarından biri).

  • James, G., Witten, D., Hastie, T., & Tibshirani, R. (2008). An introduction to statistical learning: With applications in R. Springer. (Pratik uygulamamızda kullandığımız ISLR paketi ve Default veri setinin geldiği, modern makine öğrenmesinin temel kitabı).

  • Kuhn, M. (2008). Building predictive models in R using the caret package. Journal of Statistical Software, 28(5), 1–26. (Karışıklık Matrisi oluşturmak için kullandığımız caret paketinin temel makalesi. Max Kuhn, paketin yaratıcısıdır).

  • McFadden, D. (1974). Conditional logit analysis of qualitative choice behavior. In P. Zarembka (Ed.), Frontiers in econometrics (pp. 105–142). Academic Press. (Lojistik Regresyon’un arkasındaki “Gizli Fayda” ve Rastlantısal Fayda Teorisi’nin temelini atan, Nobel ödüllü çalışma).

  • Nelder, J. A., & Wedderburn, R. W. M. (1972). Generalized linear models. Journal of the Royal Statistical Society, Series A (General), 135(3), 370–384. (Lojistik Regresyon’u da içeren Genelleştirilmiş Lineer Modeller (GLM) ailesinin temelini atan çığır açıcı makale).

  • Robin, X., Turck, N., Hainard, A., Tiberti, N., Lisacek, F., Sanchez, J. C., & Müller, M. (2011). pROC: an open-source package for R and S+ to analyze and compare ROC curves. BMC Bioinformatics, 12, 77. (ROC eğrileri ve AUC analizi için kullandığımız pROC paketinin resmi akademik makalesi).

  • Venables, W. N., & Ripley, B. D. (2002). Modern applied statistics with S (4th ed.). Springer. (Çok Sınıflı Lojistik Regresyon için kullandığımız nnet paketinin arkasındaki temel başvuru kitabı).