İçeriğe geç
academia.sh

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.

Aramak için yazmaya başlayın.

↑↓ Esc gezin · aç · kapat