---
title: 'Öneri Değerlendirmesi'
source: 'https://academia.sh/tr/kurslar/pekistirmeli-ve-oneri/oneri-degerlendirmesi'
course: 'Pekiştirmeli Öğrenme ve Öneri Sistemleri'
language: tr
updated: '2026-08-17T18:10:16+00:00'
license: 'CC BY-SA 4.0'
---

# Öneri Değerlendirmesi

Sıralama ölçütlerinin kurulması ve aynı sıralamanın iki ayrı sayı vermesi: ilk k isabeti kesme noktasına göre üç düzenin sırasını değiştiriyor, k=3'te sonuncu olan düzen k=5'te birinci ve k=10'da üçü de ayırt edilemiyor, konum indirimi k=5'in birincisini sonuncuya düşürüyor. Çevrimdışı kayıtta 0,6886 ile birinci olan düzen, kendi kararlarıyla veri toplamaya başlayınca abone başına 1,4563 etkileşimle sonuncu ve tabanın da altında kalıyor; sınav hücrelerinin 0,6305'i hiç gösterilmemiştir, ayrılmış kalemlerin 0,5868'i beş kalemden gelir ve üç kalem ayrılmış kümede hiç görünmez.

Önceki ders soğuk aboneye sorular sorup önerileri onun kendi söylediği alana çevirdi ve kayıttan
okunan sayı **düştü**. Açıklama iki türlüydü: ya sorular işe yaramıyordu, ya da ölçü yanlış yerden
okunuyordu. Bu ders önce ölçünün kendisini kurar, sonra aynı sıralamayı iki ayrı yerde ölçer.

Kurulacak üç şey var. **İlk k isabeti** bir sıralamanın ilk k önerisinde doğru kalemi bulup
bulmadığını sayar. **Kesme noktası** k'nın kendisidir ve bir ölçüm kararıdır, verinin bir özelliği
değil. **Konum indirimi** ilk k içindeki konumu da hesaba katar: birinci sıradaki isabet ile
beşinci sıradaki isabet aynı değildir.

- **ON49. Kurgu birinci derste kurulan bloğun aynısıdır** ve aynı sayıları verir: 360 abone,
  24 kalem, 3.002 gösterim, 577 etkileşim. Ayırma da birinci dersteki ayırmadır: en az iki
  etkileşimi olan abonenin sıra damgası en büyük etkileşimi ayrılmış kümeye gider.
- **ON50. Karşılaştırılan üç düzen aynı ailedendir** ve tek bir ayar değişkeniyle ayrılır:
  puan, kalemin eğitimdeki seçim sayısı ile abonenin o alandaki geçmiş payının çarpımıdır.
  `w = 0` saf taban çizgisidir — kişiselleştirme yoktur; `w = 1` ve `w = 2` alan payını sırasıyla
  hafif ve güçlü ağırlıklandırır.
- **ON51. Taban çizgisi `w = 0`'dır**, yani eğitimde en çok seçilen kalem sırası. Aile tek olduğu
  için üç sayı arasındaki fark yalnız ağırlıktan gelir.
- **ON52. Konum indirimi ağırlığı `1 / log2(1 + konum)`'dur**; konum birden başlar. Ölçüt tüm
  sıralama üzerinden okunur, kesme noktası uygulanmaz.
- **ON53. Çevrimdışı ölçüm kayıt üzerindedir:** düzen sıralar, ayrılmış kalem doğru cevap sayılır.
  Kayıtta yalnız gösterilmiş kalemlerin etkileşimi vardır.
- **ON54. Çevrimiçi ölçümde sıralamanın kendisi neyin gösterileceğine karar verir.** Her düzen
  360 abonenin her birine kendi ilk beşini gösterir, sonuç kurgunun eğiliminden çekilir, ölçü
  yirmi dönemin abone başına etkileşim ortalamasıdır. Yönü büyük iyidir.
- **ON55. Kurgunun kendi eğilimi bir yöntem değil, tavandır.** Yalnız ölçüm için okunur ve
  çevrimiçi sayının ulaşabileceği sınırı verir.
- **ON56. Deneme tasarımı bu derste yapılmaz.** Örneklem büyüklüğü, erken durdurma ve çoklu
  karşılaştırma hesabı Kullanıcı Deneyimi ve Davranış Tasarımı kursunun Ölçme konusunda ve
  Uygulamalı İstatistik kursunda kuruldu; burada yalnız geri beslemeden doğan fark ölçülür.

## İlk k, Kesme Noktası ve Konum İndirimi

