---
title: 'Model Paketleme'
source: 'https://academia.sh/tr/kurslar/mlops-temelleri/model-paketleme'
course: 'MLOps Temelleri'
language: tr
updated: '2026-08-17T18:08:53+00:00'
license: 'CC BY-SA 4.0'
---

# Model Paketleme

Eğitilen modelin ağırlığı, eşiği ve arayüz bildirimiyle tek bir birim hâline getirilmesi ve sözleşme yazılmadığında kırılan çağıranın sayılması: üç çağıranın 1800 çağrısında alan adı değiştiğinde düşen çağrı 600'den 1200'e çıkıyor, eşik alanı paketten düştüğünde hiçbir çağrı düşmüyor ama geçen 1200 çağrının 1200'ü birden yanıt değiştiriyor; yalnız girdi alanlarını bildiren sözleşme üç sürümün ikisini yakalarken çıktıyı ve parametreyi de bildiren sözleşme üçünü de yayın öncesinde yakalıyor ve bunun için 1800 çağrı yerine 3 örnek kayıt okuyor; etiket dağılımı 1752'ye 448, taban sınıf oranı 0,7964 ve modelin sınama isabeti 0,8067 ile sınama kümesindeki taban oranının birebir kendisi.

Bir önceki dersin kapılarından geçen koşum artık bir model üretmiş sayılıyordu, ama üretilen şeyin ne
olduğu hâlâ yazılmamıştı. Model üç ağırlıktan ve bir eşikten ibaret bir sözlüktü; onu çağıran taraf
alanların adını, türünü ve sırasını **tahmin ederek** kullanıyordu.

Bu ders o sözlüğü bir **pakete** çevirir. Paketleme, ağırlığın yanına çağıranın bilmek zorunda olduğu
her şeyi koymaktır: hangi alanlar hangi türle beklenir, hangi parametre pakette taşınır, karşılığında
hangi alan döner. Bu bildirime **arayüz sözleşmesi** denir. Dersin sorusu, sözleşme yazılmadığında
kimin kırıldığıdır: alan adı ya da tür değiştiğinde kaç çağrı düşüyor, kaçı hiç düşmeden yanlış
yanıt veriyor ve sözleşmeyle bunların kaçı **yayın öncesi** yakalanıyor.

- **ED21.** Kaynak, hat, model ve paket **kurgudur**. **Hiçbir paketleme biçimi, kap çalışma zamanı,
  sunum çatısı ya da öğrenme kitaplığı adı yazılmaz.** Tohum **20260218**.
- **ED22.** Üretici ile tüketici arasındaki **veri** şeması ve şema değişiminin kimi kırdığı Veri
  Mühendisliğine Giriş kursunda ölçüldü ve **tekrarlanmaz**. Buradaki sözleşme verinin değil,
  **modelin arayüzünün** sözleşmesidir.
- **ED23.** Paket dört şey taşır: **ağırlık**, **eşik**, **girdi alanlarının bildirimi** ve **çıktı
  alanının adı**. Çalışma zamanı, kaynak ayrımı ve dağıtım biçimi bu dersin dışındadır.
- **ED24.** Bir çağrı **düşmüş** sayılır: paketin beklediği alan kayıtta yoksa ya da alanın türü
  aritmetiğe girmiyorsa. Kayıtta bulunan ve türü uyan her çağrı **geçer**.
- **ED25.** Üç çağıran vardır ve üçü de aynı **600** sınama satırını gönderir; toplam **1800** çağrı.
- **ED26.** Çağıranlar üç noktada ayrışır: biri alan adlarını **paketin bildiriminden okur**, biri
  adları **kendi kodunda sabitlemiştir**, biri adları sabitlemiştir ve bir alanı **metin** taşır.
- **ED27.** Sözleşme yayımlanmış arayüzdür; hem paket hem çağıran **ona** uyar. İki biçimi
  karşılaştırılır: yalnız girdiyi kapsayan ve çıktıyı ile parametreyi de kapsayan.
- **ED28.** Etiket dağılımı **dengesizdir**; taban sınıf oranı bu derste de yazılır.
- **ED29.** Taban çizgisi **sözleşmesiz paketlemedir**: bildirim yok, yayın öncesi doğrulama yok.
- **ED30.** Çözünürlük: sınama kümesi **600 satır**, isabetin adımı **0,0017**; çağrı sayımının adımı
  **1 çağrı**.
