İçeriğe geç
academia.sh

Ders 11 / 16

Sorgu Dönüştürme

Kullanıcının yazdığı sorgunun dizine gitmeden önce tek bir model çağrısıyla belge diline çevrilmesi ve bu adımın kazandırdığı ile kaybettirdiğinin ayrı ayrı sayılması: kırk sorguluk kurgu kümede kısa yazımın tabanı 0,3750 anma ve 0,2000 üretim iken genişletme ikisini 0,7500 ve 0,7000'e çıkarıyor, yani dizin dilinde yazılmış sorgunun bıraktığı yere geliyor. Aynı düzenek uzun yazımda tabanı 0,5500'den 0,3500'e, yeniden yazma ise 0,2500'e düşürüyor, çünkü dönüştürücünün doğru kavramı bulma payı 0,9500'den 0,3500'e iniyor. Bedel her iki kümede de sorgu başına bir çağrı ve dört yüzden iki bin üç yüz altmışa kadar ek belirteçtir; iki koşum farkı anmada 0,0500, üretimde 0,1000 ölçüldü.

İçindekiler

Önceki dört ders hattın belge tarafını kurdu: dağarcık hazırlandı, parçalara bölündü, dizinlendi ve yenilendi. Dördünde de sessiz kalan bir varsayım vardı: sorgu, kullanıcının yazdığı biçimiyle dizine gider.

Abone “hangi dilim” yazar, dağarcıkta “kademe esigi” geçer. Boşluğu kapatmanın bir yolu, sorguyu dizine göndermeden önce bir modele verip belge diline çevirtmektir; bedeli sorgu başına bir çağrıdır. Dönüştürme tek adımlıdır; sonucu görüp yeniden sorgulamak M28/K05’in konusudur.

  • EH41. Kod bir benzeticidir; gerçek bir gömme ya da model uç noktası çağrılmaz. Dağarcık, kavramlar, sorgular ve kullanıcı yazımları kurgudur, tohum 20260218.
  • EH42. Hedef iki parçalıdır. Sorgunun hedefi hem bir kavram hem bir kayıt türüdür; parça ancak ikisini birden taşıyorsa ilgilidir. Anma@k ilk k içinde ilgili parça bulunan sorgu payı, kesinlik@k ilk k’nın ilgili olan payıdır.
  • EH43. Hat, gommeler/06’da ölçülen karma aramayı kullanır: açı benzerliğinin yanına belirteç örtüşmesi eklenir. Yordamı tekrarlanmaz, ağırlık sabittir. Bu dersin tabanı dönüştürmesiz erişimdir; erişimsiz çağrının tabanı erisim-hatti/01’de kuruldu.
  • EH44. Üretim benzeticisi bağlamdaki parçalardan birini seçer ve kodunu alıntılar; parçanın yeri ağırlığı değiştirir. O ağırlık erisim-hatti/07’nin konusudur, burada sabittir.
  • EH45. Aynı kırk sorgunun iki yazımı ölçülür: kısa yazım abonenin yazdığı kısaltılmış biçim, uzun yazım aynı sorunun bağlam cümleleriyle uzatılmışı. Hedef ikisinde de aynıdır.
  • EH46. Dönüştürme hız sınırına takılırsa hat ham sorguya döner; başarısız çağrının belirteci yine sayılır.

Hat ve Hedef

Hat parça düzeyinde çalışır. Aşağıdaki blok dağarcığı, gömme benzeticisini, karma getirmeyi ve üretim benzeticisini kurar; sonra sorgu dizinin tanıdığı biçimde yazıldığında hattın nerede durduğunu basar: dönüştürmenin ulaşabileceği üst sınır.

# BENZETICI -- KURGUDUR. Gercek bir gomme ya da model uc noktasi cagrilmaz; dagarcik,
# kavramlar ve sorgular kurgudur, tohum 20260218.
import math
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})


