İçeriğe geç
academia.sh

Ders 20 / 22

Çıktı Doğrulama

Şema doğrulaması ve iş kuralı denetiminin ayrı ayrı sayılması ve üzerine bir yeniden deneme döngüsü kurulması: 120 kurgu yanıtın 24'ü şemaya uymuyor, şemadan geçen 96 kaydın 24'ü iş kuralına takılıyor ve doğrulama yokken hatalı kayıt oranı 0,4000. İki denetim birlikte kabul oranını 0,6000'a indiriyor, bir yeniden deneme 26 kaydı kurtarıp 0,8167'ye çıkarıyor ve 48 ek çağrıya mal oluyor. İkinci deneme sekiz kayıt daha kurtarıyor ama kazancı 0,0666 ile iki koşum farkı 0,0667'nin altında kalıyor. Hatayı isteme yazan deneme 23 kayıt kurtarıyor ve 514 belirteç ekliyor.

İçindekiler

Önceki ders çıktının biçimini üç düzeyde ölçtü ve doğrulayıcıyı yalnız bir sayaç olarak kullandı: kaç yanıtın düştüğünü saydı, düşenleri attı. Kapanışında iki eksik yazılıydı. Birincisi, bir üretim hattında düşen kaydı atmak bir seçenek değildir. İkincisi, şemadan geçen bir kayıt da yanlış olabilir: önceki dersin biçim tarifi satırında şemadan geçen kayıtların on üçü, isteme yazılan numaranın yerine kayıtlı olmayan bir talep numarası taşıyordu ve doğrulayıcı bunu hiç görmedi.

Bu ders iki denetimi ayırır ve üzerine bir yeniden deneme döngüsü kurar. Girdi doğrulama, şema ve iş kuralı yordamı M16’nın API sözleşmesi kursunda ve M24’te ölçüldü; burada tekrarlanmaz. Eklenen tek şey üreticinin belirsiz olmasıdır: reddedilen bir kayıt yeniden istenebilir ve ikinci istek başka bir yanıt verebilir. Ölçülecek olan da budur — doğrulamanın yakaladığı, yeniden denemenin kurtardığı ve bunun kaç çağrıya mal olduğu.

  • CD25. Kod bir benzeticidir; gerçek bir uç nokta çağrılmaz. Talepler, alanlar ve kurallar kurgudur, tohum 20260218.
  • CD26. Başlangıç istemi önceki dersin biçim tarifi istemidir; şema dayatması bilerek kullanılmaz, çünkü bu ders hatalı çıktının ne yapıldığını ölçer.
  • CD27. İki denetim ayrıdır. Şema doğrulaması alanların varlığına ve değer kümelerine bakar. İş kuralı denetimi yalnız şemadan geçmiş kayıtlara uygulanır ve kurumun kurallarına bakar.
  • CD28. Üç iş kuralı kurgudur: yüksek öncelikli bir kayıt bilgilendirmeyle kapatılamaz, kesinti konulu bir kayıt tek başına kayıtla kapatılamaz, ve talep numarası kayıtlı talepler kümesinde olmalıdır. Üçünü de şema göremez.
  • CD29. Yeniden deneme aynı isteği yeni bir tohumla tekrar eder. Model belirsiz olduğu için ikinci yanıt başka çıkabilir; bu, düzeltmenin tek dayanağıdır.
  • CD30. Bir değişke, hatayı isteme yazar: reddedilen yanıtın hata adı isteme eklenir. Bu, giriş belirtecini artırır.
  • CD31. Sisteme giren hatalı kayıt ayrıca sayılır: doğrulama olmadığında kabul oranı 1,0000 görünür ama kaydın bir bölümü bozuktur.
  • CD32. Bedel ek çağrı sayısı ve toplam belirteç olarak yazılır; iki koşum farkı için ikinci koşum tohum 20260219 ile alınır.

Şemanın Göremediği Hata

Şema bir kaydın biçimini tanımlar: hangi alanlar var, değerler hangi kümeden. Bir kurumun kuralları ise kaydın anlamına bakar ve şemanın diliyle yazılamaz. Bu ders üç kurgu kural tanımlar ve üçünün de kusursuz biçimli kayıtlarda tetiklendiğini gösterir.

# BENZETICI -- KURGUDUR. Gercek bir model uc noktasi cagrilmaz. Sema dogrulamasi
# ve is kurali denetimi ders icinde yazilir; disaridan kitaplik kullanilmaz.
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


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):
    h = 2166136261
    for c in m:
        h = ((h ^ ord(c)) * 16777619) & M32
    return h


