T.UZUN_
VERİ ANALİTİĞİ

Regresyon Metrikleri, AUC ve Hipotez Testleri (Mid-Level)

Bu rehber, makine öğrenmesi ve istatistiksel modellerin başarısını dürüstçe ölçmek için kullanılan regresyon metriklerini, sıralama parametrelerini ve hipotez testlerini incelemektedir. MAE, RMSE, Adjusted R², ROC-AUC, PR-AUC ve MCC gibi ölçütlerin hangi veri yapılarında tercih edilmesi gerek..

Paylaş
mid-level-istatistik-metrikleri-ve-testleri.jpg

Bir modeli kurmak işin kolay kısmıdır; asıl zorluk, onun gerçekten işe yarayıp yaramadığını dürüstçe ölçmektir. Yanlış metrik, kötü bir modeli iyi gibi gösterebilir ya da tam tersi. Bu yazıda regresyon hatalarını, sıralama tabanlı AUC metriklerini ve iki grubu karşılaştırırken başvurduğumuz hipotez testlerini — hepsini pratik Python örnekleriyle — ele alıyoruz.

Junior seviyedeki tanımlayıcı istatistik ve karışıklık matrisi temelinin üzerine inşa ediyoruz. Örnekler yine pandas, Polars, NumPy, scikit-learn ve yeri geldiğinde SciPy ile.


1. Regresyon Hata Metrikleri

Regresyonda model, sürekli bir sayıyı tahmin eder — ve "ne kadar yanıldı?" sorusunun birden fazla yanıtı vardır. Hangi metriği seçtiğin, hangi tür hataya ne kadar önem verdiğini belirler.

MAE, MSE ve RMSE:

MAE (Ortalama Mutlak Hata), hataların mutlak değerlerinin ortalamasıdır ve aykırı değerlere dayanıklıdır — her hataya eşit ağırlık verir. MSE (Ortalama Kare Hata) ise hataları karesel olarak cezalandırdığı için büyük sapmaları çok daha ağır biçimde vurgular; türevlenebilir olması nedeniyle optimizasyonda tercih edilir. RMSE, MSE'nin kareköküdür ve hedef değişkenle aynı birimde olduğu için yorumlaması en kolay olanıdır.

MAE = mean(|y − ŷ|)  ·  MSE = mean((y − ŷ)²)  ·  RMSE = √MSE

# Üç metriği scikit-learn ile hesaplama
from sklearn.metrics import mean_absolute_error, mean_squared_error
import numpy as np

y_gercek = np.array([100, 150, 200, 250, 300])
y_tahmin = np.array([110, 140, 210, 240, 500])  # son tahmin çok kötü

mae  = mean_absolute_error(y_gercek, y_tahmin)
mse  = mean_squared_error(y_gercek, y_tahmin)
rmse = np.sqrt(mse)

print(f"MAE : {mae:.1f}")    # 48.0  → tek kötü tahmini yumuşatır
print(f"MSE : {mse:.1f}")    # büyük, çünkü 200'lük hata karesel büyür
print(f"RMSE: {rmse:.1f}")   # hedefle aynı birimde, yorumlanabilir

MAE mi RMSE mi? Aykırı hatalar senin için özellikle maliyetliyse (bir büyük sapma, on küçük sapmadan kötüyse) RMSE'yi seç. Tüm hatalar eşit derecede önemliyse ve veride gürültülü aykırılıklar varsa MAE daha adil bir resim verir.

Yüzdesel ve dayanıklı alternatifler

MAPE (Ortalama Mutlak Yüzde Hata) hatayı yüzde cinsinden sunar, bu yüzden ölçekten bağımsız ve iş birimlerine anlatması kolaydır — ama gerçek değer sıfıra yaklaştığında patlar. SMAPE bu sorunu paydaya gerçek ve tahmin değerlerinin ortalamasını koyarak yumuşatır ve simetri sağlar. Huber Loss ise iki dünyanın en iyisini birleştirir: küçük hatalarda karesel (MSE gibi), δ eşiğinden büyük hatalarda doğrusal (MAE gibi) davranarak aykırı değerlere dayanıklılık kazandırır.

# MAPE ve Huber loss — NumPy ile sıfırdan
import numpy as np

def mape(y, yhat):
    return np.mean(np.abs((y - yhat) / y)) * 100

def huber(y, yhat, delta=1.0):
    hata = y - yhat
    kucuk = np.abs(hata) <= delta
    karesel  = 0.5 * hata**2
    dogrusal = delta * (np.abs(hata) - 0.5 * delta)
    return np.mean(np.where(kucuk, karesel, dogrusal))

y    = np.array([100, 150, 200, 250])
yhat = np.array([110, 140, 210, 400])

