BÖLÜM 1 : KARAR AĞAÇLARI

1. Karar Ağaçlarına Kavramsal Giriş

Merhaba Dostlar,

Giriş:

Karar ağaçları (Decision Trees), karmaşık veri setlerini basit karar kurallarına bölerek yönetilebilir parçalara ayıran, “böl ve yönet” (divide and conquer) stratejisiyle çalışan algoritmalardır. İnsan zihninin çalışma prensibine en yakın algoritma olarak kabul edilir.

Ekranda gördüğünüz bu sahnede, karakterimiz dışarı çıkmadan önce bir karar vermek zorunda: Şemsiye almalı mıyım?

Beynimiz (veya bu görseldeki akıllı asistan) bu kararı vermek için bir Karar Ağacı oluşturur:

-Kök Düğüm (Başlangıç): Veri toplanır. (Hava Durumu Bilgisi)

-Karar Düğümü (Sorgu): Hava yağmurlu mu?

-Yaprak Düğüm (Sonuç/Aksiyon): Şemsiyeyi yanına al!”

-Sonuç ve Bağlama:

İşte Karar Ağacı algoritması tam olarak budur: Büyük bir problemi (Ne yapmalıyım?), daha küçük ve yanıtlanabilir ‘Evet/Hayır’ sorularına bölerek en doğru sonuca ulaşmak.

Bu sorular silsilesi, veriyi hiyerarşik bir yapıda filtreler. Literatürde bu yapı iki ana algoritma tipiyle incelenir:

-ID3 (Iterative Dichotomiser 3): Çoklu dallanmaya izin verir (Örn: Hava durumu -> Güneşli, Bulutlu, Yağmurlu).

-CART (Classification and Regression Trees): Sadece ikili (binary) ayrımlar yapar. Her düğümden sadece iki dal çıkar (Evet/Hayır). R ve Python kütüphanelerinin çoğu (ve bu notlar) CART yapısını temel alır.

2. Sınıflandırma Ağaçları (Classification)

Sınıflandırma problemlerinde temel hedefimiz, elimizdeki veri kümesini öyle parçalara ayırmaktır ki, oluşan her yeni parça (yaprak), tek bir sınıfa ait örneklerden oluşsun. Biz buna Homojenlik (Saflık) diyoruz.

2.1. Örnek Veri Senaryosu: Kredi Onayı

Analizimizde kullanacağımız, 7 başvuranın Not Ortalaması (GPA) ve Mülakat Puanına göre Kredi Onayı alıp almadığını gösteren veri seti şöyledir:

library(tidyverse)
library(rpart)
library(rpart.plot)
library(kableExtra)
# Veri setinin oluşturulması
df_credit <- data.frame(
  ID = 1:7,
  GPA = factor(c("<3.0", "<3.0", "<3.0", ">3.0", ">3.0", ">3.0", "<3.0")),
  Interview = factor(c("Düşük", "Yüksek", "Yüksek", "Düşük", "Yüksek", "Normal", "Normal"), 
                     levels = c("Düşük", "Normal", "Yüksek")),
  Decision = factor(c("Red", "Onay", "Onay", "Red", "Onay", "Onay", "Red"))
)

# Tablonun şık bir şekilde gösterilmesi
df_credit %>%
  kbl(caption = "Tablo 1: Kredi Onay Veri Seti") %>%
  kable_styling(bootstrap_options = c("striped", "hover", "condensed"), full_width = F)
Tablo 1: Kredi Onay Veri Seti
ID GPA Interview Decision
1 <3.0 Düşük Red
2 <3.0 Yüksek Onay
3 <3.0 Yüksek Onay
4 >3.0 Düşük Red
5 >3.0 Yüksek Onay
6 >3.0 Normal Onay
7 <3.0 Normal Red

2.2. Kaosun Matematiği: Entropy ve Gini

Veri setindeki düzensizliği (kaosu) ölçmek için iki temel metrik kullanırız. Bir düğümde sınıflar ne kadar birbirine karışmışsa, matematiksel “kirlilik” o kadar yüksektir.

A. Entropy (Bilgi Düzensizliği)

Bilgi teorisinden (Information Theory) gelen bu kavram, sürprizi ölçer. Formülü şöyledir:

\[ H(S) = - \sum_{i=1}^{C} p_i \log_2(p_i) \] şeklinde ifade edilir.

