İçeriğe geç
academia.sh

Ders 03 / 10

Veri Mühendisliği ve Veri Bilimi Ayrımı

Aynı altı bozulma sınıfının iki rolün ölçüsüne yan yana basılması: veri mühendisi beş aşamanın satır izini, model kuran ise hattın sunduğu bölge ortalamasını öznitelik alan bir tahmin kuralının ortalama sapmasını (taban 10,832 m3) görüyor. İki ölçü aynı altı sınıfı farklı sıralıyor: sema_degisti mühendisin izinde en gürültülü sınıf (2200 satır 1800'e iniyor) ama modelin sapmasını yalnız 0,003 oynatıyor; gec_gelen kaynaktan yalnız 40 satır eksiltiyor ama sapmayı 0,105 oynatarak en çok o kıpırdatıyor; eksik_bolum sapmayı 0,003 düşürüyor, yani bozulma ölçüyü iyileştiriyor. birim_degisti ve kayan_tip ikisinde de hiçbir iz bırakmıyor. Birim değişiminin görünmezliği teleskopik bir kimlikten geliyor: bölgenin on bir hücresinin toplamı uç endekslerin farkına eşit ve bozulma uçlara dokunmuyor; aynı tablo dönem ekseninde okunduğunda temmuz ortalaması 26,7 yerine 40592074,02 çıkıyor.

İçindekiler

Önceki iki ders hattı tek bir gözden okudu. Üretimde bu hattın çevresinde tek bir göz yoktur. Aşamaları yazan, iz tablosuna bakan ve bir satır düştüğünde uyarılan bir rol vardır; hattın sonundaki tabloyu öznitelik olarak alan, üzerine bir kural ya da model kuran ve başarım sayısına bakan başka bir rol vardır. İkisi aynı hattın farklı yerlerinde durur.

Rol ayrımının kendisi bu müfredatın konusu değildir; Veri Analitiğine Giriş, Makine Öğrenmesine Giriş ve Yapay Zekâ Mühendisliğine Giriş kurslarında sorumluluk sınırları ayrı ayrı çizildi. Bu dersin eklediği tek şey ayrımı hattın aşamalarına oturtmaktır: hangi rolün sayısı hangi aşamadan okunuyor ve iki sayının arasında kalan aşamayı kim ölçüyor. Bu soru sorulduğunda ortaya tatsız bir sonuç çıkar: aynı bozulma iki ölçüye farklı yansır, ikisi altı sınıfı farklı sıralar ve bir sınıf ikisinde de hiçbir iz bırakmaz.

  • YD16. Hat, kaynak, altı bozulma sınıfı ve tohum önceki iki dersle aynıdır.
  • YD17. Rol tanımlarının yordamı tekrarlanmaz; yukarıdaki üç giriş kursunda ölçüldü. Burada ayrım yalnız ölçünün okunduğu aşama olarak yazılır.
  • YD18. Veri mühendisinin ölçüsü satır izidir: beş aşamanın kalan sayıları. Bu, ilk dersteki tablonun aynısıdır.
  • YD19. Model kuranın ölçüsü başarımdır: hattın sunduğu bölge ortalamasını öznitelik alan bir tahmin kuralının ortalama sapması, m3 cinsinden. Kural bölgenin sunulan değerini o bölgenin abone sayısına böler ve bunu bölgedeki her aboneye tahmin olarak verir.
  • YD20. Sınama kümesi 2026-11 ve 2026-12 dönemleridir (400 satır). Bu iki dönem altı sınıfın hiçbirinde bozulmaz; böylece sapmadaki her fark modelin öznitelik tarafından gelir, sınama tarafından değil.
  • YD21. Model kuran öznitelik tablosunu hattan alır, kaynağa erişmez. Üretimdeki sınır budur: sunulan katman iki rol arasındaki sözleşmedir.
  • YD22. Öznitelik mühendisliği ve model değerlendirme yordamı tekrarlanmaz; Veri Hazırlama ve Öznitelik Mühendisliği ile Model Değerlendirme, Yorumlanabilirlik ve Etik kurslarında ölçüldü. Model burada kasten en yalın hâlindedir. Amaç modelin iyi olması değil, ölçüsünün neye duyarlı olduğudur.
  • YD23. Denetim yok; taban çizgisi denetimsiz hattır, yakalanan bozulma 0, gecikme tanımsız. Hat belirlenimcidir, ikinci koşum aynı tabloyu verir. Süre yazılmaz.

İki Ölçü, Aynı Hat

Aşağıdaki blok hattı ve altı bozulma sınıfını aynen kurar, üzerine model kuranın ölçüsünü ekler ve her sınıf için iki sayıyı yan yana basar: satır izi sağlam hatla aynı mı, ortalama sapma sağlam hatla aynı mı.

# KURGU hat , KURGU bozulma siniflari ve KURGU bir tahmin kurali.
TOHUM, M32 = 20260218, 0xFFFFFFFF


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


BOLGE = ["dogu", "bati", "kuzey", "guney", "merkez"]
TIP = ["mesken", "isyeri"]
DONEM = [f"2026-{a:02d}" for a in range(1, 13)]
ABONE = {}
for i in range(200):
    r = uretec(TOHUM + 37 * i)
    ABONE[f"A{i + 1:03d}"] = {"bolge": BOLGE[int(r() * 5)], "tip": TIP[int(r() * 2)],
                              "baslangic": 10000 + int(r() * 60000)}


def kaynak_uret():
    kayit = []
    for i, (ab, a) in enumerate(ABONE.items()):
        e = a["baslangic"]
        for d in DONEM:
            r = uretec(TOHUM + 101 * i + 7 * DONEM.index(d))
            e += 4 + int(r() * 46)
            kayit.append({"abone": ab, "donem": d, "bolge": a["bolge"], "tip": a["tip"],
                          "endeks": e, "birim": "m3"})
    return kayit


BOZULMA = ["gec_gelen", "yinelenen", "sema_degisti", "birim_degisti", "eksik_bolum", "kayan_tip"]


def boz(kayit, sinif, donem="2026-07"):
    """Tek bir donemi bozar , kalan donemler saglam kalir."""
    yeni, sayac = [], 0
    for k in kayit:
        if k["donem"] != donem:
            yeni.append(k)
            continue
        if sinif == "gec_gelen":
            if k["abone"] <= "A040":
                sayac += 1
                continue
            yeni.append(k)
        elif sinif == "yinelenen":
            yeni.append(k)
            if k["abone"] <= "A060":
                yeni.append(dict(k))
                sayac += 1
        elif sinif == "sema_degisti":
            y = dict(k)
            y["endeks_degeri"] = y.pop("endeks")
            sayac += 1
            yeni.append(y)
        elif sinif == "birim_degisti":
            y = dict(k)
            y["endeks"] = k["endeks"] * 1000        # m3 yerine litre
            y["birim"] = "m3"                       # ETIKET DEGISMEDI
            sayac += 1
            yeni.append(y)
        elif sinif == "eksik_bolum":
            if k["bolge"] == "kuzey":
                sayac += 1
                continue
            yeni.append(k)
        elif sinif == "kayan_tip":
            y = dict(k)
            y["endeks"] = str(k["endeks"])
            sayac += 1
            yeni.append(y)
    return yeni, sayac


def a1_ayikla(kayit):
    ZOR = ("abone", "donem", "bolge", "endeks", "birim")
    tut = [k for k in kayit if all(a in k for a in ZOR)]
    return tut, len(kayit) - len(tut)


def a2_tekille(kayit):
    gor, tut = set(), []
    for k in kayit:
        ad = (k["abone"], k["donem"])
        if ad in gor:
            continue
        gor.add(ad)
        tut.append(k)
    return tut, len(kayit) - len(tut)


def a3_tuketim(kayit):
    tablo = {(k["abone"], k["donem"]): k for k in kayit}
    cikti, dusen = [], 0
    for k in kayit:
        i = DONEM.index(k["donem"])
        if i == 0:
            continue
        onceki = tablo.get((k["abone"], DONEM[i - 1]))
        if onceki is None:
            dusen += 1
            continue
        try:
            f = int(k["endeks"]) - int(onceki["endeks"])
        except (TypeError, ValueError):
            dusen += 1
            continue
        cikti.append(dict(k, m3=f))
    return cikti, dusen


def a4_ozet(kayit):
    top = {}
    for k in kayit:
        ad = (k["bolge"], k["donem"])
        top[ad] = top.get(ad, 0) + k["m3"]
    return top, 0


def a5_sun(ozet):
    bolge = {}
    for (b, d), v in ozet.items():
        bolge.setdefault(b, []).append(v)
    return {b: round(sum(v) / len(v), 2) for b, v in bolge.items()}, 0


ASAMA = [("ayikla", a1_ayikla), ("tekille", a2_tekille), ("tuketim", a3_tuketim),
         ("ozet", a4_ozet), ("sun", a5_sun)]


def hat(kayit):
    iz, veri = [], kayit
    for ad, f in ASAMA:
        veri, dusen = f(veri)
        n = len(veri) if hasattr(veri, "__len__") else 0
        iz.append({"asama": ad, "kalan": n, "dusen": dusen})
    return veri, iz


SINAMA = ["2026-11", "2026-12"]


def model_olcu(kayit):
    """Model kuran , hattin sundugu bolge ortalamasini oznitelik olarak alir."""
    v1, _ = a1_ayikla(kayit)
    v2, _ = a2_tekille(v1)
    t, _ = a3_tuketim(v2)
    oz, _ = a4_ozet(t)
    sun, _ = a5_sun(oz)
    n = {}
    for k in t:
        n.setdefault(k["bolge"], set()).add(k["abone"])
    tahmin = {b: sun[b] / len(n[b]) for b in sun}
    si = [k for k in t if k["donem"] in SINAMA]
    return round(sum(abs(k["m3"] - tahmin[k["bolge"]]) for k in si) / len(si), 3), len(si)


kaynak = kaynak_uret()
t_izi = [a["kalan"] for a in hat(kaynak)[1]]
t_sap, t_n = model_olcu(kaynak)
print("sinama satiri", t_n, " taban sapma", t_sap, " m3")
print(f"{'sinif':<14}{'satir izi':>26}{'satir':>7}{'sapma':>8}{'fark':>8}{'model':>7}")
print(f"{'saglam':<14}{str(t_izi):>26}{'-':>7}{t_sap:>8}{'-':>8}{'-':>7}")
for s in BOZULMA:
    izi = [a["kalan"] for a in hat(boz(kaynak, s)[0])[1]]
    sap, _ = model_olcu(boz(kaynak, s)[0])
    print(f"{s:<14}{str(izi):>26}{('evet' if izi == t_izi else 'hayir'):>7}"
          + f"{sap:>8}{round(sap - t_sap, 3):>8}"
          + f"{('evet' if sap == t_sap else 'hayir'):>7}")
sinama satiri 400  taban sapma 10.832  m3
sinif                          satir izi  satir   sapma    fark  model
saglam         [2400, 2400, 2200, 55, 5]      -  10.832       -      -
gec_gelen      [2360, 2360, 2120, 55, 5]  hayir  10.937   0.105  hayir
yinelenen      [2460, 2400, 2200, 55, 5]  hayir  10.832     0.0   evet
sema_degisti   [2200, 2200, 1800, 45, 5]  hayir  10.835   0.003  hayir
birim_degisti  [2400, 2400, 2200, 55, 5]   evet  10.832     0.0   evet
eksik_bolum    [2354, 2354, 2108, 53, 5]  hayir  10.829  -0.003  hayir
kayan_tip      [2400, 2400, 2200, 55, 5]   evet  10.832     0.0   evet

Satır Gören ve Başarım Gören

İki ölçü aynı altı sınıfı farklı sıralıyor ve bu sıralama farkı rol ayrımının asıl sayısıdır.

Veri mühendisinin izinde en gürültülü sınıf sema_degisti‘dir: tüketim çıkışı 2200’den 1800‘e, özet 55’ten 45’e iniyor. Alan adının değişmesi kaynağın altıda birini götürüyor ve bu, bir gösterge tablosunda gözden kaçması olanaksız bir düşüştür. Aynı sınıf model kuranın ölçüsünde 0,003 oynatıyor, yani 10,832 üzerinden 0,0003 bağıl fark. Model kuran bu sayıya baktığında hiçbir şey olmadığını düşünür ve haklıdır: eğitim verisinin altıda biri kaybolmuş olsa bile bölge ortalaması, kalan dokuz dönemden neredeyse aynı çıkıyor.

Karşı yön daha ilginçtir. gec_gelen kaynaktan yalnız 40 satır eksiltiyor, yani 2400’ün 0,0167’sini (satır oranının en küçük adımı 0,0004’tür, yani bu oran üç haneli okunabilir); bu, çoğu satır sayısı denetiminin bandının altında kalan bir kayıptır. Buna karşılık model kuranın sapmasını 0,105 oynatıyor ve altı sınıf içinde onu en çok kıpırdatan sınıf bu. Nedeni tabloda değil hattın tanımındadır: eksik satırlar rastgele dağılmamış, ilk kırk abonede yoğunlaşmış ve bölge ortalamalarını topluca aşağı çekmiş. Az sayıda ama tek yönlü bir kayıp, çok sayıda ama dengeli bir kayıptan daha zararlıdır ve satır sayısı bu ayrımı yazmaz.

Üçüncü satır iki rolün arasındaki en temiz ayrımdır. yinelenen mühendisin izinde açıkça görünür: ayikla çıkışı 2400 yerine 2460. Model kuranın ölçüsünde ise fark tam sıfırdır, çünkü tekilleştirme aşaması altmış çift kaydı düşürüyor ve öznitelik tablosuna sağlam küme ulaşıyor. Bu, hattın işini doğru yaptığı bir durumdur; yine de mühendisin bunu görmesi gerekir, çünkü aynı üreticiden gelen bir sonraki çift kayıt aynı yerde yakalanmayabilir.

eksik_bolum satırı ise ölçü okumanın en tehlikeli yanını gösteriyor. Sapma 10,832’den 10,829’a düşüyor, yani bozulma modelin ölçüsünü iyileştiriyor. İyileşme gerçek değildir; kuzey bölgesinin iki dönemi tamamen kaybolduğu için o bölgenin sunulan ortalaması kalan dokuz hücreden hesaplanıyor ve rastlantı sonucu sınama dönemlerine biraz daha yakın düşüyor. Sonuç şudur: bir ölçünün kötüleşmemesi sağlık kanıtı değildir, çünkü bozulma ölçüyü iyileştirebilir de. İşaretin yönü bozulmanın varlığı hakkında hiçbir şey söylemez.

İkisinde de Görünmeyen

Tablonun son okuması iki satırdır: birim_degisti ve kayan_tip. İkisinde de satır izi sağlam hatla birebir aynı, sapma da birebir aynı. İki rolün rutin ölçüsünün ikisi de bu iki sınıfa tamamen kördür.

kayan_tip için neden yüzeyseldir: hat metni sayıya çeviriyor, dönüşüm başarılı oluyor ve ne satır ne değer değişiyor. Bunu gören tek şey satırın değerine hiç bakmayan bir tür denetimidir ve böyle bir denetim hattın sıfırıncı adımında koşabilir. birim_degisti için neden yapısaldır ve aşağıdaki blok onu gösterir.

def bolge_toplam(kayit):
    v1, _ = a1_ayikla(kayit)
    v2, _ = a2_tekille(v1)
    t, _ = a3_tuketim(v2)
    oz, _ = a4_ozet(t)
    top = {}
    for (b, d), v in oz.items():
        top[b] = top.get(b, 0) + v
    return top


def donem_ortalama(kayit):
    v1, _ = a1_ayikla(kayit)
    v2, _ = a2_tekille(v1)
    t, _ = a3_tuketim(v2)
    d = {}
    for k in t:
        d.setdefault(k["donem"], []).append(k["m3"])
    return {a: round(sum(v) / len(v), 2) for a, v in d.items()}


ilk = {k["abone"]: k["endeks"] for k in kaynak if k["donem"] == DONEM[0]}
son = {k["abone"]: k["endeks"] for k in kaynak if k["donem"] == DONEM[-1]}
s_top, b_top = bolge_toplam(kaynak), bolge_toplam(boz(kaynak, "birim_degisti")[0])
print("bolge      uc farki   saglam ozet    bozuk ozet")
for b in sorted(s_top):
    uc = sum(son[a] - ilk[a] for a, v in ABONE.items() if v["bolge"] == b)
    print(f"{b:<9}{uc:>11}{s_top[b]:>14}{b_top[b]:>14}")
s_d, b_d = donem_ortalama(kaynak), donem_ortalama(boz(kaynak, "birim_degisti")[0])
print("donem       saglam          bozuk")
for d in DONEM[5:9]:
    print(f"{d:<10}{s_d[d]:>10}{b_d[d]:>15}")
bolge      uc farki   saglam ozet    bozuk ozet
bati            9164          9164          9164
dogu            9695          9695          9695
guney          11721         11721         11721
kuzey          13338         13338         13338
merkez         14536         14536         14536
donem       saglam          bozuk
2026-06        24.08          24.08
2026-07         26.7    40592074.02
2026-08        25.55   -40592021.77
2026-09        28.96          28.96

Birinci tablonun üç sütunu her bölge için aynı sayıyı veriyor. Sol sütun hattan hiç geçmeden, doğrudan kaynağın uç noktalarından hesaplandı: bölgenin abonelerinin son dönem endeksi eksi ilk dönem endeksi. Orta ve sağ sütun ise hattın on bir özet hücresinin toplamı, sağlam ve bozuk kaynakla. Üçünün eşitliği bir ölçüm sonucu değil, bir kimliktir: ardışık farkların toplamı uçların farkına eşittir. birim_degisti uçlara dokunmadığı için toplam değişemez ve toplamı on bire bölen sunum değeri de değişemez. Bu, koşum yapılmadan da bilinen bir sonuçtur; koşum yalnız doğrulamıştır.

İkinci tablo aynı öznitelik tablosunu dönem ekseninde okuyor ve orada bozulma bağırıyor: temmuz ortalaması 26,7 yerine 40592074,02, ağustos ortalaması 25,55 yerine eksi 40592021,77. Veri saklamıyor; saklayan şey iki rolün de dönem eksenini toplaması. Mühendis satırları aşama başına topluyor, model kuran değerleri bölge başına topluyor; bozulma tam olarak bu iki toplamanın altındaki eksende, birbirini götüren iki işaretle yaşıyor. Buradan çıkan kural genel ve uygulanabilirdir: bir ölçü, bozulmanın yaşadığı ekseni topluyorsa o bozulmayı göremez.

Rol ayrımının sayısı da buradan okunur. Mühendisin ölçüsü birinci, ikinci ve üçüncü aşamadan okunuyor; model kuranın ölçüsü beşinci aşamanın çıktısından. Arada dördüncü aşama duruyor ve o elli beş hücreyi iki rolün de rutin ölçüsü okumuyor. Bozulmanın oturduğu yer tam olarak orası. Sınır bir görev tanımı sorusu değildir; hattın hangi aşamasından hangi sayının okunduğu sorusudur ve iki rolün ölçüsü arasında ölçülmeyen bir aşama kaldığı sürece sınır bir boşluk üretir.

Özet

  • Veri mühendisliği ile veri bilimi arasındaki sınır bir görev tanımı değil, ölçünün okunduğu aşamadır: mühendis birinci ile üçüncü aşamanın satır izini, model kuran beşinci aşamanın çıktısını okur.
  • İki ölçü aynı altı sınıfı farklı sıralıyor: sema_degisti izde en gürültülü sınıf (2200 satır 1800’e iniyor) ama sapmayı yalnız 0,003 oynatıyor; gec_gelen yalnız 40 satır eksiltiyor ama sapmayı 0,105 oynatarak en çok o kıpırdatıyor.
  • Az sayıda ama tek yönlü bir kayıp, çok sayıda ama dengeli bir kayıptan daha zararlıdır ve satır sayısı bu ayrımı yazmaz.
  • eksik_bolum sapmayı 10,832’den 10,829’a düşürüyor: bir bozulma ölçüyü iyileştirebilir, bu yüzden ölçünün kötüleşmemesi sağlık kanıtı değildir.
  • birim_degisti ve kayan_tip iki ölçüde de birebir aynı sonucu veriyor. Birim değişiminin görünmezliği teleskopik bir kimlikten gelir: bölgenin on bir hücresinin toplamı uç endekslerin farkına eşittir ve bozulma uçlara dokunmaz.
  • Aynı tablo dönem ekseninde okunduğunda temmuz ortalaması 26,7 yerine 40592074,02 çıkıyor; bir ölçü, bozulmanın yaşadığı ekseni topluyorsa o bozulmayı göremez.

Sonraki Adım

Üç ders boyunca hat, verinin geldiği yerden başlıyormuş gibi ele alındı. Kaynak kaynak_uret çağrısıyla ortaya çıktı, bozulma da ona dışarıdan uygulandı. Verinin nereden geldiği hiç sorulmadı. Oysa bu dersin son tablosundaki birim_degisti, bir sahadaki dönüştürücünün değişmesiyle olur ve hangi kaynak sınıfının böyle bir kazayı taşıyabileceği, hangisinin taşıyamayacağı önceden bilinebilir. Bir uygulama veritabanından okuyan hat ile bir günlük akışından ya da bir dış servisten okuyan hat aynı bozulma sınıflarına açık değildir ve aynı bozulmayı aynı aşamada yakalamaz. Sonraki ders kaynakları türleriyle ayırır ve her kaynak sınıfı için iki sayı basar: hangi bozulma sınıflarını taşıdığı ve her birinin yakalama gecikmesi.

İlerlemeni kaydetmek ve not almak için Giriş yap

Notlarım

Not almak için giriş yapmalısın.

Aramak için yazmaya başlayın.

↑↓ Esc gezin · aç · kapat