print(f"MAPE : {mape(y, yhat):.1f}%")
print(f"Huber: {huber(y, yhat, delta=10):.1f}")

Son olarak iki özel amaçlı kayıp: RMSLE (Kök Ortalama Kare Log Hata) logaritmik ölçekte çalıştığı için mutlak farkları değil oransal farkları önemser ve düşük tahminleri (olması gerekenin altında kalmayı) daha çok cezalandırır. Quantile / Pinball Loss ise ortalamayı değil belirli bir yüzdelik dilimi (örneğin %90) tahmin etmeye yarar — talep planlaması gibi "yeterince stok bulundurmak, az bulundurmaktan daha önemli" olan senaryolarda çok kullanışlıdır.

# Quantile (Pinball) loss — %90'lık dilim için asimetrik ceza
import numpy as np

def pinball(y, yhat, q=0.9):
    hata = y - yhat
    return np.mean(np.maximum(q * hata, (q - 1) * hata))

# q=0.9 → düşük tahmin (stok yetersizliği) daha ağır cezalanır
print(pinball(np.array([50]), np.array([40]), q=0.9))  # düşük kaldı → yüksek ceza
print(pinball(np.array([50]), np.array([60]), q=0.9))  # fazla tahmin → düşük ceza

2. Model Açıklayıcılığı ve AUC Metrikleri

R² ve Adjusted R²: model ne kadarını açıklıyor?

R² (Belirlilik Katsayısı), modelin hedef değişkendeki toplam varyansın ne kadarını açıkladığını gösterir — 1'e yakınsa iyi, 0 ise ortalama kadar, negatifse ortalamadan bile kötü demektir. Ancak bir tuzağı vardır: modele anlamsız bir değişken eklesen bile R² asla düşmez. Adjusted R² bu sorunu, değişken sayısını ve serbestlik derecesini cezalandırarak çözer; işe yaramayan bir değişken eklendiğinde düşer. Model karşılaştırırken bu yüzden çok daha güvenilirdir. Aynı dengeleme fikrini AIC ve BIC bilgi kriterleri de farklı bir açıdan sunar (düşük değer daha iyi).

R² = 1 − (SS_res / SS_tot)  ·  Adjusted R² = 1 − (1 − R²)·(n − 1)/(n − p − 1)

# R² ve elle Adjusted R² hesabı
from sklearn.metrics import r2_score
import numpy as np

y      = np.array([3, 5, 7, 9, 11, 13])
y_pred = np.array([2.8, 5.2, 6.9, 9.1, 10.8, 13.2])

r2 = r2_score(y, y_pred)

n, p = len(y), 1   # n gözlem, p bağımsız değişken
adj_r2 = 1 - (1 - r2) * (n - 1) / (n - p - 1)

print(f"R²          : {r2:.3f}")
print(f"Adjusted R² : {adj_r2:.3f}")

Sıralama gücü: ROC-AUC ve PR-AUC

Sınıflandırmada model genelde bir olasılık üretir; eşiği nereye koyduğun sonucu değiştirir. ROC eğrisi, tüm olası eşiklerde TPR (Recall) ile FPR (yanlış pozitif oranı) arasındaki ödünleşmeyi çizer. ROC-AUC, bu eğrinin altındaki alandır ve eşikten bağımsız "ayrım gücünü" tek sayıda özetler (0.5 rastgele, 1.0 mükemmel).

Ama kritik bir uyarı var: veri aşırı dengesizse (örneğin pozitifler %1) ROC-AUC yanıltıcı derecede iyimser olabilir. Böyle durumlarda PR-AUC (Precision-Recall eğrisi altındaki alan) çok daha bilgilendiricidir, çünkü doğrudan pozitif sınıfın yakalanmasına odaklanır.

# ROC-AUC ve PR-AUC — dengesiz veride farkı görün
from sklearn.metrics import roc_auc_score, average_precision_score
import numpy as np

# %10 pozitif olan dengesiz bir örnek
y_gercek = np.array([0]*90 + [1]*10)
y_skor   = np.concatenate([
    np.random.uniform(0, 0.6, 90),   # negatiflerin skorları
    np.random.uniform(0.4, 1.0, 10),  # pozitiflerin skorları
])

print(f"ROC-AUC : {roc_auc_score(y_gercek, y_skor):.3f}")
print(f"PR-AUC  : {average_precision_score(y_gercek, y_skor):.3f}")

# Gini katsayısı doğrudan AUC'den türetilir
gini = 2 * roc_auc_score(y_gercek, y_skor) - 1
print(f"Gini    : {gini:.3f}")