```python
# ORTAK -- KURGUDUR. Abone x hizmet kalemi etkilesim dizeyi ders icinde kurulur.
# Gosterim, secim ve puan ayri ayri uretilir: bir kalem once GOSTERILIR, sonra
# secilebilir, ancak secilirse puanlanabilir.
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


KALEM = [  # (ad, alan, kanal, ucretli, taahhut, randevu, taban_pay)
    ("otomatik_odeme_talimati", "odeme", "cevrimici", 0, 0, 0, 0.90),
    ("e_fatura_gecisi", "bildirim", "cevrimici", 0, 0, 0, 0.85),
    ("odeme_hatirlatma_sms", "bildirim", "cevrimici", 0, 0, 0, 0.78),
    ("taksitlendirme", "odeme", "sube", 0, 1, 0, 0.62),
    ("uzaktan_okuma_basvurusu", "olcum", "saha", 0, 1, 1, 0.55),
    ("kesinti_uyari_aboneligi", "bildirim", "cevrimici", 0, 0, 0, 0.50),
    ("borc_yapilandirma", "odeme", "sube", 0, 1, 0, 0.44),
    ("adres_guncelleme", "sozlesme", "cevrimici", 0, 0, 0, 0.40),
    ("sayac_degisimi", "olcum", "saha", 1, 0, 1, 0.36),
    ("tuketim_raporu_aboneligi", "bildirim", "cevrimici", 0, 0, 0, 0.32),
    ("fatura_itiraz_kaydi", "odeme", "sube", 0, 0, 0, 0.28),
    ("abonelik_devri", "sozlesme", "sube", 0, 0, 0, 0.25),
    ("kacak_kontrol_randevusu", "olcum", "saha", 0, 0, 1, 0.22),
    ("tesisat_bakim_paketi", "tesisat", "saha", 1, 1, 1, 0.19),
    ("ikinci_sayac_talebi", "olcum", "saha", 1, 0, 1, 0.16),
    ("isyeri_tarifesine_gecis", "sozlesme", "sube", 0, 1, 0, 0.14),
    ("basinc_duzenleyici_montaji", "tesisat", "saha", 1, 0, 1, 0.12),
    ("bahce_sulama_tarifesi", "sozlesme", "sube", 0, 1, 0, 0.10),
    ("sayac_yeri_degisikligi", "olcum", "saha", 1, 0, 1, 0.09),
    ("ortak_alan_paylasim_kaydi", "sozlesme", "sube", 0, 1, 0, 0.08),
    ("tesisat_uygunluk_raporu", "tesisat", "saha", 1, 0, 1, 0.07),
    ("gecikme_faizi_muafiyeti", "odeme", "sube", 0, 0, 0, 0.06),
    ("mobil_erisim_izni", "bildirim", "cevrimici", 0, 0, 0, 0.05),
    ("ek_hat_tesisati", "tesisat", "saha", 1, 1, 1, 0.04),
]
KESIM = {  # kesimin alanlara egilimi; yalniz uretecin icinde kullanilir
    "tasarruf": {"odeme": 0.5, "olcum": 1.7, "sozlesme": 0.6, "bildirim": 1.5, "tesisat": 0.6},
    "odeme":    {"odeme": 1.9, "olcum": 0.5, "sozlesme": 0.6, "bildirim": 1.1, "tesisat": 0.3},
    "isyeri":   {"odeme": 0.7, "olcum": 0.9, "sozlesme": 1.6, "bildirim": 0.7, "tesisat": 1.9},
    "yeni":     {"odeme": 0.8, "olcum": 0.7, "sozlesme": 1.8, "bildirim": 1.3, "tesisat": 0.7},
}
KESIM_AD = list(KESIM)
rk = uretec(TOHUM + 101)
KALITE = [0.25 + 0.70 * rk() for _ in KALEM]   # kalemin kendi doyuruculugu

N_ABONE, N_KALEM = 360, len(KALEM)
ABONE, GOSTERIM, ETKILESIM, PUAN, EGILIM = [], {}, {}, {}, {}
for i in range(N_ABONE):
    r = uretec(TOHUM + 7919 * i)
    a, kesim = 20001 + i, KESIM_AD[int(r() * 4)]
    etkinlik = 0.35 + 1.15 * r() ** 1.6
    ABONE.append(a)
    for j, (ad, alan, kanal, uc, ta, ra, pay) in enumerate(KALEM):
        egilim = min(0.95, KESIM[kesim][alan] * pay * etkinlik * 0.55)
        EGILIM[(a, j)] = egilim
        if r() < min(0.95, pay ** 0.55 * 0.72):        # sunulmus mu
            GOSTERIM[(a, j)] = 1
            if r() < egilim:                            # secilmis mi
                ETKILESIM[(a, j)] = r()                 # deger: sira damgasi
                if r() < 0.32:                          # puan birakmis mi
                    ham = (0.16 + 0.50 * KESIM[kesim][alan] / 1.9
                           + 0.42 * KALITE[j] + 0.26 * (r() - 0.5))
                    PUAN[(a, j)] = max(1, min(5, int(round(ham * 5))))
        else:
            r(), r(), r()
import math

# 01'in ayirmasi: en az iki etkilesimi olan abonenin sira damgasi en buyuk etkilesimi ayrilir.
kayit = {}
for (a, j), damga in ETKILESIM.items():
    kayit.setdefault(a, []).append((damga, j))
EGIT, AYRI, GORULEN = {}, {}, {}
for a, lst in kayit.items():
    lst.sort()
    if len(lst) >= 2:
        AYRI[a] = lst[-1][1]
        lst = lst[:-1]
    for damga, j in lst:
        EGIT[(a, j)] = 1
        GORULEN.setdefault(a, set()).add(j)
SINAV = sorted(AYRI)
secim = [0] * N_KALEM
for (a, j) in EGIT:
    secim[j] += 1
AL = [KALEM[j][1] for j in range(N_KALEM)]


def siralayici(w):
    """Populerlik x abonenin gecmisteki alan payi. w=0 saf taban cizgisidir. MODELDIR."""
    def puan(a):
        c = {}
        for i in GORULEN.get(a, set()):
            c[AL[i]] = c.get(AL[i], 0) + 1
        return [secim[j] * (1.0 + w * c.get(AL[j], 0)) for j in range(N_KALEM)]
    return puan


def sirala(puan, a):
    s = puan(a)
    return sorted((j for j in range(N_KALEM) if j not in GORULEN.get(a, set())),
                  key=lambda j: (-s[j], j))


DUZEN = (("taban, w=0", siralayici(0.0)), ("hafif, w=1", siralayici(1.0)),
         ("guclu, w=2", siralayici(2.0)))
print(f"egitim {len(EGIT)} etkilesim, ayrilmis {len(SINAV)} abone; cevrimdisi kayit uzerinde")
print("duzen        k=1     k=3     k=5     k=10    konum ind.  kapsama@5")
for ad, p in DUZEN:
    d = [sirala(p, a) for a in SINAV]
    k = [sum(1 for t, a in zip(d, SINAV) if AYRI[a] in t[:n]) / len(SINAV)
         for n in (1, 3, 5, 10)]
    ki = sum(1.0 / math.log2(2 + t.index(AYRI[a])) for t, a in zip(d, SINAV)) / len(SINAV)
    kaps = len(set(j for t in d for j in t[:5]))
    print(f"{ad:<12} {k[0]:.4f}  {k[1]:.4f}  {k[2]:.4f}  {k[3]:.4f}  {ki:.4f}      "
          f"{kaps:>2}/{N_KALEM}")
```

