İçeriğe geç
academia.sh

Ders 10 / 12

Sunum Kalıpları

Aynı paketin toplu, çevrimiçi ve akış tabanlı üç yerleşimde koşturulup üçünün gecikme sınıfı, tazeliği ve tahmin başına bedelinin ayrı ayrı sayılması: üç kalıp da aynı 600 isteğe aynı yanıtı verir ve isabet üçünde de 0,8067'dir, yani çıktıya bakan bir gözlem hangi kalıbın koştuğunu söyleyemez. Fark üç sütundadır: istek anında yapılan iş toplu ve akış kalıbında arama, çevrimiçi kalıpta 352 ile 550 satırlık tarama; yanıtın yaşı toplu kalıpta bir dönem, ötekilerde sıfır; tahmin başına okunan satır 11,00, 463,87 ve 3,67. Bayatlık süpürmesi altı döneme kadar 0 değişen tahmin verir ve bunun nedeni kalıp değil karar puanının eşiğe en az 7,6468 uzaklıkta durmasıdır. Bedel payda kararıdır: toplu ile çevrimiçi kalıp 4,74 kullanılan tahminde eşitlenir ve hangi görevin hangi kalıba dayandığı bu noktadan okunur.

İçindekiler

Bir önceki ders modeli paketledi: çalışma zamanı sabitlendi, arayüz sözleşmesi yazıldı ve sözleşme yazılmadığında kaç çağrının düştüğü sayıldı. Paketin ne kabul ettiği ve ne döndürdüğü artık yazılıdır. Yazılmayan tek şey, bu paketin ne zaman çalıştığıdır. Aynı paket dönem başında bir kez koşup iki yüz tahmini bir tabloya yazabilir, her istek geldiğinde bir kez koşabilir, ya da her yeni okuma indiğinde kendini tazeleyebilir. Üçünde de ağırlıklar aynıdır.

Bu üç yerleşimin adı sunum kalıbı (serving pattern). Aralarındaki fark modelde değil, çıkarımın (inference) hangi anda ve hangi kapsamla yapıldığındadır. Bu ders üçünü aynı iş yükünde yan yana koşturur ve tek bir isabet sayısı yerine üç sayıyı ayrı ayrı yazar: isteğin geldiği anda yapılan iş, yanıtın dayandığı en yeni okumanın yaşı ve tahmin başına maliyet (cost per prediction).

  • ED41. Kaynak, hat ve model kurgudur ve ders içinde üretilir. Hiçbir sunum çatısı, çıkarım servisi, hızlandırıcı ya da bulut servisi çağrılmaz; üç kalıp da burada yazılır. Tohum 20260218.
  • ED42. Etiket dengesizdir: dağılım {0: 1752, 1: 448}, taban sınıf oranı 0,7964. Hiçbir isabet bu oranın ne kadar üstünde olduğu yazılmadan okunmaz. Sınama kümesi 600 satırdır, yani isabetin en küçük adımı 0,0017’dir.
  • ED43. Eğitim hattı bu kursta tek makinede ele alınır; bölüşüm ve karıştırma Dağıtık Veri İşleme kursunda ölçüldü ve tekrarlanmaz.
  • ED44. Bedel okunan satır olarak sayılır; ham milisaniye yazılmaz. Gecikme sınıf olarak yazılır: arama, istek anında tek bir saklanmış kaydın okunmasıdır; tarama, istek anında abonenin ve bölgesinin geçmişinin okunmasıdır.
  • ED45. Tazelik dönem olarak sayılır: yanıtın yaşı, en yeni okumanın tahmine yansıması için beklenen dönem sayısıdır.
  • ED46. Sunum ufku sınama dönemleridir — 2026-10, 2026-11, 2026-12 — ve her dönem iki yüz abone için bir istek gelir. Toplam 600 istek.
  • ED47. Toplu kalıp her dönem bir kez koşar. Bu bir seçimdir ve aşağıda süpürülür.

Üç Kalıp Yan Yana

İlk blok kaynağı, hattın tüketime kadarki üç aşamasını, öznitelik yolunu ve kurgu modeli kurar; sonra üç kalıbı aynı ağırlıklarla koşturur. Öznitelikler bir kez hesaplanır ve ağırlıktan bağımsızdır.

# KURGUDUR. Olcum aginin sayac okumalari , hattin ilk uc asamasi , oznitelik
# yolu ve uc agirlikli esik modeli ders icinde uretilir; hicbir ogrenme
# kitapligi , sunum catisi ya da cikarim servisi cagrilmaz. Tohum 20260218.
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