- **ED31.** Süre ham milisaniye olarak yazılmaz; ölçü **çağrı**, **kayıt** ve **bildirim**dir.

## Paketin İçinde Ne Var

İlk blok kaynağı, hattın ilk üç aşamasını ve modeli kurar; hiçbiri bu derse özgü değildir.

```python
# KURGUDUR. Kaynak, hat, model ve paket ders icinde tanimlanir; gercek bir
# ogrenme kitapligi, paketleme bicimi ya da calisma zamani cagrilmaz.
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 a1_ayikla(kayit):
    ZOR = ("abone", "donem", "bolge", "endeks", "birim")
    tut = [k for k in kayit if all(a in k for a in ZOR)]
    return tut, len(kayit) - len(tut)


def a2_tekille(kayit):
    gor, tut = set(), []
    for k in kayit:
        ad = (k["abone"], k["donem"])
        if ad in gor:
            continue
        gor.add(ad)
        tut.append(k)
    return tut, len(kayit) - len(tut)


def a3_tuketim(kayit):
    tablo = {(k["abone"], k["donem"]): k for k in kayit}
    cikti, dusen = [], 0
    for k in kayit:
        i = DONEM.index(k["donem"])
        if i == 0:
            continue
        onceki = tablo.get((k["abone"], DONEM[i - 1]))
        if onceki is None:
            dusen += 1
            continue
        try:
            f = int(k["endeks"]) - int(onceki["endeks"])
        except (TypeError, ValueError):
            dusen += 1
            continue
        cikti.append(dict(k, m3=f))
    return cikti, dusen


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):
    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_isabeti": round(en_iyi, 4),
            "egitim_satiri": len(kume)}


def sina(kayitlar, model, oz):
    kume = [k for k in kayitlar if k["donem"] in SINAMA]
    d = sum(1 for k in kume
            if (1 if puan(oz[(k["abone"], k["donem"])], model["agirlik"]) > ESIK else 0)
            == etiket(k))
    return round(d / len(kume), 4)
```

İkinci blok modeli paketler ve üç sürümünü kurar. `v1` yayındaki paket, `v2` bir girdi alanının adını
değiştirmiş paket, `v3` ise eşik alanını **hiç taşımayan** pakettir. Üç çağıran aynı 600 satırı
gönderir ve düşen çağrı sayılır.

```python
# ---- Paketleme: agirlik , esik ve arayuz bildirimi tek bir birimde
KAYNAK = kaynak_uret()
V, _ = a1_ayikla(KAYNAK)
V, _ = a2_tekille(V)
SATIR, _ = a3_tuketim(V)
OZ = oznitelikler(SATIR)
MODEL = egit(SATIR, OZ)
SINAMA_KUME = [k for k in SATIR if k["donem"] in SINAMA]
DAGILIM = {e: sum(1 for k in SATIR if etiket(k) == e) for e in (0, 1)}
TABAN_S = round(sum(1 for k in SINAMA_KUME if etiket(k) == 0) / len(SINAMA_KUME), 4)
print("etiket dagilimi:", DAGILIM, " taban sinif orani:", round(DAGILIM[0] / len(SATIR), 4))
print("agirlik:", MODEL["agirlik"], " egitim satiri:", MODEL["egitim_satiri"],
      " sinama satiri:", len(SINAMA_KUME),
      f" sinama isabeti: {sina(SATIR, MODEL, OZ):.4f}  sinama taban orani: {TABAN_S:.4f}")

PAKET_V1 = {"agirlik": MODEL["agirlik"], "esik": ESIK, "cikti": "yuksek",
            "girdi": ("abone_ort", "bolge_ort", "isyeri")}
PAKET_V2 = dict(PAKET_V1, girdi=("abone_ortalamasi", "bolge_ort", "isyeri"))
PAKET_V3 = {a: v for a, v in PAKET_V1.items() if a != "esik"}
SURUM = [("v1 basvuru", PAKET_V1), ("v2 alan adi", PAKET_V2), ("v3 esik yok", PAKET_V3)]
VARSAYILAN_ESIK = 0


def cagir(paket, kayit):
    w, g = paket["agirlik"], paket["girdi"]
    o = {a: kayit[a] for a in g}                                # eksik alan -> KeyError
    p = w[0] * o[g[0]] + w[1] * o[g[1]] + w[2] * o[g[2]]        # tur uyusmazligi -> TypeError
    return {paket["cikti"]: 1 if p > paket.get("esik", VARSAYILAN_ESIK) else 0}


def c_uyarlanan(paket, o):
    """Alan adlarini paketin bildiriminden okur."""
    return dict(zip(paket["girdi"], (o["abone_ort"], o["bolge_ort"], o["isyeri"])))


def c_sabit_ad(paket, o):
    """Alan adlarini kendi kodunda sabitlemis."""
    return {"abone_ort": o["abone_ort"], "bolge_ort": o["bolge_ort"], "isyeri": o["isyeri"]}


def c_sabit_tur(paket, o):
    """Adlari sabitlemis ve isyeri alanini metin tasiyor."""
    return dict(c_sabit_ad(paket, o), isyeri=str(o["isyeri"]))


CAGIRAN = [("uyarlanan", c_uyarlanan), ("sabit_ad", c_sabit_ad), ("sabit_tur", c_sabit_tur)]
print(f"{'surum':<13}{'cagri':>7}{'dusen':>7}{'gecen':>7}{'yuksek':>8}"
      + "".join(f"{a:>12}" for a, _ in CAGIRAN))
for sad, pk in SURUM:
    dusen, gecen, yuksek, kirilan = 0, 0, 0, []
    for cad, cf in CAGIRAN:
        d = 0
        for k in SINAMA_KUME:
            try:
                yuksek += cagir(pk, cf(pk, OZ[(k["abone"], k["donem"])]))[pk["cikti"]]
                gecen += 1
            except (KeyError, TypeError):
                d += 1
        dusen += d
        kirilan.append(d)
    print(f"{sad:<13}{len(SINAMA_KUME) * 3:>7}{dusen:>7}{gecen:>7}{yuksek:>8}"
          + "".join(f"{x:>12}" for x in kirilan))
```

