9  Döngüler

for batch in dataloader — modern AI’nın ana motoru

NotBölüm bilgisi

9.1 Bu Derste Ne Var?

Bu kursun en kritik dersi. Mosh dört chapter’da Python’un tekrar etme yetisini öğretiyor; biz bunu modern ML kodunun ana motoruna bağlıyoruz. for batch in dataloader: satırı olmasaydı, sinir ağları eğitilmez, LLM’ler üretilmez, modern AI olmazdı.

flowchart LR
    A["while"] --> B["for + range"]
    B --> C["break / continue"]
    C --> D["enumerate / zip"]
    D --> E["Nested loops"]
    E --> F["List comprehension"]
    F --> G["💎 for epoch in range(EPOCHS):"]
    G --> H["💎 for batch in dataloader:"]
    H --> I["⚡ MODERN AI'NIN ANA MOTORU"]

    style G fill:#fff3e0,stroke:#f57c00,stroke-width:2px
    style H fill:#fce4ec,stroke:#c2185b,stroke-width:3px
    style I fill:#ffcdd2,stroke:#b71c1c,stroke-width:3px
Şekil 9.1: Ders 8’in akış haritası — döngülerden ML eğitim motoruna

Dersin yedi parçası:

  1. while döngüsü. — Koşul True iken tekrar.
  2. Guessing Game (proje).while + if.
  3. for döngüsü. — Koleksiyon gezme.
  4. range(). — Sayı dizisi.
  5. break ve continue. — Akış kontrol.
  6. Nested loops + 2D listeler. — Matris işleme.
  7. ML eğitim döngüsü. — Mosh’un öğrettiklerinin AI’da uygulanması.
İpucuBuilder Notu — Bu Dersin ML Köprüleri (EN GÜÇLÜ)
  • for batch in dataloader = ML eğitim döngüsünün ANA MOTORU. Her sinir ağı eğitimi, her LLM fine-tune, her görüntü sınıflandırma — hepsi bu satırla çalışır. Mosh’un “döngüde her öğeye bir şey yap” sezgisi, milyarlarca parametre üstünde milyonlarca veri örneğini işleyen ML pipeline’ının çekirdek pattern’ı.
  • for epoch in range(EPOCHS) = dış eğitim döngüsü. Bir epoch = veri setinin tamamen bir kez işlenmesi.
  • while = early stopping kontrolü. while patience_counter < max_patience: train_one_epoch().
  • break = early termination. if val_loss > best_loss: break.
  • continue = bad batch skip. if torch.isnan(loss): continue.
  • enumerate = batch index + batch. for i, batch in enumerate(loader): logging için.
  • zip = paralel iteration. for img, label in zip(images, labels):.
  • Nested for = batch × feature processing. Python loop’ta yavaş, vektörlü yap’la tek hamlede.
  • List comprehension = vectorized construction. losses = [train(b) for b in batches].

9.2 Neden Döngü?

Şimdiye kadar yazdığımız kodun büyük eksiği: tekrar yok. Öğrenci sicil dict’imiz üç öğrenci tutarsa her birine elle erişmek zorunda kalıyoruz. 100 öğrencide kopya-yapıştır cehennem.

“süre döngü temelde python içinde bir döngüdür. ve yürüt Birden çok kez bir kod bloğu.” — Mosh (Türkçe dublaj), 2:14:16

Döngü üç güç sağlar:

  1. Tekrar — aynı kodu N kez çalıştır.
  2. Gezme — bir koleksiyondaki tüm öğelere ulaş.
  3. Birikim — sonuçları toplama, sayma, filtreleme.

9.2.1 İki Tür

Tür Ne zaman?
while Koşula bağlı — bilinmeyen iterasyon sayısı
for Bilinen koleksiyon — her elemanı sırayla

ML’de:

  • for batch in dataloader: (her batch) → for
  • for epoch in range(100): (100 epoch) → for
  • while not converged:while
  • while patience > 0:while

9.3 while Döngüsü

