Çapraz Doğrulama
Cross-Validation
Veriyi birden çok eğitim/doğrulama parçasına bölüp her parçayı sırayla doğrulama olarak kullanan, modelin gerçek başarısını daha güvenilir tahmin etme yöntemi.
Tek bir eğitim/test bölünmesi şanslı ya da şanssız çıkabilir. Çapraz doğrulama (CV) bu rastlantıyı azaltmak için veriyi K eşit parçaya (fold) ayırır. Her turda K-1 parça eğitime, kalan 1 parça doğrulamaya ayrılır. K tur sonunda her örnek bir kez doğrulamada yer almıştır; K skorun ortalaması modelin başarı tahmini olur.
En yaygın varyantı K-Fold (genelde K=5 veya 10). Sınıf dengesizliği varsa Stratified K-Fold her fold'da sınıf oranlarını korur. Zaman serisi verisinde Time Series Split geleceği eğitime sızdırmadan ileri-geri yapar. Bir kullanıcı / grup yapısı varsa Group K-Fold aynı grup eğitim ve doğrulamaya birlikte düşmesin diye gruba göre böler.
Çapraz doğrulamanın iki ana kullanımı vardır. Birincisi hiperparametre seçimi: GridSearchCV/RandomizedSearchCV ile en iyi parametreleri ararken her aday için CV skorunu hesaplar. İkincisi model performansının dürüst tahmini: tek bir test setine bağlı kalmadan modelin gerçek varyansını gözlemlemek.
Bir öğretmen sınavda öğrencinin gerçek başarısını anlamak için aynı konuyu farklı sorularla beş kez sorar. Tek bir soruda şanslı çıkabilir ya da kafası dolaşmış olabilir; beş soru ortalaması gerçek bilgisini daha doğru gösterir. Çapraz doğrulama da modelden bu beş "farklı sınavı" alır; tek bir test fold'una bağlı kalmaz.
Bir sigorta şirketi 12.000 müşterilik veriyle hasar tahmin modeli kuruyor. Önce klasik 80/20 bölünme yapılıyor: train AUC 0.91, test AUC 0.83. "Aşırı öğrenme mi, yoksa şanssız bir test seti mi?" sorusu cevapsız.
5-fold cross-validation çalıştırılıyor. Sonuçlar: 0.82, 0.84, 0.79, 0.85, 0.83. Ortalama 0.826, standart sapma 0.022. Yani modelin gerçek başarısı ~0.82 civarında, ±0.02 oynayabilir. İlk testin 0.83'ü tipikti; aşırı öğrenme yok. Ekip karar verirken "0.82 civarı, en kötü %95 güvenle 0.79" der ve ürün stratejisini bu rakama göre kurar.
from sklearn.ensemble import GradientBoostingClassifier
from sklearn.model_selection import (
StratifiedKFold, cross_val_score, GridSearchCV,
)
# Sınıf dengesizliği varsa stratified şart
skf = StratifiedKFold(n_splits=5, shuffle=True, random_state=42)
# Tek bir model için CV skoru
model = GradientBoostingClassifier()
scores = cross_val_score(model, X, y, cv=skf, scoring="roc_auc", n_jobs=-1)
print(f"AUC: {scores.mean():.3f} ± {scores.std():.3f}")
print(f"Fold skorları: {scores}")
# Hiperparametre ararken de CV ile değerlendir
param_grid = {
"n_estimators": [100, 300, 500],
"max_depth": [3, 5, 7],
"learning_rate": [0.05, 0.1],
}
gs = GridSearchCV(model, param_grid, cv=skf, scoring="roc_auc", n_jobs=-1)
gs.fit(X, y)
print(f"En iyi: {gs.best_params_}, AUC={gs.best_score_:.3f}")- Modelin başarısını dürüstçe tahmin etmek istediğinde
- Veri seti küçükse — tek bir test fold'una güvenemezsin
- Hiperparametre seçimi yaparken — overfit risksiz arama için
- Farklı modelleri kıyaslarken — istatistiksel olarak anlamlı kıyaslama
- Veri çok büyükse ve eğitim çok pahalıysa — tek bölünme yeter
- Zaman serisi gibi sıralı veride sıradan k-fold zaman kuralını ihlal eder — TimeSeriesSplit kullan
- Aynı kullanıcının/grubun farklı kayıtları varsa ve bunlar fold'lara dağılırsa sızıntı olur — GroupKFold şart
Veri ön işleme sızıntısı
Scaler ya da feature selection'ı tüm veride fit edip CV'yi sonra çalıştırırsan, doğrulama foldları eğitim sırasında 'görülmüş' olur. Çözüm: Pipeline ile sarmala — her fold için ön işleme baştan yapılsın.
Sınıf dengesizliğini stratify etmemek
Düz K-fold pozitif sınıf %1'in altındaki bir veride bazı fold'lara hiç pozitif örnek koymayabilir. StratifiedKFold dengesizliği korur.
Zaman serisinde sıradan k-fold
Geleceği eğitime, geçmişi doğrulamaya koymak modelin gerçek başarısını şişirir. Zaman sıralı veride mutlaka TimeSeriesSplit veya benzeri yöntem kullan.