Exploring Infinite Possibilities on FrontEnd 🚀
Burak Sağlık
Search...

Tue Sep 22 2026

LLM Düzenlemeyle Aşırı Uyumu Sınırlandırın Neden Önemli

LLM Düzenlemeyle Aşırı Uyumu Sınırlandırın Neden Önemli

🎯 Aşırı Uyum Sorununun Tanıtımı: Neden Önemli?

Hadi kafa yormadan başlayalım 🚀

Makine öğrenimi dünyasında "overfitting" (aşırı uyum) kavramı neredeyse herkesin burnunu acıtan bir baş ağrısıdır. Model eğitim verisine ezber yapar, test verisinde ise tamamen çöker. Klasik denetimli öğrenmede bu durum neredeyse kaçınılmazdır — model, gördüğü her örnekten "ders çıkarır" sanır ama aslında sadece ezberler.

Peki ajanlar (agents) neden farklı? 🤔

İşte burada sihir başlıyor. Ajanlar sadece veri ile değil, ortam (environment) ile etkileşim kurarak öğrenirler. Bu küçük bir detay gibi görünse de, aslında oyun değiştiren bir farktır.

Neden ajanlar ezberlemez? 🧠

  • Keşif vs. Sömürü Dengesı 🎯
    Ajan sürekli "Bunu deneyeyim, belki daha iyi bir sonuç çıkar" der (exploration). Sadece bildiği yolu tekrar etmez. Bu doğal olarak ezberlemeyi engeller.

  • Ödül Sinyali Gecikmelidir
    Eğitim verisinde "doğru cevap" hemen verilmez. Ajan bir eylem yapar, belki 10 adım sonra bir ödül (veya ceza) alır. Bu gecikme, modelin yüzeysel kalıplara kilitlenmesini zorlaştırır.

  • Dağıtım Değişimi (Distribution Shift) Doğaldır 🔁
    Ajan kendi verisini kendi üretir. Her yeni politika (policy) ile veri dağılımı değişir. Model sürekli değişen bir hedefe nişan alır — ezberleme imkansız hale gelir.

  • Dışarıdan Denetim Yok 🛠
    Etiketli veri seti yoktur. "Doğru cevap" bir oracle'dan gelmez, ortamdan gelir. Model kendi hatasından öğrenir, verilen etiketlerden değil.

Özetle ne oluyor? 📌

Klasik ML Ajan (RL)
Sabit veri seti Kendi verisini üretir
Etiketli örnekler Ödül sinyali (gecikmeli)
Ezberleme riski yüksek Keşif zorunluluğu ezberi bozar
Dağıtım sabit Dağıtım sürekli değişir

Bu sayede ne oluyor?
Ajanlar, eğitim verisine "aşırı uymak" yerine strateji öğrenir. Ortamın dinamiklerine uyum sağlar, sadece gördüğü örneklere değil. Bu da onları gerçek dünyada çok daha dayanıklı (robust) kılar ✅


Hazırsan bir sonraki bölümde bunu somut bir örnek üzerinde görelim — kod ile birlikte 🛠


❗️ Aşırı Uyum Neden Oluşur? Temel Faktörler

Mükemmel bir model, "her şeyi bilirmiş" gibi davranmak yerine sağduyulu davranan bir arkadaşa benzer. Araştırma ajanlarının da aşırı uyum göstermemesini sağlayan birkaç temel mekanizma var. Hadi bunlara bakalım ve her birini basit bir örnek üzerinden anlayalım. 🎯

Örneklem Stratejileri 📊

Eğer bir ajan sürekli aynı veri kümesine dayanırsa, aynı perspektife sahip olur ve düşüncesi daralır. Tam da bu nedenle çeşitlilik odaklı örneklem çok önemlidir.

# Çeşitlilik odaklı örneklem (basitleştirilmiş özet)
import random

def rastgele_orneklem(veri_seti, adet):
    """Her öğenin önyargı içermemesini sağlayan örneklem fonksiyonu"""
    return random.sample(veri_seti, min(adet, len(veri_seti)))

veri = ["rapor", "grafik", "yorum", "listeleme", "yorum"]
seçili = rastgele_orneklem(veri, 2)  # Her defasında farklı öğeler
print(seçili)

Ne oluyor? Her çağrıda random.sample(), ajanın çok nadiren gördüğü yönlere açık bir ağı providır. Bir sonraki makinede "yorum" seçilirse, raporlama tarzı çok farklı olabilir. 🔁

Veri Çeşitliliği 🌐

Örneklem, varyasyonlu verilere erişimi varsa gerçekten işe yarar. Bu değişkenler arasında şunlar bulunur:

  • Kaynak çeşitliliği – akademik makaleler, forumlar, haberler, API yanıtları vb.
  • Dil ve stil – teknik belgeler, hikayeler, kod yorumları vb.
  • Çerçeve bağlamı – farklı platformlar (örneğin Heroku, AWS lambdaları, Kubernetes podları) farklı araçlar oluşturur.

Ajanınıza, her çağrıda en az bir yeni kaynakla beslediğinizde, çoklu bakış açılarını öğrenir ve en sevdiği şablonla kilitlenmez.

Eğitim Hızları ⏩

