---
title: 'Eğitim Hatları'
source: 'https://academia.sh/tr/kurslar/mlops-temelleri/egitim-hatlari'
course: 'MLOps Temelleri'
language: tr
updated: '2026-08-17T18:08:53+00:00'
license: 'CC BY-SA 4.0'
---

# Eğitim Hatları

Eğitilen bir modelin üretime çıkma yolunun ilk adımı olarak eğitim hattının sayılması: altı adımın düşürdüğü satır ayrı ayrı ölçülüyor ve tüketim adımı 200 satır kaybederken kendi sayacı 0 yazıyor, öznitelik adımı hiç satır düşürmeden 200 satırı geçmişsiz bırakıyor, bölünme 1600 ile 600'ü hiç satır düşürmeden ayırıyor; etiket dağılımı 1752'ye 448 ve taban sınıf oranı 0,7964 iken sınama kümesinde model 600 satırın 600'üne 0 diyor ve isabet 0,8067 ile taban sınıf oranının birebir kendisi oluyor; geç gelen 40 satır geri doldurulduğunda eğitim satırını 1520'den 1600'e çıkaran tek kurulum uçtan uca yeniden koşan hat oluyor ve yedi kurulumun yedisi de aynı 0,8067'yi rapor ediyor.

Bu kursun ilk altı dersi modeli **yeniden üretilebilir** kıldı: koşum kaydedildi, veri ile model
sürümlendi, eğitimdeki öznitelik yolu sunumdaki yolla karşılaştırıldı, ortam kalemleri sabitlendi ve
aşama geçişleri bir deftere bağlandı. Hepsinin ortak varsayımı tek cümleyle yazılabilir: model bir
kez eğitilmiştir ve mesele onu **yeniden** eğitebilmektir. Hiçbirinde eğitilen modelin **üretime
nasıl çıkacağı** sorulmadı.

Bu ders o sorunun ilk adımını açar. Veri Mühendisliğine Giriş kursundaki hat beş aşamada 2400
satırdan 2400'e, 2200'e, 55 özet hücresine ve 5 sunum değerine iniyordu. Model o zincirin **sonuna**
bağlanmaz; **üçüncü aşamanın çıktısına**, yani 2200 tüketim satırına bağlanır. Bu dersin sorusu, o
noktadan sonra gelen adımların elle koşturulan bir dizi olmaktan çıkıp uçtan uca koşturulabilir bir
**eğitim hattına** dönüştüğünde neyin ölçülebilir hâle geldiğidir.

- **ED1.** Kaynak, hat ve model **kurgudur**; gerçek bir öğrenme kitaplığı, deney takip düzeneği,
  öznitelik deposu ya da sunum çatısı çağrılmaz. Tohum **20260218**.
- **ED2.** Eğitim hattı bu kursta **tek makinede** ele alınır; küme boyutlandırma ve bölüşüm Dağıtık
  Veri İşleme kursunda ölçüldü ve tekrarlanmaz.
- **ED3.** Adımların birbirine bağlanması, çizge çözümü ve yeniden deneme yordamı Veri Hatları ve
  Orkestrasyon kursunda ölçüldü. Burada sorulan şey sıra değil, **her adımın satıra ne yaptığı**.
- **ED4.** Etiket: tüketimi **40 m3**'ü aşan satır "yüksek" sayılır. Dağılım **dengesizdir** ve her
  derste yazılır.
- **ED5.** Eğitim dönemleri `2026-02`–`2026-09`, sınama dönemleri `2026-10`–`2026-12`.
- **ED6.** Model üç ağırlıklı bir eşiktir; eğitim, 27 adaylık bir ızgarada aramaktır.
- **ED7.** Öznitelikler **bir kez** hesaplanır ve ağırlıktan bağımsızdır.
- **ED8.** Taban çizgisi **elle koşturulan adımlardır**: ara çıktılar elde durur, yeniden koşum
  kısmidir.
- **ED9.** Çözünürlük: sınama kümesi **600 satır**, isabetin en küçük adımı **0,0017**.
- **ED10.** Süre ham milisaniye olarak yazılmaz; ölçü **satır**, **adım** ve **dönem**dir.

## Eğitim Hattının Altı Adımı

İlk blok kaynağı, hattın ilk üç aşamasını ve modelin tarafını kurar. Hiçbiri bu derse özgü değildir:
ilk üçü veri hattından gelir, model tarafı bu kursun ortak tanımıdır.