BOLGE = ["dogu", "bati", "kuzey", "guney", "merkez"]
TIP = ["mesken", "isyeri"]
DONEM = [f"2026-{a:02d}" for a in range(1, 13)]
ABONE = {}
for i in range(200):
    r = uretec(TOHUM + 37 * i)
    ABONE[f"A{i + 1:03d}"] = {"bolge": BOLGE[int(r() * 5)], "tip": TIP[int(r() * 2)],
                              "baslangic": 10000 + int(r() * 60000)}


def kaynak_uret():
    kayit = []
    for i, (ab, a) in enumerate(ABONE.items()):
        e = a["baslangic"]
        for d in DONEM:
            r = uretec(TOHUM + 101 * i + 7 * DONEM.index(d))
            e += 4 + int(r() * 46)
            kayit.append({"abone": ab, "donem": d, "bolge": a["bolge"], "tip": a["tip"],
                          "endeks": e, "birim": "m3"})
    return kayit


def a3_tuketim(kayit):
    tablo = {(k["abone"], k["donem"]): k for k in kayit}
    cikti = []
    for k in kayit:
        i = DONEM.index(k["donem"])
        onceki = tablo.get((k["abone"], DONEM[i - 1])) if i else None
        if onceki is not None:
            cikti.append(dict(k, m3=int(k["endeks"]) - int(onceki["endeks"])))
    return cikti


EGITIM, SINAMA, ESIK = DONEM[1:9], DONEM[9:], 40


def etiket(k):
    return 1 if k["m3"] > ESIK else 0


def oznitelikler(kayitlar, pencere=None, basamak=4):
    """Egitim yolu tam gecmisi gorur. Agirliktan bagimsiz , bir kez hesaplanir."""
    sirali = sorted(kayitlar, key=lambda k: DONEM.index(k["donem"]))
    ab, bo = {}, {}
    for k in sirali:
        ab.setdefault(k["abone"], []).append((DONEM.index(k["donem"]), k["m3"]))
        bo.setdefault(k["bolge"], []).append((DONEM.index(k["donem"]), k["m3"]))

    def ortalama(dizi, i):
        secili = [v for d, v in dizi if (d < i and (pencere is None or d >= i - pencere))]
        return round(sum(secili) / len(secili), basamak) if secili else 0.0

    return {(k["abone"], k["donem"]): {
        "abone_ort": ortalama(ab[k["abone"]], DONEM.index(k["donem"])),
        "bolge_ort": ortalama(bo[k["bolge"]], DONEM.index(k["donem"])),
        "isyeri": 1 if k["tip"] == "isyeri" else 0} for k in kayitlar}


IZGARA = [(a, b, c) for a in (0.6, 0.8, 1.0) for b in (0.0, 0.2, 0.4) for c in (0, 4, 8)]


def puan(o, w):
    return w[0] * o["abone_ort"] + w[1] * o["bolge_ort"] + w[2] * o["isyeri"]


def egit(kayitlar, oz):
    kume = [k for k in kayitlar if k["donem"] in EGITIM]
    en_iyi, en_iyi_w = -1.0, None
    for w in IZGARA:
        d = sum(1 for k in kume
                if (1 if puan(oz[(k["abone"], k["donem"])], w) > ESIK else 0) == etiket(k))
        if d / len(kume) > en_iyi:
            en_iyi, en_iyi_w = d / len(kume), w
    return {"agirlik": en_iyi_w, "egitim_satiri": len(kume), "aday": len(IZGARA)}


TUM = a3_tuketim(kaynak_uret())
OZ = oznitelikler(TUM)
M = egit(TUM, OZ)
W = M["agirlik"]
SUNUM, ISTEK = SINAMA, sorted(ABONE)


def toplu_kosum(kayitlar, donem, w):
    """Butun gecmis bir kez taranir , butun tahminler uretilip saklanir."""
    oz = oznitelikler(kayitlar)
    return ({k["abone"]: (1 if puan(oz[(k["abone"], k["donem"])], w) > ESIK else 0)
             for k in kayitlar if k["donem"] == donem}, len(kayitlar))


def cevrimici_istek(dz, abone, donem, w):
    """Istek aninda abonenin ve bolgesinin gecmisi taranir."""
    ab, bo = dz
    i, b = DONEM.index(donem), ab[abone][0]["bolge"]
    sa = [k["m3"] for k in ab[abone] if DONEM.index(k["donem"]) < i]
    sb = [k["m3"] for k in bo[b] if DONEM.index(k["donem"]) < i]
    o = {"abone_ort": round(sum(sa) / len(sa), 4) if sa else 0.0,
         "bolge_ort": round(sum(sb) / len(sb), 4) if sb else 0.0,
         "isyeri": 1 if ab[abone][0]["tip"] == "isyeri" else 0}
    return (1 if puan(o, w) > ESIK else 0), len(ab[abone]) + len(bo[b])