KONU = ["fatura", "ariza", "sayac", "tarife", "kesinti"]
ONCELIK, AKSIYON = ["dusuk", "orta", "yuksek"], ["kayit", "yonlendirme", "bilgi"]
SEMA = {"talep_no": "sayi", "konu": KONU, "oncelik": ONCELIK, "aksiyon": AKSIYON}
KALIP = [("bu ayki fatura tutari gecen aya gore cok yuksek geldi", "fatura"),
         ("faturami odedim ama sistemde borc gorunuyor", "fatura"),
         ("fatura ayrintisini nereden gorebilirim", "fatura"),
         ("evde su akmiyor bir ariza var galiba", "ariza"),
         ("baglanti bozuk oldu ve hic calismiyor", "ariza"),
         ("ariza kaydi actim ama ekip gelmedi", "ariza"),
         ("sayac okumasi yanlis girilmis endeks tutmuyor", "sayac"),
         ("sayac degisimi icin randevu istiyorum", "sayac"),
         ("sayac uzerindeki endeks ile fatura ayni degil", "sayac"),
         ("hangi tarife basamagindayim ogrenmek istiyorum", "tarife"),
         ("tarife degisikligi icin ne yapmam gerekiyor", "tarife"),
         ("birim ucret abone tipine gore degisiyor mu", "tarife"),
         ("mahallede kesinti var ne zaman gelecek", "kesinti"),
         ("planli kesinti duyurusu nereden takip edilir", "kesinti"),
         ("aksamdan beri kesinti yasiyoruz", "kesinti")]
TALEP = []
for i in range(120):                    # 120 KURGU destek talebi
    r = uretec(TOHUM + i)
    k = KONU[ayrik(r(), [0.24, 0.22, 0.18, 0.20, 0.16])]
    TALEP.append({"no": 4001 + i, "konu": k,
                  "metin": [x for x in KALIP if x[1] == k][int(r() * 3)][0]})

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"}
TUZAK = {"degis": "tarife", "kayit": "ariza", "yukse": "tarife", "gorun": "fatura",
         "ekip": "kesinti", "takip": "tarife", "giril": "fatura"}   # yaniltici baglar
SAYAC = [0]


def ayristir(metin):
    """Anahtar=deger cifti ayristirici. Ayrilamayan yanit icin None doner."""
    if "=" not in metin:
        return None
    kayit = {}
    for parca in metin.split(";"):
        if "=" not in parca:
            return None
        a, _, d = parca.partition("=")
        kayit[a.strip()] = d.strip()
    return kayit


def dogrula(kayit):
    """Sema dogrulama: eksik anahtar, fazladan anahtar, gecersiz deger."""
    if kayit is None:
        return ["ayristirilamadi"]
    hata = [f"eksik:{a}" for a in SEMA if a not in kayit]
    hata += [f"fazla:{a}" for a in kayit if a not in SEMA]
    for a, kural in SEMA.items():
        if a not in kayit:
            continue
        d = kayit[a]
        if kural == "sayi" and not d.isdigit():
            hata.append(f"sayi_degil:{a}")
        elif kural != "sayi" and d not in kural:
            hata.append(f"gecersiz:{a}")
    return hata


def cekilis(istem, tohum, tuz):
    """Her karar icin ayri tuzlanmis tek cekilis; kararlar birbirine baglanmaz."""
    return uretec((tohum + tuz) ^ izno(istem))()