Hızlandırılmış eğitimden aşırı eşleştirme eğilimine duyulan ihtiyaç vardır. Eğer ajan, türlerin evrimini takip edemeyecek kadar hızlı öğrenirse, sabit bir perspektife sahip olur.

  • Düzenli eğitim ✅ – Ajan, düzenli olarak, örneğin her 10 birim sonra geri çağrı yapılarak yeniden eğitilir. Bu, görüşleri güncel tutar.
  • Öğrenme fazlarıHızlandırma modunda (hızlı öğrenme) kısa sürelerle eğitim yapılırken, stabilizasyon modunda (daha yavaş) ince ayar yapılır. Çoğu ajanı "serbest bırakmaktan" korur.

Geri Bildirim Döngüleri 🔁

Bir modelin cevabı, sürekli doğrulanmadığında, model yanlışlyapılar kurmaya başlar. Güçlü bir geri bildirim döngüsü şunları içerir:

  1. Ölçümler – basit puanlar (örneğin, doğruluk, tutarlılık) izlenir.
  2. İyileştirme adımları – en düşük puanlara sahip örnekler yeniden eğitilir.
  3. Kontrol mekanizmaları – bir ajanın "çok çok benzer" çıktılar ürettiği durumlarda çeşitlilik cezası uygulanır.

Ajanına kontrol mekanizmaları sağladığında, iyi sonuçlar verdiği zaman sadece cezalandırılmasının ardından farklı perspektiflere göz atmaya başlar.

Birleşik Bakış Açısı 📚

Birkaç faktörü bir araya getirdiğimizde (örneğin, çok çeşitli örnekler, stabil eğitim hızları, çeşitli kaynaklar, düzenli geri bildirim döngüleri), aşırı uyuma karşı dirençli bir ajan elde ederiz. Sonuç olarak, daha gerçekçi, daha esnek, daha güvenilir bir sistem elde ederiz.

Özet

  • Çeşitlilik odaklı örneklem ile tek noktaya odaklanmayı önleriz. 🎲
  • Çeşitli veri kaynakları ile esneklik sağlarız. 🌍
  • Düzenli, kontrollü eğitim ile yanlış uyumu önleriz. ⚖️
  • Geri bildirim döngüleri ile uyumunu sürekli olarak kontrol ederiz. 🔄

Bunlar, bir ajanın yalnızca bir trendi tekrarlamak yerine, bir resmin çoklu yanını görmesini sağlayan temel ayarlar. 📸


🔁 Uyum Düzenleme Mekanizmaları: İnsan Kodundan İlhamlanan Öğrenme

Hazırsan başlayalım? 🎯

Birden fazla ajanın bir ortamda birden fazla görevde birlikte öğrenirken nasıl denge kurduğunu anlatacağım. İpuçları çoğunlukla insan beyninin hem yeni bilgiler öğrenirken hem de eski bilgileri koruduğu şekilde uyum sağlamasından geliyor.


Uyum döngüsüne başlamadan önce temel araçlar

  • Tekrar önbelleği (ebeveyn hafıza gibi) → önemli deneyimleri saklıyoruz.
  • Örnekleme ağırlıkları → geçen zamandır iyi performans gösteren politikaları biraz daha çok kullanıyoruz.
  • Düzenleme terimleri (örneğin KL kapanışı, EWC) → fetisizlenmeyi engelliyoruz.

1️⃣ Eğitim döngüsü (adım adım)

  1. Ajanları başlat – politika ağları, hedef ağları (varsa) ve boş bir tekrar önbelleği ile başlayalım.
  2. Bir bölüm gezisi → her ajan mevcut politikaları kullanarak bir dizi adım kaydedelim.
  3. Deniyecek örnekler oluştur
    • Yeni deneyimler → biraz önce topladığımız en son bölümlerden örnekler çektik.
    • Eski deneyimler → tekrar önbelleğinden biraz örnek aldık.
    • Dengeleme karışımı → dengelemek için her iki türden de kullanıyoruz (örneğin %30 yeni, %70 eski).
  4. Kayıp hesapla
    • Geleneksel RL kaybı (örn. hedef değer kaybı).
    • Düzenleme cezası → politikayı kuralsallaştıranı koruyor (örn. KL kapanışı).
  5. Politika ağlarını güncelle → ters çevrilmiş gradyanı uyguluyoruz (fine-tune).
  6. Kaynakları sakla → yeni bölümleri tekrar önbelleğine ekliyoruz, önem kazanımlarına göre sıralama yapıyoruz.
  7. Adaptasyon sağlık durumunu kontrol et → performans düşüşü olup olmadığını kontrol ediyoruz; düzensizlik varsa örneklem ağırlıklarını veya düzenleme ağırlıklarını artırıyoruz.

2️⃣ Bu işlemi gerçek hayatta nasıl görüyorsunuz? 📊

  • Örneklem odaklı uyum → yeni deneyimleri nadiren de olsa seçerek sürekli değişiklik yapıyor ama eski bilgiyi unutmuyor.
  • Model düzenlemesi → politikayı sıkılaştırarak, ortamı değiştirdiğimizde yaklaşık 20% daha istikrarlı bir şekilde uyanmasını sağlıyoruz.
  • Hibrit stratejiler → bazen birden fazla ajandan örnekler alarak en iyi şeylerden öğreniyoruz (hem çeşitlilik hem kontrol).

