---
title: 'Soğuk Başlangıç'
source: 'https://academia.sh/tr/kurslar/pekistirmeli-ve-oneri/soguk-baslangic'
course: 'Pekiştirmeli Öğrenme ve Öneri Sistemleri'
language: tr
updated: '2026-08-17T18:10:15+00:00'
license: 'CC BY-SA 4.0'
---

# Soğuk Başlangıç

Hiç etkileşimi olmayan abone ve hiç seçilmemiş kalem için önerinin kurulması: 360 abonenin 80'inin hiç, 113'ünün tek etkileşimi vardır ve tek etkileşim gizlenince 193 abone soğuk sayılır, 464 etkileşimlik eğitim kümesinde bir kalem hiç seçilmemiş ve sekiz kalem beşin altındadır. Popülerlik geri dönüşü 193 abonenin tamamını ısıtır ama hepsine aynı beş kalemi verir, öznitelik köprüsü tek soğuk kalemi 114 aboneye ulaştırır ama hiçbir soğuk aboneyi ısıtmaz, üç soruluk giriş 339 soruyla 71 aboneyi ısıtıp kapsamayı 5'ten 13 kaleme çıkarır ve ilk beş isabetini 0,5752'den 0,5487'ye düşürür.

Dört derste öneri hep var olan etkileşimlerden üretildi: içerik temelli yaklaşım kalemin
özniteliklerinden, işbirlikçi süzgeçleme komşu abonelerin geçmişinden, dizey ayrıştırma gizli
etkenlerden. Üçünün de sessiz bir ortak koşulu vardı — abonenin dolu bir satırı olması. Satırı
tümüyle boş olan abone ile sütunu tümüyle boş olan kalem için ne yapılacağı sorulmadı.

Bu dersin ölçtüğü şey bir doğruluk değil, **ısıtmadır**: kaç abone ve kaç kalem soğuk, ve her
çözüm bunların kaçını öneri üretilebilir hale getiriyor. Her ısıtmanın bir bedeli vardır ve bedel
aynı satırda sayılır.

- **ON41. Kurgu birinci derste kurulan bloğun aynısıdır** ve aynı sayıları verir: 360 abone,
  24 hizmet kalemi, 8.640 hücre, tohum 20260218; 3.002 gösterim, 577 etkileşim, 218 puan.
- **ON42. Soğuk abone, eğitim kümesinde hiç etkileşimi olmayan abonedir.** Soğuk kalem, eğitim
  kümesinde hiç seçilmemiş kalemdir.
- **ON43. Soğuk protokol ayırmayı değiştirir.** Hiç etkileşimi olmayan abonenin doğru cevabı da
  yoktur ve ölçüye giremez. Tek etkileşimi olan abonenin o tek etkileşimi gizlenir: satırı boşalır,
  doğru cevabı bilinir. Geriye kalan etkileşimler eğitim kümesidir.
- **ON44. Taban çizgisi, eğitimde en çok seçilen beş kalemi herkese sunmaktır.** Birinci derste
  kurulan taban budur; soğuk abone için elde başka hiçbir bilgi olmadığından burada da o seçilir.
- **ON45. Isıtma, bir çözümün soğuk aboneyi ya da soğuk kalemi öneri üretilebilir hale
  getirmesidir** ve sayısı kaç abone, kaç kalemdir.
- **ON46. Bedel üç sayıyla yazılır:** sorulan soru sayısı, cevapsız kalan abone sayısı, ve
  önerilerin yayıldığı ayrı kalem sayısı.
- **ON47. Üç soruluk giriş kurgudur:** ilgilendiğiniz alan, ikinci alan, başvuru sıklığı.
  Cevaplama oranı 0,62'dir ve kurgunun bir parametresidir.
- **ON48. Ölçüt ilk beş isabetidir**; tanımı birinci derste kuruldu ve burada tekrarlanmaz.

## Soğuk Olanı Saymak