```
etiket dagilimi: {0: 1752, 1: 448}  taban sinif orani: 0.7964
agirlik: (0.6, 0.4, 0)  egitim satiri: 1600  sinama satiri: 600  sinama isabeti: 0.8067  sinama taban orani: 0.8067
surum          cagri  dusen  gecen  yuksek   uyarlanan    sabit_ad   sabit_tur
v1 basvuru      1800    600   1200       0           0           0         600
v2 alan adi     1800   1200    600       0           0         600         600
v3 esik yok     1800    600   1200    1200           0           0         600
```

## Sözleşme Yazılmadığında Kırılan Çağıran

İlk iki satır modelin kendisini yazar ve bu kursta her derste tekrarlanan uyarıyı taşır. Etiket
dağılımı **1752'ye 448**, yani taban sınıf oranı **0,7964**; sınama kümesinde bu oran **0,8067** ve
modelin sınama isabeti de **0,8067**. İsabet tek başına okunduğunda yanıltır: paketlenen model,
sınama kümesinde çoğunluk sınıfının payının **birebir kendisini** üretiyor. Aşağıdaki bütün çağrı
sayıları bu modelin çağrılarıdır.

Taban satırı **v1**'dir ve orada bile 1800 çağrının **600'ü** düşer. Kıran şey bir sürüm değişikliği
değil, baştan var olan bir **tür uyuşmazlığıdır**: `sabit_tur` çağıranı `isyeri` alanını metin
taşıyor ve puan hesabı aritmetiğe giremiyor. Sözleşmesiz kurulumda bu uyuşmazlık ancak üretimde,
çağrı çağrı ortaya çıkar.

**v2** satırı alan adı değişiminin bedelini verir. Paket `abone_ort` yerine `abone_ortalamasi`
beklemeye başlıyor ve düşen çağrı 600'den **1200**'e çıkıyor. Adları kendi kodunda sabitlemiş iki
çağıran birden kırılıyor, çünkü gönderdikleri kayıtta paketin aradığı alan yok. Ayakta kalan tek
çağıran, adları paketin bildiriminden **okuyan** çağırandır ve onun 600 çağrısının hepsi geçiyor. Bir
paketin alan adlarını bildirmesi ile çağıranların o bildirimi okuması ayrı iki karardır; ikincisi
olmadan birincisi işe yaramaz.