```python
# KURGUDUR. Sayac okumalari, hat ve model ders icinde tanimlanir; gercek bir
# ogrenme kitapligi, deney takip duzenegi ya da sunum catisi 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


# ---- Veri hattinin ilk uc asamasi
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


# ---- Modelin tarafi
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):
    """pencere=None -> tam gecmis. Agirliktan bagimsizdir , 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_isabeti": round(en_iyi, 4),
            "aday": len(IZGARA), "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 hattı kurar. Altı adımın ilk üçü yukarıdaki aşamalardır; kalan üçü etiketleme, öznitelik
üretimi ve bölünmedir. `hat_kostur` her adımın girdisini, çıktısını ve **kendi düşen satır sayacını**
ayrı ayrı bildirir; `bastan` değeri verildiğinde ilk adımlar saklanan çıktıdan gelir ve yalnız kalanı
yeniden koşar.

```python
def h4_etiketle(v):
    return [dict(k, y=etiket(k)) for k in v], 0


def h5_oznitelik(v):
    oz = oznitelikler(v)
    return [dict(k, **oz[(k["abone"], k["donem"])]) for k in v], 0


def h6_bolunme(v):
    return {"egitim": [k for k in v if k["donem"] in EGITIM],
            "sinama": [k for k in v if k["donem"] in SINAMA]}, 0


ADIM = [("ayikla", a1_ayikla), ("tekille", a2_tekille), ("tuketim", a3_tuketim),
        ("etiketle", h4_etiketle), ("oznitelik", h5_oznitelik), ("bolunme", h6_bolunme)]


def uzunluk(v):
    return len(v) if isinstance(v, list) else sum(len(x) for x in v.values())


def hat_kostur(kaynak, bastan=0, saklanan=None):
    """bastan=p ise ilk p adim saklanan ciktidan gelir , kalani yeniden kosar."""
    veri = kaynak if bastan == 0 else saklanan[ADIM[bastan - 1][0]]
    ara, iz, islenen = dict(saklanan or {}), [], 0
    for i, (ad, f) in enumerate(ADIM):
        if i < bastan:
            continue
        g = uzunluk(veri)
        veri, sayac = f(veri)
        ara[ad], islenen = veri, islenen + g
        iz.append((ad, g, uzunluk(veri), sayac))
    return veri, iz, ara, islenen


def degerlendir(bolunmus):
    kume = bolunmus["egitim"] + bolunmus["sinama"]
    oz = {(k["abone"], k["donem"]): {a: k[a] for a in ("abone_ort", "bolge_ort", "isyeri")}
          for k in kume}
    m = egit(kume, oz)
    return m, sina(kume, m, oz), oz


KAYNAK = kaynak_uret()
BOLUNMUS, IZ, ARA, ISLENEN = hat_kostur(KAYNAK)
print(f"{'adim':<11}{'girdi':>7}{'cikti':>7}{'kaybolan':>10}{'adimin sayaci':>15}")
for ad, g, c, sayac in IZ:
    print(f"{ad:<11}{g:>7}{c:>7}{g - c:>10}{sayac:>15}")
print("bolunme:", {a: len(b) for a, b in BOLUNMUS.items()},
      " gecmissiz satir:", sum(1 for k in ARA["oznitelik"] if k["abone_ort"] == 0.0))
DAGILIM = {0: 0, 1: 0}
for k in ARA["etiketle"]:
    DAGILIM[k["y"]] += 1
print("etiket dagilimi:", DAGILIM, " taban sinif orani:",
      round(DAGILIM[0] / len(ARA["etiketle"]), 4), " islenen satir:", ISLENEN)
```

```
adim         girdi  cikti  kaybolan  adimin sayaci
ayikla        2400   2400         0              0
tekille       2400   2400         0              0
tuketim       2400   2200       200              0
etiketle      2200   2200         0              0
oznitelik     2200   2200         0              0
bolunme       2200   2200         0              0
bolunme: {'egitim': 1600, 'sinama': 600}  gecmissiz satir: 200
etiket dagilimi: {0: 1752, 1: 448}  taban sinif orani: 0.7964  islenen satir: 13800
```

Tablonun son iki sütunu birbiriyle çelişir ve çelişki tek bir adımdadır. Tüketim adımının girdisi
2400, çıktısı 2200; arada **200 satır** kayboluyor. Aynı adımın kendi sayacı **0** yazıyor. İkisi de
doğrudur: sayaç yalnızca **beklenmedik** düşüşü, yani önceki dönemi bulunamayan satırı sayar. İlk
dönemin 200 satırı ise tanımı gereği düşer, çünkü tüketim iki dönem arasındaki farktır. Bir adımın
düşen satır sayacına bakmak, o adımın kaç satır kaybettiğini söylemez; **girdi ile çıktı arasındaki
farkı ayrıca ölçmek gerekir.**

İkinci çelişki öznitelik adımındadır ve ters yönlüdür. Bu adım **hiç satır düşürmez**, ama
çıktısındaki **200 satırın abone ortalaması 0,0**'dır, çünkü `2026-02` satırlarının kendilerinden
önce hiçbir dönemi yoktur. Düşen satırı sıfır olan bir adım da veriyi bozabilir; hattın sayacı bunu
görmez.

Bölünme adımı ise gerçekten hiçbir satır düşürmez: 1600 eğitim ve 600 sınama satırı toplamda 2200
eder. Uçtan uca bir koşum altı adım boyunca **13800 satır** işler.

## Değerlendirme Adımının Ürettiği Sayı

Hattın yedinci ve sekizinci adımları eğitim ile değerlendirmedir. Üçüncü blok ikisini birden koşturur
ve çıkan sayıyı taban sınıf oranıyla yan yana koyar.

```python
MODEL, ISABET, OZTABLO = degerlendir(BOLUNMUS)
SINAMA_KUME = BOLUNMUS["sinama"]
TAHMIN = [1 if puan(OZTABLO[(k["abone"], k["donem"])], MODEL["agirlik"]) > ESIK else 0
          for k in SINAMA_KUME]