def cagir(istem, talep, tohum=TOHUM):
    """Onceki dersin bicim tarifi istemi; yanitin bir payi tarife uymaz."""
    SAYAC[0] += 1
    bel = belirtecle(istem)
    p = {k: 0.15 for k in KONU}
    for t in belirtecle(talep["metin"]):    # konu yalniz talep metninden okunur
        for tablo, w in ((IZ, 1.0), (TUZAK, 1.3)):
            if tablo.get(t) in p:
                p[tablo[t]] += w
    k = max(sorted(p), key=lambda a: p[a])
    o = ONCELIK[ayrik(cekilis(istem, tohum, 11), [0.31, 0.44, 0.25])]
    a = AKSIYON[ayrik(cekilis(istem, tohum, 29), [0.46, 0.32, 0.22])]
    duz = f"talep_no={talep['no']} ; konu={k} ; oncelik={o} ; aksiyon={a}"
    egilim = 0.62 if "bicim" in bel else 0.0            # istemdeki bicim tarifi
    if "hatal" in bel:                                  # hatayi isteme yazan deneme
        egilim += 0.14
    if cekilis(istem, tohum, 53) < egilim:
        return duz
    bozuk = ayrik(cekilis(istem, tohum, 71),            # tarife uymayan yanit
                  [0.22, 0.20, 0.18, 0.16, 0.24])
    if bozuk == 0:
        return f"talebiniz {k} konusunda kaydedildi ve {a} adimi baslatildi"
    if bozuk == 1:
        return f"talep_no={talep['no']} ; konu={k} ; aksiyon={a}"
    if bozuk == 2:
        return f"talep_no={talep['no']} ; konu={k} ; oncelik=acil ; aksiyon={a}"
    if bozuk == 3:
        return f"talep_no=TL{talep['no']} ; konu={k} ; oncelik={o} ; aksiyon={a}"
    return f"talep_no={talep['no'] + 500} ; konu={k} ; oncelik={o} ; aksiyon={a}"


TARIF = ("Yaniti su bicimde yaz: talep_no=<sayi> ; konu=<fatura|ariza|sayac|"
         "tarife|kesinti> ; oncelik=<dusuk|orta|yuksek> ; aksiyon=<kayit|"
         "yonlendirme|bilgi> . ")


def istemi(onek, x):
    return onek + f"Talep {x['no']} : {x['metin']}"


KAYITLI = {t["no"] for t in TALEP}


def is_kurali(kayit):
    """Semadan gecen kaydin kurum kurallari. Sema bunlarin hicbirini goremez."""
    hata = []
    if kayit.get("oncelik") == "yuksek" and kayit.get("aksiyon") == "bilgi":
        hata.append("yuksek_oncelik_bilgi_ile_kapanamaz")
    if kayit.get("konu") == "kesinti" and kayit.get("aksiyon") == "kayit":
        hata.append("kesinti_kayitla_kapanamaz")
    if kayit.get("talep_no", "").isdigit() and int(kayit["talep_no"]) not in KAYITLI:
        hata.append("kayitli_olmayan_talep_no")
    return hata


sem, isk, gorulen = 0, 0, {}
for x in TALEP:
    y = cagir(istemi(TARIF, x), x)
    kayit = ayristir(y)
    h = dogrula(kayit)
    if h:
        sem += 1
        continue
    k = is_kurali(kayit)
    isk += bool(k)
    if k:
        gorulen.setdefault(k[0], y)
print(f"KURGU talep {len(TALEP)}: semaya takilan {sem}, is kuraline takilan {isk}")
for e, y in sorted(gorulen.items()):
    print(f"  {e}\n    {y}")
KURGU talep 120: semaya takilan 24, is kuraline takilan 24
  kayitli_olmayan_talep_no
    talep_no=4505 ; konu=sayac ; oncelik=orta ; aksiyon=kayit
  kesinti_kayitla_kapanamaz
    talep_no=4015 ; konu=kesinti ; oncelik=dusuk ; aksiyon=kayit
  yuksek_oncelik_bilgi_ile_kapanamaz
    talep_no=4022 ; konu=tarife ; oncelik=yuksek ; aksiyon=bilgi

İki sayı birbirine eşit ve bu eşitlik dersin çıkış noktasıdır: 24 yanıt şemaya uymuyor, şemadan geçen 96 yanıtın 24’ü iş kuralına takılıyor. Yani biçim denetimi hatanın ancak yarısını görüyor. Üç örneğin üçü de kusursuz biçimlidir; ayrıştırıcı ve doğrulayıcı hiçbirinde bir şey bulmaz. Birincisinde talep numarası istemde yazılı olmayan bir sayıdır, ikincisinde kesinti kaydı yanlış aksiyonla kapatılmıştır, üçüncüsünde yüksek öncelikli bir kayıt bilgilendirmeye bağlanmıştır.

Bu üç kural şemanın diline çevrilemez, çünkü hiçbiri tek bir alanın değeriyle ilgili değildir. İlk ikisi alanlar arası bir tutarlılıktır, üçüncüsü ise kaydın dış dünyayla tutarlılığıdır. Belirsiz bir üreticinin çıktısında bu iki sınıf ayrı ayrı sayılmadan doğrulama ölçülmüş sayılmaz.

Yeniden Denemenin Kurtardığı