```
egitim 410 etkilesim, ayrilmis 167 abone; cevrimdisi kayit uzerinde
duzen        k=1     k=3     k=5     k=10    konum ind.  kapsama@5
taban, w=0   0.2575  0.5509  0.6527  0.9162  0.5736       9/24
hafif, w=1   0.2635  0.5569  0.6647  0.9162  0.5766      12/24
guclu, w=2   0.2635  0.5090  0.6886  0.9102  0.5727      13/24
```

Üç düzenin sırası **kesme noktasına göre değişiyor**. `k = 3`'te güçlü düzen sonuncudur
(**0,5090**), taban ondan öndedir. `k = 5`'te güçlü düzen birincidir (**0,6886**) ve tabanı
0,0359 geçer. `k = 10`'da üçü de ayırt edilemez hale gelir: 0,9162, 0,9162 ve 0,9102. Aynı üç
sıralama, aynı kayıt, üç ayrı kesme noktasında üç ayrı sıra. Kesme noktası raporlanan sayının
bir parçası değil, o sayıyı üreten karardır; yazılmadığı sürece ilk k isabeti okunamaz.

Konum indirimi dördüncü bir sıra veriyor. Bu ölçütte güçlü düzen **0,5727** ile sonuncudur, oysa
`k = 5`'te birinciydi. Sebep ilk k isabetinin görmediği şeydir: güçlü düzen doğru kalemi ilk beşe
sokuyor ama beşin **içinde daha aşağıya** koyuyor. İlk k isabeti kesme noktasının içindeki her
konumu eşit sayar; konum indirimi saymaz. İki ölçüt aynı sıralamayı iki ayrı sırada bitirir ve
ikisi de yanlış değildir — farklı şeyleri ölçerler.