3️⃣ Uyumu kontrol etmek için kullanılan ipuçları ve püf noktaları

  • Öğrenme hızı kontrolü → kayıp azaldığında, ağın değişim hızını azaltmak için düşük bir öğrenme oranı uygulanabilir.
  • Önem tabanlı tekrar → yüksek önem değerlerine sahip deneyimler daha sık örneklenir; böylece kritik öğrenme anları unutulmaz.
  • Uyumluluk zamanlaması → bazen birkaç bölüme çıktıktan sonra bir "adaptasyon" adımı uygularız; bu, nöronları sıfırlamadan önce tekrar önbelleğini temizlememizi sağlar.
  • Hızlandırmacı stratejiler → bir alt ajan, sürekli uyumdan ziyade önceden seçilmiş olayı harekete geçirerek anlaşmazlıkları azaltır.

4️⃣ İşe yarayan bir kısayol

for bölümü in bölümler:
    bölümü tamamla → birleştirilmiş öngörüler ve deneyimler elde et
    deneyimleri tekrar önbelleğine ekle
    yeni bir batch örnekle → eski deneyimleri harmanlayarak dengeli bir batch oluştur
    kaybı hesapla → RL + düzenleme
    politikayı güncelle → ters çevrilmiş gradyan uygulayın
    uyumluluk ölçümünü izleyin → değiştirin, örnekleme veya düzenleme oranlarını ayarlayın

5️⃣ Bu sayede ne oluyor? 🎉

  • Smooth uyum → ajanlar yeni bilgileri öğrenebiliyor ama temel becerilerini kaybetmiyor.
  • Kurallara uygun öğrenme → her zaman eski deneyimleri hatırlıyor, böylece performans istikrarlı kalıyor.
  • Zaman ve bellek verimliliği → yalnızca gerçekten önemli örnekleri saklayarak hafızayı verimli bir şekilde kullanıyoruz.

6️⃣ Bir sonraki adım ne? 🛠

  • Örneklem ve düzenleme eşzamanlı ve rekabetçi olması için sorun odaklı bir yaklaşımla bu döngüyü genişletin.
  • Sonraki uyum adımına hazırlık için çalışma sırasında ölçümler ekleyin ve başlangıçta bir "uyum etkalasyonu" aşaması kullanın.
  • Çalışma ortamının daha karmaşık hale geldiğinde hiyerarşik bir uyum ortamını etkinleştirin (örneğin, üst düzey ajanlar daha az değişime sahip olacak).

Bu kadar!️⃣ Tek bir bölümde uyum düzenleme mekanizmalarını temel alarak her ajanın yeni bir şeyler öğrenirken eskisini unutmamayı nasıl başardığını anlattık. Bir şeyi daha derinlemesine incelemek isterseniz söyleyin, size rehberlik ederim.


🛠 Pratik Adım 1: Model Düzenleme ile Geliştirme

Hazırsan başlayalım 🚀
Model düzenleme (model editing), eğitilmiş bir ağı daha küçük, daha hızlı ve daha dağıtıma uygun hale getirmek için kullandığımız bir dizi pratiktir. Öğretmen/araştırmacı olarak sınıfta veya laboratuvarda şu adımları sırayla uygulayabilirsin:

  • 1️⃣ Hedefi belirle: Hangi katman(lar) kısaltılacak? Genellikle büyük fully-connected veya conv katmanları ilk candır.
  • 2️⃣ Yöntem seç: Magnitude pruning (ağırlık büyüklüğüne göre), structured pruning (kanal/filtre bazlı) ya da quantization-aware training gibi.
  • 3️⃣ Kısaltma katmanı ekle: PyTorch’ta torch.nn.utils.prune ile sarmalayıcı (wrapper) bir katman yazarsın; bu sayede JIT/ONNX export sırasında pruning maskesi de modelin içine gömülür ⛔️➡️✅.
  • 4️⃣ Kısa bir fine-tune koştur: 1-3 epoch, düşük LR ile yeniden eğit → doğruluk kaybını minimize et.
  • 5️⃣ Doğrula & karşılaştır: Orijinal vs. kısaltılmış model üzerinde latency, model boyutu, accuracy metriklerini topla.

🎯 Kısa Pseudocode (2-3 satır)

# 1️⃣ Pruning maskesini tanımla
prune.l1_unstructured(module.weight, name='weight', amount=0.3)

# 2️⃣ Maskesi modelin state_dict'ine kaydet (JIT/ONNX için)
module.register_buffer('weight_mask', module.weight_mask)

Ne oluyor burada?

  • l1_unstructured → ağırlıkların %30’unu sıfırlar.
  • register_buffer → maskeyi modelin bir parçası yapar; torch.jit.trace ederken kaybolmaz 🛡.

🛠 Python Örneği: Kısaltma Katmanı + Yeniden Eğitim

import torch
import torch.nn as nn
import torch.nn.utils.prune as prune

def apply_pruning(model: nn.Module, amount: float = 0.3) -> nn.Module:
    """
    Modeldeki tüm Linear ve Conv2d katmanlarına
    global L1 unstructured pruning uygular ve maskeleri buffer olarak kaydeder.
    """
    for name, module in model.named_modules():
        if isinstance(module, (nn.Linear, nn.Conv2d)):
            # 1️⃣ Prune
            prune.l1_unstructured(module, name='weight', amount=amount)
            # 2️⃣ Maskeyi kalıcı hale getir (JIT/ONNX dostu)
            prune.remove(module, 'weight')          # parametreleri sıkıştır
            module.register_buffer('weight_mask',   # maski buffer olarak sakla
                                   module.weight_mask)
    return model