“buna döngü olarak bakın bekçi. ve temelde kod boyunca döngü devam edeceğiz while döngüsü içinde. bu durum doğru olduğu sürece.” — Mosh (Türkçe dublaj), 2:15:36

9.3.1 Sentaks

while kosul:
    # girintili kod (kosul True ise, sonra TEKRAR kontrol)

Kritik fark if’ten: while kodu çalıştırıp koşulu tekrar kontrol eder. if bir kere.

9.3.2 İlk Örnek

i = 1

while i <= 10:
    print(i)
    i += 1   # "i = i + 1" kisayolu

print("Dongu bitti")

Çıktı: 1, 2, 3, ..., 10, Dongu bitti.

9.3.3 += Kısayollar

i = 5

i += 1    # i = i + 1   -> 6
i -= 2    # i = i - 2
i *= 3    # i = i * 3
i //= 2   # i = i // 2
i %= 2    # i = i % 2

9.3.4 Sonsuz Döngü Tuzağı

i = 1
while i <= 10:
    print(i)
    # i += 1 unutuldu! i hep 1, sonsuz dongu!

PyCharm’da Ctrl+C ile dur. Bilinçli sonsuz döngü (while True: + break) ML’de yaygın.

9.3.5 while = Early Stopping

İpucuBuilder Notu — Patience Pattern
import torch

model = ...
optimizer = ...
best_val_loss = float('inf')
patience = 5
patience_counter = 0
epoch = 0
max_epochs = 1000

while patience_counter < patience and epoch < max_epochs:
    train_one_epoch(model, optimizer)
    val_loss = validate(model)

    if val_loss < best_val_loss:
        best_val_loss = val_loss
        patience_counter = 0   # iyilesti, sabir resetle
    else:
        patience_counter += 1  # iyilesmedi, sabir azalt

    epoch += 1

print(f"Egitim {epoch} epoch sonra bitti")

Mosh’un i <= 10 sayı mantığı, ML’de “sabır kalması” koşuluna dönüşür.

9.4 Proje — Guessing Game

“bir süre döngü denilen bir şey […] sürekli olarak kişiye sormak için sözcüğü tahmin etmek doğru tahmin edene kadar.” — Mosh (Türkçe dublaj), 2:21:47

9.4.1 Basit Sürüm

secret_word = "draft"
guess = ""

while guess != secret_word:
    guess = input("Tahmin et: ")

print("Kazandiniz!")

Problem: sonsuz tahmin yapabilir.

9.4.2 Üç Hak Sınırlı

secret_word = "draft"
guess_count = 0
guess_limit = 3

for attempt in range(guess_limit):
    guess = input(f"Tahmin et ({guess_limit - attempt} hak): ")
    if guess == secret_word:
        print("Kazandiniz!")
        break
else:
    # for-else: for normal bittiyse (break olmadan) calisir
    print("Kaybettiniz!")

for-else — Python’a özgü tuhaf ama güzel: for döngüsü break ile bitmediyse else çalışır.

9.5 for Döngüsü

“bir for döngüsü python’da bize izin veren özel bir döngü türüdür farklı koleksiyonlar üzerinde dolaşmak” — Mosh (Türkçe dublaj), 2:32:50

9.5.1 Sentaks

for degisken in koleksiyon:
    # her oge icin tekrarlanir
    print(degisken)

9.5.2 String, List, Tuple, Set, Dict

# String:
for letter in "Draft Academy":
    print(letter)

# List:
friends = ["Kevin", "Karen", "Jim"]
for friend in friends:
    print(f"Merhaba {friend}!")

# Tuple:
for c in (3, 5, 7):
    print(c)

# Dict:
kullanici = {"ad": "Deniz", "yas": 35, "sehir": "Istanbul"}
for key, value in kullanici.items():
    print(f"{key}: {value}")

while ile aynı işi yapmak için index yönetmek gerekir; for çok daha Pythonic.

9.5.3 Yararlı Helpers — enumerate, zip

# enumerate - index + eleman:
friends = ["Kevin", "Karen", "Jim"]
for i, friend in enumerate(friends):
    print(f"{i}: {friend}")
