---
title: 'Otomatik İstem Eniyileme'
source: 'https://academia.sh/tr/kurslar/istem-muhendisligi/otomatik-istem-eniyileme'
course: 'İstem Mühendisliği'
language: tr
updated: '2026-08-17T18:06:39+00:00'
license: 'CC BY-SA 4.0'
---

# 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.

Ö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 $b$ iken **ilk $b$ 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 $b$ için bedel $b \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

```python
# 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

```python
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ığı.
