---
title: 'Model Kayıt Defteri'
source: 'https://academia.sh/tr/kurslar/mlops-temelleri/model-kayit-defteri'
course: 'MLOps Temelleri'
language: tr
updated: '2026-08-17T18:08:52+00:00'
license: 'CC BY-SA 4.0'
---

# Model Kayıt Defteri

Bir modelin yaşam döngüsü aşamalarının ve her aşama geçişinin hangi koşuma bağlandığının sayılması: on altı koşumluk bir kayıtta yalnız iki ayrı ağırlık üçlüsü çıkıyor, üretimdeki üçlüyü on iki koşum birebir taşıyor ve bu on iki koşum kendi sonucunu 0,7950 ile 0,8067 gibi iki ayrı sayıyla bildiriyor. Kayıt defteri olmadan üretimdeki modelin hangi koşumdan geldiğini bulmak için on altı kaydın tamamına bakılıyor ve arama on iki adaydan aşağı inmiyor, geri alınacak önceki üretim koşumu ise hiç bulunamıyor; dört aşama ve beş geçişi koşum kimliğine bağlayan defterle iki sorunun ikisi de tek kayıt okunarak yanıtlanıyor ve defterin bedeli yirmi bir kayıttır.

Beş kalem sabitlendi ve üç koşum artık aynı sayıyı veriyor. Yeniden üretilebilirlik sorusunun
yanıtı budur, ama bir soruyu daha açar: elde duran model **hangi koşumdan** geldi. Eğitilmiş bir
modelin taşıdığı tek şey ağırlıklarıdır; ağırlıklar kendilerini üreten veri sürümünü, öznitelik
penceresini ya da sınama bölünmesini içlerinde taşımaz.

Bu ders o boşluğu ölçer. Bir modelin denenmekte mi, sınanmakta mı yoksa iş görmekte mi olduğu
bilgisi ve o duruma **hangi koşumla** gelindiği, modelin dosyasında değil ayrı bir kayıtta durur.
**Model kayıt defteri (model registry)** tam olarak bu kayıttır: aşamaları ve aşamalar arasındaki
geçişleri koşum kimliğine bağlar. Ölçülecek olan, o bağın bir soruya yanıt verirken kaç kayıt
okuttuğudur.

- **YU57.** Kaynak, hattın ilk üç aşaması, kurgu model ve kayıt defteri **kurgudur**; gerçek bir
  öğrenme kitaplığı ya da kayıt defteri ürünü çağrılmaz. Tohum **20260218**.
- **YU58.** **Koşum**, belirli ayarlarla yürütülmüş tek bir eğitim işidir ve bir kimlik taşır.
  **Model** o koşumun ürettiği ağırlık üçlüsüdür ve kimlik taşımaz.
- **YU59.** **Aşama**, modelin yaşam döngüsündeki durumudur. Burada dördü sayılır: `aday`,
  `sinamada`, `uretimde`, `arsivde`. **Geçiş**, bir modeli bir aşamadan öbürüne taşıyan kayıttır ve
  **bir koşum kimliğine bağlıdır**.
- **YU60.** Taban çizgisi **deftersiz kurulumdur**: koşumlar bir yerde kayıtlıdır, ama hiçbir aşama
  bir koşuma bağlı değildir. Bir aşamadaki modelden koşuma gitmenin tek yolu **ağırlığı
  eşleştirmektir**.
- **YU61.** Etiket dengesizdir: `{0: 1752, 1: 448}`, **taban sınıf oranı 0,7964**, sınama kümesinde
  **0,8067**. İsabet tek başına okunduğunda yanıltır; bu derste iki koşum aynı modeli taşıyıp
  farklı sayı bildirecektir.
- **YU62.** Koşum kaydının kendisi ve veri sürümleme bu konunun önceki derslerinde ele alındı;
  burada eklenen tek şey **aşama geçişinin koşuma bağlanmasıdır**. Soyağacı yordamı Veri
  Mühendisliğine Giriş kursunda ölçüldü ve **tekrarlanmaz**.
- **YU63.** Kayıt defteri **on altı koşumluk** bir kayıt üzerinde kurulur. Koşumlar dört öznitelik
  penceresi, iki ızgara boyu ve iki sınama bölünmesinin birleşimidir.
- **YU64.** Çözünürlük: tam sınama kümesi **600 satır**, adım **1/600 = 0,0017**. Bu derste aynı
  ağırlığın bildirdiği iki sayı arasındaki fark **0,0117**, yani adımın altı katından büyük.

## Modelin Kimliği Yoktur

