---
title: 'Veri Temizleme'
source: 'https://academia.sh/tr/kurslar/oznitelik-muhendisligi/veri-temizleme'
course: 'Veri Hazırlama ve Öznitelik Mühendisliği'
language: tr
updated: '2026-08-17T18:10:11+00:00'
license: 'CC BY-SA 4.0'
---

# Veri Temizleme

Bir temizleme kararının modele ne kattığının ayrılmış kümede ölçülmesi: ham kayıttaki üç kusur tek tek düzeltilir, model sabit tutulur ve sınama kümesindeki iki sayı yan yana basılır. Birim karışıklığının düzeltilmesi uzaklık temelli yordama on iki abone kazandırırken karar ağacına iki abone kaybettirir; üç kusur birden düzeltildiğinde ağacın sınama doğruluğu 0,7659'dan 0,7778'e, uzaklık temelli yordamınki 0,7540'tan 0,7857'ye çıkar ve taban çizgisi her ikisinde de 0,7579'dur.

Önceki kurs on bir derste ayrımı kurdu: bir modelin gördüğü veride ölçülen sayı ile görmediği
veride ölçülen sayı iki ayrı sayıdır ve her sayının yanına kendi kümesinde hesaplanmış bir taban
çizgisi yazılır. O kursun kapanışı bir eksikle bitti. Modele verilen **öznitelikler** hep hazır
kabul edildi: ortalama tüketim bir sayıydı, bölge beş ikili sütundu, oynaklık hesaplanmıştı.
Hangi sütunun nasıl bir sayıya çevrildiği ve o çevirinin tabanla arasındaki farkı ne kadar
oynattığı hiç sorulmadı.

Bu ders o soruyu sorar ve kursun ölçü birimini kurar. Yöntem her derste aynıdır: **model sabit
tutulur, yalnız öznitelikler değişir.** Tek bir hazırlama kararı açılır ve kapatılır, ayrılmış
kümedeki iki sayı yan yana basılır, aradaki fark **katkı** olarak adlandırılır. Kursun kuralı
buradan çıkar: **bir hazırlama adımı, ayrılmış kümede ölçülen katkısı kadar vardır. Katkısı
ölçülmemiş adım, adım değil alışkanlıktır.**

- **HA1.** Küme M27/K01'den devralınır ve **kurgudur**: bölgesel ölçüm ağından türetilen 1.260
  abone, kaçak ya da arıza şüphesi etiketi, tohum 20260218, bölme 756/252/252.
- **HA2.** Bu kursta **ayrılmış küme sınama kümesidir** ve taban çizgisi orada 0,7579'dur —
  eğitim kümesinin en sık sınıfını her aboneye söylemek. K01'in kuralı gereği her bakış bir seçim
  payı biriktirir; bu payın hesabı kursun sonuna bırakılır.
- **HA3.** K01'in kullandığı tablo **temizlenmiş** tablodur. Bu ders bir adım geriye gider: aynı
  kurgunun ham kayıt hali, temizleme kararları alınmadan önceki biçimi.
- **HA4.** Ham kayıtta üç kusur vardır ve üçü de **kurgudur**. Eski sayaçların bir bölümü tüketimi
  litre cinsinden bildirir; bölge adı üç ayrı yazımla kaydedilir; okunamayan sayaç ikinci kez
  okunduğu için aynı abone birden çok satırda görünür.
- **HA5.** Kusurlar yalnız **öznitelik sütunlarını** bozar. Etiket denetim sonucudur ve hiçbir
  kusurdan etkilenmez; bu yüzden taban çizgisi 0,7579 sabit kalır.
- **HA6.** Bölme **abone üzerinden** yapılır. Yinelenen satırlar kümeler arasına geçmez, yalnız
  eğitim kümesindeki ağırlığı değiştirir.