TABAN_S = sum(1 for k in SINAMA_KUME if k["y"] == 0) / len(SINAMA_KUME)
print("agirlik:", MODEL["agirlik"], " aday:", MODEL["aday"],
      " egitim satiri:", MODEL["egitim_satiri"], " egitim isabeti:", MODEL["egitim_isabeti"])
print(f"sinama isabeti: {ISABET:.4f}  sinama taban sinif orani: {TABAN_S:.4f}"
      f"  taban uzerindeki kazanc: {ISABET - TABAN_S:.4f}")
print("sinama tahmin dagilimi:", {0: TAHMIN.count(0), 1: TAHMIN.count(1)})
```

```
agirlik: (0.6, 0.4, 0)  aday: 27  egitim satiri: 1600  egitim isabeti: 0.7931
sinama isabeti: 0.8067  sinama taban sinif orani: 0.8067  taban uzerindeki kazanc: 0.0000
sinama tahmin dagilimi: {0: 600, 1: 0}
```

Hattın ürettiği sayı **0,8067**'dir ve tek başına okunduğunda iyi görünür. Yanındaki iki sayı onu
okunamaz hâle getirir. Etiket dağılımı **1752'ye 448**, yani taban sınıf oranı **0,7964**; sınama
kümesinde bu oran **0,8067**'dir. Modelin isabeti taban sınıf oranının **birebir kendisidir** ve
taban üzerindeki kazanç **0,0000**.

Son satır nedenini yazar: model 600 sınama satırının **600'üne** 0 diyor. Hiçbir satırı "yüksek"
saymıyor, dolayısıyla isabeti çoğunluk sınıfının payından ibaret. Sınama kümesinin çözünürlüğü
**0,0017**'dir; kazanç bu en küçük adımın altında bile değil, tam olarak **sıfırdır**. Bir eğitim
hattının değerlendirme adımı tek bir isabet basıyorsa, o hat ölçmüyor demektir.

## Uçtan Uca Yeniden Koşturmak

Kaynak değişmez bir şey değildir. `2026-07` döneminde 40 abonenin okuması **geç gelir** ve sonradan
geri doldurulur. Dördüncü blok önce eksik kaynakla koşar, sonra geri doldurulmuş kaynakla hattı
farklı noktalardan devam ettirir. `bayat adim` sayısı, saklanan eski çıktıdan gelen adım sayısıdır.

```python
GEC = [k for k in KAYNAK if not (k["donem"] == "2026-07" and k["abone"] <= "A040")]
BOL1, IZ1, ARA1, _ = hat_kostur(GEC)
M1, S1, _ = degerlendir(BOL1)
print("gec gelen kaynak:", len(GEC), " tuketim ciktisi:", IZ1[2][2],
      " egitim satiri:", M1["egitim_satiri"], f" sinama isabeti: {S1:.4f}")
print()
print(f"{'bayat adim':>11}{'yeniden kosan':>14}{'islenen satir':>14}"
      f"{'egitim satiri':>14}{'egitim isabeti':>15}{'sinama isabeti':>15}")
for p in range(7):
    if p == 6:
        bol, islenen = ARA1["bolunme"], 0
    else:
        bol, _, _, islenen = hat_kostur(KAYNAK, bastan=p, saklanan=ARA1)
    m, s, _ = degerlendir(bol)
    print(f"{p:>11}{6 - p:>14}{islenen:>14}{m['egitim_satiri']:>14}"
          f"{m['egitim_isabeti']:>15.4f}{s:>15.4f}")