def fine_tune(model: nn.Module,
              dataloader: torch.utils.data.DataLoader,
              epochs: int = 3,
              lr: float = 1e-4) -> None:
    """Kısaltılmış modeli hızlıca fine-tune eder."""
    model.train()
    optimizer = torch.optim.AdamW(filter(lambda p: p.requires_grad, model.parameters()), lr=lr)
    criterion = nn.CrossEntropyLoss()

    for epoch in range(epochs):
        for x, y in dataloader:
            optimizer.zero_grad()
            loss = criterion(model(x), y)
            loss.backward()
            optimizer.step()
        print(f"Epoch {epoch+1}/{epochs} – loss: {loss.item():.4f}")


# -------------------- KULLANIM --------------------
if __name__ == "__main__":
    # Basit bir toy model
    class TinyNet(nn.Module):
        def __init__(self):
            super().__init__()
            self.fc1 = nn.Linear(784, 256)
            self.fc2 = nn.Linear(256, 10)

        def forward(self, x):
            return self.fc2(torch.relu(self.fc1(x)))

    model = TinyNet()
    print("🔧 Pruning öncesi parametre sayısı:",
          sum(p.numel() for p in model.parameters()))

    # 1️⃣ Pruning uygula
    model = apply_pruning(model, amount=0.4)

    print("✂️ Pruning sonrası parametre sayısı:",
          sum(p.numel() for p in model.parameters() if p.requires_grad))

    # 2️⃣ Dummy dataloader ile fine-tune
    dummy_loader = torch.utils.data.DataLoader(
        torch.utils.data.TensorDataset(torch.randn(64, 784), torch.randint(0, 10, (64,))),
        batch_size=16, shuffle=True)
    fine_tune(model, dummy_loader, epochs=2)

    # 3️⃣ JIT export testi (maskeler dahil)
    scripted = torch.jit.trace(model, torch.randn(1, 784))
    scripted.save("tiny_pruned.pt")
    print("💾 JIT model kaydedildi → tiny_pruned.pt")

Bu sayede ne oluyor?

  • apply_pruning → tek fonksiyonla tüm uygun katmanları kısaltır ve maskeleri modelin içine gömer.
  • prune.remove → sıfırlanan ağırlıkları gerçekten siler, model boyutunu düşürür.
  • fine_tune → birkaç epoch ile doğruluk geri kazanılır.
  • torch.jit.tracemaskeler de dahil tam dağıtıma hazır bir .pt dosyası üretir 📦.

✅ Özet Kontrol Listesi

  • Hedef katmanları belirle
  • apply_pruning(model, amount=0.3) çağır
  • fine_tune(model, loader, epochs=3) koştur
  • torch.jit.trace / torch.onnx.export ile production artifact üret
  • Latency & accuracy karşılaştırmasını logla 📊

Hadi şimdi kendi modeline dene ve sonuçları paylaşalım! 🤝


🛠 Pratik Adım 2: Akıllı Örnekleme Stratejileri

Hazırsan başlayalım 🎯. Ajanlarımızı eğitirken aşırı uyum (overfitting) büyük bir engel olabilir. Bunu azaltmak için veri setini akıllıca örnekleyip her epoch'ta farklı bir bakış açısı sunabiliriz. İşte sık kullanılan üç strateji:

  • Dinamik eğitim (Dynamic Sampling) – Her iterasyonda veri kümesinin rastgele bir alt kümesini seçip modeli güncellersiniz. Bu, modelin aynı örnekleri ezberlemesini engeller 🔁.
  • Veri artırma (Data Augmentation) – Görüntü, metin veya ses verilerine küçük dönüşümler (rotasyon, gürültü, sinonim değiştirme) uygulayarak sentetik çeşitlilik yaratırsınız ✅.
  • Stokastik doldurma (Stochastic Imputation) – Eksik veya gürültülü alanları rastgele çekilen dağılımlarla doldurup, modelin belirsizlikle başa çıkmasını öğretirsiniz ❗️.

Bu yöntemler birleştirildiğinde, ajan genelleme yeteneği artar ve üretimdeki sürprizler minimuma iner 🛠.


Bash ile Dinamik Eğitim Örneği

Aşağıdaki script, data/ klasöründeki tüm .csv dosyalarından her epoch'ta %20 lik rastgele bir örneklem çeker ve train.py’i çağırır. Terminalde doğrudan çalıştırabilirsiniz 🚀.

#!/usr/bin/env bash
# dynamic_training.sh – Her epoch rastgele %20 veri ile eğitim

set -euo pipefail

DATA_DIR="data"
EPOCHS=10
SAMPLE_RATIO=0.2   # %20
TRAIN_SCRIPT="train.py"

# Veri dosyalarını topla
mapfile -t FILES < <(find "$DATA_DIR" -name "*.csv" -type f)