- **HA7.** İki model ailesi karşılaştırılır: K01'in derinlik 6 karar ağacı ve en yakın on beş
  komşuya bakan uzaklık temelli bir yordam. İkisi de ders içinde yazılır ve ikisi de birer
  modeldir; kurs boyunca ayarları değişmez.
- **HA8.** Ölçü doğruluktur. Sınama kümesi 252 abonedir, bu yüzden **bir abone 0,0040 eder** ve
  bundan küçük farklar ölçülmemiş sayılır.

Temizleme yordamının kendisi bu derste kurulmuyor. Eksik değer, tip dönüşümü, yinelenen kayıt ve
kategori birleştirme M26'nın Veri Toplama ve Hazırlama kursunda ölçüldü; oradaki ölçü **satır
sayısıydı** — kaç satır düzeldi, kaç satır atıldı. Buradaki soru başkadır: aynı karar **ayrılmış
kümedeki sayıyı** ne kadar oynatıyor ve hangi model ailesi ona duyarlı.

## Ham Kayıt ve Üç Kusur

Kurulum kümeyi K01'deki tohumla yeniden üretir, abone üzerinden böler ve eğitim ile sınama
kümelerinin ham kayıt halini kurar. Etikete dokunulmaz.

```python
# hazirlama.py — MODELDIR. M27/K01'in kurgu abone tablosu ayni tohumla yeniden
# uretilir; uzerine kaydin HAM halindeki uc kusur konur.
import math

TOHUM, ADAY, M32 = 20260218, 1400, 0xFFFFFFFF
BOLGE = [("kuzey", 0.28, 21, 0.00), ("guney", 0.22, 17, -0.10),
         ("dogu", 0.18, 26, 0.30), ("bati", 0.14, 14, -0.05),
         ("merkez", 0.18, 23, 0.05)]


def uretec(t):
    x = ((t ^ (t >> 16)) * 2246822507) & M32
    x = ((x ^ (x >> 13)) * 3266489909) & M32
    s = [(x ^ (x >> 16)) & M32]

    def sonraki():
        s[0] = (s[0] * 1664525 + 1013904223) & M32
        return s[0] / 4294967296
    return sonraki


def ayrik(u, w):
    t = 0.0
    for i, x in enumerate(w):
        t += x
        if u < t:
            return i
    return len(w) - 1


ABONE = []
for i in range(ADAY):
    r = uretec(TOHUM + i)
    b = BOLGE[ayrik(r(), [x[1] for x in BOLGE])]
    hane = 1 + ayrik(r(), [0.06, 0.24, 0.30, 0.24, 0.11, 0.05])
    memnun = 1 + ayrik(r(), [0.08, 0.14, 0.27, 0.34, 0.17])
    if r() >= 0.046:
        ABONE.append({"no": 10001 + i, "bolge": b, "hane": hane, "memnuniyet": memnun})
OKUMA = {}
for k in ABONE:
    r = uretec(TOHUM + 7000 + k["no"])
    for d in range(ayrik(r(), [0.05, 0.12, 0.21, 0.62])):
        OKUMA.setdefault(k["no"], []).append(0.0 if r() < 0.038 else math.floor(
            k["bolge"][2] * math.exp((r() + r() + r() - 1.5) * 0.62)
            * (1 - d * 0.05) * 100 + 0.5) / 100)
        r()

VERI = []
for k in ABONE:
    v = OKUMA.get(k["no"])
    if v is None:
        continue
    ort, oyn, r = sum(v) / len(v), max(v) - min(v), uretec(TOHUM + 51000 + k["no"])
    z = (0.052 * (ort - 20) + 0.85 * (min(v) == 0.0) + 0.026 * oyn
         + 0.24 * (k["hane"] >= 5) - 0.20 * (k["memnuniyet"] >= 4) + k["bolge"][3]
         + 0.9 * (k["no"] - 10001) / 1399 + (r() + r() + r() - 1.5) * 1.30)
    VERI.append({"no": k["no"], "hane": k["hane"], "memnuniyet": k["memnuniyet"],
                 "donem": len(v), "ort_tuketim": round(ort, 2),
                 "oynaklik": round(oyn, 2), "sifir_okuma": int(min(v) == 0.0),
                 "bolge": k["bolge"][0], "supheli": int(z > 1.35)})


def karistir(veri, tohum):
    r, s = uretec(tohum), list(range(len(veri)))
    for i in range(len(s) - 1, 0, -1):
        j = int(r() * (i + 1))
        s[i], s[j] = s[j], s[i]
    return [veri[i] for i in s]


K = karistir(VERI, TOHUM + 90000)
EGT0, SIN0 = K[:756], K[1008:]
TABAN = sum(x["supheli"] == 0 for x in SIN0) / len(SIN0)

YAZIM = {"kuzey": ["kuzey", "Kuzey", "KUZEY"], "guney": ["guney", "Guney"],
         "dogu": ["dogu", "Dogu"], "bati": ["bati", "BATI"],
         "merkez": ["merkez", "Merkez "]}


def hamla(satirlar, tohum):                 # litre kaydi + yazim tutarsizligi
    r, out = uretec(tohum), []
    for x in satirlar:
        y = dict(x)
        if r() < 0.35:
            y["ort_tuketim"] = round(y["ort_tuketim"] * 1000, 1)
            y["oynaklik"] = round(y["oynaklik"] * 1000, 1)
        v = YAZIM[y["bolge"]]
        y["bolge"] = v[0] if r() < 0.70 else v[int(r() * (len(v) - 1)) + 1]
        out.append(y)
    return out


def yinele(satirlar, tohum):                # okunamayan sayac ikinci kez okunur
    r, out = uretec(tohum), []
    for x in satirlar:
        out.append(x)
        if x["sifir_okuma"] == 1 and r() < 0.85:
            out += [dict(x), dict(x)]
    return out


HAM_EGT = yinele(hamla(EGT0, TOHUM + 61000), TOHUM + 62000)
HAM_SIN = hamla(SIN0, TOHUM + 63000)
print(f"egitim {len(EGT0)} abone, ham kayitta {len(HAM_EGT)} satir; "
      f"sinama {len(SIN0)} abone, {len(HAM_SIN)} satir")
print(f"litre cinsinden kaydedilmis satir: egitim "
      f"{sum(1 for x in HAM_EGT if x['ort_tuketim'] > 1000)}, sinama "
      f"{sum(1 for x in HAM_SIN if x['ort_tuketim'] > 1000)}")
print(f"bes bolge icin {len({x['bolge'] for x in HAM_EGT})} ayri yazim, "
      f"taban cizgisi (en sik sinif) sinamada {TABAN:.4f}")
```