Burada \(p_i\), ilgili sınıfın o düğümde bulunma olasılığıdır.

  • Saflık Durumu: Eğer bir küme tamamen safsa (örneğin hepsi “Onay”), ilgili olasılık \(p=1\) olur. Matematiksel olarak \(\log_2(1) = 0\) olduğundan, işlemin sonucu Entropy = 0 olur. Bu, hiç belirsizlik olmadığı anlamına gelir.

Mevcut Veri İçin Hesaplama:

Kök düğümde toplam 7 kişi bulunmaktadır: 4 Onay ve 3 Red. Bu oranları formülde yerine koyarsak:

\[ H(Root) = -\frac{4}{7}\log_2\left(\frac{4}{7}\right) - \frac{3}{7}\log_2\left(\frac{3}{7}\right) \approx 0.985 \]

# R ile Hesaplama Sağlaması
p_onay <- 4/7
p_red <- 3/7
entropy <- - (p_onay * log2(p_onay) + p_red * log2(p_red))

cat("Hesaplanan Entropi Değeri:", round(entropy, 3))
## Hesaplanan Entropi Değeri: 0.985

B. Gini Impurity (Kirlilik Ölçütü)

Entropy’ye güçlü bir alternatif olan Gini Impurity, hesaplama maliyeti daha düşük olduğu için (logaritma işlemi içermez) özellikle büyük veri setlerinde ve CART algoritmasında tercih edilir. Gini, rastgele seçilen bir örneğin, o kümedeki sınıf dağılımına göre yanlış etiketlenme olasılığını modeller.

Genel Formül: \[ G(S) = 1 - \sum_{i=1}^{C} p_i^2 \]

İki sınıflı durum için (Yes/No) özelleştirilmiş hali: \[ G(S) = 1 - (p_{Yes}^2 + p_{No}^2) \]

Mevcut Veri İçin Hesaplama (Kök Düğüm):

Veri setimizin kök düğümünde (Root) toplam 7 örnek bulunmaktadır. Dağılım şöyledir: 4 Onay (\(p_{Yes} = 4/7\)), 3 Red (\(p_{No} = 3/7\)).

Matematiksel dökümü şu şekildedir:

\[ G(Root) = 1 - \left( \left(\frac{4}{7}\right)^2 + \left(\frac{3}{7}\right)^2 \right) \]

\[ G(Root) = 1 - (0.3265 + 0.1836) \approx 0.4898 \]

Bunu R kod bloğu ile hesaplayarak doğrulayalım:

# 1. Olasılıkların Tanımlanması
toplam_gozlem <- 7
p_onay <- 4 / toplam_gozlem
p_red  <- 3 / toplam_gozlem

# 2. Gini Formülünün Uygulanması
gini_score <- 1 - (p_onay^2 + p_red^2)

# Sonucun Gösterilmesi
cat("Hesaplanan Gini Değeri:", round(gini_score, 4))
## Hesaplanan Gini Değeri: 0.4898

Not: Gini değeri 0 ile 0.5 arasında değişir (ikili sınıflandırma için).

-0: Küme tamamen saftır (Tüm örnekler aynı sınıftadır).

-0.5: Küme maksimum düzensizliğe sahiptir (Örnekler yarı yarıya dağılmıştır).

Bizim bulduğumuz 0.4898 değeri, kümenin oldukça karışık olduğunu ve bölünmeye (split) ihtiyaç duyduğunu gösterir.

2.3. En İyi Ayrımı Bulmak (Information Gain)

Algoritma karar verirken her bir değişkeni (GPA ve Mülakat Puanı) tek tek dener ve şu soruyu sorar: “Hangi soru belirsizliği (entropiyi) en çok düşürür?”

Buna Bilgi Kazancı (Information Gain) denir. Mantığı şudur: Ana kümenin entropisinden, bölünme sonrası oluşan alt kümelerin ağırlıklı entropisi çıkarılır.

Matematiksel formülü:

\[ Gain = H(S_{parent}) - \sum \frac{|S_{child}|}{|S_{parent}|} H(S_{child}) \]

Burada:

  • \(H(S_{parent})\): Bölünmeden önceki kaos (entropi).

  • \(H(S_{child})\): Bölünme sonrası oluşan alt kümelerin entropisi.

R ile Bilgi Kazancı Hesaplaması ve Karşılaştırma

Aşağıdaki R kodu ile veri setimizdeki iki aday değişkenin (GPA ve Mülakat) bilgi kazançlarını hesaplayıp karşılaştıralım:

# 1. Yardımcı Fonksiyon: Entropi Hesaplama
calc_entropy <- function(prob_yes) {
  if (prob_yes == 0 || prob_yes == 1) return(0)
  prob_no <- 1 - prob_yes
  return(- (prob_yes * log2(prob_yes) + prob_no * log2(prob_no)))
}

# Kök Düğüm (Parent)
# 4 Onay (Yes), 3 Red (No) -> Toplam 7
parent_entropy <- calc_entropy(4/7)

# --- SENARYO 1: Mülakat Puanına Göre Bölme ---
# PDF'teki mantık: Yüksek olanlar (Sol), Diğerleri (Sağ)
# Yüksek: 3 Kişi (Hepsi Onay) -> Entropi 0
# Diğerleri: 4 Kişi (1 Onay, 3 Red) -> Entropi hesaplanacak
entropy_high <- 0 
entropy_low  <- calc_entropy(1/4)

# Ağırlıklı Entropi (Weighted Average)
weighted_entropy_interview <- (3/7 * entropy_high) + (4/7 * entropy_low)
gain_interview <- parent_entropy - weighted_entropy_interview
cat("Gain Interview =", gain_interview)
## Gain Interview = 0.5216406
# --- SENARYO 2: GPA'ya Göre Bölme ---
# PDF'teki mantık: GPA > 3.0 (Sol), GPA < 3.0 (Sağ)
# >3.0: 3 Kişi (2 Onay, 1 Red)
# <3.0: 4 Kişi (2 Onay, 2 Red)
entropy_gpa_high <- calc_entropy(2/3)
entropy_gpa_low  <- calc_entropy(2/4) # 0.5, 0.5 -> Entropi 1 olur

weighted_entropy_gpa <- (3/7 * entropy_gpa_high) + (4/7 * entropy_gpa_low)
gain_gpa <- parent_entropy - weighted_entropy_gpa
print(gain_gpa)
## [1] 0.02024421
cat("Gain GPA =", gain_gpa)
## Gain GPA = 0.02024421
# --- SONUÇLARI GÖRSELLEŞTİRME ---
results <- data.frame(
  Split = c("Mülakat Puanı (Interview)", "Not Ortalaması (GPA)"),
  Gain = c(gain_interview, gain_gpa)
)

# Grafik Çizimi
ggplot(results, aes(x = Split, y = Gain, fill = Split)) +
  geom_col(width = 0.5, show.legend = FALSE) +
  geom_text(aes(label = round(Gain, 3)), vjust = -0.5, size = 3, fontface = "bold") +
  scale_fill_manual(values = c("#2ecc71", "#e74c3c")) + # Yeşil (Kazanan), Kırmızı (Kaybeden)
  labs(title = "Hangi Değişken Kök Düğüm Olmalı?",
       subtitle = "Daha yüksek 'Information Gain' değerine sahip değişken seçilir.",
       y = "Bilgi Kazancı (Information Gain)",
       x = "Aday Değişkenler") +
  theme_minimal() +
  theme(axis.text.x = element_text(size = 12, face = "bold"))
Şekil: Hangi Değişken Daha Çok Bilgi Kazandırıyor?

Şekil: Hangi Değişken Daha Çok Bilgi Kazandırıyor?

Hesaplama Sonuçları ve Yorum:

Grafikte ve hesaplamalarda görüldüğü üzere:

-GPA Ayrımı: Bilgi kazancı sadece 0.02 seviyesindedir. Bu ayrım belirsizliği neredeyse hiç azaltmamıştır (Gruplar hala karışıktır).

-Mülakat Ayrımı: Bilgi kazancı 0.522 seviyesindedir. Bu oldukça yüksek bir değerdir. Algoritma, maksimum kazancı sağlayan yolu seçeceği için ağacın en tepesine (Kök Düğüm) Mülakat Puanı değişkenini yerleştirir.

2.4. R ile Sınıflandırma Ağacının Oluşturulması

Manuel hesaplamalarımız sonucunda algoritmanın Mülakat Puanını kök düğüm olarak seçmesi gerektiğini bulmuştuk. Şimdi R’daki rpart algoritmasını kullanarak teorik bulgularımızı doğrulayalım ve ağacın tamamını görselleştirelim.

(Not: Veri seti sadece 7 satırdan oluştuğu için, algoritmanın erken durmasını (pruning) engellemek adına kontrol parametrelerini serbest bırakıyoruz.)

