Ders 01 / 12
MLOps Nedir
Yazılım mühendisliği pratiğinin model üreten bir hatta uygulanmasının kurulması ve sabitlemesiz tabanın ölçülmesi: hattan çıkan 2200 satır 40 m3 eşiğiyle etiketlendiğinde dağılım 1752 ile 448 oluyor, taban sınıf oranı 0,7964 çıkıyor, 27 adaylık ızgarada aranan model eğitimde 0,7931 sınamada 0,8067 veriyor, ama sınama kümesinin kendi taban oranı da 0,8067 olduğu için model 600 sınama satırının hiçbirine yüksek demiyor ve duyarlılığı 0,0000 kalıyor; hiçbir kalem sabitlenmediğinde aynı iş üç kez koşturulduğunda ağırlık üç koşumda da aynı kalırken sınama isabeti 0,8067, 0,7955 ve 0,8078 çıkıyor ve üç sayının üçü de kendi sınama kümesinin taban oranına eşit olduğu için fark modelden değil kümenin değişmesinden geliyor.
İçindekiler
Yirmi yedi derste veri taşındı, saklandı, dönüştürüldü ve bölüştürüldü. Hattın her aşaması kaç satır düşürdüğü sayıldı, bozulmanın kaç aşama sonra yakalandığı ölçüldü, satırların hangi düzende durduğu ve dört işçiye bölündüğünde ne kazanıldığı yazıldı. Bütün bu işin bir amacı vardı ve o amaç bir kez bile açılmadı: bu verinin beslediği model.
Bu kurs iki soruyu sorar: aynı veriyle aynı modelin yeniden üretilip üretilemeyeceği, ve eğitilen bir modelin üretime nasıl çıkacağı. İlk konu birincisini ele alır. Bu ders kursun ölçü düzenini, etiketi ve kurgu modeli kurar, sonra tek bir şeyi ölçer: hiçbir kalem sabitlenmemişken aynı iş üç kez koşturulduğunda kaç ayrı sayı çıkıyor.
- YU1. Kaynak, hat ve model kurgudur. Gerçek bir öğrenme kitaplığı, deney takip düzeneği, öznitelik deposu, model kayıt defteri ya da sunum çatısı çağrılmaz ve adı yazılmaz. Tohum 20260218.
- YU2. Kursun kuralı: bir modelin sayısı onu üreten yolla birlikte anlamlıdır. Yeniden üretilemeyen sayı bir ölçüm değil bir anıdır.
- YU3. Taban çizgisi her derste sürümsüz, sabitlemesiz ve tek yollu kurulumdur.
- YU4. Etiket: bir dönemin tüketimi 40 m3’ü aşıyorsa “yüksek” (1), aşmıyorsa 0. Eşik bir seçimdir ve ona duyarlı her sonuç eşikle birlikte yazılır.
- YU5. Etiket dağılımı dengesizdir:
{0: 1752, 1: 448}, yani taban sınıf oranı 0,7964. Bir isabet sayısı bunun ne kadar üstünde olduğu yazılmadan ölçülmüş sayılmaz. Taban çizgisi yordamı Denetimli Öğrenme kursunda ölçüldü; burada devralınır, tekrarlanmaz. - YU6. Kurgu model üç ağırlıklı bir eşiktir; eğitim, 27 adaylık bir ızgarada aramaktır.
- YU7. Eğitim dönemi sekiz (
2026-02ile2026-09, 1600 satır), sınama dönemi üç (2026-10ile2026-12, 600 satır). - YU8. Çözünürlük: sınama kümesi 600 satır olduğu için isabetin en küçük adımı 0,0017’dir.
- YU9. Eğitim hattı bu kursta tek makinede ele alınır. Bölüşüm, karıştırma ve çarpıklık Dağıtık Veri İşleme kursunda ölçüldü ve burada tekrarlanmaz.
- YU10. Sayılan birimler isabet, aday, eğitim satırı, sabitlenen kalem ve aynı çıkan koşumdur; süre ham milisaniye olarak yazılmaz.
- YU11. Beş sabitleme kalemi:
veri_surumu,oznitelik_kodu,bolunme,izgara,yuvarlama. MLOps bir pratik adıdır, bir ürün adı değildir.
Yazılım Pratiğinin Modele Uygulanması
Bir programın çıktısını kaynağı belirler ve yazılım pratiğinin bütün araçları bu varsayımın üzerine kuruldu: sürüm denetimi kaynağı saklar, gerileme testi davranışı sabitler, sürekli tümleştirme her değişikliği aynı yoldan geçirir. Bu yordamlar DevOps ve Sürekli Tümleştirme kursunda ve Veri Hatları ve Orkestrasyon kursunda ölçüldü; tekrarlanmaz.
Bir modelde varsayım düşer. Bir modelin verdiği sayıyı belirleyen şey yalnız kaynak kodu değildir. En az beş kalem vardır: modelin gördüğü veri, o verinin eğitimle sınamaya nasıl bölündüğü, özniteliğin hangi kodla hesaplandığı, arama uzayının hangi adaylardan oluştuğu ve sayıların kaç basamağa yuvarlandığı. Bu beş kalemden yalnız biri kaynak dosyasının içinde durur; kalan dördü ya bir dizinde, ya bir komut satırı seçeneğinde, ya da hiçbir yerde. MLOps bu kalemleri kaynak kodunun zaten sahip olduğu disipline bağlama pratiğinin adıdır: yeni bir matematik değil, kayıt tutma getirir.
Kurgu Model ve Etiket
Aşağıdaki blok Veri Mühendisliğine Giriş kursundaki kurgu ölçüm ağı kaynağını ve hattın ilk üç aşamasını aynen yeniden kurar, üzerine bu kursun etiketini, öznitelik üretimini ve kurgu modelini ekler.
# KURGUDUR. Sayac okumalari, hat ve model ders icinde tanimlanir; gercek bir # ogrenme kitapligi, deney takip duzenegi ya da model kayit defteri 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 = 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 # ---- Oznitelik uretimi. Agirliktan bagimsizdir , bir kez hesaplanir. def oznitelikler(kayitlar, pencere=None, basamak=4): """pencere=None -> tam gecmis (egitim yolu).""" 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 # ---- KURGU model: uc agirlikli esik. Egitim = agirliklari izgarada aramak. 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) # ---- Yeniden uretilebilirlik: sabitlenen kalemler KALEM = ("veri_surumu", "oznitelik_kodu", "bolunme", "izgara", "yuvarlama") def kosum(kayitlar, sabit, tur=0): """Sabitlenmeyen her kalem tur'a gore degisir.""" kay = kayitlar if "veri_surumu" in sabit else kayitlar[: len(kayitlar) - 20 * tur] pencere = None if "oznitelik_kodu" in sabit else (None if tur == 0 else 12 - tur) basamak = 4 if "yuvarlama" in sabit else max(4 - tur, 0) izgara = IZGARA if "izgara" in sabit else IZGARA[: len(IZGARA) - 6 * tur] donemler = SINAMA if "bolunme" in sabit else DONEM[9 + (tur % 2):] oz = oznitelikler(kay, pencere, basamak) m = egit(kay, oz, izgara) return {"agirlik": m["agirlik"], "egitim": m["egitim_isabeti"], "sinama": sina(kay, m, oz, donemler=donemler)}
Model bir abonenin geçmiş tüketim ortalamasına, bölgesinin ortalamasına ve işyeri olup olmadığına
bakar; üç ağırlıkla bir puan üretir ve puan eşiği aşarsa “yüksek” der. Eğitim, 27 adayı deneyip
eğitim kümesinde en çok tutturanı seçmektir. Öznitelikler ağırlıktan bağımsız olduğu için
oznitelikler bunları bir kez hesaplar.
S = satirlar() dagilim = {0: 0, 1: 0} for k in S: dagilim[etiket(k)] += 1 print("hattan cikan satir:", len(S), " esik:", ESIK) print("etiket dagilimi:", dagilim) print("taban sinif orani:", round(dagilim[0] / len(S), 4)) print() oz = oznitelikler(S) model = egit(S, oz) print("aday:", model["aday"], " egitim satiri:", model["egitim_satiri"]) print("agirlik:", model["agirlik"]) print("egitim isabeti:", model["egitim_isabeti"]) print("sinama isabeti:", sina(S, model, oz))
hattan cikan satir: 2200 esik: 40
etiket dagilimi: {0: 1752, 1: 448}
taban sinif orani: 0.7964
aday: 27 egitim satiri: 1600
agirlik: (0.6, 0.4, 0)
egitim isabeti: 0.7931
sinama isabeti: 0.8067
İki sayı burada bir arada durur ve ikisi de kursun geri kalanında geçer. Birincisi etiket dağılımıdır: 2200 satırın 1752’si “yüksek değil”, 448’i “yüksek”, yani dağılım dengesizdir. İkincisi taban sınıf oranıdır: hiçbir şey öğrenmeden her satıra “yüksek değil” diyen bir kural 0,7964 isabet alır. Model 0,8067 aldı; kâğıt üzerinde tabandan 0,0103 yukarıda görünür.
Taban Sınıf Oranı Yazılmadan Sayı Okunmaz
O karşılaştırma yanlıştır, çünkü 0,7964 bütün verinin taban oranıdır, model ise yalnız sınama kümesinde ölçüldü. Doğrusu sınama kümesinin kendi taban oranıyla yapılır.
sk = [k for k in S if k["donem"] in SINAMA] yuksek = sum(1 for k in sk if etiket(k) == 1) tahmin = {0: 0, 1: 0} tutan = 0 for k in sk: t = 1 if puan(oz[(k["abone"], k["donem"])], model["agirlik"]) > ESIK else 0 tahmin[t] += 1 if t == 1 and etiket(k) == 1: tutan += 1 print("sinama satiri:", len(sk), " yuksek etiketli:", yuksek) print("sinama taban sinif orani:", round((len(sk) - yuksek) / len(sk), 4)) print("modelin sinama isabeti :", sina(S, model, oz)) print("modelin tahmin dagilimi:", tahmin) print(f"duyarlilik: {tutan / yuksek:.4f}") print(f"tabanin ustunde: {sina(S, model, oz) - (len(sk) - yuksek) / len(sk):.4f}")
sinama satiri: 600 yuksek etiketli: 116
sinama taban sinif orani: 0.8067
modelin sinama isabeti : 0.8067
modelin tahmin dagilimi: {0: 600, 1: 0}
duyarlilik: 0.0000
tabanin ustunde: 0.0000
Sınama kümesinin taban oranı 0,8067’dir ve modelin isabeti de 0,8067. Fark 0,0000. Sebebi son iki satırda görünür: model 600 sınama satırının hiçbirine “yüksek” demiyor, yüksek etiketli 116 satırın hiçbirini yakalamıyor, ve duyarlılığı 0,0000 kalıyor.
Bu sonuç bilerek yazılmıştır. Kurgu model taban çizgisinin üzerine çıkmaz, ve bu kursun ölçtüğü şeyi karışıklıktan kurtarır: buradan sonra isabetin her oynayışı modelin başarımından değil, sayıyı üreten yoldan gelir. Model kurmanın, eşik seçmenin ve dengesizlikle başa çıkmanın yordamı Makine Öğrenmesi müfredatında ölçüldü ve tekrarlanmaz. Kural şudur: 0,8067 tek başına yazıldığında bir başarım iddiasıdır ve yanlıştır; taban oranıyla yan yana yazıldığında modelin hiçbir şey ölçmediğini söyler.
Aynı İş, Üç Koşum, Üç Sayı
Şimdi asıl soru sorulabilir. Yukarıdaki koşum bir kez yapıldı ve bir sayı verdi; aynı iş bir hafta
sonra tekrar yapılırsa aynı sayı çıkar mı. Hiçbir kalem sabitlenmemiştir: depodan o gün ne varsa
okunur, öznitelik kodu değişmiş, ızgara kısalmış, bölünme kaymış olabilir. kosum bu kurulumu üç
tur için canlandırır.
print("sabitlenen kalem: 0 -- besinin hicbiri sabit degil") print(f"{'tur':<5}{'agirlik':>16}{'egitim':>9}{'sinama':>9}") for tur in range(3): r = kosum(S, (), tur) print(f"{tur:<5}{str(r['agirlik']):>16}{r['egitim']:>9.4f}{r['sinama']:>9.4f}") print() print(f"{'tur':<5}{'satir':>7}{'aday':>6}{'sinama donemi':>15}{'sinama satiri':>15}{'taban orani':>13}") for tur in range(3): kay = S[: len(S) - 20 * tur] donemler = DONEM[9 + (tur % 2):] sk3 = [k for k in kay if k["donem"] in donemler] y3 = sum(1 for k in sk3 if etiket(k) == 1) print(f"{tur:<5}{len(kay):>7}{len(IZGARA) - 6 * tur:>6}{len(donemler):>15}" f"{len(sk3):>15}{(len(sk3) - y3) / len(sk3):>13.4f}")
sabitlenen kalem: 0 -- besinin hicbiri sabit degil tur agirlik egitim sinama 0 (0.6, 0.4, 0) 0.7931 0.8067 1 (0.6, 0.4, 0) 0.7932 0.7955 2 (0.6, 0.4, 0) 0.7926 0.8078 tur satir aday sinama donemi sinama satiri taban orani 0 2200 27 3 600 0.8067 1 2180 21 2 396 0.7955 2 2160 15 3 588 0.8078
Üst tablo kursun taban çizgisidir: 0,8067, 0,7955, 0,8078. En büyüğüyle en küçüğü
arasında 0,0123 fark var; çözünürlük 0,0017 olduğuna göre bu yedi adımdan büyüktür, yani
gürültü değildir. Üç koşumun ağırlığı ise birebir aynıdır: (0.6, 0.4, 0).
Alt tablo farkın nereden geldiğini söyler. Her turda okunan satır düştü, aday sayısı 27’den 21’e ve 15’e indi, ve sınama dönemi değişti: birinci turda üç dönem, ikinci turda iki. Son sütun kesin cevabı verir. Üç turun sınama taban oranı sırasıyla 0,8067, 0,7955 ve 0,8078’dir; üst tablodaki üç sayının aynısı. Model üç turda da her satıra “yüksek değil” dediği için ölçülen şey modelin başarımı değil, o turda hangi satırların sınamaya düştüğüdür.
Buradan kursun kuralı okunur. Üç sayı aynı sorunun üç cevabı değildir; üç ayrı sorunun birer cevabıdır ve hangi soruya cevap verdikleri hiçbir yerde yazmaz. Bu sayılardan biri bir hafta sonra bir rapora girse, onu okuyan kişi ne kadar veri okunduğunu, kaç aday denendiğini ve hangi dönemlerin sınamaya ayrıldığını bilemez. Yeniden üretilemeyen sayı bir ölçüm değil bir anıdır.
Kursun Üç Sütunu
Kursun geri kalanında her ders üç sayıyı yan yana koyar. Birincisi sabitlemesiz tabandır: yukarıdaki üç koşum, üç ayrı sayı. İkincisi sabitlenmiş kurulumdur: aynı iş, belirli kalemler sabitlenmiş, koşumların kaçının aynı çıktığı sayılmış. Üçüncüsü bedeldir: sabitlenen kalem, saklanan kayıt, eklenen adım. Üçüncü sütun boş bırakılamaz, çünkü katkısı gösterilemeyen bir sabitleme ölçülmemiş bir güvence verir.
Özet
- MLOps, bir modelin sayısını belirleyen beş kalemi kaynak kodunun zaten sahip olduğu disipline bağlama pratiğinin adıdır: veri, bölünme, öznitelik kodu, arama uzayı ve yuvarlama. Beşinden yalnız biri kaynak dosyasının içinde durur.
- Kurgu model üç ağırlıklı bir eşiktir, eğitim 27 adaylık bir ızgarada aramaktır. Etiket 40 m3
eşiğiyle üretilir, dağılım
{0: 1752, 1: 448}çıkar, taban sınıf oranı 0,7964’tür. - Modelin sınama isabeti 0,8067, sınama kümesinin taban oranı da 0,8067’dir. Model 600 satırın hiçbirine “yüksek” demez, duyarlılığı 0,0000’dır ve tabanın üstünde 0,0000 durur.
- Sabitlemesiz tabanda üç koşum 0,8067, 0,7955 ve 0,8078 verir; aradaki 0,0123 fark 0,0017’lik çözünürlüğün yedi katıdır. Üç koşumun ağırlığı ise birebir aynıdır ve üç sayının üçü de kendi sınama kümesinin taban oranına eşittir.
- Kursun kuralı budur: bir modelin sayısı onu üreten yolla birlikte anlamlıdır ve yeniden üretilemeyen sayı bir ölçüm değil bir anıdır.
Sonraki Adım
Üç koşum yapıldı ve üç sayı çıktı, ama hiçbiri bir yere yazılmadı. Sayıları yan yana görebilmemizin tek sebebi üçünü de aynı blokta koşturmuş olmamızdır; gerçek bir çalışmada bu üç koşum üç ayrı güne dağılır ve aralarında yalnız hatırlanan bir sayı kalır. Sonraki ders o kaydı kurar ve tek bir soruyu ölçer: bir sonucu üreten ağırlığı bulmak için kaç koşumun tekrar koşturulması gerekiyor, kayıtla kaç, ve kaydın kendi bedeli ne kadar.
İlerlemeni kaydetmek ve not almak için Giriş yap
Notlarım
Not almak için giriş yapmalısın.