```
egitim 756 abone, ham kayitta 864 satir; sinama 252 abone, 252 satir
litre cinsinden kaydedilmis satir: egitim 295, sinama 86
bes bolge icin 11 ayri yazim, taban cizgisi (en sik sinif) sinamada 0.7579
```

Üç kusurun büyüklüğü ölçülebilir: 756 abone 864 satıra çıkmış, 295 satırda tüketim bin katına
kaymış, beş bölge on bir ayrı yazımla kaydedilmiş. Bunlar M26'da satır hesabıyla anlatılan
kusurların aynısıdır. Yeni olan, her birinin bir **karar** olması ve kararın bedelinin modelde
okunacak olmasıdır.

## Aynı Karar, İki Model Ailesi

Aşağıdaki kod iki modeli yazar ve üç temizleme kararını tek tek uygular. Karar ağacı her düğümde
bir öznitelik ve bir eşik seçer, kümeyi ikiye ayırır ve yaprakta çoğunluk sınıfını söyler.
Uzaklık temelli yordam bir aboneye en yakın on beş komşuyu bulur ve onların çoğunluğunu söyler;
yakınlık, bütün sütunlardaki farkların karelerinin toplamıdır.

```python
def gini(s):
    p = sum(x["supheli"] for x in s) / len(s) if s else 0.0
    return 2 * p * (1 - p)


def agac(s, derinlik, alan, enaz=2):        # MODELDIR: karar agaci, derinlik 6
    p = sum(x["supheli"] for x in s) / len(s)
    en = None
    if derinlik and len(s) >= 2 * enaz and 0.0 < p < 1.0:
        for a in alan:
            d = sorted({x[a] for x in s})
            for v in (d[1:] if len(d) < 10 else
                      [d[int(i * len(d) / 10)] for i in range(1, 10)]):
                sol = [x for x in s if x[a] < v]
                sag = [x for x in s if x[a] >= v]
                if min(len(sol), len(sag)) < enaz:
                    continue
                k = gini(s) - (len(sol) * gini(sol) + len(sag) * gini(sag)) / len(s)
                if en is None or k > en[0]:
                    en = (k, a, v, sol, sag)
    if en is None or en[0] <= 1e-9:
        return {"tahmin": int(p > 0.5)}
    return {"alan": en[1], "esik": en[2], "sol": agac(en[3], derinlik - 1, alan, enaz),
            "sag": agac(en[4], derinlik - 1, alan, enaz)}


def agac_tahmin(d, x):
    while "tahmin" not in d:
        d = d["sol"] if x[d["alan"]] < d["esik"] else d["sag"]
    return d["tahmin"]


def komsu_tahmin(egt, x, alan, k=15):       # MODELDIR: uzaklik temelli yordam
    u = sorted((sum((x[a] - y[a]) ** 2 for a in alan), y["supheli"]) for y in egt)[:k]
    return int(sum(t[1] for t in u) * 2 > k)


def sutunla(egt, sin):                      # bolge yazimlari ikili sutuna acilir
    kat = sorted({x["bolge"] for x in egt})
    alan = ["ort_tuketim", "oynaklik", "hane", "memnuniyet", "donem", "sifir_okuma"]
    ac = (lambda s: [dict(x, **{"b_" + k: int(x["bolge"] == k) for k in kat})
                     for x in s])
    return alan + ["b_" + k for k in kat], ac(egt), ac(sin)


def olc(egt, sin):
    alan, e, s = sutunla(egt, sin)
    m = agac(e, 6, alan)
    return (sum(agac_tahmin(m, x) == x["supheli"] for x in s) / len(s),
            sum(komsu_tahmin(e, x, alan) == x["supheli"] for x in s) / len(s))


def birim(s):                               # litre kaydi metrekupe cevrilir
    return [dict(x, ort_tuketim=round(x["ort_tuketim"] / 1000, 2),
                 oynaklik=round(x["oynaklik"] / 1000, 2))
            if x["ort_tuketim"] > 1000 else dict(x) for x in s]


def yazim(s):
    return [dict(x, bolge=x["bolge"].strip().lower()) for x in s]


def yinelenen(s):                           # ilk okuma tutulur, kopyalar atilir
    g, out = set(), []
    for x in s:
        if x["no"] not in g:
            g.add(x["no"])
            out.append(x)
    return out


KARAR = [("hicbiri (ham kayit)", lambda e, s: (e, s)),
         ("birim duzeltildi", lambda e, s: (birim(e), birim(s))),
         ("yazim birlestirildi", lambda e, s: (yazim(e), yazim(s))),
         ("yinelenen atildi", lambda e, s: (yinelenen(e), s)),
         ("ucu birden", lambda e, s: (yinelenen(yazim(birim(e))), yazim(birim(s))))]

SONUC = {}
print(f"{'uygulanan karar':<22} {'agac':>8} {'uzaklik':>9}")
print(f"{'taban cizgisi':<22} {TABAN:>8.4f} {TABAN:>9.4f}")
for ad, f in KARAR:
    SONUC[ad] = olc(*f(HAM_EGT, HAM_SIN))
    print(f"{ad:<22} {SONUC[ad][0]:>8.4f} {SONUC[ad][1]:>9.4f}")
```