Kredi skorlama gibi alanlarda Gini katsayısı (Gini = 2·AUC − 1) sık kullanılır. Modelin rastgeleye kıyasla kazanımını ölçmek için ise Lift & Gain eğrileri ve pozitif–negatif dağılımların maksimum ayrımını gösteren Kolmogorov-Smirnov (KS) istatistiği yaygındır.


3. Derin Sınıflandırma Metrikleri

F-beta Score, F1'in ayarlanabilir bir genellemesidir: β > 1 olduğunda Recall'a, β < 1 olduğunda Precision'a ağırlık verir. Böylece "hangisi daha önemli?" kararını metriğe gömebilirsin.

Fβ = (1 + β²) · (Precision · Recall) / (β² · Precision + Recall)

MCC (Matthews Korelasyon Katsayısı), karışıklık matrisinin dört hücresini de (TP, FP, TN, FN) hesaba katar ve [−1, +1] aralığında bir değer üretir. Dengesiz sınıflarda tek bir sayıyla model kalitesini özetlemek için en güvenilir metrik odur — accuracy'nin aksine, bir hücreyi ihmal edip seni kandıramaz. Cohen's Kappa ise gözlemlenen uyumdan şansa dayalı uyumu çıkararak "tesadüfen ne kadar tutturulurdu?" sorusunu düzeltir.

# F-beta, MCC ve Cohen's Kappa — scikit-learn
from sklearn.metrics import fbeta_score, matthews_corrcoef, cohen_kappa_score

y_gercek = [1, 0, 1, 1, 0, 1, 0, 0, 1, 0]
y_tahmin = [1, 0, 0, 1, 0, 1, 1, 0, 1, 0]

print(f"F2 (Recall ağırlıklı): {fbeta_score(y_gercek, y_tahmin, beta=2):.3f}")
print(f"F0.5 (Prec. ağırlıklı): {fbeta_score(y_gercek, y_tahmin, beta=0.5):.3f}")
print(f"MCC   : {matthews_corrcoef(y_gercek, y_tahmin):.3f}")
print(f"Kappa : {cohen_kappa_score(y_gercek, y_tahmin):.3f}")

Neden MCC? 99 negatif, 1 pozitif olan bir veride "hepsi negatif" diyen model %99 accuracy alır ama MCC'si 0 çıkar — çünkü MCC modelin hiçbir pozitifi yakalamadığını görür. Dengesiz problemde tek sayı raporlaman gerekiyorsa MCC en dürüst seçimdir.


4. Hipotez Testleri ve p-değeri

İki grubu (A/B testinde iki tasarım, iki ilaç, iki model) karşılaştırırken gördüğün fark gerçek mi, yoksa şans eseri mi? Hipotez testleri tam da bunu yanıtlar.

p-değeri, sıfır hipotezi (gruplar arasında fark yok) doğruyken, gözlediğin kadar veya daha uç bir sonucun ortaya çıkma olasılığıdır. Küçük p (genelde < 0.05) sıfır hipotezine karşı kanıttır. Ama dikkat: p-değeri etki büyüklüğü değildir — farkın var olup olmadığını söyler, ne kadar büyük olduğunu değil.

En yaygın yanlış anlama: p-değeri "sıfır hipotezinin doğru olma olasılığı" değildir. Ayrıca büyük örneklemde çok küçük, pratikte önemsiz farklar bile "istatistiksel olarak anlamlı" çıkabilir. Bu yüzden p-değerini her zaman etki büyüklüğüyle birlikte rapor et.

Hangi test, ne zaman?

Test

Kullanım amacı

Türü

Student's t-test

İki grubun ortalaması eşit mi (eşit varyans varsayımı)

Parametrik

Welch's t-test

İki grup ortalaması (varyanslar eşit değilken; güvenli varsayılan)

Parametrik

Paired t-test

Eşleştirilmiş / tekrarlı ölçümler (önce–sonra)

Parametrik

ANOVA (F-testi)

Üç ve daha fazla grubun ortalamalarını karşılaştırma

Parametrik

Mann-Whitney U

İki bağımsız grup (normallik varsayımı yokken)

Non-parametrik

Wilcoxon Signed-Rank

Eşleştirilmiş iki grup (normallik varsayımı yokken)

Non-parametrik

Kruskal-Wallis

ANOVA'nın non-parametrik karşılığı (3+ grup)

Non-parametrik

Chi-Square (χ²)

Kategorik değişkenlerin bağımsızlığı / uyum iyiliği

Non-parametrik

SciPy bu testlerin neredeyse hepsini tek satırda sunar scipy

# İki grubu karşılaştırma — parametrik ve non-parametrik
from scipy import stats
import numpy as np

rng = np.random.default_rng(0)
grup_A = rng.normal(100, 15, 50)   # kontrol
grup_B = rng.normal(108, 15, 50)   # deney (biraz yüksek)

