İçeriğe geç
academia.sh

Ders 16 / 22

Otomatik İstem Eniyileme

İstem elle yazılmak yerine bir ölçütle aranıyor: dört parçadan mekanik olarak on aday üretiliyor, kurgu destek talepleri 40 kayıtlık doğrulama ve 80 kayıtlık sınama kümesine ayrılıyor. Arama bütçesi bir adaydan on adaya çıkarken doğrulamadaki en iyi puan 0,7750'den 0,9000'e yükseliyor, aynı adayın sınama puanı 0,6750'den 0,6500'e iniyor: doğrulama kazancı +0,1250, sınama kazancı -0,0250 ve seçilen adayın iyimserlik payı 0,2500. Arama 40 çağrıdan 400 çağrıya çıkıyor, sınamada gerçekten en iyi olan aday (0,8000) hiç seçilmiyor ve ikinci koşumda arama başka bir adayı seçiyor.

İçindekiler

Önceki derste üç istem elle yazıldı, üçü de aynı kümede ölçüldü ve en iyisi gözle seçildi. O seçimin dayanağı tek bir koşumdu ve ikinci koşumda sıralama tersine döndü. Bu işin elle yapılan kısmı aslında dardır: adayları üretmek bir birleştirme işi, puanlamak bir döngü, seçmek bir karşılaştırma. Üçü de yazılabilir. Yazıldığında ortaya otomatik istem eniyileme çıkar — istemin bir ölçütle aranması.

Aramanın kendisi bu dersin konusu değildir. Bir aday kümesi üzerinde en iyiyi seçmenin yordamı, ve ayar bütçesi büyüdükçe doğrulama kümesindeki en iyi puanın iyimserleşmesi, Denetimli Öğrenme kursunun hiperparametre arama dersinde ölçüldü ve tekrarlanmaz. Burada aranan şey bir ayar değeri değil bir metindir, ve puanı veren şey belirsiz bir bileşendir. Dersin tek sorusu şudur: arama bütçesi büyüdükçe doğrulamada kazanılan sayı, hiç görülmemiş bir sınama kümesine taşınıyor mu.

  • AY69. Kod gerçek bir model uç noktası çağırmaz; standart kitaplıkla yazılmış bir benzetici çağırır. Destek talepleri ve konular kurgudur.
  • AY70. Aday sayısı 10’u aşmaz. Adaylar dört parçadan mekanik olarak üretilir: rol cümlesi, önek cümlesi, etiket listesinin sırası ve biçim cümlesi.
  • AY71. Küme ikiye ayrılır: doğrulama 40 kayıt, sınama 80 kayıt. Sınama kümesi arama boyunca hiç görülmez ve hiçbir seçim ona bakılarak yapılmaz.
  • AY72. Ölçüt etiket isabetidir; yanıttan etiket okunamazsa kayıt yanlış sayılır.
  • AY73. Arama kuralı: bütçe bb iken ilk bb aday içinde doğrulaması en yüksek olan seçilir. Beraberlikte listede önce gelen kazanır.
  • AY74. Arama bedeli çağrı sayısıyla yazılır. Her aday doğrulama kümesinin tamamında koşturulur; bütçe bb için bedel b×40b \times 40 çağrıdır.
  • AY75. İyimserlik payı, seçilen adayın doğrulama puanı ile sınama puanı arasındaki farktır.
  • AY76. İki koşum basılır. Tohum 20260219 ile arama baştan tekrarlanır; seçilen adayın değişip değişmediği ve aynı adayın sınama puanının ne kadar oynadığı yazılır.

On Aday, İki Küme

# BENZETICI -- KURGUDUR. Bu kod gercek bir model uc noktasi cagirmaz; standart
# kitaplikla yazilmis bir dil modeli benzeticisini cagirir. 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"]
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, tohum=TOHUM, sicaklik=0.6, en_uzun=EN_UZUN):
    SAYAC[0] += 1
    bel = belirtecle(istem)
    if len(bel) > PENCERE:
        return {"durum": "baglam_asimi", "giris": len(bel), "cikis": 0, "yanit": ""}
    if SAYAC[0] % 37 == 0:
        return {"durum": "hiz_siniri", "giris": len(bel), "cikis": 0, "yanit": ""}
    r = uretec(tohum ^ izno(istem))
    if len(bel) > 90 and r() < 0.04:
        return {"durum": "zaman_asimi", "giris": len(bel), "cikis": 0, "yanit": ""}
    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])]
    y = k if "tek" in bel else SERBEST[ayrik(r(), [0.42, 0.26, 0.32])].format(k=k)
    cb = belirtecle(y)
    if len(cb) > en_uzun:                            # durdurma kosulu
        cb = cb[:en_uzun]
        y = " ".join(cb)
    return {"durum": "tamam", "giris": len(bel), "cikis": len(cb), "yanit": y}