```
uygulanan karar            agac   uzaklik
taban cizgisi            0.7579    0.7579
hicbiri (ham kayit)      0.7659    0.7540
birim duzeltildi         0.7579    0.8016
yazim birlestirildi      0.7738    0.7540
yinelenen atildi         0.7778    0.7659
ucu birden               0.7778    0.7857
```

İkinci satır dersin çıkış noktasıdır. Ham kayıtla eğitilen uzaklık temelli yordam sınama kümesinde
0,7540 okuyor ve bu, taban çizgisinin **altındadır**. Hiçbir özniteliğe bakmayan, hiçbir şey
öğrenmeyen ve her aboneye aynı yanıtı veren bir yordam ondan iyidir. Aynı ham kayıtla eğitilen
ağaç ise tabanı 0,0079 geçiyor. İki model, aynı tablo, iki ayrı işaret.

Üçüncü satır dersin asıl sayısıdır. Birim düzeltmesi uzaklık temelli yordamı 0,7540'tan 0,8016'ya
çıkarıyor; ağacı 0,7659'dan 0,7579'a **indiriyor**. Aynı karar, aynı veri, ters işaret. Sebep
modellerin sütunu okuma biçimidir. Ağaç her sütunda yalnız **sıraya** bakar ve tek bir eşikle
böler; birim karışıklığı sıralamayı bozduğunda ağaç önce bin sınırında bölüp sonra sütunu her
dalda yeniden kullanabilir, ödediği bedel bir düğüm derinliğidir. Uzaklık temelli yordam ise
bütün sütunların farklarını **toplar**; bin kat büyümüş bir sütun toplamı tek başına belirler ve
hane, memnuniyet, dönem, bölge sütunlarının hepsi hesaba katılmaz duruma gelir.

