İçeriğe geç
academia.sh

Ders 05 / 22

Biçim ve Uzunluk Denetimi

Açık bir talebin yanıtı hâlâ serbest metindir ve bir program onu okuyamaz. Aynı 120 kurgu destek talebinde üç alanlı bir kayıt isteniyor: serbest yanıtta katı alan ayrıştırıcısının okuduğu oran 0,0000, biçim bildirimi eklendiğinde 0,9750 oluyor ve etiket isabeti 0,3083'ten 0,6833'e çıkıyor. Bedel giriş belirtecinde 6140'tan 8780'e çıkış, çıkış belirtecinde 1392'den 2026'ya artıştır. En büyük çıktı uzunluğu 24'ten 10'a indirildiğinde çıkış belirteci 2026'dan 1170'e iniyor ama ayrıştırılabilir oran 0,9750'den 0,0000'a düşüyor; ara değerlerde eğri kesilen yanıt sayısına birebir bağlı kalıyor.

İçindekiler

Önceki ders belirsiz bir talebin kaç ayrı biçimde yanıtlandığını saydı ve talebi ölçülebilir kılmanın bu dağılımı ne kadar daralttığını gösterdi. Talep artık açıktır: hangi etiket kümesinden seçileceği istemde yazılıdır, ne istendiği tek cümlede durur. Yine de bir karar hâlâ modele bırakılmış durumdadır. Model ne söyleyeceğini biliyor, ama bunu hangi biçimde yazacağını bilmiyor.

Bu ayrımın bedeli, yanıtı kimin okuyacağına bağlıdır. Bir insan “kaydınız alındı, konuyu inceleyip dönüş yapacağız” cümlesini sorunsuz okur. Aynı cümleyi bir kayıt alanına yazacak program okuyamaz: içinde ne etiket alanı vardır, ne arıza kodu, ne de ayrılmış bir gerekçe. Bu ders yanıtın biçimini bir tasarım kararı olarak ele alır ve iki şeyi ölçer: biçim bildiriminin makinece ayrıştırılabilirliğe kattığı fark, ve uzunluk sınırının aynı ölçüden geri aldığı pay.

  • IT41. Model bir benzeticidir; gerçek bir uç nokta çağrılmaz. Standart kitaplıkla yazılmıştır, tohumu 20260218’dir ve aynı istem aynı tohumda aynı yanıtı verir.
  • IT42. Destek talepleri kurgudur: beş konuda 120 kısa Türkçe kayıt, bir bölümüne eklenmiş yanıltıcı bir cümleyle.
  • IT43. Görev üç alanlı bir kayıt ister: etiket, arıza kodu ve kısa gerekçe. Arıza kodları da kurgudur.
  • IT44. İki ayrıştırıcı kullanılır. Katı alan ayrıştırıcısı üç alanın da tam ve tutarlı olmasını arar; gevşek okuma yanıtın herhangi bir yerinde bir etiket sözcüğü arar.
  • IT45. Üç istemde de etiket kümesi aynıdır ve talep aynı derecede açıktır. Değişen tek şey biçim bildirimidir; uzunluk sınırı ayrıca ölçülür.
  • IT46. Uzunluk sınırı benzeticinin en büyük çıktı uzunluğudur. Sınır aşıldığında durdurma koşulu devreye girer ve yanıt ortasından kesilir.
  • IT47. Bedel belirteçle yazılır: giriş belirteci, çıkış belirteci ve çağrı sayısı.

Serbest Yanıt, Programın Okuyamadığı Yanıttır

İlk blok benzeticiyi kurar, üç alanlı kaydı tanımlar ve iki ayrıştırıcıyı yazar. Üç istem yan yana koşturulur: biçim bildirimi olmayan, biçim bildirimi olan, ve biçim bildirimi olup çıktı uzunluğu on iki belirteçle sınırlanan.