# Modelin Eğitilmesi (Method = 'class' sınıflandırma demektir)
# minsplit=1 diyerek en küçük grubu bile bölmeye zorluyoruz.
class_tree <- rpart(Decision ~ GPA + Interview, 
                    data = df_credit, 
                    method = "class",
                    parms = list(split = "information"), # Entropy kullan (Gini yerine)
                    control = rpart.control(minsplit = 1, minbucket = 1, cp = -1))

# Ağacın Görselleştirilmesi
rpart.plot(class_tree, 
           main = "Kredi Başvurusu Karar Mekanizması",
           type = 4,             # Dalları isimlendir
           extra = 104,          # Sınıf oranlarını ve olasılıkları göster
           box.palette = "GnRd", 
           shadow.col = "gray",
           nn = TRUE)            # Düğüm numaralarını göster
Şekil: Kredi Onayı İçin Oluşturulan Karar Ağacı

Şekil: Kredi Onayı İçin Oluşturulan Karar Ağacı

Model Yorumu ve Karar Kuralları

Yukarıdaki ağaç şeması, algoritmanın mantığını mükemmel bir şekilde özetlemektedir:

Kök Düğüm (En Üst): Algoritma ilk olarak Interview (Mülakat) puanına bakmıştır. (Teorik hesaplamamız doğru çıktı!)

Soru: Mülakat puanı Düşük veya Normal mi?

Sol Dal (Evet): Eğer mülakat Yüksek değilse, algoritma ikinci soruyu sorar:

Soru: GPA 3.0’dan küçük mü?

- Eğer Küçükse (<3.0) Red (Kırmızı Kutu).

- Eğer Büyükse (>=3.0) Onay (Yeşil Kutu).

Sağ Dal (Hayır): Eğer mülakat puanı Yüksek ise:

Başka hiçbir şeye bakmaksızın doğrudan Onay verir.

Bir Tahmin Örneği

Şimdi bankaya yeni bir müşteri geldiğini varsayalım:

GPA: 2.8 (3.0’dan küçük)

Mülakat: Normal

Model bu kişiyi nasıl sınıflandırır?

Mülakat Düşük/Normal mi? → Evet. (Sola git)

GPA < 3.0 mı? → Evet. (Sola git)

Sonuç: RED.

Bunu R kodu ile teyit edelim:

# Yeni Başvuru
yeni_basvuru <- data.frame(GPA = factor("<3.0", levels = c("<3.0", ">3.0")),
                           Interview = factor("Normal", levels = c("Düşük", "Normal", "Yüksek")))

# Tahmin
sonuc <- predict(class_tree, yeni_basvuru, type = "class")
cat("Modelin Kararı:", as.character(sonuc))
## Modelin Kararı: Red

2.5. Gerçek Hayat Senaryosu: Diyabet Teşhisi

Karar ağaçlarının en yaygın kullanım alanlarından biri tıbbi teşhislerdir. Doktorların kafasındaki “Eğer şekeri X’ten yüksekse ve yaşı Y’den büyükse risklidir” mantığını modelleyelim.

Bunun için Pima Indians Diabetes veri setini kullanacağız. Bilimsel geçerlilik adına veri setimizi %70 Eğitim (Modeli kurmak için) ve %30 Test (Modeli denemek için) olarak ikiye ayıracağız.

# Gerekli kütüphaneler
library(mlbench)
library(caret) # Confusion Matrix ve Split işlemi için ideal paket
data("PimaIndiansDiabetes2")

# 1. Veri Temizliği
df_diabet <- na.omit(PimaIndiansDiabetes2)

# 2. Eğitim ve Test Olarak Bölme (%70 - %30)
set.seed(123) # Her seferinde aynı sonucu almak için
index <- createDataPartition(df_diabet$diabetes, p = 0.7, list = FALSE)

train_set <- df_diabet[index, ]  # Modeli bununla eğiteceğiz (%70)
test_set  <- df_diabet[-index, ] # Modeli bununla test edeceğiz (%30)

# 3. Modeli Kurma (Sadece Eğitim Seti ile)
model_diabet <- rpart(diabetes ~ ., data = train_set, method = "class")

# 4. Test Seti Üzerinde Tahmin
tahminler <- predict(model_diabet, test_set, type = "class")