```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()
kayit = {}
for (a, j), damga in ETKILESIM.items():
    kayit.setdefault(a, []).append((damga, j))
SIFIR = [a for a in ABONE if a not in kayit]
TEKIL = sorted(a for a in kayit if len(kayit[a]) == 1)
COKLU = [a for a in kayit if len(kayit[a]) >= 2]
GIZLI = {a: kayit[a][0][1] for a in TEKIL}          # SOGUK PROTOKOL: tek etkilesim gizlenir
EGIT = dict(((a, j), 1) for a in COKLU for _, j in kayit[a])
secim = [0] * N_KALEM
for (a, j) in EGIT:
    secim[j] += 1
SOGUK_K = [j for j in range(N_KALEM) if secim[j] == 0]
AZ_K = sorted(range(N_KALEM), key=lambda j: (secim[j], j))
SIRALI = sorted(range(N_KALEM), key=lambda j: (-secim[j], j))
print(f"{N_ABONE} abone: {len(SIFIR)} sifir etkilesim, {len(TEKIL)} tek etkilesim, "
      f"{len(COKLU)} iki ve ustu")
print(f"soguk abone {len(SIFIR) + len(TEKIL)}; olculebilen {len(TEKIL)} abone, "
      f"egitim kumesi {len(EGIT)} etkilesim")
print(f"soguk kalem {len(SOGUK_K)}: {', '.join(KALEM[j][0] for j in SOGUK_K)}; "
      f"bes etkilesimin altinda {sum(1 for j in range(N_KALEM) if secim[j] < 5)} kalem")
print("taban listesi (egitimde en cok secilen bes kalem):")
for j in SIRALI[:5]:
    print(f"  {KALEM[j][0]:26s} {secim[j]:3d}")
```

```
360 abone: 80 sifir etkilesim, 113 tek etkilesim, 167 iki ve ustu
soguk abone 193; olculebilen 113 abone, egitim kumesi 464 etkilesim
soguk kalem 1: mobil_erisim_izni; bes etkilesimin altinda 8 kalem
taban listesi (egitimde en cok secilen bes kalem):
  e_fatura_gecisi             76
  odeme_hatirlatma_sms        71
  otomatik_odeme_talimati     58
  taksitlendirme              46
  uzaktan_okuma_basvurusu     31
```

Üç sayı üç ayrı abone kümesi tarif ediyor. **80** abonenin hiç etkileşimi yok; bu aboneler için
elde ne bir geçmiş var ne de bir doğru cevap, dolayısıyla hiçbir ölçüye giremezler ama sisteme
her gün gelirler. **113** abonenin tek etkileşimi var ve soğuk protokol o tek etkileşimi gizler:
satırları boşalır, doğru cevapları elde kalır. Soğuk abone toplamı **193**, yani 360 abonenin
yarıdan biraz azı; ölçülebilen kısmı **113**.

Kalem tarafı çok daha dar: eğitim kümesinde hiç seçilmemiş **1** kalem var, beş etkileşimin
altında kalan **8** kalem. Taban listesi kataloğun eğriliğini olduğu gibi yansıtıyor — beş kalem
464 etkileşimin 282'sini topluyor. Soğuk olmak ile önerilmemek ayrı şeylerdir: önceki derslerde
taban listesinin 24 kalemin **15**'ini hiçbir aboneye önermediği ölçülmüştü, oysa o kalemlerin
etkileşimi vardır ve soğuk değildirler; yalnız sıralamaya girmezler. Soğuk başlangıcın iki yüzü
de aynı ağırlıkta değildir: bu kurguda soğuk abone sorunu soğuk kalem sorunundan çok büyüktür.

## Kalemi Isıtmak: Öznitelik Köprüsü

Soğuk kalemin etkileşimi yoktur ama **özniteliği vardır**: hangi alana ait olduğu, hangi kanaldan
yürüdüğü, ücretli mi, taahhüt mü istediği, randevu mu gerektirdiği. Köprü bu özniteliklerle soğuk
kalemi sıcak komşularına bağlar ve kalem, o komşularla etkileşmiş abonelerin listesine girer.

```python
import math

ALAN = ["odeme", "olcum", "sozlesme", "bildirim", "tesisat"]
KANAL = ["cevrimici", "saha", "sube"]


def oz(j):
    """Kalem oznitelikleri: alan, kanal ve uc ikili bayrak. Etkilesim gerektirmez."""
    ad, alan, kanal, uc, ta, ra, p = KALEM[j]
    return ([1.0 if alan == x else 0.0 for x in ALAN]
            + [1.0 if kanal == x else 0.0 for x in KANAL] + [float(uc), float(ta), float(ra)])


def benzer(i, j):
    x, y = oz(i), oz(j)
    return sum(p * q for p, q in zip(x, y)) / (
        math.sqrt(sum(p * p for p in x) * sum(q * q for q in y)) + 1e-9)


sicak = [j for j in range(N_KALEM) if secim[j] > 0]
print("icerik temelli kopru; son sutun komsulariyla etkilesmis abone sayisi")
for j in AZ_K[:4]:
    kom = sorted(sicak, key=lambda t: (-benzer(j, t), t))[:2]
    if j in kom:
        kom = [t for t in kom if t != j] + [sorted(sicak, key=lambda t: (-benzer(j, t), t))[2]]
    ulas = set(a for (a, t) in EGIT if t in kom)
    print(f"  {KALEM[j][0]:24s}{secim[j]:2d}  komsu: {KALEM[kom[0]][0]}, "
          f"{KALEM[kom[1]][0]} -> {len(ulas):>3}")
print(f"kopru {len(SOGUK_K)}/{len(SOGUK_K)} soguk kalemi oneri havuzuna sokuyor, "
      f"0/{len(SIFIR) + len(TEKIL)} soguk aboneyi isitiyor")
```