# BENZETICI -- KURGUDUR. Bu kod gercek bir model uc noktasi cagirmaz; standart
# kitaplikla yazilmis bir dil modeli benzeticisidir. Talepler de kurgudur.
import math

TOHUM, M32 = 20260218, 0xFFFFFFFF
PENCERE, EN_UZUN = 240, 24          # baglam penceresi ve en buyuk cikti, belirtec


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):                  # KURGU belirtecleyici: parca en cok bes damga
    b = []
    for s in m.lower().replace(",", " , ").split():
        while len(s) > 5:
            b.append(s[:5])
            s = s[5:]
        b.append(s)
    return b


def izno(m):                        # istemin icerigine bagli, kosumdan bagimsiz iz
    h = 2166136261
    for c in m:
        h = ((h ^ ord(c)) * 16777619) & M32
    return h


KONU = ["fatura", "ariza", "sayac", "tarife", "kesinti"]
KOD = {"fatura": "ft-21", "ariza": "ar-14", "sayac": "sy-32", "tarife": "tr-05",
       "kesinti": "ks-40", "odeme": "od-11", "sikayet": "sk-09", "bilgi": "bg-02",
       "genel": "gn-00"}
KALIP = {"fatura": ["bu ayki fatura tutari gecen aya gore cok yuksek geldi",
                    "faturami odedim ama sistemde borc gorunuyor",
                    "fatura ayrintisini nereden gorebilirim"],
         "ariza": ["evde su akmiyor bir ariza var galiba",
                   "baglanti bozuk oldu ve hic calismiyor",
                   "ariza kaydi actim ama ekip gelmedi"],
         "sayac": ["sayac okumasi yanlis girilmis endeks tutmuyor",
                   "sayac degisimi icin randevu istiyorum",
                   "sayac uzerindeki endeks ile fatura ayni degil"],
         "tarife": ["hangi tarife basamagindayim ogrenmek istiyorum",
                    "tarife degisikligi icin ne yapmam gerekiyor",
                    "birim ucret abone tipine gore degisiyor mu"],
         "kesinti": ["mahallede kesinti var ne zaman gelecek",
                     "planli kesinti duyurusu nereden takip edilir",
                     "aksamdan beri kesinti yasiyoruz"]}
EK = ["ayrica gecen ay da ayni sorun olmustu", "bu konuda memnun degilim",
      "acil bilgi almam gerekiyor", "kayit numaram elimde yok"]

TALEP = []
for i in range(120):
    r = uretec(TOHUM + i)
    k = KONU[ayrik(r(), [0.24, 0.22, 0.18, 0.20, 0.16])]
    m = KALIP[k][int(r() * 3)]
    if r() < 0.34:
        m += " " + EK[int(r() * 4)]
    TALEP.append({"no": 4001 + i, "metin": m, "konu": k})

KAVRAM = KONU + ["odeme", "sikayet", "bilgi", "genel"]
IZ = {"fatur": "fatura", "tutar": "fatura", "ayrin": "fatura", "ariza": "ariza",
      "bozuk": "ariza", "calis": "ariza", "akmiy": "ariza", "sayac": "sayac",
      "endek": "sayac", "okuma": "sayac", "tarif": "tarife", "birim": "tarife",
      "abone": "tarife", "basam": "tarife", "kesin": "kesinti", "duyur": "kesinti",
      "mahal": "kesinti", "borc": "odeme", "odedi": "odeme", "ucret": "odeme",
      "memnu": "sikayet", "sorun": "sikayet", "acil": "sikayet", "bilgi": "bilgi",
      "ogren": "bilgi", "nered": "bilgi"}
TUZAK = {"degis": "tarife", "kayit": "ariza", "yukse": "tarife", "gorun": "fatura",
         "ekip": "kesinti", "takip": "tarife", "giril": "fatura"}   # yaniltici baglar