## Katkı Kaç Abone Eder

Farkları abone sayısına çevirmek, hangi satırın okunmaya değer olduğunu ayırır.

```python
HAMD = SONUC["hicbiri (ham kayit)"]
print(f"{'karar':<22} {'agac katki':>11} {'abone':>6} "
      f"{'uzaklik katki':>14} {'abone':>6}")
for ad, _ in KARAR[1:]:
    ka, ku = SONUC[ad][0] - HAMD[0], SONUC[ad][1] - HAMD[1]
    print(f"{ad:<22} {ka:>+11.4f} {round(ka * 252):>6} "
          f"{ku:>+14.4f} {round(ku * 252):>6}")
print(f"\ntabanin ustundeki fark, ham kayitta: agac {HAMD[0] - TABAN:+.4f}, "
      f"uzaklik {HAMD[1] - TABAN:+.4f}")
u = SONUC["ucu birden"]
print(f"tabanin ustundeki fark, ucu birden: agac {u[0] - TABAN:+.4f}, "
      f"uzaklik {u[1] - TABAN:+.4f}")
```

```
karar                   agac katki  abone  uzaklik katki  abone
birim duzeltildi           -0.0079     -2        +0.0476     12
yazim birlestirildi        +0.0079      2        +0.0000      0
yinelenen atildi           +0.0119      3        +0.0119      3
ucu birden                 +0.0119      3        +0.0317      8

tabanin ustundeki fark, ham kayitta: agac +0.0079, uzaklik -0.0040
tabanin ustundeki fark, ucu birden: agac +0.0198, uzaklik +0.0278
```

Tabloda okunmaya değer tek bir büyük sayı var: birim düzeltmesinin uzaklık temelli yordama
kattığı on iki abone. Geri kalan hücreler iki ya da üç abonedir ve 252 abonelik bir kümede iki
abone, kümenin kendi rastgeleliğinden ayırt edilemez. Ağacın birim düzeltmesinden gördüğü
−0,0079'luk zarar da bu boydadır; işareti eksidir ama okunacak doğru cümle "ağaç için bu adımın
katkısı ölçülmemiştir" olur, "ağaca zarar verir" değil. Bu ayrım kurs boyunca sürer: bir katkının
işareti, büyüklüğü ölçüm çözünürlüğünü aştığında anlam kazanır.

