Her modelin altında, çoğu zaman görmezden gelinen bir katman vardır: verinin kendisini anlamak. Ortalamayı, dağılımın şeklini ve bir sınıflandırıcının nerede yanıldığını kavramadan kurulan modeller, çalışıyormuş gibi görünüp sessizce yanlış kararlar verir. Bu yazıda tanımlayıcı istatistiğin temel taşlarını, aralarına serpiştirdiğim Python örnekleriyle birlikte adım adım ele alıyorum.
Tanımlayıcı İstatistik Nedir? / Neden Önemlidir?
Tanımlayıcı İstatistik, toplanmış veri kümelerinin temel özelliklerini özetlemek, verinin tipik değerlerini, yayılımını ve genel yapısını sayısal metriklerle betimlemek amacıyla kullanılan istatistik dalıdır. Makine öğrenmesi süreçlerinde verinin karakteristiğini kavramak, veri temizleme aşamalarını doğru yönlendirmek ve modeli yanlış yönlendirecek aykırı değerleri tespit etmek için vazgeçilmez bir ön hazırlık adımıdır.
1. Merkezi Eğilim: Verinin "tipik" değeri nedir?
Bir veri kümesini tek bir sayıyla özetlemek istediğinde üç aday çıkar karşına: ortalama, ortanca ve tepedeğer. Aralarındaki fark akademik değil, tamamen pratiktir — yanlış olanı seçmek yanıltıcı bir tabloya yol açar.
Mean (Ortalama) tüm değerlerin toplamının gözlem sayısına bölümüdür. Sezgisel ve hesaplaması kolaydır, ama tek bir aykırı değer onu ciddi şekilde kaydırabilir. Median (Ortanca) sıralı verinin tam ortasındaki değerdir ve bu yüzden aykırı değerlere karşı dayanıklıdır; çarpık dağılımlarda ortalamadan çok daha temsilcidir. Mode (Tepedeğer) ise en sık tekrar eden değerdir ve kategorik verilerde merkezi eğilimi ölçmenin geçerli tek yoludur.
Pratik sezgi: Gelir, ev fiyatı, süre gibi sağa çarpık verilerde ortalama neredeyse her zaman medyandan büyüktür. "Ortalama maaş" ile "medyan maaş" arasındaki uçurum tam olarak buradan doğar.
Bir maaş kümesinde ortalamanın nasıl yanıltabileceğini görelim pandas
# pandas ile üç merkezi eğilim ölçüsü
import pandas as pd
maaslar = pd.Series([42, 45, 47, 50, 52, 48, 300]) # 300 = CEO maaşı
print("Ortalama:", maaslar.mean()) # 83.4 → tek kişi tabloyu bozdu
print("Medyan :", maaslar.median()) # 48.0 → tipik çalışanı doğru anlatır
print("Mode :", maaslar.mode()[0]) # en sık değerAynı işi polars ile yapmak da bir o kadar temiz. Polars, büyük veri kümelerinde tembel değerlendirme (lazy evaluation) ve çoklu çekirdek kullanımıyla öne çıkar:
import polars as pl
df = pl.DataFrame({"maas": [42, 45, 47, 50, 52, 48, 300]})
df.select(
pl.col("maas").mean().alias("ortalama"),
pl.col("maas").median().alias("medyan"),
)Ortalamanın akrabaları: budanmış, geometrik ve harmonik
Klasik ortalama tek seçenek değildir. Trimmed Mean (Budanmış Ortalama), uç yüzdelik dilimleri (örneğin en düşük ve en yüksek %5) attıktan sonra hesaplanır ve aykırı değerlerin etkisini kırar. Geometrik ortalama oransal büyümelerde (yıllık getiri gibi) doğru sonucu verirken, harmonik ortalama oranların ortalamasında kullanılır — nitekim ileride göreceğimiz F1-Score bir harmonik ortalamadır.
# Budanmış ortalama — SciPy'nin pratik yardımcısı
from scipy import stats
import numpy as np
x = np.array([42, 45, 47, 50, 52, 48, 300])
print(stats.trim_mean(x, 0.1)) # baştan/sondan %10 atılmış ortalama
print(stats.gmean([1.05, 1.10, 0.95])) # geometrik: ortalama büyüme çarpanı2. Yayılım: Değerler ne kadar dağınık?
Merkez tek başına yeterli değildir. Ortalaması aynı olan iki kümeden biri sımsıkı toplanmış, diğeri geniş yayılmış olabilir. Yayılım ölçüleri bu farkı yakalar.
Variance (Varyans), değerlerin ortalamadan sapmalarının karelerinin ortalamasıdır. Burada ince bir nokta var: popülasyonun tamamı elimizdeyken paydada N kullanırız; ama elimizde yalnızca bir örneklem varsa, gerçek varyansı yansız (unbiased) tahmin edebilmek için Bessel düzeltmesi yaparak paydada n − 1 kullanırız.
σ² = Σ(xᵢ − μ)² / N (popülasyon) · s² = Σ(xᵢ − x̄)² / (n − 1) (örneklem)
Varyansın birimi karesel olduğu için (TL değil, TL²) doğrudan yorumlaması zordur. Standard Deviation (Standart Sapma) onun kareköküdür ve verinin kendi biriminde olduğu için çok daha okunaklıdır.
Sık yapılan hata: NumPy'nin np.var() fonksiyonu varsayılan olarak popülasyon varyansı (ddof=0) hesaplar. Bir örneklemle çalışıyorsan ddof=1 vermeyi unutma — pandas ise varsayılan olarak ddof=1 kullanır. Bu tutarsızlık gerçek projelerde sessiz hatalara yol açar.
# NumPy ve pandas'ın varsayılanları FARKLI davranır
import numpy as np
import pandas as pd
x = [42, 45, 47, 50, 52]
print(np.var(x)) # ddof=0 → popülasyon varyansı
print(np.var(x, ddof=1)) # ddof=1 → örneklem varyansı (Bessel)
print(pd.Series(x).var()) # pandas zaten ddof=1 kullanır
print(np.std(x, ddof=1)) # standart sapma = karekökAykırı değere dayanıklı yayılım: IQR, MAD ve CV
Range (Açıklık) yalnızca maksimum ile minimum arasındaki farktır; iki uç değere bağlı olduğu için kırılgandır. IQR (Çeyrekler Arası Açıklık) ise Q3 − Q1 ile verinin orta %50'sinin yayılımını ölçer ve aykırı değerlere dayanıklıdır. MAD sapmaların mutlak değerlerinin ortalaması ya da medyanıdır. Son olarak Varyasyon Katsayısı (CV = σ/μ) birimsizdir ve farklı ölçekteki iki dağılımın göreli değişkenliğini karşılaştırmaya yarar.
# IQR ile klasik aykırı değer sınırlarını hesaplama — pandas
gelir = pd.Series([30, 32, 33, 35, 36, 38, 40, 250])
Q1, Q3 = gelir.quantile(0.25), gelir.quantile(0.75)
IQR = Q3 - Q1
alt, ust = Q1 - 1.5 * IQR, Q3 + 1.5 * IQR
aykiri = gelir[(gelir < alt) | (gelir > ust)]
print("IQR:", IQR)
print("Aykırı değerler:", aykiri.tolist()) # [250]
# Varyasyon katsayısı — birimsiz karşılaştırma
cv = gelir.std() / gelir.mean()
print("CV:", round(cv, 2))3. Dağılımın Şekli: Çarpıklık ve Basıklık
Aynı ortalama ve standart sapmaya sahip dağılımlar bile çok farklı şekillerde olabilir. İki metrik bu şekli özetler.
Skewness (Çarpıklık) dağılımın simetriden ne kadar saptığını gösterir. Pozitif çarpıklıkta sağ kuyruk uzundur ve ortalama, medyandan büyüktür; negatif çarpıklıkta tersi geçerlidir. Kurtosis (Basıklık) ise kuyruk yoğunluğunu ve uç değer eğilimini ölçer. Normal dağılımın kurtosis değeri 3'tür; bu yüzden çoğu kütüphane excess kurtosis (kurtosis − 3) raporlar, böylece normal dağılım için değer sıfır olur.
Kurtosis türü | Anlamı | Kuyruk |
|---|---|---|
Leptokurtic | Excess kurtosis > 0 | Kalın kuyruk — uç değerlere yatkın |
Mesokurtic | Excess kurtosis ≈ 0 | Normale yakın |
Platykurtic | Excess kurtosis < 0 | İnce kuyruk — uç değer az |
# Çarpıklık ve basıklığı ölçmek — pandas doğrudan verir
import pandas as pd
import numpy as np
saga_carpik = pd.Series(np.random.exponential(scale=2, size=10000))
print("Skewness:", round(saga_carpik.skew(), 2)) # pozitif → sağ kuyruk
print("Kurtosis:", round(saga_carpik.kurtosis(), 2)) # excess kurtosis (Fisher)4. Ölçeklendirme: Farklı birimleri ortak bir dile çevirmek
Modeller, ölçekleri çok farklı değişkenlerle (yaş ile gelir gibi) çalışırken zorlanır. Ölçeklendirme bu değişkenleri karşılaştırılabilir hale getirir.
Z-Score (Standart Skor) bir değerin ortalamadan kaç standart sapma uzakta olduğunu söyler: z = (x − μ) / σ. Aykırı değer tespitinde de sık kullanılır — genelde |z| > 3 eşiği bir işaret sayılır. Percentile / Quantile ise bir değerin altında verinin ne kadarının kaldığını gösterir.
İki yaygın ölçeklendirme yaklaşımı vardır: Min-Max normalizasyonu değerleri [0, 1] aralığına sıkıştırır ama aykırı değerlere duyarlıdır; Robust Scaling ise medyan ve IQR kullandığı için aykırı değerlere dayanıklıdır.
scikit-learn bu üç yaklaşımı tek tip bir arayüzle sunar scikit-learn
from sklearn.preprocessing import StandardScaler, MinMaxScaler, RobustScaler
import numpy as np
X = np.array([[25], [30], [35], [40], [200]]) # 200 = aykırı değer
print("Z-score :", StandardScaler().fit_transform(X).ravel().round(2))
print("Min-Max :", MinMaxScaler().fit_transform(X).ravel().round(2))
print("Robust :", RobustScaler().fit_transform(X).ravel().round(2))Neden fit ve transform ayrı? scikit-learn'de ölçekleyiciyi yalnızca eğitim verisiyle fit eder, aynı parametrelerle test verisini transform edersin. Test verisinin istatistiklerini modele sızdırmamak (data leakage) için bu ayrım kritiktir.
5. Olasılık Dağılımları ve İki Temel Teorem
Verinin arkasındaki süreci modellemek için olasılık dağılımlarını kullanırız. En bilineni, çan eğrisi şeklindeki Normal (Gaussian) dağılımdır ve meşhur 68–95–99.7 kuralına uyar: veri sırasıyla ±1σ, ±2σ ve ±3σ içinde bu oranlarda toplanır. Bunun yanında tek denemeli Bernoulli, n bağımsız denemeli Binomial, sabit bir aralıktaki nadir olayları modelleyen Poisson ve ayrıca Uniform, Exponential, Geometric dağılımlar sık karşımıza çıkar.
İki teorem tüm çıkarımsal istatistiğin bel kemiğidir. Merkezi Limit Teoremi (CLT), ana dağılımın şekli ne olursa olsun, yeterince büyük örneklem ortalamalarının dağılımının normale yaklaşacağını söyler. Büyük Sayılar Yasası (LLN) ise örneklem büyüdükçe örneklem ortalamasının gerçek popülasyon ortalamasına yakınsayacağını ifade eder. İkisi benzer görünse de farklıdır: LLN bir sayının nereye yakınsadığını, CLT ise onun etrafındaki dağılımın şeklini anlatır.
# CLT'yi gözle görmek: çarpık bir dağılımdan alınan
# örneklem ortalamaları normale yaklaşır
import numpy as np
rng = np.random.default_rng(42)
anakütle = rng.exponential(scale=2.0, size=1_000_000) # hiç normal değil
# 5000 kez, 40'ar örneklik gruplar çek ve ortalamalarını topla
ortalamalar = [rng.choice(anakütle, 40).mean() for _ in range(5000)]
print("Anakütle çarpıklığı:", round(float(np.mean(anakütle)), 2))
print("Ortalamaların std'si:", round(float(np.std(ortalamalar)), 3))
# ortalamalar histogramı çizilirse çan eğrisi görülür6. Karışıklık Matrisi ve Sınıflandırma Metrikleri
Bir sınıflandırma modelini "doğruluk %92" diye özetlemek çoğu zaman aldatıcıdır. Gerçek resim, modelin ne tür hatalar yaptığını gösteren karışıklık matrisinde gizlidir. İkili sınıflandırmada bu matris dört hücreden oluşur:
Gerçek: Pozitif | Gerçek: Negatif | |
|---|---|---|
Tahmin: Pozitif | TP — doğru pozitif | FP — yanlış pozitif (Tip I hata) |
Tahmin: Negatif | FN — yanlış negatif (Tip II hata) | TN — doğru negatif |
Buradaki iki hata türü istatistikteki iki temel hataya karşılık gelir: Tip I hata (α) yanlış pozitiftir, yani doğru olan sıfır hipotezini yanlışlıkla reddetmektir. Tip II hata (β) yanlış negatiftir; testin gücü ise 1 − β ile hesaplanır.
Metrikleri okumak
Accuracy (Doğruluk) doğru tahminlerin tüm tahminlere oranıdır. Sezgisel ama tehlikeli: 100 kişiden 1'inin hasta olduğu bir veride "herkes sağlıklı" diyen model %99 doğruluk alır — hiçbir hastayı yakalamadan. Bu yüzden dengesiz sınıflarda Balanced Accuracy ya da veri içindeki gerçek pozitif oranı olan Prevalence / Base Rate dikkate alınmalıdır.
Asıl ayrımı Precision ve Recall yapar:
Precision = TP / (TP + FP) · Recall = TP / (TP + FN) · Specificity = TN / (TN + FP)
Precision, "pozitif dediklerimin ne kadarı gerçekten pozitif?" sorusunu yanıtlar ve yanlış alarm maliyeti yüksek olduğunda (örneğin bir e-postayı yanlışlıkla spam işaretlemek) kritiktir. Recall ise "gerçek pozitiflerin ne kadarını yakaladım?" sorusunu sorar ve kaçırma maliyeti yüksek olduğunda (örneğin bir kanser vakasını gözden kaçırmak) hayati önem taşır. Specificity ise gerçek negatiflerin yakalanma oranını ölçer.
Precision ile Recall genellikle birbiriyle çelişir; ikisini dengeleyen tek sayı F1-Score'dur — ve bu, ikisinin harmonik ortalamasıdır (aritmetik değil, çünkü harmonik ortalama düşük olan değeri cezalandırır). Scikit-learn tüm bunları tek bir raporda toplar.
from sklearn.metrics import confusion_matrix, classification_report
# 1 = pozitif (ör. hasta), 0 = negatif (ör. sağlıklı)
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(confusion_matrix(y_gercek, y_tahmin))
# [[TN FP]
# [FN TP]]
print(classification_report(y_gercek, y_tahmin, digits=3))
# precision, recall, f1-score ve support sütunlarını tek tabloda verirMetrikleri sıfırdan hesaplayarak formüllerin ne yaptığını netleştirmek de öğreticidir numpy
import numpy as np
y_gercek = np.array([1, 0, 1, 1, 0, 1, 0, 0, 1, 0])
y_tahmin = np.array([1, 0, 0, 1, 0, 1, 1, 0, 1, 0])
TP = np.sum((y_tahmin == 1) & (y_gercek == 1))
FP = np.sum((y_tahmin == 1) & (y_gercek == 0))
FN = np.sum((y_tahmin == 0) & (y_gercek == 1))
TN = np.sum((y_tahmin == 0) & (y_gercek == 0))
precision = TP / (TP + FP)
recall = TP / (TP + FN)
f1 = 2 * precision * recall / (precision + recall)
print(f"Precision: {precision:.3f}")
print(f"Recall : {recall:.3f}")
print(f"F1-Score : {f1:.3f}")Metrik seçimi bir iş kararıdır: Precision mi Recall mı önemli sorusunun cevabı modelde değil, hatanın maliyetinde saklıdır. Bir dolandırıcılık dedektöründe kaçırılan işlem (düşük recall) çok pahalıysa recall'ı; müşteriyi rahatsız eden yanlış alarmlar (düşük precision) sorunsa precision'ı önceliklendirirsin.
Tanımlayıcı istatistik, modelleme öncesi verinin karakterini tanıma sanatıdır. Merkezi eğilim sana "tipik" değeri, yayılım ölçüleri belirsizliği, şekil metrikleri dağılımın kişiliğini, ölçeklendirme ise değişkenleri ortak bir dile çevirmeyi verir. Karışıklık matrisi ve türevleri ise modelin performansını tek bir aldatıcı sayının ötesinde, hatanın türüne göre okumanı sağlar.
Bu temeller sağlam oturduğunda, bir sonraki katmana — regresyon metrikleri, ROC eğrileri ve hipotez testlerine — çok daha güvenli adım atarsın. Çünkü her ileri teknik, buradaki kavramların üzerine inşa edilir.
Kod örneklerini kendi verinle çalıştırarak denemeni öneririm; bir metriği elle hesaplamak, onu ezberlemekten çok daha kalıcı bir sezgi bırakır.