# 0: Kevin
# 1: Karen
# 2: Jim

# zip - paralel iteration:
isimler = ["Deniz", "Aylin", "Mosh"]
yaslar = [35, 28, 40]
for ad, yas in zip(isimler, yaslar):
    print(f"{ad} ({yas})")

# reversed / sorted:
for friend in reversed(friends):
    print(friend)

for friend in sorted(friends):
    print(friend)

9.6 range()

list(range(5))           # [0, 1, 2, 3, 4]
list(range(2, 8))        # [2, 3, 4, 5, 6, 7]
list(range(0, 20, 3))    # [0, 3, 6, 9, 12, 15, 18]
list(range(10, 0, -1))   # [10, 9, 8, 7, 6, 5, 4, 3, 2, 1]

range(stop)stop dahil değil (yarı açık aralık).

9.6.1 for ile Kullanım

for i in range(5):
    print(i)

# 100 kez tekrar (sadece tekrar):
for _ in range(100):
    print("merhaba")    # 100 kez basilir

_ — “değişkene ihtiyacım yok, sadece tekrar etmeliyim”.

9.6.2 range vs enumerate

friends = ["Kevin", "Karen", "Jim"]

# C/Java tarzi (Python'da KOTU):
for i in range(len(friends)):
    print(f"{i}: {friends[i]}")

# Pythonic:
for i, friend in enumerate(friends):
    print(f"{i}: {friend}")

PEP 8 + linter’lar enumerate öneriri.

9.6.3 range ML’in Epoch Döngüsü

ÖnemliBuilder Notu — ML EĞİTİM OMURGASI
import torch
import torch.nn as nn

EPOCHS = 100
BATCH_SIZE = 64

model = ...
optimizer = ...

for epoch in range(EPOCHS):                  # outer for - epoch sayisi
    epoch_losses = []

    for batch_idx, batch in enumerate(train_loader):   # inner for + enumerate
        loss = compute_loss(batch)
        loss.backward()
        optimizer.step()
        optimizer.zero_grad()
        epoch_losses.append(loss.item())

        if batch_idx % 100 == 0:             # mod ile periyodik log
            print(f"Epoch {epoch}, Batch {batch_idx}: loss={loss.item():.4f}")

    avg_loss = sum(epoch_losses) / len(epoch_losses)
    print(f"Epoch {epoch} avg loss: {avg_loss:.4f}")

Mosh’un for i in range(10): mikro örneği ↔︎ ML’in for epoch in range(EPOCHS): makro hali. Aynı yapı, daha büyük ölçek.

Her ML eğitim sistemi bu iki nested for döngüsünden oluşur:

  • Outer: epochs üzerinde (range)
  • Inner: batch’ler üzerinde (dataloader)

9.7 break ve continue

# break - donguden tamamen cik:
for i in range(10):
    if i == 5:
        break
    print(i)
# 0, 1, 2, 3, 4

# continue - bu iterasyonu atla:
for i in range(10):
    if i % 2 == 0:
        continue
    print(i)
# 1, 3, 5, 7, 9

9.7.1 ML Eşdeğerleri

# break = early stopping:
for epoch in range(MAX_EPOCHS):
    if val_loss > best_loss * 1.1:
        print("Early stopping!")
        break

# continue = bad batch skip:
for batch in train_loader:
    loss = compute_loss(batch)
    if torch.isnan(loss):
        print("Bad batch, atlandi")
        continue
    loss.backward()
    optimizer.step()

9.8 Nested Loops + 2D Listeler

matris = [
    [1, 2, 3],
    [4, 5, 6],
    [7, 8, 9],
]

print(matris[0])       # [1, 2, 3]
print(matris[0][2])    # 3
print(matris[2][0])    # 7

# Nested for - her elemani yazdir:
for satir in matris:
    for eleman in satir:
        print(eleman, end=" ")
    print()
# 1 2 3
# 4 5 6
# 7 8 9

