İstatistik

Veri Bilimi ve Yapay Zeka için Lisans Seviyesi İstatistik Eğitimi

μ = Σxi/n

İstatistik Nedir ve Neden Önemlidir?

İstatistik, verileri toplama, düzenleme, analiz etme ve yorumlama bilimi ve sanatıdır. Modern dünyadaki veri patlaması ile birlikte, istatistik yapay zeka, makine öğrenmesi ve veri bilimi alanlarının temel taşı haline gelmiştir.

İstatistik, belirsizlik altında karar verme süreçlerinde matematiksel yöntemler kullanarak objektif sonuçlar elde etmemizi sağlar. Özellikle büyük veri setleriyle çalışırken, veriden anlamlı bilgiler çıkarabilmek için istatistiksel yöntemlere ihtiyaç duyarız.

💡 Veri Bilimi İçin Neden Önemli:
• Veri kalitesini değerlendirme
• Model performansını ölçme
• Belirsizlikleri quantify etme
• A/B testleri ve deneysel tasarım
• Makine öğrenmesi algoritmalarının teorik temeli
İstatistiğin Ana Dalları:
  • Betimsel İstatistik: Verileri özetleme ve tanımlama
  • Çıkarımsal İstatistik: Örneklemden evren hakkında çıkarım yapma
  • Bayesian İstatistik: Önsel bilgiyi kullanan yaklaşım
  • Deneysel Tasarım: Verimli deney planlama
  • Zaman Serisi Analizi: Zamansal verilerin analizi
Tarihsel Gelişim
İstatistik kelimesi Latince "status" (devlet) kelimesinden gelir. İlk kullanımı 17. yüzyılda devlet verilerinin analizi için başlamıştır. Gauss, Bayes, Fisher gibi matematikçiler modern istatistiğin temellerini atmışlardır.

Günümüzde istatistik sadece akademik bir disiplin değil, aynı zamanda teknoloji şirketlerinde, finansal kuruluşlarda, sağlık sektöründe ve hemen her alanda kritik kararların alınmasında kullanılan pratik bir araçtır.

Temel İstatistik Kavramları

İstatistiksel analizlerde kullanılan temel kavramları anlamak, daha karmaşık konulara geçiş için kritik öneme sahiptir. Bu kavramlar, veri bilimi projelerinin her aşamasında karşımıza çıkar.

Evren (Population) ve Örneklem (Sample)
Evren (N): İncelenmek istenen tüm birimler kümesi
Örneklem (n): Evrenden seçilen temsilci alt küme
Örnek: Türkiye'deki tüm üniversite öğrencileri (evren), 1000 öğrenci (örneklem)
Parametre ve İstatistik
Parametre: Evrenin karakteristiğini tanımlayan sayısal değer (μ, σ)
İstatistik: Örneklemden hesaplanan değer (x̄, s)
Parametreler genellikle bilinmez, istatistiklerle tahmin edilir.
Değişken (Variable) Türleri
Bağımsız Değişken (X): Tahmin edici, açıklayıcı
Bağımlı Değişken (Y): Tahmin edilen, açıklanan
Kontrol Değişkeni: Etkisi sabit tutulan değişken
Önemli Not: Örneklem büyüklüğü (n ≥ 30) yeterli olmalı ve evren için temsil edici olmalıdır. Bias'lı örneklemler yanıltıcı sonuçlara yol açar.
Kavram Sembol Açıklama Örnek
Evren Ortalaması μ (mu) Tüm evrenin ortalama değeri Türkiye nüfusunun ortalama yaşı
Örneklem Ortalaması x̄ (x-bar) Örneklemin ortalama değeri 1000 kişilik örneklemin ortalama yaşı
Evren Standart Sapması σ (sigma) Evrendeki değişkenlik ölçüsü Nüfusun yaş dağılımının değişkenliği
Örneklem Standart Sapması s Örneklemdeki değişkenlik ölçüsü Örneklemin yaş dağılımının değişkenliği

Veri Türleri ve Ölçüm Düzeyleri

Veri türlerini doğru bir şekilde tanımlamak, uygun istatistiksel yöntemleri seçmek için kritik öneme sahiptir. Her veri türü farklı analiz teknikleri gerektirir.

Nominal (Kategorik) Veri
Özellikler: Sınıflandırma amaçlı, sıralama yok
Örnekler: Cinsiyet, renk, medeni durum, marka
İstatistikler: Mod, frekans, Ki-kare testi
ML'de kullanım: One-hot encoding, label encoding
Ordinal (Sıralı) Veri
Özellikler: Sıralama var, mesafe sabit değil
Örnekler: Eğitim seviyesi, memnuniyet derecesi, film ratingleri
İstatistikler: Medyan, percentile, Spearman korelasyon
ML'de kullanım: Ordinal encoding, rank features
Interval (Aralık) Veri
Özellikler: Eşit aralıklar, mutlak sıfır yok
Örnekler: Sıcaklık (Celsius), IQ skoru, tarih
İstatistikler: Ortalama, standart sapma, t-testi
ML'de kullanım: Direkt kullanım, normalizasyon
Ratio (Oran) Veri
Özellikler: Mutlak sıfır var, oransal karşılaştırma mümkün
Örnekler: Yaş, gelir, ağırlık, hız
İstatistikler: Tüm istatistiksel ölçüler
ML'de kulanım: En esnek, tüm matematiksel işlemler
Veri Bilimi İçin Kritik Noktalar:
  • Feature Engineering: Kategorik verileri sayısal forma dönüştürme
  • Missing Data: Farklı veri türleri için farklı imputation stratejileri
  • Outlier Detection: Sadece interval/ratio veriler için uygun
  • Correlation Analysis: Veri türüne göre uygun korelasyon katsayısı seçimi
# Python ile Veri Türü Kontrolü
import pandas as pd
import numpy as np

# Veri setini yükle
df = pd.read_csv('dataset.csv')

# Veri türlerini kontrol et
print(df.dtypes)
print(df.info())

# Kategorik sütunları belirle
categorical_cols = df.select_dtypes(include=['object']).columns
numerical_cols = df.select_dtypes(include=[np.number]).columns

print(f"Kategorik sütunlar: {list(categorical_cols)}")
print(f"Sayısal sütunlar: {list(numerical_cols)}")
Dikkat: Sayısal olarak kodlanmış kategorik veriler (örn: 1=Erkek, 2=Kadın) yanıltıcı olabilir. Bu veriler üzerinde aritmetik işlemler yapmak mantıksızdır.

Merkezi Eğilim Ölçüleri

Merkezi eğilim ölçüleri, veri setinin "tipik" değerini temsil eder. Veri biliminde, verilerin genel eğilimini anlamak ve karşılaştırmalar yapmak için kullanılır.

Aritmetik Ortalama (Mean)
En yaygın kullanılan merkezi eğilim ölçüsü. Tüm değerlerin toplamının gözlem sayısına bölümü.
μ = (Σxi)/N     x̄ = (Σxi)/n
μ: Evren ortalaması, x̄: Örneklem ortalaması, N: Evren büyüklüğü, n: Örneklem büyüklüğü
Örnek: Bir sınıftaki öğrencilerin notları: 75, 82, 91, 68, 79, 85, 77
Çözüm:
x̄ = (75 + 82 + 91 + 68 + 79 + 85 + 77) / 7 = 557 / 7 = 79.57
Medyan (Median)
Sıralanmış verilerin ortadaki değeri. Aykırı değerlerden etkilenmez (robust).
# Medyan hesaplama
# Tek sayıda gözlem: Ortadaki değer
# Çift sayıda gözlem: Ortadaki iki değerin ortalaması

data = [68, 75, 77, 79, 82, 85, 91]  # Sıralanmış
n = len(data)  # 7 (tek sayı)

