Ders 10 / 16
Dizinleme ve Güncelleme
Dizinin bir anlık görüntü olduğunun ve kaynak değiştikçe bayatladığının ölçülmesi: on iki dönemlik kurgu bir değişiklik akışında yenileme aralığı birden on ikiye çıkarıldığında bayat parça payı 0,0000'dan 0,2562'ye, yanlış yanıt payı 0,0750'den 0,3875'e çıkıyor. Erişim sütunu bu bozulmanın hiçbirini göstermiyor: erişim anması altı aralıkta da 0,9500, kavram isabeti 0,9250; düşen tek sütun, yanıtın kopyaladığı yürürlük kaydının güncel olma payıdır. Yenileme maliyeti iki politikada ayrı okunuyor: tam yeniden dizinleme aralık birde 8316 parça gömüyor, artımlı yenileme 881. Aralığı on iki katına çıkarmak artımlı yenilemede güncel yanıt başına gömülen parçayı yalnız 1,98'den 1,77'ye indiriyor, yani kazancı yüzde on bir; aynı kararın bedeli güncel yanıt payında 0,3125'tir. İki koşumun farkı bütün satırlarda 0,0000.
İçindekiler
Önceki üç ders dağarcığı durağan kabul etti. Belgeler bir kez hazırlandı, bir kez parçalandı, bir kez gömüldü; dizin kurulduktan sonra bir daha ele alınmadı. Saha kayıtları böyle davranmaz. Bir yordam yeniden yayımlanır, bir eşik güncellenir, bir kayıt yürürlükten kalkar. Kaynak değiştiğinde dizin değişmez; dizin bir anlık görüntüdür ve ne zaman çekildiği yazılmadıkça neyi gösterdiği bilinmez.
Bu dersin ölçtüğü bozulma öncekilerden başka türlüdür. Erişim yanlış parça getirmiyor: getirilen parça hâlâ doğru belgeden, doğru kavramdan. Bozulan şey parçanın içeriğidir. Bu yüzden erişim sütunu sessiz kalır ve arıza yalnız üretim sütununda görünür.
- EH21. Kod bir benzeticidir; dağarcık, değişiklik akışı ve sorgular kurgudur, tohum 20260218. Gömme ve dil modeli önceki derslerin tanımlarıdır.
- EH22. Her belge bir yürürlük kaydı taşır. Belge yeniden yayımlandığında kayıt bir artar; parça dizinden servis edilirken kaydıyla birlikte verilir. Değişim akışı on iki dönemdir ve her dönemde belgelerin 0,10’u yeniden yayımlanır.
- EH23. Yeniden yayım parçanın gövdesini değil kaydını değiştirir. Bu, ölçümü sadeleştiren bir varsayımdır: gömme oynamadığı için erişim sıralaması bütün aralıklarda aynı kalır ve düşen sütunun yalnız bayatlıktan düştüğü kesinleşir.
- EH24. Benzeticiye tek bir davranış eklenir: model, seçtiği kavramın yüzeyini taşıyan ilk kaynak parçadaki yürürlük kaydını olduğu gibi kopyalar. Alıntılayan bir modelin yaptığı budur ve bayatlığın yanıta geçtiği yer burasıdır.
- EH25. Bayat parça payı, servis edilen parçaların kaydı ile kaynağın o dönemdeki gerçek kaydının uyuşmama oranıdır. Güncel yanıt payı, kavramı doğru olan ve kopyaladığı kaydı kaynağın güncel kaydına eşit olan yanıtların oranıdır.
- EH26. İki yenileme politikası ölçülür: tam yeniden dizinleme her yenilemede bütün parçaları yeniden gömer, artımlı yenileme yalnız o aralıkta değişmiş belgelerin parçalarını. Bir aralıkta iki kez değişen belge bir kez gömülür.
- EH27. Ölçüm on iki dönemin hepsinde yapılır; her dönem kırk sorgu sorulur, yani her aralık için 480 istek. Bayat parça payı ile gömülen parça sayısı koşumdan bağımsızdır.
Bayatlığın Yanıta Geçtiği Yer
İlk blok dağarcığı kurar, üstüne değişiklik akışını ve yürürlük kaydını koyar, benzeticiyi kopyalama davranışıyla birlikte tanımlar ve yenileme aralığını süpürür.
# KURGUDUR. Dagarcik, kavram ekseni, gomme, degisim akisi ve dil modeli benzeticidir; # gercek bir uc nokta cagrilmaz. Tohum 20260218. TOHUM, M32 = 20260218, 0xFFFFFFFF BOYUT = 32 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 def belirtecle(m): b = [] for s in m.lower().replace(",", " , ").split(): while len(s) > 5: b.append(s[:5]) s = s[5:] b.append(s) return b # ---- KURGU anlam ekseni: her kavramin belge dilinde ve sorgu dilinde ayri yuzeyi var SINIF = ["tarife", "ariza", "sayac", "kesinti", "bakim"] KOD = {"tarife": "TR", "ariza": "AR", "sayac": "SY", "kesinti": "KS", "bakim": "BK"} KAVRAM = { # kavram: (sinif, belge yuzeyi, sorgu yuzeyi) "basamak": ("tarife", "kademe esigi", "hangi dilimdeyim"), "birim": ("tarife", "birim ucret", "metrekup fiyati"), "abonetip": ("tarife", "abone tipi", "mesken mi isyeri mi"), "gecis": ("tarife", "tarife gecisi", "plan degistirme"), "arizakod": ("ariza", "ariza kodu", "hata numarasi"), "sizinti": ("ariza", "hat sizintisi", "su kacagi"), "basinc": ("ariza", "basinc dususu", "zayif akis"), "ekip": ("ariza", "saha ekibi", "gorevli ne zaman gelir"), "endeks": ("sayac", "endeks degeri", "sayac ustundeki rakam"), "okuma": ("sayac", "okuma yordami", "nasil kaydediliyor"), "degisim": ("sayac", "sayac degisimi", "cihaz yenileme"), "dogrula": ("sayac", "okuma dogrulamasi", "yanlis girilmis mi"), "planli": ("kesinti", "planli kesinti", "onceden duyurulan durma"), "duyuru": ("kesinti", "duyuru kanali", "nereden ogrenirim"), "sure": ("kesinti", "kesinti suresi", "ne kadar surer"), "geridonus": ("kesinti", "yeniden verme", "ne zaman gelir"), "periyot": ("bakim", "periyodik bakim", "duzenli kontrol"), "vana": ("bakim", "vana kontrolu", "musluk kapatma duzeni"), "filtre": ("bakim", "filtre degisimi", "temizleme parcasi"), "kalib": ("bakim", "kalibrasyon kaydi", "olcum ayari"), } ANAHTAR = list(KAVRAM) ORTAK = ["kayit", "bolge", "donem", "islem", "form", "onay", "not"] # ---- KURGU dagarcik BELGE = [] for i in range(200): r = uretec(TOHUM + 7919 * i) s = SINIF[ayrik(r(), [0.22, 0.24, 0.20, 0.18, 0.16])] kav = [k for k in ANAHTAR if KAVRAM[k][0] == s] ana = kav[int(r() * len(kav))] n = 2 + int(r() * 4) par, kavlar = [], [ana] for _ in range(n): y = kav[int(r() * len(kav))] kavlar.append(y) o = ORTAK[int(r() * len(ORTAK))] par.append(f"{KAVRAM[y][1]} icin {o} tutulur ve {KAVRAM[ana][1]} ile birlikte yazilir") BELGE.append({"kod": f"{KOD[s]}{i + 1:03d}", "sinif": s, "ana": ana, "kavram": kavlar, "baslik": f"{KAVRAM[ana][1]} yordami", "par": par}) # ---- KURGU gomme: yuzey once kavrama, kavram sonra boyuta dusuruluyor def _kavramla(m, alan=True): v = [0.0] * len(ANAHTAR) dm = " " + m.lower() + " " for i, k in enumerate(ANAHTAR): bel, sor = KAVRAM[k][1], KAVRAM[k][2] if bel in dm: v[i] += 1.0 if sor in dm: v[i] += 1.0 if alan else 0.0 if not alan: for o in ORTAK: if " " + o + " " in dm: for i in range(len(ANAHTAR)): v[i] += 0.05 return v IZDUS = [] for i in range(len(ANAHTAR)): r = uretec(TOHUM ^ (i + 1) * 2654435761) IZDUS.append([r() * 2 - 1 for _ in range(64)]) def gom(m, boyut=BOYUT, alan=True): k = _kavramla(m, alan) v = [0.0] * boyut for i, a in enumerate(k): if a: for j in range(boyut): v[j] += a * IZDUS[i][j % 64] n = sum(x * x for x in v) ** 0.5 return [x / n for x in v] if n else v def aci(a, b): return sum(x * y for x, y in zip(a, b)) # ---- KURGU sorgu kumesi: sorgu dili belge dilinden ayri SORGU = [] for i in range(40): r = uretec(TOHUM + 104729 * i) d = BELGE[int(r() * len(BELGE))] SORGU.append({"metin": f"{KAVRAM[d['ana']][2]} {ORTAK[int(r() * len(ORTAK))]}", "sinif": d["sinif"], "kavram": d["ana"]}) import math # ---- KURGU degisim akisi: on iki donem, her donemde bir bolum belge yeniden yayimlanir DONEM = 12 DEGISIM = [] for t in range(1, DONEM + 1): r = uretec(TOHUM + 6007 * t) DEGISIM.append([i for i in range(len(BELGE)) if r() < 0.10]) def damga(i, t): """i numarali belgenin t doneminin sonundaki yururluk kaydi.""" return "Y%02d" % sum(i in DEGISIM[u] for u in range(t)) PARCA = [{"belge": i, "kod": d["kod"], "sinif": d["sinif"], "govde": p, "kavram": [k for k in ANAHTAR if KAVRAM[k][1] in p]} for i, d in enumerate(BELGE) for p in d["par"]] VEK = [gom(x["govde"]) for x in PARCA] # damga gommeyi degistirmez UST = [] for s in SORGU: q = gom(s["metin"]) UST.append(sorted(range(len(PARCA)), key=lambda i: -aci(q, VEK[i]))[:3]) # ---- KURGU dil modeli benzeticisi: onceki derslerin benzeticisi, tek eklenti # baglamda gordugu yururluk kaydini kopyalamasi PENCERE = 240 ON_BILGI = {"sizinti", "basinc", "sure", "degisim", "vana", "duyuru", "gecis"} SAYAC = [0] def izno(m): h = 2166136261 for c in m: h = ((h ^ ord(c)) * 16777619) & M32 return h def cagir(istem, tohum=TOHUM, sicaklik=0.6): SAYAC[0] += 1 b = belirtecle(istem) if len(b) > PENCERE: return {"durum": "baglam_asimi", "giris": len(b), "cikis": 0, "yanit": ""} if SAYAC[0] % 37 == 0: return {"durum": "hiz_siniri", "giris": len(b), "cikis": 0, "yanit": ""} r = uretec(tohum ^ izno(istem)) dm = " " + istem.lower() + " " p = {k: 0.15 for k in ANAHTAR} for k in ANAHTAR: p[k] += 2.0 * dm.count(KAVRAM[k][1]) if k in ON_BILGI and KAVRAM[k][2] in dm: p[k] += 2.0 w = [math.exp(p[a] / sicaklik) for a in sorted(p)] y = sorted(p)[ayrik(r(), [x / sum(w) for x in w])] for x in istem.split(" . "): # kaynaktaki kaydi oldugu gibi kopyalar if KAVRAM[y][1] in x and "yururluk kaydi" in x: y += " " + x.split("yururluk kaydi ")[1].split()[0] break return {"durum": "tamam", "giris": len(b), "cikis": len(belirtecle(y)), "yanit": y} YONERGE = ("Talebi su kavramlardan birine bagla ve kaynagin yururluk kaydini yaz: " + " , ".join(ANAHTAR) + " . Yanit olarak tek kavram ve kayit yaz . ") def kosum(aralik, tohum=TOHUM): SAYAC[0] = 0 bayat = kavram = guncel = anma = n = 0 gomulen = tam = 0 for t in range(1, DONEM + 1): son = (t // aralik) * aralik # dizinin gordugu son donem if t % aralik == 0: # bu donem yenileme var deg = {i for u in range(t - aralik, t) for i in DEGISIM[u]} gomulen += sum(x["belge"] in deg for x in PARCA) tam += len(PARCA) for s, ug in zip(SORGU, UST): metin = {i: "%s yururluk kaydi %s" % (PARCA[i]["govde"], damga(PARCA[i]["belge"], son)) for i in ug} bayat += sum(damga(PARCA[i]["belge"], son) != damga(PARCA[i]["belge"], t) for i in ug) / 3 anma += any(s["kavram"] in PARCA[i]["kavram"] for i in ug) y = cagir(YONERGE + "Kaynak: " + " . ".join(metin[i] for i in ug) + " . Talep: " + s["metin"], tohum) kv, _, dg = y["yanit"].partition(" ") kay = next((i for i in ug if KAVRAM[kv][1] in metin[i]), None) if kv in ANAHTAR \ else None kavram += kv == s["kavram"] guncel += (kv == s["kavram"] and kay is not None and dg == damga(PARCA[kay]["belge"], t)) n += 1 return bayat / n, anma / n, kavram / n, guncel / n, gomulen, tam print("donem %d, toplam yeniden yayim %d, hic degismeyen belge %d" % (DONEM, sum(len(x) for x in DEGISIM), sum(1 for i in range(len(BELGE)) if all(i not in d for d in DEGISIM)))) print("aralik yenileme gomulen(artimli) gomulen(tam) bayat parca anma kavram guncel") for a in (1, 2, 3, 4, 6, 12): b, an, kv, gu, go, tm = kosum(a) print("%6d %9d %17d %13d %12.4f %6.4f %.4f %.4f" % (a, DONEM // a, go, tm, b, an, kv, gu))
donem 12, toplam yeniden yayim 254, hic degismeyen belge 51
aralik yenileme gomulen(artimli) gomulen(tam) bayat parca anma kavram guncel
1 12 881 8316 0.0000 0.9500 0.9250 0.9250
2 6 839 4158 0.0347 0.9500 0.9250 0.8917
3 4 774 2772 0.0625 0.9500 0.9250 0.8771
4 3 741 2079 0.0937 0.9500 0.9250 0.8208
6 2 662 1386 0.1278 0.9500 0.9250 0.7708
12 1 519 693 0.2562 0.9500 0.9250 0.6125
Tablonun ilk okuması iki sütunun ayrı tutulmasının en açık gerekçesidir. Erişim anması altı satırda da 0,9500, kavram isabeti altı satırda da 0,9250. Yenileme aralığı bir dönemden on iki döneme çıkarken erişim sütununda hiçbir şey değişmiyor, çünkü dizin doğru belgeleri getirmeye devam ediyor. Getirdiği parçaların 0,2562’si artık kaynakta olmayan bir metni gösteriyor ve bunu erişim ölçütlerinden hiçbiri söylemiyor.
Düşen tek sütun güncel yanıt payıdır: 0,9250’den 0,6125’e. Aradaki 0,3125 eşiğin dört katından fazladır. Bunun kullanıcıya görünen karşılığı şudur: model doğru yordamı buluyor, doğru kavramı adlandırıyor, ve yanına yürürlükten kalkmış bir kayıt yazıyor. Bu yanıt bir halüsinasyon değildir; kaynağa sadıktır. Kaynağın kendisi bayattır. Kaynağa bağlama, kaynağın tazeliğini garanti etmez.
Bayat parça payı ile yanlış yanıt payı da bire bir örtüşmüyor. Aralık on ikide parçaların 0,2562’si bayat ama yanıtların 0,3875’i yanlış. Fark, kavram isabetinin zaten 0,9250 olmasından ve bayat parçanın seçilen kavramı taşıyan parça olma olasılığının kendi başına bir dağılım taşımasından gelir. Bayatlık bir girdi ölçütüdür, yanlış yanıt bir çıktı ölçütü; ikisi aynı sayı değildir ve birbirinin yerine yazılamaz.
Yenilemenin Fiyatı
Gömme maliyeti iki politikada tamamen ayrı davranıyor. Tam yeniden dizinleme her yenilemede altı yüz doksan üç parçayı yeniden gömüyor: aralık birde 8316, aralık on ikide 693. Bu politikada aralık, maliyeti doğrudan bölen bir kaldıraçtır. Artımlı yenileme yalnız değişmiş belgelerin parçalarını gömüyor: aralık birde 881, yani tam dizinlemenin 9,4’te biri.
İkinci blok bu iki politikayı doğru iş başına okur ve ölçümün kendi kararlılığını sınar.
print("aralik yanlis yanit payi artimli/guncel tam/guncel 2. tohum guncel fark") for a in (1, 2, 4, 12): b, an, kv, gu, go, tm = kosum(a) g2 = kosum(a, TOHUM + 1)[3] n = gu * DONEM * len(SORGU) print("%6d %17.4f %15.2f %11.2f %17.4f %6.4f" % (a, 1 - gu, go / n, tm / n, g2, abs(gu - g2)))
aralik yanlis yanit payi artimli/guncel tam/guncel 2. tohum guncel fark
1 0.0750 1.98 18.73 0.9250 0.0000
2 0.1083 1.96 9.71 0.8917 0.0000
4 0.1792 1.88 5.28 0.8208 0.0000
12 0.3875 1.77 2.36 0.6125 0.0000
Artımlı sütun aralığın neden yanlış kaldıraç olduğunu gösteriyor. Aralık birden on ikiye çıkarıldığında gömülen parça 881’den 519’a iniyor, yani ancak yüzde kırk bir. Sebep, bir aralıkta birden çok kez yeniden yayımlanan belgenin yalnız bir kez gömülmesidir; aralık uzadıkça bu birleşme artar ama toplam değişen belge sayısı değişmez. Güncel yanıt başına okunduğunda kazanç daha da eriyor: 1,98’den 1,77’ye, yani yüzde on bir. Aynı kararın bedeli güncel yanıt payında 0,3125’tir. Artımlı yenilemede aralık uzatmak, neredeyse hiçbir şey karşılığında dörtte bir doğruluk satmaktır.
Tam dizinleme sütununda tablo tersine görünüyor: güncel yanıt başına 18,73’ten 2,36’ya. Bu satır aralığı uzatmayı haklı çıkarmaz, tam yeniden dizinlemeyi bırakmayı haklı çıkarır. Aralık biri artımlı politikayla kurmak, aralık on ikiyi tam dizinlemeyle kurmaktan hem ucuzdur (881’e karşı 693, aynı büyüklük sınıfı) hem de 0,3125 daha doğrudur.
Son iki sütun ölçümün kendi kararlılığıdır. İkinci tohumla koşulduğunda güncel yanıt payı dört satırda da birebir aynı çıkıyor, fark 0,0000. Bu, ilk dersin bulgusunun sürmesidir: kaynağı verilmiş bir çağrının çıktısı tohuma bağlı kalmıyor. Tablodaki farkların hepsi bu yüzden eşiğin çok üstündedir ve ölçülmüştür.
Özet
- Dizin bir anlık görüntüdür; kaynak değiştiğinde dizin değişmez ve arada geçen sürede doğru parçayı bayat içerikle servis eder.
- Yenileme aralığı birden on ikiye çıkarken bayat parça payı 0,0000’dan 0,2562’ye, yanlış yanıt payı 0,0750’den 0,3875’e çıkıyor.
- Erişim sütunu bu bozulmanın hiçbirini göstermiyor: anma altı aralıkta da 0,9500, kavram isabeti 0,9250. Kaynağa bağlama, kaynağın tazeliğini garanti etmez.
- Bayat parça payı bir girdi ölçütü, yanlış yanıt payı bir çıktı ölçütüdür; 0,2562 ile 0,3875 aynı şeyin iki adı değildir.
- Tam yeniden dizinleme aralık birde 8316 parça gömüyor, artımlı yenileme 881; aralık uzatmak artımlı politikada gömülen parçayı yalnız yüzde kırk bir azaltıyor.
- Güncel yanıt başına gömülen parça artımlı politikada 1,98’den 1,77’ye iniyor: yüzde on birlik kazanç karşılığında 0,3125 doğruluk satılıyor.
Sonraki Adım
Dört derste hat girdi tarafından kuruldu: kaynak hazırlandı, parçalandı, gömüldü, dizin yenilendi. Bu dört kararın hepsi belgenin tarafındaydı. Hattın öbür ucundaki metin, yani abonenin yazdığı sorgu, dört derste de olduğu gibi kullanıldı: kısa, eksik, kaydın dilinden başka bir dilde. Oysa erişimin bulduğu şeyi belirleyen iki metinden biri odur. Sorgunun genişletilmesi, yeniden yazılması ya da bir model çağrısıyla kaydın diline çevrilmesi anmayı yükseltebilir, ve o çağrının kendisi hattın bedeline eklenir. Sonraki ders sorguyu ele alır ve dönüştürmenin kattığı anmayı eklediği çağrıyla birlikte ölçer.
İlerlemeni kaydetmek ve not almak için Giriş yap
Notlarım
Not almak için giriş yapmalısın.