def oku(y):                                          # yanittan etiket cikarma
    for s in y.lower().split():
        if s in KONU:
            return s
    return None


ROL = ["", "Sen destek masasi gorevlisisin . ", "Kayit gorevlisi olarak yanitla . "]
ONEK = ["", "Once talebin hangi islem alanina girdigini belirle , sonra ",
        "Ornek: endeks tutmuyor -> sayac . "]
LISTE = ["fatura , ariza , sayac , tarife , kesinti",
         "kesinti , tarife , sayac , ariza , fatura",
         "ariza , kesinti , fatura , sayac , tarife"]
BICIM = ["Yanit olarak tek etiket yaz .", "Tek etiket yaz , aciklama ekleme .",
         "Cevabin tek sozcuk olsun , listedeki etiketlerden biri ."]

ADAY, PARCA = [], []
r = uretec(TOHUM + 777)
while len(ADAY) < 10:                # adaylar mekanik uretilir, tohum sabittir
    d = [int(r() * 3) for _ in range(4)]
    y = (ROL[d[0]] + ONEK[d[1]] + "Talebi su etiketlerden birine ata: " + LISTE[d[2]]
         + " . " + BICIM[d[3]] + " Talep: ")
    if y not in ADAY:
        ADAY.append(y)
        PARCA.append("".join(str(x) for x in d))

DOG, SIN = TALEP[:40], TALEP[40:]


def puan(yonerge, kume, tohum=TOHUM):
    d = 0
    for x in kume:
        d += oku(cagir(yonerge + x["metin"], tohum=tohum)["yanit"]) == x["konu"]
    return d / len(kume)


SAYAC[0] = 0
PD = [puan(y, DOG) for y in ADAY]
CAGRI_ARAMA = SAYAC[0]
PS = [puan(y, SIN) for y in ADAY]
print(f"{'aday':>4} {'parca':>6} {'belirtec':>8} {'dogrulama':>10} {'sinama':>8} "
      f"{'fark':>8}")
for i, y in enumerate(ADAY):
    print(f"{i + 1:>4d} {PARCA[i]:>6} {len(belirtecle(y)):>8d} {PD[i]:>10.4f} "
          f"{PS[i]:>8.4f} {PS[i] - PD[i]:>+8.4f}")
print(f"\ndogrulama kumesi {len(DOG)} kayit, sinama kumesi {len(SIN)} kayit")
print(f"arama cagrisi {CAGRI_ARAMA}, dogrulama ortalamasi {sum(PD) / 10:.4f}, "
      f"sinama ortalamasi {sum(PS) / 10:.4f}")
aday  parca belirtec  dogrulama   sinama     fark
   1   2110       53     0.7750   0.6750  -0.1000
   2   2201       51     0.7250   0.7250  +0.0000
   3   1210       50     0.7500   0.6500  -0.1000
   4   1000       41     0.6500   0.8000  +0.1500
   5   0212       47     0.4250   0.4625  +0.0375
   6   1101       56     0.9000   0.6500  -0.2500
   7   0121       47     0.6000   0.6750  +0.0750
   8   0202       47     0.5250   0.6000  +0.0750
   9   1020       41     0.7750   0.7375  -0.0375
  10   0100       45     0.7750   0.6875  -0.0875

dogrulama kumesi 40 kayit, sinama kumesi 80 kayit
arama cagrisi 400, dogrulama ortalamasi 0.6900, sinama ortalamasi 0.6663

Son satır bir yanlış açıklamayı baştan kapatıyor. İki kümenin ortalamaları 0,6900 ve 0,6663; aralarında sistematik bir uçurum yok. Yani sınama kümesi daha zor değil, dağılımı farklı değil. Buna rağmen fark sütunu iki yöne birden gidiyor ve 0,2500 büyüklüğüne ulaşıyor. Ayrışma kümelerin arasında değil, aday başınadır.