Son iki satır kararların nereden geldiğini gösteriyor. Üç kusur birden düzeltildiğinde ağaç tabanı
0,0198, uzaklık temelli yordam 0,0278 geçiyor. Bu iki fark **öğrenmeden** gelir: kusurlar
etiketten bağımsız üretildi, hiçbiri şüpheli abonelerde daha sık değil, dolayısıyla hiçbir
temizleme kararı modele etiket hakkında saklı bir bilgi taşımıyor. Kursun ilerleyen derslerinde
bunun tersi de ölçülecek — katkısı öğrenmeden değil sızıntıdan gelen adımlar vardır ve ikisi
ancak kaynağı sorulduğunda ayrılır.

Bir doğrulama daha var. Üç kusur birden düzeltildiğinde ağacın sınama doğruluğu 0,7778 çıkıyor ve
bu, M27/K01'in aynı model, aynı bölme ve aynı tohumla okuduğu sayının **birebir aynısıdır**. Bu
tesadüf değil: temizlenmiş tablo, K01'in en baştan kullandığı tablodur. Önceki kurs boyunca
görünmeyen şey, o tablonun kendisinin bir dizi karardan çıkmış olmasıydı.

## Özet

- Ham kayıtla eğitilen uzaklık temelli yordam sınama kümesinde 0,7540 okuyor ve taban çizgisinin
  0,0040 altında kalıyor; aynı tabloyla eğitilen karar ağacı 0,7659 ile tabanı 0,0079 geçiyor.
- Birim karışıklığının düzeltilmesi uzaklık temelli yordama +0,0476, yani on iki abone katıyor;
  aynı karar karar ağacında −0,0079, yani iki abone eksiye düşürüyor.
- İşaretin ters dönme sebebi modellerin sütunu okuma biçimidir: ağaç her sütunda yalnız sıraya
  bakar ve karışık birimi bir düğüm derinliğiyle telafi eder, uzaklık temelli yordam bütün
  sütunları toplar ve bin kat büyümüş bir sütun toplamı tek başına belirler.
- Yazım birleştirme ve yinelenen kayıt atma her iki modelde de iki ya da üç abone oynatıyor; 252
  abonelik sınama kümesinde bir abone 0,0040 ettiği için bu farklar ölçülmemiş sayılır.
- Üç kusur birden düzeltildiğinde ağaç 0,7778 okuyor; bu sayı M27/K01'in aynı model ve aynı
  bölmeyle okuduğu sayının aynısıdır, çünkü K01 zaten temizlenmiş tabloyu kullanıyordu.

## Sonraki Adım

Bu derste birim karışıklığının uzaklık temelli yordamı yıktığı görüldü, ama düzeltmeden sonra da
o yordam ağaçtan geride kaldı ve tabanı yalnız 0,0278 geçebildi. Sebep tabloda hâlâ duruyor:
sütunlar aynı birime çevrildi ama **aynı büyüklüğe** çevrilmedi. Ortalama tüketim sıfır ile
kırk üç arasında değişirken hane büyüklüğü bir ile altı, bölge sütunları sıfır ile bir arasında
değişiyor; farkların karelerini toplayan bir yordam için bu, sütunlara sessizce ağırlık vermektir.
Sonraki ders iki ölçekleme kararını — standartlaştırma ve normalleştirme — üç model ailesinde ayrı
ayrı ölçer, ölçeğin **yalnız eğitim kümesinden** öğrenilip ayrılmış kümeye uygulandığı disiplini
kurar ve hangi model ailesinde katkının sıfır çıktığını sayar.