Altı hat aynı 120 talepte koşturulur. İlk üçünde yeniden deneme yoktur ve yalnız denetimin neyi elediği ölçülür; son üçü reddedilen kaydı yeniden ister.

HAT = [("dogrulama yok", False, False, 0, False),
       ("yalniz sema", True, False, 0, False),
       ("sema + is kurali", True, True, 0, False),
       ("+ 1 yeniden deneme", True, True, 1, False),
       ("+ 2 yeniden deneme", True, True, 2, False),
       ("+ 1 deneme, hata istemde", True, True, 1, True)]


def denetle(kayit, semali, kurali):
    h = dogrula(kayit) if semali else []
    if not h and kurali and kayit is not None:
        h = is_kurali(kayit)
    return h


def hat(semali, kurali, deneme, hatayi_yaz, tohum=TOHUM):
    SAYAC[0] = 0
    ilk_sema = ilk_kural = kurtarilan = kabul = hatali = ek = bel = 0
    for x in TALEP:
        istem = istemi(TARIF, x)
        y = cagir(istem, x, tohum)
        bel += len(belirtecle(istem)) + len(belirtecle(y))
        kayit = ayristir(y)
        ilk_sema += bool(dogrula(kayit))
        ilk_kural += not dogrula(kayit) and bool(is_kurali(kayit))
        h = denetle(kayit, semali, kurali)
        for d in range(deneme):
            if not h:
                break
            ek += 1
            i2 = istem + f" Onceki yanit hatali: {h[0]} ." if hatayi_yaz else istem
            y = cagir(i2, x, tohum + 1 + d)
            bel += len(belirtecle(i2)) + len(belirtecle(y))
            kayit = ayristir(y)
            h = denetle(kayit, semali, kurali)
            kurtarilan += not h
        kabul += not h
        hatali += (not h) and bool(dogrula(kayit) or is_kurali(kayit))
    return (ilk_sema, ilk_kural, kurtarilan, kabul / 120, hatali / 120, ek, bel)


print("hat                       sema  kural  kurtarilan  kabul   hatali  ek cagri  belirtec")
for ad, s, k, d, w in HAT:
    a = hat(s, k, d, w)
    print(f"{ad:<25} {a[0]:>4}  {a[1]:>5}  {a[2]:>10}  {a[3]:>6.4f}  {a[4]:>6.4f}"
          f"  {a[5]:>8}  {a[6]:>8}")
b = hat(True, True, 1, False, TOHUM + 1)
print(f"ikinci kosum (+ 1 yeniden deneme): kabul {b[3]:.4f}, kurtarilan {b[2]}, "
      f"ek cagri {b[5]}")
hat                       sema  kural  kurtarilan  kabul   hatali  ek cagri  belirtec
dogrulama yok               24     24           0  1.0000  0.4000         0      7403
yalniz sema                 24     24           0  0.8000  0.2000         0      7403
sema + is kurali            24     24           0  0.6000  0.0000         0      7403
+ 1 yeniden deneme          24     24          26  0.8167  0.0000        48     10350
+ 2 yeniden deneme          24     24          34  0.8833  0.0000        70     11716
+ 1 deneme, hata istemde    24     24          23  0.7917  0.0000        48     10864
ikinci kosum (+ 1 yeniden deneme): kabul 0.7500, kurtarilan 26, ek cagri 56

İlk üç satır tek bir çağrıyla üretilmiştir ve belirteç sütunu üçünde de aynıdır: 7403. Değişen tek şey kabulden önce yapılan denetimdir. Doğrulama yokken kabul oranı 1,0000 görünür ve kayıt sistemine giren yanlış kayıt oranı 0,4000’dır. Yani hiçbir şey ölçülmediğinde sistem kusursuz görünür ve her beş kayıttan ikisi bozuktur. Şema eklendiğinde hatalı kayıt 0,2000’a, iş kuralı da eklendiğinde 0,0000’a iniyor.

Bunun bedeli kabul oranıdır: 1,0000’dan 0,6000’a. Doğrulama hiçbir kaydı düzeltmez, yalnız görünür kılar. Üçüncü satırdaki sistem birincisinden daha iyidir ama daha az iş yapar; 48 talep elde kalır. Doğrulamanın ölçüsü kabul oranı değil, kabul edilenlerin ne kadarının doğru olduğudur.

Kurtarmanın Bedeli