Eğitilmiş bir model bir yordamın çıktısıdır ve çıktı, kendisini üreten yordamı içermez. Burada
model üç sayıdan ibarettir; gerçek bir kurulumda çok daha büyük olur, ama durum değişmez. Modelin
içinde hangi veriyle eğitildiği, hangi öznitelik penceresinin seçildiği ya da sınamanın hangi
dönemler üzerinde yapıldığı yazmaz. Bu bilgiyi taşıyan tek şey **koşum kaydıdır**, ve model ile
koşum arasındaki bağ ayrıca kurulmadıkça yoktur.

Bağ kurulmadığında yapılabilecek tek şey **eşleştirmedir**: elde duran ağırlıkları koşum kaydındaki
ağırlıklarla karşılaştırıp hangisinin tuttuğuna bakmak. Bu yöntemin sessiz bir varsayımı vardır —
her koşumun farklı bir model ürettiği. Aşağıdaki bloklar o varsayımı sınayacaktır. İlk blok kaynağı,
hattın modele bakan ilk üç aşamasını ve kurgu modeli kurar.

```python
# KURGUDUR. Olcum aginin sayac okumalari, hattin ilk uc asamasi ve esik tabanli
# model ders icinde tanimlanir; gercek bir ogrenme kitapligi ya da model kayit
# defteri urunu cagrilmaz. Defter de ders icinde bir kayit listesi olarak kurulur.
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):
    """Donem farkindan tuketim. Onceki donem yoksa satir hesaplanamaz."""
    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 = DONEM[1:9]        # 2026-02 .. 2026-09
SINAMA = DONEM[9:]         # 2026-10 .. 2026-12
ESIK = 40                  # bu m3 uzerindeki tuketim "yuksek" sayilir


def satirlar():
    v, _ = a1_ayikla(kaynak_uret())
    v, _ = a2_tekille(v)
    v, _ = a3_tuketim(v)
    return v


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


def oznitelikler(kayitlar, pencere=None, basamak=4):
    """pencere=None -> tam gecmis; pencere=n -> son n donem."""
    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

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


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, izgara=None, esik=ESIK, donemler=None):
    izgara = IZGARA if izgara is None else izgara
    donemler = EGITIM if donemler is None else donemler
    kume = [k for k in kayitlar if k["donem"] in donemler]
    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))
        o = d / len(kume)
        if o > en_iyi:
            en_iyi, en_iyi_w = o, w
    return {"agirlik": en_iyi_w, "egitim_isabeti": round(en_iyi, 4),
            "aday": len(izgara), "egitim_satiri": len(kume)}


def sina(kayitlar, model, oz, esik=ESIK, donemler=None):
    donemler = SINAMA if donemler is None else donemler
    kume = [k for k in kayitlar if k["donem"] in donemler]
    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)
```

## Aynı Ağırlığı Üreten On İki Koşum

İkinci blok on altı koşumluk bir kayıt üretir. Koşumlar birbirinden gerçekten farklıdır: dört ayrı
öznitelik penceresi, iki ayrı ızgara boyu ve iki ayrı sınama bölünmesi denenmiştir. Sonra kayıt
üretilen ağırlık üçlüsüne ve bildirilen sınama isabetine göre gruplanır.

```python
import collections

S = satirlar()
dag = collections.Counter(etiket(k) for k in S)
print("satir:", len(S), " etiket dagilimi:", dict(sorted(dag.items())),
      " taban sinif orani:", round(dag[0] / len(S), 4),
      " sinamada:", round(sum(1 for k in S if k["donem"] in SINAMA and etiket(k) == 0)
                          / sum(1 for k in S if k["donem"] in SINAMA), 4))

# Kosum kaydi: dort oznitelik penceresi x iki izgara boyu x iki sinama bolunmesi.
OZ = {p: oznitelikler(S, p) for p in (None, 1, 2, 3)}
KAYIT = []
for p in (None, 1, 2, 3):
    for aday in (27, 21):
        for don in (SINAMA, DONEM[10:]):
            m = egit(S, OZ[p], IZGARA[:aday])
            KAYIT.append({"kimlik": f"K{len(KAYIT) + 1:02d}", "pencere": p, "aday": aday,
                          "donem": len(don), "agirlik": m["agirlik"],
                          "sinama": sina(S, m, OZ[p], donemler=don)})

grup = {}
for k in KAYIT:
    grup.setdefault((k["agirlik"], k["sinama"]), []).append(k["kimlik"])
print("\nkosum:", len(KAYIT), " farkli agirlik uclusu:",
      len(set(k["agirlik"] for k in KAYIT)), " farkli (agirlik , sinama):", len(grup))
print(f"{'agirlik':<16}{'sinama':>8}{'kosum':>7}   kimlikler")
for (w, s), ks in grup.items():
    print(f"{str(w):<16}{s:>8.4f}{len(ks):>7}   {','.join(ks)}")
```