**v3** satırı en tehlikeli olanıdır ve düşen çağrı sayısına bakan hiçbir gözlem onu göremez. Eşik
alanı paketten çıkarılmıştır; çağıran alanı bulamayınca kendi öntanımlı değerine, yani **0**'a
düşüyor. Hiçbir çağrı düşmüyor: v3'te de v1'deki gibi **600** çağrı düşer, **1200** çağrı geçer.
Değişen tek sütun sonuncusudur. Geçen 1200 çağrının **1200'ü** birden "yüksek" yanıtı dönüyor, oysa
v1'de dönen yüksek sayısı **0**'dı. Model aynı, ağırlıklar aynı, çağıran aynı; **eksik tek bir
parametre yüzünden her yanıt tersine dönmüş** durumda. Hata kaydına düşen hiçbir satır yok.

## Sözleşmenin Yayın Öncesinde Yakaladığı

Üçüncü blok sözleşmeyi yazar. Sözleşme **yayımlanmış arayüzdür**: hem paket hem çağıran ona uyar,
ikisi birbirine değil sözleşmeye bakar. İki biçimi karşılaştırılır: yalnız girdi alanlarını
bildiren sözleşme ile çıktıyı ve parametreyi de bildiren sözleşme.

```python
# ---- Arayuz sozlesmesi: yayimlanmis arayuz. Paket de cagiran da buna uyar.
TUR = {"ondalik": float, "tamsayi": int}
SOZLESME_GIRDI = {"girdi": {"abone_ort": "ondalik", "bolge_ort": "ondalik",
                            "isyeri": "tamsayi"}}
SOZLESME_TAM = dict(SOZLESME_GIRDI, cikti="yuksek", parametre=("esik",))


def dogrula(sozlesme, paket, ornekler):
    bulgu = []
    if set(paket["girdi"]) != set(sozlesme["girdi"]):
        bulgu.append("paket: girdi alan adi")
    if "cikti" in sozlesme and paket["cikti"] != sozlesme["cikti"]:
        bulgu.append("paket: cikti alan adi")
    for p in sozlesme.get("parametre", ()):
        if p not in paket:
            bulgu.append(f"paket: eksik parametre {p}")
    for ad, ornek in ornekler:
        for a, t in sozlesme["girdi"].items():
            if a not in ornek:
                bulgu.append(f"{ad}: eksik alan {a}")
            elif type(ornek[a]) is not TUR[t]:
                bulgu.append(f"{ad}: {a} turu")
    return bulgu


ORNEK = OZ[(SINAMA_KUME[0]["abone"], SINAMA_KUME[0]["donem"])]
print(f"{'surum':<13}{'girdi sozlesmesi':>18}{'tam sozlesme':>14}   tam sozlesmenin bulgusu")
for sad, pk in SURUM:
    ornekler = [(cad, cf(pk, ORNEK)) for cad, cf in CAGIRAN]
    g = dogrula(SOZLESME_GIRDI, pk, ornekler)
    t = dogrula(SOZLESME_TAM, pk, ornekler)
    print(f"{sad:<13}{len(g):>18}{len(t):>14}   {t}")
print("yayin oncesi okunan kayit:", len(CAGIRAN),
      " sozlesmesiz kurulumda cagri:", len(SINAMA_KUME) * 3,
      " sozlesmedeki bildirim:", len(SOZLESME_TAM["girdi"]) + 1 + len(SOZLESME_TAM["parametre"]))
```

```
surum          girdi sozlesmesi  tam sozlesme   tam sozlesmenin bulgusu
v1 basvuru                    1             1   ['sabit_tur: isyeri turu']
v2 alan adi                   3             3   ['paket: girdi alan adi', 'uyarlanan: eksik alan abone_ort', 'sabit_tur: isyeri turu']
v3 esik yok                   1             2   ['paket: eksik parametre esik', 'sabit_tur: isyeri turu']
yayin oncesi okunan kayit: 3  sozlesmesiz kurulumda cagri: 1800  sozlesmedeki bildirim: 5
```

Üç sürümün üçünde de düşen çağrı sayısı **0**'a iner, çünkü uyuşmazlık yayın öncesinde bulunur ve
sürüm yayımlanmaz. Ölçülen fark, uyuşmazlığın nerede görüldüğüdür: sözleşmesiz kurulumda **1800
çağrının** içinde, sözleşmeli kurulumda **3 örnek kayıtta**. Doğrulama çağıran başına tek kayıt okur.