SERBEST = ["talebiniz {k} konusuyla ilgili gorunuyor",
           "bu kayit {k} basligina girer , ilgili ekibe yonlendirildi",
           "kaydiniz alindi , konuyu inceleyip donus yapacagiz"]
SAYAC = [0]


def cagir(istem, ozet, tohum=TOHUM, sicaklik=0.6, en_uzun=EN_UZUN):
    SAYAC[0] += 1
    bel = belirtecle(istem)
    bos = {"giris": len(bel), "cikis": 0, "yanit": "", "kesik": 0}
    if len(bel) > PENCERE:
        return dict(bos, durum="baglam_asimi")
    if SAYAC[0] % 37 == 0:
        return dict(bos, durum="hiz_siniri")
    r = uretec(tohum ^ izno(istem))
    if len(bel) > 90 and r() < 0.04:
        return dict(bos, durum="zaman_asimi")
    aday = [k for k in KAVRAM if k[:5] in bel]      # istemde adi gecen kavramlar
    if len(aday) < 3:
        aday = KAVRAM
    p = {k: 0.15 for k in aday}
    for t in bel:
        for tablo, w in ((IZ, 1.0), (TUZAK, 1.3)):
            if tablo.get(t) in p:
                p[tablo[t]] += w
    if sicaklik <= 0.0:
        k = max(sorted(p), key=lambda a: p[a])       # en olasi secim
    else:
        e = [math.exp(p[a] / sicaklik) for a in sorted(p)]
        k = sorted(p)[ayrik(r(), [v / sum(e) for v in e])]
    if "bicim" in bel:                               # istemde bicim bildirimi var
        y = f"etiket : {k} ; kod : {KOD[k]} ; gerekce : {ozet}"
    else:
        y = SERBEST[ayrik(r(), [0.42, 0.26, 0.32])].format(k=k)
    cb, kesik = belirtecle(y), 0
    if len(cb) > en_uzun:                            # durdurma kosulu
        cb, kesik, y = cb[:en_uzun], 1, " ".join(cb[:en_uzun])
    return {"durum": "tamam", "giris": len(bel), "cikis": len(cb),
            "yanit": y, "kesik": kesik}


def ayristir(y):                    # KATI alan ayristirici: uc alan da tam olmali
    a = {}
    for parca in y.split(";"):
        ad = parca.split(":")
        if len(ad) == 2:
            a[ad[0].strip()] = ad[1].strip()
    tam = a.get("etiket") in KONU and a.get("kod") == KOD.get(a.get("etiket"))
    return a["etiket"] if tam and a.get("gerekce") else None


def oku(y):                         # GEVSEK okuma: yanittaki ilk etiket sozcugu
    for s in y.lower().split():
        if s in KONU:
            return s
    return None


TABAN = ("Talebi su etiketlerden birine ata : fatura , ariza , sayac , tarife , "
         "kesinti . Ilgili ariza kodunu ve kisa gerekcesini de bildir . Talep : ")
BICIM = "Yanitin bicimi : etiket : <deger> ; kod : <deger> ; gerekce : <deger> . "


def olc(bicim, en_uzun=EN_UZUN, tohum=TOHUM):
    SAYAC[0] = 0
    d = {"kati": 0, "gevsek": 0, "isabet": 0, "giris": 0, "cikis": 0, "kesik": 0}
    for x in TALEP:
        s = cagir((BICIM if bicim else "") + TABAN + x["metin"],
                  " ".join(x["metin"].split()[:3]), tohum=tohum, en_uzun=en_uzun)
        for a in ("giris", "cikis", "kesik"):
            d[a] += s[a]
        d["kati"] += ayristir(s["yanit"]) is not None
        d["gevsek"] += oku(s["yanit"]) is not None
        d["isabet"] += oku(s["yanit"]) == x["konu"]
    for a in ("kati", "gevsek", "isabet"):
        d[a] /= len(TALEP)
    d["cagri"] = SAYAC[0]
    return d