Beşinci sütunun yanında altıncı duruyor: kapsama. Taban 167 aboneye toplam **9** ayrı kalem
öneriyor, güçlü düzen **13**. Kataloğun yarısından çoğu hiçbir aboneye ilk beşte hiç görünmüyor.

## Aynı Sıralama, Kendi Verisini Toplarken

Buraya kadarki bütün sayılar tek bir kayıttan okundu ve o kayıt bu üç düzenin hiçbiri tarafından
toplanmadı. Şimdi karar el değiştiriyor: her düzen kendi ilk beşini gösterir ve sonucunu görür.

```python
DONEM = 20


def cevrimici(puan, k=5):
    """Siralamanin kendisi neyin gosterilecegine karar verir; sonuc kurgudan cekilir."""
    top, gos = 0, set()
    for a in ABONE:
        ilk = sirala(puan, a)[:k]
        gos.update(ilk)
        for d in range(DONEM):
            r = uretec(TOHUM + 880000 + a * 37 + d * 911)
            for j in ilk:
                if r() < EGILIM[(a, j)]:
                    top += 1
    return top / (len(ABONE) * DONEM), len(gos)


print(f"cevrimici: her duzen kendi ilk besini gosterir, {DONEM} donem, {len(ABONE)} abone")
for ad, p in DUZEN:
    e, g = cevrimici(p)
    bek = sum(sum(EGILIM[(a, j)] for j in sirala(p, a)[:5]) for a in ABONE) / len(ABONE)
    print(f"  {ad:<12} abone basina etkilesim {e:.4f}  (beklenen {bek:.4f})  "
          f"gosterilen kalem {g}/{N_KALEM}")
```

```
cevrimici: her duzen kendi ilk besini gosterir, 20 donem, 360 abone
  taban, w=0   abone basina etkilesim 1.4581  (beklenen 1.4519)  gosterilen kalem 9/24
  hafif, w=1   abone basina etkilesim 1.4788  (beklenen 1.4795)  gosterilen kalem 12/24
  guclu, w=2   abone basina etkilesim 1.4563  (beklenen 1.4560)  gosterilen kalem 13/24
```

Çevrimdışı sıralama şuydu: taban 0,6527, hafif 0,6647, güçlü 0,6886 — güçlü birinci. Çevrimiçi
sıralama şudur: güçlü **1,4563**, taban **1,4581**, hafif **1,4788** — güçlü **sonuncu** ve
tabanın da altında. Çevrimdışı kayıtta birinci olan düzen, kendi kararlarını vermeye başladığında
hiç kişiselleştirmeyen tabanı bile geçemiyor.

Farklar küçüktür ve öyle olduğu yazılmalıdır: çevrimiçi en iyi ile en kötü arasında abone başına
0,0225 etkileşim vardır. Ölçülen şey farkın büyüklüğü değil, **sıranın taşınmaması**. Yirmi dönem
boyunca çekilen sayı beklenen değerin binde biri içinde kaldığı için bu sıralama çekim
gürültüsünden gelmiyor; düzenlerin kendisinden geliyor.

## Kaydın Göremediği

```python
from collections import Counter

c = Counter(AYRI.values())
gorunmez = sum(1 for a in SINAV for j in range(N_KALEM) if (a, j) not in GOSTERIM)
print(f"kaydin gorebildigi: {len(SINAV)} abone x {N_KALEM} kalem = {len(SINAV) * N_KALEM} "
      f"hucrenin {gorunmez}'i ({gorunmez / (len(SINAV) * N_KALEM):.4f}) hic gosterilmemis")
ustbes = sorted(range(N_KALEM), key=lambda j: (-secim[j], j))[:5]
print(f"ayrilmis kalemlerin {sum(c[j] for j in ustbes) / len(AYRI):.4f}'i egitimde en cok "
      f"secilen bes kalemden; {sum(1 for j in range(N_KALEM) if c[j] == 0)} kalem "
      f"ayrilmis kumede hic gorunmuyor")


def kurgu_egilimi(a):
    """Bir yontem degil: kurgunun kendi egilimi. Cevrimici tavani verir."""
    return [EGILIM[(a, j)] for j in range(N_KALEM)]


e, g = cevrimici(kurgu_egilimi)
d = [sirala(kurgu_egilimi, a) for a in SINAV]
print(f"kurgu egilimi (cevrimici tavan): cevrimici {e:.4f}, gosterilen kalem {g}/{N_KALEM}")
print(f"  ayni siralamanin cevrimdisi ilk bes isabeti "
      f"{sum(1 for t, a in zip(d, SINAV) if AYRI[a] in t[:5]) / len(SINAV):.4f}")
```