v2 satırı sözleşmenin ne olduğunu da gösterir. Üç bulgunun biri pakete, ikisi çağıranlara aittir. Bu
bulgulardan biri şaşırtıcıdır: paketin bildirimini okuyan `uyarlanan` çağıranı üretimde **hiç
düşmüyordu**, ama sözleşmeye göre uyumsuz bir kayıt üretiyor. İkisi de doğrudur. O çağıran pakete
uyuyor, sözleşmeye uymuyor; çünkü paket sözleşmeden sapmış ve çağıran sapmayı sessizce izlemiş.
Sözleşmenin işi paketle çağıranı değil, **ikisini birden yayımlanmış arayüzle** karşılaştırmaktır.

v3 satırı ise sözleşmenin **kendisinin kusurlu olabileceğini** yazar. Yalnız girdi alanlarını bildiren
sözleşme v3'te tek bulgu üretir ve o bulgu ilgisizdir: `sabit_tur` çağıranının baştan beri var olan
tür uyuşmazlığı. Eşik alanının eksikliğini görmez, çünkü sözleşmesinde parametre diye bir kalem
yoktur. Çıktıyı ve parametreyi de bildiren sözleşme aynı sürümde **iki** bulgu üretir ve ikincisi
tam olarak eksik parametredir. Üç sürümün ikisini girdi sözleşmesi de yakalıyor; **1200 yanıtı
tersine çeviren sessiz kırılmayı yakalayan tek şey parametre bildirimidir.**

Sözleşmenin bedeli de sayılabilir. Beş bildirim yazılır: üç girdi alanı, bir çıktı alanı, bir
parametre. Her yayından önce bir doğrulama adımı eklenir ve o adım çağıran başına bir örnek kayıt
ister. Bir kalemi eksik bırakılan sözleşme, kapsamadığı yerde **ölçülmemiş bir güvence** verir:
girdi sözleşmesi v3'te yeşil görünüyordu.

Kursun kuralı arayüze de uygulanır: **yeniden üretilemeyen sayı bir ölçüm değil bir anıdır.** Bir
çağrının döndürdüğü yanıt, onu üreten arayüz yazılı değilse yeniden üretilemez; v3'ün 1200 yanıtı
bunun kanıtıdır.

## Özet

- Paketleme, ağırlığın yanına çağıranın bilmek zorunda olduğu her şeyi koymaktır: **ağırlık, eşik,
  girdi bildirimi ve çıktı alanı**. Bu bildirim arayüz sözleşmesidir.
- Etiket dağılımı **1752'ye 448**, taban sınıf oranı **0,7964**; paketlenen modelin sınama isabeti
  **0,8067** ile sınama kümesindeki taban oranının birebir kendisidir.
- Sözleşmesiz kurulumda taban sürümde bile 1800 çağrının **600'ü** düşer; alan adı değiştiğinde düşen
  çağrı **1200**'e çıkar ve ayakta kalan tek çağıran adları paketin bildiriminden okuyandır.
- Eşik alanı paketten düştüğünde **hiçbir çağrı düşmez**: 1200 çağrı geçer ve **1200'ü birden** yanıt
  değiştirir; v1'de 0 olan yüksek sayısı v3'te **1200** olur.
- Sözleşmeli kurulumda üç sürümde de düşen çağrı **0**'dır; uyuşmazlık 1800 çağrı yerine **3 örnek
  kayıtta** görülür ve bedeli **5 bildirim** ile bir doğrulama adımıdır.
- Yalnız girdiyi kapsayan sözleşme üç sürümün **ikisini** yakalar; sessiz kırılmayı yakalayan tek
  kalem **parametre bildirimidir**.

## Sonraki Adım

Bu üç derste model bir hatta bağlandı, kapılardan geçirildi ve bir arayüzle paketlendi. Üçünün de
ortak varsayımı tek cümleyle yazılabilir: çağıran ne zaman isterse çağırır ve yanıt hemen gelir. Bu
dersin 1800 çağrısı da öyle sayıldı, sanki hepsi aynı anda ve aynı bedelle koşuyormuş gibi. Oysa
paketlenmiş bir modeli **gecenin sonunda bir kerede on iki dönem için** koşturmakla, bir isteğin
ortasında **tek satır için** koşturmak aynı şey değildir. Sonraki ders sunum kalıplarını ayırır:
toplu, çevrimiçi ve akış tabanlı çıkarım. Ölçü, üç kalıbın **gecikme sınıfı**, **tazeliği** ve
**tahmin başına bedelidir**.