def akis_kosum(kayitlar, w):
    """Her okuma geldiginde durum artimli guncellenir ve tahmin tazelenir."""
    da, db, tah, okunan, tazeleme = {}, {}, {}, 0, 0
    for k in sorted(kayitlar, key=lambda k: (DONEM.index(k["donem"]), k["abone"])):
        okunan += 1
        a, b = k["abone"], k["bolge"]
        o = {"abone_ort": round(da[a][0] / da[a][1], 4) if a in da else 0.0,
             "bolge_ort": round(db[b][0] / db[b][1], 4) if b in db else 0.0,
             "isyeri": 1 if k["tip"] == "isyeri" else 0}
        tah[(a, k["donem"])] = 1 if puan(o, w) > ESIK else 0
        da.setdefault(a, [0, 0]); db.setdefault(b, [0, 0])
        da[a][0] += k["m3"]; da[a][1] += 1
        db[b][0] += k["m3"]; db[b][1] += 1
        tazeleme += 1
    return tah, okunan, tazeleme, len(da) + len(db)


ab, bo = {}, {}
for k in TUM:
    ab.setdefault(k["abone"], []).append(k)
    bo.setdefault(k["bolge"], []).append(k)
DZ = (ab, bo)

GERCEK = {(k["abone"], k["donem"]): etiket(k) for k in TUM if k["donem"] in SUNUM}
N = len(ISTEK) * len(SUNUM)


def isabet(t):
    return round(sum(1 for c in GERCEK if t[c] == GERCEK[c]) / N, 4)


TOPLU, ok_t = {}, 0
for d in SUNUM:
    t, o = toplu_kosum(TUM, d, W)
    ok_t += o
    for a in ISTEK:
        TOPLU[(a, d)] = t[a]

CEV, ok_c, en_az, en_cok = {}, 0, 10 ** 9, 0
for d in SUNUM:
    for a in ISTEK:
        p, o = cevrimici_istek(DZ, a, d, W)
        CEV[(a, d)], ok_c = p, ok_c + o
        en_az, en_cok = min(en_az, o), max(en_cok, o)

AKIS, ok_a, taz, durum = akis_kosum(TUM, W)
print(f"egitim satiri {M['egitim_satiri']} , agirlik {W} , aday {M['aday']}")
print(f"sunum ufku {len(SUNUM)} donem x {len(ISTEK)} abone = {N} istek")
print("kalip      istek aninda  yanit yasi  okunan satir  tahmin basina  isabet")
for adi, yas, ok, ia in (("toplu", 1, ok_t, isabet(TOPLU)),
                         ("cevrimici", 0, ok_c, isabet(CEV)),
                         ("akis", 0, ok_a, isabet(AKIS))):
    print(f"{adi:<9}  {'tarama' if adi == 'cevrimici' else 'arama':>12}  {yas:>10}"
          f"  {ok:>12}  {ok / N:>13.2f}  {ia}")
print(f"cevrimici istek basina okunan: en az {en_az} , en cok {en_cok}")
print(f"akis: tazeleme {taz} , kullanilan {N} , tutulan durum girdisi {durum}")
egitim satiri 1600 , agirlik (0.6, 0.4, 0) , aday 27
sunum ufku 3 donem x 200 abone = 600 istek
kalip      istek aninda  yanit yasi  okunan satir  tahmin basina  isabet
toplu             arama           1          6600          11.00  0.8067
cevrimici        tarama           0        278322         463.87  0.8067
akis              arama           0          2200           3.67  0.8067
cevrimici istek basina okunan: en az 352 , en cok 550
akis: tazeleme 2200 , kullanilan 600 , tutulan durum girdisi 205

Son sütun üç satırda da 0,8067. Aynı ağırlıklar, aynı öznitelik yolu, aynı 600 istek; üç kalıp da aynı yanıtları verir. Etiket dengesizdir ve taban sınıf oranı 0,7964’tür; sınama kümesinin kendi taban oranı da 0,8067’dir, yani bu kurulum kursun ilk dersinde yazıldığı gibi tabanın 0,0000 üstünde durur. Kalıp seçimi de onu değiştirmez ve çıktıya bakan bir gözlem hangi kalıbın koştuğunu söyleyemez.