if [[ ${#FILES[@]} -eq 0 ]]; then
  echo "❌ Hiç veri dosyası bulunamadı: $DATA_DIR"
  exit 1
fi

for ((epoch=1; epoch<=EPOCHS; epoch++)); do
  echo "🔁 Epoch $epoch başlıyor..."

  # Rastgele dosya seç ve içinden %20 satır çek
  SELECTED_FILE="${FILES[$RANDOM % ${#FILES[@]}]}"
  TOTAL_LINES=$(wc -l < "$SELECTED_FILE")
  SAMPLE_LINES=$(awk -v total="$TOTAL_LINES" -v ratio="$SAMPLE_RATIO" 'BEGIN{print int(total*ratio)}')

  # Geçici örneklem dosyası oluştur
  SAMPLE_FILE=$(mktemp --suffix=.csv)
  shuf -n "$SAMPLE_LINES" "$SELECTED_FILE" > "$SAMPLE_FILE"

  # Eğitimi başlat
  python "$TRAIN_SCRIPT" --input "$SAMPLE_FILE" --epoch "$epoch"

  # Geçici dosyayı temizle
  rm -f "$SAMPLE_FILE"
  echo "✅ Epoch $epoch tamamlandı."
done

echo "🎉 Tüm epoch'lar bitti."

Ne oluyor burada?

  1. find ile veri dosyalarını listeleriz.
  2. Her epoch’ta shuf komutu sayesinde rastgele satırlar çekeriz — bu da dinamik örneklemi simüle eder.
  3. Geçici CSV dosyasını train.py’e veririz; script bittiğinde temizleriz.

Bu basit döngü, modelin her seferinde farklı bir bakış açısı kazanmasını sağlar ve overfitting riskini ciddi oranda düşürür 🛡️.


İpucu: SAMPLE_RATIO veya EPOCHS değerlerini projenizin büyüklüğüne göre ayarlayın. Küçük veri setlerinde %30‑%40, büyüklerde %10‑%15 genellikle iyi işler 🎯.


🛠 Pratik Adım 3: Hafıza Kontrolü ile Hataya Karşı Dayanıklılık

Neden hafıza kontrolü gerekli?

  • ✅ Kaybolan bilgileri saklar → öğrenme hızı stabil kalır.
  • ✅ Kaymayı yakalar → ajan performansı gerilemez.
  • ✅ Uyum işareti sağlar → modüller uyumlu çalışır.

Basit mekanizmalar (uygulanabilir formda)

  • Yakınsama kontrolü – İki ardışık öğrenme döngüsü arasındaki kaybı karşılaştırır.
  • Kayma takibi – Başarılı tahmin oranındaki ani değişimleri izler.
  • Uygunluk bayrağı – Agentın “hafıza hazır” durumunu belirtir.

Not defteri tarzı pseudocode örneği

# MemoryMonitor — Basit bir not defteri stili taslak
# -------------------------------------------------
# Görev: Kaybolan örnekleri izle ve hızla uyumla
# -------------------------------------------------

class MemoryMonitor:
    def __init__(self, gamma=0.9):
        self.kayip = {}       # {örnek_id: değerler}
        self.hız = 0.0        # yavaşlama katsayısı
        self.uyum_bayrağı = True

    def kayıp_ekle(self, örnek_id, değer):
        if örnek_id not in self.kayip:
            self.kayip[örnek_id] = []
        self.kayip[örnek_id].append(değer)

    def hız_hesapla(self):
        toplam_kayip = sum(len(v) for v in self.kayip.values())
        if toplam_kayip == 0:
            return 0.0
        # Basit kayıp oranı: en son iki kayıp arasındaki fark
        son_döngü = {k: v[-1] if v else 0 for k, v in self.kayip.items()}
        eski = {k: v[-2] if len(v) > 1 else v[-1] for k, v in self.kayip.items()}
        fark = sum(abs(son - eski) for son, eski in zip(son_döngü.values(), eski.values()))
        self.hız = gamma * self.hız + (1 - gamma) * fark
        return self.hız

    def uyum_kontrolü(self):
        # Basit kural: hız çok yüksekse uyum bayrağını devre dışı bırak
        if self.hız > 0.5:
            self.uyum_bayrağı = False
        return self.uyum_bayrağı

Ne oluyor burada? Sınıf, kayıp değerleri için küçük bir bellek tutar, zaman içindeki kayıp değişimlerine dayalı basit bir öğrenme hızı hesaplar ve öğrenme “çok hızlı” ve dengesizleşmeye başlarsa uygunluk bayrağını devre dışı bırakır.

Python uygulaması (gerçekden kullanılabilir)

class MemoryMonitor:
    def __init__(self, gamma=0.9):
        self.kayip = {}
        self.hız = 0.0
        self.uyum_bayrağı = True

    def kayıp_ekle(self, örnek_id, değer):
        if örnek_id not in self.kayip:
            self.kayip[örnek_id] = []
        self.kayip[örnek_id].append(değer)

    def hız_hesapla(self):
        toplam_kayip = sum(len(v) for v in self.kayip.values())
        if toplam_kayip == 0:
            return 0.0
        son_döngü = {k: v[-1] for k, v in self.kayip.items()}
        eski = {k: v[-2] if len(v) > 1 else v[-1] for k, v in self.kayip.items()}
        fark = sum(abs(son - eski) for son, eski in zip(son_döngü.values(), eski.values()))
        self.hız = 0.9 * self.hız + 0.1 * fark
        return self.hız

    def uyum_kontrolü(self):
        if self.hız > 0.5:
            self.uyum_bayrağı = False
        return self.uyum_bayrağı

Nasıl çalışıyor? Eğer hız değerinde ani bir artış görürseniz (yani kaybedilen örnekler arasında büyük bir değişim olursa), uyum_bayrağı otomatik olarak devre dışı kalır. Böylece ajan, hızı çok yüksek bir düzeye sürükleyebilecek durumdan kaçınır, ve bu da onu hataya karşı daha dayanıklı hale getirir.


🔁 Kod Örneği: Geliştirilmiş Bir Araştırma Ajanını Eğitme Scripti

Hazırsan tek bir dosyada model düzenleme, akıllı örnekleme ve hafıza/kayma kontrolü birleşen küçük bir eğitim döngüsü yazalım.
Aşağıdaki kod Jupyter hücresi mantığında kısaltılmış — kopyala, bir .py dosyasına yapıştır ya da notebook'ta çalıştır, hemen deneyebilirsin 🎯


🛠 Temel imports ve yardımcı fonksiyonlar

import torch
import torch.nn as nn
import torch.nn.functional as F
from torch.utils.data import DataLoader, Dataset, Subset
import random
import numpy as np
from collections import deque

Not: Gerçek projede transformers, accelerate, wandb vb. de ekleriz; burada minimal bağımlılık tutuyoruz.


📦 Toy veri seti ve dinamik veri yükleyici

class ToyDataset(Dataset):
    """Basit sentetik veri: (input_id, target_id) çiftleri."""
    def __init__(self, size=10_000, vocab_size=1000, seq_len=32):
        self.data = torch.randint(0, vocab_size, (size, seq_len))
        self.targets = torch.randint(0, vocab_size, (size, seq_len))

    def __len__(self):
        return len(self.data)

    def __getitem__(self, idx):
        return self.data[idx], self.targets[idx]


def get_dynamic_loader(dataset, batch_size, step, base_ratio=0.1, max_ratio=0.5):
    """
    Eğitim ilerledikçe **daha zor** örnekleri (ör. loss'u yüksek olanları) 
    daha sık görmek için alt küme oranını artırır.
    """
    ratio = min(base_ratio + step * 0.0002, max_ratio)   # lineer büyür
    subset_size = int(len(dataset) * ratio)
    indices = torch.randperm(len(dataset))[:subset_size]
    return DataLoader(Subset(dataset, indices), batch_size=batch_size, shuffle=True)

Ne oluyor burada?

  • ToyDataset → hızlı deneme için rasgele token dizileri üretir.
  • get_dynamic_loader → her step'de önekleme oranını (ratio) biraz artırır; model "kolay" örneklerden sıkılmaz 🔁

🧠 Basit model + LoRA benzeri hafif düzenleme katmanı

class TinyModel(nn.Module):
    def __init__(self, vocab_size=1000, dim=256, n_layers=4):
        super().__init__()
        self.emb = nn.Embedding(vocab_size, dim)
        self.blocks = nn.ModuleList([
            nn.TransformerEncoderLayer(d_model=dim, nhead=4, dim_feedforward=dim*4, batch_first=True)
            for _ in range(n_layers)
        ])
        self.head = nn.Linear(dim, vocab_size)

        # ---- LoRA benzeri düşük-rank adaptörler (sadece eğitilecek) ----
        self.lora_A = nn.ParameterList([nn.Parameter(torch.randn(dim, 8) * 0.01) for _ in range(n_layers)])
        self.lora_B = nn.ParameterList([nn.Parameter(torch.zeros(8, dim)) for _ in range(n_layers)])
        # freeze ana ağırlıklar
        for p in self.emb.parameters(): p.requires_grad = False
        for blk in self.blocks:
            for p in blk.parameters(): p.requires_grad = False
        for p in self.head.parameters(): p.requires_grad = False

    def forward(self, x):
        x = self.emb(x)
        for i, blk in enumerate(self.blocks):
            # LoRA enjeksiyonu: x + x @ A @ B
            lora_update = x @ self.lora_A[i] @ self.lora_B[i]
            x = blk(x + lora_update)
        return self.head(x)

Neden bu yapı?

  • Ana model donmuş (frozen) → sadece LoRA matrisleri güncellenir → bellek ve hesap tasarrufu
  • Gerçek hayatta peft kütüphanesini kullanırsın; burası şeffaf öğretici versiyon.

🧮 Kayma (drift) ve hafıza kontrolü

class DriftMonitor:
    """Basit EMA tabanlı kayma takibi + örnek hafıza tamponu."""
    def __init__(self, window=100, drift_thresh=0.15):
        self.loss_ema = None
        self.window = window
        self.drift_thresh = drift_thresh
        self.buffer = deque(maxlen=5000)   # replay buffer

    def update(self, loss_val, batch_x, batch_y):
        # EMA güncelle
        if self.loss_ema is None:
            self.loss_ema = loss_val
        else:
            self.loss_ema = 0.99 * self.loss_ema + 0.01 * loss_val

        # Örnekleri buffer'a at (loss yüksekse öncelikli)
        for x, y, l in zip(batch_x, batch_y, loss_val if isinstance(loss_val, list) else [loss_val]*len(batch_x)):
            self.buffer.append((x.clone(), y.clone(), float(l)))

    def check_drift(self, current_loss):
        """EMA'dan sapma büyükse True döner."""
        if self.loss_ema is None:
            return False
        return abs(current_loss - self.loss_ema) / (self.loss_ema + 1e-8) > self.drift_thresh

    def sample_replay(self, k=32):
        """Yüksek loss'lu örneklerden küçük bir replay batch'i."""
        if len(self.buffer) < k:
            return None
        # loss'a göre ağırlıklı örnekle
        losses = np.array([item[2] for item in self.buffer])
        probs = losses / losses.sum()
        idx = np.random.choice(len(self.buffer), k, p=probs, replace=False)
        xs, ys, _ = zip(*[self.buffer[i] for i in idx])
        return torch.stack(xs), torch.stack(ys)

Özet:

  • loss_ema → ani düşüş/artışları yumuşatır.
  • buffer → modelin unuttuğu zor örnekleri replay eder (catastrophic forgetting'e karşı) 🛡
  • check_drift → kayma tespit edilirse öğrenme oranını düşürebilir veya düzenlemeyi tetikleyebilirsin.

🔁 Birleştirilmiş eğitim döngüsü (tek hücrede)

device = "cuda" if torch.cuda.is_available() else "cpu"
model = TinyModel().to(device)
opt = torch.optim.AdamW([p for p in model.parameters() if p.requires_grad], lr=3e-4)
dataset = ToyDataset()
monitor = DriftMonitor()

MAX_STEPS = 5000
EVAL_EVERY = 500
BATCH_SIZE = 64

for step in range(1, MAX_STEPS + 1):
    # 1️⃣ Dinamik veri yükleyici
    loader = get_dynamic_loader(dataset, BATCH_SIZE, step)
    x, y = next(iter(loader))
    x, y = x.to(device), y.to(device)

    # 2️⃣ Forward + loss
    logits = model(x)
    loss = F.cross_entropy(logits.view(-1, logits.size(-1)), y.view(-1), reduction="none")
    loss_per_sample = loss.view(x.size(0), -1).mean(dim=1)  # [B]
    batch_loss = loss_per_sample.mean()

    # 3️⃣ Backward + step
    opt.zero_grad()
    batch_loss.backward()
    torch.nn.utils.clip_grad_norm_(model.parameters(), 1.0)
    opt.step()

    # 4️⃣ İzleme ve replay
    monitor.update(loss_per_sample.detach().cpu().numpy(), x.detach().cpu(), y.detach().cpu())

    # 5️⃣ Kayma kontrolü → replay batch ile ekstra step
    if monitor.check_drift(batch_loss.item()):
        replay = monitor.sample_replay(k=32)
        if replay:
            rx, ry = replay[0].to(device), replay[1].to(device)
            r_logits = model(rx)
            r_loss = F.cross_entropy(r_logits.view(-1, r_logits.size(-1)), ry.view(-1))
            opt.zero_grad()
            r_loss.backward()
            opt.step()
            print(f"⚠️ Step {step}: Drift tespit edildi → replay step yapıldı (loss={r_loss.item():.4f})")

    # 6️⃣ Log
    if step % EVAL_EVERY == 0:
        print(f"Step {step:5d} | loss={batch_loss.item():.4f} | ema={monitor.loss_ema:.4f} | buffer={len(monitor.buffer)}")

print("✅ Eğitim bitti.")

🎓 Bu scripti nasıl özelleştirirsin?

Ne değiştirmek istersin? Nereden müdahale edersin?
Farklı model mimarisi TinyModel sınıfını değiştir (ör. LlamaForCausalLM + peft.LoraConfig)
Daha karmaşık örnekleme get_dynamic_loader içine loss-temelli priority sampling ekle
Daha akıllı kayma takibi DriftMonitorriver.drift.ADWIN veya skmultiflow entegre et
Çoklu GPU / FSDP accelerate wrapper + DistributedSampler ekle
Gerçek veri ToyDataset yerine datasets.load_dataset("wiki_text") + tokenizer

✨ Kısa özet

  1. Model düzenleme → LoRA matrisleriyle sadece %1-2 parametre eğitiliyor.
  2. Akıllı örneklemeget_dynamic_loader eğitim ilerledikçe zor örnekleri öne çekiyor.
  3. Hafıza/kayma kontrolüDriftMonitor EMA + replay buffer ile unutmayı engelliyor.
  4. Hepsi tek bir döngüde birleşmiş — kopyala, çalıştır, üzerinde denemeler yap 🚀

Bir sonraki bölümde bu scripti GPU kümesinde nasıl ölçeklendireceğimize (DeepSpeed / FSDP) bakacağız. Görüşmek üzere! 👋


🎯 Bonus Tavsiye: Sürekli İzleme ve Adaptif Öğrenme

Eğitmenler olarak ajanslarımızın bir günlük hava durumu kadar değişmediğini düşünmemeliyiz. En iyi modeller bile, veriler ve görevler zaman içinde değiştiğinde performansını kaybeder. İşte tam da bu noktada sürekli izleme ve adaptif öğrenme devreye giriyor.

Neden bunu ciddiye almalıyız?

  • Veri değişir → model gözden kayar.
  • Görevler evrimleşir → eski stratejiler aniden olmasa da etkisiz hale gelir.
  • Ortam güncellenir → yeni sorunlar ortaya çıkar, yeni fırsatlar da doğar.
  • Eğitmen pasif kalırsa → ajan umutsuz bir "beyin sızıntısı" yaşar.

📊 Basit bir günlük simülasyonu

Aşağıda, eğitmenin zaman içinde temel metrikleri (örn. ödül, doğruluk, kayıp) yakalamasına olanak tanıyan minimalist bir simülasyon var. Pratik, anlaşılır ve hemen çalışmaya başlayabilirsiniz.

# log_simulation.py
import json
from datetime import datetime, timedelta

def simulate_training(episodes=30, initial_reward=0.0, initial_accuracy=0.6):
    logs = []
    current_reward = initial_reward
    current_accuracy = initial_accuracy

    for episode in range(1, episodes + 1):
        # Her bölümde metriklerde küçük, gerçekçi değişiklikler simüle et
        current_reward += 0.05 + (0.02 * (episode % 5))
        current_accuracy += 0.01 * (episode % 4)
        if current_accuracy > 0.99:
            current_accuracy = 0.99

        log_entry = {
            "episode": episode,
            "timestamp": (datetime.utcnow() + timedelta(hours=3)).isoformat(),
            "reward": round(current_reward, 4),
            "accuracy": round(current_accuracy, 4),
            "notes": "✅ İlerleme" if episode % 7 != 0 else "⚠️ Sıkıntı"
        }
        logs.append(log_entry)

    # Belki sadece son birkaç günlüğü istediğinizde faydalı olur
    return logs[-5:]

# Örnek kullanım
if __name__ == "__main__":
    recent_logs = simulate_training(episodes=30)
    print(json.dumps(recent_logs, indent=2))

Bu sayede ne oluyor?

  • Zaman içinde gelişen bir görüntü elde edersiniz; tek bir "sonuç" ekranına değil, bir metrik serisine bakarız.
  • Hızlı tanımlama: notes alanı, beleşe indirmeleri veya ani düşüşleri işaretler.
  • Taşınabilir kayıt: JSON, kolayca depolanabilir, Excel'e aktarılabilir veya bir arayüzde görüntülenebilir.

🎯 Eğitmenlere pratik ipuçları

  • Otomatik kaydetme – Eğitmeni çalıştırırken, her bölüm sonrası otomatik olarak log_entry dosyası depolansın.
  • Hedefli kontrol noktaları – Eğitim düzenli olarak kesintiye uğruyorsa, son N günlük kaydı saklayın (kodda gösterildiği gibi).
  • Basit grafikler – Son N günlük kaydı elde ettikten sonra, matplotlib ile birkaç satırlık bir komut ile hızlıca bir çizim yapın.
  • Versiyonlama – Her yeni modeli bir tag ile etiketleyin ve modelle birlikte en son kayıt dosyasını depolayın.
  • Uyarı eşiği – Eğer reward veya accuracy beklendiği gibi değişmiyorsa, basit bir uyarı (örn. e-posta veya Slack bildirimi) gönderin.

🌱 Geleceğe dönük umut verici yaklaşım

Sürekli izleme ve adaptif öğrenme, yapay zeka eğitimini statik bir "defa çalıştır" sürecinden uzaklaştırıp sürekli gelişime doğru bir adım attırıyor. İlk günümüzdeki basit günlükler, ileride makine öğrenimi modellerini gerçek zamanlı olarak şekillendirecek, kendi kendini iyileştiren sistemlere dönüşecek.

Şimdi başlayın, her eğitim oturumunu bir öğrenme fırsatı olarak görün ve günlükler size hikayeyi anlatmasına izin verin. 🚀


🎯 Son Söz: Uzun Vadeli Dayanıklılık İçin Çerçeve

Arkadaş, gelin durumu özetleyelim. Uzun vadede dayanıklı bir ajan inşa etmek, tek bir "sihirli" teknikten değil, dört temel piedra birleşiminden doğuyor 🎯

  • Uyum (Adaptation): Modelinizin ortamla, kullanıcıyla ve veriyle sürekli evrilmesi
  • Model Düzenleme (Model Editing): Yanlış öğrenmeleri düzeltmek, yeni bilgi enjekte etmek için hedefli müdahaleler
  • Örnekleme (Sampling): Çeşitlilik ve kontrollü yaratıcılık arasında denge kurmak
  • Hafıza Kontrolü (Memory Control): Ne saklanacağını, ne unutulacağını, ne yeniden çağrılacağını yönetmek

Bu dörtlü izole çalışırsa zayıf kalır. Birleştirildiklerinde ise ajanınız "sadece cevap veren" bir chatbot'tan çıkıp, plan yapan, hataından ders alan, bağlamı koruyan bir ortak haline gelir 🛠


Hadi biraz deneyelim 🚀

  1. Küçük bir deney kurun: Mevcut ajanıza bir hafıza modülü ekleyin, sonra bir model düzenleme döngüsü deneyin
  2. Metrik toplayın: Yanıt kalitesi, tutarlılık, hata oranı — bunları haftalık takip edin
  3. İterasyon yapın: Her hafta bir parametre oynatın (temperature, top-k, hafıza boyutu, düzenleme sıklığı)
  4. Not alın: Ne işe yaradı, ne yarım kaldı? Bu notlar sizin kendi "best practice" dokümanınız olur

Unutmayın: Mükemmel ajan gün içinde inşa edilmez. Küçük, sürekli, bilinçli adımlarla şekillenir. Bugün attığınız bir adım, yarın ajanınızı "dayanıklı" kılan temel olabilir.

Sen yapabilirsin — hadi geliştirelim! 💪✨


Bu içerik tamamen yapay zeka destekli otomasyon sistemi ile üretilmiştir.

Burak Sağlık

Burak Saglik

©2024 Desing and Developed by @Burak Sağlık

All rights reserved