Altıncı aday doğrulamada 0,9000 ile açık ara birinci, sınamada 0,6500 ile sondan ikinci. Dördüncü aday tam tersi: doğrulamada 0,6500 ile alt sıralarda, sınamada 0,8000 ile birinci. Kırk kayıtlık bir kümede tek kayıt 0,0250 eder; altıncı adayı birinciden ayıran 0,1250 farkı beş kaydın nereye düştüğünden ibarettir.

parca sütunu adayın dört hanesini verir: rol cümlesi, önek cümlesi, etiket listesinin sırası, biçim cümlesi. Dördüncü aday 1000, dokuzuncu aday 1020; yalnız üçüncü hanede ayrılıyorlar. Aynı rol cümlesi, aynı önek yokluğu, aynı biçim cümlesi, aynı beş etiket — tek fark etiketlerin yazılma sırasıdır, ve sınama puanları 0,8000 ile 0,7375. İstemin taşıdığı bilgi değişmeden puanın 0,0625 oynaması, bu aramanın neyi ölçtüğü sorusunu şimdiden açıyor.

Arama Bütçesi Büyüdükçe

def secim(pd):                       # butce b: ilk b aday icinde dogrulamasi en yuksek olan
    return [max(range(b), key=lambda i: pd[i]) for b in range(1, len(pd) + 1)]


S = secim(PD)
print(f"{'butce':>5} {'secilen':>7} {'dogrulama':>10} {'sinama':>8} {'arama cagrisi':>14}")
for b, i in enumerate(S, 1):
    print(f"{b:>5d} {i + 1:>7d} {PD[i]:>10.4f} {PS[i]:>8.4f} {b * len(DOG):>14d}")
ilk, son = S[0], S[-1]
print(f"\nbutce 1 -> 10: dogrulama {PD[son] - PD[ilk]:+.4f}, sinama {PS[son] - PS[ilk]:+.4f}")
print(f"secilen adayin iyimserlik payi {PD[son] - PS[son]:+.4f}")
en = max(range(10), key=lambda i: PS[i])
print(f"sinamada en iyi aday {en + 1} ({PS[en]:.4f}); dogrulamasi {PD[en]:.4f}, "
      f"arama onu hic secmedi")

SAYAC[0] = 0
PD2 = [puan(y, DOG, TOHUM + 1) for y in ADAY]
PS2 = [puan(y, SIN, TOHUM + 1) for y in ADAY]
son2 = secim(PD2)[-1]
print(f"\nikinci kosum (tohum {TOHUM + 1}): secilen aday {son2 + 1}, dogrulama "
      f"{PD2[son2]:.4f}, sinama {PS2[son2]:.4f}")
print(f"aday {son + 1} sinamasi iki kosumda {PS[son]:.4f} -> {PS2[son]:.4f} "
      f"({PS2[son] - PS[son]:+.4f})")
print(f"on adayin sinama sirasi iki kosumda ayni mi: "
      f"{sorted(range(10), key=lambda i: -PS[i]) == sorted(range(10), key=lambda i: -PS2[i])}")
butce secilen  dogrulama   sinama  arama cagrisi
    1       1     0.7750   0.6750             40
    2       1     0.7750   0.6750             80
    3       1     0.7750   0.6750            120
    4       1     0.7750   0.6750            160
    5       1     0.7750   0.6750            200
    6       6     0.9000   0.6500            240
    7       6     0.9000   0.6500            280
    8       6     0.9000   0.6500            320
    9       6     0.9000   0.6500            360
   10       6     0.9000   0.6500            400

butce 1 -> 10: dogrulama +0.1250, sinama -0.0250
secilen adayin iyimserlik payi +0.2500
sinamada en iyi aday 4 (0.8000); dogrulamasi 0.6500, arama onu hic secmedi

ikinci kosum (tohum 20260219): secilen aday 9, dogrulama 0.7500, sinama 0.7875
aday 6 sinamasi iki kosumda 0.6500 -> 0.8500 (+0.2000)
on adayin sinama sirasi iki kosumda ayni mi: False

Tablonun iki sütunu ters yönde ilerliyor. Bütçe birden ona çıkarken doğrulama sütunu 0,7750’den 0,9000’e yükseliyor — arama çalışıyor, işini yapıyor, her yeni adayla daha yüksek bir sayı buluyor. Aynı satırlarda sınama sütunu 0,6750’den 0,6500’e iniyor. Doğrulama kazancı +0,1250, sınama kazancı −0,0250. Arama bütçesinin dokuz katına çıkması, hiç görülmemiş veride hiçbir şey kazandırmadı; küçük bir kayıp getirdi.