Fark öbür sütunlarda durur. Çevrimiçi kalıp istek başına 352 ile 550 satır okur, ortalaması 463,87. Bunun neredeyse tamamı bölge geçmişidir; abonenin kendi geçmişi on bir satırdır. bolge_ort özniteliği tek bir abone için hesaplanamaz, bölgenin bütün abonelerini ister. Çevrimiçi çıkarımın (online inference) pahalı oluşu modelden değil, özniteliğin kapsamından gelir — bir tahmin başına kırk iki kat fazla satır okunmasının nedeni budur.

Toplu çıkarım (batch inference) aynı bölge ortalamasını bir kez hesaplayıp bölgedeki bütün abonelere paylaştırır: 6600 satır, 600 tahmin, tahmin başına 11,00. Karşılığında yanıtı bir dönem yaşlanır, çünkü iki koşum arasında gelen hiçbir okuma tahmine giremez. Akış kalıbı her satırı bir kez okur ve durumu artımlı günceller: 2200 satır, tahmin başına 3,67. Tablo onun bedelini göstermez; 2200 tazelemenin yalnız 600’ü kullanılır, 205 durum girdisi sürekli tutulur ve durum kaybolduğunda yeniden kurmak 2200 satırı baştan okumak demektir. Okunan satır sütunu akışın en ucuz göründüğü sütundur ve akışın bedeli tam olarak o sütunda yazmaz.

Bedel Hangi Paydayla Bölünüyor

Yanıtın bir dönem yaşlanması bir bedel gibi durur. İkinci blok önce onu ölçer: aynı istekleri gitgide daha eski bir koşumdan yanıtlar. Sonra tahmin başına maliyetin paydasını değiştirir.

# Bu blok ilk bloktaki TUM , OZ , W , SUNUM , ISTEK , CEV , ok_c , N ,
# puan , ESIK , DONEM ve isabet tanimlarini surdurur.
print("yanit yasi (donem)  degisen tahmin  isabet")
for g in range(0, 7):
    t = {}
    for d in SUNUM:
        j = max(DONEM.index(d) - g, 1)
        for a in ISTEK:
            t[(a, d)] = 1 if puan(OZ[(a, DONEM[j])], W) > ESIK else 0
    deg = sum(1 for c in t if t[c] != CEV[c])
    print(f"{g:>18}  {deg:>14}  {isabet(t)}")

uz = sorted(abs(puan(OZ[c], W) - ESIK) for c in CEV)
print(f"esik {ESIK} , karar puaninin esige uzakligi: en az {uz[0]:.4f}"
      f" , medyan {uz[len(uz) // 2]:.4f}")

print("\nkullanilan tahmin    toplu  cevrimici    akis  en ucuz  toplu kullanilmayan")
ort_c = ok_c / N
for u in (1, 2, 5, 20, 50, 200):
    s = [len(TUM) / u, ort_c, len(ISTEK) / u]
    print(f"{u:>17}  {s[0]:>7.2f}  {s[1]:>9.2f}  {s[2]:>6.2f}"
          f"  {('toplu', 'cevrimici', 'akis')[s.index(min(s))]:>7}  {len(ISTEK) - u:>19}")
print(f"toplu ile cevrimici {len(TUM) / ort_c:.2f} kullanilan tahminde esitlenir")
yanit yasi (donem)  degisen tahmin  isabet
                 0               0  0.8067
                 1               0  0.8067
                 2               0  0.8067
                 3               0  0.8067
                 4               0  0.8067
                 5               0  0.8067
                 6               0  0.8067
esik 40 , karar puaninin esige uzakligi: en az 7.6468 , medyan 13.6826

kullanilan tahmin    toplu  cevrimici    akis  en ucuz  toplu kullanilmayan
                1  2200.00     463.87  200.00     akis                  199
                2  1100.00     463.87  100.00     akis                  198
                5   440.00     463.87   40.00     akis                  195
               20   110.00     463.87   10.00     akis                  180
               50    44.00     463.87    4.00     akis                  150
              200    11.00     463.87    1.00     akis                    0
toplu ile cevrimici 4.74 kullanilan tahminde esitlenir