9.8.1 Çarpım Tablosu

for i in range(1, 6):
    for j in range(1, 6):
        print(f"{i*j:3d}", end=" ")
    print()

9.8.2 Nested = Çarpımsal Maliyet

# 100 x 100 = 10K iterasyon
# 1000 x 1000 = 1M iterasyon
# 1000 x 1000 x 1000 = 1B (tehlikeli!)

9.8.3 Vectorization Kararı

UyarıBuilder Notu — Nested vs Tensor

Python nested loops kavramsal olarak doğru ama performans için yetersiz:

import time
import numpy as np
import torch

A = [[i*j for j in range(1000)] for i in range(1000)]   # 1000x1000

# Python loops:
start = time.time()
result = [[x ** 2 for x in row] for row in A]
print(f"Python: {time.time() - start:.3f}s")
# ~0.5 sn

# NumPy:
A_np = np.array(A)
start = time.time()
result_np = A_np ** 2
print(f"NumPy: {time.time() - start:.6f}s")
# ~0.003 sn  - 100+ kat

# PyTorch GPU:
A_t = torch.tensor(A).cuda()
start = time.time()
result_t = A_t ** 2
torch.cuda.synchronize()
print(f"PyTorch GPU: {time.time() - start:.6f}s")
# 1000+ kat

ML perspektifi:

  • for batch in dataloader: OK çünkü batch sayısı az (~1000).
  • for pixel in image: YASAK çünkü pixel sayısı çok (224×224×3 ≈ 150K). Tensor op ile yap.

9.9 List Comprehension

Mosh göstermez ama modern Python’un en sevdiği deyim.

# Klasik for:
kareler = []
for i in range(10):
    kareler.append(i * i)

# List comprehension:
kareler = [i * i for i in range(10)]

# Filtreli:
cift_kareler = [i * i for i in range(10) if i % 2 == 0]

# Dict comprehension:
kareler_dict = {i: i*i for i in range(5)}

# Set comprehension:
benzersiz_kareler = {x*x for x in [-2, -1, 0, 1, 2]}

9.9.1 Comprehension ML’de

# Bir liste tensoru cevirme:
tensors = [torch.tensor(data) for data in batches]

# Filtering:
valid_losses = [loss for loss in all_losses if not torch.isnan(loss)]

# Dict olusturma:
param_count = {name: p.numel() for name, p in model.named_parameters()}

3 satırı tek satıra indirir. Okunabilir ve hızlı.

9.10 ML Eğitim Döngüsü — KURSUN ZIRVESI

Bu bölüm Ders 8’in ve tüm kursun zirvesi. Mosh’un öğrettikleri tek bir kod parçasında bir araya geliyor. Bu kod, modern AI’nın kalbi.

import torch
import torch.nn as nn
from torch.utils.data import DataLoader

# Ders 7 (dict + config):
config = {
    "lr": 1e-3,
    "batch_size": 64,
    "epochs": 100,
    "patience": 5,
    "device": "cuda" if torch.cuda.is_available() else "cpu",
}

model = MyModel().to(config["device"])
optimizer = torch.optim.AdamW(model.parameters(), lr=config["lr"])
criterion = nn.CrossEntropyLoss()

train_loader = DataLoader(train_dataset, batch_size=config["batch_size"], shuffle=True)
val_loader = DataLoader(val_dataset, batch_size=config["batch_size"], shuffle=False)

# Ders 4 (list):
train_losses = []
val_losses = []
best_val_loss = float('inf')
patience_counter = 0

