Normal Dağılım, Z-Score, Modified Z-Score ve MAD: Anomaly Detection'ın İstatistiksel Aleti
Normal dağılımın anomaly detection için anlamı; z-score formülü, sezgisi ve sınırları; modified z-score ve MAD (Median Absolute Deviation) — outlier'a dirençli alternatifler; from-scratch Python implementasyon.
Şükrü Yusuf KAYA
30 dakikalık okuma
Başlangıç📐 Matematik korkma — sezgi önce
Bu modülde formüller var. Ama formülle başlamayacağız. Önce sezgi, sonra görsel, en son denklem. Bu yolu izlediğinde z-score gibi 100 yaşındaki bir aracın bugün hâlâ neden production'da yaşadığını kavrarsın. Lab bölümünde de hepsini Python'dan sıfırdan yazacağız — kütüphane değil. Anlamak için bir kez kendi elinle yapmalısın.
Normal Dağılım Neden Bu Kadar Önemli?#
İstatistik literatürünün belkemiği: normal dağılım (Gauss, bell curve).
Birçok doğal olay normal dağılır — ama hepsi değil. Anomaly detection'da
normal dağılımı bilmemiz iki nedenle:
-
Pek çok istatistiksel test normal varsayar. Z-score, t-test, Grubbs — hepsinin altında "veri normal dağılıyor" varsayımı var. Bu varsayım bozulursa yanlış cevap alırsın.
-
"Normal" olduğunu varsaydığımız davranış pratikte sıklıkla normal dağılmaz. Örneğin kart işlem tutarları log-normal, web request süresi Pareto-tail, sensör okumaları multi-modal. Doğru dağılımı tanımak, doğru aracı seçmektir.
Normal Dağılımın Yoğunluk Fonksiyonu#
Bir tek-değişkenli normal dağılımın olasılık yoğunluk fonksiyonu (PDF):
Burada:
- μ (mu) — dağılımın merkezi (ortalama)
- σ (sigma) — dağılımın yayılımı (standart sapma)
- Eğri simetrik, çan şeklinde
- Toplam alan = 1 (olasılık aksiyomu)
68-95-99.7 Kuralı (Empirical Rule)#
Normal bir dağılımda:
- %68 veri μ ± 1σ aralığında
- %95 veri μ ± 2σ aralığında
- %99.7 veri μ ± 3σ aralığında
Bu kural, z-score ile anomaly detection'ın altyapısıdır: 3σ dışında kalan bir gözlemi anomali olarak işaretlersek, normal dağılan veride sadece %0.3 false positive yaparız. 4σ → %0.006, 5σ → %0.00006.
Z-Score: Standart Sapma Cinsinden Mesafe#
Bir gözlemin kaç sigma uzakta olduğunu söyleyen ölçü:
Sezgi: z-score "bu gözlem dağılımın merkezinden kaç sigma uzakta?" sorusunun cevabı.
| |z| değeri | Yorum | Empirical olasılık (normal'de) |
|---|---|---|---|
| 0 | Merkezde | – |
| 1 | Tipik | %68 içinde |
| 2 | Az aykırı | %95 içinde |
| 3 | Outlier şüphesi | %99.7 içinde |
| 4 | Güçlü outlier | %99.994 içinde |
| 5 | Aşırı outlier | %99.99994 içinde |
| 6+ | Pratikte imkansız (normal'de) | – |
Pratik kural: |z| > 3 outlier eşiği geleneksel kabul. Ama dağılım normal değilse bu kural yanıltıcı olabilir.
python
import numpy as np def z_score(x, axis=None): """ Klasik z-score: (x - mean) / std """ mu = np.mean(x, axis=axis, keepdims=True) sigma = np.std(x, axis=axis, ddof=0, keepdims=True) return (x - mu) / (sigma + 1e-9) # küçük epsilon ile sıfıra bölmeyi önle # Kullanımnp.random.seed(42)data = np.random.normal(loc=100, scale=15, size=1000)data = np.append(data, [200, 250, 300]) # 3 outlier ekle z = z_score(data)outliers = np.where(np.abs(z) > 3)[0]print(f"Outlier sayısı (|z|>3): {len(outliers)}")print(f"Outlier değerler: {data[outliers]}")Z-score implementasyonu — from scratch
Z-Score'un Sinsi Zayıflığı: Masking#
Z-score basit ve hızlı, ama bir sorunu var: kendi outlier'larına karşı duyarlı.
Mean ve std outlier'lardan etkilenir. Sonuç: birkaç büyük outlier, kendi
z-score'larını küçük gösterir ve diğer gerçek outlier'ları gizler.
Bu fenomene literatürde "masking" denir.
Somut Örnek#
Diyelim ki 100 normal değer (μ=100, σ=10) + 5 outlier (değer=500) var:
data = np.concatenate([np.random.normal(100, 10, 100), [500]*5]) mu = data.mean() # ≈ 119 ← outlier'lar mean'i yukarı çekti sigma = data.std() # ≈ 78 ← outlier'lar std'yi büyüttü # Bir outlier'ın z-score'u: z_outlier = (500 - 119) / 78 # ≈ 4.88 # 4.88 büyük ama 3 sigma kuralıyla yine de yakalanır # Şimdi normal bir 130 değerini düşün: z_normal = (130 - 119) / 78 # ≈ 0.14 # 0.14 — değer normalmiş gibi görünüyor
Masking sorunu büyük outlier kümeleri olduğunda gerçek outlier'ları
saklar. Bu, anomaly detection'da kritik problem — özellikle DDoS attack
gibi senaryolarda yüz binlerce outlier birlikte gelir.
🛡️ Robust istatistik ihtiyacı
Z-score'un kendi outlier'larına karşı kırılganlığı, robust istatistik alanını doğurdu: outlier'lara karşı dirençli istatistikler kullanmak. Bunun en yaygın aracı: median + MAD.
MAD: Median Absolute Deviation#
MAD, "median'dan medyan mutlak sapma" anlamına gelir. Outlier'a karşı çok
daha dirençlidir:
Neden Robust?#
Hatırla: medyan, dizinin ortasındaki değerdir. Bir outlier'ın medyana etkisi
minimal. Bir outlier'ın mean'e etkisi büyük.
Breakdown point:
- Mean: %0 — bir tek outlier mean'i istediğin kadar bozar
- Median: %50 — verinin yarısı outlier olsa bile median değişmez
MAD aynı %50 breakdown point'i taşır. Bu, "verinin %49'u kötü olsa bile MAD
hâlâ çalışır" demek.
Modified Z-Score (MAD-based)#
Klasik z-score'un MAD versiyonu:
Buradaki 0.6745 sihirli sayı değil — normal dağılım altında MAD'in
standart sapmaya yaklaşması için gerekli ölçeklendirme. (Iglewicz ve
Hoaglin, 1993)
Modified Z-Score Eşiği#
| |M| değeri | Yorum |
|---|---|
| 0 | Median'da |
| 2 | Az aykırı |
| 3.5 | Outlier şüphesi (geleneksel eşik) |
| 5+ | Güçlü outlier |
Iglewicz-Hoaglin önerisi: |M| > 3.5 outlier eşiği. Klasik z-score'daki 3'ten neden farklı? Çünkü MAD daha "konservatif" ölçek; aynı outlier rate'i tutmak için biraz daha yüksek eşik gerek.
python
def mad(x): """Median Absolute Deviation""" med = np.median(x) return np.median(np.abs(x - med)) def modified_z_score(x): """Modified z-score with MAD""" med = np.median(x) m = mad(x) if m == 0: # Tüm değerler aynıysa — MAD = 0 — fallback'e dön return np.zeros_like(x, dtype=float) return 0.6745 * (x - med) / m # Yukarıdaki masking örneğini tekrar denedata = np.concatenate([np.random.normal(100, 10, 100), [500]*5]) # Klasik z-scorez = z_score(data)print(f"Klasik z-score outlier sayısı (|z|>3): {(np.abs(z) > 3).sum()}") # Modified z-score (MAD-based)m = modified_z_score(data)print(f"Modified z-score outlier sayısı (|M|>3.5): {(np.abs(m) > 3.5).sum()}")MAD + Modified Z-Score implementasyonu
Z-Score vs Modified Z-Score: Yan Yana Karşılaştırma#
| Özellik | Klasik Z-Score | Modified Z-Score (MAD) |
|---|---|---|
| Merkez ölçüsü | Mean | Median |
| Yayılım ölçüsü | Std sapma | MAD |
| Breakdown point | %0 | %50 |
| Hesaplama | Hızlı | Orta |
| Outlier dirençi | Düşük | Yüksek |
| Normal varsayımı | Güçlü | Hafif |
| Eşik | z | |
| Production tercihi | Çok aza | Yaygın |
Hangisini Ne Zaman?#
- Klasik z-score: Veri kesinlikle (veya neredeyse kesinlikle) normal dağılan; outlier oranı çok düşük (<%1); hız kritik.
- Modified z-score: Veri kirli olabilir; outlier oranı orta-yüksek (%5+); robust gerekiyor.
- Pratik öneri: Üretimde başlangıç olarak modified z-score; klasik z-score'a yalnızca normal-varsayan bir test (Grubbs) çıktısını besliyorsan dön.
Pratik İpucu: Log-Normal Veri için Önce Log Al#
Çoğu finansal veri log-normal dağılır (kart işlem tutarı, gelir, gecikme
süreleri). Doğrudan z-score yanlış cevap verir. Önce veya
uygula, sonra z-score:
loglog1p# Yanlış yaklaşım amounts = [100, 150, 200, ..., 50000, 80000] # tutarlar log-normal z = z_score(amounts) # Büyük tutarlar abartılı z-score alır # Doğru yaklaşım log_amounts = np.log1p(amounts) z = z_score(log_amounts) # Daha düzgün dağılım, sağlıklı z-score
Modül 3'te (Veri Hazırlığı) bu dönüşümleri sistematik ele alacağız.
💼 Production Pearl
Türk bir bankada fraud feature pipeline'ı 2023'te z-score'lardan modified z-score'lara geçti. Sadece bu değişiklikle fraud detection PR-AUC'ı %4 arttı, alarm false positive %12 düştü. Bir kelime: 'mean'i median' yap. Sermaye getirisi: aylık ~600K TL analist saati.
Bu Yöntemlerin Sınırları#
Z-score ve MAD güçlü ama her şey değil. Açık zayıflıkları var:
1. Tek-değişkenli#
Z-score tek özellik üzerinde çalışır. Çok-değişkenli anomalileri yakalayamaz. (Örn: müşterinin kombinasyonu "yüksek tutar + yeni alıcı + gece saati" anomali; tek tek hepsi normal.) Bunun için Mahalanobis distance (Modül 8) lazım.
2. Statik#
Anlık dağılımdan z-score hesaplıyorsun. Zamana göre değişen dağılım (concept drift) yakalanmaz. Rolling z-score gerekir.
3. Dağılımı varsayar#
"Z-score 3" eşiği normal dağılımda %0.3 yapar. Pareto-tail dağılımda çok daha
fazla false positive üretir. EVT/POT (Modül 2.4) bunun çözümü.
4. Bağlamı bilmez#
Z-score "müşterinin profili" gibi bağlamı modele entegre etmez. Bu, Modül
1.2'deki contextual anomaly tipinin sınırı.
Bu sınırların hepsini sonraki modüllerde aşacağız. Şu an için z-score + MAD
ikilisi temel taşı — tüm sonraki yöntemler bu üstüne bina ediliyor.
👉 Bir sonraki ders
Ders 2.2 — IQR, Tukey's Fences, Adjusted Boxplot. Çeyrekler ve quartile-based outlier tespiti. Z-score'un kuzenleri ama daha az dağılım varsayımıyla. Skewed (asimetrik) veride z-score'dan üstün.
Sık Sorulan Sorular
Tarihsel bir konvansiyon — Shewhart (1931) kalite kontrol kartları için 3σ önerdi. Empirically, normal dağılımda %0.3 false positive verir. Pratikte sektöre göre 2 (daha duyarlı) veya 4 (daha konservatif) seçilebilir. Modern AD sistemlerinde POT veya percentile tabanlı dinamik eşik tercih ediliyor.
Yorumlar & Soru-Cevap
(0)Yorum yazmak için giriş yap.
Yorumlar yükleniyor...
İlgili İçerikler
Modül 0: Kurs Çerçevesi ve Atölye Kurulumu
Anomaly Detection Engineer Kimdir? Fraud, SRE, Quality Engineer ile Farklar ve Türkiye Maaş Manzarası
Öğrenmeye BaşlaModül 0: Kurs Çerçevesi ve Atölye Kurulumu
Kurs Felsefesi: Neden Bu Yol, Neden Bu Sıra — Anomaly Detection Öğrenme Nehri
Öğrenmeye BaşlaModül 0: Kurs Çerçevesi ve Atölye Kurulumu