Ders 03 / 12
Veri ve Model Sürümleme
Aynı ada verilen iki farklı içeriğin ayrılmasının ölçülmesi: dört teslim aynı `olcum-2026` adı altında 2200, 2180, 2160 ve yine 2200 satır getirdiğinde sürümsüz kurulumda tek bir ad dört koşumun tamamını belirsiz bırakıyor ve üç ayrı sınama sayısı 0,8067, 0,8064 ile 0,8078 aynı adın arkasında duruyor, içerik imzasıyla adlandırıldığında üç ad doğuyor ve belirsiz koşum sıfıra iniyor; model tarafında dört koşumun ağırlığı birebir aynı olduğu için yalnız ağırlığa bakan bir model kimliği dört koşumu tek sürümde topluyor ve ancak veri imzası eklendiğinde üç sürüm ayrılıyor; bedel olarak tarih adlı şema 8740 satır saklarken içerik adlı şema 6540 satır saklıyor ve her teslimde imza için 8740 satır okunuyor; çıktı imzası hattın yuttuğu değişikliği görmüyor, altmış kayıt iki kez geldiğinde kaynak imzası değişirken çıktı imzası ve isabet birebir aynı kalıyor.
İçindekiler
Önceki dersin defteri her koşumun kaç satır okuduğunu yazdı. On sekiz koşumun hepsi verisini aynı yerden okudu ve o yerin adı hiç değişmedi. Defter “2200 satır” yazdığında iki koşumun aynı 2200 satırı okuduğunu varsaydık, ama bu varsayım hiçbir yerde sınanmadı.
Bu ders o varsayımı sınar. Veri soyağacı, yani bir sunum değerinden kaynağa giden bağın kaydı, Veri Mühendisliğine Giriş kursunda ölçüldü ve burada tekrarlanmaz. Buradaki soru daha dar: bir ad altındaki içerik değiştiğinde ve ad değişmediğinde, kaç koşum birbirinden ayırt edilemez hâle geliyor.
- YU19. Kurgu üretici veriyi dört teslimde getirir. Teslimler sırasıyla 2200, 2180, 2160 ve
yine 2200 satırdır; dördü de aynı
olcum-2026adıyla yazılır. Dördüncü teslim birincinin içeriğiyle birebir aynıdır. - YU20. Veri sürümü bir adla bir içeriğin eşleşmesidir. Üç şema karşılaştırılır: sürümsüz (tek ad, üzerine yazılır), tarih adlı (her teslime bir ad) ve içerik adlı (ad, içerikten üretilen imzayı taşır).
- YU21. İmza içerikten üretilen kısa bir özettir ve ders içinde yazılır; hiçbir dış kitaplık çağrılmaz. İmza bir güvenlik aracı değil, bir kimlik aracıdır.
- YU22. Taban çizgisi sürümsüz kurulumdur: tek ad, üzerine yazılan içerik, geriye dönük yeniden üretim yok.
- YU23. Ölçülen birimler ad sayısı, belirsiz koşum ve saklanan satırdır. Belirsiz koşum, aynı adı taşıyıp o ad altında farklı bir sonuç veren koşumdur.
- YU24. Öznitelik kodu bu derste sabittir; dört koşum da tam geçmişi görür ve dört basamağa yuvarlar. Değişen tek şey verinin içeriğidir.
- YU25. Etiket dağılımı
{0: 1752, 1: 448}, taban sınıf oranı 0,7964’tür ve bu dersteki isabet sayıları bir başarım iddiası taşımaz. Çözünürlük 0,0017’dir.
Aynı Adın Altındaki İçerik
İlk blok önceki iki dersin kurgu kaynağını, hattını ve modelini aynen yeniden kurar.
# KURGUDUR. Sayac okumalari, hat ve model ders icinde tanimlanir; gercek bir # ogrenme kitapligi ya da model kayit defteri urunu cagrilmaz. 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 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 EGITIM = DONEM[1:9] SINAMA = DONEM[9:] ESIK = 40 def satirlar(): v, _ = a1_ayikla(kaynak_uret()) v, _ = a2_tekille(v) v, _ = a3_tuketim(v) return v def etiket(k): return 1 if k["m3"] > ESIK else 0 def oznitelikler(kayitlar, pencere=None, basamak=4): """Agirliktan bagimsizdir , bir kez hesaplanir.""" sirali = sorted(kayitlar, key=lambda k: DONEM.index(k["donem"])) ab, bo = {}, {} for k in sirali: ab.setdefault(k["abone"], []).append((DONEM.index(k["donem"]), k["m3"])) bo.setdefault(k["bolge"], []).append((DONEM.index(k["donem"]), k["m3"])) def ortalama(dizi, i): secili = [v for d, v in dizi if (d < i and (pencere is None or d >= i - pencere))] return round(sum(secili) / len(secili), basamak) if secili else 0.0 oz = {} for k in kayitlar: i = DONEM.index(k["donem"]) oz[(k["abone"], k["donem"])] = { "abone_ort": ortalama(ab[k["abone"]], i), "bolge_ort": ortalama(bo[k["bolge"]], i), "isyeri": 1 if k["tip"] == "isyeri" else 0} return oz IZGARA = [(a, b, c) for a in (0.6, 0.8, 1.0) for b in (0.0, 0.2, 0.4) for c in (0, 4, 8)] def puan(o, w): return w[0] * o["abone_ort"] + w[1] * o["bolge_ort"] + w[2] * o["isyeri"] def egit(kayitlar, oz, izgara=None, esik=ESIK, donemler=None): izgara = IZGARA if izgara is None else izgara donemler = EGITIM if donemler is None else donemler kume = [k for k in kayitlar if k["donem"] in donemler] en_iyi, en_iyi_w = -1.0, None for w in izgara: d = sum(1 for k in kume if (1 if puan(oz[(k["abone"], k["donem"])], w) > esik else 0) == etiket(k)) o = d / len(kume) if o > en_iyi: en_iyi, en_iyi_w = o, w return {"agirlik": en_iyi_w, "egitim_isabeti": round(en_iyi, 4), "aday": len(izgara), "egitim_satiri": len(kume)} def sina(kayitlar, model, oz, esik=ESIK, donemler=None): donemler = SINAMA if donemler is None else donemler kume = [k for k in kayitlar if k["donem"] in donemler] d = sum(1 for k in kume if (1 if puan(oz[(k["abone"], k["donem"])], model["agirlik"]) > esik else 0) == etiket(k)) return round(d / len(kume), 4)
Dört teslim aşağıdaki blokta koşturulur. Her teslimde aynı kod aynı adla veriyi okur, modeli eğitir
ve sonucu tuketim-esigi adıyla yazar. imza içerikten kısa bir özet üretir ve şimdilik yalnız
raporlanır; hiçbir karara girmez.
S = satirlar() def imza(metin): """Icerikten uretilen kisa bir ozet. Guvenlik degil , kimlik araci.""" h = 2166136261 for c in metin: h = ((h ^ ord(c)) * 16777619) & 0xFFFFFFFF return f"{h:08x}" def veri_imzasi(kayitlar): return imza("|".join(f"{k['abone']}:{k['donem']}:{k['m3']}" for k in kayitlar)) TESLIM = [2200, 2180, 2160, 2200] KOSUM = [] for no, n in enumerate(TESLIM, start=1): kay = S[:n] oz = oznitelikler(kay) m = egit(kay, oz) KOSUM.append({"kosum": no, "veri_adi": "olcum-2026", "satir": n, "veri_imza": veri_imzasi(kay), "model_adi": "tuketim-esigi", "agirlik": m["agirlik"], "sinama": sina(kay, m, oz)}) print(f"{'teslim':<8}{'veri adi':<13}{'satir':>7}{'veri imzasi':>13}" f"{'model adi':>15}{'agirlik':>17}{'sinama':>9}") for k in KOSUM: print(f"{k['kosum']:<8}{k['veri_adi']:<13}{k['satir']:>7}{k['veri_imza']:>13}" f"{k['model_adi']:>15}{str(k['agirlik']):>17}{k['sinama']:>9.4f}") print() print("ayri sinama sayisi:", len(set(k["sinama"] for k in KOSUM)), " ayri agirlik:", len(set(k["agirlik"] for k in KOSUM)), " ayri veri icerigi:", len(set(k["veri_imza"] for k in KOSUM)))
teslim veri adi satir veri imzasi model adi agirlik sinama 1 olcum-2026 2200 bd88a253 tuketim-esigi (0.6, 0.4, 0) 0.8067 2 olcum-2026 2180 f008c71c tuketim-esigi (0.6, 0.4, 0) 0.8064 3 olcum-2026 2160 cebfcc57 tuketim-esigi (0.6, 0.4, 0) 0.8078 4 olcum-2026 2200 bd88a253 tuketim-esigi (0.6, 0.4, 0) 0.8067 ayri sinama sayisi: 3 ayri agirlik: 1 ayri veri icerigi: 3
Tablo iki sütununda hiç değişmez: veri adı dört satırda da olcum-2026, model adı dört satırda da
tuketim-esigi. Bir sütununda da hiç değişmez: ağırlık dört koşumda da (0.6, 0.4, 0), yani
üretilen model dosyası birebir aynıdır. Değişen iki sütun vardır: içerik imzası üç ayrı değer
alır ve sınama isabeti üç ayrı sayı verir.
Adın Kaç İçeriği Var
Sayılacak şey artık nettir. Bir adlandırma şeması, aynı adı taşıyıp farklı sonuç veren koşum bırakıyorsa o koşumlar belirsizdir: hangi içerikten geldikleri addan okunamaz.
def olc(kimlik): """Kac ad var , kac kosum belirsiz kaliyor , kac satir saklaniyor.""" grup = {} for k in KOSUM: grup.setdefault(kimlik(k), []).append(k) belirsiz = sum(len(v) for v in grup.values() if len(set(x["sinama"] for x in v)) > 1) return len(grup), belirsiz, sum(v[-1]["satir"] for v in grup.values()) print(f"{'sema':<14}{'veri adi':>10}{'belirsiz kosum':>16}{'saklanan satir':>16}") for ad, kim in (("surumsuz", lambda k: k["veri_adi"]), ("tarih adli", lambda k: f"{k['veri_adi']}@t{k['kosum']}"), ("icerik adli", lambda k: f"{k['veri_adi']}@{k['veri_imza']}")): a, b, s = olc(kim) print(f"{ad:<14}{a:>10}{b:>16}{s:>16}") print() print(f"{'model kimligi':<26}{'ayri surum':>12}{'belirsiz kosum':>16}") for ad, kim in (("yalniz agirlik", lambda k: imza(str(k["agirlik"]))), ("veri imzasi + agirlik", lambda k: imza(f"{k['veri_imza']}|{k['agirlik']}"))): a, b, _ = olc(kim) print(f"{ad:<26}{a:>12}{b:>16}") print() print("imza icin okunan satir:", sum(TESLIM))
sema veri adi belirsiz kosum saklanan satir surumsuz 1 4 2200 tarih adli 4 0 8740 icerik adli 3 0 6540 model kimligi ayri surum belirsiz kosum yalniz agirlik 1 4 veri imzasi + agirlik 3 0 imza icin okunan satir: 8740
Sürümsüz kurulumda tek bir ad vardır ve dört koşumun dördü de belirsizdir. Bu satır kursun kuralının veri tarafındaki hâlidir: 0,8078 sayısı bir rapora girdiğinde onu üreten içerik artık yoktur, çünkü dördüncü teslim üçüncünün üzerine yazmıştır. Saklanan satır sütunu bunu doğrular: sürümsüz şema en az yeri tutar, 2200 satır, ve karşılığında geçmişin tamamını kaybeder.
Tarih adlı şema belirsizliği sıfıra indirir, ama bir kusuru vardır: dört ad üretir, oysa üç içerik vardır. Birinci ve dördüncü teslim birebir aynı içeriktir ve tarih şeması bunu göremediği için aynı 2200 satırı iki kez saklar. İçerik adlı şema aynı belirsizliği üç adla ve 6540 satırla karşılar; dördüncü teslim hiç yeni yer tutmaz, çünkü imzası zaten defterdedir.
İmza Neyi İmzalar
veri_imzasi hattın çıktısını imzalar, yani abone, dönem ve hesaplanmış tüketim üçlüsünü. Bu
bir seçimdir ve bedeli vardır: hattın yuttuğu bir üretici değişikliği çıktı imzasına hiç yansımaz.
Aşağıdaki blok bunu ölçer. Üretici, temmuz ayında altmış kaydı iki kez göndersin; kaynak değişmiştir
ama tekilleştirme aşaması yinelenen satırları düşürür.
def kaynak_imzasi(kayitlar): return imza("|".join(f"{k['abone']}:{k['donem']}:{k['endeks']}" for k in kayitlar)) def hatta_ver(kaynak): v, _ = a1_ayikla(kaynak) v, _ = a2_tekille(v) v, _ = a3_tuketim(v) return v ham = kaynak_uret() # Uretici 60 kaydi iki kez gonderdi: kaynak degisti , hat onu yutuyor. yinelenen = ham + [dict(k) for k in ham if k["abone"] <= "A060" and k["donem"] == "2026-07"] print(f"{'teslim':<12}{'kaynak satiri':>15}{'kaynak imzasi':>15}" f"{'cikti satiri':>14}{'cikti imzasi':>14}{'sinama':>9}") for ad, kaynak in (("saglam", ham), ("yinelenen", yinelenen)): c = hatta_ver(kaynak) oz2 = oznitelikler(c) m2 = egit(c, oz2) print(f"{ad:<12}{len(kaynak):>15}{kaynak_imzasi(kaynak):>15}{len(c):>14}" f"{veri_imzasi(c):>14}{sina(c, m2, oz2):>9.4f}") print() print(f"{'teslim':<8}{'satir':>7}{'sinama satiri':>15}{'cozunurluk':>12}") for n in TESLIM[:3]: sk = [k for k in S[:n] if k["donem"] in SINAMA] print(f"{n:<8}{n:>7}{len(sk):>15}{1 / len(sk):>12.4f}")
teslim kaynak satiri kaynak imzasi cikti satiri cikti imzasi sinama saglam 2400 d501f04f 2200 bd88a253 0.8067 yinelenen 2460 93576832 2200 bd88a253 0.8067 teslim satir sinama satiri cozunurluk 2200 2200 600 0.0017 2180 2180 594 0.0017 2160 2160 588 0.0017
Kaynak imzası değişti, çıktı imzası birebir aynı kaldı ve isabet de aynı. İki teslimin sürüm kaydı aynı satırı gösterir, oysa üreticiden gelen içerik farklıdır. Bu, hattın doğru davranışıdır ve sürümlemenin bir sınırıdır: çıktı imzası hattın yuttuğu değişikliği görmez. Ters yönde de eksiktir; kaynağı imzalayan bir şema burada bir sürüm farkı işaretler, oysa modele giden veri hiç değişmemiştir. İki imza iki ayrı soruyu yanıtlar ve hangisinin tutulduğu yazılmadan bir veri sürümü eksik kalır.
Alt tablo bir başka ayrıntıyı kapatır. Teslim küçüldükçe sınama kümesi de küçülür: 600, 594 ve 588 satır. Üç teslimde çözünürlük 0,0017’de kalır, ama karşılaştırılan sayılar aynı kümede ölçülmüş değildir. 0,8067 ile 0,8064 arasındaki fark bu yüzden bir başarım farkı olarak okunamaz.
Modelin Kimliği Ağırlığından İbaret Değildir
Alt tablo dersin en sessiz bulgusunu taşır. Model dosyası dört koşumda da aynıdır, dolayısıyla modeli kendi içeriğine göre adlandıran bir şema dört koşumu tek bir sürümde toplar ve dördünü de belirsiz bırakır. Bu, veri tarafındaki hatanın aynadaki görüntüsüdür: orada bir ad üç içeriği örtüyordu, burada bir içerik üç sayıyı örtüyor.
Dört model dosyası birbirinin yerine konabilir görünür, çünkü aynı ağırlıkları taşırlar. Yerlerine konamazlar: her biri farklı bir veri kümesinde ölçülmüştür ve bildirdikleri sayı 0,8067, 0,8064 ve 0,8078’dir. Aradaki 0,0014 ile 0,0011 fark çözünürlüğün altında değildir, çünkü sınama kümesinin boyu da teslimle birlikte değişmiştir. Ağırlığa veri imzası eklendiğinde kimlik üç sürüme ayrılır ve belirsiz koşum 0’a iner. Bir model sürümü, model dosyasının değil, model dosyasıyla onu üreten veri sürümünün birlikte imzasıdır.
Sürümlemenin Bedeli ve Söylemediği
Bedel üç kalemdir. Birincisi saklanan satırdır: içerik adlı şema 6540 satır tutar, sürümsüz şemanın 2,97 katı. İkincisi okunan satırdır: imza içerikten hesaplandığı için her teslimde bütün satırlar bir kez daha okunur, dört teslimde 8740 satır. Üçüncüsü eklenen adımdır: yazma işlemi artık imza hesaplamak ve defter satırı eklemek zorundadır.
Bunun karşılığında alınan şey dar ve kesindir: sürümleme hangi içeriğin hangi sayıyı ürettiğini söyler. Söylemediği şeyse hangi içeriğin doğru olduğudur. Üç teslimden hangisinin eksik geldiğini, hangisinin tam olduğunu ve 0,8078 sayısının güvenilir olup olmadığını üç imza da söylemez; onu söyleyen şey Veri Mühendisliğine Giriş kursunda ölçülen denetimlerdir. Sürümleme bir kalite aracı değil, bir kimlik aracıdır ve katkısı yalnız belirsiz koşum sayısıyla ölçülür.
Özet
- Dört teslim aynı
olcum-2026adıyla 2200, 2180, 2160 ve yine 2200 satır getirdi; ad hiç değişmedi, içerik üç ayrı imza aldı ve sınama isabeti 0,8067, 0,8064 ile 0,8078 oldu. - Sürümsüz şemada tek ad vardır ve dört koşumun dördü de belirsizdir; içerik adlı şemada üç ad vardır ve belirsiz koşum 0’dır.
- Tarih adlı şema belirsizliği aynı şekilde kapatır ama dört ad üretip 8740 satır saklar; içerik adlı şema aynı işi üç ad ve 6540 satırla, yani sürümsüz şemanın 2,97 katıyla yapar, çünkü dördüncü teslimin birinciyle aynı olduğunu görür.
- Çıktı imzası hattın yuttuğu değişikliği görmez: altmış kayıt iki kez geldiğinde kaynak imzası değişir, çıktı imzası ve isabet birebir aynı kalır. Hangi imzanın tutulduğu yazılmadan bir veri sürümü eksik kalır.
- Model dosyası dört koşumda da birebir aynıdır. Yalnız ağırlığa bakan bir model kimliği dört koşumu tek sürümde toplar; veri imzası eklendiğinde üç sürüm ayrılır ve belirsiz koşum 0 olur.
- Sürümleme hangi içeriğin hangi sayıyı ürettiğini söyler, hangisinin doğru olduğunu söylemez; o soru denetimlerin işidir.
Sonraki Adım
Üç derste koşumun kendisi kayda geçti ve sürümlendi: hangi kalemlerle koşulduğu yazıldı, hangi içeriği okuduğu bir imzaya bağlandı ve aynı adın arkasındaki üç içerik birbirinden ayrıldı. Bütün bu iş eğitim tarafında yapıldı. Modele giren özniteliğin eğitim sırasında bir kodla, üretimde çağrıldığında başka bir kodla hesaplanıyor olabileceği hiç sorulmadı. Sonraki ders o iki yolu yan yana koyar ve tek bir soruyu ölçer: ağırlıklar birebir aynıyken isabet neden düşüyor.
İlerlemeni kaydetmek ve not almak için Giriş yap
Notlarım
Not almak için giriş yapmalısın.