Bedel aynı tabloda ve tartışmasız: 40 çağrıdan 400 çağrıya. Fazladan 360 çağrı harcandı ve karşılığında elde edilen tek şey rapor edilecek sayının 0,1250 yükselmesi oldu. Seçilen adayın iyimserlik payı 0,2500: doğrulamada 0,9000 yazan istem, hiç görülmemiş kayıtlarda 0,6500 veriyor. Bu istemi “0,9000’lik istem” diye teslim etmek, ölçünün dörtte birini uydurmak demektir.

Üçüncü satır aramanın körlüğünü gösteriyor. Sınamada gerçekten en iyi olan aday dördüncüdür (0,8000), ve arama onu hiçbir bütçede seçmedi; doğrulamada 0,6500 aldığı için daha ilk karşılaştırmada elendi. Arama iyi istemi bulamadı, doğrulama kümesine en iyi uyan istemi buldu.

İki Koşum ve Aramanın Ölçtüğü Şey

Son üç satır bütün alıştırmanın zeminini yokluyor. Tohum değiştirilip arama baştan koşturulunca seçilen aday altıncıdan dokuzuncuya kayıyor: aynı adaylar, aynı kümeler, aynı kural, başka bir kazanan. Dokuzuncu aday, sınamada birinci olan dördüncüden yalnız etiket sırasıyla ayrılıyordu. Dahası, altıncı adayın sınama puanı 0,6500’den 0,8500’e, yani +0,2000 oynuyor. Aramanın on aday üzerinde kazandığı doğrulama farkı 0,1250 idi; tek bir adayın koşumdan koşuma oynaması bunun üstünde. Son satır bunu tamamlıyor: on adayın sınama sıralaması iki koşumda aynı değil.

Buradan çıkan sonuç aramayı yasaklamaz, ölçüsünü düzeltir. Doğrulama kümesindeki en iyi puan bir istemin niteliği değil, bir arama bütçesinin artığıdır; bütçe büyüdükçe iyimserleşir ve bu iyimserlik ayrı bir sayıyla, hiç dokunulmamış bir kümede ölçülmedikçe görünmez. Aynı şey belirsiz bir bileşenin ikinci koşumu için de geçerlidir. Bu kursun kuralı burada son biçimini alıyor: ölçülmeden değiştirilen istem bir iyileştirme değil bir tahmindir — ve tek bir kümede, tek bir koşumda ölçülen istem de öyledir.

Özet

  • On aday dört parçadan mekanik olarak üretiliyor; doğrulama kümesi 40, sınama kümesi 80 kayıt. İki kümenin ortalamaları 0,6900 ve 0,6663, yani ayrışma kümeler arasında değil aday başınadır.
  • Arama bütçesi birden ona çıkarken doğrulama 0,7750’den 0,9000’e yükseliyor, aynı adayın sınaması 0,6750’den 0,6500’e iniyor: +0,1250 karşılığında −0,0250.
  • Bedel çağrı sayısıyla yazılır: arama 40 çağrıdan 400 çağrıya çıkıyor.
  • Seçilen adayın iyimserlik payı 0,2500. Sınamada gerçekten en iyi olan aday (0,8000) doğrulamada 0,6500 aldığı için hiçbir bütçede seçilmiyor.
  • İkinci koşumda arama başka bir adayı seçiyor ve altıncı adayın sınaması +0,2000 oynuyor — tek bir adayın koşum farkı, aramanın on adayda kazandığı farktan büyük.

Sonraki Adım

On altı derste isteme ne söyleneceği düzenlendi ve modelden nasıl düşüneceği istendi: yönerge, rol, biçim, örnek, yasak bildirimi, adım adım çözüm, çoklu örnek, dallanma, geri adım, eylem alanı, topluluk ve şimdi arama. Hepsinin altında sessiz duran bir şey vardı — modelden gelen yanıt serbest metindi. Etiket her derste yanıtın içinden bir okuma yordamıyla çıkarıldı; okunamayan yanıt yanlış sayıldı ve o pay ayrıca sayıldı. İstem tarafında yapılan her iyileştirme, çıktının biçimini rica etmekten ibaretti. Sonraki konu bu tarafa geçer: yanıtın üretilme ayarları, yanıtın nerede durduğu, biçimin dayatılması, gelen çıktının şemaya ve iş kuralına karşı doğrulanması, ve doğrulamaya takılan yanıtın ne kadarının yeniden denemeyle kurtarıldığı.

İ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