Bayatlık süpürmesinin sonucu tek bir sayıdır: yanıtın yaşı sıfırdan altı döneme çıkarken değişen tahmin 0 ve isabet 0,8067’de kalır. Bu iş yükünde bayatlığın ölçülebilir bir karşılığı yoktur ve buradan “toplu kalıp bedelsizdir” çıkarılmaz. Nedeni bir alt satırdadır: karar puanının eşiğe en yakın uzaklığı 7,6468, medyanı 13,6826. Kararlar eşikten uzak durur ve bir dönemlik ek geçmiş, on bir dönemlik kümülatif ortalamayı bu uzaklığı kapatacak kadar oynatmaz. Kararlar eşiğe yaklaştığında aynı bayatlık tahmini oynatır. Ölçülemeyen bedel yok sayılmaz; ölçülemediği ve hangi koşulda görüneceği yazılır — kursun ikinci iddiası burada bedel tarafından okunmuş hâlidir.

İkinci tablo tahmin başına maliyetin bir payda kararı olduğunu gösterir. Toplu kalıp bir koşumda 2200 satır okur ve iki yüz tahmin üretir; o tahminlerin kaçının gerçekten okunduğu kalıbın değil işin sorusudur. Tek tahmin kullanılıyorsa toplu kalıbın tahmin başına maliyeti 2200,00‘dir ve çevrimiçi kalıbın 463,87’sinin dört katından fazladır; iki kalıp 4,74 kullanılan tahminde eşitlenir. Son sütun toplu kalıbın bedelinin adıdır: bir tahmin kullanıldığında 199 tahmin üretilip hiç okunmaz.

Hangi görevin hangi kalıba dayandığı bu iki tablodan okunur. Dönem başında bütün abonelerin listelendiği iş toplu kalıba dayanır: payda 200’dür, bayatlık ölçülemez ve maliyet 11,00’e iner. Önceden bilinmeyen tek abonelik bir sorgu çevrimiçi kalıba dayanır: payda 1’dir ve toplu kalıp orada dört kattan fazla pahalıdır, üstelik listede olmayan bir anahtarı hiç yanıtlayamaz. Okumanın geldiği anda tetiklenmesi gereken iş yalnız akışla yapılır: akış 2200 tetikleme üretir, çevrimiçi kalıp yalnız istek geldiğinde 600 üretir ve hiç istek gelmezse hiç tetiklenmez, toplu kalıp ise 600’ü dönem başında ve bir dönem gecikmeli üretir.

Özet

  • Üç sunum kalıbı aynı 600 isteğe aynı yanıtları verir ve isabet üçünde de 0,8067’dir; taban sınıf oranı 0,7964, sınama kümesinin taban oranı 0,8067 ve bu kurulum onun 0,0000 üstünde. Kalıp seçimi bir isabet kararı değildir ve çıktıya bakan bir gözlem hangi kalıbın koştuğunu söyleyemez.
  • Fark üç sütundadır: istek anındaki gecikme sınıfı toplu ve akış kalıbında arama, çevrimiçi kalıpta 352 ile 550 satırlık tarama; yanıtın yaşı 1, 0 ve 0 dönem; tahmin başına okunan satır 11,00, 463,87 ve 3,67.
  • Çevrimiçi kalıbın kırk iki katlık farkı modelden değil bolge_ort özniteliğinin kapsamından gelir; abonenin kendi geçmişi on bir satır, bölgesininki 341 ile 539 satır arasındadır.
  • Yanıtın yaşı altı döneme çıkarıldığında değişen tahmin 0’dır; bunun nedeni kalıp değil, karar puanının eşiğe en az 7,6468 uzaklıkta durmasıdır. Ölçülemeyen bedel, ölçülmüş bir güvence değildir.
  • Tahmin başına maliyet paydaya bağlıdır: toplu kalıp bir tahmin kullanıldığında 2200,00, iki yüz tahmin kullanıldığında 11,00 verir ve çevrimiçi kalıpla 4,74 kullanılan tahminde eşitlenir.
  • Akış kalıbı okunan satırda en ucuzudur, ama 2200 tazelemenin 1600’ü kullanılmaz ve 205 durum girdisi sürekli tutulur; bu bedel okunan satır sütununda hiç görünmez.

Sonraki Adım

Kalıp seçildi, ama her kalıp içinde hâlâ tek bir soru yanıtsızdır: bir çağrı kaç isteği birlikte taşımalıdır. Toplu kalıpta bu, koşumun kaç tahmin ürettiğidir; çevrimiçi kalıpta ise gelen istekleri biriktirip bir arada işlemek demektir ve biriktirmenin bedeli, ilk gelen isteğin beklemesidir. Sonraki ders aynı istekleri toplu boyut bir ile altmış dört arasında koşturur, tahmin başına maliyetin düşüşünü bekleyen isteğin gecikmesiyle yan yana sayar ve aynı süpürmeyi iki hızlandırıcı sınıfında tekrarlar.

İ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