A, B, C = olc(False), olc(True), olc(True, en_uzun=12)
ornek = cagir(BICIM + TABAN + TALEP[3]["metin"], " ".join(TALEP[3]["metin"].split()[:3]))
print(f"KURGU: {len(TALEP)} destek talebi. bicimli yanit ornegi ({ornek['cikis']} belirtec)")
print(f"  {ornek['yanit']}")
print(f"\n{'olcu':<26}{'serbest':>10}{'bicim kisiti':>14}{'bicim + 12':>12}")
for ad, k, b in (("ayristirilabilir oran", "kati", "{:.4f}"),
                 ("etiketi okunan oran", "gevsek", "{:.4f}"),
                 ("etiket isabeti", "isabet", "{:.4f}"),
                 ("giris belirteci", "giris", "{:d}"),
                 ("cikis belirteci", "cikis", "{:d}"),
                 ("kesilen yanit", "kesik", "{:d}")):
    print(f"{ad:<26}{b.format(A[k]):>10}{b.format(B[k]):>14}{b.format(C[k]):>12}")
KURGU: 120 destek talebi. bicimli yanit ornegi (15 belirtec)
  etiket : ariza ; kod : ar-14 ; gerekce : ariza kaydi actim

olcu                         serbest  bicim kisiti  bicim + 12
ayristirilabilir oran         0.0000        0.9750      0.0000
etiketi okunan oran           0.4667        0.9750      0.4833
etiket isabeti                0.3083        0.6833      0.2667
giris belirteci                 6140          8780        8780
cikis belirteci                 1392          2026        1404
kesilen yanit                      0             0         117

İlk satır bu dersin asıl sayısıdır. Serbest yanıtta katı alan ayrıştırıcısının okuduğu kayıt sayısı sıfırdır: yüz yirmi yanıtın hiçbiri üç alanlı bir kayıt değildir. Talep açıktı, etiket kümesi istemde yazılıydı, arıza kodu ve gerekçe ayrıca istenmişti; buna rağmen ortaya çıkan şey bir cümledir. İkinci satır cümlelerin okunamaz olmadığını gösteriyor: yanıtların 0,4667 payında gevşek okuma bir etiket sözcüğü buluyor. Aradaki uçurum bu dersin konusudur. Serbest yanıt insanın okuduğu, programın okuyamadığı bir çıktıdır.

Biçim bildirimi eklendiğinde ayrıştırılabilir oran 0,9750 oluyor. Kalan pay modelin biçimi bozmasından değil, hız sınırına takılan üç çağrıdan geliyor; benzetici her otuz yedinci çağrıda boş yanıt döndürür ve boş yanıttan kayıt okunmaz. Etiket isabeti aynı anda 0,3083’ten 0,6833’e çıkıyor, ama bu artışın kaynağı modelin daha iyi karar vermesi değildir. Serbest yanıtın üçte biri hiçbir etiket taşımıyordu ve etiketi okunamayan her kayıt yanlış sayılıyordu. Biçim bildirimi kararı düzeltmiyor, kararı görünür kılıyor.

Bedel iki yönde birden hareket ediyor. Giriş belirteci 6140’tan 8780’e çıkıyor: biçim bildirimi on altı belirteçtir ve yüz yirmi isteğin her birinin başına eklenir. Çıkış belirteci de 1392’den 2026’ya çıkıyor, çünkü üç alanlı kayıt serbest cümleden uzundur. Buradaki dersin kendisi budur: biçim kısıtı, bu görevde her iki belirteç kalemini de büyüten bir karardır. Üçüncü sütun ise bu büyümeyi geri almanın maliyetini gösteriyor. Çıktı uzunluğu on iki belirteçle sınırlandığında çıkış belirteci 1404’e iniyor, ama ayrıştırılabilir oran 0,0000 oluyor: kesilen yanıt sayısı 117’dir ve kesik bir kayıt eksik kayıttır.