# DIS DONGU - epochs:
for epoch in range(config["epochs"]):
    # === EGITIM FAZI ===
    model.train()
    epoch_train_losses = []

    # IC DONGU - batch:
    for batch_idx, batch in enumerate(train_loader):
        # Ders 4 (tuple unpacking):
        images = batch["image"].to(config["device"])
        labels = batch["label"].to(config["device"])

        # Ders 5 (fonksiyon):
        logits = model(images)
        loss = criterion(logits, labels)

        # Ders 6 (if) + Ders 8 (continue):
        if torch.isnan(loss):
            print(f"NaN at epoch {epoch}, batch {batch_idx} - skip")
            continue

        optimizer.zero_grad()
        loss.backward()
        optimizer.step()

        epoch_train_losses.append(loss.item())

        # Ders 6 (if) + Ders 2 (modulus):
        if batch_idx % 100 == 0:
            print(f"E{epoch} B{batch_idx}: loss={loss.item():.4f}")

    # === DOGRULAMA ===
    model.eval()
    epoch_val_losses = []

    with torch.no_grad():
        for batch in val_loader:
            images = batch["image"].to(config["device"])
            labels = batch["label"].to(config["device"])
            logits = model(images)
            loss = criterion(logits, labels)
            epoch_val_losses.append(loss.item())

    # Ders 4 (sum + len):
    avg_train_loss = sum(epoch_train_losses) / len(epoch_train_losses)
    avg_val_loss = sum(epoch_val_losses) / len(epoch_val_losses)

    train_losses.append(avg_train_loss)
    val_losses.append(avg_val_loss)

    print(f"Epoch {epoch}: train={avg_train_loss:.4f}, val={avg_val_loss:.4f}")

    # Ders 8 (break) + Ders 7 (dict):
    if avg_val_loss < best_val_loss:
        best_val_loss = avg_val_loss
        patience_counter = 0
        torch.save({
            "epoch": epoch,
            "model_state_dict": model.state_dict(),
            "val_loss": avg_val_loss,
        }, "best_model.pt")
    else:
        patience_counter += 1
        if patience_counter >= config["patience"]:
            print(f"Early stopping at epoch {epoch}")
            break

print("Egitim bitti!")

9.10.1 Mosh’un 8 Dersinin Tek Class’ta Sentezi

Bu tek kod parçasında:

Ders Konsept Yerleşim
1 print, sıralı yürütme her print(...) ve kodun akışı
2 değişken, tip, math lr = 1e-3, modulus (batch_idx % 100)
3 input → config dict JSON config yükleme aynı pattern
4 list, append, tuple unpacking train_losses = [], images, labels = batch
5 def, return model(images), criterion(...)
6 if, comparison if torch.isnan(...), if avg_val_loss < best
7 dict, .get config["lr"], batch["image"], model.state_dict()
8 for, range, break, continue tüm döngü iskeleti

Mosh’un 8 dersi, modern AI’nın tek bir eğitim sistemine dökülüyor.

9.10.2 for batch in dataloader — Modern AI’nın Tek Cümlesi

for batch in dataloader:
    ...

Bu dokuz karakter modern AI’nın çekirdek mantığını taşır. GPT-4 eğitilirken bu satır milyonlarca kez çağrıldı. Stable Diffusion’da gigabayt veri akıttı.

Şekil 9.2: ML eğitim döngüsünün anatomi — outer (epochs) × inner (batches)

9.11 Bu Dersin Özeti

  1. while kosul: — koşul True iken tekrar.
  2. for x in koleksiyon: — her öğeye uygula.
  3. range(start, stop, step) — sayı dizisi.
  4. enumerate(...) — (index, eleman) tuple.
  5. zip(a, b) — paralel iteration.
  6. break — döngüden çık.
  7. continue — bu iterasyonu atla.
  8. Nested loops — çarpımsal.
  9. List comprehension[ifade for x in iter if kosul].
  10. ML training loop — Mosh’un sentezi.
ÖnemliTek Bir Cümle

while koşullu tekrar, for koleksiyon gezme — Mosh’un sekiz dakikalık i <= 10 mikro örneği ve “for letter in ‘Draft Academy’” pattern’ı, modern AI’nın çekirdek kodu olan for epoch in range(EPOCHS): for batch in dataloader: train(batch) döngüsünün birebir atasıdır; her sinir ağı eğitimi, her LLM fine-tune, her görüntü sınıflandırması bu döngü üzerinde inşa edilir; break early stopping’tir, continue bad batch skip’tir, enumerate logging’in temelidir; ve Mosh’un üç-hak Guessing Game’i, modern hyperparameter search’ün ilkel formudur.