```
kaydin gorebildigi: 167 abone x 24 kalem = 4008 hucrenin 2527'i (0.6305) hic gosterilmemis
ayrilmis kalemlerin 0.5868'i egitimde en cok secilen bes kalemden; 3 kalem ayrilmis kumede hic gorunmuyor
kurgu egilimi (cevrimici tavan): cevrimici 1.6606, gosterilen kalem 13/24
  ayni siralamanin cevrimdisi ilk bes isabeti 0.7485
```

Ayrılma buradan geliyor. Sınav kümesinin **0,6305**'i hiç gösterilmemiş hücredir: o hücreler için
kayıtta ne bir seçim vardır ne de bir ret, yalnız boşluk. Çevrimdışı ölçüm bu boşluğu **ret gibi**
saymak zorundadır, çünkü elinde başka bir okuma yok. Bir düzen ne kadar çok gösterilmemiş kalem
önerirse çevrimdışı o kadar cezalanır — o kalem aboneye uygun olsa bile.

İkinci satır aynı şeyi doğru cevap tarafından gösteriyor: ayrılmış kalemlerin **0,5868**'i
eğitimde en çok seçilen beş kalemden geliyor ve **3** kalem ayrılmış kümede hiç görünmüyor. O üç
kalemi öneren bir düzen çevrimdışı hiçbir koşulda puan alamaz. Doğru cevabın kendisi, geçmişteki
gösterim kararlarının bir izidir.

Üçüncü satır ölçünün tavanını veriyor. Kurgunun kendi eğilimiyle sıralamak çevrimiçi **1,6606**
veriyor; taban 1,4581'de, en iyi düzen 1,4788'de duruyor. Üç düzen tavanla taban arasındaki
açıklığın onda birini kapatıyor. Aynı sıralamanın çevrimdışı ilk beş isabeti **0,7485**'tir, yani
çevrimdışı ölçüt tavanı bile 1'e çıkarmaz — kayıt, en iyi olası sıralamaya da yalnız gösterilmiş
kalemler üzerinden puan verebilir.

## Özet

- İlk k isabeti kesme noktası yazılmadan okunamaz: güçlü düzen k=3'te sonuncu (0,5090), k=5'te
  birinci (0,6886), k=10'da üç düzen ayırt edilemez (0,9162 / 0,9162 / 0,9102).
- Konum indirimi ilk k'nın görmediğini görür: k=5'in birincisi olan düzen konum ağırlığında
  0,5727 ile sonuncudur, çünkü doğru kalemi ilk beşin aşağısına koyar.
- Çevrimdışı birinci olan düzen (0,6886) çevrimiçi sonuncudur (1,4563) ve hiç kişiselleştirmeyen
  tabanın (1,4581) altında kalır; sıra taşınmaz.
- Ayrılmanın sebebi kaydın kendisidir: sınav hücrelerinin 0,6305'i hiç gösterilmemiştir, ayrılmış
  kalemlerin 0,5868'i beş kalemden gelir, 3 kalem ayrılmış kümede hiç görünmez.
- Çevrimiçi tavan 1,6606'dır; taban 1,4581 ile en iyi düzen 1,4788 arasındaki fark, tavanla taban
  arasındaki açıklığın yaklaşık onda biridir.

## Sonraki Adım

Bu derste her düzen kayda **bir kez** baktı ve kararını **bir kez** verdi. Gerçek bir sistemde
karar tekrarlanır: gösterilen kalem etkileşim üretir, etkileşim kaydı büyütür, büyüyen kayıt bir
sonraki gösterimi belirler. Kapsama sütunu bu döngünün nereye gittiğini şimdiden söylüyor — taban
24 kalemin 9'unu, güçlü düzen 13'ünü gösteriyor ve gösterilmeyen kalem bir sonraki turda daha da
az sebeple gösterilecek. Sonraki ders bu döngüyü birkaç düzine dönem çalıştırır: kaç kalem hiç
gösterilmez oluyor, popülerlik yanlılığı ne kadar büyüyor, ve çeşitliliği artırmanın kısa dönem
bedeli ile uzun dönem kazancı hangi dönemde eşitleniyor.