Uzunluk Sınırı Bir Eğim Değil, Bir Eşiktir

İkinci blok sınırı geniş bir aralıkta tarar ve kesilen yanıt sayısı ile ayrıştırılabilir oranın nasıl bağlandığını gösterir.

print("en uzun  kesilen  ayristirilabilir  etiket isabeti  cikis belirteci")
for n in (24, 20, 18, 16, 14, 12, 10):
    d = olc(True, en_uzun=n)
    print(f"{n:>7}  {d['kesik']:>7}  {d['kati']:>16.4f}  {d['isabet']:>14.4f}"
          f"  {d['cikis']:>15}")

kalan = {}
for x in TALEP:
    s = cagir(BICIM + TABAN + x["metin"], " ".join(x["metin"].split()[:3]), en_uzun=12)
    e = oku(s["yanit"])
    kalan[e] = kalan.get(e, 0) + 1
print(f"\nen uzun 12 , kesik yanitta okunabilen etiket: {sorted(k for k in kalan if k)}")
print(f"bes damgayi asan etiket: {[k for k in KONU if len(k) > 5]}")

B2, A2 = olc(True, tohum=TOHUM + 1), olc(False, tohum=TOHUM + 1)
print(f"\nbicim kisitinin katkisi : ayristirilabilir {B['kati'] - A['kati']:+.4f} ,"
      f" isabet {B['isabet'] - A['isabet']:+.4f}")
print(f"iki kosum farki         : ayristirilabilir {B2['kati'] - B['kati']:+.4f} ,"
      f" isabet {B2['isabet'] - B['isabet']:+.4f}")
print(f"serbest istem iki kosum : isabet {A['isabet']:.4f} / {A2['isabet']:.4f}")
en uzun  kesilen  ayristirilabilir  etiket isabeti  cikis belirteci
     24        0            0.9750          0.6833             2026
     20        0            0.9750          0.6833             2026
     18       30            0.7250          0.4417             1992
     16       78            0.3250          0.3500             1865
     14      117            0.0000          0.2917             1638
     12      117            0.0000          0.2667             1404
     10      117            0.0000          0.2667             1170

en uzun 12 , kesik yanitta okunabilen etiket: ['ariza', 'sayac']
bes damgayi asan etiket: ['fatura', 'tarife', 'kesinti']

bicim kisitinin katkisi : ayristirilabilir +0.9750 , isabet +0.3750
iki kosum farki         : ayristirilabilir +0.0000 , isabet +0.1167
serbest istem iki kosum : isabet 0.3083 / 0.5000

Çizelgenin ikinci ve üçüncü sütunu birbirine kilitlidir. Sınır yirmide iken kesilen yanıt yoktur ve oran 0,9750’dir; on sekizde otuz yanıt kesilir ve oran 0,7250’ye iner; on altıda yetmiş sekiz yanıt kesilir ve oran 0,3250 olur. Her satırda ayrıştırılabilir yanıt sayısı, kesilmemiş ve hata döndürmemiş yanıt sayısına birebir eşittir. Tek bir kayıt için uzunluk sınırı bir eşiktir: ya kayıt tamdır ya da hiç yoktur, arası yoktur. Küme düzeyinde eğri yumuşak görünür, çünkü yanıt uzunlukları kayıttan kayda değişir; eğrinin eğimi modelin değil, gerekçe alanının uzunluk dağılımının özelliğidir.

Belirteç sütunu bu kararın cazibesini açıklıyor. Sınırı yirmi dörtten ona indirmek çıkış belirtecini 2026’dan 1170’e, yani kabaca yarıya düşürüyor. Tasarruf gerçektir ve peşindir; karşılığında elde kalan kayıt sayısı sıfırdır. Uzunluk sınırı bir maliyet ayarıdır ve doğru yeri, kaydın tam uzunluğunun hemen üstüdür; altına inen her belirteç kazancı, kaydın tamamını siler.