# Welch's t-test — varyans eşitliği varsaymaz, güvenli varsayılan
t, p = stats.ttest_ind(grup_A, grup_B, equal_var=False)
print(f"Welch t-test    → t={t:.2f}, p={p:.4f}")

# Normallik yoksa non-parametrik karşılığı
u, p_mw = stats.mannwhitneyu(grup_A, grup_B)
print(f"Mann-Whitney U  → p={p_mw:.4f}")

# 3+ grup için ANOVA
grup_C = rng.normal(115, 15, 50)
f, p_anova = stats.f_oneway(grup_A, grup_B, grup_C)
print(f"ANOVA           → F={f:.2f}, p={p_anova:.4f}")

Anlamlılık yetmez: etki büyüklüğü ve güç

p-değeri "fark var mı?" der; Cohen's d (Etki Büyüklüğü) ise "fark ne kadar büyük?" sorusunu yanıtlar ve örneklem büyüklüğünden bağımsızdır. İkisini birlikte raporlamak iyi bir alışkanlıktır. Güç Analizi (Statistical Power) ise deney öncesinde devreye girer: gerçek bir etkiyi yakalayabilmek için kaç gözleme ihtiyacın olduğunu (1 − β) hesaplamanı sağlar.

# Cohen's d — iki grup arasındaki standartlaştırılmış fark
import numpy as np

def cohens_d(a, b):
    na, nb = len(a), len(b)
    # birleştirilmiş (pooled) standart sapma
    s = np.sqrt(((na-1)*a.var(ddof=1) + (nb-1)*b.var(ddof=1)) / (na+nb-2))
    return (a.mean() - b.mean()) / s

d = cohens_d(grup_B, grup_A)
print(f"Cohen's d: {d:.2f}")  # ~0.2 küçük, ~0.5 orta, ~0.8 büyük etki
# Güç analizi — gerekli örneklem büyüklüğü (statsmodels)
from statsmodels.stats.power import TTestIndPower

analiz = TTestIndPower()
n = analiz.solve_power(effect_size=0.5, alpha=0.05, power=0.8)
print(f"Grup başına gereken örneklem: {n:.0f}")  # orta etki için ~64

KAPANIŞ

Bu katman, bir modeli yargılama repertuvarını genişletir. Regresyonda MAE'den Huber'a kadar her metrik, hatanın farklı bir yüzünü öne çıkarır. R² ve Adjusted R² açıklayıcılığı, ROC-AUC ile PR-AUC ise sıralama gücünü — özellikle dengesiz veride farklı hikayeler anlatarak — ölçer. MCC gibi metrikler tek sayıda dürüst bir özet sunarken, hipotez testleri gördüğün farkın gerçek mi tesadüf mü olduğunu ayırt etmeni sağlar.

Altın kural değişmiyor: doğru metrik, modelinden değil probleminden doğar. Hatanın maliyeti, sınıfların dengesi ve kararın etkisi — metriği bunlar seçer. Bir sonraki katmanda regresyon varsayımları, olasılıksal kayıplar ve Bayesçi çıkarım gibi daha derin araçlara geçeceğiz.

Örnekleri kendi veri kümene uyarlayıp iki metriğin ne zaman ayrıştığını (örneğin ROC-AUC yüksekken PR-AUC'nin düşük kalması) gözlemlemeni öneririm; bu, teoriyi sezgiye çeviren en hızlı yoldur.

Sık Sorulan Sorular

Dengesiz veri setlerinde neden Accuracy (Doğruluk) yerine MCC veya PR-AUC kullanılmalıdır?

Pozitif sınıfın %1 olduğu bir veride tüm örneklere "negatif" diyen basit bir model %99 doğruluk oranına ulaşır ancak hiçbir fayda sağlamaz. MCC ve PR-AUC, yanlış pozitif ve yanlış negatif durumlarını doğrudan hesaba katarak modelin gerçek performansını dürüstçe yansıtır.

R² ile Adjusted R² arasındaki temel fark nedir?

R² modele eklenen her yeni değişkende artma eğilimindeyken, Adjusted R² değişken sayısını cezalandırarak modelin açıklayıcılık gücüne gerçekten katkı sağlamayan değişkenler eklendiğinde düşer.

Welch's t-test neden standart Student's t-test yerine tercih edilir?

Student's t-test iki grubun varyanslarının eşit olduğunu varsayar; Welch's t-test ise bu varsayıma ihtiyaç duymadan farklı varyanslara ve örneklem boyutlarına sahip grupları güvenle karşılaştırır.

Bu içerik sana ne hissettirdi?

İlgili Yazılar