```
satir: 2200  etiket dagilimi: {0: 1752, 1: 448}  taban sinif orani: 0.7964  sinamada: 0.8067

kosum: 16  farkli agirlik uclusu: 2  farkli (agirlik , sinama): 4
agirlik           sinama  kosum   kimlikler
(0.6, 0.4, 0)     0.8067      6   K01,K03,K09,K11,K13,K15
(0.6, 0.4, 0)     0.7950      6   K02,K04,K10,K12,K14,K16
(0.6, 0.0, 0)     0.8067      2   K05,K07
(0.6, 0.0, 0)     0.7950      2   K06,K08
```

On altı ayrı koşum yalnız **iki ayrı ağırlık üçlüsü** üretiyor. Eşleştirmenin varsayımı burada
çöker: elde `(0.6, 0.4, 0)` duran biri, koşum kaydının tamamını okusa bile **on iki aday** bulur ve
arama daha aşağı inmez. Bu bir kusur değil, aramanın doğal sonucudur — sonlu bir ızgarada gezinen
her eğitim işi aynı adaya varabilir ve çoğu zaman varır.

Tablonun taşıdığı ikinci sayı daha ağırdır. Aynı `(0.6, 0.4, 0)` üçlüsünü taşıyan on iki koşumun
altısı sonucunu **0,8067**, altısı **0,7950** diye bildiriyor. İkisi de doğrudur; farkı yapan şey
modelin kendisi değil, koşumun sınamayı **kaç dönem üzerinde** yaptığıdır. Yani üretimdeki model
için "isabeti neydi" diye sorulduğunda, ağırlıklardan gidilerek verilecek yanıt 0,0117 genişliğinde
bir aralıktır ve bu çözünürlüğün altı katından büyüktür. Etiket dengesizliği bunu daha da
sakıncalı kılar: sınamada taban sınıf oranı 0,8067 olduğu için iki sayı da çoğunluk sınıfının
bandındadır ve aradaki farkı bir başarım farkı sanmak yanıltıcıdır.

## Aşamalar ve Geçişlerin Bağlandığı Koşum

Kayıt defteri modelin dosyasına dokunmaz; onun yerine **ayrı bir kayıt** tutar ve bu kayıt bir
aşamayı bir koşum kimliğine bağlar. Dört aşama ile bunlar arasındaki geçişler dizisi defterin
içeriğidir; her geçiş satırı hangi koşumun hangi aşamaya taşındığını söyler. Üçüncü blok defteri
kurar ve iki soruyu iki kurulumda yanıtlar.

```python
# Model kayit defteri: dort asama ve asamalar arasi gecisler. Her gecis BIR KOSUMA baglidir.
ASAMA = ("aday", "sinamada", "uretimde", "arsivde")
GECIS = [("K03", "aday", "sinamada"), ("K03", "sinamada", "uretimde"),
         ("K11", "aday", "sinamada"), ("K11", "sinamada", "uretimde"),
         ("K03", "uretimde", "arsivde")]
GUNCEL = {}
for kim, _, hedef in GECIS:
    GUNCEL[hedef] = kim
URETIMDEKI = next(k for k in KAYIT if k["kimlik"] == GUNCEL["uretimde"])["agirlik"]

esleyen = [k for k in KAYIT if k["agirlik"] == URETIMDEKI]
skor = sorted(set(k["sinama"] for k in esleyen))
print("uretimdeki agirlik:", URETIMDEKI, " defterdeki gecis:", len(GECIS))
print(f"\n{'soru':<34}{'defterisiz bakilan':>20}{'defterisiz yanit':>19}"
      f"{'defterli':>10}{'yanit':>7}")
print(f"{'bu agirlik hangi kosumdan geldi':<34}{len(KAYIT):>20}"
      f"{str(len(esleyen)) + ' aday':>19}{1:>10}{GUNCEL['uretimde']:>7}")
print(f"{'geri alinacak: onceki uretim':<34}{len(KAYIT):>20}{'yok':>19}"
      f"{1:>10}{GUNCEL['arsivde']:>7}")
print("\nayni agirligi tasiyan kosum:", len(esleyen), " bildirdikleri farkli sinama:",
      len(skor), "->", " .. ".join(f"{x:.4f}" for x in skor),
      " fark:", round(skor[-1] - skor[0], 4))
print("defterin bedeli: kosum kaydi", len(KAYIT), "+ gecis kaydi", len(GECIS),
      "=", len(KAYIT) + len(GECIS), "kayit ;", "asama:", len(ASAMA))
```

```
uretimdeki agirlik: (0.6, 0.4, 0)  defterdeki gecis: 5

soru                                defterisiz bakilan   defterisiz yanit  defterli  yanit
bu agirlik hangi kosumdan geldi                     16            12 aday         1    K11
geri alinacak: onceki uretim                        16                yok         1    K03

ayni agirligi tasiyan kosum: 12  bildirdikleri farkli sinama: 2 -> 0.7950 .. 0.8067  fark: 0.0117
defterin bedeli: kosum kaydi 16 + gecis kaydi 5 = 21 kayit ; asama: 4
```