Kesik yanıtta hangi etiketin okunabildiği Türkçeye özgü bir ayrıntı gösteriyor. Sınır on ikide iken gevşek okuma yalnız ariza ve sayac etiketlerini buluyor; fatura, tarife ve kesinti hiç görünmüyor. Nedeni belirteçleyicidir: beş damgayı aşan sözcükler parçalara bölünür ve kesilmiş bir çıktı yeniden birleştirildiğinde bu parçalar ayrı sözcük olarak kalır. Aynı uzunluk sınırı, etiketin damga sayısına göre farklı davranıyor — sınır bir belirteç eşiğidir ama etkisi sözcüğün yazımına bağlıdır.

Son üç satır kursun kuralını uyguluyor. Biçim bildiriminin ayrıştırılabilirliğe kattığı fark +0,9750, aynı istemin iki koşumu arasındaki fark ise +0,0000. Ölçü koşumdan bağımsızdır ve kazanç tartışmasızdır. İsabet tarafı aynı derecede rahat değildir: kazanç +0,3750, iki koşum farkı +0,1167. Kazanç farkın üç katından büyük olduğu için ölçülmüş sayılır, ama aynı istemin iki koşumu arasında 0,1167’lik bir oynama varken 0,05’lik bir iyileştirme iddiası bu düzenekte ölçülmemiş bir tahmindir. İstem bir tasarım nesnesidir; ölçülmeden değiştirilen istem bir iyileştirme değil bir tahmindir.

Özet

  • Açık bir talep yanıtın biçimini belirlemez. Serbest yanıtta katı alan ayrıştırıcısının okuduğu kayıt oranı 0,0000, gevşek okumanın etiket bulduğu oran 0,4667: yanıt insan için okunabilir, program için okunamazdır.
  • Biçim bildirimi ayrıştırılabilir oranı 0,9750‘ye, etiket isabetini **0,3083’ten 0,6833’e** taşıyor. Kalan 0,0250 modelin değil, hız sınırına takılan üç çağrının payıdır.
  • Bedel çift yönlüdür: giriş belirteci 6140’tan 8780’e, çıkış belirteci 1392’den 2026’ya çıkıyor. Biçim kısıtı bu görevde iki belirteç kalemini de büyütür.
  • En büyük çıktı uzunluğu 24’ten 10’a indirilince çıkış belirteci 2026’dan 1170’e iniyor ve ayrıştırılabilir oran 0,0000 oluyor; her satırda ayrıştırılabilir yanıt sayısı, kesilmemiş ve hata döndürmemiş yanıt sayısına eşittir.
  • Biçim bildiriminin ayrıştırılabilirliğe kattığı +0,9750, iki koşum farkı +0,0000; isabete kattığı +0,3750, iki koşum farkı +0,1167. İkinci ölçü daha gürültülüdür ve bu düzeneğin ölçebileceği en küçük isabet farkını belirler.

Sonraki Adım

Bu derste isteme yazılan şey bir tarifti: alanların adı, sırası ve ayracı. Tarif yanıtın kabını belirledi ve kabı belirlemek isabeti dolaylı olarak yükseltti. Ama modelin hangi talebin hangi etikete gittiğine dair kararı hiç desteklenmedi; istemde bunun tek bir örneği bile yok. Sonraki ders tarif yerine örnek koyar: çözülmüş birkaç talep isteme yazılır ve isabetin nasıl değiştiği sayılır. Örnek sayısı sıfırdan sekize çıkarılır, her adımda isabet ve belirteç yan yana basılır, kazancın doyduğu nokta yazılır. Aynı ders bir de rahatsız edici bir şey gösterir: aynı örnekler farklı sırayla yazıldığında sayı değişir, yani örnek kümesi kadar örneklerin dizilişi de bir tasarım kararıdır.

İ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