```
icerik temelli kopru; son sutun komsulariyla etkilesmis abone sayisi
  mobil_erisim_izni        0  komsu: e_fatura_gecisi, odeme_hatirlatma_sms -> 114
  tesisat_uygunluk_raporu  1  komsu: basinc_duzenleyici_montaji, tesisat_bakim_paketi ->  10
  gecikme_faizi_muafiyeti  1  komsu: fatura_itiraz_kaydi, taksitlendirme ->  53
  ek_hat_tesisati          1  komsu: tesisat_bakim_paketi, basinc_duzenleyici_montaji ->  10
kopru 1/1 soguk kalemi oneri havuzuna sokuyor, 0/193 soguk aboneyi isitiyor
```

Köprü soğuk kalem sorununu çözüyor: **1/1**. Erişim genişliği ise komşunun kim olduğuna bağlı ve
bu, köprünün gizli bedelidir. `mobil_erisim_izni` en yakın komşuları çevrimiçi bildirim kalemleri
olduğu için **114** aboneye ulaşıyor; `tesisat_uygunluk_raporu` ile `ek_hat_tesisati` ise saha
tesisat kalemlerine komşu oldukları için **10**'ar aboneye. Köprü, kalemi kendi komşularının
yaygınlığı kadar ısıtır — yaygın komşusu olan soğuk kalem hemen ısınır, seyrek komşusu olan soğuk
kalır. Kalemi ısıtmak, sütunun kendi popülerliğini değil, komşusununkini ödünç almaktır.

Son satır asıl sınırı yazıyor: köprü **0/193** soğuk aboneyi ısıtıyor. Kurguda kalemin özniteliği
vardır, abonenin yoktur; abone hakkında bilinen tek şey geçmişidir ve soğuk abonenin geçmişi
boştur. İçerik temelli yaklaşım soğuk başlangıcın yalnız bir yüzünü görür.

## Aboneyi Isıtmak: Üç Soruluk Giriş

Abone tarafında iki seçenek kalır: tabana düşmek — herkese aynı beş kalemi sunmak — ya da abonenin
kendisine sormak. İkincisi kayıtta olmayan veriyi **üretir** ve bedeli sorudur.

```python
KESIMI = dict((20001 + i, KESIM_AD[int(uretec(TOHUM + 7919 * i)() * 4)])
              for i in range(N_ABONE))
CEVAP = {}
for a in TEKIL:                                     # uc soru: alan, ikinci alan, etkinlik
    q = uretec(TOHUM + 555000 + a)
    if q() < 0.62:                                  # cevaplama orani kurgudur
        s = sorted(KESIM[KESIMI[a]], key=lambda x: -KESIM[KESIMI[a]][x])
        CEVAP[a] = (s[0], s[1], 0.35 + 1.15 * uretec(TOHUM + 7919 * (a - 20001))() ** 1.6)


def taban(a):
    return SIRALI[:5]


def giris(a, ucuncu=False):
    """Cevap verilmisse alan sirasi, verilmemisse taban listesi. MODELDIR."""
    if a not in CEVAP:
        return SIRALI[:5]
    a1, a2, etkinlik = CEVAP[a]
    kat = etkinlik if ucuncu else 1.0               # ucuncu cevap her kalemi esit carpar
    return sorted(range(N_KALEM), key=lambda j: (
        -kat * (secim[j] + 1) ** 0.35 * (3.0 if KALEM[j][1] == a1 else
                                       1.8 if KALEM[j][1] == a2 else 1.0), j))[:5]


print(f"uc soruluk giris: {3 * len(TEKIL)} soru soruldu, {len(CEVAP)} abone cevapladi, "
      f"{len(TEKIL) - len(CEVAP)} abone taban listesine dustu")
for ad, f in (("taban (populerlik)", taban), ("giris, iki cevap", giris),
              ("giris, uc cevap", lambda a: giris(a, True))):
    isabet = sum(1 for a in TEKIL if GIZLI[a] in f(a)) / len(TEKIL)
    kaps = len(set(j for a in TEKIL for j in f(a)))
    print(f"  {ad:<20} ilk bes isabet {isabet:.4f}  kapsama {kaps:>2}/{N_KALEM}")
```