Birinci satır aşama geçişinin ne kazandırdığını gösterir. Deftersiz kurulumda on altı kaydın
tamamına bakılır ve elde on iki aday kalır; arama bakılan kayıt sayısı kadar iş yapıp **hiç
daralmaz**. Defterli kurulumda `uretimde` aşaması bir koşum kimliğine bağlı olduğu için tek kayıt
okunur ve yanıt `K11`'dir. Kazanılan şey on beş kayıtlık bir tasarruf değildir; kazanılan şey
**tekil bir yanıttır**, ve deftersiz kurulumda o yanıt kayıt sayısı ne olursa olsun elde edilemez.

İkinci satır daha keskindir. Geri alma gerektiğinde sorulan soru "önceki üretim koşumu hangisiydi"
olur ve deftersiz kurulumda bunun yanıtı yalnız zor değil, **yoktur**: eldeki tek şey şu anda
yerinde duran ağırlıklardır ve önceki modelin ağırlıkları yerine yazılmıştır. Defterde ise
`K03`'ün `uretimde` aşamasından `arsivde` aşamasına geçtiği kayıtlıdır; geri dönülecek koşum tek
kayıtta okunur. Aşamaların değeri modelin nerede olduğunu söylemelerinden çok, **nereden geldiğini
ve nereye dönüleceğini** söylemelerindedir.

Defterin bedeli son satırdadır ve mütevazıdır: on altı koşum kaydı ve beş geçiş kaydı, toplam
**21 kayıt**. Bu bedel modelin kendisine dokunmaz, ağırlıkları büyütmez, çıkarımı yavaşlatmaz;
yalnızca her aşama geçişinde bir satır yazılmasını zorunlu kılar. Yazılmadığında kaybedilen şey de
tam olarak bu dersin ölçtüğü şeydir: üretimdeki sayının kime ait olduğu.

## Özet

- Eğitilmiş bir model yalnız ağırlıklarını taşır; kendisini üreten veri sürümünü, öznitelik
  penceresini ya da sınama bölünmesini içinde taşımaz, dolayısıyla kimliği yoktur.
- On altı ayrı koşum yalnız iki ayrı ağırlık üçlüsü üretiyor; üretimdeki üçlüyü **12 koşum** birebir
  taşıdığı için ağırlık eşleştirerek yapılan arama tekil bir yanıta hiç ulaşmıyor.
- Aynı üçlüyü taşıyan koşumlar sonuçlarını **0,7950** ve **0,8067** diye bildiriyor; aradaki 0,0117
  çözünürlüğün altı katından büyüktür ve etiket dengesizliği (taban oranı 0,7964, sınamada 0,8067)
  bu farkı başarım farkı sanmayı kolaylaştırır.
- Dört aşama ve beş geçişi koşum kimliğine bağlayan defterle "üretimdeki model hangi koşumdan
  geldi" sorusu **tek kayıtta** yanıtlanıyor, deftersiz kurulumda 16 kayıt okunup 12 aday kalıyor.
- Geri alma sorusunun deftersiz kurulumda yanıtı yoktur; defterde arşiv geçişi tek kayıtta önceki
  üretim koşumunu veriyor ve defterin toplam bedeli 21 kayıttır.

## Sonraki Adım

Altı derste model **yeniden üretilebilir** kılındı. Koşumun kendisi kaydedildi ve sürümlendi, aynı
ada verilen iki farklı içerik ayrıldı, öznitelik iki yerde iki kez hesaplanmaktan çıkıp tek yerde
hesaplanır oldu, hangi kalemin sabitlenmesinin üç koşumu aynılaştırdığı sayıldı ve her aşama
geçişi bir koşum kimliğine bağlandı. Artık üretimde duran bir sayının kime ait olduğu ve nasıl
yeniden elde edileceği yazılıdır.

Yazılı olmayan tek şey, bu modelin **oraya nasıl gideceğidir**. Altı dersin hiçbirinde eğitimin
kendisi uçtan uca bir hat olarak kurulmadı, hiçbir kapı yeni bir veri sürümünün ya da düşen bir
ölçütün yayına çıkmasını durdurmadı, ve model bir çağıranın kullanabileceği bir arayüz olarak hiç
paketlenmedi. Sonraki konu bu üç boşluğu sırayla kapatır: eğitim hattının adımlarını ve uçtan uca
yeniden koşturulabilirliğini sayar, kod, veri ve model kapılarının hangi bozulmayı durdurduğunu
ölçer, ve arayüz sözleşmesi yazılmadığında kaç çağıranın kırıldığını yazar.