9.12 Egzersizler

Egzersiz 1. En büyük sayıyı bul (max() kullanma):

nums = [3, 7, 1, 9, 4, 6, 8, 2]

en_buyuk = ???    # baslangic

for n in nums:
    if ???:
        en_buyuk = n

print(en_buyuk)   # 9

Egzersiz 2. Guessing Game (5 hak + ipucu):

secret = "python"
attempts = 5

for i in range(attempts):
    guess = input(f"Tahmin ({attempts - i} hak): ")
    if guess == secret:
        print("Kazandiniz!")
        break
    else:
        ipucu = ???   # eslesen harfler
        print(f"Ipucu: {ipucu}")
else:
    print(f"Kaybettiniz! Kelime: {secret}")

Egzersiz 3. 5×5 çarpım tablosu:

for i in range(1, 6):
    for j in range(1, 6):
        print(???, end=" ")
    print()

Egzersiz 4. (enumerate + zip + list comp)

isimler = ["Deniz", "Aylin", "Mosh"]
yaslar = [35, 28, 40]

# Klasik:
yas_dict = {}
for ad, yas in zip(isimler, yaslar):
    yas_dict[ad] = yas

# Comprehension (tek satir):
yas_dict_compact = {???}

# Enumerate ile numaralandirilmis:
sirali_dict = {???}
# {1: "Deniz", 2: "Aylin", 3: "Mosh"}

Egzersiz 5. (Builder eksen — fake training loop)

import random

dataset = [random.uniform(0, 1) for _ in range(1000)]

EPOCHS = 10
BATCH_SIZE = 50

train_losses = []
best_loss = float('inf')
patience_counter = 0
PATIENCE = 3

for epoch in range(EPOCHS):
    epoch_losses = []

    n_batches = ???   # dataset // BATCH_SIZE
    for batch_idx in range(n_batches):
        start = batch_idx * BATCH_SIZE
        end = start + BATCH_SIZE
        batch = ???   # dataset slicing

        loss = sum(batch) / len(batch) + random.uniform(-0.1, 0.1)

        if batch_idx % 5 == 0:
            print(f"E{epoch} B{batch_idx}: {loss:.4f}")

        epoch_losses.append(loss)

    avg_loss = ???
    train_losses.append(avg_loss)

    print(f"Epoch {epoch} avg: {avg_loss:.4f}")

    if avg_loss < best_loss:
        best_loss = avg_loss
        patience_counter = 0
    else:
        patience_counter += 1
        if patience_counter >= PATIENCE:
            print("Early stopping!")
            break

print(f"\nBitti! Best loss: {best_loss:.4f}")

PyTorch eğitim kodunun iskeletini birebir anlamış olacaksın.

9.13 Sonraki Ders İçin Hazırlık

Ders 9: Uygulama — Çevirmen ve İyi Yorum Alışkanlığı

Kısa bir pratik ders. Mosh’un Ch 25 + Ch 26 (Translator + Comments).

  • Mosh’un Ch 25-26’sını izle (2:52:44-3:04:23, ~12 dk).
  • Şu cümleyi içselleştir: “Yorum kodu çalışmaz ama okuyucuya rehberlik eder.”
İpucuBu dersten tek bir şey alıp gideceksen

for batch in dataloader: — bu dokuz karakter modern AI’nın çekirdek mantığını taşır; Mosh’un Ch 22’de öğrettiği for letter in "Draft Academy": ve Ch 20’de öğrettiği while i <= 10: mikro örnekleri, GPT-4 eğitilirken, Stable Diffusion’da, BERT fine-tune’larında birebir aynı yapıyla milyonlarca kez çağrıldı; break early stopping’dir, continue bad batch skip’tir, enumerate logging’dir, nested loops vectorization kararının kapısıdır — Mosh’un sekiz dersinde öğrettiği her şey bu derste tek bir ML eğitim sisteminde birleşiyor.