```
uc soruluk giris: 339 soru soruldu, 71 abone cevapladi, 42 abone taban listesine dustu
  taban (populerlik)   ilk bes isabet 0.5752  kapsama  5/24
  giris, iki cevap     ilk bes isabet 0.5487  kapsama 13/24
  giris, uc cevap      ilk bes isabet 0.5487  kapsama 13/24
```

Üç çözümün ısıttığı artık yan yana okunabilir. Popülerlik geri dönüşü **193/193** aboneyi ısıtır
ve **0/1** kalemi; öznitelik köprüsü **0/193** aboneyi ve **1/1** kalemi; üç soruluk giriş
ölçülebilen 113 abonenin **71**'ini ısıtır ve **0/1** kalemi. Hiçbiri iki yüzü birden ısıtmaz.
Soğuk başlangıç tek bir sorun değildir; iki ayrı sorundur ve iki ayrı çözüm ister.

Bedeller de yan yana durur. Giriş için **339** soru soruldu, **42** abone hiç cevap vermeyip
tabana düştü; cevaplama oranının 0,62 olması kurgunun bir seçimidir ve daha düşük bir oran
ısıtılan abone sayısını doğrudan aşağı çeker. Üçüncü sorunun bedeli özel bir tür: başvuru sıklığı
cevabı her kalemi **aynı katsayıyla** çarptığı için sıralamayı hiç değiştirmiyor, isabet de kapsama
da iki cevaplı kurulumla birebir aynı çıkıyor. 113 abonenin her birine sorulan bu üçüncü soru
karşılığında sistemin eline hiçbir sıralama değişikliği geçmiyor. Bir cevabın bilgi taşıması, o
cevabın seçenekleri **birbirinden ayırmasına** bağlıdır.

Tabanın bedeli soruda değil, tekdüzeliktedir: 113 aboneye toplam **5** ayrı kalem önerildi. Giriş
bu sayıyı **13**'e çıkarıyor. Buna karşılık kayıttan okunan ilk beş isabeti tabanda **0,5752**,
girişte **0,5487** — soru sorulduğunda ölçü **düşüyor**. Bu sayıların hangi kayıttan okunduğu
önemlidir: gizlenen tek etkileşim, o abonenin **gösterilmiş** bir kalemle kurduğu tek etkileşimdir
ve gösterim düzeni ağırlıkla kataloğun üst ucunu sunmuştur. Taban tam olarak o üst ucu öneriyor.

## Özet

- Soğuk başlangıç iki ayrı sorundur: kurgu dizeyde 80 abonenin hiç, 113 abonenin tek etkileşimi
  vardır ve tek etkileşim gizlenince 193 abone soğuk sayılır; kalem tarafında 464 etkileşimlik
  eğitim kümesinde 1 kalem hiç seçilmemiş, 8 kalem beşin altındadır.
- Popülerlik geri dönüşü 193/193 aboneyi ısıtır, hiçbir kalemi ısıtmaz ve hepsine aynı 5 kalemi
  verir; öznitelik köprüsü 1/1 kalemi ısıtır, hiçbir soğuk aboneyi ısıtmaz ve kalemi komşusunun
  yaygınlığı kadar taşır: 114 aboneye karşı 10 abone.
- Üç soruluk giriş 339 soru karşılığında 71 aboneyi ısıtır, 42 abone cevapsız kalır, kapsama
  5'ten 13 kaleme çıkar; üçüncü soru her kalemi aynı katsayıyla çarptığı için sıralamayı hiç
  değiştirmez.
- Kayıttan okunan ilk beş isabeti tabanda 0,5752, girişte 0,5487'dir; bu kayıt yalnız gösterilmiş
  kalemlerdeki etkileşimlerden oluşur.

## Sonraki Adım

Bu dersin son tablosu tuhaf bir şey söylüyor: soğuk aboneye sorular sorup önerileri onun kendi
söylediği alana çevirmek, kayıttan okunan sayıyı **düşürdü**. İki açıklama var. Ya sorular işe
yaramıyor, ya da ölçü yanlış yerden okunuyor — çünkü kayıttaki her etkileşim, kararı sistemin
değil **gösterim düzeninin** verdiği bir anda doğdu ve gösterilmemiş bir kalemin etkileşimi
kayıtta hiç görünmüyor. Sonraki ders sıralama ölçütlerini kurar: ilk k, kesme noktası ve konum
indirimi. Sonra aynı sıralamayı iki kez ölçer — bir kez bu kayıt üzerinde, bir kez de sıralamanın
kendisi neyin gösterileceğine karar verirken. İki sayı yan yana basılır.