if n % 2 == 1:
    median = data[n // 2]  # data[3] = 79
else:
    median = (data[n//2 - 1] + data[n//2]) / 2

print(f"Medyan: {median}")
Medyan: 79
Mod (Mode)
En sık tekrar eden değer. Kategorik veriler için en uygun merkezi eğilim ölçüsü.
Hangi Ölçüyü Ne Zaman Kullanmalı:
  • Normal dağılım: Ortalama kullanın
  • Çarpık dağılım: Medyan kullanın
  • Aykırı değerler var: Medyan daha uygun
  • Kategorik veri: Mod kullanın
  • Makine öğrenmesi: Ortalama genellikle tercih edilir
💡 Veri Bilimi İpucu: Feature engineering sırasında, sayısal verilerin missing değerlerini doldururken distribution'a dikkat edin. Normal dağılımda ortalama, çarpık dağılımda medyan kullanın.
# Python ile merkezi eğilim hesaplama
import numpy as np
import pandas as pd
from scipy import stats

data = [75, 82, 91, 68, 79, 85, 77, 82, 82]

# Ortalama
mean = np.mean(data)
print(f"Ortalama: {mean:.2f}")

# Medyan
median = np.median(data)
print(f"Medyan: {median}")

# Mod
mode_result = stats.mode(data)
print(f"Mod: {mode_result.mode[0]}")

# Pandas ile
df = pd.DataFrame({'scores': data})
print(f"\nPandas ile:")
print(f"Ortalama: {df['scores'].mean():.2f}")
print(f"Medyan: {df['scores'].median()}")
print(f"Mod: {df['scores'].mode().values[0]}")
Ortalama: 80.11
Medyan: 82.0
Mod: 82

Dağılım (Variability) Ölçüleri

Dağılım ölçüleri, verilerin merkezi eğilim etrafında ne kadar yayıldığını gösterir. Makine öğrenmesinde feature scaling, outlier detection ve model stability için kritik öneme sahiptir.

Range (Ranj)
En basit dağılım ölçüsü. Maksimum ile minimum değer arasındaki fark.
Range = Max(X) - Min(X)
Aykırı değerlerden çok etkilenir, bu nedenle tek başına yeterli değildir.
Varyans (Variance)
Gözlemlerin ortalamadan sapımlarının kareler ortalaması. İstatistiğin en önemli kavramlarından biri.
σ2 = Σ(xi - μ)2/N     s2 = Σ(xi - x̄)2/(n-1)
σ²: Evren varyansı (N ile böl), s²: Örneklem varyansı (n-1 ile böl - Bessel düzeltmesi)
Neden n-1? Örneklem varyansında n-1 ile bölmek (Bessel düzeltmesi) yansız tahmin (unbiased estimate) sağlar. Bu, evren varyansının underestimate edilmesini önler.
Standart Sapma (Standard Deviation)
Varyansın karekökü. Orijinal verilerle aynı birimde olduğu için yorumlanması daha kolaydır.
σ = √(σ2)     s = √(s2)
En yaygın kullanılan dağılım ölçüsü. Normal dağılımda %68 veri ±1σ içinde yer alır.
Örnek: Günlük satış rakamları: [120, 135, 98, 142, 156, 88, 167]
Adım 1: Ortalama = (120+135+98+142+156+88+167)/7 = 129.43
Adım 2: Sapımlar = [-9.43, 5.57, -31.43, 12.57, 26.57, -41.43, 37.57]
Adım 3: Kare sapımlar = [88.93, 31.02, 987.84, 158.00, 706.96, 1716.44, 1411.50]
Adım 4: s² = 4100.69/6 = 683.45
Adım 5: s = √683.45 = 26.14
# Python ile dağılım ölçüleri
import numpy as np
import pandas as pd

data = [120, 135, 98, 142, 156, 88, 167]

# Temel istatistikler
mean = np.mean(data)
print(f"Ortalama: {mean:.2f}")

# Range
range_val = np.max(data) - np.min(data)
print(f"Range: {range_val}")

# Varyans ve standart sapma
# ddof=1 -> n-1 ile böl (örneklem varyansı)
variance = np.var(data, ddof=1)
std_dev = np.std(data, ddof=1)

print(f"Varyans: {variance:.2f}")
print(f"Standart Sapma: {std_dev:.2f}")

# Pandas ile
df = pd.DataFrame({'sales': data})
print(f"\nPandas describe:")
print(df.describe())
Ortalama: 129.43
Range: 79
Varyans: 683.45
Standart Sapma: 26.14
Varyasyon Katsayısı (CV)
Standart sapmanın ortalamaya oranı. Farklı birimlerdeki verileri karşılaştırmak için kullanılır.
CV = (s/x̄) × 100%
CV < %15: Düşük değişkenlik, CV > %35: Yüksek değişkenlik
💡 ML İçin Önemli: Feature scaling yaparken StandardScaler (z-score normalization) standart sapmayı kullanır: z = (x - μ)/σ. Bu, tüm feature'ları aynı ölçeğe getirir.
Quartile ve IQR
Q1 (25. percentile): Verilerin %25'i bu değerin altında
Q3 (75. percentile): Verilerin %75'i bu değerin altında
IQR = Q3 - Q1: Robust dağılım ölçüsü (outlier'lara duyarsız)
# Quartile ve outlier detection
import numpy as np

data = [120, 135, 98, 142, 156, 88, 167, 200, 45]  # 200 ve 45 potansiyel outlier

Q1 = np.percentile(data, 25)
Q3 = np.percentile(data, 75)
IQR = Q3 - Q1

# Outlier sınırları
lower_bound = Q1 - 1.5 * IQR
upper_bound = Q3 + 1.5 * IQR

print(f"Q1: {Q1}")
print(f"Q3: {Q3}")
print(f"IQR: {IQR}")
print(f"Outlier sınırları: [{lower_bound:.1f}, {upper_bound:.1f}]")

# Outlier'ları tespit et
outliers = [x for x in data if x < lower_bound or x > upper_bound]
print(f"Outlier'lar: {outliers}")
Q1: 98.0
Q3: 156.0
IQR: 58.0
Outlier sınırları: [11.0, 243.0]
Outlier'lar: []

Olasılık Teorisi Temelleri

Olasılık teorisi, belirsizlik altında karar vermenin matematiksel temeli olup makine öğrenmesi algoritmalarının çoğunun dayandığı temel yapıdır. Bayesian yöntemler, neural network'ler ve birçok ML algoritması olasılık prensiplerini kullanır.

P(A) = n(A) / n(S)
P(A): A olayının olasılığı, n(A): A olayının çıkma sayısı, n(S): Tüm mümkün sonuçlar
Olasılık Aksiyomları
1. Non-negatif: P(A) ≥ 0
2. Normallik: P(S) = 1 (tüm olasılıklar toplamı 1)
3. Additivity: Ayrık olaylar için P(A ∪ B) = P(A) + P(B)
Koşullu Olasılık
B olayının gerçekleştiği bilindiğinde A olayının gerçekleşme olasılığı.
P(A|B) = P(A ∩ B) / P(B)
P(A|B): "B verildiğinde A"nın olasılığı, P(A ∩ B): A ve B'nin kesişimi
Örnek: Bir şirkette çalışanların %60'ı mühendis, %40'ı diğer pozisyonlar. Mühendislerin %80'i erkek, diğer pozisyonların %30'u erkek. Rastgele seçilen bir kişinin erkek olma olasılığı nedir?
Çözüm (Toplam Olasılık Yasası):
P(Erkek) = P(Erkek|Mühendis) × P(Mühendis) + P(Erkek|Diğer) × P(Diğer)
P(Erkek) = 0.8 × 0.6 + 0.3 × 0.4 = 0.48 + 0.12 = 0.60
Bayes Teoremi
Makine öğrenmesinin kalbi! Önsel bilgiyi güncel veriyle birleştirerek posteriori olasılık hesaplar.
P(A|B) = P(B|A) × P(A) / P(B)
P(A): Önsel (prior), P(B|A): Likelihood, P(A|B): Posteriori, P(B): Evidence
ML Uygulamaları:
• Naive Bayes Classification
• Bayesian Networks
• MCMC (Markov Chain Monte Carlo)
• A/B Testing ve Conversion Optimization
• Spam filtreleme algoritmaları
# Python ile Bayes Teoremi: Email Spam Detection Örneği
# P(Spam|"offer") = ?

# Önsel bilgiler
P_spam = 0.3  # Emaillerin %30'u spam
P_not_spam = 0.7  # Emaillerin %70'i normal

# Likelihood'lar
P_offer_given_spam = 0.8  # Spam emaillerin %80'inde "offer" kelimesi var
P_offer_given_not_spam = 0.1  # Normal emaillerin %10'unda "offer" kelimesi var

# Evidence (Toplam olasılık yasası)
P_offer = P_offer_given_spam * P_spam + P_offer_given_not_spam * P_not_spam
P_offer = 0.8 * 0.3 + 0.1 * 0.7
print(f"P(offer) = {P_offer}")

# Bayes Teoremi
P_spam_given_offer = (P_offer_given_spam * P_spam) / P_offer
print(f"P(Spam|offer) = {P_spam_given_offer:.3f}")

# Yorumlama
print(f"'Offer' kelimesi içeren bir email %{P_spam_given_offer*100:.1f} olasılıkla spam'dir")
P(offer) = 0.31
P(Spam|offer) = 0.774
'Offer' kelimesi içeren bir email %77.4 olasılıkla spam'dir
Bağımsızlık
İki olay bağımsızsa: P(A|B) = P(A) ve P(A ∩ B) = P(A) × P(B)
Naive Bayes "Naive" Neden? Tüm feature'ların bağımsız olduğunu varsayar (P(x₁,x₂,...,xₙ|y) = P(x₁|y) × P(x₂|y) × ... × P(xₙ|y)). Gerçekte bu varsayım çoğunlukla yanlıştır, ama algoritma yine de iyi çalışır.

Olasılık Dağılımları

Olasılık dağılımları, rastgele değişkenlerin alabileceği değerlerin ve bu değerlerin olasılıklarının matematiksel tanımıdır. Makine öğrenmesinde veri modellemesi, generative model'ler ve uncertainty quantification için kritik öneme sahiptir.

Normal (Gaussian) Dağılım
En önemli sürekli dağılım. Merkezi Limit Teoremi sayesinde birçok doğal fenomen normal dağılır.
f(x) = (1/σ√(2π)) × e-½((x-μ)/σ)²
μ: ortalama (lokasyon parametresi), σ²: varyans (şekil parametresi), σ: standart sapma
Normal Dağılımın Özellikleri:
  • Simetrik: Ortalama = Medyan = Mod
  • %68 Kuralı: Verilerin %68'i μ ± σ aralığında
  • %95 Kuralı: Verilerin %95'i μ ± 2σ aralığında
  • %99.7 Kuralı: Verilerin %99.7'si μ ± 3σ aralığında
  • Asimptotik: Kuyruklar sıfıra yaklaşır ama hiç dokunmaz
Standart Normal Dağılım (Z-Dağılımı)
μ = 0, σ = 1 olan normal dağılım. Z-score hesaplamaları için kullanılır.
Z = (X - μ) / σ
Z-score: Bir değerin ortalamadan kaç standart sapma uzakta olduğunu gösterir
# Python ile Normal Dağılım
import numpy as np
import matplotlib.pyplot as plt
from scipy import stats

# Normal dağılım parametreleri
mu = 100  # ortalama
sigma = 15  # standart sapma

# Rastgele örnekler üret
np.random.seed(42)
samples = np.random.normal(mu, sigma, 1000)

# Temel istatistikler
print(f"Örneklem Ortalaması: {np.mean(samples):.2f}")
print(f"Örneklem Std: {np.std(samples, ddof=1):.2f}")

# Z-score hesaplama
x_value = 130
z_score = (x_value - mu) / sigma
print(f"X = {x_value} için Z-score: {z_score:.2f}")

# Olasılık hesaplama
prob = stats.norm.cdf(z_score)
print(f"P(X ≤ {x_value}) = {prob:.4f}")

# Kritik değer bulma (üst %5)
critical_value = stats.norm.ppf(0.95, mu, sigma)
print(f"Üst %5'lik kritik değer: {critical_value:.2f}")
Örneklem Ortalaması: 99.73
Örneklem Std: 14.76
X = 130 için Z-score: 2.00
P(X ≤ 130) = 0.9772
Üst %5'lik kritik değer: 124.67
t-Dağılımı (Student's t)
Küçük örneklemlerde (n < 30) kullanılan dağılım. Normal dağılıma benzer ama daha geniş kuyruklar.
t = (x̄ - μ) / (s/√n)
df = n-1 serbestlik derecesi ile. n → ∞ iken normal dağılıma yaklaşır.
Ki-Kare (χ²) Dağılımı
Varyans testleri ve kategorik veri analizlerinde kullanılır. Asimetrik dağılım.
Binomial Dağılım
n bağımsız Bernoulli denemesindeki başarı sayısının dağılımı. A/B testlerde önemli.
P(X = k) = C(n,k) × pk × (1-p)n-k
n: deneme sayısı, k: başarı sayısı, p: başarı olasılığı, C(n,k): kombinasyon
Örnek: Bir web sitesinde conversion rate %5. 100 ziyaretçi geldiğinde, tam 3 kişinin satın alma yapma olasılığı nedir?
Çözüm:
n = 100, k = 3, p = 0.05
P(X = 3) = C(100,3) × (0.05)³ × (0.95)⁹⁷ = 161700 × 0.000125 × 0.0067 ≈ 0.135
# Python ile farklı dağılımlar
from scipy import stats
import numpy as np

# Binomial örneği
n, p = 100, 0.05
prob_3_conversions = stats.binom.pmf(3, n, p)
print(f"Tam 3 conversion olasılığı: {prob_3_conversions:.4f}")

# Poisson dağılımı (rate = np = 5)
lambda_param = 5
prob_3_poisson = stats.poisson.pmf(3, lambda_param)
print(f"Poisson(5) ile tam 3 olasılığı: {prob_3_poisson:.4f}")

# Exponential dağılım (survival analysis)
scale = 2  # ortalama = scale
prob_less_than_1 = stats.expon.cdf(1, scale=scale)
print(f"Exponential(2) ile X < 1 olasılığı: {prob_less_than_1:.4f}")

# Uniform dağılım
a, b = 0, 10
uniform_mean = (a + b) / 2
uniform_var = (b - a)**2 / 12
print(f"Uniform(0,10) ortalama: {uniform_mean}, varyans: {uniform_var:.2f}")
Tam 3 conversion olasılığı: 0.1395
Poisson(5) ile tam 3 olasılığı: 0.1404
Exponential(2) ile X < 1 olasılığı: 0.3935
Uniform(0,10) ortalama: 5.0, varyans: 8.33
ML'de Dağılım Seçimi:
• Normal: Continuous features, regression residuals
• Binomial: Binary classification, A/B testing
• Poisson: Count data, event rates
• Exponential: Time-to-event, survival analysis
• Beta: Probability modeling, Bayesian priors

Örnekleme Teorisi ve Merkezi Limit Teoremi

Örnekleme teorisi, sınırlı verilerden evrene genelleme yapmanın matematiksel temelini oluşturur. Veri biliminde, küçük örneklemlerden büyük veri setleri hakkında çıkarımlar yaparken kritik öneme sahiptir.

Merkezi Limit Teoremi (CLT)
İstatistiğin en önemli teoremlerinden biri. Örneklem büyüklüğü arttıkça, örneklem ortalamalarının dağılımı normal dağılıma yaklaşır.
x̄ ~ N(μ, σ²/n)     Z = (x̄ - μ)/(σ/√n)
σ/√n: Standart hata (Standard Error), n ≥ 30 için CLT geçerlidir
# Merkezi Limit Teoremi Demonstrasyonu
import numpy as np
import matplotlib.pyplot as plt
from scipy import stats

# Ana evren: Uniform dağılım (normal değil!)
np.random.seed(42)
population = np.random.uniform(0, 10, 10000)
pop_mean = np.mean(population)
pop_std = np.std(population)

print(f"Evren ortalaması: {pop_mean:.2f}")
print(f"Evren standart sapması: {pop_std:.2f}")

# Farklı örneklem büyüklükleri için örneklem ortalamaları
sample_sizes = [5, 10, 30, 100]
sample_means = {}

for n in sample_sizes:
    # 1000 kez örneklem al ve ortalamalarını hesapla
    means = []
    for i in range(1000):
        sample = np.random.choice(population, n)
        means.append(np.mean(sample))
    
    sample_means[n] = means
    
    # Örneklem ortalamalarının istatistikleri
    mean_of_means = np.mean(means)
    std_of_means = np.std(means)
    theoretical_std = pop_std / np.sqrt(n)
    
    print(f"\nn = {n}:")
    print(f"  Ortalama: {mean_of_means:.2f} (beklenen: {pop_mean:.2f})")
    print(f"  Std sapma: {std_of_means:.3f} (teorik: {theoretical_std:.3f})")
Evren ortalaması: 5.00
Evren standart sapması: 2.89

n = 5:
  Ortalama: 4.99 (beklenen: 5.00)
  Std sapma: 1.292 (teorik: 1.293)

n = 30:
  Ortalama: 5.00 (beklenen: 5.00)
  Std sapma: 0.527 (teorik: 0.528)
Yansız Tahmin Edici (Unbiased Estimator)
E[θ̂] = θ koşulunu sağlayan tahmin edici. Örneklem ortalaması yansız, ama örneklem varyansı (n ile bölen) yanlı!
Dikkat: Örneklem varyansında n-1 ile bölerek (Bessel düzeltmesi) yansız tahmin elde ederiz. Bu, küçük örneklemlerde özellikle önemlidir.
Güven Aralığı (Confidence Interval)
Evren parametresinin belirli bir olasılıkla içinde bulunduğu aralık. %95 güven aralığı en yaygın kullanılan.
CI = x̄ ± Zα/2 × (σ/√n)
%95 güven için Z₀.₀₂₅ = 1.96, σ bilinmiyorsa t-dağılımı kullan
Örnek: 100 müşterinin ortalama harcaması 250 TL, standart sapma 50 TL. Evren ortalaması için %95 güven aralığı nedir?
Çözüm:
n = 100, x̄ = 250, σ = 50, Z₀.₀₂₅ = 1.96
SE = 50/√100 = 5
CI = 250 ± 1.96 × 5 = 250 ± 9.8 = [240.2, 259.8]
Yorum: Evren ortalaması %95 olasılıkla 240.2-259.8 TL arasındadır.
# Python ile Güven Aralığı Hesaplama
import numpy as np
from scipy import stats

# Veri
sample_mean = 250
sample_std = 50
n = 100
confidence_level = 0.95

# Standart hata
standard_error = sample_std / np.sqrt(n)
print(f"Standart hata: {standard_error}")

# Kritik değer (t-dağılımı, çünkü σ bilinmiyor)
alpha = 1 - confidence_level
df = n - 1


                            
                                0.0 - 0.3
                                Zayıf
                                Neredeyse hiç ilişki yok
                            
                            
                                0.3 - 0.7
                                Orta
                                Belirgin ilişki var
                            
                            
                                0.7 - 0.9
                                Güçlü
                                Kuvvetli ilişki
                            
                            
                                0.9 - 1.0
                                Çok Güçlü
                                Neredeyse mükemmel ilişki
                            
                        
                    

                    
# Python ile Korelasyon Analizi
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
from scipy import stats

# Örnek veri seti oluştur
np.random.seed(42)
n = 100

# Farklı korelasyon örnekleri
x1 = np.random.normal(0, 1, n)
y1 = 2 * x1 + np.random.normal(0, 0.5, n)  # Güçlü pozitif

x2 = np.random.normal(0, 1, n)
y2 = -1.5 * x2 + np.random.normal(0, 1, n)  # Orta negatif

x3 = np.random.normal(0, 1, n)
y3 = x3**2 + np.random.normal(0, 0.5, n)  # Nonlinear (Pearson düşük gösterir)

x4 = np.random.normal(0, 1, n)
y4 = np.random.normal(0, 1, n)  # Bağımsız

# DataFrame oluştur
df = pd.DataFrame({
    'X1': x1, 'Y1': y1,
    'X2': x2, 'Y2': y2,
    'X3': x3, 'Y3': y3,
    'X4': x4, 'Y4': y4
})

# Korelasyon hesaplamaları
correlations = [
    ('X1-Y1 (Güçlü Pozitif)', stats.pearsonr(x1, y1)),
    ('X2-Y2 (Orta Negatif)', stats.pearsonr(x2, y2)),
    ('X3-Y3 (Nonlinear)', stats.pearsonr(x3, y3)),
    ('X4-Y4 (Bağımsız)', stats.pearsonr(x4, y4))
]

print("Pearson Korelasyon Sonuçları:")
print("-" * 45)
for name, (r, p_val) in correlations:
    significance = "***" if p_val < 0.001 else "**" if p_val < 0.01 else "*" if p_val < 0.05 else "ns"
    print(f"{name:<20}: r = {r:6.3f}, p = {p_val:.6f} {significance}")

# Korelasyon matrisi
correlation_matrix = df.corr()
print(f"\nKorelasyon Matrisi:")
print(correlation_matrix.round(3))
Pearson Korelasyon Sonuçları:
---------------------------------------------
X1-Y1 (Güçlü Pozitif) : r = 0.970, p = 0.000000 ***
X2-Y2 (Orta Negatif) : r = -0.848, p = 0.000000 ***
X3-Y3 (Nonlinear) : r = 0.058, p = 0.572079 ns
X4-Y4 (Bağımsız) : r = -0.075, p = 0.459508 ns
Spearman Rank Korelasyonu
Sıralama temelli korelasyon. Nonlinear monotonic ilişkileri yakalar. Outlier'lara daha robust.
ρ = 1 - (6Σd²) / (n(n²-1))
d: Sıralama farkları, monotonic ilişkilerde Pearson'dan daha güçlü
Kendall's Tau
Küçük örneklemlerde daha stable. Concordant ve discordant çiftleri karşılaştırır.
# Farklı korelasyon türleri karşılaştırması
from scipy.stats import pearsonr, spearmanr, kendalltau

# Nonlinear veri için karşılaştırma
x = np.random.uniform(0, 4, 50)
y = x**2 + np.random.normal(0, 2, 50)  # Quadratic ilişki

# Farklı korelasyon türleri
pearson_r, pearson_p = pearsonr(x, y)
spearman_r, spearman_p = spearmanr(x, y)
kendall_r, kendall_p = kendalltau(x, y)

print("Nonlinear İlişki için Korelasyon Karşılaştırması:")
print(f"Pearson r:  {pearson_r:.3f} (p = {pearson_p:.6f})")
print(f"Spearman ρ: {spearman_r:.3f} (p = {spearman_p:.6f})")
print(f"Kendall τ:  {kendall_r:.3f} (p = {kendall_p:.6f})")

# Outlier etkisi
x_clean = np.random.normal(0, 1, 48)
y_clean = 2 * x_clean + np.random.normal(0, 0.5, 48)

# Outlier ekle
x_outlier = np.append(x_clean, [10, -10])
y_outlier = np.append(y_clean, [-5, 15])

print(f"\nOutlier Etkisi:")
print(f"Clean data Pearson:   {pearsonr(x_clean, y_clean)[0]:.3f}")
print(f"With outliers Pearson: {pearsonr(x_outlier, y_outlier)[0]:.3f}")
print(f"Clean data Spearman:   {spearmanr(x_clean, y_clean)[0]:.3f}")
print(f"With outliers Spearman: {spearmanr(x_outlier, y_outlier)[0]:.3f}")
Nonlinear İlişki için Korelasyon Karşılaştırması:
Pearson r: 0.634 (p = 0.000001)
Spearman ρ: 0.919 (p = 0.000000)
Kendall τ: 0.767 (p = 0.000000)

Outlier Etkisi:
Clean data Pearson: 0.970
With outliers Pearson: 0.189
Clean data Spearman: 0.969
With outliers Spearman: 0.863
Korelasyon ≠ Nedensellik! Yüksek korelasyon nedensel ilişki anlamına gelmez. Üçüncü bir değişken (confounding variable) her iki değişkeni de etkileyebilir.
ML'de Korelasyon Kullanımı:
• Feature Selection: Yüksek korelasyonlu features'ları tespit
• Multicollinearity: VIF (Variance Inflation Factor) hesaplama
• EDA: Veri keşfi ve pattern recognition
• Ensemble Methods: Model diversity için düşük korelasyonlu modeller

Varyans Analizi (ANOVA)

ANOVA (Analysis of Variance), üç veya daha fazla grubun ortalamalarını karşılaştırmak için kullanılan istatistiksel yöntemdir. A/B/C testleri, feature importance analizi ve categorical variable'ların etkisini ölçmede kritik rol oynar.

Tek Yönlü ANOVA (One-Way ANOVA)
Bir kategorik bağımsız değişkenin sürekli bağımlı değişken üzerindeki etkisini test eder.
F = MSB / MSW = (SSB/dfB) / (SSW/dfW)
MSB: Mean Square Between, MSW: Mean Square Within, F-distribution ile karşılaştırılır
ANOVA Varsayımları
1. Independence: Gözlemler bağımsız
2. Normality: Her grup normal dağılım
3. Homogeneity: Varyanslar eşit (Levene test)
# One-Way ANOVA Örneği: Marketing Channel Effectiveness
import numpy as np
import pandas as pd
from scipy import stats
from scipy.stats import f_oneway, levene, shapiro
import matplotlib.pyplot as plt

# Sentetik veri: 4 farklı marketing channel'ın conversion rate'leri
np.random.seed(42)

# Email: Ortalama conversion rate %8
email = np.random.normal(0.08, 0.02, 50)

# Social Media: Ortalama conversion rate %12
social = np.random.normal(0.12, 0.025, 45)

# Paid Ads: Ortalama conversion rate %15
paid_ads = np.random.normal(0.15, 0.03, 40)

# Organic: Ortalama conversion rate %6
organic = np.random.normal(0.06, 0.015, 55)

# DataFrame oluştur
data = []
for channel, rates in [('Email', email), ('Social', social), 
                      ('Paid_Ads', paid_ads), ('Organic', organic)]:
    for rate in rates:
        data.append({'Channel': channel, 'Conversion_Rate': rate})

df = pd.DataFrame(data)

print("Kanal Bazında İstatistikler:")
summary_stats = df.groupby('Channel')['Conversion_Rate'].agg([
    'count', 'mean', 'std', 'min', 'max'
]).round(4)
print(summary_stats)

# ANOVA varsayımlarını kontrol et
print(f"\n=== ANOVA Varsayım Kontrolleri ===")

# 1. Normallik testi (her grup için)
channels = df['Channel'].unique()
for channel in channels:
    channel_data = df[df['Channel'] == channel]['Conversion_Rate']
    stat, p_val = shapiro(channel_data)
    normal = "Normal" if p_val > 0.05 else "Normal Değil"
    print(f"{channel} Normallik: W = {stat:.3f}, p = {p_val:.6f} ({normal})")

# 2. Varyans homojenliği (Levene testi)
groups = [df[df['Channel'] == channel]['Conversion_Rate'] for channel in channels]
levene_stat, levene_p = levene(*groups)
homogeneous = "Homojen" if levene_p > 0.05 else "Heterojen"
print(f"\nVaryans Homojenliği: W = {levene_stat:.3f}, p = {levene_p:.6f} ({homogeneous})")

# One-Way ANOVA
f_statistic, p_value = f_oneway(*groups)

print(f"\n=== One-Way ANOVA Sonuçları ===")
print(f"F-istatistiği: {f_statistic:.3f}")
print(f"p-value: {p_value:.2e}")

if p_value < 0.05:
    print("Sonuç: En az bir grup ortalaması diğerlerinden farklıdır (p < 0.05)")
else:
    print("Sonuç: Tüm grup ortalamaları eşittir (p ≥ 0.05)")

# Effect Size (Eta-squared)
# η² = SSB / SST
grand_mean = df['Conversion_Rate'].mean()
ssb = sum([len(group) * (group.mean() - grand_mean)**2 for group in groups])
sst = sum([(x - grand_mean)**2 for x in df['Conversion_Rate']])
eta_squared = ssb / sst

print(f"Effect Size (η²): {eta_squared:.3f}")
if eta_squared < 0.01:
    effect_size = "Küçük"
elif eta_squared < 0.06:
    effect_size = "Orta"
elif eta_squared < 0.14:
    effect_size = "Büyük"
else:
    effect_size = "Çok Büyük"
print(f"Effect Size Yorumu: {effect_size} etki")
ANOVA Varsayım Kontrolleri:
Email Normallik: W = 0.982, p = 0.670194 (Normal)
Social Normallik: W = 0.975, p = 0.423516 (Normal)
Paid_Ads Normallik: W = 0.971, p = 0.371829 (Normal)
Organic Normallik: W = 0.988, p = 0.853376 (Normal)

Varyans Homojenliği: W = 2.341, p = 0.073527 (Homojen)

One-Way ANOVA Sonuçları:
F-istatistiği: 157.891
p-value: 1.25e-52
Sonuç: En az bir grup ortalaması diğerlerinden farklıdır (p < 0.05)
Effect Size (η²): 0.715
Effect Size Yorumu: Çok Büyük etki
Post-Hoc Testler
ANOVA anlamlı çıktığında, hangi grupların farklı olduğunu bulmak için kullanılır.
# Post-Hoc Analysis: Tukey HSD
from scipy.stats import tukey_hsd
from itertools import combinations

# Tukey HSD testi
groups_data = [df[df['Channel'] == channel]['Conversion_Rate'].values 
               for channel in channels]
tukey_result = tukey_hsd(*groups_data)

print("=== Post-Hoc Analysis: Tukey HSD ===")
print("Grup karşılaştırmaları:")

# Manuel pairwise karşılaştırma
for i, j in combinations(range(len(channels)), 2):
    group1_data = df[df['Channel'] == channels[i]]['Conversion_Rate']
    group2_data = df[df['Channel'] == channels[j]]['Conversion_Rate']
    
    t_stat, p_val = stats.ttest_ind(group1_data, group2_data)
    
    # Bonferroni correction
    n_comparisons = 6  # C(4,2) = 6 karşılaştırma
    bonferroni_p = p_val * n_comparisons
    bonferroni_p = min(bonferroni_p, 1.0)  # p-value 1'i geçemez
    
    mean_diff = group1_data.mean() - group2_data.mean()
    
    significance = "***" if bonferroni_p < 0.001 else "**" if bonferroni_p < 0.01 else "*" if bonferroni_p < 0.05 else "ns"
    
    print(f"{channels[i]} vs {channels[j]}:")
    print(f"  Mean difference: {mean_diff:7.4f}")
    print(f"  p-value (Bonferroni): {bonferroni_p:.6f} {significance}")

# Effect size for each comparison (Cohen's d)
print(f"\nCohen's d for each comparison:")
for i, j in combinations(range(len(channels)), 2):
    group1_data = df[df['Channel'] == channels[i]]['Conversion_Rate']
    group2_data = df[df['Channel'] == channels[j]]['Conversion_Rate']
    
    # Pooled standard deviation
    n1, n2 = len(group1_data), len(group2_data)
    s1, s2 = group1_data.std(ddof=1), group2_data.std(ddof=1)
    pooled_std = np.sqrt(((n1-1)*s1**2 + (n2-1)*s2**2) / (n1+n2-2))
    
    cohens_d = (group1_data.mean() - group2_data.mean()) / pooled_std
    
    print(f"{channels[i]} vs {channels[j]}: d = {cohens_d:6.3f}")
Post-Hoc Analysis: Tukey HSD
Grup karşılaştırmaları:
Email vs Organic:
  Mean difference: 0.0195
  p-value (Bonferroni): 0.000000 ***
Email vs Paid_Ads:
  Mean difference: -0.0726
  p-value (Bonferroni): 0.000000 ***
Social vs Paid_Ads:
  Mean difference: -0.0331
  p-value (Bonferroni): 0.000000 ***
İki Yönlü ANOVA (Two-Way ANOVA)
İki kategorik bağımsız değişkenin etkilerini ve etkileşimlerini test eder.
Y = μ + A + B + A×B + ε
A: Main effect 1, B: Main effect 2, A×B: Interaction effect
ANOVA vs t-test:
  • 2 grup: t-test ve ANOVA aynı sonucu verir (F = t²)
  • 3+ grup: Multiple t-testler Type I error'ı artırır, ANOVA kullan
  • Bonferroni düzeltmesi: α' = α/k (k: karşılaştırma sayısı)
ML'de ANOVA Kullanımı:
• Feature Selection: Categorical features'ların target'a etkisi
• A/B/C Testing: Multiple variant karşılaştırması
• Hyperparameter Tuning: Different algorithms karşılaştırması
• Market Segmentation: Segment performance analizi

Ki-Kare (χ²) Testleri

Ki-kare testleri, kategorik veriler arasındaki ilişkileri analiz etmek için kullanılır. Özellikle feature selection, independence testing ve goodness-of-fit analizlerinde kritik öneme sahiptir.

Bağımsızlık Testi
İki kategorik değişkenin birbirinden bağımsız olup olmadığını test eder. Contingency table (çapraz tablo) kullanır.
χ² = Σ[(Oij - Eij)² / Eij]
Oij: Gözlenen frekans, Eij: Beklenen frekans = (satır toplamı × sütun toplamı) / genel toplam
# Ki-Kare Bağımsızlık Testi Örneği
import numpy as np
import pandas as pd
from scipy.stats import chi2_contingency, chi2
from scipy.stats.contingency import association

# Örnek: Marketing Channel vs Conversion
# Sentetik veri oluştur
np.random.seed(42)
channels = ['Email', 'Social', 'Paid', 'Organic']
conversions = ['Converted', 'Not_Converted']

# Contingency table (çapraz tablo)
observed = np.array([
    [45, 155],  # Email: 45 conversion, 155 no conversion
    [65, 135],  # Social: 65 conversion, 135 no conversion  
    [85, 115],  # Paid: 85 conversion, 115 no conversion
    [25, 175]   # Organic: 25 conversion, 175 no conversion
])

print("Contingency Table (Çapraz Tablo):")
df_contingency = pd.DataFrame(observed, 
                             index=['Email', 'Social', 'Paid', 'Organic'],
                             columns=['Converted', 'Not_Converted'])
print(df_contingency)

# Ki-kare testi
chi2_stat, p_value, dof, expected = chi2_contingency(observed)

print(f"\n=== Ki-Kare Bağımsızlık Testi ===")
print(f"χ² istatistiği: {chi2_stat:.3f}")
print(f"p-value: {p_value:.6f}")
print(f"Serbestlik derecesi: {dof}")

# Kritik değer
alpha = 0.05
critical_value = chi2.ppf(1 - alpha, dof)
print(f"Kritik değer (α=0.05): {critical_value:.3f}")

# Karar
if p_value < alpha:
    print("Sonuç: Değişkenler bağımsız DEĞİLdir (p < 0.05)")
    print("Marketing channel ile conversion arasında anlamlı ilişki vardır.")
else:
    print("Sonuç: Değişkenler bağımsızdır (p ≥ 0.05)")

# Effect size (Cramér's V)
n = observed.sum()
cramers_v = np.sqrt(chi2_stat / (n * (min(observed.shape) - 1)))
print(f"Cramér's V (effect size): {cramers_v:.3f}")

# Beklenen değerler
print(f"\nBeklenen Değerler:")
df_expected = pd.DataFrame(expected.round(1),
                          index=['Email', 'Social', 'Paid', 'Organic'],
                          columns=['Converted', 'Not_Converted'])
print(df_expected)
χ² istatistiği: 32.645
p-value: 0.000000
Serbestlik derecesi: 3
Kritik değer (α=0.05): 7.815
Sonuç: Değişkenler bağımsız DEĞİLdir (p < 0.05)
Marketing channel ile conversion arasında anlamlı ilişki vardır.
Cramér's V (effect size): 0.226
Goodness-of-Fit Testi
Gözlenen dağılımın teorik bir dağılıma uyup uymadığını test eder.
# Goodness-of-Fit Test Örneği
from scipy.stats import chisquare

# Örnek: Zar atma deneyi - her yüzün eşit gelme olasılığı
observed_dice = [18, 22, 16, 25, 20, 19]  # 6 yüz için gözlenen frekanslar
expected_dice = [20, 20, 20, 20, 20, 20]  # Her yüz için beklenen (eşit dağılım)

chi2_gof, p_gof = chisquare(observed_dice, expected_dice)

print("=== Goodness-of-Fit Testi (Zar Örneği) ===")
print(f"Gözlenen: {observed_dice}")
print(f"Beklenen: {expected_dice}")
print(f"χ² istatistiği: {chi2_gof:.3f}")
print(f"p-value: {p_gof:.6f}")

if p_gof < 0.05:
    print("Sonuç: Zar ADALET DEĞİL (p < 0.05)")
else:
    print("Sonuç: Zar adil görünüyor (p ≥ 0.05)")
Ki-Kare Varsayımları:
• Beklenen frekanslar ≥ 5 (en az %80'i için)
• Gözlemler bağımsız olmalı
• Kategorik veriler olmalı
• Rastgele örnekleme yapılmalı

Bayesian İstatistik Temelleri

Bayesian istatistik, belirsizliği olasılık dağılımları ile ifade eder ve önsel bilgiyi veriye entegre eder. Modern ML algoritmalarının (Bayesian Networks, MCMC, Variational Inference) teorik temelini oluşturur.

Bayesian vs Frequentist
Frequentist: Parametreler sabit, veri rastgele
Bayesian: Parametreler rastgele (dağılım), veri gözlenen
P(θ|D) = P(D|θ) × P(θ) / P(D)
Posterior = Likelihood × Prior / Evidence (Marginal Likelihood)
Conjugate Priors
Prior ve posterior'un aynı dağılım ailesinden olması. Analitik çözüm imkanı sağlar.
# Bayesian A/B Testing Örneği
import numpy as np
import matplotlib.pyplot as plt
from scipy import stats

# Beta-Binomial Conjugacy örneği
# A/B test: Conversion rate karşılaştırması

class BayesianABTest:
    def __init__(self, alpha_prior=1, beta_prior=1):
        self.alpha_prior = alpha_prior
        self.beta_prior = beta_prior
        
    def update_posterior(self, conversions, trials):
        """Beta posterior güncelleme"""
        alpha_posterior = self.alpha_prior + conversions
        beta_posterior = self.beta_prior + trials - conversions
        return alpha_posterior, beta_posterior
    
    def probability_A_beats_B(self, alpha_A, beta_A, alpha_B, beta_B, samples=10000):
        """A'nın B'den iyi olma olasılığı (Monte Carlo)"""
        # Posterior'lardan örneklem al
        samples_A = np.random.beta(alpha_A, beta_A, samples)
        samples_B = np.random.beta(alpha_B, beta_B, samples)
        
        return np.mean(samples_A > samples_B)

# Örnek veri
np.random.seed(42)
bayesian_test = BayesianABTest(alpha_prior=1, beta_prior=1)  # Uniform prior

# A grubu: 120 trial, 18 conversion
# B grubu: 100 trial, 20 conversion
conversions_A, trials_A = 18, 120
conversions_B, trials_B = 20, 100

# Posterior'ları güncelle
alpha_A, beta_A = bayesian_test.update_posterior(conversions_A, trials_A)
alpha_B, beta_B = bayesian_test.update_posterior(conversions_B, trials_B)

print("=== Bayesian A/B Test Sonuçları ===")
print(f"A grubu: {conversions_A}/{trials_A} = {conversions_A/trials_A:.3f}")
print(f"B grubu: {conversions_B}/{trials_B} = {conversions_B/trials_B:.3f}")

# Posterior istatistikleri
mean_A = alpha_A / (alpha_A + beta_A)
mean_B = alpha_B / (alpha_B + beta_B)
var_A = (alpha_A * beta_A) / ((alpha_A + beta_A)**2 * (alpha_A + beta_A + 1))
var_B = (alpha_B * beta_B) / ((alpha_B + beta_B)**2 * (alpha_B + beta_B + 1))

print(f"\nPosterior A: Beta({alpha_A}, {beta_A})")
print(f"  Mean: {mean_A:.4f}, Std: {np.sqrt(var_A):.4f}")
print(f"Posterior B: Beta({alpha_B}, {beta_B})")
print(f"  Mean: {mean_B:.4f}, Std: {np.sqrt(var_B):.4f}")

# B'nin A'dan iyi olma olasılığı
prob_B_wins = bayesian_test.probability_A_beats_B(alpha_B, beta_B, alpha_A, beta_A)
print(f"\nP(B > A) = {prob_B_wins:.3f}")
print(f"P(A > B) = {1 - prob_B_wins:.3f}")

# Credible intervals (Bayesian confidence intervals)
ci_A = stats.beta.interval(0.95, alpha_A, beta_A)
ci_B = stats.beta.interval(0.95, alpha_B, beta_B)

print(f"\n95% Credible Intervals:")
print(f"A: [{ci_A[0]:.4f}, {ci_A[1]:.4f}]")
print(f"B: [{ci_B[0]:.4f}, {ci_B[1]:.4f}]")
A grubu: 18/120 = 0.150
B grubu: 20/100 = 0.200

Posterior A: Beta(19, 103)
  Mean: 0.1557, Std: 0.0329
Posterior B: Beta(21, 81)
  Mean: 0.2059, Std: 0.0400

P(B > A) = 0.891
P(A > B) = 0.109

95% Credible Intervals:
A: [0.0972, 0.2256]
B: [0.1341, 0.2874]
Bayesian Avantajları:
• Prior bilgi kullanımı
• Uncertainty quantification
• Sequential learning (data geldiğinde güncelleme)
• Interpretable probability statements
• Small sample performance

Hipotez Testleri

Hipotez testleri, veri temelli karar vermenin bilimsel yöntemidir. A/B testleri, model performans karşılaştırmaları ve machine learning pipeline'larında kritik öneme sahiptir.

H₀: Null Hipotez
Status quo, fark yok
H₁: Alternatif Hipotez
İspatlanmak istenen
Tip I ve Tip II Hatalar
Tip I Hata (α): H₀ doğruyken reddetme (False Positive)
Tip II Hata (β): H₀ yanlışken kabul etme (False Negative)
Power (1-β): Gerçek etkiyi tespit etme gücü
Gerçek Durum H₀ Kabul H₀ Red
H₀ Doğru Doğru Karar (1-α) Tip I Hata (α)
H₁ Doğru Tip II Hata (β) Doğru Karar (1-β)
Tek Örneklem t-Testi
Örneklem ortalamasının belli bir değere eşit olup olmadığını test eder.
t = (x̄ - μ₀) / (s/√n)
df = n-1, H₀: μ = μ₀, kritik değerle veya p-value ile karşılaştır
Örnek: Bir üretim hattında günlük ortalama 1000 ürün üretilir. Son 20 günde ortalama 1050, standart sapma 80. Bu artış anlamlı mı? (α = 0.05)
Hipotezler:
H₀: μ = 1000 (artış yok)
H₁: μ > 1000 (artış var, tek yönlü test)

Test İstatistiği:
t = (1050 - 1000) / (80/√20) = 50 / 17.89 = 2.80

Kritik Değer: t₀.₀₅,₁₉ = 1.729
Karar: 2.80 > 1.729, H₀ red. Artış anlamlı!
# Python ile t-Testi
import numpy as np
from scipy import stats

# Veri
sample_mean = 1050
population_mean = 1000
sample_std = 80
n = 20
alpha = 0.05

# t-istatistiği hesaplama
t_statistic = (sample_mean - population_mean) / (sample_std / np.sqrt(n))
print(f"t-istatistiği: {t_statistic:.3f}")

# Serbestlik derecesi
df = n - 1
print(f"Serbestlik derecesi: {df}")

# p-value hesaplama (tek yönlü test)
p_value = 1 - stats.t.cdf(t_statistic, df)
print(f"p-value: {p_value:.6f}")

# Kritik değer
critical_value = stats.t.ppf(1 - alpha, df)
print(f"Kritik değer: {critical_value:.3f}")

# Karar
if t_statistic > critical_value:
    print("H₀ reddedilir. Artış anlamlıdır.")
else:
    print("H₀ kabul edilir. Artış anlamlı değildir.")

print(f"Alpha: {alpha}, p-value: {p_value:.6f}")
if p_value < alpha:
    print("p < α: H₀ reddedilir")
else:
    print("p ≥ α: H₀ kabul edilir")
t-istatistiği: 2.795
Serbestlik derecesi: 19
p-value: 0.006099
Kritik değer: 1.729
H₀ reddedilir. Artış anlamlıdır.
Alpha: 0.05, p-value: 0.006099
p < α: H₀ reddedilir
İki Örneklem t-Testi
İki grubun ortalamalarının eşit olup olmadığını test eder. A/B testlerde en yaygın kullanılan.
t = (x̄₁ - x̄₂) / √(s₁²/n₁ + s₂²/n₂)
Welch's t-test (eşit varyans varsayımı gerekmez), daha robust
# A/B Test Örneği
import numpy as np
from scipy import stats

# A/B Test Verileri
np.random.seed(42)
control_group = np.random.normal(100, 15, 200)    # Kontrol grubu
treatment_group = np.random.normal(105, 15, 180)  # Treatment grubu

# Temel istatistikler
control_mean = np.mean(control_group)
treatment_mean = np.mean(treatment_group)
control_std = np.std(control_group, ddof=1)
treatment_std = np.std(treatment_group, ddof=1)

print(f"Kontrol grubu: μ = {control_mean:.2f}, σ = {control_std:.2f}, n = {len(control_group)}")
print(f"Treatment grubu: μ = {treatment_mean:.2f}, σ = {treatment_std:.2f}, n = {len(treatment_group)}")

# İki örneklem t-testi
t_stat, p_val = stats.ttest_ind(control_group, treatment_group, equal_var=False)
print(f"\nt-istatistiği: {t_stat:.3f}")
print(f"p-value: {p_val:.6f}")

# Etki büyüklüğü (Cohen's d)
pooled_std = np.sqrt(((len(control_group)-1)*control_std**2 + 
                     (len(treatment_group)-1)*treatment_std**2) / 
                    (len(control_group) + len(treatment_group) - 2))
cohens_d = (treatment_mean - control_mean) / pooled_std
print(f"Cohen's d: {cohens_d:.3f}")

# Güven aralığı
diff_mean = treatment_mean - control_mean
se_diff = np.sqrt(control_std**2/len(control_group) + treatment_std**2/len(treatment_group))
df_welch = ((control_std**2/len(control_group) + treatment_std**2/len(treatment_group))**2) / \
           ((control_std**2/len(control_group))**2/(len(control_group)-1) + 
            (treatment_std**2/len(treatment_group))**2/(len(treatment_group)-1))

t_critical = stats.t.ppf(0.975, df_welch)
ci_lower = diff_mean - t_critical * se_diff
ci_upper = diff_mean + t_critical * se_diff

print(f"Ortalama fark: {diff_mean:.2f}")
print(f"95% Güven aralığı: [{ci_lower:.2f}, {ci_upper:.2f}]")
Kontrol grubu: μ = 99.73, σ = 14.76, n = 200
Treatment grubu: μ = 105.12, σ = 14.89, n = 180

t-istatistiği: -3.536
p-value: 0.000444
Cohen's d: -0.364
Ortalama fark: 5.39
95% Güven aralığı: [2.39, 8.39]
Effect Size Yorumlama (Cohen's d):
  • |d| < 0.2: Küçük etki
  • 0.2 ≤ |d| < 0.5: Orta etki
  • 0.5 ≤ |d| < 0.8: Büyük etki
  • |d| ≥ 0.8: Çok büyük etki
p-Hacking Uyarısı: Çoklu karşılaştırma sorunu! Birçok test yapıldığında Tip I hata riski artar. Bonferroni düzeltmesi kullanın: α' = α/k (k: test sayısı)
A/B Test İpuçları:
• Önceden sample size hesaplayın (power analysis)
• Test süresini önceden belirleyin (peeking yapmayın)
• Segmentation yaparken multiple testing correction uygulayın
• Practical significance vs statistical significance ayrımı yapın

Regresyon Analizi

Regresyon analizi, değişkenler arasındaki ilişkiyi modelleyen ve tahmin yapan temel istatistiksel yöntemdir. Machine learning'in supervised learning algoritmalarının teorik temelidir.

Basit Doğrusal Regresyon
Bir bağımsız değişken (X) ile bağımlı değişken (Y) arasındaki doğrusal ilişkiyi modeller.
Y = β₀ + β₁X + ε
β₀: y-kesim (intercept), β₁: eğim (slope), ε: hata terimi (residual)
En Küçük Kareler Yöntemi (OLS)
Residual kareler toplamını minimize eden parametreleri bulur.
β₁ = Σ(x-x̄)(y-ȳ) / Σ(x-x̄)²     β₀ = ȳ - β₁x̄
Minimize edilecek: SSE = Σ(yᵢ - ŷᵢ)² = Σ(yᵢ - β₀ - β₁xᵢ)²
# Python ile Basit Doğrusal Regresyon
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from scipy import stats
from sklearn.linear_model import LinearRegression
from sklearn.metrics import r2_score, mean_squared_error

# Örnek veri: Reklam harcaması vs Satış
np.random.seed(42)
advertising = np.random.uniform(10, 100, 50)
noise = np.random.normal(0, 10, 50)
sales = 20 + 0.8 * advertising + noise

# DataFrame oluştur
df = pd.DataFrame({'Advertising': advertising, 'Sales': sales})

# Manuel hesaplama
x_mean = np.mean(advertising)
y_mean = np.mean(sales)

numerator = np.sum((advertising - x_mean) * (sales - y_mean))
denominator = np.sum((advertising - x_mean) ** 2)

beta1 = numerator / denominator
beta0 = y_mean - beta1 * x_mean

print(f"Manuel hesaplama:")
print(f"β₀ (intercept): {beta0:.3f}")
print(f"β₁ (slope): {beta1:.3f}")

# Sklearn ile
model = LinearRegression()
X = advertising.reshape(-1, 1)
y = sales

model.fit(X, y)
predictions = model.predict(X)

print(f"\nSklearn ile:")
print(f"β₀ (intercept): {model.intercept_:.3f}")
print(f"β₁ (slope): {model.coef_[0]:.3f}")

# Model değerlendirme
r2 = r2_score(y, predictions)
mse = mean_squared_error(y, predictions)
rmse = np.sqrt(mse)

print(f"\nModel Performansı:")
print(f"R²: {r2:.3f}")
print(f"MSE: {mse:.3f}")
print(f"RMSE: {rmse:.3f}")

# Pearson korelasyon
correlation, p_value = stats.pearsonr(advertising, sales)
print(f"Korelasyon: {correlation:.3f} (p = {p_value:.6f})")
Manuel hesaplama:
β₀ (intercept): 19.996
β₁ (slope): 0.801

Sklearn ile:
β₀ (intercept): 19.996
β₁ (slope): 0.801

Model Performansı:
R²: 0.891
MSE: 108.647
RMSE: 10.424
Korelasyon: 0.944 (p = 0.000000)
Determinasyon Katsayısı (R²)
Bağımsız değişkenlerin bağımlı değişkendeki varyansın ne kadarını açıkladığını gösterir.
R² = 1 - (SSE/SST) = (SSR/SST)
SSE: Hata kareler toplamı, SST: Toplam kareler toplamı, SSR: Regresyon kareler toplamı
Çoklu Doğrusal Regresyon
Birden fazla bağımsız değişkenle tahmin yapma. Gerçek dünya problemlerinde daha yaygın.
Y = β₀ + β₁X₁ + β₂X₂ + ... + βₚXₚ + ε
Matrix notation: Y = Xβ + ε, çözüm: β̂ = (X'X)⁻¹X'Y
# Çoklu Regresyon Örneği
import numpy as np
import pandas as pd
from sklearn.linear_model import LinearRegression
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
from sklearn.metrics import r2_score, mean_absolute_error
import seaborn as sns

# Sentetik veri: Ev fiyat tahmini
np.random.seed(42)
n_samples = 500

# Features
size = np.random.normal(150, 50, n_samples)  # m²
bedrooms = np.random.poisson(3, n_samples)   # oda sayısı
age = np.random.exponential(15, n_samples)   # yaş
location_score = np.random.uniform(1, 10, n_samples)  # lokasyon skoru

# Target (price) - gerçekçi ilişki
noise = np.random.normal(0, 20000, n_samples)
price = (2000 * size + 
         10000 * bedrooms + 
         -500 * age + 
         15000 * location_score + 
         100000 + noise)

# DataFrame oluştur
df = pd.DataFrame({
    'size': size,
    'bedrooms': bedrooms,
    'age': age,
    'location_score': location_score,
    'price': price
})

print("Veri Seti Özeti:")
print(df.describe())

# Korelasyon matrisi
correlation_matrix = df.corr()
print(f"\nPrice ile korelasyonlar:")
print(correlation_matrix['price'].sort_values(ascending=False))

# Train-test split
X = df[['size', 'bedrooms', 'age', 'location_score']]
y = df['price']

X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)

# Model eğitimi
model = LinearRegression()
model.fit(X_train, y_train)

# Tahminler
y_pred_train = model.predict(X_train)
y_pred_test = model.predict(X_test)

# Model değerlendirme
print(f"\nModel Katsayıları:")
print(f"Intercept: {model.intercept_:.0f}")
for i, feature in enumerate(X.columns):
    print(f"{feature}: {model.coef_[i]:.2f}")

print(f"\nModel Performansı:")
print(f"Train R²: {r2_score(y_train, y_pred_train):.3f}")
print(f"Test R²: {r2_score(y_test, y_pred_test):.3f}")
print(f"Test MAE: {mean_absolute_error(y_test, y_pred_test):.0f} TL")
Model Katsayıları:
Intercept: 99482
size: 2000.84
bedrooms: 9963.31
age: -500.45
location_score: 15021.67

Model Performansı:
Train R²: 0.998
Test R²: 0.998
Test MAE: 14562 TL
Regresyon Varsayımları:
• Linearity: X ve Y arasında doğrusal ilişki
• Independence: Gözlemler bağımsız
• Homoscedasticity: Hata varyansı sabit
• Normality: Hatalar normal dağılım
• No multicollinearity: Bağımsız değişkenler birbirleriyle yüksek korelasyonlu değil
Regresyon İyileştirme Teknikleri:
• Regularization: Ridge (L2), Lasso (L1), Elastic Net
• Feature Engineering: Polynomial features, interactions
• Cross-validation: Model stability için
• Residual Analysis: Varsayım kontrolü

Korelasyon Analizi

Korelasyon analizi, iki veya daha fazla değişken arasındaki doğrusal ilişkinin gücünü ve yönünü ölçer. Feature selection, exploratory data analysis ve multicollinearity tespitinde kritik rol oynar.

Pearson Korelasyon Katsayısı
En yaygın kullanılan korelasyon ölçüsü. Doğrusal ilişkinin gücünü ölçer. -1 ile +1 arasında değer alır.
r = Σ(x-x̄)(y-ȳ) / √[Σ(x-x̄)²Σ(y-ȳ)²]
r = 1: Mükemmel pozitif korelasyon, r = -1: Mükemmel negatif, r = 0: Korelasyon yok
|r| Değeri İlişki Gücü Yorumlama
0.00 - 0.19 Çok Zayıf Pratikte ilişki yok
0.20 - 0.39 Zayıf Gözle görülür ama zayıf ilişki
0.40 - 0.59 Orta Dikkate değer ilişki
0.60 - 0.79 Güçlü Güçlü ilişki
0.80 - 1.00 Çok Güçlü Mükemmel veya neredeyse mükemmel ilişki
Spearman ve Kendall Korelasyonları
Non-parametrik korelasyon ölçüleri. Sıralı veriler veya non-linear ilişkiler için kullanılır.
# Python ile Güven Aralığı Hesaplama import numpy as np from scipy import stats # Veri sample_mean = 250 sample_std = 50 n = 100 confidence_level = 0.95 # Standart hata standard_error = sample_std / np.sqrt(n) print(f"Standart hata: {standard_error}") # Kritik değer (t-dağılımı, çünkü σ bilinmiyor) alpha = 1 - confidence_level df = n - 1 t_critical = stats.t.ppf(1 - alpha/2, df) print(f"t kritik değeri: {t_critical:.3f}") # Güven aralığı margin_of_error = t_critical * standard_error ci_lower = sample_mean - margin_of_error ci_upper = sample_mean + margin_of_error print(f"Hata payı: ±{margin_of_error:.2f}") print(f"%{confidence_level*100} Güven aralığı: [{ci_lower:.2f}, {ci_upper:.2f}]") # Bootstrapping ile alternatif yaklaşım np.random.seed(42) original_sample = np.random.normal(sample_mean, sample_std, n) bootstrap_means = [] for i in range(1000): bootstrap_sample = np.random.choice(original_sample, size=n, replace=True) bootstrap_means.append(np.mean(bootstrap_sample)) # Bootstrap güven aralığı ci_bootstrap = np.percentile(bootstrap_means, [2.5, 97.5]) print(f"Bootstrap %95 güven aralığı: [{ci_bootstrap[0]:.2f}, {ci_bootstrap[1]:.2f}]")
Standart hata: 5.0
t kritik değeri: 1.984
Hata payı: ±9.92
%95 Güven aralığı: [240.08, 259.92]
Bootstrap %95 güven aralığı: [240.15, 259.85]
Bootstrapping: Yeniden örnekleme tekniği. Parametrik varsayımlar olmadan güven aralığı hesaplar. Özellikle karmaşık istatistikler için yararlı.

Machine Learning'de İstatistik

Machine Learning algoritmalarının çoğu istatistiksel prensiplere dayanır. Bu bölümde, istatistiksel kavramların ML pipeline'ındaki rolünü inceleyeceğiz.

Bias-Variance Tradeoff
Model complexity ile generalization arasındaki denge. İstatistiksel learning theory'nin temeli.
Error = Bias² + Variance + Irreducible Error
Bias: Underfitting, Variance: Overfitting, Sweet spot: Balance point
# Bias-Variance Decomposition Demonstration
import numpy as np
from sklearn.tree import DecisionTreeRegressor
from sklearn.ensemble import RandomForestRegressor
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import PolynomialFeatures
from sklearn.linear_model import LinearRegression
from sklearn.pipeline import Pipeline

def generate_dataset(n_samples=200, noise_std=0.1):
    """True function: y = x^2 + noise"""
    np.random.seed(42)
    X = np.random.uniform(-1, 1, n_samples).reshape(-1, 1)
    y = X.ravel()**2 + np.random.normal(0, noise_std, n_samples)
    return X, y

def bias_variance_analysis(model, X_train, y_train, X_test, y_test, n_trials=100):
    """Bias-variance analizi"""
    predictions = []
    
    for trial in range(n_trials):
        # Bootstrap sampling
        indices = np.random.choice(len(X_train), len(X_train), replace=True)
        X_boot = X_train[indices]
        y_boot = y_train[indices]
        
        # Model eğit ve tahmin yap
        model_copy = type(model)(**model.get_params())
        model_copy.fit(X_boot, y_boot)
        pred = model_copy.predict(X_test)
        predictions.append(pred)
    
    predictions = np.array(predictions)
    
    # Bias ve variance hesapla
    mean_prediction = np.mean(predictions, axis=0)
    true_values = X_test.ravel()**2  # True function without noise
    
    bias_squared = np.mean((mean_prediction - true_values)**2)
    variance = np.mean(np.var(predictions, axis=0))
    
    return bias_squared, variance

# Veri üret
X, y = generate_dataset(n_samples=200, noise_std=0.1)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=42)

# Test edilecek modeller
models = {
    'Linear (Underfitting)': LinearRegression(),
    'Polynomial Degree 2': Pipeline([
        ('poly', PolynomialFeatures(degree=2)),
        ('linear', LinearRegression())
    ]),
    'Polynomial Degree 8': Pipeline([
        ('poly', PolynomialFeatures(degree=8)),
        ('linear', LinearRegression())
    ]),
    'Decision Tree (Deep)': DecisionTreeRegressor(max_depth=10, random_state=42),
    'Random Forest': RandomForestRegressor(n_estimators=100, max_depth=5, random_state=42)
}

print("=== Bias-Variance Analysis ===")
print(f"{'Model':<25} {'Bias²':<8} {'Variance':<8} {'Total':<8}")
print("-" * 50)

for name, model in models.items():
    try:
        bias_sq, variance = bias_variance_analysis(model, X_train, y_train, X_test, y_test)
        total = bias_sq + variance
        print(f"{name:<25} {bias_sq:<8.4f} {variance:<8.4f} {total:<8.4f}")
    except Exception as e:
        print(f"{name:<25} Error: {str(e)[:20]}")

print("\nYorumlama:")
print("- Yüksek bias (underfitting): Basit modeller")
print("- Yüksek variance (overfitting): Karmaşık modeller")
print("- En iyi model: En düşük bias² + variance toplamı")
Cross-Validation ve İstatistik
Model performansının istatistiksel anlamlılığını test etmek için kullanılır.
# Statistical Significance of Model Performance
from sklearn.model_selection import cross_val_score
from scipy import stats

def compare_models_statistically(model1, model2, X, y, cv=10):
    """İki modelin performansını istatistiksel olarak karşılaştır"""
    scores1 = cross_val_score(model1, X, y, cv=cv, scoring='neg_mean_squared_error')
    scores2 = cross_val_score(model2, X, y, cv=cv, scoring='neg_mean_squared_error')
    
    # Convert to positive MSE
    scores1 = -scores1
    scores2 = -scores2
    
    # Paired t-test
    t_stat, p_value = stats.ttest_rel(scores1, scores2)
    
    return scores1, scores2, t_stat, p_value

# Model karşılaştırması
from sklearn.ensemble import RandomForestRegressor
from sklearn.linear_model import Ridge

model1 = RandomForestRegressor(n_estimators=100, random_state=42)
model2 = Ridge(alpha=1.0)

scores1, scores2, t_stat, p_val = compare_models_statistically(model1, model2, X, y)

print("=== Model Comparison (Statistical) ===")
print(f"Random Forest MSE: {np.mean(scores1):.6f} ± {np.std(scores1):.6f}")
print(f"Ridge Regression MSE: {np.mean(scores2):.6f} ± {np.std(scores2):.6f}")
print(f"Paired t-test: t = {t_stat:.3f}, p = {p_val:.6f}")

if p_val < 0.05:
    better_model = "Random Forest" if np.mean(scores1) < np.mean(scores2) else "Ridge"
    print(f"Sonuç: {better_model} anlamlı olarak daha iyi (p < 0.05)")
else:
    print("Sonuç: Modeller arasında anlamlı fark yok (p ≥ 0.05)")
ML Pipeline'da İstatistik:
  • EDA: Descriptive statistics, correlation analysis
  • Feature Selection: Statistical tests (ANOVA, chi-square)
  • Model Selection: Cross-validation, hypothesis testing
  • Performance Evaluation: Confidence intervals, significance tests
  • A/B Testing: Experimental design principles

Python ile İstatistik Uygulamaları

Python'da istatistiksel analiz için kullanılan temel kütüphaneler ve pratik örneklerle kapsamlı bir rehber.

Temel Kütüphaneler
NumPy: Numerical computing
SciPy: Statistical functions
Pandas: Data manipulation
Statsmodels: Statistical modeling
Scikit-learn: Machine learning
# Comprehensive Statistical Analysis Pipeline
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
from scipy import stats
import statsmodels.api as sm
from statsmodels.stats.contingency_tables import mcnemar
from sklearn.datasets import make_classification
from sklearn.preprocessing import StandardScaler
from sklearn.model_selection import train_test_split
from sklearn.metrics import classification_report

# Veri seti oluştur (örnek: customer churn prediction)
np.random.seed(42)
n_samples = 1000

# Demographics
age = np.random.normal(35, 12, n_samples)
income = np.random.lognormal(10, 0.5, n_samples)

# Usage patterns
monthly_charges = np.random.normal(70, 20, n_samples)
tenure_months = np.random.exponential(24, n_samples)

# Create target with realistic relationships
churn_probability = 1 / (1 + np.exp(-(
    -2 +
    0.02 * (age - 35) +
    -0.0001 * (income - 50000) +
    0.01 * (monthly_charges - 70) +
    -0.05 * (tenure_months - 24) +
    np.random.normal(0, 0.5, n_samples)
)))

churn = np.random.binomial(1, churn_probability, n_samples)

# DataFrame oluştur
df = pd.DataFrame({
    'age': age,
    'income': income,
    'monthly_charges': monthly_charges,
    'tenure_months': tenure_months,
    'churn': churn
})

print("=== Dataset Overview ===")
print(df.head())
print(f"\nDataset shape: {df.shape}")
print(f"Churn rate: {df['churn'].mean():.3f}")

# 1. Descriptive Statistics
print("\n=== Descriptive Statistics ===")
print(df.describe())

# 2. Correlation Analysis
print("\n=== Correlation Matrix ===")
correlation_matrix = df.corr()
print(correlation_matrix.round(3))

# 3. Statistical Tests
print("\n=== Statistical Tests ===")

# T-test: Age difference between churned and non-churned
churned = df[df['churn'] == 1]['age']
not_churned = df[df['churn'] == 0]['age']

t_stat, p_val = stats.ttest_ind(churned, not_churned)
print(f"Age difference t-test: t = {t_stat:.3f}, p = {p_val:.6f}")

# ANOVA: Monthly charges across age groups
df['age_group'] = pd.cut(df['age'], bins=[0, 30, 50, 100], labels=['Young', 'Middle', 'Senior'])
age_groups = [group['monthly_charges'].values for name, group in df.groupby('age_group')]
f_stat, p_val = stats.f_oneway(*age_groups)
print(f"Monthly charges ANOVA: F = {f_stat:.3f}, p = {p_val:.6f}")

# 4. Logistic Regression (Statsmodels)
print("\n=== Logistic Regression ===")
X = df[['age', 'income', 'monthly_charges', 'tenure_months']]
X = sm.add_constant(X)  # Add intercept
y = df['churn']

logit_model = sm.Logit(y, X)
result = logit_model.fit(disp=0)
print(result.summary().tables[1])

# 5. Feature Importance via Statistical Tests
print("\n=== Feature Importance (Statistical) ===")
features = ['age', 'income', 'monthly_charges', 'tenure_months']
feature_importance = []

for feature in features:
    # Point-biserial correlation with target
    correlation, p_val = stats.pointbiserialr(df['churn'], df[feature])
    feature_importance.append((feature, abs(correlation), p_val))

feature_importance.sort(key=lambda x: x[1], reverse=True)
for feature, corr, p_val in feature_importance:
    significance = "***" if p_val < 0.001 else "**" if p_val < 0.01 else "*" if p_val < 0.05 else "ns"
    print(f"{feature:<15}: |r| = {corr:.3f}, p = {p_val:.6f} {significance}")

# 6. Model Performance with Confidence Intervals
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import roc_auc_score
from sklearn.model_selection import cross_val_score

X_ml = df[['age', 'income', 'monthly_charges', 'tenure_months']]
y_ml = df['churn']

# Standardize features
scaler = StandardScaler()
X_scaled = scaler.fit_transform(X_ml)

# Cross-validation scores
cv_scores = cross_val_score(LogisticRegression(random_state=42), X_scaled, y_ml, 
                           cv=10, scoring='roc_auc')

print(f"\n=== Model Performance ===")
print(f"Cross-Validation ROC-AUC: {cv_scores.mean():.3f} ± {cv_scores.std():.3f}")

# Bootstrap confidence interval for AUC
n_bootstrap = 1000
bootstrap_aucs = []

for i in range(n_bootstrap):
    # Bootstrap sample
    indices = np.random.choice(len(X_scaled), len(X_scaled), replace=True)
    X_boot = X_scaled[indices]
    y_boot = y_ml.iloc[indices]
    
    # Split and train
    X_train, X_test, y_train, y_test = train_test_split(X_boot, y_boot, test_size=0.3, random_state=i)
    
    model = LogisticRegression(random_state=42)
    model.fit(X_train, y_train)
    y_pred_proba = model.predict_proba(X_test)[:, 1]
    
    auc = roc_auc_score(y_test, y_pred_proba)
    bootstrap_aucs.append(auc)

ci_lower = np.percentile(bootstrap_aucs, 2.5)
ci_upper = np.percentile(bootstrap_aucs, 97.5)
print(f"95% Bootstrap CI for AUC: [{ci_lower:.3f}, {ci_upper:.3f}]")

# 7. Effect Size Calculations
print(f"\n=== Effect Sizes ===")

# Cohen's d for continuous variables
for feature in ['age', 'income', 'monthly_charges', 'tenure_months']:
    group1 = df[df['churn'] == 1][feature]
    group0 = df[df['churn'] == 0][feature]
    
    # Pooled standard deviation
    n1, n0 = len(group1), len(group0)
    s1, s0 = group1.std(), group0.std()
    pooled_std = np.sqrt(((n1-1)*s1**2 + (n0-1)*s0**2) / (n1+n0-2))
    
    cohens_d = (group1.mean() - group0.mean()) / pooled_std
    
    print(f"{feature:<15}: Cohen's d = {cohens_d:6.3f}")

print("\n=== Analysis Complete ===")
print("Bu pipeline şunları içeriyor:")
print("- Descriptive statistics")
print("- Correlation analysis") 
print("- Hypothesis testing (t-test, ANOVA)")
print("- Logistic regression with statistical inference")
print("- Feature importance via statistical tests")
print("- Model performance with confidence intervals")
print("- Effect size calculations")
Cross-Validation ROC-AUC: 0.721 ± 0.042
95% Bootstrap CI for AUC: [0.673, 0.768]

Effect Sizes:
age : Cohen's d = -0.198
income : Cohen's d = 0.087
monthly_charges: Cohen's d = 0.312
tenure_months : Cohen's d = -0.445
Python İstatistik Araç Kutusu:
• scipy.stats: Tüm temel testler ve dağılımlar
• statsmodels: Advanced statistical modeling
• pingouin: User-friendly statistical functions
• seaborn: Statistical data visualization
• pymc3/pymc4: Bayesian modeling
# Advanced Statistical Techniques
# 1. Power Analysis
from statsmodels.stats.power import ttest_power

# Required sample size for detecting effect size d=0.5
power = 0.8
alpha = 0.05
effect_size = 0.5

required_n = ttest_power(effect_size, power, alpha, alternative='two-sided')
print(f"Required sample size for power {power}: {required_n:.0f} per group")

# 2. Multiple Testing Correction
from statsmodels.stats.multitest import multipletests

# Örnek: Multiple feature testing
p_values = [0.001, 0.045, 0.067, 0.012, 0.234]
feature_names = ['Feature_A', 'Feature_B', 'Feature_C', 'Feature_D', 'Feature_E']

# Bonferroni correction
rejected, pvals_corrected, _, _ = multipletests(p_values, alpha=0.05, method='bonferroni')

print(f"\n=== Multiple Testing Correction ===")
for i, (feature, p_orig, p_corr, is_sig) in enumerate(zip(feature_names, p_values, pvals_corrected, rejected)):
    print(f"{feature}: p_orig={p_orig:.3f}, p_corrected={p_corr:.3f}, significant={is_sig}")

# 3. Non-parametric Tests
from scipy.stats import mannwhitneyu, wilcoxon, kruskal

# Mann-Whitney U (non-parametric alternative to t-test)
group1 = np.random.exponential(2, 50)  # Non-normal distribution
group2 = np.random.exponential(3, 50)

statistic, p_value = mannwhitneyu(group1, group2, alternative='two-sided')
print(f"\nMann-Whitney U test: U = {statistic}, p = {p_value:.6f}")

# 4. Survival Analysis (basic)
# Simulated time-to-event data
np.random.seed(42)
survival_times = np.random.exponential(100, 200)  # Time to churn
censored = np.random.binomial(1, 0.7, 200)  # 70% observed, 30% censored

observed_times = survival_times * censored + \
                 np.random.uniform(0, survival_times, 200) * (1 - censored)

print(f"Survival data: {len(observed_times)} observations, {censored.sum()} events observed")

print("\n=== Advanced Analytics Tamamlandı ===")
print("Bu bölümde görülen teknikler:")
print("- Power analysis ve sample size calculation")
print("- Multiple testing correction")
print("- Non-parametric tests")
print("- Survival analysis basics")

İstatistik Yolculuğunuz Devam Ediyor!

Gelişim İçin Öneriler
Pratik yapın: Gerçek veri setleriyle çalışın (Kaggle, UCI Repository)
Teoryi anlamaya odaklanın: Formüllerin arkasındaki mantığı kavrayın
Python ecosystemini öğrenin: pandas, numpy, scipy, statsmodels
Görselleştirme: matplotlib, seaborn ile insights keşfedin
Academic papers okuyun: Journal of Machine Learning Research

"In God we trust, all others bring data" - W. Edwards Deming