# 5. Başarıyı Ölçme (Confusion Matrix)
# Test setindeki Gerçek Durum vs Bizim Tahminimiz
confusionMatrix(tahminler, test_set$diabetes)
## Confusion Matrix and Statistics
## 
##           Reference
## Prediction neg pos
##        neg  71  19
##        pos   7  20
##                                           
##                Accuracy : 0.7778          
##                  95% CI : (0.6916, 0.8494)
##     No Information Rate : 0.6667          
##     P-Value [Acc > NIR] : 0.005846        
##                                           
##                   Kappa : 0.4583          
##                                           
##  Mcnemar's Test P-Value : 0.030984        
##                                           
##             Sensitivity : 0.9103          
##             Specificity : 0.5128          
##          Pos Pred Value : 0.7889          
##          Neg Pred Value : 0.7407          
##              Prevalence : 0.6667          
##          Detection Rate : 0.6068          
##    Detection Prevalence : 0.7692          
##       Balanced Accuracy : 0.7115          
##                                           
##        'Positive' Class : neg             
## 

2.6. Model Performansının Detaylı Analizi

Elde edilen Confusion Matrix çıktısı, modelin hiç görmediği test verisi üzerindeki başarısını gösterir. İşte sonuçların tıbbi ve istatistiksel yorumu:

1. Karışıklık Matrisi (Confusion Matrix) Analizi

Tablonun sol üst köşesindeki rakamlar (71, 19, 7, 20) modelin tahminleri ile gerçekler arasındaki ilişkiyi gösterir:

  • Doğru Negatifler (True Negatives - Sağlıklı): 71 Kişi

    • Gerçekte sağlıklı olan 78 kişinin 71’ini model doğru bilmiştir.
  • Doğru Pozitifler (True Positives - Diyabet): 20 Kişi

    • Gerçekte diyabet hastası olan 39 kişinin 20’sini model doğru teşhis etmiştir.
  • Hatalı Alarm (False Positive - Tip 1 Hata): 7 Kişi

    • Bu 7 kişi aslında sağlıklı, ama model onlara yanlışlıkla “Diyabet olabilir” demiştir. (Bu kabul edilebilir bir hatadır, tekrar test yapılır).
  • Kaçırılan Vaka (False Negative - Tip 2 Hata): 19 Kişi (KRİTİK)

    • En tehlikeli hata burasıdır. Bu 19 kişi aslında Diyabet hastası, ancak model onlara “Sağlıklısın” demiştir. Bu hastalar tedavi olamayacağı için risk altındadır.

2. İstatistiksel Metriklerin Yorumu

  • Accuracy (Doğruluk): 0.7778 (%77.8)

    • Modelimiz her 100 hastadan yaklaşık 78’ine doğru teşhis koymaktadır. Tıbbi bir model için “orta seviye” bir başarıdır.
  • P-Value [Acc > NIR]: 0.0058

    • Bu değerin 0.05’ten küçük olması, modelimizin “rastgele sallamaktan” (yazı tura atmaktan) istatistiksel olarak anlamlı derecede daha iyi olduğunu kanıtlar.
  • Kappa: 0.4583

    • Kappa değeri modelin tutarlılığını ölçer. 0.4 - 0.6 arası “Orta Düzeyde Uyum” anlamına gelir. Model çalışıyor ama mükemmel değil.
  • Sensitivity (Duyarlılık - Sağlıklıyı Bulma): 0.9103 (%91)

    • Model, sağlıklı insanları tespit etmekte çok başarılıdır. Sağlıklı birine “Sen hastasın” deme ihtimali çok düşüktür.
  • Specificity (Özgüllük - Hastayı Bulma): 0.5128 (%51.3)

    • Modelin zayıf karnı burasıdır. Gerçek hastaların sadece yarısını (%51) yakalayabilmiştir. Diğer yarısını (19 kişiyi) kaçırmıştır.

3. Genel Değerlendirme

Sonuç: Modelimiz muhafazakar davranmıştır. Kimseyi boş yere korkutmamak (False Alarm vermemek) konusunda çok iyidir (%91 Sensitivity), ancak hastalıkları yakalama konusunda (Specificity %51) yeterince agresif değildir.

Geliştirme Önerisi:

Tıbbi modellerde hastalığı kaçırmak (Tip 2 Hata), yanlış alarm vermekten (Tip 1 Hata) daha kötüdür. Bu modelin başarısını artırmak için ya daha fazla veriye ihtiyaç vardır ya da Karar Ağacı yerine Random Forest veya XGBoost gibi daha güçlü modellere geçilmelidir.

Ağacın Görselleştirilmesi

rpart.plot(model_diabet, 
           main = "Diyabet Teşhis Kuralları",
           type = 4,
           extra = 104,           
           box.palette = "GnRd",
           shadow.col = "gray",
           nn = TRUE)