```

```
gec gelen kaynak: 2360  tuketim ciktisi: 2120  egitim satiri: 1520  sinama isabeti: 0.8067

 bayat adim yeniden kosan islenen satir egitim satiri egitim isabeti sinama isabeti
          0             6         13800          1600         0.7931         0.8067
          1             5         11080          1520         0.7914         0.8067
          2             4          8720          1520         0.7914         0.8067
          3             3          6360          1520         0.7914         0.8067
          4             2          4240          1520         0.7914         0.8067
          5             1          2120          1520         0.7914         0.8067
          6             0             0          1520         0.7914         0.8067
```

Geç gelen 40 satır hattın çıktısından **80 satır** götürüyor: kendileri düşüyor ve bir sonraki dönemin
40 satırı önceki dönemini bulamadığı için düşüyor. Eğitim kümesi 1600 yerine **1520** satırla
kuruluyor.

Tablo tek bir şeyi söyler. Geri doldurma yapıldıktan sonra eğitim satırını **1600**'e çıkaran tek
kurulum, bayat adımı sıfır olan, yani **kaynaktan itibaren uçtan uca yeniden koşan** hattır. Bir tek
adımın bile saklanan eski çıktıdan gelmesi yeterlidir: hat kalan beş adımı gerçekten yeniden koşsa
bile eğitim satırı **1520**'de kalır, çünkü kaybolan satırlar zaten ilk adımın çıktısında yoktu.
Kısmi koşum, işlenen satırı 13800'den 11080'e düşürerek tasarruf eder ve karşılığında **düzeltilmiş
kaynağı hiç görmez**.

Rapor edilen sayı yedi kurulumda da **0,8067**'dir. Sınama isabetine bakan hiç kimse, 1600 satırla
eğitilmiş bir modelle 1520 satırla eğitilmiş bir modeli birbirinden ayıramaz. Farkı gösteren tek yer
eğitim isabetidir ve orada da fark **0,0017**'dir. Kursun kuralı burada tam karşılığını bulur:
**yeniden üretilemeyen sayı bir ölçüm değil bir anıdır** ve bir hattın uçtan uca koşturulabilir
olması, o sayının hangi kaynaktan geldiğinin **belirlenebilir** olması demektir.

Uçtan uca koşumun bedeli de tablodadır: her koşumda **13800 satır** yeniden işlenir; tümüyle bayat
kurulumda bu sayı **0**'dır. Sabitlemek bedelsiz değildir.

## Özet

- Eğitim hattı veri hattının **beşinci** aşamasından değil **üçüncüsünden** dallanır: model 5 sunum
  değerine değil, 2200 tüketim satırına bağlanır.
- Altı adımın girdi ve çıktısı ayrı ayrı sayıldığında tüketim adımı **200 satır** kaybediyor, ama
  adımın kendi sayacı **0** yazıyor; sayaç yalnızca beklenmedik düşüşü sayar.
- Öznitelik adımı hiç satır düşürmeden **200 satırı geçmişsiz** bırakır; düşen satırı sıfır olan
  adım da veriyi bozabilir.
- Etiket dağılımı **1752'ye 448**, taban sınıf oranı **0,7964**; sınama kümesinde **0,8067**. Model
  600 satırın 600'üne 0 diyor, isabeti **0,8067** ve taban üzerindeki kazancı **0,0000**.
- Geç gelen 40 satır eğitim kümesinden **80 satır** götürür; geri doldurmadan sonra 1600 satıra
  dönen tek kurulum bayat adımı **sıfır** olan uçtan uca koşumdur, bedeli koşum başına **13800
  işlenen satır**.
- Yedi kurulumun yedisi de aynı **0,8067**'yi rapor eder; sınama isabeti 1600 satırlık eğitimle 1520
  satırlık eğitimi ayırt edemez.

## Sonraki Adım

Bu dersin hattı bir kez kurulduktan sonra hep aynı biçimde koşuyordu ve koştuğu her seferde bir model
üretiyordu. Üretilen modelin **yayına çıkıp çıkmayacağı** hiç sorulmadı. Geç gelen satırların
eksikliğiyle eğitilen 1520 satırlık model de, geri doldurulmuş 1600 satırlık model de aynı kolaylıkla
yayına gidebilirdi, çünkü ikisi de aynı sayıyı rapor ediyordu. Sonraki ders koşum ile yayın arasına
**kapılar** koyar: kod kapısı, veri kapısı ve model kapısı. Ölçü, Veri Mühendisliğine Giriş kursunda
tanımlanan altı bozulma sınıfının bu üç kapıya nasıl dağıldığı ve **hiçbir kapının durdurmadığı**
sınıfın hangisi olduğudur.