def metin(d):
    return d["baslik"] + " " + " ".join(d["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      # alan disi gomme sorgu dilini tanimaz
    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"]})

# ---- hat: parcalar, karma getirme, hedef tanimi ve uretim
PARCA = [{"kod": d["kod"], "ana": d["ana"], "metin": p} for d in BELGE for p in d["par"]]
for p in PARCA:
    p["vek"], p["bel"] = gom(p["metin"]), set(belirtecle(p["metin"]))
for s in SORGU:
    s["kayit"] = s["metin"].split()[-1]


def getir(q, k=5, w=0.5):
    qv, qb = gom(q), set(belirtecle(q))
    s = sorted(((aci(qv, p["vek"]) + w * len(qb & p["bel"]) / len(qb | p["bel"]), i)
                for i, p in enumerate(PARCA)), key=lambda t: (-t[0], t[1]))
    return [PARCA[i] for _, i in s[:k]]


def ilgili(s, p):
    return KAVRAM[s["kavram"]][1] in p["metin"] and s["kayit"] in p["bel"]


def izno(m):
    h = 2166136261
    for c in m:
        h = ((h ^ ord(c)) * 16777619) & M32
    return h


PENCERE = 240
SAYAC = [0]
YON_Y = "Asagidaki parcalara bakarak yanitla ve kullandigin parcanin kodunu yaz . "


def yanitla(sorgu, parcalar, tohum=TOHUM, sicaklik=0.12):
    """KURGU uretim: baglamdan bir parca secilir, parcanin YERI agirligi degistirir."""
    SAYAC[0] += 1
    istem = YON_Y + " ".join(f"[{p['kod']}] {p['metin']} ." for p in parcalar) + " Soru: " + sorgu
    bel = belirtecle(istem)
    if len(bel) > PENCERE:
        return {"durum": "baglam_asimi", "giris": len(bel), "cikis": 0, "parca": None}
    r, qb, n = uretec(tohum ^ izno(istem)), set(belirtecle(sorgu)), len(parcalar)
    p = [(1.0 if i == 0 else 0.8 if i == n - 1 else 0.45) * (0.3 + len(qb & x["bel"]) / len(qb))
         for i, x in enumerate(parcalar)]
    w = [math.exp(a / sicaklik) for a in p]
    se = parcalar[ayrik(r(), [a / sum(w) for a in w])]
    return {"durum": "tamam", "giris": len(bel), "parca": se,
            "cikis": len(belirtecle(f"{se['kod']} : {se['metin']}"))}


a = u = 0
for s in SORGU:
    g = getir(s["metin"], 5)
    a += any(ilgili(s, p) for p in g)
    u += ilgili(s, yanitla(s["metin"], g)["parca"])
print("dagarcik %d belge %d parca ; ortalama parca %.1f belirtec ; ornek sorgu %r"
      % (len(BELGE), len(PARCA), sum(len(p["bel"]) for p in PARCA) / len(PARCA),
         SORGU[0]["metin"]))
print("hedef parca kumesi ortalama %.1f parca"
      % (sum(len([p for p in PARCA if ilgili(s, p)]) for s in SORGU) / 40))
print("dizin dilinde yazilmis sorgu  k=5  anma %.4f  uretim %.4f" % (a / 40, u / 40))
dagarcik 200 belge 693 parca ; ortalama parca 15.3 belirtec ; ornek sorgu 'nasil kaydediliyor form'
hedef parca kumesi ortalama 8.9 parca
dizin dilinde yazilmis sorgu  k=5  anma 0.8000  uretim 0.7000

Hedef kümesi ortalama 8,9 parçadır, altı yüz doksan üçün yüzde biraz üstü. Sorgu dizin dilinde yazıldığında ilk beş parça bu kümeden birini 0,8000 payla getiriyor, üretim bunun 0,7000’ini yanıta çeviriyor.

İki Yazım ve Dönüştürücü

Abone bu cümleleri yazmaz. “nasil kaydediliyor form” bir dizin sorgusudur; abone “kaydediliyor mu form” yazar ya da derdini uzun uzun anlatır. Aşağıdaki blok aynı kırk hedefin iki yazımını kurar ve üç kurulumu ikisinde de koşturur: taban (ham sorgu), genişletme (üzerine belge dilindeki terim eklenir) ve yeniden yazma (ham sorgu atılır, yerine belge dilinde bir cümle konur).

# KURGU: kullanicinin yazdigi kisa bicim -- dizinin tanidigi yuzeyi tasimaz
KISA = {"basamak": "hangi dilim", "birim": "metrekup ucreti", "abonetip": "mesken mi isyeri",
        "gecis": "plan degisimi", "arizakod": "hata kodu", "sizinti": "kacagi olabilir",
        "basinc": "akis zayif", "ekip": "gorevli gelmedi", "endeks": "sayac rakami",
        "okuma": "kaydediliyor mu", "degisim": "cihaz yenilendi", "dogrula": "yanlis girilmis",
        "planli": "onceden duyurulan", "duyuru": "nereden bakarim", "sure": "kac saat surer",
        "geridonus": "tekrar gelir mi", "periyot": "duzenli bakim", "vana": "musluk kapatma",
        "filtre": "temizleme filtresi", "kalib": "olcum kalibrasyonu"}
ONEK = ["gecen hafta", "birkac gundur", "sabahtan beri", "dun aksam"]
BAG = ["bir de sunu soracaktim", "ayrica ilgili birime yazdim", "bu arada merak ettim",
       "daha once de aramistim"]
KISASORGU, UZUNSORGU = [], []
for i, s in enumerate(SORGU):
    r = uretec(TOHUM + 31337 * i)
    y, o2 = ANAHTAR[int(r() * 20)], ORTAK[int(r() * 7)]
    z = ANAHTAR[int(r() * 20)]
    KISASORGU.append(dict(s, metin=f"{KISA[s['kavram']]} {s['kayit']}"))
    UZUNSORGU.append(dict(s, metin=f"{ONEK[int(r() * 4)]} {KAVRAM[y][2]} {o2} "
                                   f"{BAG[int(r() * 4)]} {s['metin']} {KAVRAM[z][2]}"))

SORGU_IZ = {}                       # sorgu dili -> kavram
for k in ANAHTAR:
    for t in belirtecle(KAVRAM[k][2]):
        if len(t) > 3:
            SORGU_IZ.setdefault(t, k)
YON_D = "Sorguyu belge diline cevir . Sorgu: "


def donustur(q, kip, tohum=TOHUM, sicaklik=0.5):
    """KURGU donusturucu: tek adimli bir model cagrisi, dongu ve planlama yok."""
    SAYAC[0] += 1
    bel = belirtecle(YON_D + q)
    if SAYAC[0] % 37 == 0:                       # hiz siniri: ham sorgu
        return {"durum": "hiz_siniri", "giris": len(bel), "cikis": 0, "metin": q, "kavram": None}
    r, p = uretec(tohum ^ izno(q)), {}
    for t in bel:
        if t in SORGU_IZ:
            p[SORGU_IZ[t]] = p.get(SORGU_IZ[t], 0.0) + 1.0
    if not p:
        return {"durum": "bos", "giris": len(bel), "cikis": 0, "metin": q, "kavram": None}
    a = sorted(p)
    w = [math.exp(p[x] / sicaklik) for x in a]
    k = a[ayrik(r(), [x / sum(w) for x in w])]
    o = next((t for t in bel if t in ORTAK), "")
    y = f"{KAVRAM[k][1]} icin {o} tutulur" if kip == "yeniden yazma" else f"{q} {KAVRAM[k][1]}"
    return {"durum": "tamam", "giris": len(bel), "cikis": len(belirtecle(y)),
            "metin": y, "kavram": k}


def olc(kume, kip, tohum=TOHUM, k=5):
    SAYAC[0] = 0
    an = ur = ca = bt = ds = dk = 0
    for s in kume:
        q = s["metin"]
        if kip != "taban":
            d = donustur(q, kip, tohum)
            q, ca, bt = d["metin"], ca + 1, bt + d["giris"] + d["cikis"]
            ds, dk = ds + (d["durum"] != "tamam"), dk + (d["kavram"] == s["kavram"])
        g = getir(q, k)
        an += any(ilgili(s, p) for p in g)
        y = yanitla(s["metin"], g, tohum)
        ca, bt = ca + 1, bt + y["giris"] + y["cikis"]
        ur += y["parca"] is not None and ilgili(s, y["parca"])
    return an / 40, ur / 40, ca, bt, ds, dk / 40


print("ortalama sorgu: kisa %.1f  uzun %.1f belirtec"
      % (sum(len(belirtecle(s["metin"])) for s in KISASORGU) / 40,
         sum(len(belirtecle(s["metin"])) for s in UZUNSORGU) / 40))
print("sorgu kurulum        anma@5  uretim  cagri  belirtec  dogru kavram  basarisiz")
fark = [0.0, 0.0]
for ad, kume in (("kisa ", KISASORGU), ("uzun ", UZUNSORGU)):
    for kip in ("taban", "genisletme", "yeniden yazma"):
        a, u, c, b, ds, dk = olc(kume, kip)
        a2, u2 = olc(kume, kip, TOHUM + 1)[:2]
        fark = [max(fark[0], abs(a - a2)), max(fark[1], abs(u - u2))]
        print("%s %-14s %.4f  %.4f  %5d  %8d  %12s  %9d"
              % (ad, kip, a, u, c, b, "-" if kip == "taban" else "%.4f" % dk, ds))
print("iki kosum farki (tohum 20260219): anma en cok %.4f  uretim en cok %.4f"
      % (fark[0], fark[1]))
ortalama sorgu: kisa 4.5  uzun 21.7 belirtec
sorgu kurulum        anma@5  uretim  cagri  belirtec  dogru kavram  basarisiz
kisa  taban          0.3750  0.2000     40      5366             -          0
kisa  genisletme     0.7500  0.7000     80      6356        0.9500          1
kisa  yeniden yazma  0.7500  0.7000     80      6335        0.9500          1
uzun  taban          0.5500  0.3250     40      6166             -          0
uzun  genisletme     0.3500  0.2000     80      8526        0.3500          1
uzun  yeniden yazma  0.2500  0.0500     80      7842        0.3500          1
iki kosum farki (tohum 20260219): anma en cok 0.0500  uretim en cok 0.1000

Kısa Yazımda Kazanç

Kısa yazımın tabanı 0,3750 anma ve 0,2000 üretimdir. Üst sınırla arasındaki fark hattın kusuru değil, sorgunun dizine değmemesidir: “hangi dilim” hiçbir parçada geçmez, geriye kayıt türünün örtüşmesi kalır.

Dönüştürme boşluğu kapatıyor. Genişletme anmayı 0,7500’e, üretimi 0,7000’e çıkarıyor; ikisi de iki koşum farkının (0,0500 ve 0,1000) üstünde ve üretim üst sınıra birebir yetişiyor. Sebep tabloda yazılı: dönüştürücü doğru kavramı 0,9500 payla buluyor.

Genişletme ile yeniden yazmanın burada aynı sonucu vermesi rastlantı değildir: ham sorguyu tutmanın bedeli de kazancı da yoktur, çünkü atılacak bir sinyal yoktur.

Uzun Yazımda Kayıp

Uzun yazımın tabanı 0,5500’dür, kısa yazımınkinden yüksektir: abone derdini uzatırken dizinin tanıdığı ifadeyi de yazıyor. Dönüştürme tabanı düşürüyor — genişletmeyle 0,3500, yeniden yazmayla 0,2500 — ve ikisi de iki koşum farkının üstünde, ölçülmüş bir kayıptır.

Nedeni yine doğru kavram sütunundadır: isabet 0,3500’e iniyor. Uzun sorguda üç kavram yüzeyi ve iki kayıt türü var; tek adımlı bir çağrı hangisinin asıl soru olduğunu seçmek zorunda ve çoğu kez yanılıyor. Yanıldığında genişletme yanlış bir terim ekler ama ham sorgu yerinde kalır; yeniden yazma doğru olan tek şeyi, abonenin yazdığı ifadeyi siler ve üretim 0,0500’e iniyor. Kursun ikinci iddiasının bu derse düşen örneği budur: eklenen düzenek işi kötüleştirdi.

Dönüştürmenin Faturası

Çağrı sorgu başına birden ikiye, kırktan seksene çıkıyor. Belirteç kısa yazımda 5366’dan 6356’ya, uzun yazımda 6166’dan 8526’ya gidiyor; uzun sorguyu bir de modele okutmak hattın en pahalı satırıdır ve kırk çağrının biri hız sınırına takılıyor. Gecikme sınıf olarak sayılır: hat tek çağrılık bir adımdan iki aşamalı bir zincire dönüşüyor. Sorgu başına yirmi beş ek belirteç anmayı 0,3750’den 0,7500’e çıkarırken, elli dokuz ek belirteç onu 0,5500’den 0,3500’e indiriyor.

Özet

  • Sorgunun hedefi hem kavram hem kayıt türüdür; ilk beşte ikisini taşıyan parça bulunma payı erişim, o parçanın yanıta dönme payı üretim ölçüsüdür.
  • Kullanıcının yazdığı kısa biçim dizine değmediği için taban 0,3750 / 0,2000’dir; dizin dilindeki aynı sorgu 0,8000 / 0,7000 veriyor.
  • Genişletme kısa yazımda anmayı 0,7500’e, üretimi 0,7000’e çıkarıyor; doğru kavramı bulma payı 0,9500’dür.
  • Uzun yazımda aynı düzenek tabanı 0,5500’den 0,3500’e, yeniden yazma 0,2500’e düşürüyor; doğru kavram payı 0,3500’e iner ve yeniden yazma abonenin yazdığı ifadeyi de siler.
  • Bedel sorgu başına bir çağrı ve 990 ile 2360 arası ek belirteçtir; hat zincire dönüşür.

Sonraki Adım

Bu dersin ölçümleri ilk beş parçayı birlikte sayıyor: içinde ilgili bir parça varsa anma yazılıyor, sıra sorulmuyor. Oysa kesinlik@5 ilk beşin çoğunun ilgisiz olduğunu söylüyor. Sonraki ders getirmeyi ikiye ayırır: geniş bir aday kümesi toplayan ucuz bir aşama ve her adayı sorguyla birlikte okuyan pahalı bir aşama.

İ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