Şekil: Diyabet Risk Ağacı

Şekil: Diyabet Risk Ağacı

Ağacın Görselleştirilmesi ve Tıbbi Yorumu

Eğitim veri seti üzerinde kurulan modeli incelediğimizde, algoritmanın diyabet teşhisi için aşağıdaki hiyerarşik kuralları oluşturduğunu görüyoruz:

  1. Birincil Kural (Kök Düğüm): Glikoz Seviyesi

    • En belirleyici faktör yine Glikozdur. Eşik değeri 128 olarak belirlenmiştir.

    • Sol Taraf (Glikoz < 128): Düşük risk bölgesidir. Ancak burada ilginç bir alt kontrol vardır: İnsülin. Eğer glikoz düşük ve İnsülin de 144’ten küçükse, kişinin sağlıklı (neg) olma ihtimali %92’ye çıkar. Bu ağacın en güvenli yaprağıdır.

  2. Yüksek Risk ve Kesin Teşhis (En Sağ Dal)

    • Eğer Glikoz >= 166 ise (Sağdaki ilk ayrımın sağı), algoritma başka hiçbir soru sormadan kişiyi %89 ihtimalle Diyabet (pos) olarak etiketler. Bu, “Kırmızı Alarm” bölgesidir.
  3. Gri Bölge ve Fiziksel Özellikler (128 <= Glikoz < 166)

    • Glikoz seviyesi 128 ile 166 arasındaysa durum belirsizdir. Burada devreye Triceps (Deri kıvrım kalınlığı) girer.

    • Şaşırtıcı Bulgu: Glikoz yüksek olsa bile (128-166 arası), eğer kişinin deri kıvrım kalınlığı düşükse (Triceps < 23), model bu kişiyi %85 ihtimalle Sağlıklı (neg) olarak sınıflandırır.

    • Ancak Triceps kalınlığı yüksekse (>= 23), devreye Yaş (Age) girer. 41 yaşından büyük olanlar yüksek risk grubuna (%76 pos) dahil edilir.

Bir Hasta İçin Tahmin Senaryosu

Yeni bir hasta geldiğini ve değerlerinin şu şekilde olduğunu varsayalım:

  • Glikoz: 145 (Orta-Yüksek)

  • Triceps: 20 (İnce deri kıvrımı)

  • Yaş: 45

Ağaç üzerinde bu hastayı takip edelim:

  1. Glikoz < 128 mi? Hayır (145). \(\rightarrow\) Sağa git.

  2. Glikoz < 166 mı? Evet (145). \(\rightarrow\) Sola git.

  3. Triceps < 23 mü? Evet (20). \(\rightarrow\) Sola git.

  4. Sonuç: Model bu hastaya, yaşına ve glikozuna rağmen fiziksel yapısı (Triceps) nedeniyle Sağlıklı (neg) teşhisi koyacaktır (%85 olasılıkla).

Bu durum, Karar Ağaçlarının bazen doğrusal olmayan, şaşırtıcı ama veri odaklı örüntüleri (Glikoz yüksek olsa bile zayıf bireylerin diyabet olmayabileceği gibi) yakalayabildiğini gösterir.

Model bu hastaya ne der? Kod üzerinde görelim:

# Yeni Hasta Verisi
# Senaryomuzdaki kritik değerler: Glucose=145, Triceps=20
# Not: Yeni ağaçta bu hasta için 'Mass' değil 'Triceps' belirleyici oldu.
yeni_hasta <- data.frame(
  pregnant = 1,       
  glucose = 145,      # <-- KRİTİK: Yüksek Şeker (Riskli Bölge)
  pressure = 70,      
  triceps = 20,       # <-- KRİTİK: İnce Deri Kıvrımı (Kurtarıcı Faktör)
  insulin = 80,       
  mass = 35,          
  pedigree = 0.5,     
  age = 45            
)

# Tahmin İşlemi
tahmin_sinif <- predict(model_diabet, yeni_hasta, type = "class")
tahmin_olasilik <- predict(model_diabet, yeni_hasta, type = "prob")

# Sonucu Yazdıralım
cat("Modelin Teşhisi:", as.character(tahmin_sinif), "\n")
## Modelin Teşhisi: neg
cat("Diyabet Olma İhtimali: %", round(tahmin_olasilik[2] * 100, 2))
## Diyabet Olma İhtimali: % 15.38
# Beklenen Sonuç: neg (Sağlıklı) çıkması lazım çünkü Triceps < 23.