Dördüncü satır yeniden denemeyi ekliyor. 26 kayıt kurtarılıyor ve kabul oranı 0,6000’dan 0,8167’ye çıkıyor; hatalı kayıt oranı 0,0000’da kalıyor, çünkü kurtarma denetimin önüne değil arkasına konmuştur. Bedel 48 ek çağrı ve 2947 belirteçtir: kurtarılan kayıt başına 1,85 çağrı ve 113,3 belirteç. Kazanç 0,2167 ve iki koşum farkı 0,0667 olduğu için bu satır rahatça ölçülebilir.

Beşinci satır kursun kuralının en keskin uygulandığı yerdir. İkinci deneme sekiz kayıt daha kurtarıyor ve kabul oranını 0,8833’e çıkarıyor. Kazanç 0,0666. Aynı hattın iki koşum farkı ise 0,0667: birinci koşumda 0,8167, ikinci koşumda 0,7500. Kazanç farktan büyük değil, dolayısıyla ölçülmemiş sayılır. Bu satır için ödenen bedel ise kesindir: 22 ek çağrı ve 1366 belirteç, kurtarılan kayıt başına 2,75 çağrı. Ölçülemeyen bir kazanç, ölçülebilir bir bedelle satın alınmıştır.

Altıncı satır sezgiye en uygun düzeltmeyi sınıyor: reddedilen yanıtın hatasını isteme yazmak. Sonuç 26 yerine 23 kurtarma ve kabul oranında 0,7917. Aradaki 0,0250, iki koşum farkı 0,0667’nin çok altında kaldığı için bu satırla dördüncü satır arasında ölçülebilir bir fark yoktur. Bedel ise ölçülebilir: aynı 48 çağrıyla belirteç 10350’den 10864’e çıkıyor, yani 514 belirteç eklenmiştir. Hataları isteme yazmak burada bir iyileştirme değil, ölçülmemiş bir tahmindir.

Üç sayıyla toparlanır. Önceki istem biçim tarifi istemidir: kabul 0,6000, hatalı kayıt 0,0000, 7403 belirteç, 120 çağrı. Değiştirilmiş hat bir yeniden deneme ekler: kabul 0,8167, aynı hatalı kayıt oranı, 10350 belirteç, 168 çağrı. Bedel 48 çağrı ve 2947 belirteçtir; bu kursta ilk kez bir düzenek çağrı sayısını oynatıyor ve bedelin belirteçten büyük olan kısmı orada duruyor.

Özet

  • Şema doğrulaması 24 yanıtı eliyor, iş kuralı denetimi şemadan geçen 96 yanıtın 24’ünü daha eliyor: biçim denetimi hatanın yarısını görüyor.
  • Üç iş kuralının üçü de kusursuz biçimli kayıtlarda tetikleniyor; ikisi alanlar arası tutarlılık, biri kaydın dış dünyayla tutarlılığıdır.
  • Doğrulama yokken kabul oranı 1,0000 ve sisteme giren hatalı kayıt 0,4000’dır; iki denetim hatalıyı 0,0000’a indirirken kabulü 0,6000’a düşürür. Doğrulama düzeltmez, görünür kılar.
  • Bir yeniden deneme 26 kaydı kurtarır ve kabulü 0,8167’ye çıkarır; bedeli 48 ek çağrı ve 2947 belirteçtir, kurtarılan kayıt başına 1,85 çağrı.
  • İkinci denemenin kazancı 0,0666, hattın iki koşum farkı 0,0667’dir: kazanç ölçülmemiş sayılır ve karşılığında 22 çağrı ile 1366 belirteç ödenir.
  • Hatayı isteme yazmak 26 yerine 23 kayıt kurtarır ve 514 belirteç ekler; iki hat arasında ölçülebilir bir fark yoktur.

Sonraki Adım

Bu derste kurtarma tek bir kaldıraçla yapıldı: aynı isteği yeniden sormak. Kurtarılamayan 14 kayıt ise hiç incelenmedi. Onların bir kısmı ne kadar denenirse denensin düzelmez, çünkü sorun yanıtın çekilişinde değil, modelin bilmediği bir şeydedir. Bir talebin hangi tarife basamağına girdiği isteme yazılmamışsa, daha iyi bir yönerge bunu üretemez. Sonraki ders bu ayrımı sayar: aynı yanlış yanıt bazen daha iyi bir yönergeyle, bazen yalnız eksik bilginin sağlanmasıyla düzelir. Hangi hatanın hangisiyle düzeldiği ayrı ayrı sayılır ve ikisinin bedeli karşılaştırılı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