---
title: 'Derin Öğrenme'
source: 'https://academia.sh/tr/kurslar/derin-ogrenme'
language: tr
updated: '2026-08-17T04:42:02+00:00'
license: 'CC BY-SA 4.0'
lessons: 24
outcomes:
    - 'Bir sinir ağının ileri ve geri geçişini kendi eliyle yazar ve eğimi sayısal türevle doğrular'
    - 'Evrişimli, yinelemeli ve dikkat temelli mimarileri uygun veri yapısına uygular ve kattıklarını ölçer'
    - 'Eğitim sürecini düzenlileştirme ve eniyileme ayarlarıyla kararlı kılar ve koşum değişkenliğini raporlar'
---

# Derin Öğrenme

Bir ağın ürettiği sayının kapasitesinden mi eğitiminden mi geldiğinin, aynı ağın ikinci koşumuyla birlikte ölçülmesi: tek katmanlı ağın doğrusal modelle aynı olması, doygunluk ve ölü birim sayısı, katman genişledikçe parametre ve çarpma sayısı, kayıp seçiminin oynattığı sayı, geri yayılımın sayısal türevle doğrulanması, üç eniyileyicinin aynı bütçedeki kaybı, derinleştikçe sönen eğim, seyreltme ve erken durdurmanın katkısı, toplu normalleştirmenin izin verdiği öğrenme adımı, evrişimin tam bağlı katmana göre parametre kazancı, havuzlamanın attığı bilgi, atlamalı bağlantının eğimi ilk katmana taşıması, gizli durumun uzun dizide taşıdığı bilgi, dikkat ağırlıklarının nereye düştüğü, konum kodlamasının zorunluluğu, öğrenilen gömme ile öğrenilmeyen izdüşümün farkı, aktarımın kaç örnekle kattığı, otomatik türevin elle yazılan eğimle farkı, toplu boyut ile bellek ilişkisi ve koşum değişkenliğinin aramayı yanıltması.

## Sinir Ağı Temelleri

Tam bağlı bir ağın her parçasının ne kattığının ve aynı ağın ikinci koşumunun ne kadar oynadığının ölçülmesi: tek katmanlı ağın doğrusal modelle aynı şey olması ve katman eklemenin değiştirdiği, doygunluğun eğimi küçültmesi ile ölü birim sayısı, katman genişledikçe parametre ve çarpma sayısının büyümesi, kayıp seçiminin aynı ağda iki ayrı sonuç vermesi ve kaybın ölçütle aynı şey olmaması, geri yayılımın sayısal türevle doğrulanması, üç eniyileyicinin aynı tur bütçesinde ulaştığı kayıp ve kararlılığı, derinleştikçe sönen ve patlayan eğim, seyreltme ile erken durdurmanın katkısı ve erken durdurmanın hangi kümeden okunduğu, toplu normalleştirmenin izin verdiği öğrenme adımı.

### Algılayıcı ve Çok Katmanlı Ağ

Source: https://academia.sh/tr/kurslar/derin-ogrenme/algilayici-ve-cok-katmanli-ag

Bir ağın sayısının kapasitesinden mi eğitiminden mi geldiğinin ilk kez ölçülmesi: tek katmanlı ağ, sıfırdan ilklendirildiğinde M27/K03'ün doğrusal modelinin üç ayar değerindeki üç sayısını da son basamağına kadar veriyor. Küçültülmüş 300 satırlık eğitim kümesinde 113 parametreli iki katmanlı ağ dört adayla 0,7857'ye çıkıyor, taban çizgisi 0,7579; ama aynı ağın yalnız başlangıç değerleri değiştirilen ikinci koşumu 0,7698 veriyor ve beş koşumun bandı 0,7659-0,7857. Koşum değişkenliği beş abone, kapasitenin kattığı bir abone; etkinleştirmesi doğrusal bırakılan iki katmanlı ağ 113 parametresine karşın tek katmanlının bandından çıkamıyor.

Yirmi bir derste — on biri etiketsiz — her yöntem özniteliklerin verildiği varsayımıyla çalıştı.
Ölçekleme, kodlama, üretme ve azaltma hep elle karar verildi ve her kararın bedeli ayrı ayrı
ölçüldü. Bu kararları da verinin kendisinden öğrenen bir yordamın neyi kazandırdığı ve neyi
görünmez kıldığı, hiç sorulmadı.

Sinir ağı bu soruya verilen bir cevap iddiasıdır: ara temsili elle tasarlamak yerine ara
katmanların ağırlıklarını da eğitimle belirlemek. Bu ders o iddianın en küçük halini kurar ve
kursun üç sayısını yerleştirir: **taban çizgisi**, **ağın sayısı**, **aynı ağın yalnız başlangıç
değerleri değişen ikinci koşumu**. Üçüncüsü kursun imzasıdır, çünkü bir ağın sayısı kapasitesinden
değil eğitiminden gelebilir. Bir şey daha baştan duyurulur: bu kurgu tablo verisinde ağın karar
ağacını ya da doğrusal modeli geçmesi beklenmiyor ve bu saklanmayacak.

- **SA1.** Küme, bölme ve tohum M27/K01–K04'ten aynen sürer: kurgu abone tablosu, 756/252/252,
  tohum 20260218. Hedef **şüpheli** etiketidir ve taban çizgisi en sık sınıfı söylemektir.
- **SA2.** Öznitelik kümesi M27/K02'nin bıraktığı on iki sütundur ve kurs boyunca sabittir. Ağ bu
  sütunları **hazır alır**; ölçekleme, kodlama ve türetme kararları hâlâ elle verilmiştir.
- **SA3.** Sütunlar eğitim kümesinden öğrenilen ortalama ve değişkenlikle ölçeklenir. M27/K02 bu
  adımın eğim temelli bir modele +0,0437 kattığını ölçmüştü; burada varsayılır.
- **SA4.** Eğitim kümesi bu kursta **300 satıra küçültülür**. Gerekçe koşum süresidir: her ders
  aynı ağı en az iki kez eğitir. Küçültmenin bedeli bu derste ölçülür.
- **SA5.** Çözüm **eğim inişidir**; yordamı M27/K03 `dogrusal-modeller`'de kuruldu ve burada
  tekrarlanmaz. Eğimin katmanlara nasıl dağıtıldığı `05`'in konusudur.
- **SA6.** Ağırlıklar **kazanç ölçekli ilklendirme** ile başlatılır: başlangıç aralığı girdi
  sayısının kareköküyle ölçeklenir. Yanmalar sıfırdan başlar.
- **SA7.** Ölçü doğruluktur, sınama kümesi 252 abonedir ve bir abone 0,0040 eder. Denenen aday
  sayısı **4**'tür, seçim doğrulama kümesinden yapılır.

#### Ağırlık, Yanma ve Birim

Bir **birim** üç parçadan kuruludur: girdilerin her birine bir **ağırlık** düşer, ağırlıklı toplama
bir sabit eklenir, sonuç bir **etkinleştirme fonksiyonundan** geçirilir. Eklenen sabite bu kursta
**yanma** denir. Ayrım gereklidir: M27/K01'in yanlılık–değişkenlik dengesindeki **yanlılık** bir
hata bileşenidir, buradaki **yanma** ise öğrenilen bir parametredir ve birimin eşiğini kaydırır.

Yan yana duran birimler bir **katman** oluşturur. Bu derste iki mimari karşılaştırılır: girdiyi
doğrudan çıktıya bağlayan **tek katmanlı** ağ ve arada sekiz birimlik bir katman taşıyan **iki
katmanlı** ağ.

```python
# sinir_agi.py — MODELDIR. Ayni KURGU abone tablosu, ayni tohum ve ayni bolme;
# hedef kacak ya da ariza suphesi etiketidir.
import math
import statistics

TOHUM, HAM, M32 = 20260218, 1400, 0xFFFFFFFF
BOLGE = [("kuzey", 0.28, 21, 0.00), ("guney", 0.22, 17, -0.10),
         ("dogu", 0.18, 26, 0.30), ("bati", 0.14, 14, -0.05),
         ("merkez", 0.18, 23, 0.05)]


def uretec(t):                              # kendi yazilan uretec, kitaplik yok
    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


def ayrik(u, w):
    t = 0.0
    for i, x in enumerate(w):
        t += x
        if u < t:
            return i
    return len(w) - 1


ABONE, VERI = [], []
for i in range(HAM):
    r = uretec(TOHUM + i)
    b = BOLGE[ayrik(r(), [x[1] for x in BOLGE])]
    hane = 1 + ayrik(r(), [0.06, 0.24, 0.30, 0.24, 0.11, 0.05])
    memnun = 1 + ayrik(r(), [0.08, 0.14, 0.27, 0.34, 0.17])
    if r() >= 0.046:
        ABONE.append({"no": 10001 + i, "bolge": b, "hane": hane, "memnuniyet": memnun})
for k in ABONE:
    r, v = uretec(TOHUM + 7000 + k["no"]), []
    for d in range(ayrik(r(), [0.05, 0.12, 0.21, 0.62])):
        v.append(0.0 if r() < 0.038 else math.floor(
            k["bolge"][2] * math.exp((r() + r() + r() - 1.5) * 0.62)
            * (1 - d * 0.05) * 100 + 0.5) / 100)
        r()
    if not v:
        continue
    ort, oyn, r = sum(v) / len(v), max(v) - min(v), uretec(TOHUM + 51000 + k["no"])
    z = (0.052 * (ort - 20) + 0.85 * (min(v) == 0.0) + 0.026 * oyn
         + 0.24 * (k["hane"] >= 5) - 0.20 * (k["memnuniyet"] >= 4) + k["bolge"][3]
         + 0.9 * (k["no"] - 10001) / 1399 + (r() + r() + r() - 1.5) * 1.30)
    x = {"hane": k["hane"], "memnuniyet": k["memnuniyet"], "donem": len(v),
         "ort_tuketim": round(ort, 2), "oynaklik": round(oyn, 2),
         "sifir_okuma": int(min(v) == 0.0), "supheli": int(z > 1.35)}
    x["kisi_basi"] = round(x["ort_tuketim"] / x["hane"], 3)
    for b in BOLGE:
        x["b_" + b[0]] = int(k["bolge"][0] == b[0])
    VERI.append(x)


def karistir(veri, tohum):
    r, s = uretec(tohum), list(range(len(veri)))
    for i in range(len(s) - 1, 0, -1):
        j = int(r() * (i + 1))
        s[i], s[j] = s[j], s[i]
    return [veri[i] for i in s]


K = karistir(VERI, TOHUM + 90000)
EGT, DOG, SIN = K[:756], K[756:1008], K[1008:]
ALAN = ["ort_tuketim", "oynaklik", "hane", "memnuniyet", "donem", "sifir_okuma",
        "kisi_basi", "b_kuzey", "b_guney", "b_dogu", "b_bati", "b_merkez"]
ORTALAMA = {a: statistics.fmean(x[a] for x in EGT) for a in ALAN}
SAPMA = {a: max(1e-9, statistics.pstdev([x[a] for x in EGT])) for a in ALAN}
TABAN = sum(x["supheli"] == 0 for x in SIN) / len(SIN)


def olcekli(x):                             # OGRENME egitimden, UYGULAMA her kumeye
    return [(x[a] - ORTALAMA[a]) / SAPMA[a] for a in ALAN]


def kume(veri):
    return [olcekli(x) for x in veri], [float(x["supheli"]) for x in veri]


XT, YT = kume(EGT)                          # tam egitim kumesi, 756 satir
XE, YE = kume(EGT[:300])                    # KUCULTULMUS egitim kumesi, 300 satir
XD, YD = kume(DOG)
XS, YS = kume(SIN)

print(f"egitim {len(XT)}, kucultulmus egitim {len(XE)}, dogrulama {len(XD)}, "
      f"sinama {len(XS)}, sutun {len(ALAN)}")
print(f"supheli orani tam egitimde {sum(YT) / len(YT):.4f}, "
      f"kucultulmuste {sum(YE) / len(YE):.4f}, sinamada {sum(YS) / len(YS):.4f}")
print(f"taban cizgisi (en sik sinif) sinamada {TABAN:.4f}")
```

```
egitim 756, kucultulmus egitim 300, dogrulama 252, sinama 252, sutun 12
supheli orani tam egitimde 0.2222, kucultulmuste 0.2200, sinamada 0.2421
taban cizgisi (en sik sinif) sinamada 0.7579
```

Karşılaştırma çizgisi M27/K03'ten gelir ve tam 756 satırla ölçülmüştür: eğim temelli doğrusal
model ve doğrulamadan ayarlanmış karar ağacı sınama kümesinde **0,8016** veriyor, ayarsız karar
ağacı 0,7857. Ağın geçmesi gereken şey taban çizgisi değil, bu sayıdır.

#### Tek Katmanlı Ağ Yeni Bir Model Değildir

Gizli katmanı olmayan bir ağ on iki ağırlık ile bir yanma taşır, ağırlıklı toplamı S biçimli bir
işleve verir ve bir olasılık üretir. Bu tarif M27/K03'ün lojistik bağlanımınınkiyle kelimesi
kelimesine aynıdır ve aynılık sınanabilir: ağırlıklar sıfırdan başlatılıp aynı öğrenme adımı ve
tur sayısıyla eğitilirse ağ o dersin tablosunu üretmelidir.

```python
def sikistir(z):                            # S bicimli islev, tasma korumali
    if z >= 0:
        return 1.0 / (1.0 + math.exp(-z)) if z < 700 else 1.0
    e = math.exp(z) if z > -700 else 0.0
    return e / (1.0 + e)


def ilklendir(tohum, kat):                  # kazanc olcekli ilklendirme, yanma sifir
    r, ag = uretec(tohum), []
    for a, b in zip(kat, kat[1:]):
        o = math.sqrt(2.0 / a)
        ag.append(([[(r() * 2 - 1) * o for _ in range(a)] for _ in range(b)], [0.0] * b))
    return ag


def ileri(ag, x, dogrusal=False):           # ILERI GECIS: katman katman
    a, ara = x, [x]
    for k, (W, y) in enumerate(ag):
        z = [sum(w * v for w, v in zip(s, a)) + b for s, b in zip(W, y)]
        a = [sikistir(z[0])] if k == len(ag) - 1 else (
            z[:] if dogrusal else [t if t > 0 else 0.0 for t in z])
        ara.append(a)
    return ara


def egit(ag, X, Y, adim, tur, dogrusal=False):   # MODELDIR: tam toplu egim inisi
    n = len(X)
    for _ in range(tur):
        gW = [[[0.0] * len(W[0]) for _ in W] for W, _ in ag]
        gy = [[0.0] * len(y) for _, y in ag]
        for i in range(n):
            ara = ileri(ag, X[i], dogrusal)
            d = [ara[-1][0] - Y[i]]
            for k in range(len(ag) - 1, -1, -1):
                W, a = ag[k][0], ara[k]
                for j, dj in enumerate(d):
                    if dj:
                        s = gW[k][j]
                        for p in range(len(a)):
                            s[p] += dj * a[p]
                        gy[k][j] += dj
                if k:
                    onceki = [0.0] * len(a)
                    for j, dj in enumerate(d):
                        if dj:
                            s = W[j]
                            for p in range(len(a)):
                                onceki[p] += dj * s[p]
                    d = onceki if dogrusal else [onceki[p] if a[p] > 0 else 0.0
                                                 for p in range(len(a))]
        for k, (W, y) in enumerate(ag):
            for j in range(len(W)):
                s, g = W[j], gW[k][j]
                for p in range(len(s)):
                    s[p] -= adim * g[p] / n
                y[j] -= adim * gy[k][j] / n
    return ag


def dogruluk(ag, X, Y, dogrusal=False):
    return sum((ileri(ag, x, dogrusal)[-1][0] > 0.5) == (y > 0.5)
               for x, y in zip(X, Y)) / len(X)


def parametre(kat):
    return sum(a * b + b for a, b in zip(kat, kat[1:]))


print(f"tek katmanli agin parametre sayisi {parametre([12, 1])}, "
      f"iki katmanli (8 birim) {parametre([12, 8, 1])}")
print(f"{'ogrenme adimi':>14} {'tur':>5} {'egitimde':>9} {'dogrulama':>10} {'sinama':>8}")
for adim, tur in ((0.1, 100), (0.1, 300), (0.1, 600)):
    ag = egit([([[0.0] * 12], [0.0])], XT, YT, adim, tur)   # sifirdan ilklendirme
    print(f"{adim:>14} {tur:>5} {dogruluk(ag, XT, YT):>9.4f} "
          f"{dogruluk(ag, XD, YD):>10.4f} {dogruluk(ag, XS, YS):>8.4f}")
```

```
tek katmanli agin parametre sayisi 13, iki katmanli (8 birim) 113
 ogrenme adimi   tur  egitimde  dogrulama   sinama
           0.1   100    0.8175     0.8056   0.8016
           0.1   300    0.8201     0.8373   0.7937
           0.1   600    0.8188     0.8373   0.8016
```

Üç satırın dokuz sayısı da M27/K03'ün lojistik bağlanım tablosunun ilk üç satırıyla son
basamağına kadar aynı. Tek katmanlı ağ yeni bir model ailesi değil, bilinen bir modelin başka bir
sözlükle yazılmış halidir. "Sinir ağı" adının kattığı hiçbir şey bu satırlarda yok.

#### Katmanı Doğrusal Olmayan Yapan Şey

Aradaki katman 113 parametre getiriyor, tek katmanlı ağın 13'üne karşı. Ama kapasite yalnız
parametre sayısı değildir. Ara katmanın etkinleştirmesi kimlik işlevi olarak bırakılırsa — yani
ağırlıklı toplam olduğu gibi geçirilirse — iki dizey çarpımının bileşimi yine tek bir dizey
çarpımıdır. Ağın **temsil edebildiği işlevler kümesi** değişmez; aynı işlev daha çok parametreyle
yazılmış olur.

Ölçü bunu gösterir: üç mimari, aynı ayar, iki koşum. Ara katmanın etkinleştirmesi bir kez kimlik
işlevi, bir kez **doğrultulmuş doğrusal birim** — sıfırın altını sıfıra kesen işlev.

```python
MIMARI = (("tek katmanli", [12, 1], False),
          ("iki katman dogrusal", [12, 8, 1], True),
          ("iki katman dogrultulmus", [12, 8, 1], False))
print(f"{'mimari':<24} {'parametre':>9} {'kosum':>6} {'egitimde':>9} "
      f"{'dogrulama':>10} {'sinama':>8}")
BANT = {}
for ad, kat, dg in MIMARI:
    BANT[ad] = []
    for kosum in (1, 2):
        ag = egit(ilklendir(TOHUM + kosum, kat), XE, YE, 0.3, 100, dg)
        s = dogruluk(ag, XS, YS, dg)
        BANT[ad].append(s)
        print(f"{ad:<24} {parametre(kat):>9} {kosum:>6} "
              f"{dogruluk(ag, XE, YE, dg):>9.4f} {dogruluk(ag, XD, YD, dg):>10.4f} {s:>8.4f}")
print()
for ad, v in BANT.items():
    print(f"{ad:<24} sinama bandi {min(v):.4f}-{max(v):.4f}")
```

```
mimari                   parametre  kosum  egitimde  dogrulama   sinama
tek katmanli                    13      1    0.8433     0.7976   0.7817
tek katmanli                    13      2    0.8300     0.8016   0.7698
iki katman dogrusal            113      1    0.8233     0.8056   0.7698
iki katman dogrusal            113      2    0.8267     0.8016   0.7738
iki katman dogrultulmus        113      1    0.8400     0.8214   0.7857
iki katman dogrultulmus        113      2    0.8367     0.8056   0.7698

tek katmanli             sinama bandi 0.7698-0.7817
iki katman dogrusal      sinama bandi 0.7698-0.7738
iki katman dogrultulmus  sinama bandi 0.7698-0.7857
```

Doğrusal etkinleştirmeli ağ 113 parametresine karşın tek katmanlının bandının içinde kalıyor:
0,7698–0,7738'e karşı 0,7698–0,7817. Sekiz kat parametre ayrı bir sayı üretmeye yetmiyor.
Doğrusal olmayan ayrım katman sayısından değil **etkinleştirme fonksiyonundan** geliyor;
0,7857 ötekilerin üstüne çıkan tek sayı ve doğrultulmuş birimli ağa ait.

#### Kursun İmzası: İkinci Koşum

Üst uç 0,7857 tek başına raporlanabilir bir sayıdır ve raporlandığında yanıltır. Aynı ağ, aynı
veri, aynı ayar — yalnız başlangıç değerleri değişerek — beş kez eğitilir.

```python
ADAY = []
print(f"{'adim':>5} {'tur':>5} {'dogrulama':>10} {'sinama':>8}")
for adim in (0.3, 0.5):
    for tur in (100, 200):
        ag = egit(ilklendir(TOHUM + 1, [12, 8, 1]), XE, YE, adim, tur)
        ADAY.append((adim, tur, dogruluk(ag, XD, YD), dogruluk(ag, XS, YS)))
        print(f"{adim:>5} {tur:>5} {ADAY[-1][2]:>10.4f} {ADAY[-1][3]:>8.4f}")
SEC = max(ADAY, key=lambda t: t[2])
print(f"denenen aday {len(ADAY)}, secilen (adim {SEC[0]}, tur {SEC[1]})\n")

KOSUM = {}
print(f"{'kosum':>6} {'tek katmanli':>14} {'iki katmanli':>14}")
for kosum in range(1, 6):
    satir = []
    for kat in ([12, 1], [12, 8, 1]):
        ag = egit(ilklendir(TOHUM + kosum, kat), XE, YE, SEC[0], SEC[1])
        satir.append(dogruluk(ag, XS, YS))
    KOSUM[kosum] = satir
    print(f"{kosum:>6} {satir[0]:>14.4f} {satir[1]:>14.4f}")

tek, iki = [KOSUM[k][0] for k in KOSUM], [KOSUM[k][1] for k in KOSUM]
print(f"\ntaban cizgisi {TABAN:.4f}, agin sayisi {iki[0]:.4f}, "
      f"ikinci kosum {iki[1]:.4f}, fark {round(abs(iki[0] - iki[1]) * len(XS))} abone")
for ad, v in (("tek katmanli", tek), ("iki katmanli", iki)):
    print(f"{ad:<13} bant {min(v):.4f}-{max(v):.4f}, kosum degiskenligi "
          f"{max(v) - min(v):.4f} = {round((max(v) - min(v)) * len(XS))} abone")
print(f"kapasitenin kattigi {max(iki) - max(tek):.4f} "
      f"= {round((max(iki) - max(tek)) * len(XS))} abone; kucultmenin bedeli "
      f"(756 satirda 0.8016) {0.8016 - max(tek):.4f} "
      f"= {round((0.8016 - max(tek)) * len(XS))} abone")
```

```
 adim   tur  dogrulama   sinama
  0.3   100     0.8214   0.7857
  0.3   200     0.8135   0.7817
  0.5   100     0.8175   0.7857
  0.5   200     0.7937   0.7738
denenen aday 4, secilen (adim 0.3, tur 100)

 kosum   tek katmanli   iki katmanli
     1         0.7817         0.7857
     2         0.7698         0.7698
     3         0.7738         0.7738
     4         0.7698         0.7817
     5         0.7698         0.7659

taban cizgisi 0.7579, agin sayisi 0.7857, ikinci kosum 0.7698, fark 4 abone
tek katmanli  bant 0.7698-0.7817, kosum degiskenligi 0.0119 = 3 abone
iki katmanli  bant 0.7659-0.7857, kosum degiskenligi 0.0198 = 5 abone
kapasitenin kattigi 0.0040 = 1 abone; kucultmenin bedeli (756 satirda 0.8016) 0.0199 = 5 abone
```

Son iki satır kursun kuralını kuruyor. Kapasitenin kattığı fark **bir abone**, aynı kapasitenin
koşumdan koşuma oynaması **beş abone**. Ağın 0,7857'si kapasiteden değil o koşumun başlangıç
değerlerinden geliyor; beşinci koşum 0,7659 veriyor ve o sayı taban çizgisinin yalnız iki abone
üstünde. Tek katmanlı ağın bandı daha dar, üç abone, çünkü çözdüğü problemin tek bir en iyi
noktası vardır; ara katman eklendiğinde o güvence kayboluyor.

İkinci iddia da tablodan okunuyor. Ağın en iyi koşumu 0,7857 ile ayarsız karar ağacına eşit ve
M27/K03'ün iki ailesinin 0,8016'sının dört abone altında. Farkın bir bölümü eğitim kümesinin
küçültülmesinden geliyor: aynı tek katmanlı ağ 756 satırla 0,8016, 300 satırla 0,7817 veriyor.
Kalanı verinin kendisiyle ilgilidir — on iki sütunlu bir abone tablosunda öğrenilecek ara temsil
azdır.

#### Özet

- Bir birim ağırlık, yanma ve etkinleştirme fonksiyonundan kuruludur; yanma bir katman
  parametresidir ve M27/K01'in hata bileşeni olan yanlılıktan ayrıdır.
- Gizli katmanı olmayan ağ, sıfırdan ilklendirildiğinde M27/K03'ün doğrusal modelinin dokuz
  sayısını da son basamağına kadar veriyor: 0,8016, 0,7937 ve 0,8016.
- Ara katmanın etkinleştirmesi kimlik işlevi bırakılırsa 113 parametreli ağ 13 parametrelinin
  bandından çıkamıyor; doğrusal olmayan ayrım katman sayısından değil etkinleştirmeden gelir.
- Üçlü: taban çizgisi 0,7579, ağın sayısı 0,7857, ikinci koşum 0,7698. Beş koşumun bandı
  0,7659–0,7857; koşum değişkenliği beş abone, kapasitenin kattığı bir abone.
- Ağ 0,7857'de kalıyor: ayarsız karar ağacına eşit, M27/K03'ün iki ailesinin 0,8016'sının dört
  abone altında; farkın beş abonesi eğitim kümesinin 300 satıra küçültülmesinden geliyor.

#### Sonraki Adım

Doğrusal olmayan ayrımın etkinleştirmeden geldiği ölçüldü, ama kullanılan iki işlev — sıfırın
altını kesen doğrultulmuş doğrusal birim ve çıktıdaki S biçimli sıkıştırma — hiçbir gerekçeyle
seçilmedi. Sonraki ders o seçimi bir tercih olarak değil **bir sayı** olarak ele alır: sıkıştıran
bir işlev uçlarda düzleşir ve eğimi neredeyse sıfıra iner, kesen bir işlev ise girdisi sıfırın
altında kalan birimi tümüyle susturur. Sekiz birimin kaçı hiçbir örnekte etkinleşmiyor ve
doygunluk eğimi kaç kat küçültüyor — üç etkinleştirme yan yana, her biri iki koşumla.

### Etkinleştirme Fonksiyonları

Source: https://academia.sh/tr/kurslar/derin-ogrenme/etkinlestirme-fonksiyonlari

Etkinleştirme seçiminin doygunluk, ölü birim ve ilk katmana ulaşan eğim üzerinden ölçülmesi: sigmoidin türevi z=1'de 0,1966 iken z=6'da 0,0025'e iner, oran 79,7; hiperbolik tanjantta oran 17.088. Aynı ağda ilk katmana ulaşan ortalama eğim sigmoitle 1,0456, doğrultulmuş doğrusal birimle 4,4498 — 4,26 kat. Üç etkinleştirme ikişer koşumla: sigmoit 0,7937 ve 0,7976, doğrultulmuş 0,7857 ve 0,7698, hiperbolik tanjant 0,7659 ve 0,7698; taban çizgisi 0,7579. Öğrenme adımı 20'ye çıkarıldığında doğrultulmuş birimlerin dördü, 30'da sekizi de ölüyor ve ortalama türev tam olarak 0,0000 oluyor; sigmoit ile hiperbolik tanjantta hiçbir birim ölmüyor ama ortalama türev 0,1971'den 0,0295'e iniyor.

Önceki ders doğrusal olmayan ayrımın etkinleştirme fonksiyonundan geldiğini ölçtü, ama kullanılan
iki işlev hiçbir gerekçeyle seçilmedi. Bir etkinleştirmenin ağa kattığı şey yalnız eğrisi değildir;
eğitim sırasında geriye akan eğimi de o işlev belirler. Eğim zincir kuralıyla katman katman
çarpılarak gerideki katmanlara ulaşır ve çarpanlardan biri etkinleştirmenin **türevidir**.

Bu dersin ölçüsü buradadır. Bir işlevin türevi girdinin bir bölgesinde neredeyse sıfıra iniyorsa,
o bölgede kalan birim eğim almaz ve öğrenmesi durur. Bunun iki ayrı biçimi vardır ve karıştırılır:
türev **küçülür ama sıfır olmaz** — **doygunluk**; ya da türev **tam olarak sıfırdır** —
**ölü birim**. İkisi ayrı ölçülür.

- **SA8.** Küme, bölme, tohum ve on iki sütun `01`'deki gibidir; eğitim kümesi yine
  **300 satıra küçültülmüştür**. Taban çizgisi sınama kümesinde 0,7579.
- **SA9.** Ağ `01`'in ağıdır: 12 girdi, sekiz birimlik bir ara katman, tek çıktı, 113 parametre.
  Değişen tek şey **ara katmanın etkinleştirmesidir**.
- **SA10.** Çıkış katmanı üç kurulumda da sigmoittir, çünkü çıktının bir olasılık olması gerekir.
  Karşılaştırma yalnız ara katman üzerinden yapılır.
- **SA11.** Türev, etkinleştirmenin **çıktısı** cinsinden yazılır. Sigmoit için $a(1-a)$,
  hiperbolik tanjant için $1-a^2$, doğrultulmuş birim için çıktı pozitifken 1, değilse 0.
- **SA12.** Bir birim, ara katmandaki türevi tavanının yüzde beşinin altında kalıyorsa o satırda
  **etkin sayılmaz**. Eğitim kümesinin 300 satırının hiçbirinde etkin olmayan birim **ölüdür**.
- **SA13.** İlk katmana ulaşan eğim, **ilk turun** ağırlık eğimlerinin ortalama mutlak
  büyüklüğüdür. Üç kurulum aynı başlangıç değerlerinden başladığı için sayılar karşılaştırılabilir.
- **SA14.** Öğrenme adımı süpürmesi bir ayar araması değildir; ölü birimin **hangi adımda**
  ortaya çıktığını göstermek için yapılır ve seçim yapmaz.

#### Doygunluk Bir Sayıdır

Doygunluk sözle anlatıldığında bir eğri betimlemesi olarak kalır. Sayıya çevrilince ne kadar sert
bir sınır olduğu görünür: aynı işlevin türevi girdinin iki noktasında kaç kat ayrılıyor.

```python
# etkinlestirme.py — MODELDIR. Ayni KURGU abone tablosu, ayni tohum ve ayni bolme;
# egitim kumesi 01'deki gibi 300 satira kucultulmustur.
import math
import statistics

TOHUM, HAM, M32 = 20260218, 1400, 0xFFFFFFFF
BOLGE = [("kuzey", 0.28, 21, 0.00), ("guney", 0.22, 17, -0.10),
         ("dogu", 0.18, 26, 0.30), ("bati", 0.14, 14, -0.05),
         ("merkez", 0.18, 23, 0.05)]


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


def ayrik(u, w):
    t = 0.0
    for i, x in enumerate(w):
        t += x
        if u < t:
            return i
    return len(w) - 1


ABONE, VERI = [], []
for i in range(HAM):
    r = uretec(TOHUM + i)
    b = BOLGE[ayrik(r(), [x[1] for x in BOLGE])]
    hane = 1 + ayrik(r(), [0.06, 0.24, 0.30, 0.24, 0.11, 0.05])
    memnun = 1 + ayrik(r(), [0.08, 0.14, 0.27, 0.34, 0.17])
    if r() >= 0.046:
        ABONE.append({"no": 10001 + i, "bolge": b, "hane": hane, "memnuniyet": memnun})
for k in ABONE:
    r, v = uretec(TOHUM + 7000 + k["no"]), []
    for d in range(ayrik(r(), [0.05, 0.12, 0.21, 0.62])):
        v.append(0.0 if r() < 0.038 else math.floor(
            k["bolge"][2] * math.exp((r() + r() + r() - 1.5) * 0.62)
            * (1 - d * 0.05) * 100 + 0.5) / 100)
        r()
    if not v:
        continue
    ort, oyn, r = sum(v) / len(v), max(v) - min(v), uretec(TOHUM + 51000 + k["no"])
    z = (0.052 * (ort - 20) + 0.85 * (min(v) == 0.0) + 0.026 * oyn
         + 0.24 * (k["hane"] >= 5) - 0.20 * (k["memnuniyet"] >= 4) + k["bolge"][3]
         + 0.9 * (k["no"] - 10001) / 1399 + (r() + r() + r() - 1.5) * 1.30)
    x = {"hane": k["hane"], "memnuniyet": k["memnuniyet"], "donem": len(v),
         "ort_tuketim": round(ort, 2), "oynaklik": round(oyn, 2),
         "sifir_okuma": int(min(v) == 0.0), "supheli": int(z > 1.35)}
    x["kisi_basi"] = round(x["ort_tuketim"] / x["hane"], 3)
    for b in BOLGE:
        x["b_" + b[0]] = int(k["bolge"][0] == b[0])
    VERI.append(x)


def karistir(veri, tohum):
    r, s = uretec(tohum), list(range(len(veri)))
    for i in range(len(s) - 1, 0, -1):
        j = int(r() * (i + 1))
        s[i], s[j] = s[j], s[i]
    return [veri[i] for i in s]


K = karistir(VERI, TOHUM + 90000)
EGT, DOG, SIN = K[:756], K[756:1008], K[1008:]
ALAN = ["ort_tuketim", "oynaklik", "hane", "memnuniyet", "donem", "sifir_okuma",
        "kisi_basi", "b_kuzey", "b_guney", "b_dogu", "b_bati", "b_merkez"]
ORTALAMA = {a: statistics.fmean(x[a] for x in EGT) for a in ALAN}
SAPMA = {a: max(1e-9, statistics.pstdev([x[a] for x in EGT])) for a in ALAN}
TABAN = sum(x["supheli"] == 0 for x in SIN) / len(SIN)


def kume(veri):
    return ([[(x[a] - ORTALAMA[a]) / SAPMA[a] for a in ALAN] for x in veri],
            [float(x["supheli"]) for x in veri])


XE, YE = kume(EGT[:300])                    # KUCULTULMUS egitim kumesi
XD, YD = kume(DOG)
XS, YS = kume(SIN)


def sikistir(z):                            # S bicimli islev, tasma korumali
    if z >= 0:
        return 1.0 / (1.0 + math.exp(-z)) if z < 700 else 1.0
    e = math.exp(z) if z > -700 else 0.0
    return e / (1.0 + e)


ETKIN = {                                   # (islev, turev — girdisi etkinlestirme ciktisi)
    "sigmoit": (sikistir, lambda a: a * (1.0 - a)),
    "hiperbolik tanjant": (math.tanh, lambda a: 1.0 - a * a),
    "dogrultulmus": (lambda z: z if z > 0.0 else 0.0, lambda a: 1.0 if a > 0.0 else 0.0),
}
Z = (0.0, 1.0, 2.0, 4.0, 6.0, 8.0)
print(f"egitim {len(XE)}, dogrulama {len(XD)}, sinama {len(XS)}, "
      f"taban cizgisi {TABAN:.4f}")
print("\n" + f"{'turev':<20}" + "".join(f"{'z=' + str(int(z)):>10}" for z in Z))
for ad, (f, t) in ETKIN.items():
    print(f"{ad:<20}" + "".join(f"{t(f(z)):>10.4f}" for z in Z))
for ad, (f, t) in ETKIN.items():
    print(f"{ad:<20} z=1'de {t(f(1.0)):.6f}, z=6'da {t(f(6.0)):.6f}, "
          f"oran {t(f(1.0)) / max(t(f(6.0)), 1e-12):.1f}")
```

```
egitim 300, dogrulama 252, sinama 252, taban cizgisi 0.7579

turev                      z=0       z=1       z=2       z=4       z=6       z=8
sigmoit                 0.2500    0.1966    0.1050    0.0177    0.0025    0.0003
hiperbolik tanjant      1.0000    0.4200    0.0707    0.0013    0.0000    0.0000
dogrultulmus            0.0000    1.0000    1.0000    1.0000    1.0000    1.0000
sigmoit              z=1'de 0.196612, z=6'da 0.002467, oran 79.7
hiperbolik tanjant   z=1'de 0.419974, z=6'da 0.000025, oran 17088.4
dogrultulmus         z=1'de 1.000000, z=6'da 1.000000, oran 1.0
```

Sigmoidin türevi hiçbir yerde 0,25'i geçmiyor. Bu tek başına bir sınırdır: on iki sütunlu bir
girdiden gelen eğim, ara katmanı geçerken en iyi ihtimalle dörtte birine iner. Girdi 6'ya çıkınca
türev 0,0025 olur ve oran 79,7'ye varır. Hiperbolik tanjant tavanda daha cömerttir — türevi 1'den
başlar — ama daha hızlı doyar: aynı iki nokta arasındaki oran 17.088. Doğrultulmuş birimin türevi
pozitif bölgede sabit 1'dir, negatif bölgede tam olarak 0.

#### Üç Etkinleştirme, İki Koşum

Tablo tek başına hangisinin daha iyi olduğunu söylemez, çünkü ağın gerçekte hangi girdi
bölgesinde çalıştığı ölçülmemiştir. Aynı ağ üç etkinleştirmeyle, aynı başlangıç değerlerinden,
ikişer koşumla eğitilir.

```python
def ilklendir(tohum, kat):                  # kazanc olcekli ilklendirme, yanma sifir
    r, ag = uretec(tohum), []
    for a, b in zip(kat, kat[1:]):
        o = math.sqrt(2.0 / a)
        ag.append(([[(r() * 2 - 1) * o for _ in range(a)] for _ in range(b)], [0.0] * b))
    return ag


def ileri(ag, x, f):                        # ILERI GECIS, cikis katmani her zaman sigmoit
    a, ara = x, [x]
    for k, (W, y) in enumerate(ag):
        z = [sum(w * v for w, v in zip(s, a)) + b for s, b in zip(W, y)]
        a = [sikistir(z[0])] if k == len(ag) - 1 else [f(t) for t in z]
        ara.append(a)
    return ara


def egit(ag, X, Y, adim, tur, ad):          # MODELDIR: tam toplu egim inisi
    f, turev = ETKIN[ad]
    n, ilk = len(X), [0.0]
    for t in range(tur):
        gW = [[[0.0] * len(W[0]) for _ in W] for W, _ in ag]
        gy = [[0.0] * len(y) for _, y in ag]
        for i in range(n):
            ara = ileri(ag, X[i], f)
            d = [ara[-1][0] - Y[i]]
            for k in range(len(ag) - 1, -1, -1):
                W, a = ag[k][0], ara[k]
                for j, dj in enumerate(d):
                    if dj:
                        s = gW[k][j]
                        for p in range(len(a)):
                            s[p] += dj * a[p]
                        gy[k][j] += dj
                if k:
                    onceki = [0.0] * len(a)
                    for j, dj in enumerate(d):
                        if dj:
                            s = W[j]
                            for p in range(len(a)):
                                onceki[p] += dj * s[p]
                    d = [onceki[p] * turev(a[p]) for p in range(len(a))]
        if t == 0:                          # ilk katmana ulasan ortalama egim buyuklugu
            ilk[0] = sum(abs(v) for s in gW[0] for v in s) / (len(gW[0]) * len(gW[0][0]))
        for k, (W, y) in enumerate(ag):
            for j in range(len(W)):
                s, g = W[j], gW[k][j]
                for p in range(len(s)):
                    s[p] -= adim * g[p] / n
                y[j] -= adim * gy[k][j] / n
    return ag, ilk[0]


def dogruluk(ag, X, Y, ad):
    f = ETKIN[ad][0]
    return sum((ileri(ag, x, f)[-1][0] > 0.5) == (y > 0.5) for x, y in zip(X, Y)) / len(X)


def birim_olcum(ag, X, ad):                 # birim basina etkin satir sayisi ve ort. turev
    f, turev = ETKIN[ad]
    W, y = ag[0]
    tavan = 0.25 if ad == "sigmoit" else 1.0
    sayac, toplam = [0] * len(W), 0.0
    for x in X:
        for j in range(len(W)):
            t = turev(f(sum(w * v for w, v in zip(W[j], x)) + y[j]))
            toplam += t
            if t > 0.05 * tavan:
                sayac[j] += 1
    return sayac, toplam / (len(X) * len(W))


SONUC = {}
print(f"{'etkinlestirme':<20} {'kosum':>6} {'dogrulama':>10} {'sinama':>8} "
      f"{'ort_turev':>10} {'ilk_katman_egimi':>17}")
for ad in ETKIN:
    SONUC[ad] = []
    for kosum in (1, 2):
        ag, ilk = egit(ilklendir(TOHUM + kosum, [12, 8, 1]), XE, YE, 0.3, 100, ad)
        sayac, ort = birim_olcum(ag, XE, ad)
        SONUC[ad].append((dogruluk(ag, XD, YD, ad), dogruluk(ag, XS, YS, ad), ort, ilk))
        print(f"{ad:<20} {kosum:>6} {SONUC[ad][-1][0]:>10.4f} {SONUC[ad][-1][1]:>8.4f} "
              f"{ort:>10.4f} {ilk:>17.4f}")
SEC = max(ETKIN, key=lambda a: SONUC[a][0][0])
print(f"\ndogrulamadan secilen etkinlestirme: {SEC}")
print(f"taban cizgisi {TABAN:.4f}, agin sayisi {SONUC[SEC][0][1]:.4f}, "
      f"ikinci kosum {SONUC[SEC][1][1]:.4f}")
print(f"ilk katman egimi: {SEC} {SONUC[SEC][0][3]:.4f}, dogrultulmus "
      f"{SONUC['dogrultulmus'][0][3]:.4f}, oran "
      f"{SONUC['dogrultulmus'][0][3] / SONUC[SEC][0][3]:.2f} kat")
```

```
etkinlestirme         kosum  dogrulama   sinama  ort_turev  ilk_katman_egimi
sigmoit                   1     0.8294   0.7937     0.1971            1.0456
sigmoit                   2     0.8333   0.7976     0.2100            1.5007
hiperbolik tanjant        1     0.7976   0.7659     0.5913            3.1693
hiperbolik tanjant        2     0.8016   0.7698     0.6587            4.8762
dogrultulmus              1     0.8214   0.7857     0.5183            4.4498
dogrultulmus              2     0.8056   0.7698     0.5012            5.2971

dogrulamadan secilen etkinlestirme: sigmoit
taban cizgisi 0.7579, agin sayisi 0.7937, ikinci kosum 0.7976
ilk katman egimi: sigmoit 1.0456, dogrultulmus 4.4498, oran 4.26 kat
```

Eğim ölçüsü tabloyu doğruluyor: ilk katmana ulaşan ortalama eğim büyüklüğü sigmoitle 1,0456,
doğrultulmuş birimle 4,4498 — **4,26 kat**. Bu fark doğrudan türev tavanından geliyor ve sözle
anlatılan doygunluğun ağdaki karşılığıdır.

Ama sınama sütunu beklenenin tersini söylüyor. Doygun işlev en yüksek sayıyı veriyor: 0,7937 ve
0,7976. Nedeni ortalama türev sütununda: sigmoit birimlerinin ortalama türevi 0,1971, tavanı olan
0,2500'ün yüzde 79'u. Ağ doygun bölgede çalışmıyor, çünkü ölçeklenmiş girdilerle ağırlıklı toplam
küçük kalıyor. Doygunluk bir işlev özelliği değil, o işlevin **hangi bölgede çalıştırıldığına**
bağlı bir sonuçtur. Bu ölçekte küçük eğim bir engel değil; katman derinleştiğinde ve aynı çarpan
üst üste bindiğinde engel olacak.

Üçlü yine yerinde: taban çizgisi 0,7579, ağın sayısı 0,7937, ikinci koşum 0,7976. İki koşum
arasındaki fark bir abone; ama üç etkinleştirme arasındaki en büyük fark 0,7937 ile 0,7659, yani
yedi abone. Bu derste seçim koşum gürültüsünün üstünde bir fark üretiyor.

#### Ölü Birim ile Doygun Birim

İki bozulma biçimini ayırmanın yolu öğrenme adımını büyütmektir. Adım büyüdükçe ağırlıklar daha
uzağa savrulur ve birimler türevin küçük olduğu bölgeye girer.

```python
print(f"{'etkinlestirme':<20} {'adim':>6} {'sinama':>8} {'olu birim':>10} "
      f"{'ort_turev':>10}  birim basina etkin satir")
for ad in ETKIN:
    for adim in (0.3, 20.0, 30.0):
        ag, _ = egit(ilklendir(TOHUM + 1, [12, 8, 1]), XE, YE, adim, 100, ad)
        sayac, ort = birim_olcum(ag, XE, ad)
        print(f"{ad:<20} {adim:>6} {dogruluk(ag, XS, YS, ad):>8.4f} "
              f"{sum(1 for c in sayac if c == 0):>10} {ort:>10.4f}  {sayac}")
```

```
etkinlestirme          adim   sinama  olu birim  ort_turev  birim basina etkin satir
sigmoit                 0.3   0.7937          0     0.1971  [300, 300, 300, 300, 300, 300, 300, 300]
sigmoit                20.0   0.7579          0     0.0536  [176, 127, 118, 119, 132, 169, 141, 127]
sigmoit                30.0   0.6071          0     0.0295  [89, 68, 66, 70, 53, 95, 85, 71]
hiperbolik tanjant      0.3   0.7659          0     0.5913  [296, 299, 291, 291, 283, 289, 288, 282]
hiperbolik tanjant     20.0   0.7421          0     0.0527  [27, 37, 61, 28, 35, 34, 10, 47]
hiperbolik tanjant     30.0   0.7976          0     0.0242  [5, 30, 7, 15, 18, 20, 22, 27]
dogrultulmus            0.3   0.7857          0     0.5183  [151, 185, 143, 142, 154, 134, 132, 203]
dogrultulmus           20.0   0.7579          4     0.0825  [0, 30, 91, 33, 44, 0, 0, 0]
dogrultulmus           30.0   0.7540          8     0.0000  [0, 0, 0, 0, 0, 0, 0, 0]
```

Ayrım son sütunda duruyor. Sigmoit ve hiperbolik tanjantla **hiçbir birim ölmüyor**: adım 30'da
bile her birim 300 satırın bir bölümünde etkin kalıyor, 53 ile 95 arasında. Ortalama türev
0,1971'den 0,0295'e iniyor — altı kat küçülme — ve sayı 0,6071'e, taban çizgisinin çok altına
düşüyor. Ama türev sıfır değil; ağ yavaş da olsa öğrenmeye devam edebilir.

Doğrultulmuş birimde durum başkadır. Adım 20'de sekiz birimin **dördü**, adım 30'da **sekizi de**
ölüyor ve ortalama türev tam olarak **0,0000** oluyor. Ölü bir birimin geri akan eğimi sıfırla
çarpılır; ağırlıkları bir daha hiç güncellenmez. Bu geri dönüşü olmayan bir kayıptır ve tabloda
sayıyla görünür: sekiz birimin sekizi öldüğünde ağın çıktısı sabittir ve sınama sayısı 0,7540,
yani **taban çizgisinin bile altında**. Adım 20'de dört birim ölmüş haldeyken sayı tam olarak
0,7579, yani ağ herkese "şüpheli değil" diyor.

#### Özet

- Doygunluk bir sayıdır: sigmoidin türevi z=1'de 0,1966 iken z=6'da 0,0025, oran 79,7; hiperbolik
  tanjantta aynı oran 17.088. Doğrultulmuş birimin türevi pozitif bölgede sabit 1'dir.
- Aynı ağda ilk katmana ulaşan ortalama eğim sigmoitle 1,0456, doğrultulmuş birimle 4,4498 —
  4,26 kat. Fark doğrudan türev tavanından gelir.
- Üçlü: taban çizgisi 0,7579, ağın sayısı 0,7937 (sigmoit), ikinci koşum 0,7976. Etkinleştirmeler
  arasındaki en büyük fark yedi abone, iki koşum arasındaki fark bir abone.
- Doygunluk bir işlev özelliği değil, işlevin çalıştırıldığı bölgenin sonucudur: sigmoit birimlerin
  ortalama türevi 0,1971, yani tavanının yüzde 79'u, çünkü ölçeklenmiş girdilerle toplam küçük
  kalıyor.
- Ölü birim ile doygun birim ayrı şeylerdir. Adım 30'da sigmoit ve hiperbolik tanjantta hiçbir
  birim ölmüyor, doğrultulmuş birimde sekizinin sekizi ölüyor ve ortalama türev 0,0000 oluyor;
  sayı 0,7540 ile taban çizgisinin altına iniyor.

#### Sonraki Adım

İki derste ağ hep aynı kaldı: on iki girdi, sekiz birim, tek çıktı. Ara katmanın **kaç birim**
taşıyacağı seçilmedi, seçilseydi neyin değişeceği ölçülmedi. Sonraki ders ileri geçişi katman
katman açar ve bu seçime iki ayrı sayı bağlar: birim sayısı arttıkça **parametre sayısı** ve bir
tek örnek için yapılan **çarpma sayısı** nasıl büyüyor ve ayrılmış küme sayısı bu büyümeye ne
kadar karşılık veriyor. Dizey çarpımı elle yazılır, çünkü katmanın maliyeti ancak açık yazıldığında
sayılabilir.

### İleri Yayılım

Source: https://academia.sh/tr/kurslar/derin-ogrenme/ileri-yayilim

Ara katmanın genişliğinin iki maliyet sayısı ve bir karşılık sayısıyla ölçülmesi: 12 girdili bir ağda ara katman 2'den 32 birime çıktığında parametre sayısı 29'dan 449'a (15,5 kat), örnek başına çarpma 26'dan 416'ya (16,0 kat), yüz turluk eğitimin toplam çarpması 780.000'den 12.480.000'e büyüyor. Karşılık bunun yanında küçük kalıyor: on koşumun sınama bandı 0,7540-0,7857, yani sekiz abone; her genişliğin iyi koşumları arasındaki fark beş abone ve tek bir genişlikte iki koşum arasındaki en büyük fark da beş abone. Doğrulamadan seçilen genişlik 4 birim, yani 57 parametre ve o adayın sınama sayısı 0,7540 ile taban çizgisinin altında; ikinci koşumu 0,7738.

İki derste ağ hep aynı kaldı: on iki girdi, sekiz birim, tek çıktı. Ara katmanın kaç birim
taşıyacağı hiç seçilmedi ve seçilseydi neyin değişeceği ölçülmedi. Bu ders o seçime iki maliyet
sayısı ve bir karşılık sayısı bağlar.

Maliyet tarafı hesapla bulunur ve koşumdan koşuma değişmez: **parametre sayısı** — ağın bellekte
tuttuğu ağırlık ve yanma adedi — ve **örnek başına çarpma sayısı** — bir abonenin ağdan bir kez
geçmesi için yapılan çarpma adedi. İkisi de ileri geçişin yapısından okunur. Karşılık tarafı ise
ancak ölçülerek bulunur ve bu kursun kuralı gereği **iki koşumla** yazılır.

- **SA15.** Küme, bölme, tohum, on iki sütun ve **300 satıra küçültülmüş** eğitim kümesi
  `01`–`02`'deki gibidir. Taban çizgisi sınama kümesinde 0,7579.
- **SA16.** Ara katmanın etkinleştirmesi bu derste **doğrultulmuş doğrusal birimdir** ve sabit
  tutulur; `02` üç etkinleştirmeyi ölçtü, burada değişken yalnız genişliktir.
- **SA17.** Çıkış katmanı sigmoittir, çünkü çıktının bir olasılık olması gerekir. Eşik 0,5'tir ve
  eşiğin bir karar olduğu M27/K03 `dogrusal-modeller/04`'te ölçüldü.
- **SA18.** Parametre sayısı katman çiftleri üzerinden $\sum (a_i b_i + b_i)$, örnek başına çarpma
  sayısı $\sum a_i b_i$ ile hesaplanır; $a_i$ girdi, $b_i$ çıktı genişliğidir. Toplama ve
  etkinleştirme çağrıları sayılmaz, çünkü ölçü çarpma adedidir.
- **SA19.** Eğitimdeki toplam çarpma, örnek başına çarpmanın 300 satır ve 100 turla çarpımıdır;
  geri geçiş sayılmaz, ölçü yalnız ileri geçişindir.
- **SA20.** Denenen genişlik sayısı **5**'tir (2, 4, 8, 16, 32) ve seçim doğrulama kümesinden,
  iki koşumun toplamına bakılarak yapılır. Tek bir koşuma bakarak seçmek bu kursta kabul edilmez.
- **SA21.** Öğrenme adımı 0,3 ve tur sayısı 100'dür; `01`'de doğrulamadan seçilen ayardır ve
  genişlik süpürmesi boyunca sabit tutulur.

#### İki Maliyet Sayısı

Bir katmanın maliyeti şeklinden okunur. On iki girdiden sekiz birime giden bir katman 96 ağırlık
ve sekiz yanma taşır; sekiz birimden tek çıktıya giden katman sekiz ağırlık ve bir yanma. Toplam
113. Aynı hesap çarpma için de yapılır ve yanmalar dışarıda kalır, çünkü yanma eklenir, çarpılmaz.

```python
# ileri_gecis.py — MODELDIR. Ayni KURGU abone tablosu, ayni tohum ve ayni bolme;
# egitim kumesi 01'deki gibi 300 satira kucultulmustur.
import math
import statistics

TOHUM, HAM, M32 = 20260218, 1400, 0xFFFFFFFF
BOLGE = [("kuzey", 0.28, 21, 0.00), ("guney", 0.22, 17, -0.10),
         ("dogu", 0.18, 26, 0.30), ("bati", 0.14, 14, -0.05),
         ("merkez", 0.18, 23, 0.05)]


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


def ayrik(u, w):
    t = 0.0
    for i, x in enumerate(w):
        t += x
        if u < t:
            return i
    return len(w) - 1


ABONE, VERI = [], []
for i in range(HAM):
    r = uretec(TOHUM + i)
    b = BOLGE[ayrik(r(), [x[1] for x in BOLGE])]
    hane = 1 + ayrik(r(), [0.06, 0.24, 0.30, 0.24, 0.11, 0.05])
    memnun = 1 + ayrik(r(), [0.08, 0.14, 0.27, 0.34, 0.17])
    if r() >= 0.046:
        ABONE.append({"no": 10001 + i, "bolge": b, "hane": hane, "memnuniyet": memnun})
for k in ABONE:
    r, v = uretec(TOHUM + 7000 + k["no"]), []
    for d in range(ayrik(r(), [0.05, 0.12, 0.21, 0.62])):
        v.append(0.0 if r() < 0.038 else math.floor(
            k["bolge"][2] * math.exp((r() + r() + r() - 1.5) * 0.62)
            * (1 - d * 0.05) * 100 + 0.5) / 100)
        r()
    if not v:
        continue
    ort, oyn, r = sum(v) / len(v), max(v) - min(v), uretec(TOHUM + 51000 + k["no"])
    z = (0.052 * (ort - 20) + 0.85 * (min(v) == 0.0) + 0.026 * oyn
         + 0.24 * (k["hane"] >= 5) - 0.20 * (k["memnuniyet"] >= 4) + k["bolge"][3]
         + 0.9 * (k["no"] - 10001) / 1399 + (r() + r() + r() - 1.5) * 1.30)
    x = {"hane": k["hane"], "memnuniyet": k["memnuniyet"], "donem": len(v),
         "ort_tuketim": round(ort, 2), "oynaklik": round(oyn, 2),
         "sifir_okuma": int(min(v) == 0.0), "supheli": int(z > 1.35)}
    x["kisi_basi"] = round(x["ort_tuketim"] / x["hane"], 3)
    for b in BOLGE:
        x["b_" + b[0]] = int(k["bolge"][0] == b[0])
    VERI.append(x)


def karistir(veri, tohum):
    r, s = uretec(tohum), list(range(len(veri)))
    for i in range(len(s) - 1, 0, -1):
        j = int(r() * (i + 1))
        s[i], s[j] = s[j], s[i]
    return [veri[i] for i in s]


K = karistir(VERI, TOHUM + 90000)
EGT, DOG, SIN = K[:756], K[756:1008], K[1008:]
ALAN = ["ort_tuketim", "oynaklik", "hane", "memnuniyet", "donem", "sifir_okuma",
        "kisi_basi", "b_kuzey", "b_guney", "b_dogu", "b_bati", "b_merkez"]
ORTALAMA = {a: statistics.fmean(x[a] for x in EGT) for a in ALAN}
SAPMA = {a: max(1e-9, statistics.pstdev([x[a] for x in EGT])) for a in ALAN}
TABAN = sum(x["supheli"] == 0 for x in SIN) / len(SIN)


def kume(veri):
    return ([[(x[a] - ORTALAMA[a]) / SAPMA[a] for a in ALAN] for x in veri],
            [float(x["supheli"]) for x in veri])


XE, YE = kume(EGT[:300])                    # KUCULTULMUS egitim kumesi
XD, YD = kume(DOG)
XS, YS = kume(SIN)


def sikistir(z):                            # S bicimli islev, tasma korumali
    if z >= 0:
        return 1.0 / (1.0 + math.exp(-z)) if z < 700 else 1.0
    e = math.exp(z) if z > -700 else 0.0
    return e / (1.0 + e)


BIRIM = (2, 4, 8, 16, 32)
OLCU = {}
print(f"{'birim':>6} {'sekil':>12} {'parametre':>10} {'carpma/ornek':>13} "
      f"{'egitimde toplam carpma':>23}")
for h in BIRIM:
    kat = [len(ALAN), h, 1]
    par = sum(a * b + b for a, b in zip(kat, kat[1:]))
    carp = sum(a * b for a, b in zip(kat, kat[1:]))
    OLCU[h] = (par, carp)
    print(f"{h:>6} {str(tuple(kat)):>12} {par:>10} {carp:>13} "
          f"{carp * len(XE) * 100:>23}")
p0, c0 = OLCU[BIRIM[0]]
p1, c1 = OLCU[BIRIM[-1]]
print(f"\nbirim {BIRIM[0]}'den {BIRIM[-1]}'ye: parametre {p0} -> {p1} "
      f"({p1 / p0:.1f} kat), carpma {c0} -> {c1} ({c1 / c0:.1f} kat)")
```

```
 birim        sekil  parametre  carpma/ornek  egitimde toplam carpma
     2   (12, 2, 1)         29            26                  780000
     4   (12, 4, 1)         57            52                 1560000
     8   (12, 8, 1)        113           104                 3120000
    16  (12, 16, 1)        225           208                 6240000
    32  (12, 32, 1)        449           416                12480000

birim 2'den 32'ye: parametre 29 -> 449 (15.5 kat), carpma 26 -> 416 (16.0 kat)
```

İki sütun da genişlikle **doğru orantılı** büyüyor, çünkü on iki girdi her birime ayrı ayrı
bağlanıyor. Genişlik on altı katına çıktığında parametre 15,5, çarpma 16,0 katına çıkıyor.
Son sütun ölçünün süre olmadığını gösteriyor: yüz turluk bir eğitim en dar ağda 780.000, en geniş
ağda 12.480.000 çarpma yapıyor. Bu sayılar hangi makinede koşulduğuna bağlı değildir.

#### Dizey Çarpımı Elle

İleri geçiş iki adımın tekrarıdır: bir **dizey çarpımı** ve bir **etkinleştirme**. Dizey çarpımının
her satırı bir birime aittir ve o birimin ağırlıklarını girdi vektörüyle eşleştirir. Elle
yazıldığında maliyetin nereden geldiği görünür: iki iç içe döngü, dış döngü birim sayısı kadar,
iç döngü girdi sayısı kadar döner.

```python
def dogrultulmus(z):                        # sifirin altini sifira kesen etkinlestirme
    return z if z > 0.0 else 0.0


def ilklendir(tohum, kat):                  # kazanc olcekli ilklendirme, yanma sifir
    r, ag = uretec(tohum), []
    for a, b in zip(kat, kat[1:]):
        o = math.sqrt(2.0 / a)
        ag.append(([[(r() * 2 - 1) * o for _ in range(a)] for _ in range(b)], [0.0] * b))
    return ag


def dizey_carp(W, y, a):                    # DIZEY CARPIMI elle: her satir bir birim
    return [sum(w * v for w, v in zip(satir, a)) + yanma
            for satir, yanma in zip(W, y)]


def ileri(ag, x):                           # ILERI GECIS: katman katman
    a = x
    for k, (W, y) in enumerate(ag):
        z = dizey_carp(W, y, a)
        a = [sikistir(z[0])] if k == len(ag) - 1 else [dogrultulmus(t) for t in z]
    return a


def ileri_izle(ag, x):                      # ayni gecis, her katman basilarak
    a, carpma = x, 0
    print(f"  girdi katmani      {len(a):>3} deger, ilk uc {[round(v, 3) for v in a[:3]]}")
    for k, (W, y) in enumerate(ag):
        carpma += len(W) * len(a)
        z = dizey_carp(W, y, a)
        a = [sikistir(z[0])] if k == len(ag) - 1 else [dogrultulmus(t) for t in z]
        ad = "cikis katmani" if k == len(ag) - 1 else f"ara katman {k + 1}"
        print(f"  {ad:<18} {len(a):>3} deger, ilk uc {[round(v, 3) for v in a[:3]]}")
    return a[0], carpma


for h in (4, 8):
    ag = ilklendir(TOHUM + 1, [len(ALAN), h, 1])
    print(f"ara katmanda {h} birim, sinama kumesinin ilk abonesi:")
    cikti, carpma = ileri_izle(ag, XS[0])
    print(f"  yapilan carpma {carpma}, tablodaki {OLCU[h][1]}, "
          f"cikti {cikti:.4f}, gercek etiket {int(YS[0])}")
```

```
ara katmanda 4 birim, sinama kumesinin ilk abonesi:
  girdi katmani       12 deger, ilk uc [-0.008, -0.63, 1.399]
  ara katman 1         4 deger, ilk uc [0.047, 0.0, 0.673]
  cikis katmani        1 deger, ilk uc [0.407]
  yapilan carpma 52, tablodaki 52, cikti 0.4068, gercek etiket 0
ara katmanda 8 birim, sinama kumesinin ilk abonesi:
  girdi katmani       12 deger, ilk uc [-0.008, -0.63, 1.399]
  ara katman 1         8 deger, ilk uc [0.047, 0.0, 0.673]
  cikis katmani        1 deger, ilk uc [0.492]
  yapilan carpma 104, tablodaki 104, cikti 0.4923, gercek etiket 0
```

Sayılan çarpma tablodaki hesapla birebir uyuşuyor: 52 ve 104. Geçişin şekli de görünüyor —
12 değer 4 değere, 4 değer 1 değere iniyor. Ara katmanın ikinci biriminin çıktısı 0,0; girdi
ağırlıklı toplamı negatif kaldığı için doğrultulmuş birim onu kesmiş. Aynı abone için iki ağ
0,4068 ve 0,4923 veriyor; ikisi de 0,5 eşiğinin altında ve gerçek etiket 0 olduğu için ikisi de
doğru.

#### Genişlik Ne Kadar Karşılık Veriyor

Maliyet on altı katına çıkarken karşılığın ne olduğu ancak eğitilerek bulunur. Beş genişlik, her
biri iki koşum.

```python
def egit(ag, X, Y, adim, tur):              # MODELDIR: tam toplu egim inisi
    n = len(X)
    for _ in range(tur):
        gW = [[[0.0] * len(W[0]) for _ in W] for W, _ in ag]
        gy = [[0.0] * len(y) for _, y in ag]
        for i in range(n):
            a, ara = X[i], [X[i]]
            for k, (W, y) in enumerate(ag):
                z = dizey_carp(W, y, a)
                a = [sikistir(z[0])] if k == len(ag) - 1 else [dogrultulmus(t) for t in z]
                ara.append(a)
            d = [ara[-1][0] - Y[i]]
            for k in range(len(ag) - 1, -1, -1):
                W, a = ag[k][0], ara[k]
                for j, dj in enumerate(d):
                    if dj:
                        s = gW[k][j]
                        for p in range(len(a)):
                            s[p] += dj * a[p]
                        gy[k][j] += dj
                if k:
                    onceki = [0.0] * len(a)
                    for j, dj in enumerate(d):
                        if dj:
                            s = W[j]
                            for p in range(len(a)):
                                onceki[p] += dj * s[p]
                    d = [onceki[p] if a[p] > 0 else 0.0 for p in range(len(a))]
        for k, (W, y) in enumerate(ag):
            for j in range(len(W)):
                s, g = W[j], gW[k][j]
                for p in range(len(s)):
                    s[p] -= adim * g[p] / n
                y[j] -= adim * gy[k][j] / n
    return ag


def dogruluk(ag, X, Y):
    return sum((ileri(ag, x)[0] > 0.5) == (y > 0.5) for x, y in zip(X, Y)) / len(X)


SONUC = {}
print(f"{'birim':>6} {'parametre':>10} {'kosum':>6} {'dogrulama':>10} {'sinama':>8}")
for h in BIRIM:
    SONUC[h] = []
    for kosum in (1, 2):
        ag = egit(ilklendir(TOHUM + kosum, [len(ALAN), h, 1]), XE, YE, 0.3, 100)
        SONUC[h].append((dogruluk(ag, XD, YD), dogruluk(ag, XS, YS)))
        print(f"{h:>6} {OLCU[h][0]:>10} {kosum:>6} {SONUC[h][-1][0]:>10.4f} "
              f"{SONUC[h][-1][1]:>8.4f}")
SEC = max(BIRIM, key=lambda h: sum(t[0] for t in SONUC[h]))
hepsi = [t[1] for h in BIRIM for t in SONUC[h]]
en_iyi = [max(t[1] for t in SONUC[h]) for h in BIRIM]
kosum_farki = max(abs(SONUC[h][0][1] - SONUC[h][1][1]) for h in BIRIM)
print(f"\ndogrulamadan secilen genislik {SEC} birim ({OLCU[SEC][0]} parametre)")
print(f"taban cizgisi {TABAN:.4f}, agin sayisi {SONUC[SEC][0][1]:.4f}, "
      f"ikinci kosum {SONUC[SEC][1][1]:.4f}")
print(f"on kosumun bandi {min(hepsi):.4f}-{max(hepsi):.4f} "
      f"({round((max(hepsi) - min(hepsi)) * len(XS))} abone)")
print(f"genisligin kattigi (her genisligin iyi kosumu) {min(en_iyi):.4f}-{max(en_iyi):.4f} "
      f"= {round((max(en_iyi) - min(en_iyi)) * len(XS))} abone")
print(f"tek genislikte en buyuk kosum farki {kosum_farki:.4f} "
      f"= {round(kosum_farki * len(XS))} abone")
```

```
 birim  parametre  kosum  dogrulama   sinama
     2         29      1     0.8135   0.7579
     2         29      2     0.8016   0.7659
     4         57      1     0.8254   0.7540
     4         57      2     0.8135   0.7738
     8        113      1     0.8214   0.7857
     8        113      2     0.8056   0.7698
    16        225      1     0.8135   0.7659
    16        225      2     0.7937   0.7778
    32        449      1     0.8056   0.7817
    32        449      2     0.8056   0.7698

dogrulamadan secilen genislik 4 birim (57 parametre)
taban cizgisi 0.7579, agin sayisi 0.7540, ikinci kosum 0.7738
on kosumun bandi 0.7540-0.7857 (8 abone)
genisligin kattigi (her genisligin iyi kosumu) 0.7659-0.7857 = 5 abone
tek genislikte en buyuk kosum farki 0.0198 = 5 abone
```

Son iki satır yan yana okunmalıdır. On beş buçuk kat parametre farkı, her genişliğin iyi koşumları
arasında **beş abone** üretiyor. Tek bir genişlikte, hiçbir şey değiştirmeden yalnız başlangıç
değerleri değişerek, en büyük fark yine **beş abone**. Genişliği ikiye katlamakla ağı yeniden
eğitmek arasındaki fark bu ölçüde ayırt edilemiyor.

Doğrulama sütunu ayrı bir uyarı taşıyor. Seçim doğrulamadan yapıldığında kazanan **4 birim**,
yani beş adayın en darlardan biri; 57 parametreyle. O adayın sınama sayısı 0,7540 ve bu
**taban çizgisinin altında** — en sık sınıfı söylemek 0,7579 veriyor. Aynı adayın ikinci koşumu
0,7738 veriyor; iki koşum arasında beş abone var ve doğrulama kümesi ikisi arasında seçim
yapamıyor, çünkü doğrulamada da 0,8254 ile 0,8135 arasında oynuyor. Ayar bütçesinin şişirdiği
farkı M27/K03 `model-degerlendirme/07` ölçmüştü; buraya eklenen şey, aynı adayın **kendi içindeki**
oynamasının seçimi bozmasıdır.

#### Özet

- İleri geçiş bir dizey çarpımı ile bir etkinleştirmenin tekrarıdır. Dizey çarpımının her satırı
  bir birime aittir ve elle yazıldığında maliyet iki iç içe döngüden okunur.
- Ara katman 2'den 32 birime çıktığında parametre 29'dan 449'a (15,5 kat), örnek başına çarpma
  26'dan 416'ya (16,0 kat), yüz turluk eğitimin toplam çarpması 780.000'den 12.480.000'e büyüyor.
  Üç sayı da makineden bağımsızdır.
- Tek abone izlendiğinde sayılan çarpma tablodaki hesapla birebir uyuşuyor: 4 birimde 52,
  8 birimde 104; 12 değer önce ara katmanın genişliğine, sonra tek bir olasılığa iniyor.
- Üçlü: taban çizgisi 0,7579, ağın sayısı 0,7540, ikinci koşum 0,7738. Doğrulamanın seçtiği
  genişlik 4 birimdir ve ilk koşumu taban çizgisinin altında kalır.
- On beş buçuk kat parametre farkı beş abone, aynı genişlikte iki koşum arasındaki fark da beş abone
  ediyor; on koşumun tamamı 0,7540 ile 0,7857 arasında, sekiz abonelik bir bantta duruyor.

#### Sonraki Adım

Üç derste ağın çıktısı hep bir olasılık oldu ve o olasılık hep aynı biçimde hedefle karşılaştırıldı:
fark alınıp geriye verildi. Bu karşılaştırmanın kendisi bir seçimdir ve hiç tartışılmadı. Sonraki
ders **kayıp fonksiyonunu** bir tercih olarak değil bir sayı olarak ele alır: aynı ağ, aynı veri,
iki ayrı kayıpla eğitilirse iki ayrı sonuç veriyor mu ve fark kaç abone. Aynı derste ikinci bir
ayrım kurulur — eğitimi yöneten kayıp ile başarımı bildiren ölçüt aynı şey değildir ve kaybı
düşüren bir değişiklik ölçütü kötüleştirebilir.

### Kayıp Fonksiyonları

Source: https://academia.sh/tr/kurslar/derin-ogrenme/kayip-fonksiyonlari

Kayıp seçiminin ağın gördüğü eğimi ve ulaştığı sayıyı nasıl oynattığının ölçülmesi: ağ 0,99 diyip gerçek etiket 0 olduğunda çapraz düzensizliğin çıkış katmanına verdiği eğim 0,9900, kare hatanınki 0,0196 — oran 50,5. Aynı ağ iki kayıpla dört adayda eğitildiğinde doğrulama kare hatayı ve 25 turu seçiyor; o adayın sınama sayısı 0,7619, ikinci koşumu 0,7897, aradaki fark yedi abone. Kayıp seçiminin kattığı ise üç abone. Eğitim kaybı 0,4861'den 0,3279'a hep düşerken ve eğitim doğruluğu 0,78'den 0,86'ya çıkarken sınama doğruluğu 50. turda 0,7937 ile tepe yapıp 0,7817'ye iniyor; aynı koşumda yakalanan şüpheli 1'den 25'e çıkıyor.

Üç derste ağın çıktısı hep bir olasılık oldu ve o olasılık hep aynı biçimde hedefle
karşılaştırıldı: fark alınıp geriye verildi. Bu karşılaştırma bir seçimdir. Geriye verilen sayı
**kayıp fonksiyonunun** çıkış katmanına göre eğimidir ve kayıp değişince o sayı da değişir.

Kayıp iki ayrı işi birden yapar: eğitim sırasında ağın hangi yöne gideceğini söyler, eğitim
bittiğinde ise başarımı bildiren sayı olarak okunmaya çalışılır. İkincisi için tasarlanmamıştır ve
dersin ikinci ölçüsü bunu gösterir.

- **SA22.** Küme, bölme, tohum, on iki sütun ve **300 satıra küçültülmüş** eğitim kümesi
  `01`–`03`'teki gibidir; ağ 12–8–1, 113 parametre. Taban çizgisi sınama kümesinde 0,7579.
- **SA23.** Sınıflandırma kayıpları **çapraz düzensizlik** ve **kare hatadır**. İkisi de aynı
  sigmoit çıktısı üzerinden hesaplanır; değişen yalnız çıkış katmanına verilen eğimdir.
- **SA24.** Çapraz düzensizliğin çıkış eğimi $a-y$'dir; sigmoidin türevi kaybın türeviyle
  sadeleşir. Kare hatanın eğimi $2(a-y)\,a(1-a)$'dır ve sigmoidin türevini taşımayı sürdürür.
- **SA25.** Çapraz düzensizlikte olasılık taşma koruması için $10^{-12}$ ile alttan sınırlanır.
  Sınır sayıyı etkilemez, çünkü ağın ürettiği hiçbir olasılık o değere yaklaşmıyor.
- **SA26.** Bağlanım kayıpları bu derste **eğitilmez**, yalnız eğim davranışı hesapla gösterilir.
  M27/K03 `model-degerlendirme/05` iki uydurmayı ölçtü: açıklanan değişim 0,4770 ile 0,4751.
- **SA27.** Denenen aday sayısı **4**'tür: iki kayıp ile iki tur bütçesi (25 ve 100). Seçim
  doğrulama kümesinden, iki koşumun toplamına bakılarak yapılır.
- **SA28.** İkinci ölçüt **yakalanan şüpheli sayısıdır**: 0,5 eşiğinde işaretlenen gerçek
  şüpheliler, sınama kümesindeki 61 şüpheli üzerinden. Ölçüt tasarımı M27/K03
  `model-degerlendirme/02`'de ölçüldü.

#### Kayıp Seçimi Eğimi Değiştirir

İki kayıp arasındaki fark kayıp değerinde değil, **türevde** görünür. Ağ bir aboneye 0,99 diyor
ve gerçek etiket 0. Bu, olabilecek en kötü hatalardan biridir; kaybın buna verdiği tepki
ölçülebilir.

```python
# kayip.py — MODELDIR. Ayni KURGU abone tablosu, ayni tohum ve ayni bolme;
# egitim kumesi 01'deki gibi 300 satira kucultulmustur.
import math
import statistics

TOHUM, HAM, M32 = 20260218, 1400, 0xFFFFFFFF
BOLGE = [("kuzey", 0.28, 21, 0.00), ("guney", 0.22, 17, -0.10),
         ("dogu", 0.18, 26, 0.30), ("bati", 0.14, 14, -0.05),
         ("merkez", 0.18, 23, 0.05)]


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


def ayrik(u, w):
    t = 0.0
    for i, x in enumerate(w):
        t += x
        if u < t:
            return i
    return len(w) - 1


ABONE, VERI = [], []
for i in range(HAM):
    r = uretec(TOHUM + i)
    b = BOLGE[ayrik(r(), [x[1] for x in BOLGE])]
    hane = 1 + ayrik(r(), [0.06, 0.24, 0.30, 0.24, 0.11, 0.05])
    memnun = 1 + ayrik(r(), [0.08, 0.14, 0.27, 0.34, 0.17])
    if r() >= 0.046:
        ABONE.append({"no": 10001 + i, "bolge": b, "hane": hane, "memnuniyet": memnun})
for k in ABONE:
    r, v = uretec(TOHUM + 7000 + k["no"]), []
    for d in range(ayrik(r(), [0.05, 0.12, 0.21, 0.62])):
        v.append(0.0 if r() < 0.038 else math.floor(
            k["bolge"][2] * math.exp((r() + r() + r() - 1.5) * 0.62)
            * (1 - d * 0.05) * 100 + 0.5) / 100)
        r()
    if not v:
        continue
    ort, oyn, r = sum(v) / len(v), max(v) - min(v), uretec(TOHUM + 51000 + k["no"])
    z = (0.052 * (ort - 20) + 0.85 * (min(v) == 0.0) + 0.026 * oyn
         + 0.24 * (k["hane"] >= 5) - 0.20 * (k["memnuniyet"] >= 4) + k["bolge"][3]
         + 0.9 * (k["no"] - 10001) / 1399 + (r() + r() + r() - 1.5) * 1.30)
    x = {"hane": k["hane"], "memnuniyet": k["memnuniyet"], "donem": len(v),
         "ort_tuketim": round(ort, 2), "oynaklik": round(oyn, 2),
         "sifir_okuma": int(min(v) == 0.0), "supheli": int(z > 1.35)}
    x["kisi_basi"] = round(x["ort_tuketim"] / x["hane"], 3)
    for b in BOLGE:
        x["b_" + b[0]] = int(k["bolge"][0] == b[0])
    VERI.append(x)


def karistir(veri, tohum):
    r, s = uretec(tohum), list(range(len(veri)))
    for i in range(len(s) - 1, 0, -1):
        j = int(r() * (i + 1))
        s[i], s[j] = s[j], s[i]
    return [veri[i] for i in s]


K = karistir(VERI, TOHUM + 90000)
EGT, DOG, SIN = K[:756], K[756:1008], K[1008:]
ALAN = ["ort_tuketim", "oynaklik", "hane", "memnuniyet", "donem", "sifir_okuma",
        "kisi_basi", "b_kuzey", "b_guney", "b_dogu", "b_bati", "b_merkez"]
ORTALAMA = {a: statistics.fmean(x[a] for x in EGT) for a in ALAN}
SAPMA = {a: max(1e-9, statistics.pstdev([x[a] for x in EGT])) for a in ALAN}
TABAN = sum(x["supheli"] == 0 for x in SIN) / len(SIN)


def kume(veri):
    return ([[(x[a] - ORTALAMA[a]) / SAPMA[a] for a in ALAN] for x in veri],
            [float(x["supheli"]) for x in veri])


XE, YE = kume(EGT[:300])                    # KUCULTULMUS egitim kumesi
XD, YD = kume(DOG)
XS, YS = kume(SIN)


def sikistir(z):                            # S bicimli islev, tasma korumali
    if z >= 0:
        return 1.0 / (1.0 + math.exp(-z)) if z < 700 else 1.0
    e = math.exp(z) if z > -700 else 0.0
    return e / (1.0 + e)


def dogrultulmus(z):
    return z if z > 0.0 else 0.0


def ilklendir(tohum, kat):                  # kazanc olcekli ilklendirme, yanma sifir
    r, ag = uretec(tohum), []
    for a, b in zip(kat, kat[1:]):
        o = math.sqrt(2.0 / a)
        ag.append(([[(r() * 2 - 1) * o for _ in range(a)] for _ in range(b)], [0.0] * b))
    return ag


def dizey_carp(W, y, a):                    # DIZEY CARPIMI elle: her satir bir birim
    return [sum(w * v for w, v in zip(satir, a)) + yanma
            for satir, yanma in zip(W, y)]


def ileri(ag, x):                           # ILERI GECIS: katman katman
    a = x
    for k, (W, y) in enumerate(ag):
        z = dizey_carp(W, y, a)
        a = [sikistir(z[0])] if k == len(ag) - 1 else [dogrultulmus(t) for t in z]
    return a


KAYIP = {                                   # (kayip, cikis katmanindaki egim)
    "capraz duzensizlik": (
        lambda a, y: -(math.log(max(a, 1e-12)) if y else math.log(max(1 - a, 1e-12))),
        lambda a, y: a - y),
    "kare hata": (
        lambda a, y: (a - y) ** 2,
        lambda a, y: 2.0 * (a - y) * a * (1.0 - a)),
}
print(f"egitim {len(XE)}, dogrulama {len(XD)}, sinama {len(XS)}, "
      f"taban cizgisi {TABAN:.4f}\n")
print("siniflandirma, gercek etiket 0:")
print(f"{'cikti':>7} {'capraz kayip':>13} {'capraz egim':>12} {'kare kayip':>11} "
      f"{'kare egim':>10} {'oran':>7}")
for a in (0.01, 0.10, 0.50, 0.90, 0.99):
    ck, ce = KAYIP["capraz duzensizlik"]
    kk, ke = KAYIP["kare hata"]
    print(f"{a:>7.2f} {ck(a, 0.0):>13.4f} {ce(a, 0.0):>12.4f} {kk(a, 0.0):>11.4f} "
          f"{ke(a, 0.0):>10.4f} {ce(a, 0.0) / ke(a, 0.0):>7.1f}")
print("\nbaglanim, artik r:")
print(f"{'r':>7} {'kare kayip':>11} {'kare egim':>10} {'mutlak kayip':>13} "
      f"{'mutlak egim':>12} {'oran':>7}")
for r in (0.5, 1.0, 2.0, 5.0, 10.0):
    print(f"{r:>7.1f} {r * r:>11.4f} {2 * r:>10.4f} {r:>13.4f} {1.0:>12.4f} "
          f"{2 * r:>7.1f}")
```

```
egitim 300, dogrulama 252, sinama 252, taban cizgisi 0.7579

siniflandirma, gercek etiket 0:
  cikti  capraz kayip  capraz egim  kare kayip  kare egim    oran
   0.01        0.0101       0.0100      0.0001     0.0002    50.5
   0.10        0.1054       0.1000      0.0100     0.0180     5.6
   0.50        0.6931       0.5000      0.2500     0.2500     2.0
   0.90        2.3026       0.9000      0.8100     0.1620     5.6
   0.99        4.6052       0.9900      0.9801     0.0196    50.5

baglanim, artik r:
      r  kare kayip  kare egim  mutlak kayip  mutlak egim    oran
    0.5      0.2500     1.0000        0.5000       1.0000     1.0
    1.0      1.0000     2.0000        1.0000       1.0000     2.0
    2.0      4.0000     4.0000        2.0000       1.0000     4.0
    5.0     25.0000    10.0000        5.0000       1.0000    10.0
   10.0    100.0000    20.0000       10.0000       1.0000    20.0
```

Son satır sınıflandırmanın kararını veriyor. Ağ 0,99 deyip yanıldığında çapraz düzensizlik çıkış
katmanına 0,9900 gönderiyor, kare hata 0,0196 — arada **50,5 kat** var. Kare hatanın eğimi
sigmoidin türevini taşıdığı için ağ ne kadar emin yanılıyorsa düzeltme o kadar zayıflıyor.
`02`'de ölçülen doygunluk burada kayıp üzerinden bir kez daha karşımıza çıkıyor.

Bağlanım tablosu aynı mantığı ters yönde gösteriyor. Artık 10 birimken kare hatanın eğimi 20,
mutlak hatanınki 1. Kare hata büyük artıkları öne çıkarır ve tek bir aykırı gözlem uydurmayı
kendine çeker; mutlak hata her artığa aynı ağırlığı verir. Hangisinin doğru olduğu verinin değil,
hatanın bedelinin sorusudur.

#### Aynı Ağ, İki Kayıp

Türev farkı sayıya dönüşüyor mu, ancak eğiterek anlaşılır. Aynı ağ, aynı başlangıç değerleri,
aynı öğrenme adımı; değişen yalnız kayıp ve tur bütçesi.

```python
def egit(ag, X, Y, adim, tur, kad, izle=()):    # MODELDIR: tam toplu egim inisi
    kay, cikis_egimi = KAYIP[kad]
    n, iz = len(X), []
    for t in range(tur):
        gW = [[[0.0] * len(W[0]) for _ in W] for W, _ in ag]
        gy = [[0.0] * len(y) for _, y in ag]
        toplam = 0.0
        for i in range(n):
            a, ara = X[i], [X[i]]
            for k, (W, y) in enumerate(ag):
                z = dizey_carp(W, y, a)
                a = [sikistir(z[0])] if k == len(ag) - 1 else [dogrultulmus(q) for q in z]
                ara.append(a)
            toplam += kay(ara[-1][0], Y[i])
            d = [cikis_egimi(ara[-1][0], Y[i])]
            for k in range(len(ag) - 1, -1, -1):
                W, a = ag[k][0], ara[k]
                for j, dj in enumerate(d):
                    if dj:
                        s = gW[k][j]
                        for p in range(len(a)):
                            s[p] += dj * a[p]
                        gy[k][j] += dj
                if k:
                    onceki = [0.0] * len(a)
                    for j, dj in enumerate(d):
                        if dj:
                            s = W[j]
                            for p in range(len(a)):
                                onceki[p] += dj * s[p]
                    d = [onceki[p] if a[p] > 0 else 0.0 for p in range(len(a))]
        for k, (W, y) in enumerate(ag):
            for j in range(len(W)):
                s, g = W[j], gW[k][j]
                for p in range(len(s)):
                    s[p] -= adim * g[p] / n
                y[j] -= adim * gy[k][j] / n
        if (t + 1) in izle:
            iz.append((t + 1, toplam / n, dogruluk(ag, XE, YE), dogruluk(ag, XD, YD),
                       dogruluk(ag, XS, YS), yakalanan(ag, XS, YS)))
    return ag, iz


def dogruluk(ag, X, Y):
    return sum((ileri(ag, x)[0] > 0.5) == (y > 0.5) for x, y in zip(X, Y)) / len(X)


def yakalanan(ag, X, Y):                    # 0,5 esiginde isaretlenen gercek supheli
    return sum(1 for x, y in zip(X, Y) if y > 0.5 and ileri(ag, x)[0] > 0.5)


ADAY = {}
print(f"{'kayip':<20} {'tur':>5} {'kosum':>6} {'egt_kayip':>10} {'dogrulama':>10} "
      f"{'sinama':>8}")
for kad in KAYIP:
    for kosum in (1, 2):
        _, iz = egit(ilklendir(TOHUM + kosum, [12, 8, 1]), XE, YE, 0.3, 100, kad,
                     izle=(25, 100))
        for tur, kayip, _, dog, sin, _ in iz:
            ADAY.setdefault((kad, tur), []).append((dog, sin))
            print(f"{kad:<20} {tur:>5} {kosum:>6} {kayip:>10.4f} {dog:>10.4f} {sin:>8.4f}")
SEC = max(ADAY, key=lambda k: sum(t[0] for t in ADAY[k]))
print(f"\ndenenen aday {len(ADAY)}, dogrulamadan secilen: {SEC[0]}, {SEC[1]} tur")
print(f"taban cizgisi {TABAN:.4f}, agin sayisi {ADAY[SEC][0][1]:.4f}, "
      f"ikinci kosum {ADAY[SEC][1][1]:.4f}, fark "
      f"{round(abs(ADAY[SEC][0][1] - ADAY[SEC][1][1]) * len(XS))} abone")
en = {k: max(t[1] for t in ADAY[k]) for k in ADAY}
print(f"kayip secimi (her adayin iyi kosumu) {min(en.values()):.4f}-{max(en.values()):.4f} "
      f"= {round((max(en.values()) - min(en.values())) * len(XS))} abone")
```

```
kayip                  tur  kosum  egt_kayip  dogrulama   sinama
capraz duzensizlik      25      1     0.4341     0.8135   0.7778
capraz duzensizlik     100      1     0.3601     0.8214   0.7857
capraz duzensizlik      25      2     0.4152     0.8333   0.7778
capraz duzensizlik     100      2     0.3648     0.8056   0.7698
kare hata               25      1     0.1556     0.8135   0.7619
kare hata              100      1     0.1312     0.8214   0.7857
kare hata               25      2     0.1536     0.8373   0.7897
kare hata              100      2     0.1232     0.8056   0.7738

denenen aday 4, dogrulamadan secilen: kare hata, 25 tur
taban cizgisi 0.7579, agin sayisi 0.7619, ikinci kosum 0.7897, fark 7 abone
kayip secimi (her adayin iyi kosumu) 0.7778-0.7897 = 3 abone
```

Kayıp sütunları doğrudan karşılaştırılamaz, çünkü iki kayıp iki ayrı ölçekte sayı üretiyor:
0,4341'e karşı 0,1556. Karşılaştırılabilir olan sınama sütunudur ve iki kayıp arasındaki fark
**üç abone**, aynı adayın iki koşumu arasındaki fark ise **yedi abone**.

Tur bütçesi eğim farkını görünür kılıyor. Yirmi beş turda kare hata 0,7619'da kalırken çapraz
düzensizlik 0,7778'e ulaşıyor, yüz turda ikisi de 0,7857'ye çıkıyor. Kare hatanın zayıf eğimi
öğrenmeyi durdurmuyor, **geciktiriyor**.

#### Kayıp Ölçüt Değildir

Şimdiye kadar kayıp yalnız eğitimi yönlendirdi. Aşağıdaki tablo aynı koşumu tur tur izliyor ve üç
sayıyı yan yana koyuyor: eğitim kaybı, sınama doğruluğu ve yakalanan şüpheli sayısı.

```python
IZ = (10, 25, 50, 100, 200)
print(f"sinama kumesindeki supheli sayisi {int(sum(YS))}")
print(f"{'kosum':>6} {'tur':>5} {'egt_kayip':>10} {'egitimde':>9} {'sinamada':>9} "
      f"{'yakalanan':>10}")
IZLER = {}
for kosum in (1, 2):
    _, iz = egit(ilklendir(TOHUM + kosum, [12, 8, 1]), XE, YE, 0.3, IZ[-1],
                 "capraz duzensizlik", izle=IZ)
    IZLER[kosum] = iz
    for tur, kayip, egt, _, sin, yak in iz:
        print(f"{kosum:>6} {tur:>5} {kayip:>10.4f} {egt:>9.4f} {sin:>9.4f} {yak:>10}")
for kosum in (1, 2):
    iz = IZLER[kosum]
    en_iyi = max(iz, key=lambda t: t[4])
    print(f"kosum {kosum}: kayip {iz[0][1]:.4f} -> {iz[-1][1]:.4f} (hep dusuyor), "
          f"sinama en yuksek {en_iyi[0]}. turda {en_iyi[4]:.4f}, "
          f"{IZ[-1]}. turda {iz[-1][4]:.4f}")
    print(f"         yakalanan supheli {iz[0][5]} -> {iz[-1][5]}, "
          f"en yuksek {max(t[5] for t in iz)}")
```

```
sinama kumesindeki supheli sayisi 61
 kosum   tur  egt_kayip  egitimde  sinamada  yakalanan
     1    10     0.4861    0.7800    0.7619          1
     1    25     0.4341    0.7933    0.7778          7
     1    50     0.3899    0.8133    0.7937         20
     1   100     0.3601    0.8400    0.7857         21
     1   200     0.3279    0.8600    0.7817         25
     2    10     0.4995    0.7967    0.7817         10
     2    25     0.4152    0.8233    0.7778         16
     2    50     0.3805    0.8233    0.7738         23
     2   100     0.3648    0.8367    0.7698         25
     2   200     0.3518    0.8400    0.7738         25
kosum 1: kayip 0.4861 -> 0.3279 (hep dusuyor), sinama en yuksek 50. turda 0.7937, 200. turda 0.7817
         yakalanan supheli 1 -> 25, en yuksek 25
kosum 2: kayip 0.4995 -> 0.3518 (hep dusuyor), sinama en yuksek 10. turda 0.7817, 200. turda 0.7738
         yakalanan supheli 10 -> 25, en yuksek 25
```

Kayıp sütunu iki koşumda da tek yönlüdür: hep düşüyor. Eğitim doğruluğu da tek yönlü, 0,78'den
0,86'ya. Sınama doğruluğu ise değil. Birinci koşumda 50. turda 0,7937 ile tepe yapıp 200. turda
0,7817'ye iniyor; ikinci koşumda tepe 10. turdadır ve sonrasında hep aşağı gidiyor. Kaybı
düşürmeye devam eden turlar ayrılmış kümedeki doğruluğu kötüleştiriyor.

Son sütun ayrımı tamamlıyor. Yakalanan şüpheli sayısı iki koşumda da **artıyor**: 1'den 25'e ve
10'dan 25'e. Aynı eğitimin aynı anında bir ölçüt kötüleşirken bir başkası iyileşiyor. Onuncu turda
ağ 61 şüphelinin yalnız birini yakalıyor ama doğruluğu 0,7619; 200. turda 25'ini yakalıyor ve
doğruluğu 0,7817. "Ağ 50. turda en iyisiydi" cümlesi doğruluğu okuyan için doğru, yakalanan
şüpheliyi okuyan için yanlıştır. Hangi turda durulacağı kaybın değil ölçütün ve ölçütün ardındaki
bedelin sorusudur; o hesap M27/K03 `model-degerlendirme/03`'ün konusudur.

#### Özet

- Kayıp seçimi kayıp değerinde değil türevde belirleyicidir. Ağ 0,99 deyip yanıldığında çapraz
  düzensizliğin çıkış eğimi 0,9900, kare hatanınki 0,0196 — oran 50,5.
- Bağlanımda aynı mantık ters yönde işler: artık 10 birimken kare hatanın eğimi 20, mutlak
  hatanınki 1. Kare hata büyük artıkları öne çıkarır, mutlak hata hepsine eşit ağırlık verir.
- Üçlü: taban çizgisi 0,7579, ağın sayısı 0,7619, ikinci koşum 0,7897. Kayıp seçiminin kattığı
  üç abone, aynı adayın koşum farkı yedi abone.
- Kare hatanın zayıf eğimi öğrenmeyi durdurmuyor, geciktiriyor: 25 turda 0,7619 ile 0,7778
  ayrılıyor, 100 turda ikisi de 0,7857'ye geliyor.
- Kayıp ölçüt değildir. Eğitim kaybı 0,4861'den 0,3279'a hep düşerken sınama doğruluğu 50. turda
  tepe yapıp iniyor, yakalanan şüpheli ise 1'den 25'e çıkıyor.

#### Sonraki Adım

Dört derste eğim hep hazır geldi. Çıkış katmanındaki sayının nasıl bulunduğu bu derste yazıldı,
ama o sayının ara katmanın ağırlıklarına **nasıl dağıtıldığı** hiç açılmadı. Sonraki ders o kutuyu
açar: zincir kuralı ağ üzerinde katman katman uygulanır ve elde edilen eğim **sayısal türevle**
karşılaştırılır. Ölçü iki sayıdır — elle hesaplanan eğim ile sayısal türev arasındaki en büyük
fark ve iki yöntemin kaç ileri geçiş tuttuğu.

### Geri Yayılım

Source: https://academia.sh/tr/kurslar/derin-ogrenme/geri-yayilim

Zincir kuralının ağ üzerinde elle uygulanması ve elde edilen eğimin sayısal türevle doğrulanması: 113 parametrenin tamamında en büyük mutlak fark ilklendirmede 2,193e-10, yüz tur eğitimden sonra 8,195e-11. Adım büyüklüğü 0,001 seçildiğinde eğitilmiş ağda fark 2,518e-01'e fırlıyor; bu bir hesap hatası değil, doğrultulmuş birimin kırığıdır. Maliyet: geri yayılım 113 eğimin hepsini örnek başına bir ileri ve bir geri geçişle çıkarıyor, sayısal türev aynı iş için 4.520 geçiş istiyor ve oran parametre sayısıyla büyüyor: 58, 226, 898. Üçlü değişmiyor — taban çizgisi 0,7579, ağın sayısı 0,7857, ikinci koşum 0,7698.

Dört derste eğim hep hazır geldi. Çıkış katmanındaki sayının nasıl bulunduğu `04`'te yazıldı, ama
o sayının ara katmanın ağırlıklarına nasıl dağıtıldığı hiç açılmadı. Bu ders o dağıtımı yazar ve
yazdığı şeyin doğru olduğunu ayrı bir yöntemle sınar.

Dağıtımın kuralı zincir kuralıdır. Bir ağırlığın kayba etkisi iki parçanın çarpımıdır: beslediği
birime **geriye gelen** değer ve çarptığı **girdi**. Geriye gelen değer de bir çarpımdır — sonraki
katmandan gelenlerin ağırlıklarla toplamı, çarpı etkinleştirmenin türevi. Tek bir kural katman
katman uygulanınca bütün parametrelerin eğimi çıkar.

- **SA29.** Küme, bölme, tohum, on iki sütun ve **300 satıra küçültülmüş** eğitim kümesi
  `01`–`04`'teki gibidir; ağ 12–8–1, 113 parametre. Taban çizgisi sınama kümesinde 0,7579.
- **SA30.** Kayıp **çapraz düzensizliktir**. Çıkış katmanına gelen değer $a-y$'dir, çünkü sigmoidin
  türevi kaybın türeviyle sadeleşir; `04`'te gösterildi.
- **SA31.** Ara katmanın etkinleştirmesi doğrultulmuş doğrusal birimdir. Türevi girdisi pozitifken
  1, değilse 0'dır; sıfır noktasında tanımsızdır ve kodda 0 seçilmiştir.
- **SA32.** Eğimler örnekler üzerinden **toplanır**. Sayısal türev ortalama kayıp üzerinden
  hesaplandığı için sonucu örnek sayısıyla çarpılır ve iki yöntem aynı ölçeğe gelir.
- **SA33.** Sayısal türev **merkezi farktır**: parametre bir yukarı bir aşağı oynatılır ve fark
  iki adıma bölünür. Tek yanlı farktan daha doğrudur, iki kat geçiş ister.
- **SA34.** Doğrulama **20 satırlık bir alt kümede** yapılır; gerekçe geçiş sayısıdır.
- **SA35.** Geçiş sayısı **ileri geçiş** cinsindendir. Geri yayılımın geri geçişi bir ileri
  geçişle aynı mertebededir ve ayrı sayılmaz; oran bu yüzden bir alt sınırdır.

#### Zincir Kuralı Ağ Üzerinde

Geri yayılım iki koşudan oluşur. İleri geçişte ara değerler **saklanır**, çünkü ağırlık eğimi
onlara ihtiyaç duyar. Geri geçişte çıkıştan başlanır ve her katmanda iki iş yapılır: o katmanın
eğimleri yazılır, sonra geriye gelen değer bir önceki katmana taşınır.

```python
# geri_yayilim.py — MODELDIR. Ayni KURGU abone tablosu, ayni tohum ve ayni bolme;
# egitim kumesi 01'deki gibi 300 satira kucultulmustur.
import math
import statistics

TOHUM, HAM, M32 = 20260218, 1400, 0xFFFFFFFF
BOLGE = [("kuzey", 0.28, 21, 0.00), ("guney", 0.22, 17, -0.10),
         ("dogu", 0.18, 26, 0.30), ("bati", 0.14, 14, -0.05),
         ("merkez", 0.18, 23, 0.05)]


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


def ayrik(u, w):
    t = 0.0
    for i, x in enumerate(w):
        t += x
        if u < t:
            return i
    return len(w) - 1


ABONE, VERI = [], []
for i in range(HAM):
    r = uretec(TOHUM + i)
    b = BOLGE[ayrik(r(), [x[1] for x in BOLGE])]
    hane = 1 + ayrik(r(), [0.06, 0.24, 0.30, 0.24, 0.11, 0.05])
    memnun = 1 + ayrik(r(), [0.08, 0.14, 0.27, 0.34, 0.17])
    if r() >= 0.046:
        ABONE.append({"no": 10001 + i, "bolge": b, "hane": hane, "memnuniyet": memnun})
for k in ABONE:
    r, v = uretec(TOHUM + 7000 + k["no"]), []
    for d in range(ayrik(r(), [0.05, 0.12, 0.21, 0.62])):
        v.append(0.0 if r() < 0.038 else math.floor(
            k["bolge"][2] * math.exp((r() + r() + r() - 1.5) * 0.62)
            * (1 - d * 0.05) * 100 + 0.5) / 100)
        r()
    if not v:
        continue
    ort, oyn, r = sum(v) / len(v), max(v) - min(v), uretec(TOHUM + 51000 + k["no"])
    z = (0.052 * (ort - 20) + 0.85 * (min(v) == 0.0) + 0.026 * oyn
         + 0.24 * (k["hane"] >= 5) - 0.20 * (k["memnuniyet"] >= 4) + k["bolge"][3]
         + 0.9 * (k["no"] - 10001) / 1399 + (r() + r() + r() - 1.5) * 1.30)
    x = {"hane": k["hane"], "memnuniyet": k["memnuniyet"], "donem": len(v),
         "ort_tuketim": round(ort, 2), "oynaklik": round(oyn, 2),
         "sifir_okuma": int(min(v) == 0.0), "supheli": int(z > 1.35)}
    x["kisi_basi"] = round(x["ort_tuketim"] / x["hane"], 3)
    for b in BOLGE:
        x["b_" + b[0]] = int(k["bolge"][0] == b[0])
    VERI.append(x)


def karistir(veri, tohum):
    r, s = uretec(tohum), list(range(len(veri)))
    for i in range(len(s) - 1, 0, -1):
        j = int(r() * (i + 1))
        s[i], s[j] = s[j], s[i]
    return [veri[i] for i in s]


K = karistir(VERI, TOHUM + 90000)
EGT, DOG, SIN = K[:756], K[756:1008], K[1008:]
ALAN = ["ort_tuketim", "oynaklik", "hane", "memnuniyet", "donem", "sifir_okuma",
        "kisi_basi", "b_kuzey", "b_guney", "b_dogu", "b_bati", "b_merkez"]
ORTALAMA = {a: statistics.fmean(x[a] for x in EGT) for a in ALAN}
SAPMA = {a: max(1e-9, statistics.pstdev([x[a] for x in EGT])) for a in ALAN}
TABAN = sum(x["supheli"] == 0 for x in SIN) / len(SIN)


def kume(veri):
    return ([[(x[a] - ORTALAMA[a]) / SAPMA[a] for a in ALAN] for x in veri],
            [float(x["supheli"]) for x in veri])


XE, YE = kume(EGT[:300])                    # KUCULTULMUS egitim kumesi
XD, YD = kume(DOG)
XS, YS = kume(SIN)


def sikistir(z):                            # S bicimli islev, tasma korumali
    if z >= 0:
        return 1.0 / (1.0 + math.exp(-z)) if z < 700 else 1.0
    e = math.exp(z) if z > -700 else 0.0
    return e / (1.0 + e)


def dogrultulmus(z):
    return z if z > 0.0 else 0.0


def ilklendir(tohum, kat):                  # kazanc olcekli ilklendirme, yanma sifir
    r, ag = uretec(tohum), []
    for a, b in zip(kat, kat[1:]):
        o = math.sqrt(2.0 / a)
        ag.append(([[(r() * 2 - 1) * o for _ in range(a)] for _ in range(b)], [0.0] * b))
    return ag


def dizey_carp(W, y, a):                    # DIZEY CARPIMI elle: her satir bir birim
    return [sum(w * v for w, v in zip(satir, a)) + yanma
            for satir, yanma in zip(W, y)]


def ileri(ag, x):                           # ILERI GECIS: katman katman
    a = x
    for k, (W, y) in enumerate(ag):
        z = dizey_carp(W, y, a)
        a = [sikistir(z[0])] if k == len(ag) - 1 else [dogrultulmus(t) for t in z]
    return a


def kayip(a, y):                            # capraz duzensizlik
    return -(math.log(max(a, 1e-12)) if y else math.log(max(1 - a, 1e-12)))


def geri_yayilim(ag, X, Y, iz=False):       # MODELDIR: zincir kurali katman katman
    gW = [[[0.0] * len(W[0]) for _ in W] for W, _ in ag]
    gy = [[0.0] * len(y) for _, y in ag]
    toplam = 0.0
    for i in range(len(X)):
        a, ara = X[i], [X[i]]               # ILERI GECIS: ara degerler saklanir
        for k, (W, y) in enumerate(ag):
            z = dizey_carp(W, y, a)
            a = [sikistir(z[0])] if k == len(ag) - 1 else [dogrultulmus(q) for q in z]
            ara.append(a)
        toplam += kayip(ara[-1][0], Y[i])
        d = [ara[-1][0] - Y[i]]             # cikis katmani: kayip ile sigmoit sadelesir
        for k in range(len(ag) - 1, -1, -1):
            W, a = ag[k][0], ara[k]         # a: bu katmanin GIRDISI
            if iz:
                print(f"  katman {k + 1}: geriye gelen {len(d)} deger, ilk iki "
                      f"{[round(v, 5) for v in d[:2]]}")
            for j, dj in enumerate(d):      # agirlik egimi = geriye gelen x girdi
                s = gW[k][j]
                for p in range(len(a)):
                    s[p] += dj * a[p]
                gy[k][j] += dj              # yanma egimi = geriye gelen
            if k:                           # onceki katmana tasi, etkinlestirme turevi ile
                onceki = [0.0] * len(a)
                for j, dj in enumerate(d):
                    s = W[j]
                    for p in range(len(a)):
                        onceki[p] += dj * s[p]
                d = [onceki[p] if a[p] > 0 else 0.0 for p in range(len(a))]
    return gW, gy, toplam / len(X)


ag = ilklendir(TOHUM + 1, [12, 8, 1])
print(f"tek abone, gercek etiket {int(YE[0])}, agin ciktisi {ileri(ag, XE[0])[0]:.5f}")
gW, gy, k0 = geri_yayilim(ag, XE[:1], YE[:1], iz=True)
print(f"  kayip {k0:.5f}")
print(f"  cikis katmani agirlik egimi, ilk uc "
      f"{[round(v, 5) for v in gW[1][0][:3]]}")
print(f"  ara katman 1. birimin agirlik egimi, ilk uc "
      f"{[round(v, 5) for v in gW[0][0][:3]]}")
print(f"  ara katman yanma egimleri, ilk uc {[round(v, 5) for v in gy[0][:3]]}")
```

```
tek abone, gercek etiket 0, agin ciktisi 0.49369
  katman 2: geriye gelen 1 deger, ilk iki [0.49369]
  katman 1: geriye gelen 8 deger, ilk iki [0.0, 0.00155]
  kayip 0.68061
  cikis katmani agirlik egimi, ilk uc [0.0, 0.15433, 0.18243]
  ara katman 1. birimin agirlik egimi, ilk uc [0.0, 0.0, 0.0]
  ara katman yanma egimleri, ilk uc [0.0, 0.00155, -0.03503]
```

Çıkış katmanına gelen değer 0,49369, yani ağın çıktısı eksi gerçek etiket. Ara katmana sekiz değer
iniyor ve birincisi tam olarak 0,0. Nedeni `02`'de ölçülmüştü: o birim bu abone için etkin değil,
doğrultulmuş işlev girdisini kesmiş, türevi 0 ve zincir orada kopuyor. Sonucu son iki satırda
görünüyor — birinci birimin on iki ağırlık eğimi de sıfır ve yanma eğimi de sıfır. Bu abone o
birime hiçbir şey öğretemiyor.

#### Sayısal Türevle Doğrulama

Elle yazılan bir türev sessizce yanlış olabilir: kod çalışır, kayıp düşer, sayı üretilir ve hata
yalnız başarımın biraz düşük kalmasıyla kendini belli eder. Bağımsız sınama, kaybı parametrenin
küçük bir oynamasıyla iki kez ölçüp farkı almaktır. Yavaştır, ama ağın yapısı hakkında hiçbir şey
bilmediği için zincir kuralıyla aynı hatayı yapmaz.

```python
def ortalama_kayip(ag, X, Y):
    return sum(kayip(ileri(ag, x)[0], y) for x, y in zip(X, Y)) / len(X)


def sayisal_turev(ag, X, Y, eps):           # merkezi fark, her parametre icin iki gecis
    gW = [[[0.0] * len(W[0]) for _ in W] for W, _ in ag]
    gy = [[0.0] * len(y) for _, y in ag]
    gecis = 0
    for k, (W, y) in enumerate(ag):
        for j in range(len(W)):
            for p in range(len(W[j]) + 1):
                hedef, dizin = (W[j], p) if p < len(W[j]) else (y, j)
                eski = hedef[dizin]
                hedef[dizin] = eski + eps
                art = ortalama_kayip(ag, X, Y)
                hedef[dizin] = eski - eps
                eksi = ortalama_kayip(ag, X, Y)
                hedef[dizin] = eski
                deger = (art - eksi) / (2 * eps) * len(X)
                gecis += 2 * len(X)
                if p < len(W[j]):
                    gW[k][j][p] = deger
                else:
                    gy[k][j] = deger
    return gW, gy, gecis


def kontrol(ag, X, Y, eps):                 # elle yazilan egim ile sayisal turev
    aW, ay, _ = geri_yayilim(ag, X, Y)
    sW, sy, gecis = sayisal_turev(ag, X, Y, eps)
    f = []
    for k in range(len(ag)):
        for j in range(len(aW[k])):
            for p in range(len(aW[k][j])):
                f.append((abs(aW[k][j][p] - sW[k][j][p]), abs(aW[k][j][p])))
            f.append((abs(ay[k][j] - sy[k][j]), abs(ay[k][j])))
    return len(f), max(a for a, _ in f), max(a / max(b, 1e-12) for a, b in f), gecis


def egit(ag, X, Y, adim, tur):              # MODELDIR: tam toplu egim inisi
    n = len(X)
    for _ in range(tur):
        gW, gy, _ = geri_yayilim(ag, X, Y)
        for k, (W, y) in enumerate(ag):
            for j in range(len(W)):
                s, g = W[j], gW[k][j]
                for p in range(len(s)):
                    s[p] -= adim * g[p] / n
                y[j] -= adim * gy[k][j] / n
    return ag


ALT_X, ALT_Y = XE[:20], YE[:20]             # denetim alt kumesi, 20 satir
EGITILMIS = egit(ilklendir(TOHUM + 1, [12, 8, 1]), XE, YE, 0.3, 100)
print(f"{'ag':<24} {'eps':>7} {'parametre':>10} {'en buyuk mutlak':>16} "
      f"{'en buyuk bagil':>15}")
for etiket, a in (("ilklendirmede", ilklendir(TOHUM + 1, [12, 8, 1])),
                  ("100 tur egitimden sonra", EGITILMIS)):
    for eps in (1e-3, 1e-5, 1e-7):
        n, mutlak, bagil, gecis = kontrol(a, ALT_X, ALT_Y, eps)
        print(f"{etiket:<24} {eps:>7g} {n:>10} {mutlak:>16.3e} {bagil:>15.3e}")
```

```
ag                           eps  parametre  en buyuk mutlak  en buyuk bagil
ilklendirmede              0.001        113        2.199e-07       1.583e-07
ilklendirmede              1e-05        113        2.193e-10       4.567e-08
ilklendirmede              1e-07        113        2.591e-08       4.932e-06
100 tur egitimden sonra    0.001        113        2.518e-01       2.881e+00
100 tur egitimden sonra    1e-05        113        8.195e-11       1.412e-09
100 tur egitimden sonra    1e-07        113        7.523e-09       2.697e-07
```

İlk üç satır sayısal türevin kendi hatasını gösteriyor. Adım büyükken kesme hatası baskındır,
küçükken yuvarlama hatası; en iyi uyum ortada, 1e-05'te, 2,193e-10 ile. Yani 113 parametrenin
hepsinde iki yöntem yaklaşık on anlamlı basamağa kadar aynı sayıyı veriyor. Bu, elle yazılan
zincir kuralının doğru olduğunun kanıtıdır.

Dördüncü satır bir tuzaktır ve ölçülmeden geçilmemelidir. Eğitilmiş ağda, adım 0,001 seçildiğinde
en büyük mutlak fark 2,518e-01'e, bağıl fark 2,881'e fırlıyor. Bu bir hesap hatası değildir; aynı
ağ aynı adımda 1e-05'te 8,195e-11 veriyor. Neden doğrultulmuş birimin **kırığıdır**: 0,001'lik bir
oynama, ağırlıklı toplamı sıfırın bir yanından öbür yanına geçirmeye yetiyor ve merkezi farkın iki
ucu işlevin iki ayrı doğrusal parçasına düşüyor. Doğrulama başarısız olduğunda ilk bakılacak yer
kod değil, adım büyüklüğüdür.

#### Maliyet: Kaç Geçiş

İki yöntem aynı sayıyı üretiyorsa hangisinin kullanılacağı maliyete bakar. Geri yayılım bir ileri
ve bir geri geçişte **bütün** parametrelerin eğimini çıkarır. Sayısal türev her parametre için
ayrı iki geçiş ister.

```python
print(f"{'birim':>6} {'parametre':>10} {'geri yayilim':>13} {'sayisal turev':>14} "
      f"{'oran':>7}")
for h in (2, 8, 32):
    kat = [12, h, 1]
    P = sum(a * b + b for a, b in zip(kat, kat[1:]))
    print(f"{h:>6} {P:>10} {len(ALT_X):>13} {2 * P * len(ALT_X):>14} {2 * P:>7}")

print(f"\n{'kosum':>6} {'egt_kayip':>10} {'dogrulama':>10} {'sinama':>8}")
SIN_SAYI = []
for kosum in (1, 2):
    ag = egit(ilklendir(TOHUM + kosum, [12, 8, 1]), XE, YE, 0.3, 100)
    _, _, k = geri_yayilim(ag, XE, YE)
    d = sum((ileri(ag, x)[0] > 0.5) == (y > 0.5) for x, y in zip(XD, YD)) / len(XD)
    s = sum((ileri(ag, x)[0] > 0.5) == (y > 0.5) for x, y in zip(XS, YS)) / len(XS)
    SIN_SAYI.append(s)
    print(f"{kosum:>6} {k:>10.4f} {d:>10.4f} {s:>8.4f}")
print(f"taban cizgisi {TABAN:.4f}, agin sayisi {SIN_SAYI[0]:.4f}, "
      f"ikinci kosum {SIN_SAYI[1]:.4f}, fark "
      f"{round(abs(SIN_SAYI[0] - SIN_SAYI[1]) * len(XS))} abone")
```

```
 birim  parametre  geri yayilim  sayisal turev    oran
     2         29            20           1160      58
     8        113            20           4520     226
    32        449            20          17960     898

 kosum  egt_kayip  dogrulama   sinama
     1     0.3597     0.8214   0.7857
     2     0.3646     0.8056   0.7698
taban cizgisi 0.7579, agin sayisi 0.7857, ikinci kosum 0.7698, fark 4 abone
```

Geri yayılım sütunu üç satırda da 20'dir — örnek sayısı kadar. Sayısal türev sütunu parametre
sayısıyla birlikte büyüyor: 1.160, 4.520, 17.960. Oran parametre sayısının iki katıdır ve 32
birimlik ağda 898'e çıkıyor. Geri yayılımın maliyeti parametre sayısından bağımsızdır; işi ileri
geçişte saklanan ara değerler yapar. Sayısal türev bu yüzden bir eğitim yöntemi değil, bir
**denetim** aracıdır.

Son satır dört dersin sayısını doğruluyor. Bu bölümde eğitim `geri_yayilim` ile yürütüldü ve üçlü
`01`'dekiyle aynı çıktı: 0,7579 — 0,7857 — 0,7698. Bunun nedeni açıktır; `01`'den beri koşan kod
zaten geri yayılımdı, yalnız adı konmamıştı.

#### Özet

- Bir ağırlığın eğimi, beslediği birime geriye gelen değer ile o ağırlığın çarptığı girdinin
  çarpımıdır; geriye gelen değer sonraki katmandan taşınıp etkinleştirmenin türeviyle çarpılır.
- Etkin olmayan bir birimin bütün eğimleri sıfırdır: örnek abonede ara katmanın birinci biriminin
  on iki ağırlık eğimi de yanma eğimi de 0,0 çıkıyor.
- Merkezi farkla doğrulama 113 parametrenin hepsinde uyuyor: ilklendirmede en büyük mutlak fark
  2,193e-10, yüz tur eğitimden sonra 8,195e-11. Adım çok büyük ya da çok küçük seçildiğinde
  sayısal türevin kendi hatası büyüyor.
- Eğitilmiş ağda adım 0,001'de fark 2,518e-01'e fırlıyor; bu doğrultulmuş birimin kırığıdır, hesap
  hatası değil. Aynı ağ 1e-05'te 8,195e-11 veriyor.
- Geri yayılım 113 eğimin hepsini örnek başına bir ileri ve bir geri geçişle çıkarıyor; sayısal
  türev aynı iş için 4.520 geçiş istiyor ve oran parametre sayısıyla büyüyor: 58, 226, 898.

#### Sonraki Adım

Eğim artık doğru hesaplanıyor ve ucuz. Ama onunla ne yapılacağı beş derste hiç sorulmadı: her
turda eğim aynı sabit sayıyla çarpılıp ağırlıklardan çıkarıldı, hep aynı büyüklükte, önceki
turların ne yaptığına hiç bakılmadan. Aynı eğimi başka türlü kullanmak — önceki adımların yönünü
hatırlamak ya da her parametreye kendi adım büyüklüğünü vermek — aynı tur bütçesinde hangi kayba
varır ve iki koşum arasında ne kadar oynar, ölçülmedi. Sonraki ders eğimi bir sonuç değil bir
girdi olarak ele alır.

### Eniyileme Algoritmaları

Source: https://academia.sh/tr/kurslar/derin-ogrenme/eniyileme-algoritmalari

Aynı eğimin üç ayrı adım kuralıyla kullanılması ve düşen kaybın düşen hata anlamına gelmediğinin ölçülmesi: 40 turluk ortak bütçede momentumlu iniş eğitim kaybını 0,2777'ye, uyarlamalı adım 0,2923'e indirir, yalın iniş 0,3296'da kalır; buna karşılık sınama doğrulukları 0,7500, 0,7222 ve 0,7698'dir. Doğrulamadan okunan üç ayarda ağın sayısı 0,7857, aynı ağın ikinci koşumu 0,7698'dir ve taban çizgisi 0,7579. Yalnız ilklendirme değişerek dört koşum yapıldığında tek bir eniyileyicinin sınama açıklığı 0,0317'ye, yani sekiz aboneye çıkar; eniyileyiciler arası fark ise koşuma göre 0,0516 ile 0,0079 arasında oynar ve on iki koşumun hiçbiri doğrusal modelin 0,8016'sını geçmez.

Önceki ders eğimin doğru hesaplandığını gösterdi: geri yayılımın verdiği sayı sayısal türevle
karşılaştırıldı ve aradaki fark basıldı. Ama eğim bir **yön** verir, bir **adım** vermez. Beş
derste ağırlıkların o yönde hangi kuralla oynatılacağı hiç sorulmadı; sorulmadığı için tek bir
kural varmış gibi duruyor: ağırlıktan eğimin sabit bir katını çıkar.

Bu ders o boşluğu doldurur. Aynı ağ, aynı veri, aynı eğim ve aynı tur bütçesiyle **üç ayrı adım
kuralı** koşturulur. Ölçü ikilidir: eniyileyicinin işi eğitim kaybını düşürmektir, modelin işi
ayrılmış kümede doğru bilmektir. Bu dersin bulgusu ikisinin **ters yönde gidebildiğidir**.

- **SA46.** Küme, bölme ve tohum önceki derslerdeki gibidir; tablo **kurgudur**. Koşum süresi ders
  içinde kalsın diye eğitim kümesi **756 satırdan 300 satıra küçültülmüştür**; doğrulama ve sınama
  kümeleri değişmedi (252 ve 252) ve taban çizgisi sınamada **0,7579**.
- **SA47.** Ağ sabittir: 12 girdi, 8 gizli birim, 1 çıktı. Değişen yalnız adım kuralıdır. Gizli
  katmanda doğrultulmuş doğrusal birim, çıktıda sigmoit, kayıpta çapraz düzensizlik vardır;
  ilklendirme **kazanç ölçeklidir** ve yanmalar sıfırdan başlar.
- **SA48.** Tur bütçesi 40, toplu boyut 20'dir; üçü de aynı sayıda güncelleme harcar.
- **SA49.** Üç kural şudur: **yalın iniş** (ağırlıktan eğimin sabit katı çıkarılır),
  **momentumlu iniş** (eğimler 0,9 unutma katsayısıyla birikir) ve **uyarlamalı adım** (her ağırlık
  için karesel eğim birikimi tutulur ve adım o birikimin köküne bölünür).
- **SA50.** Toplu bölme sırası her koşumda aynıdır. Koşumdan koşuma değişen tek şey
  **ilklendirmedir**.
- **SA51.** Denenen aday **9**'dur: üç eniyileyici çarpı üç öğrenme adımı, seçim doğrulama
  kümesinden.
- **SA52.** Karşılaştırma çizgileri M27/K03'ten gelir ve yeniden eğitilmez: doğrusal model
  **0,8016**, karar ağacı **0,7857**. İkisi de aynı sınama kümesinde ölçülmüştü.
- **SA53.** Hızın ölçüsü süre değil **tur sayısıdır**: kayıp 0,40 eşiğinin altına ilk kez hangi
  turda iniyor. Eşik keyfidir ve üç eniyileyici için aynıdır.

#### Eğimden Adıma

Kurulum kurgu tabloyu üretir, kümeleri ayırır ve ağı tanımlar. Her ağırlık satırının son katsayısı
**yanmadır**.

```python
# eniyileme.py — MODELDIR. Ayni KURGU abone tablosu, ayni tohum, ayni bolme;
# egitim kumesi bu konuda 300 satira kucultulmustur.
import math
import statistics

TOHUM, HAM, M32 = 20260218, 1400, 0xFFFFFFFF
BOLGE = [("kuzey", 0.28, 21, 0.00), ("guney", 0.22, 17, -0.10),
         ("dogu", 0.18, 26, 0.30), ("bati", 0.14, 14, -0.05),
         ("merkez", 0.18, 23, 0.05)]


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


def ayrik(u, w):
    t = 0.0
    for i, x in enumerate(w):
        t += x
        if u < t:
            return i
    return len(w) - 1


VERI = []
for i in range(HAM):
    r = uretec(TOHUM + i)
    b = BOLGE[ayrik(r(), [x[1] for x in BOLGE])]
    hane = 1 + ayrik(r(), [0.06, 0.24, 0.30, 0.24, 0.11, 0.05])
    memnun = 1 + ayrik(r(), [0.08, 0.14, 0.27, 0.34, 0.17])
    if r() < 0.046:
        continue
    no = 10001 + i
    r, v = uretec(TOHUM + 7000 + no), []
    for d in range(ayrik(r(), [0.05, 0.12, 0.21, 0.62])):
        v.append(0.0 if r() < 0.038 else math.floor(
            b[2] * math.exp((r() + r() + r() - 1.5) * 0.62)
            * (1 - d * 0.05) * 100 + 0.5) / 100)
        r()
    if not v:
        continue
    ort, oyn, r = sum(v) / len(v), max(v) - min(v), uretec(TOHUM + 51000 + no)
    z = (0.052 * (ort - 20) + 0.85 * (min(v) == 0.0) + 0.026 * oyn + 0.24 * (hane >= 5)
         - 0.20 * (memnun >= 4) + b[3] + 0.9 * (no - 10001) / 1399
         + (r() + r() + r() - 1.5) * 1.30)
    x = {"hane": hane, "memnuniyet": memnun, "donem": len(v), "ort_tuketim": round(ort, 2),
         "oynaklik": round(oyn, 2), "sifir_okuma": int(min(v) == 0.0),
         "supheli": int(z > 1.35)}
    x["kisi_basi"] = round(x["ort_tuketim"] / x["hane"], 3)
    for q in BOLGE:
        x["b_" + q[0]] = int(b[0] == q[0])
    VERI.append(x)

r, S = uretec(TOHUM + 90000), list(range(len(VERI)))
for i in range(len(S) - 1, 0, -1):
    j = int(r() * (i + 1))
    S[i], S[j] = S[j], S[i]
K = [VERI[i] for i in S]
EGT, DOG, SIN = K[:300], K[756:1008], K[1008:]      # egitim 756'dan 300'e KUCULTULDU
ALAN = ["ort_tuketim", "oynaklik", "hane", "memnuniyet", "donem", "sifir_okuma",
        "kisi_basi", "b_kuzey", "b_guney", "b_dogu", "b_bati", "b_merkez"]
ORT = {a: statistics.fmean(x[a] for x in EGT) for a in ALAN}
SAP = {a: max(1e-9, statistics.pstdev([x[a] for x in EGT])) for a in ALAN}


def olcekli(s):                             # OGRENME egitimden, UYGULAMA her kumeye
    return ([[(x[a] - ORT[a]) / SAP[a] for a in ALAN] for x in s],
            [float(x["supheli"]) for x in s])


XE, YE = olcekli(EGT)
XD, YD = olcekli(DOG)
XS, YS = olcekli(SIN)
TABAN = sum(y == 0.0 for y in YS) / len(YS)
AGAC, DOGRUSAL = 198 / len(SIN), 202 / len(SIN)     # M27/K03'un iki sayisi


def sikistir(z):
    if z >= 0:
        return 1.0 / (1.0 + math.exp(-z)) if z < 700 else 1.0
    e = math.exp(z) if z > -700 else 0.0
    return e / (1.0 + e)


def ilklendir(tohum, bicim, kazanc=1.0):    # kazanc olcekli; her satirin son sutunu YANMA
    r, kat = uretec(tohum), []
    for g, c in bicim:
        a = math.sqrt(6.0 * kazanc / g)
        kat.append([[(r() * 2 - 1) * a for _ in range(g)] + [0.0] for _ in range(c)])
    return kat


def sifir(kat):
    return [[[0.0] * len(w) for w in W] for W in kat]


def ileri(kat, x):                          # ara katmanlarda dogrultulmus dogrusal birim,
    a, iz = x, []                           # cikista sigmoit
    for i, W in enumerate(kat):
        iz.append(a)
        z = [sum(p * q for p, q in zip(w, a)) + w[-1] for w in W]
        a = [sikistir(z[0])] if i == len(kat) - 1 else [t if t > 0 else 0.0 for t in z]
    iz.append(a)
    return iz


def egim(kat, X, Y, idx):                   # GERI YAYILIM, capraz duzensizlik kaybi
    G, kayip = sifir(kat), 0.0
    for i in idx:
        iz = ileri(kat, X[i])
        p = min(max(iz[-1][0], 1e-12), 1 - 1e-12)
        kayip -= Y[i] * math.log(p) + (1 - Y[i]) * math.log(1 - p)
        d = [p - Y[i]]
        for L in range(len(kat) - 1, -1, -1):
            W, a = kat[L], iz[L]
            for k, dk in enumerate(d):
                gk = G[L][k]
                for j, aj in enumerate(a):
                    gk[j] += dk * aj
                gk[-1] += dk
            if L:
                d = [sum(d[k] * W[k][j] for k in range(len(W))) * (a[j] > 0)
                     for j in range(len(a))]
    for W in G:
        for w in W:
            w[:] = [v / len(idx) for v in w]
    return G, kayip / len(idx)


def dogruluk(kat, X, Y):
    return sum((ileri(kat, x)[-1][0] > 0.5) == (y > 0.5) for x, y in zip(X, Y)) / len(X)


def sira(tur):                              # toplu bolme sirasi her kosumda AYNI
    r, s = uretec(TOHUM + 500 + tur), list(range(len(XE)))
    for i in range(len(s) - 1, 0, -1):
        j = int(r() * (i + 1))
        s[i], s[j] = s[j], s[i]
    return s


KAT0 = ilklendir(TOHUM + 1, [(len(ALAN), 8), (8, 1)])
print(f"egitim {len(EGT)} (756'dan kucultuldu), dogrulama {len(DOG)}, "
      f"sinama {len(SIN)}, sutun {len(ALAN)}")
print(f"ag {len(ALAN)}-8-1, parametre {sum(len(w) for W in KAT0 for w in W)}, "
      f"tur 40, toplu 20, guncelleme {40 * len(XE) // 20}")
print(f"taban {TABAN:.4f}; karsilastirma cizgileri dogrusal model {DOGRUSAL:.4f}, "
      f"karar agaci {AGAC:.4f}; ilklendirilmis ag {dogruluk(KAT0, XS, YS):.4f}")
```

```
egitim 300 (756'dan kucultuldu), dogrulama 252, sinama 252, sutun 12
ag 12-8-1, parametre 113, tur 40, toplu 20, guncelleme 600
taban 0.7579; karsilastirma cizgileri dogrusal model 0.8016, karar agaci 0.7857; ilklendirilmis ag 0.3333
```

Son sayı çıkış noktasını veriyor: eğitilmemiş ağ sınama kümesinde 0,3333 tutturuyor, taban
çizgisinin çok altında. 113 parametrenin tamamı henüz gürültüdür ve 600 güncellemenin işi bu
sayıyı yukarı taşımaktır.

#### Aynı Tur Bütçesinde Üç Eniyileyici

Üç kural tek bir işlevde durur. Yalın iniş eğimi doğrudan kullanır. Momentumlu iniş geçmiş
eğimleri biriktirir; yön tutarlıysa adım büyür, yön salınıyorsa adımlar birbirini götürür.
Uyarlamalı adım her ağırlık için ayrı bir karesel eğim birikimi tutar ve o ağırlığın adımını
birikimin köküne böler; sürekli büyük eğim gören ağırlık küçük, seyrek eğim gören ağırlık büyük
adımla ilerler.

```python
def uygula(kat, G, M, V, yontem, adim):     # tek bir guncelleme adimi
    for W, gW, mW, vW in zip(kat, G, M, V):
        for w, g, m, v in zip(W, gW, mW, vW):
            for j in range(len(w)):
                if yontem == "momentumlu":          # birikmis yon
                    m[j] = 0.9 * m[j] + g[j]
                    w[j] -= adim * m[j]
                elif yontem == "uyarlamali":        # karesel egim birikimi
                    v[j] = 0.9 * v[j] + 0.1 * g[j] * g[j]
                    w[j] -= adim * g[j] / (math.sqrt(v[j]) + 1e-8)
                else:                               # yalin inis
                    w[j] -= adim * g[j]


def egit(yontem, adim, tohum, tur=40, toplu=20):
    kat = ilklendir(tohum, [(len(ALAN), 8), (8, 1)])
    M, V, iz = sifir(kat), sifir(kat), []
    for t in range(tur):
        s, top = sira(t), 0.0
        for b in range(0, len(s), toplu):
            G, k = egim(kat, XE, YE, s[b:b + toplu])
            uygula(kat, G, M, V, yontem, adim)
            top += k * toplu
        iz.append(top / len(s))
    return kat, iz


def hedefe_tur(iz, esik=0.40):              # kayip esigin altina inen ilk tur
    for t, k in enumerate(iz):
        if k < esik:
            return str(t + 1)
    return "inmedi"


YONTEM = ("yalin", "momentumlu", "uyarlamali")
SONUC = {}
print(f"{'eniyileyici':>12} {'adim':>6} {'egitim kaybi':>13} {'hedefe tur':>11} "
      f"{'dogrulama':>10} {'sinama':>8}")
for y in YONTEM:
    for adim in (0.02, 0.05, 0.15):
        kat, iz = egit(y, adim, TOHUM + 1)
        SONUC[(y, adim)] = (iz[-1], dogruluk(kat, XD, YD), dogruluk(kat, XS, YS))
        print(f"{y:>12} {adim:>6} {iz[-1]:>13.4f} {hedefe_tur(iz):>11} "
              f"{SONUC[(y, adim)][1]:>10.4f} {SONUC[(y, adim)][2]:>8.4f}")
SECIM = {y: max((0.02, 0.05, 0.15), key=lambda a: SONUC[(y, a)][1]) for y in YONTEM}
enk = min(SONUC.values(), key=lambda t: t[0])
enb = max(SONUC.values(), key=lambda t: t[2])
print(f"\ndenenen aday {len(SONUC)}; dogrulamadan okunan adimlar "
      + ", ".join(f"{y} {SECIM[y]}" for y in YONTEM)
      + f"\nen dusuk kayip {enk[0]:.4f} (sinama {enk[2]:.4f}), "
      + f"en yuksek sinama {enb[2]:.4f} (kayip {enb[0]:.4f})")
```

```
 eniyileyici   adim  egitim kaybi  hedefe tur  dogrulama   sinama
       yalin   0.02        0.4042      inmedi     0.8135   0.7857
       yalin   0.05        0.3664          19     0.8056   0.7897
       yalin   0.15        0.3296           8     0.7817   0.7698
  momentumlu   0.02        0.3186           6     0.7976   0.7579
  momentumlu   0.05        0.2811           4     0.7817   0.7540
  momentumlu   0.15        0.2777           3     0.7817   0.7500
  uyarlamali   0.02        0.2948           4     0.7659   0.7341
  uyarlamali   0.05        0.2923           3     0.7500   0.7222
  uyarlamali   0.15        0.3038           8     0.7341   0.7460

denenen aday 9; dogrulamadan okunan adimlar yalin 0.02, momentumlu 0.02, uyarlamali 0.02
en dusuk kayip 0.2777 (sinama 0.7500), en yuksek sinama 0.7897 (kayip 0.3664)
```

Kayıp sütunu eniyileyicilerin işini yaptığını gösteriyor. Aynı 600 güncellemede momentumlu iniş
0,2777'ye, uyarlamalı adım 0,2923'e iniyor; yalın inişin en iyisi 0,3296'da kalıyor. Fark tur
cinsinden daha keskin: momentumlu iniş 0,40 eşiğini **üçüncü** turda geçiyor, yalın iniş en küçük
adımda kırk turda hiç geçemiyor.

Sınama sütunu bunun karşılığını vermiyor. En düşük kaybı üreten ayar sınamada **0,7500** veriyor;
en yüksek sınama sayısını, **0,7897**, kaybı yalnız 0,3664'e indiren yalın iniş üretiyor. İki
sütun ters yönde gidiyor, çünkü 300 satırda 113 parametre için kaybı daha aşağı çekmenin bir yolu
var: eğitim satırlarını ezberlemek. Momentumlu iniş ve uyarlamalı adım oraya daha çabuk varıyor.
**Eniyileyici kaybı düşürür, genellemeyi düşürmez.** Seçim bu yüzden doğrulama kümesinden okunuyor
ve üçünde de en küçük adım, 0,02, kazanıyor.

#### Koşum Değişkenliği Yöntem Farkını Yutuyor

Yukarıdaki tablonun her satırı **tek bir koşumdur**. Aşağıdaki blok üç eniyileyiciyi doğrulamadan
okunan adımlarıyla dörder kez koşturuyor; veri, sıra, bütçe ve adım sabit, değişen yalnız
ilklendirme.

```python
print(f"{'eniyileyici':>12} {'kayip 4 kosum':>32} {'sinama 4 kosum':>32}")
OZ = {}
for y in YONTEM:
    ks = [egit(y, SECIM[y], TOHUM + t) for t in (1, 2, 3, 4)]
    OZ[y] = ([iz[-1] for _, iz in ks], [dogruluk(k, XS, YS) for k, _ in ks])
    print(f"{y:>12} " + " ".join(f"{v:>7.4f}" for v in OZ[y][0])
          + "  " + " ".join(f"{v:>7.4f}" for v in OZ[y][1]))
for y in YONTEM:
    s = OZ[y][1]
    print(f"{y:>12} sinama acikligi {max(s) - min(s):.4f} "
          f"({round((max(s) - min(s)) * len(SIN))} abone)")
en_iyi = max(YONTEM, key=lambda y: OZ[y][1][0])
print(f"\ntaban cizgisi {TABAN:.4f}, agin sayisi {OZ[en_iyi][1][0]:.4f} ({en_iyi}), "
      f"ayni agin ikinci kosumu {OZ[en_iyi][1][1]:.4f}")
print("kosum basina en iyi ile en kotu eniyileyici arasindaki fark: "
      + ", ".join(f"{max(OZ[y][1][t] for y in YONTEM) - min(OZ[y][1][t] for y in YONTEM):.4f}"
                  for t in range(4)))
print(f"karar agacini gecen kosum "
      f"{sum(v > AGAC + 1e-9 for _, s in OZ.values() for v in s)}/12, dogrusal modeli gecen "
      f"kosum {sum(v > DOGRUSAL + 1e-9 for _, s in OZ.values() for v in s)}/12")
```

```
 eniyileyici                    kayip 4 kosum                   sinama 4 kosum
       yalin  0.4042  0.3874  0.3980  0.3972   0.7857  0.7698  0.7897  0.7817
  momentumlu  0.3186  0.3373  0.3244  0.3177   0.7579  0.7659  0.7817  0.7738
  uyarlamali  0.2948  0.3064  0.2922  0.2976   0.7341  0.7619  0.7619  0.7659
       yalin sinama acikligi 0.0198 (5 abone)
  momentumlu sinama acikligi 0.0238 (6 abone)
  uyarlamali sinama acikligi 0.0317 (8 abone)

taban cizgisi 0.7579, agin sayisi 0.7857 (yalin), ayni agin ikinci kosumu 0.7698
kosum basina en iyi ile en kotu eniyileyici arasindaki fark: 0.0516, 0.0079, 0.0278, 0.0159
karar agacini gecen kosum 1/12, dogrusal modeli gecen kosum 0/12
```

Kayıp sütunları dar: her eniyileyici dört koşumda kendi bandında kalıyor ve üç bant birbirine
değmiyor. Eniyileyicinin kayıp üzerindeki etkisi bu ölçekte **kararlıdır**.

Sınama sütunları dar değil. Uyarlamalı adım 0,7341 ile 0,7659 arasında geziyor; bu 0,0317, yani
sekiz abone eder. Son satırdan bir öncesi dersin asıl bulgusudur: eniyileyiciler arasındaki fark
birinci koşumda 0,0516, ikinci koşumda **0,0079**. Aynı üç yöntem, aynı ayarlar, aynı veri —
yalnız ilklendirme değişti ve aradaki mesafe altı kattan fazla daraldı. Birinci koşuma bakıp
"yalın iniş uyarlamalı adımı 0,0516 geçiyor" demek ölçülmüş bir sonuç değildir.

Üçlü şu haldedir: taban çizgisi 0,7579, ağın sayısı 0,7857, aynı ağın ikinci koşumu 0,7698; fark
tabana göre 0,0278, yani yedi abone. Son satır kursun ikinci iddiasını veriyor: on iki koşumun
**yalnız biri** karar ağacının 0,7857'sini geçiyor, **hiçbiri** doğrusal modelin 0,8016'sını
geçmiyor. Bu tablo verisinde ağ iki basit aileyi geçmiyor ve bu gizlenmiyor.

#### Özet

- Geri yayılım bir yön verir; adım kuralı ayrı bir karardır ve üç kural aynı 600 güncellemelik
  bütçede karşılaştırılır.
- Momentumlu iniş eğitim kaybını 0,2777'ye, uyarlamalı adım 0,2923'e indiriyor; yalın iniş
  0,3296'da kalıyor ve 0,40 eşiğine en küçük adımda hiç inemiyor.
- Sınama sütunu tersine dönüyor: en düşük kayıp 0,7500, en yüksek sınama sayısı 0,7897 veriyor.
  Eniyileyici kaybı düşürür, genellemeyi düşürmez.
- Yalnız ilklendirme değişen dört koşumda tek bir eniyileyicinin sınama açıklığı 0,0317, yani
  sekiz abonedir; eniyileyiciler arası fark ise koşuma göre 0,0516 ile 0,0079 arasında oynuyor.
- Üçlü: taban 0,7579, ağın sayısı 0,7857, ikinci koşum 0,7698. On iki koşumun biri karar ağacını
  geçiyor, hiçbiri doğrusal modeli geçmiyor.

#### Sonraki Adım

Bu dersin ağı iki katmanlıydı ve eğim geri gelirken yalnız bir kez zincirlendi. Katman sayısı
arttığında soru temiz kalmıyor: eğim çıkıştan girişe doğru her katmanda bir çarpanla süzülür ve o
çarpanların çarpımı ya sıfıra iner ya da taşar. Sonraki ders bunu bir sayıya bağlar — ağ
derinleştikçe ilk katmanın gördüğü eğim büyüklüğü son katmanınkine göre kaç kat küçülüyor, hangi
ilklendirme kazancında tersine dönüp patlıyor ve eğim kırpmayla öğrenme adımı çizelgesi bu iki
uçtan hangisini ne kadar düzeltiyor.

### Eğitim Kararlılığı

Source: https://academia.sh/tr/kurslar/derin-ogrenme/egitim-kararliligi

Eğimin katmanlardan geçerken sönmesinin ve patlamasının sayıyla ölçülmesi: doygun etkinleştirmeyle ilk katmanın eğim büyüklüğü tek gizli katmanda 1,274e-02 iken altı katmanda 5,539e-05'e, yani 230 kat aşağı iner ve son katmana oran 18,8'den 3977,2'ye çıkar; doğrultulmuş doğrusal birimle aynı derinlikte oran 0,7022'de kalır, ilklendirme kazancı 16'ya çıkarıldığında ise 134,99 kat büyür. Öğrenme adımı 10'da üç gizli katmanlı ağın eğim büyüklüğü 2,800e+07'ye fırlıyor, 24 birimin 15'i ölüyor ve iki koşum da tam olarak taban çizgisini, 0,7579'u veriyor. Eğim kırpma 450 güncellemenin 400'ünü kırpıp eğitimi kurtarıyor ama sınama 0,6984'e, tabanın altına düşüyor; kırpma ile çizelge birlikte kaybı 0,2722'ye indiriyor ve koşum farkını 0,0516'ya, on üç aboneye çıkarıyor.

Önceki ders üç adım kuralını iki katmanlı bir ağda karşılaştırdı. Orada eğim geri gelirken bir kez
zincirlendi, bu yüzden her katman benzer büyüklükte bir eğim gördü. Katman sayısı arttığında bu
doğru olmaktan çıkar: çıkıştaki hata girişe doğru ilerlerken her katmanda bir çarpanla süzülür ve
o çarpanların **çarpımı** ilk katmana ne kaldığını belirler. Çarpanlar birden küçükse çarpım
sıfıra iner, birden büyükse taşar.

Bu ders o çarpımı ölçer. İki uç ayrı ayrı sayılır — **sönen eğim** ve **patlayan eğim** — sonra
iki düzeltme denenir: **eğim kırpma** ve **öğrenme adımı çizelgesi**. Ölçü yine ikilidir: eğitimin
kurtarılması ile ayrılmış küme sayısının düzelmesi aynı şey değildir.

- **SA54.** Küme, bölme, tohum ve ölçek önceki derstekiyle aynıdır; tablo **kurgudur**, eğitim
  kümesi **300 satıra küçültülmüştür** ve taban çizgisi sınamada **0,7579**.
- **SA55.** Her gizli katman 8 birimlidir: bir katman 113, iki katman 185, dört katman 329, altı
  katman 473 parametre eder.
- **SA56.** Eğim büyüklüğü bir katmandaki eğim girdilerinin **karelerinin ortalamasının koküdür**;
  katmanlar farklı sayıda ağırlık taşıdığı için toplam değil ortalama alınır.
- **SA57.** Ölçüm **ilklendirmeden hemen sonra**, tek bir 60 satırlık toplu üzerinde yapılır;
  sorulan şey eğitimin sonucu değil, eğimin katmanlar arasında nasıl dağıldığıdır. İki
  etkinleştirme yan yana durur: **sigmoit** (doygun) ve **doğrultulmuş doğrusal birim**
  (doygunsuz). Kazanç, ilklendirme aralığının genişliğini belirleyen çarpandır.
- **SA58.** Kararlılık denemesinde ağ üç gizli katmanlıdır, 30 tur ve 20 toplu boyutuyla **450
  güncelleme** yapar ve yalın iniş kullanır. Denenen ayar **5**'tir; bu bir arama değildir.
- **SA59.** **Eğim kırpma** eşiği 0,10'dur ve bütün ağın eğim büyüklüğüne bir kerede uygulanır:
  büyüklük eşiği aşarsa eğim aynı oranla küçültülür, yön korunur. **Çizelge** her altı turda
  öğrenme adımını yarıya indirir.
- **SA60.** **Ölü birim** hiçbir eğitim satırında sıfırdan büyük çıktı vermeyen birimdir; üç gizli
  katmanda toplam 24 birim vardır.

#### Eğim Katmanlardan Geçerken

Kurulum önceki dersinkiyle aynıdır; tek fark ileri geçişin ve geri yayılımın **etkinleştirmeyi bir
değişken olarak** almasıdır. Sigmoitin türevi çıktının kendisinden hesaplanır, doğrultulmuş
doğrusal birimin türevi sıfır ya da birdir.

```python
# kararlilik.py — MODELDIR. Ayni KURGU abone tablosu, ayni tohum, ayni bolme;
# egitim kumesi bu konuda 300 satira kucultulmustur.
import math
import statistics

TOHUM, HAM, M32 = 20260218, 1400, 0xFFFFFFFF
BOLGE = [("kuzey", 0.28, 21, 0.00), ("guney", 0.22, 17, -0.10),
         ("dogu", 0.18, 26, 0.30), ("bati", 0.14, 14, -0.05),
         ("merkez", 0.18, 23, 0.05)]


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


def ayrik(u, w):
    t = 0.0
    for i, x in enumerate(w):
        t += x
        if u < t:
            return i
    return len(w) - 1


VERI = []
for i in range(HAM):
    r = uretec(TOHUM + i)
    b = BOLGE[ayrik(r(), [x[1] for x in BOLGE])]
    hane = 1 + ayrik(r(), [0.06, 0.24, 0.30, 0.24, 0.11, 0.05])
    memnun = 1 + ayrik(r(), [0.08, 0.14, 0.27, 0.34, 0.17])
    if r() < 0.046:
        continue
    no = 10001 + i
    r, v = uretec(TOHUM + 7000 + no), []
    for d in range(ayrik(r(), [0.05, 0.12, 0.21, 0.62])):
        v.append(0.0 if r() < 0.038 else math.floor(
            b[2] * math.exp((r() + r() + r() - 1.5) * 0.62)
            * (1 - d * 0.05) * 100 + 0.5) / 100)
        r()
    if not v:
        continue
    ort, oyn, r = sum(v) / len(v), max(v) - min(v), uretec(TOHUM + 51000 + no)
    z = (0.052 * (ort - 20) + 0.85 * (min(v) == 0.0) + 0.026 * oyn + 0.24 * (hane >= 5)
         - 0.20 * (memnun >= 4) + b[3] + 0.9 * (no - 10001) / 1399
         + (r() + r() + r() - 1.5) * 1.30)
    x = {"hane": hane, "memnuniyet": memnun, "donem": len(v), "ort_tuketim": round(ort, 2),
         "oynaklik": round(oyn, 2), "sifir_okuma": int(min(v) == 0.0),
         "supheli": int(z > 1.35)}
    x["kisi_basi"] = round(x["ort_tuketim"] / x["hane"], 3)
    for q in BOLGE:
        x["b_" + q[0]] = int(b[0] == q[0])
    VERI.append(x)

r, S = uretec(TOHUM + 90000), list(range(len(VERI)))
for i in range(len(S) - 1, 0, -1):
    j = int(r() * (i + 1))
    S[i], S[j] = S[j], S[i]
K = [VERI[i] for i in S]
EGT, DOG, SIN = K[:300], K[756:1008], K[1008:]      # egitim 756'dan 300'e KUCULTULDU
ALAN = ["ort_tuketim", "oynaklik", "hane", "memnuniyet", "donem", "sifir_okuma",
        "kisi_basi", "b_kuzey", "b_guney", "b_dogu", "b_bati", "b_merkez"]
ORT = {a: statistics.fmean(x[a] for x in EGT) for a in ALAN}
SAP = {a: max(1e-9, statistics.pstdev([x[a] for x in EGT])) for a in ALAN}


def olcekli(s):                             # OGRENME egitimden, UYGULAMA her kumeye
    return ([[(x[a] - ORT[a]) / SAP[a] for a in ALAN] for x in s],
            [float(x["supheli"]) for x in s])


XE, YE = olcekli(EGT)
XS, YS = olcekli(SIN)
TABAN = sum(y == 0.0 for y in YS) / len(YS)
AGAC, DOGRUSAL = 198 / len(SIN), 202 / len(SIN)     # M27/K03'un iki sayisi


def sikistir(z):
    if z >= 0:
        return 1.0 / (1.0 + math.exp(-z)) if z < 700 else 1.0
    e = math.exp(z) if z > -700 else 0.0
    return e / (1.0 + e)


def ilklendir(tohum, bicim, kazanc=1.0):    # kazanc olcekli; her satirin son sutunu YANMA
    r, kat = uretec(tohum), []
    for g, c in bicim:
        a = math.sqrt(6.0 * kazanc / g)
        kat.append([[(r() * 2 - 1) * a for _ in range(g)] + [0.0] for _ in range(c)])
    return kat


def sifir(kat):
    return [[[0.0] * len(w) for w in W] for W in kat]


def ileri(kat, x, etkin="dogrultulmus"):
    a, iz = x, []
    for i, W in enumerate(kat):
        iz.append(a)
        z = [sum(p * q for p, q in zip(w, a)) + w[-1] for w in W]
        if i == len(kat) - 1:
            a = [sikistir(z[0])]
        elif etkin == "sigmoit":
            a = [sikistir(t) for t in z]
        else:
            a = [t if t > 0 else 0.0 for t in z]
    iz.append(a)
    return iz


def egim(kat, X, Y, idx, etkin="dogrultulmus"):      # GERI YAYILIM
    G, kayip = sifir(kat), 0.0
    tur = (lambda v: v * (1 - v)) if etkin == "sigmoit" else (lambda v: v > 0)
    for i in idx:
        iz = ileri(kat, X[i], etkin)
        p = min(max(iz[-1][0], 1e-12), 1 - 1e-12)
        kayip -= Y[i] * math.log(p) + (1 - Y[i]) * math.log(1 - p)
        d = [p - Y[i]]
        for L in range(len(kat) - 1, -1, -1):
            W, a = kat[L], iz[L]
            for k, dk in enumerate(d):
                gk = G[L][k]
                for j, aj in enumerate(a):
                    gk[j] += dk * aj
                gk[-1] += dk
            if L:
                d = [sum(d[k] * W[k][j] for k in range(len(W))) * tur(a[j])
                     for j in range(len(a))]
    for W in G:
        for w in W:
            w[:] = [v / len(idx) for v in w]
    return G, kayip / len(idx)


def sira(tur):                              # toplu bolme sirasi her kosumda AYNI
    r, s = uretec(TOHUM + 500 + tur), list(range(len(XE)))
    for i in range(len(s) - 1, 0, -1):
        j = int(r() * (i + 1))
        s[i], s[j] = s[j], s[i]
    return s


def bicim(derin, gizli=8):                  # derin adet gizli katman, sonra tek cikti
    return [(len(ALAN), gizli)] + [(gizli, gizli)] * (derin - 1) + [(gizli, 1)]


print(f"egitim {len(EGT)} (756'dan kucultuldu), sinama {len(SIN)}, sutun {len(ALAN)}")
print("gizli katman ve parametre: " + ", ".join(
    f"{d} -> {sum(len(w) for W in ilklendir(TOHUM, bicim(d)) for w in W)}"
    for d in (1, 2, 3, 4, 6)))
print(f"taban {TABAN:.4f}; karsilastirma cizgileri dogrusal model {DOGRUSAL:.4f}, "
      f"karar agaci {AGAC:.4f}")
```

```
egitim 300 (756'dan kucultuldu), sinama 252, sutun 12
gizli katman ve parametre: 1 -> 113, 2 -> 185, 3 -> 257, 4 -> 329, 6 -> 473
taban 0.7579; karsilastirma cizgileri dogrusal model 0.8016, karar agaci 0.7857
```

#### Sönen ve Patlayan Eğimin Sayısı

Her derinlikte ağ ilklendirilir, tek bir toplu üzerinde eğim hesaplanır ve **ilk katmanın** eğim
büyüklüğü ile **son katmanınki** yan yana basılır. Son sütun, aynı ailedeki tek katmanlı ağa göre
ilk katmanın kaç katına indiğini verir.

```python
def buyukluk(W):                            # kareler ortalamasinin koku
    return math.sqrt(sum(v * v for w in W for v in w) / sum(len(w) for w in W))


print(f"{'etkinlestirme':>14} {'kazanc':>7} {'derinlik':>9} {'ilk katman':>12} "
      f"{'son katman':>12} {'son/ilk':>12} {'ilke gore':>10}")
ILK = {}
for etkin, kazanc in (("sigmoit", 1.0), ("dogrultulmus", 2.0), ("dogrultulmus", 16.0)):
    for derin in (1, 2, 4, 6):
        kat = ilklendir(TOHUM + 1, bicim(derin), kazanc)
        G, _ = egim(kat, XE, YE, range(60), etkin)
        b = [buyukluk(W) for W in G]
        ILK.setdefault((etkin, kazanc), b[0])
        print(f"{etkin:>14} {kazanc:>7} {derin:>9} {b[0]:>12.3e} {b[-1]:>12.3e} "
              f"{b[-1] / b[0]:>12.1f} {b[0] / ILK[(etkin, kazanc)]:>10.4f}")
```

```
 etkinlestirme  kazanc  derinlik   ilk katman   son katman      son/ilk  ilke gore
       sigmoit     1.0         1    1.274e-02    2.393e-01         18.8     1.0000
       sigmoit     1.0         2    2.820e-03    4.822e-02         17.1     0.2213
       sigmoit     1.0         4    1.930e-04    1.318e-01        682.6     0.0151
       sigmoit     1.0         6    5.539e-05    2.203e-01       3977.2     0.0043
  dogrultulmus     2.0         1    9.817e-02    5.694e-01          5.8     1.0000
  dogrultulmus     2.0         2    5.689e-02    2.176e-01          3.8     0.5796
  dogrultulmus     2.0         4    2.513e-02    5.219e-01         20.8     0.2560
  dogrultulmus     2.0         6    6.893e-02    3.273e-01          4.7     0.7022
  dogrultulmus    16.0         1    3.065e-01    1.707e+00          5.6     1.0000
  dogrultulmus    16.0         2    5.330e-01    2.059e+00          3.9     1.7387
  dogrultulmus    16.0         4    1.769e+00    3.761e+01         21.3     5.7719
  dogrultulmus    16.0         6    4.138e+01    1.813e+02          4.4   134.9930
```

İlk dört satır sönen eğimin sayısıdır. Doygun etkinleştirmeyle ilk katmanın gördüğü eğim
büyüklüğü tek katmanda 1,274e-02, altı katmanda 5,539e-05 — son sütuna göre **0,0043**, yani
**230 kat** aşağıda; son katmana oran ise 18,8'den 3977,2'ye çıkıyor. Altı katmanlı ağın son
katmanı tek katmanlı ağınkiyle aynı büyüklükte eğim görüyor, kaybolan yalnızca **girişe yakın
katmanların payıdır**. Bu ağ eğitilirse 473 parametrenin büyük bölümü ilklendirildiği yerde kalır.

Orta dört satırda aynı derinlikler doygunsuz etkinleştirmeyle ölçülüyor ve altı katmanda oran
**0,7022**; sönme neredeyse yok. Söndüren derinlik değil, **çarpanın büyüklüğüdür**. Son dört
satır ters uçtur: kazanç 16'ya çıkarıldığında çarpanlar birden büyük olur ve çarpım yukarı kaçar.
Altı katmanda ilk katmanın eğim büyüklüğü tek katmanlınınkinin **134,99 katıdır**. Sönen eğim
ağırlıkları dondurur, patlayan eğim onları tek bir güncellemede uçurur.

#### Kırpma ve Çizelge Neyi Düzeltiyor

Patlama yalnız ilklendirmeden gelmez; büyük bir öğrenme adımı da aynı sonucu üretir. Aşağıdaki
blok üç gizli katmanlı bir ağı önce güvenli bir adımla, sonra iki yüz kat büyük bir adımla
eğitiyor ve iki düzeltmeyi tek tek ve birlikte deniyor.

```python
def norm(G):                                # butun agin egim buyuklugu
    return math.sqrt(sum(v * v for W in G for w in W for v in w))


def olu(kat):                               # hicbir egitim satirinda etkinlesmeyen birim
    canli = [[False] * len(W) for W in kat[:-1]]
    for x in XE:
        iz = ileri(kat, x)
        for L in range(len(kat) - 1):
            for j, v in enumerate(iz[L + 1]):
                if v > 0:
                    canli[L][j] = True
    return sum(not c for W in canli for c in W)


def egit(adim, tohum, kirp=0.0, cizelge=False, derin=3, tur=30, toplu=20):
    kat, kirpma, ennorm, iz = ilklendir(tohum, bicim(derin), 2.0), 0, 0.0, []
    for t in range(tur):
        a = adim * 0.5 ** (t // 6) if cizelge else adim
        s, top = sira(t), 0.0
        for b in range(0, len(s), toplu):
            G, k = egim(kat, XE, YE, s[b:b + toplu])
            n = norm(G)
            ennorm = max(ennorm, n)
            if kirp and n > kirp:           # yon korunur, buyukluk esige cekilir
                kirpma += 1
                for W in G:
                    for w in W:
                        w[:] = [v * kirp / n for v in w]
            for W, gW in zip(kat, G):
                for w, g in zip(W, gW):
                    for j in range(len(w)):
                        w[j] -= a * g[j]
            top += k * toplu
        iz.append(top / len(s))
    return kat, iz[-1], kirpma, ennorm


AYAR = (("adim 0,05", 0.05, 0.0, False), ("adim 10 ciplak", 10.0, 0.0, False),
        ("adim 10 kirpma", 10.0, 0.10, False), ("adim 10 cizelge", 10.0, 0.0, True),
        ("adim 10 ikisi", 10.0, 0.10, True))
print(f"{'ayar':>16} {'kayip 2 kosum':>16} {'sinama 2 kosum':>16} {'olu':>7} "
      f"{'kirpilan':>9} {'en buyuk egim':>14}")
OZ = {}
for ad, adim, kirp, cz in AYAR:
    kk = [egit(adim, TOHUM + s, kirp, cz) for s in (1, 2)]
    OZ[ad] = [sum((ileri(k, x)[-1][0] > 0.5) == (y > 0.5)
                  for x, y in zip(XS, YS)) / len(XS) for k, _, _, _ in kk]
    print(f"{ad:>16} {kk[0][1]:>7.4f} {kk[1][1]:>8.4f} {OZ[ad][0]:>8.4f} {OZ[ad][1]:>7.4f} "
          f"{olu(kk[0][0]):>6}/24 {kk[0][2]:>5}/450 {kk[0][3]:>14.3e}")
print(f"\ntaban cizgisi {TABAN:.4f}, agin sayisi {OZ['adim 0,05'][0]:.4f}, "
      f"ayni agin ikinci kosumu {OZ['adim 0,05'][1]:.4f}")
for ad in ("adim 10 ciplak", "adim 10 kirpma", "adim 10 ikisi"):
    print(f"{ad:>16} kosum farki {abs(OZ[ad][0] - OZ[ad][1]):.4f} "
          f"({round(abs(OZ[ad][0] - OZ[ad][1]) * len(SIN))} abone)")
```

```
            ayar    kayip 2 kosum   sinama 2 kosum     olu  kirpilan  en buyuk egim
       adim 0,05  0.3666   0.3776   0.7817  0.7778      0/24     0/450      4.599e+00
  adim 10 ciplak  0.6210   0.6210   0.7579  0.7579     15/24     0/450      2.800e+07
  adim 10 kirpma  0.4333   0.3578   0.6984  0.6944      1/24   400/450      7.982e+00
 adim 10 cizelge  0.5287   0.5287   0.7579  0.7579     15/24     0/450      2.800e+07
   adim 10 ikisi  0.2722   0.2473   0.7698  0.7183      0/24   422/450      6.445e+00

taban cizgisi 0.7579, agin sayisi 0.7817, ayni agin ikinci kosumu 0.7778
  adim 10 ciplak kosum farki 0.0000 (0 abone)
  adim 10 kirpma kosum farki 0.0040 (1 abone)
   adim 10 ikisi kosum farki 0.0516 (13 abone)
```

İkinci satır patlamanın eğitim içindeki halidir. Eğim büyüklüğü bir noktada **2,800e+07**'ye
fırlıyor, o güncelleme ağırlıkları uçuruyor ve 24 birimin **15'i** bir daha hiçbir eğitim satırında
etkinleşmiyor. Sonuç iki koşumda da aynı: 0,7579, **tam olarak taban çizgisi**. Ağ artık herkese
"şüpheli değil" diyor. İki ilklendirmenin aynı sayıyı vermesi burada iyi haber değildir — ikisi de
aynı ölü noktaya düşmüştür.

Dördüncü satır çizelgenin tek başına ne yaptığını söylüyor: hiçbir şey. Adım altı turda bir
yarılanıyor ama patlama **ilk turda** oluyor. Bir çizelge, kendisinden önce gerçekleşmiş hasarı
geri almaz.

Üçüncü satırda eğim kırpma işini yapıyor: 450 güncellemenin 400'ü kırpılıyor, gördüğü en büyük
eğim 7,982'ye iniyor ve ölü birim 15'ten 1'e düşüyor. Ama sınama sayısı **0,6984**, tabanın
belirgin biçimde altında. Kırpma eğitimi kurtardı, modeli kurtarmadı. Beşinci satırda ikisi
birlikte kaybı tablonun en düşüğüne, 0,2722'ye indiriyor; sınama 0,7698'e çıkıyor ama ikinci
koşumda 0,7183'e düşüyor — **0,0516**, on üç abone. En geniş koşum açıklığı, en iyi görünen ayarda.

Üçlü şudur: taban çizgisi 0,7579, ağın sayısı 0,7817, ikinci koşum 0,7778. Güvenli adımdaki sığ
ayar kurtarılmış derin ayarların hepsinden yüksek ve hiçbiri doğrusal modelin 0,8016'sına
yaklaşmıyor.

#### Özet

- Doygun etkinleştirmeyle ilk katmanın eğim büyüklüğü altı katmanda tek katmanlının 0,0043 katına,
  yani 230 kat aşağı iniyor; son katmana oran 18,8'den 3977,2'ye çıkıyor.
- Doygunsuz etkinleştirmeyle aynı derinlikte oran 0,7022'de kalıyor; kazanç 16'da ise aynı ölçü
  134,99 kata çıkıp patlıyor. Söndüren derinlik değil, çarpanın büyüklüğüdür.
- Öğrenme adımı 10'da eğim büyüklüğü 2,800e+07'ye fırlıyor, 24 birimin 15'i ölüyor ve iki koşum
  da tam olarak taban çizgisini veriyor; çizelge tek başına bunu düzeltmiyor.
- Eğim kırpma 450 güncellemenin 400'ünü kırpıp ölü birimi 1'e indiriyor ama sınama 0,6984'e
  düşüyor; kırpma ile çizelge birlikte en düşük kaybı ve en geniş koşum açıklığını üretiyor.

#### Sonraki Adım

Bu iki derste ağ hep aynı yönde bozuldu: eğitim kaybı düştükçe ayrılmış küme sayısı düşme
eğilimindeydi. 300 satır ve birkaç yüz parametreyle bunun adı bellidir. Sonraki ders o adı bir
sayıya bağlar. Ağırlık cezası M27/K01 ve M27/K03'te ölçüldü ve tekrarlanmayacak; eklenecek olan
**ağa özgü** iki yöntemdir — eğitim sırasında birimlerin bir bölümünü rastgele susturan
**seyreltme** ve turu erkenden kesen **erken durdurma**. İkincisinde asıl soru yöntem değil
kaynaktır: durma turu **hangi kümeden** okunuyor.

### Düzenlileştirme

Source: https://academia.sh/tr/kurslar/derin-ogrenme/duzenlilestirme

Ağa özgü iki düzenlileştirme yönteminin katkısının ve erken durdurmanın hangi kümeden okunduğunun ölçülmesi: çıplak ağın eğitim ile sınama arasındaki açığı 0,0887 iken 0,4 oranlı seyreltmede 0,0330'a iner ve sınama 0,7579'dan 0,7937'ye çıkar; aynı ayarın ikinci koşumu 0,7738 verir ve orada çıplak ağ seyreltmeli ağı geçer. Ağırlık cezası M27/K01 ve M27/K03'te süpürülmüştü, burada tek katsayıyla uygulanır ve açığı 0,0702'ye indirir. Erken durdurmada doğrulama kaybı onuncu ve on dördüncü turda dibi görür; durma turu eğitimden okunursa sınama 0,7579 ve 0,7817, doğrulamadan okunursa 0,7698 ve 0,7976, sınamadan okunursa 0,7738 ve 0,8016 çıkar — sınamadan okumanın şişmesi iki koşumda da 0,0040, yani bir abonedir.

Önceki iki ders aynı yönü işaret etti: eğitim kaybı düştükçe ayrılmış küme sayısı düşme
eğilimindeydi. Bu, adı konmuş bir durumdur — 300 satırlık bir eğitim kümesine birkaç yüz parametre
düşünce ağ satırları ezberler. Aşırı uyumun kendisi M27/K01'in Genelleme konusunda ölçüldü ve
burada tekrarlanmaz. Burada sorulan şey daha dar: **ağa özgü** hangi karşı önlemler var ve her
biri kaç abone ediyor.

**Ağırlık cezası** bu soruya verilen ilk yanıt değildir ve bu kursta yeniden süpürülmez. M27/K01
`genelleme/04` ceza katsayısını 0,001'den 1000'e taşıyıp ağırlık büyüklüğünün 10,040'tan 0,601'e
indiğini, M27/K03 `dogrusal-modeller/03` ise karesel, mutlak ve karma cezanın seyreklikte
ayrıldığını ölçmüştü. Burada ceza **tek bir katsayıyla** ve yalnız karşılaştırma çizgisi olarak
kullanılır. Dersin eklediği iki yöntem şudur: **seyreltme** ve **erken durdurma**.

Terim ayrımı: bu kurstaki **seyreltme**, eğitim sırasında gizli birimlerin bir bölümünü geçici
olarak susturmaktır. M26/K06'nın Grafik konusundaki seyreltme bir çizim tekniğiydi ve nokta
sayısını azaltıyordu; ikisinin ortak yanı yalnız adıdır.

- **SA61.** Küme, bölme, tohum ve ölçek önceki derslerdeki gibidir; tablo **kurgudur**, eğitim
  kümesi **300 satıra küçültülmüştür** ve taban çizgisi sınamada **0,7579**.
- **SA62.** Ağ bu derste 16 gizli birimlidir ve 225 parametre taşır. Genişletildi, çünkü
  seyreltmenin kapatacağı birim olması gerekiyor.
- **SA63.** Eğitim 45 tur, toplu boyut 20, yalın iniş, öğrenme adımı 0,05'tir. Bu ayarlar
  aranmadı; önceki dersten geliyor.
- **SA64.** **Seyreltme** her küçük topluda yeniden çekilen bir maskeyle uygulanır: kapatılan
  birimin çıktısı sıfır, kalanların çıktısı $1/(1-p)$ ile büyütülür. Ölçek eğitimde uygulandığı
  için **çıkarımda hiçbir düzeltme gerekmez**; ağ eğitim dışında maskesiz çalışır.
- **SA65.** Maske küçük toplu başınadır, satır başına değil. Bu bir karardır ve maske sayısını
  45 çarpı 15, yani 675'te tutar.
- **SA66.** **Ağırlık cezası** katsayısı 0,01'dir ve eğime `ceza` çarpı ağırlık olarak eklenir.
  **Yanmalar cezalandırılmaz**: yanma karar sınırının konumunu taşır, eğriliğini değil.
- **SA67.** **Erken durdurma** ölçütü **doğrulama kaybıdır**, doğruluk değil; doğruluk 252 satırlık
  bir kümede 0,0040'lık basamaklarla ölçer ve dibi belirsiz kalır.
- **SA68.** Denenen ayar **5**'tir; bu bir arama değil, dört önlemin çıplak ağla yan yana
  konmasıdır. Karşılaştırma çizgileri M27/K03'ten gelir: doğrusal model **0,8016**, karar ağacı
  **0,7857**.

#### Ağa Özgü İki Yöntem

Kurulum önceki derslerdekiyle aynıdır; eklenen iki şey ileri geçişin bir **maske** alması ve geri
yayılımın eğime bir **ceza terimi** koyabilmesidir. Maskelenmiş bir birimin çıktısı sıfır olduğu
için eğimi de sıfırdır; kalan birimlerin eğimi maskedeki büyütme çarpanıyla ölçeklenir.

```python
# duzenlilestirme.py — MODELDIR. Ayni KURGU abone tablosu, ayni tohum, ayni bolme;
# egitim kumesi bu konuda 300 satira kucultulmustur.
import math
import statistics

TOHUM, HAM, M32 = 20260218, 1400, 0xFFFFFFFF
BOLGE = [("kuzey", 0.28, 21, 0.00), ("guney", 0.22, 17, -0.10),
         ("dogu", 0.18, 26, 0.30), ("bati", 0.14, 14, -0.05),
         ("merkez", 0.18, 23, 0.05)]


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


def ayrik(u, w):
    t = 0.0
    for i, x in enumerate(w):
        t += x
        if u < t:
            return i
    return len(w) - 1


VERI = []
for i in range(HAM):
    r = uretec(TOHUM + i)
    b = BOLGE[ayrik(r(), [x[1] for x in BOLGE])]
    hane = 1 + ayrik(r(), [0.06, 0.24, 0.30, 0.24, 0.11, 0.05])
    memnun = 1 + ayrik(r(), [0.08, 0.14, 0.27, 0.34, 0.17])
    if r() < 0.046:
        continue
    no = 10001 + i
    r, v = uretec(TOHUM + 7000 + no), []
    for d in range(ayrik(r(), [0.05, 0.12, 0.21, 0.62])):
        v.append(0.0 if r() < 0.038 else math.floor(
            b[2] * math.exp((r() + r() + r() - 1.5) * 0.62)
            * (1 - d * 0.05) * 100 + 0.5) / 100)
        r()
    if not v:
        continue
    ort, oyn, r = sum(v) / len(v), max(v) - min(v), uretec(TOHUM + 51000 + no)
    z = (0.052 * (ort - 20) + 0.85 * (min(v) == 0.0) + 0.026 * oyn + 0.24 * (hane >= 5)
         - 0.20 * (memnun >= 4) + b[3] + 0.9 * (no - 10001) / 1399
         + (r() + r() + r() - 1.5) * 1.30)
    x = {"hane": hane, "memnuniyet": memnun, "donem": len(v), "ort_tuketim": round(ort, 2),
         "oynaklik": round(oyn, 2), "sifir_okuma": int(min(v) == 0.0),
         "supheli": int(z > 1.35)}
    x["kisi_basi"] = round(x["ort_tuketim"] / x["hane"], 3)
    for q in BOLGE:
        x["b_" + q[0]] = int(b[0] == q[0])
    VERI.append(x)

r, S = uretec(TOHUM + 90000), list(range(len(VERI)))
for i in range(len(S) - 1, 0, -1):
    j = int(r() * (i + 1))
    S[i], S[j] = S[j], S[i]
K = [VERI[i] for i in S]
EGT, DOG, SIN = K[:300], K[756:1008], K[1008:]      # egitim 756'dan 300'e KUCULTULDU
ALAN = ["ort_tuketim", "oynaklik", "hane", "memnuniyet", "donem", "sifir_okuma",
        "kisi_basi", "b_kuzey", "b_guney", "b_dogu", "b_bati", "b_merkez"]
ORT = {a: statistics.fmean(x[a] for x in EGT) for a in ALAN}
SAP = {a: max(1e-9, statistics.pstdev([x[a] for x in EGT])) for a in ALAN}


def olcekli(s):                             # OGRENME egitimden, UYGULAMA her kumeye
    return ([[(x[a] - ORT[a]) / SAP[a] for a in ALAN] for x in s],
            [float(x["supheli"]) for x in s])


XE, YE = olcekli(EGT)
XD, YD = olcekli(DOG)
XS, YS = olcekli(SIN)
TABAN = sum(y == 0.0 for y in YS) / len(YS)
AGAC, DOGRUSAL = 198 / len(SIN), 202 / len(SIN)     # M27/K03'un iki sayisi


def sikistir(z):
    if z >= 0:
        return 1.0 / (1.0 + math.exp(-z)) if z < 700 else 1.0
    e = math.exp(z) if z > -700 else 0.0
    return e / (1.0 + e)


def ilklendir(tohum, bicim, kazanc=1.0):    # kazanc olcekli; her satirin son sutunu YANMA
    r, kat = uretec(tohum), []
    for g, c in bicim:
        a = math.sqrt(6.0 * kazanc / g)
        kat.append([[(r() * 2 - 1) * a for _ in range(g)] + [0.0] for _ in range(c)])
    return kat


def sifir(kat):
    return [[[0.0] * len(w) for w in W] for W in kat]


def maskele(kat, oran, tohum):              # SEYRELTME: kapatilan birim 0, kalan 1/(1-oran)
    r = uretec(tohum)
    return [[0.0 if r() < oran else 1.0 / (1.0 - oran) for _ in W] for W in kat[:-1]]


def ileri(kat, x, maske=None):
    a, iz = x, []
    for i, W in enumerate(kat):
        iz.append(a)
        z = [sum(p * q for p, q in zip(w, a)) + w[-1] for w in W]
        if i == len(kat) - 1:
            a = [sikistir(z[0])]
        else:
            a = [t if t > 0 else 0.0 for t in z]
            if maske:
                a = [v * m for v, m in zip(a, maske[i])]
    iz.append(a)
    return iz


def egim(kat, X, Y, idx, maske=None, ceza=0.0):      # GERI YAYILIM
    G, kayip = sifir(kat), 0.0
    for i in idx:
        iz = ileri(kat, X[i], maske)
        p = min(max(iz[-1][0], 1e-12), 1 - 1e-12)
        kayip -= Y[i] * math.log(p) + (1 - Y[i]) * math.log(1 - p)
        d = [p - Y[i]]
        for L in range(len(kat) - 1, -1, -1):
            W, a = kat[L], iz[L]
            for k, dk in enumerate(d):
                gk = G[L][k]
                for j, aj in enumerate(a):
                    gk[j] += dk * aj
                gk[-1] += dk
            if L:
                mk = maske[L - 1] if maske else None
                d = [sum(d[k] * W[k][j] for k in range(len(W)))
                     * (0.0 if a[j] <= 0 else (mk[j] if mk else 1.0))
                     for j in range(len(a))]
    for W in G:
        for w in W:
            w[:] = [v / len(idx) for v in w]
    if ceza:                                # AGIRLIK CEZASI: yanma cezalandirilmaz
        for W, gW in zip(kat, G):
            for w, g in zip(W, gW):
                for j in range(len(w) - 1):
                    g[j] += ceza * w[j]
    return G, kayip / len(idx)


def kayipla(kat, X, Y):
    t = 0.0
    for x, y in zip(X, Y):
        p = min(max(ileri(kat, x)[-1][0], 1e-12), 1 - 1e-12)
        t -= y * math.log(p) + (1 - y) * math.log(1 - p)
    return t / len(X)


def dogruluk(kat, X, Y):
    return sum((ileri(kat, x)[-1][0] > 0.5) == (y > 0.5) for x, y in zip(X, Y)) / len(X)


def sira(tur):                              # toplu bolme sirasi her kosumda AYNI
    r, s = uretec(TOHUM + 500 + tur), list(range(len(XE)))
    for i in range(len(s) - 1, 0, -1):
        j = int(r() * (i + 1))
        s[i], s[j] = s[j], s[i]
    return s


KAT0 = ilklendir(TOHUM + 1, [(len(ALAN), 16), (16, 1)])
print(f"ag {len(ALAN)}-16-1, parametre {sum(len(w) for W in KAT0 for w in W)}, "
      f"egitim {len(EGT)}, dogrulama {len(DOG)}, sinama {len(SIN)}, tur 45, toplu 20")
print(f"taban {TABAN:.4f}; karsilastirma cizgileri dogrusal model {DOGRUSAL:.4f}, "
      f"karar agaci {AGAC:.4f}")
```

```
ag 12-16-1, parametre 225, egitim 300, dogrulama 252, sinama 252, tur 45, toplu 20
taban 0.7579; karsilastirma cizgileri dogrusal model 0.8016, karar agaci 0.7857
```

#### Seyreltme ve Ağırlık Cezası

Eğitim döngüsü tek bir işlevdedir ve iki önlemi de anahtarla alır. Ölçü üç sütundur: eğitim
doğruluğu, sınama doğruluğu ve ikisi arasındaki **açık**. Açık aşırı uyumun doğrudan ölçüsüdür;
bir düzenlileştirme yöntemi çalışıyorsa önce açığı daraltır.

```python
def egit(tohum, oran=0.0, ceza=0.0, izle=False, adim=0.05, tur=45, toplu=20, gizli=16):
    kat, egri = ilklendir(tohum, [(len(ALAN), gizli), (gizli, 1)]), []
    for t in range(tur):
        s = sira(t)
        for bi, b in enumerate(range(0, len(s), toplu)):
            mk = maskele(kat, oran, TOHUM + 900 + t * 100 + bi) if oran else None
            G, _ = egim(kat, XE, YE, s[b:b + toplu], mk, ceza)
            for W, gW in zip(kat, G):
                for w, g in zip(W, gW):
                    for j in range(len(w)):
                        w[j] -= adim * g[j]
        if izle:                            # her turun sonunda ayrilmis kume okunur
            egri.append((kayipla(kat, XE, YE), kayipla(kat, XD, YD),
                         dogruluk(kat, XS, YS)))
    return kat, egri


AYAR = (("ciplak", 0.0, 0.0), ("seyreltme 0,2", 0.2, 0.0), ("seyreltme 0,4", 0.4, 0.0),
        ("agirlik cezasi", 0.0, 0.01), ("seyreltme 0,4 + ceza", 0.4, 0.01))
print(f"{'ayar':>21} {'egitim':>15} {'sinama':>15} {'acik':>7} {'kosum':>7}")
OZ = {}
for ad, oran, ceza in AYAR:
    kk = [egit(TOHUM + s, oran, ceza)[0] for s in (1, 2)]
    e = [dogruluk(k, XE, YE) for k in kk]
    OZ[ad] = [dogruluk(k, XS, YS) for k in kk]
    print(f"{ad:>21} {e[0]:>7.4f} {e[1]:>7.4f} {OZ[ad][0]:>7.4f} {OZ[ad][1]:>7.4f} "
          f"{e[0] - OZ[ad][0]:>7.4f} {abs(OZ[ad][0] - OZ[ad][1]):>7.4f}")
print(f"\ndenenen ayar {len(AYAR)}; taban {TABAN:.4f}, agin sayisi "
      f"{OZ['seyreltme 0,4'][0]:.4f}, ayni agin ikinci kosumu {OZ['seyreltme 0,4'][1]:.4f}")
print(f"karar agacini gecen kosum {sum(v > AGAC + 1e-9 for n in OZ.values() for v in n)}/10, "
      f"dogrusal modeli gecen {sum(v > DOGRUSAL + 1e-9 for n in OZ.values() for v in n)}/10")
```

```
                 ayar          egitim          sinama    acik   kosum
               ciplak  0.8467  0.8467  0.7579  0.7817  0.0887  0.0238
        seyreltme 0,2  0.8267  0.8300  0.7778  0.7937  0.0489  0.0159
        seyreltme 0,4  0.8267  0.8133  0.7937  0.7738  0.0330  0.0198
       agirlik cezasi  0.8400  0.8433  0.7698  0.7937  0.0702  0.0238
 seyreltme 0,4 + ceza  0.8233  0.8133  0.7897  0.7738  0.0337  0.0159

denenen ayar 5; taban 0.7579, agin sayisi 0.7937, ayni agin ikinci kosumu 0.7738
karar agacini gecen kosum 4/10, dogrusal modeli gecen 0/10
```

Açık sütunu düzenli davranıyor. Çıplak ağda eğitim ile sınama arasında **0,0887** var — yirmi iki
abone. Seyreltme oranı 0,2'de bu 0,0489'a, 0,4'te **0,0330**'a iniyor. Neredeyse üç katlık daralma
seyreltmenin işini yaptığını gösteriyor: her küçük toplu farklı birimlerle çalıştığı için hiçbir
birim tek bir eğitim satırını tek başına ezberleyemiyor. Ağırlık cezası aynı açığı yalnız 0,0702'ye
indiriyor; cezanın süpürülmediği bir ayarda bu beklenen bir sonuçtur ve süpürmenin ne kazandırdığı
M27/K01'de ölçülmüştür.

Sınama sütunu ilk koşumda açığı doğruluyor: 0,7579'dan 0,7937'ye, dokuz abone. Ama ikinci koşum
bunu onaylamıyor. Orada çıplak ağ 0,7817, seyreltmeli ağ 0,7738 veriyor — **sıralama tersine
dönüyor**. İlk koşuma bakan "seyreltme 0,4 çıplak ağı 0,0358 geçiyor" der, ikinci koşuma bakan
"0,0079 geriden geliyor" der. İkisi de aynı kodu çalıştırmıştır. Son satır kursun ikinci iddiasını
sürdürüyor: on koşumun dördü karar ağacını geçiyor, **hiçbiri** doğrusal modeli geçmiyor.

#### Erken Durdurma Hangi Kümeden Okunur

Erken durdurma bir ayar değil, bir **okuma noktasıdır**: eğitim kaç turda kesilecek. Asıl soru,
turun hangi kümeye bakılarak bulunduğudur. Aşağıdaki blok üç kaynağı yan yana koyuyor.

```python
for s in (1, 2):
    _, egri = egit(TOHUM + s, izle=True)
    dg = min(range(len(egri)), key=lambda t: egri[t][1])     # dogrulama kaybinin dibi
    sn = max(range(len(egri)), key=lambda t: egri[t][2])     # sinamanin tepesi
    print(f"kosum {s}: egitim kaybi 1. turda {egri[0][0]:.4f}, son turda {egri[-1][0]:.4f}; "
          f"dogrulama kaybi {egri[0][1]:.4f} -> {egri[-1][1]:.4f}")
    print(f"  durma turu egitimden okunursa 45: sinama {egri[-1][2]:.4f}")
    print(f"  durma turu dogrulamadan okunursa {dg + 1}: dogrulama kaybi "
          f"{egri[dg][1]:.4f}, sinama {egri[dg][2]:.4f}")
    print(f"  durma turu sinamadan okunursa {sn + 1}: sinama {egri[sn][2]:.4f}, "
          f"sisme {egri[sn][2] - egri[dg][2]:.4f} "
          f"({round((egri[sn][2] - egri[dg][2]) * len(SIN))} abone)")
```

```
kosum 1: egitim kaybi 1. turda 0.5183, son turda 0.3549; dogrulama kaybi 0.5244 -> 0.4505
  durma turu egitimden okunursa 45: sinama 0.7579
  durma turu dogrulamadan okunursa 10: dogrulama kaybi 0.4475, sinama 0.7698
  durma turu sinamadan okunursa 11: sinama 0.7738, sisme 0.0040 (1 abone)
kosum 2: egitim kaybi 1. turda 0.6826, son turda 0.3478; dogrulama kaybi 0.6677 -> 0.4244
  durma turu egitimden okunursa 45: sinama 0.7817
  durma turu dogrulamadan okunursa 14: dogrulama kaybi 0.4129, sinama 0.7976
  durma turu sinamadan okunursa 11: sinama 0.8016, sisme 0.0040 (1 abone)
```

İki kayıp eğrisi ayrışıyor. Eğitim kaybı kırk beş tur boyunca hiç yükselmiyor: birinci koşumda
0,5183'ten 0,3549'a iniyor. Doğrulama kaybı ise onuncu turda 0,4475 ile dibi görüp yukarı dönüyor
ve son turda 0,4505'e çıkıyor. Eğitim kümesine bakarak durma turu seçilemez, çünkü orada duracak
bir yer yoktur — eğrinin dibi hep son turdadır.

Doğrulama kümesinden okunan tur birinci koşumda 10, ikinci koşumda 14. Karşılıkları sınamada
0,7698 ve 0,7976; kırk beş tur koşulsaydı 0,7579 ve 0,7817 olurdu. Erken durdurmanın katkısı
birinci koşumda 0,0119, ikincisinde 0,0159 — yani üç ile dört abone. Birinci koşumda çıplak ağ
tam olarak taban çizgisine düşmüştü; erken durdurma onu tabanın üstüne çıkarıyor.

Son satırlar dersin asıl uyarısıdır. Sınama kümesine bakılarak seçilseydi tur her iki koşumda da
11 olurdu ve rapor edilen sayılar 0,7738 ile 0,8016 olurdu. Şişme **0,0040**, yani bir abone.
Küçüktür, ama ölçülmemiş bir kazançtır: sınama kümesi bir kez okunduğu anda ayrılmış olmaktan
çıkar. Aynı mantık M27/K02'nin boru hattı dersinde bir dönüşümün bütün kümeden öğrenilmesi için
kurulmuştu; erken durdurma turu da bir dönüşüm kadar bilgi taşır.

#### Özet

- Ağırlık cezası M27/K01 ve M27/K03'te süpürülmüştü; burada tek katsayıyla uygulanıyor ve eğitim
  ile sınama arasındaki açığı 0,0887'den 0,0702'ye indiriyor.
- Seyreltme aynı açığı 0,4 oranında 0,0330'a indiriyor; her küçük toplu farklı birimlerle
  çalıştığı için tek bir birim tek bir satırı ezberleyemiyor.
- Ölçeklendirme eğitimde yapıldığı için çıkarımda düzeltme gerekmez; ağ eğitim dışında maskesiz
  çalışır.
- Sınama sütunu ilk koşumda seyreltmeyi 0,0358 önde gösteriyor, ikinci koşumda 0,0079 geride;
  on koşumun dördü karar ağacını geçiyor, hiçbiri doğrusal modeli geçmiyor.
- Doğrulama kaybı 10. ve 14. turda dibi görüyor; durma turu doğrulamadan okunduğunda sınama
  0,7698 ve 0,7976, sınamadan okunduğunda 0,7738 ve 0,8016 çıkıyor — şişme her iki koşumda da
  0,0040, bir abone.

#### Sonraki Adım

Bu dersin iki yöntemi de ağın **çıktısına** dokunuyordu: biri birimleri susturuyor, öbürü
ağırlıkları küçültüyordu. Katmanların **girdisine** hiç dokunulmadı. Oysa girdi ölçekleme kurs
boyunca kullanılan tek hazırlık adımıydı ve yalnız **ilk** katmana uygulandı; ikinci katmanın
gördüğü sayılar eğitim ilerledikçe kayıyor ve kimse onları yerinde tutmuyor. Sonraki ders bunu bir
ölçüye bağlar: katman girdileri her topluda yeniden ölçeklendiğinde ağ, normalleştirmesiz kararsız
olan bir öğrenme adımında ne yapıyor. Aynı ders bir sızıntı kaynağı da açar, çünkü normalleştirme
eğitimde ve çıkarımda **aynı sayıyı kullanmaz**.

### Toplu Normalleştirme

Source: https://academia.sh/tr/kurslar/derin-ogrenme/toplu-normallestirme

Katman girdilerinin küçük toplu içinde ölçeklenmesinin izin verdiği öğrenme adımının ve bunun açtığı sızıntı kaynağının ölçülmesi: normalleştirmesiz ağ öğrenme adımı 20'de kaybı 8,6577'ye taşıyor, 60'ta 16 birimin 14'ünü öldürüp tam olarak taban çizgisini veriyor; normalleştirmeli ağ aynı adımlarda kaybı 0,7206 ve 2,3236'da tutuyor ve hiçbir adımda tek bir birim bile ölmüyor — kaybı 1,0'ın altında tutan en büyük adım 5'ten 20'ye, dört katına çıkıyor. Çıkarım koşum ortalamalarıyla yapıldığında sınama 0,7698, sınama toplusunun kendi istatistiğiyle yapıldığında 0,7937 çıkıyor; şişme 0,0238, yani altı abone. Yalnız sınama satırlarının sırası değiştirildiğinde aynı model 0,7817 veriyor, yedi abone sınıf değiştiriyor ve tek bir abonenin olasılığı 0,2273 oynuyor.

Önceki dersin iki yöntemi de ağın çıktısına dokunuyordu; katmanların **girdisine** hiç
dokunulmadı. Oysa ölçekleme bu kursun tek hazırlık adımıydı ve yalnız **ilk** katmana uygulandı:
on iki sütun eğitim kümesinden öğrenilen ortalama ve değişkenlikle ölçeklendi. Gizli katmanın
gördüğü sayıların böyle bir güvencesi yok; ağırlıklar her güncellemede değiştiği için ikinci
katmanın girdi ölçeği de kayıyor.

Toplu normalleştirme bu boşluğu doldurur: bir katmanın girdileri, **içinde bulunduğu küçük
toplunun** ortalaması ve değişkenliğiyle her adımda yeniden ölçeklenir. Bu dersin ölçüsü
normalleştirmenin **izin verdiği öğrenme adımıdır**. İkinci ölçü bedelidir: normalleştirme
eğitimde ve çıkarımda aynı sayıyı kullanmaz ve bu fark bir sızıntı kaynağıdır.

- **SA69.** Küme, bölme, tohum ve ölçek önceki derslerdeki gibidir; tablo **kurgudur**, eğitim
  kümesi **300 satıra küçültülmüştür** ve taban çizgisi sınamada **0,7579**.
- **SA70.** Ağ önceki dersteki gibi 12-16-1 ve 225 parametredir. Eğitim 30 tur, toplu boyut 20,
  yalın iniştir. Değişen tek şey öğrenme adımı ve normalleştirmenin olup olmadığıdır.
- **SA71.** Normalleştirme gizli katmanın **etkinleştirme öncesi** değerlerine uygulanır; öğrenilen
  ölçek ve kaydırma katsayıları **kullanılmaz**. Sıfıra bölünmemek için değişkenliğe $10^{-8}$
  eklenir ve bu eşik görünür basamakta hiçbir şeyi oynatmaz.
- **SA72.** Normalleştirmenin **kendi türevi** geri yayılıma yazılır: ortalama ve sapma toplunun
  bütün satırlarından geldiği için bir satırın eğimi öbür satırlara da bağlıdır.
- **SA73.** **Çıkarımda** toplu istatistiği yoktur; eğitim boyunca 0,9 katsayılı bir koşum
  ortalaması biriktirilir ve çıkarımda o kullanılır. Ölü birim önceki dersteki tanımdır.
- **SA74.** Denenen ayar **8**'dir: iki normalleştirme durumu çarpı dört öğrenme adımı. Bu bir
  arama değildir; adımlar kararlılık sınırını göstermek için seçilmiştir. Karşılaştırma çizgileri
  M27/K03'ten gelir: doğrusal model **0,8016**, karar ağacı **0,7857**.

#### Toplunun İçinde Ölçeklemek

Bu dersin kodu ileri geçişi ve geri yayılımı **satır satır değil toplu toplu** yazar, çünkü
normalleştirilecek istatistik toplunun tamamından gelir. Geri yayılımdaki normalleştirme türevi
bunun sonucudur: bir satırın eğimi, aynı toplunun öbür satırlarının değerlerini içerir.

```python
# normallestirme.py — MODELDIR. Ayni KURGU abone tablosu, ayni tohum, ayni bolme;
# egitim kumesi bu konuda 300 satira kucultulmustur.
import math
import statistics

TOHUM, HAM, M32 = 20260218, 1400, 0xFFFFFFFF
BOLGE = [("kuzey", 0.28, 21, 0.00), ("guney", 0.22, 17, -0.10),
         ("dogu", 0.18, 26, 0.30), ("bati", 0.14, 14, -0.05),
         ("merkez", 0.18, 23, 0.05)]


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


def ayrik(u, w):
    t = 0.0
    for i, x in enumerate(w):
        t += x
        if u < t:
            return i
    return len(w) - 1


VERI = []
for i in range(HAM):
    r = uretec(TOHUM + i)
    b = BOLGE[ayrik(r(), [x[1] for x in BOLGE])]
    hane = 1 + ayrik(r(), [0.06, 0.24, 0.30, 0.24, 0.11, 0.05])
    memnun = 1 + ayrik(r(), [0.08, 0.14, 0.27, 0.34, 0.17])
    if r() < 0.046:
        continue
    no = 10001 + i
    r, v = uretec(TOHUM + 7000 + no), []
    for d in range(ayrik(r(), [0.05, 0.12, 0.21, 0.62])):
        v.append(0.0 if r() < 0.038 else math.floor(
            b[2] * math.exp((r() + r() + r() - 1.5) * 0.62)
            * (1 - d * 0.05) * 100 + 0.5) / 100)
        r()
    if not v:
        continue
    ort, oyn, r = sum(v) / len(v), max(v) - min(v), uretec(TOHUM + 51000 + no)
    z = (0.052 * (ort - 20) + 0.85 * (min(v) == 0.0) + 0.026 * oyn + 0.24 * (hane >= 5)
         - 0.20 * (memnun >= 4) + b[3] + 0.9 * (no - 10001) / 1399
         + (r() + r() + r() - 1.5) * 1.30)
    x = {"hane": hane, "memnuniyet": memnun, "donem": len(v), "ort_tuketim": round(ort, 2),
         "oynaklik": round(oyn, 2), "sifir_okuma": int(min(v) == 0.0),
         "supheli": int(z > 1.35)}
    x["kisi_basi"] = round(x["ort_tuketim"] / x["hane"], 3)
    for q in BOLGE:
        x["b_" + q[0]] = int(b[0] == q[0])
    VERI.append(x)

r, S = uretec(TOHUM + 90000), list(range(len(VERI)))
for i in range(len(S) - 1, 0, -1):
    j = int(r() * (i + 1))
    S[i], S[j] = S[j], S[i]
K = [VERI[i] for i in S]
EGT, SIN = K[:300], K[1008:]                        # egitim 756'dan 300'e KUCULTULDU
ALAN = ["ort_tuketim", "oynaklik", "hane", "memnuniyet", "donem", "sifir_okuma",
        "kisi_basi", "b_kuzey", "b_guney", "b_dogu", "b_bati", "b_merkez"]
ORT = {a: statistics.fmean(x[a] for x in EGT) for a in ALAN}
SAP = {a: max(1e-9, statistics.pstdev([x[a] for x in EGT])) for a in ALAN}


def olcekli(s):                             # OGRENME egitimden, UYGULAMA her kumeye
    return ([[(x[a] - ORT[a]) / SAP[a] for a in ALAN] for x in s],
            [float(x["supheli"]) for x in s])


XE, YE = olcekli(EGT)
XS, YS = olcekli(SIN)
TABAN = sum(y == 0.0 for y in YS) / len(YS)
AGAC, DOGRUSAL = 198 / len(SIN), 202 / len(SIN)     # M27/K03'un iki sayisi


def sikistir(z):
    if z >= 0:
        return 1.0 / (1.0 + math.exp(-z)) if z < 700 else 1.0
    e = math.exp(z) if z > -700 else 0.0
    return e / (1.0 + e)


def ilklendir(tohum, bicim, kazanc=1.0):    # kazanc olcekli; her satirin son sutunu YANMA
    r, kat = uretec(tohum), []
    for g, c in bicim:
        a = math.sqrt(6.0 * kazanc / g)
        kat.append([[(r() * 2 - 1) * a for _ in range(g)] + [0.0] for _ in range(c)])
    return kat


def sira(tur):                              # toplu bolme sirasi her kosumda AYNI
    r, s = uretec(TOHUM + 500 + tur), list(range(len(XE)))
    for i in range(len(s) - 1, 0, -1):
        j = int(r() * (i + 1))
        s[i], s[j] = s[j], s[i]
    return s


def ileri_toplu(W1, W2, Xb, ist=None, norm=False):   # BIR KUCUK TOPLUNUN TAMAMI
    Z = [[sum(p * q for p, q in zip(w, x)) + w[-1] for w in W1] for x in Xb]
    mu = sd = None
    if norm:
        n, m = len(Z), len(W1)
        if ist is None:                     # EGITIM: toplunun kendi istatistigi
            mu = [sum(z[j] for z in Z) / n for j in range(m)]
            sd = [math.sqrt(sum((z[j] - mu[j]) ** 2 for z in Z) / n + 1e-8)
                  for j in range(m)]
        else:                               # CIKARIM: kosum ortalamalari
            mu, sd = ist
        Z = [[(z[j] - mu[j]) / sd[j] for j in range(m)] for z in Z]
    A = [[t if t > 0 else 0.0 for t in z] for z in Z]
    P = [sikistir(sum(p * q for p, q in zip(W2[0], a)) + W2[0][-1]) for a in A]
    return Z, mu, sd, A, P


def egim_toplu(W1, W2, Xb, Yb, norm=False):          # GERI YAYILIM
    Z, mu, sd, A, P = ileri_toplu(W1, W2, Xb, norm=norm)
    n, m, kayip = len(Xb), len(W1), 0.0
    g1 = [[0.0] * len(W1[0]) for _ in W1]
    g2 = [[0.0] * len(W2[0])]
    dZ = [[0.0] * m for _ in range(n)]
    for i in range(n):
        p = min(max(P[i], 1e-12), 1 - 1e-12)
        kayip -= Yb[i] * math.log(p) + (1 - Yb[i]) * math.log(1 - p)
        d = p - Yb[i]
        for j in range(m):
            g2[0][j] += d * A[i][j] / n
            dZ[i][j] = d * W2[0][j] * (Z[i][j] > 0)
        g2[0][-1] += d / n
    if norm:                                # normallestirmenin kendi turevi
        for j in range(m):
            s1 = sum(dZ[i][j] for i in range(n))
            s2 = sum(dZ[i][j] * Z[i][j] for i in range(n))
            for i in range(n):
                dZ[i][j] = (n * dZ[i][j] - s1 - Z[i][j] * s2) / (n * sd[j])
    for i in range(n):
        for j in range(m):
            if dZ[i][j]:
                for k, xk in enumerate(Xb[i]):
                    g1[j][k] += dZ[i][j] * xk / n
                g1[j][-1] += dZ[i][j] / n
    return g1, g2, kayip / n, mu, sd


def tahmin(W1, W2, X, ist=None, norm=False, toplu=0):
    if not toplu:
        return ileri_toplu(W1, W2, X, ist, norm)[4]
    return [p for b in range(0, len(X), toplu)
            for p in ileri_toplu(W1, W2, X[b:b + toplu], None, norm)[4]]


def dg(P, Y):
    return sum((p > 0.5) == (y > 0.5) for p, y in zip(P, Y)) / len(Y)


def olu(W1, W2, KM, KS, norm):              # hicbir egitim satirinda etkinlesmeyen birim
    A = ileri_toplu(W1, W2, XE, (KM, KS) if norm else None, norm)[3]
    return sum(all(a[j] <= 0 for a in A) for j in range(len(W1)))


W1, W2 = ilklendir(TOHUM + 1, [(len(ALAN), 16), (16, 1)])
print(f"ag {len(ALAN)}-16-1, parametre {sum(len(w) for w in W1 + W2)}, egitim {len(EGT)}, "
      f"sinama {len(SIN)}, tur 30, toplu 20")
print(f"taban {TABAN:.4f}; karsilastirma cizgileri dogrusal model {DOGRUSAL:.4f}, "
      f"karar agaci {AGAC:.4f}")
```

```
ag 12-16-1, parametre 225, egitim 300, sinama 252, tur 30, toplu 20
taban 0.7579; karsilastirma cizgileri dogrusal model 0.8016, karar agaci 0.7857
```

#### Normalleştirmenin İzin Verdiği Öğrenme Adımı

Eğitim döngüsü koşum ortalamalarını da biriktirir, çünkü çıkarımda toplu yoktur.

```python
def egit(tohum, adim, norm=False, tur=30, toplu=20, gizli=16):
    W1, W2 = ilklendir(tohum, [(len(ALAN), gizli), (gizli, 1)])
    KM, KS, iz = [0.0] * gizli, [1.0] * gizli, []
    for t in range(tur):
        s, top = sira(t), 0.0
        for b in range(0, len(s), toplu):
            i = s[b:b + toplu]
            g1, g2, k, mu, sd = egim_toplu(W1, W2, [XE[q] for q in i],
                                           [YE[q] for q in i], norm)
            for w, g in zip(W1, g1):
                for j in range(len(w)):
                    w[j] -= adim * g[j]
            for j in range(len(W2[0])):
                W2[0][j] -= adim * g2[0][j]
            if norm:                        # kosum ortalamalari cikarim icin biriktirilir
                KM = [0.9 * a + 0.1 * b for a, b in zip(KM, mu)]
                KS = [0.9 * a + 0.1 * b for a, b in zip(KS, sd)]
            top += k * len(i)
        iz.append(top / len(s))
    return W1, W2, KM, KS, iz[-1]


print(f"{'normallestirme':>15} {'adim':>6} {'kayip 2 kosum':>16} {'sinama 2 kosum':>16} "
      f"{'olu birim':>11}")
OZ = {}
for norm in (False, True):
    for adim in (0.05, 5.0, 20.0, 60.0):
        r = [egit(TOHUM + s, adim, norm) for s in (1, 2)]
        n = [dg(tahmin(a, b, XS, (c, d), norm), YS) for a, b, c, d, _ in r]
        OZ[(norm, adim)] = n
        print(f"{'var' if norm else 'yok':>15} {adim:>6} {r[0][4]:>7.4f} {r[1][4]:>8.4f} "
              f"{n[0]:>8.4f} {n[1]:>7.4f} {olu(*r[0][:4], norm):>7}/16 "
              f"{olu(*r[1][:4], norm):>2}/16")
print(f"\ndenenen ayar {len(OZ)}; taban {TABAN:.4f}, agin sayisi {OZ[(True, 0.05)][0]:.4f}, "
      f"ayni agin ikinci kosumu {OZ[(True, 0.05)][1]:.4f}")
```

```
 normallestirme   adim    kayip 2 kosum   sinama 2 kosum   olu birim
            yok   0.05  0.3740   0.3671   0.7659  0.7817       0/16  0/16
            yok    5.0  0.3841   0.3717   0.6905  0.5992       1/16  2/16
            yok   20.0  8.6577   8.1051   0.6270  0.6190       0/16  0/16
            yok   60.0  6.0788   6.0788   0.7579  0.7579      14/16 16/16
            var   0.05  0.4020   0.3922   0.7698  0.7857       0/16  0/16
            var    5.0  0.3809   0.4014   0.7381  0.7579       0/16  0/16
            var   20.0  0.7206   0.6698   0.6984  0.6865       0/16  0/16
            var   60.0  2.3236   1.9163   0.6429  0.6587       0/16  0/16

denenen ayar 8; taban 0.7579, agin sayisi 0.7698, ayni agin ikinci kosumu 0.7857
```

Kayıp sütunu dersin başlığındaki sayıyı veriyor. Normalleştirmesiz ağ 5'te hâlâ ayakta, 20'de kayıp
8,6577'ye çıkıyor; normalleştirmeli ağ aynı 20'de 0,7206'da kalıyor ve 60'ta bile 2,3236'yı aşmıyor.
Kaybı 1,0'ın altında tutan en büyük adım normalleştirmesiz **5**, normalleştirmeli **20**: **dört
kat**. Normalleştirmenin izin verdiği şey budur.

Ölü birim sütunu farkı daha keskin gösteriyor. Normalleştirmesiz ağ 60'ta 16 birimin 14'ünü, ikinci
koşumda **hepsini** kaybediyor ve iki koşum da tam olarak taban çizgisini veriyor. Normalleştirmeli
ağ hiçbir adımda **tek bir birim bile** kaybetmiyor: girdinin her adımda yeniden ölçeklenmesi,
etkinleştirme öncesi değerlerin kalıcı olarak sıfırın altına itilmesini engelliyor.

Sınama sütunu bir uyarı taşıyor: normalleştirme büyük adımı **mümkün** kılıyor ama **işe yarar**
kılmıyor, çünkü en yüksek sayı iki ailede de en küçük adımdadır. Üçlü şudur — taban 0,7579, ağın
sayısı 0,7698, aynı ağın ikinci koşumu **0,7857**; ikincisi birincisinden 0,0159 yüksek ve tam
olarak karar ağacının sayısına oturuyor.

#### Eğitimde Başka, Çıkarımda Başka

Normalleştirmenin bedeli **davranışın ikiye ayrılmasıdır**. Eğitimde bir satırın çıktısı yanındaki
on dokuz satıra bağlıdır; çıkarımda olmamalıdır. Aşağıdaki blok çıkarımı üç yoldan yapıyor.

```python
W1, W2, KM, KS, _ = egit(TOHUM + 1, 0.05, True)
PA = tahmin(W1, W2, XS, (KM, KS), True)                 # dogru yol: kosum ortalamalari
PB = tahmin(W1, W2, XS, norm=True, toplu=20)            # toplunun kendi istatistigi
r, S2 = uretec(TOHUM + 4242), list(range(len(XS)))
for i in range(len(S2) - 1, 0, -1):
    j = int(r() * (i + 1))
    S2[i], S2[j] = S2[j], S2[i]
PC = [0.0] * len(XS)
for k, i in enumerate(tahmin(W1, W2, [XS[q] for q in S2], norm=True, toplu=20)):
    PC[S2[k]] = i
print(f"cikarim kosum ortalamalariyla     {dg(PA, YS):.4f}")
print(f"cikarim toplunun istatistigiyle   {dg(PB, YS):.4f}  "
      f"sisme {dg(PB, YS) - dg(PA, YS):.4f} "
      f"({round((dg(PB, YS) - dg(PA, YS)) * len(SIN))} abone)")
print(f"ayni yol, sinama sirasi degisik    {dg(PC, YS):.4f}")
print(f"sinif degistiren abone: kosum ort. ile toplu ist. arasinda "
      f"{sum((a > 0.5) != (b > 0.5) for a, b in zip(PA, PB))}, "
      f"yalniz sira degisince {sum((a > 0.5) != (b > 0.5) for a, b in zip(PB, PC))}")
print(f"tek bir abonenin olasiligindaki en buyuk oynama "
      f"{max(abs(a - b) for a, b in zip(PB, PC)):.4f}")
```

```
cikarim kosum ortalamalariyla     0.7698
cikarim toplunun istatistigiyle   0.7937  sisme 0.0238 (6 abone)
ayni yol, sinama sirasi degisik    0.7817
sinif degistiren abone: kosum ort. ile toplu ist. arasinda 6, yalniz sira degisince 7
tek bir abonenin olasiligindaki en buyuk oynama 0.2273
```

İkinci satır ilk bakışta iyi haber gibi duruyor: 0,7698 yerine 0,7937, altı abone daha doğru. Ama
o altı abone öğrenmeden gelmiyor. Sınama toplusunun ortalaması sınama satırlarının kendisinden
hesaplandı; her abonenin tahmini, aynı topludaki öbür on dokuz abonenin sayılarını içeriyor.

Üçüncü satır bunu kanıtlıyor. Model aynı, ağırlıklar aynı, sınama kümesi aynı — yalnız satırların
**sırası** değişti ve sayı 0,7937'den 0,7817'ye indi. Yedi abone sınıf değiştirdi, bir abonenin
olasılığı **0,2273** oynadı. Bir modelin tahmini tahmin edilen kişiden başka kimseye bağlı
olmamalıdır; burada bağlı. M27/K02'nin boru hattı dersi bir dönüşümün bütün kümeden öğrenilmesinin
0,0397 ile 0,0476 arasında şişme ürettiğini ölçmüştü; toplu normalleştirme aynı hatayı
**sessizce** yapılabilir kılar. Doğru yol tektir: çıkarımda koşum ortalamaları.

#### Özet

- Toplu normalleştirme katmanın etkinleştirme öncesi değerlerini içinde bulunduğu küçük toplunun
  ortalaması ve değişkenliğiyle ölçekler; türevi de toplunun tamamından gelir.
- Kaybı 1,0'ın altında tutan en büyük öğrenme adımı normalleştirmesiz 5, normalleştirmeli 20'dir —
  dört kat. Normalleştirmesiz ağ 20'de kaybı 8,6577'ye taşıyor.
- Adım 60'ta normalleştirmesiz ağın 16 biriminin 14'ü, ikinci koşumda hepsi ölüyor ve sonuç tam
  olarak taban çizgisi oluyor; normalleştirmeli ağda hiçbir adımda birim ölmüyor.
- Büyük adım mümkün oluyor ama işe yaramıyor: en yüksek sınama sayısı iki ailede de en küçük
  adımdadır. Üçlü taban 0,7579, ağın sayısı 0,7698, ikinci koşum 0,7857'dir.
- Çıkarım toplunun kendi istatistiğiyle yapılırsa sayı 0,7937'ye şişiyor; yalnız sınama sırası
  değişince 0,7817'ye iniyor ve bir olasılık 0,2273 oynuyor.

#### Sonraki Adım

Dokuz ders bir ağı parça parça kurdu: doğrusal olmayan ayrım, etkinleştirme, ileri geçiş, kayıp,
geri yayılım, eniyileyici, kararlılık, düzenlileştirme ve normalleştirme. Her derste üç sayı yan
yana durdu ve üçüncüsü — aynı ağın ikinci koşumu — hiçbir yerde birinciyle aynı çıkmadı. Kursun
kuralı son dört derste doğrulandı: her derste kapasite sabit tutulup yalnız bir ayar
değiştirildi ve eniyileyici, öğrenme adımı, seyreltme ile normalleştirme sayıyı 0,5992 ile
0,7937 arasında gezdirdi. Kursun ikinci iddiası da
sürüyor: hiçbir koşum doğrusal modelin 0,8016'sını geçmedi.

Bu ağın dokuz derste hiç değişmeyen bir yanı var. Her girdi sütunu her gizli birime bağlandı ve her
bağlantı kendi ağırlığını taşıdı — ağ **tam bağlı** kaldı. Bu, girdi sütunlarının birbiriyle
hiçbir ilişkisi yokmuş gibi davranmaktır: sütunların sırası karıştırılsa ağ aynı sonucu verirdi.
Oysa gerçek girdilerin çoğunda **yapı** vardır; bir sayaç okuma dizisinde komşu dönemler, bir
kapsama ızgarasında komşu hücreler komşudur. Sonraki konu bu yapıyı ağın kendisine yazar ve ilk
soruyu bir parametre sayısıyla sorar: aynı işi tam bağlı bir katman kaç ağırlıkla, komşuluğu bilen
bir katman kaç ağırlıkla yapıyor.

## Görüntü ve Dizi Mimarileri

Girdinin yapısını kullanan mimarilerin ne kattığının ve neyi hâlâ kaçırdığının sayılması: evrişimin aynı işi tam bağlı katmana göre kaç ağırlıkla yapması, havuzlamanın attığı bilgi ile kaydırmaya dayanıklılık, derinlik arttıkça eğimin ilk katmana ulaşması ve atlamalı bağlantının bunu düzeltmesi, gizli durumun dizi uzadıkça taşıyabildiği bilgi, kapı birimlerinin kaç adım geriye bağımlılık taşıdığı, dikkat ağırlıklarının kaçının doğru adıma gitmesi ve yüksek ağırlığın açıklama olmaması, baş sayısının kattığı fark ile konum kodlaması çıkarıldığında kaybolan sıra bilgisi, öğrenilen gömme ile öğrenilmeyen izdüşümün farkı, aktarımın kaç örnekle kattığı ve dondurma ile ince ayarın ayrımı, geri kurma hatası ile çekişmeli düzenin iki koşum arasındaki kararsızlığı.

### Evrişim İşlemi

Source: https://academia.sh/tr/kurslar/derin-ogrenme/evrisim-islemi

Girdinin yapısını kullanan ilk katmanın kaç ağırlıkla çalıştığının sayılması: aynı 144 çıktıyı üreten tam bağlı katman 20.880 sayı tutarken 3x3 evrişim çekirdeği 10 sayı tutuyor, oran 2.088 kat. Elle yazılmış iki çekirdek dolgusuz 0,8900, dolgu 1 ile 0,9380 uyuşma veriyor ve aradaki fark tümüyle kenar hücrelerdir. Sınamada en sık sınıf 0,5850 iken 1.169 parametreli tam bağlı ağ eğitim kümesini tamamen ezberleyip 0,5100 ve 0,5350 veriyor, 23 parametreli evrişimli ağ ise 0,8000 ve 0,8150 veriyor: iki koşum arasındaki fark tam bağlı ağda 0,0250, evrişimli ağda 0,0150.

Dokuz derste ağ **tam bağlı** kaldı: her girdi sütunu her birime kendi ağırlığıyla bağlandı. Böyle
bir katmanda sütunların sırası hiçbir şey ifade etmez; sütunlar karıştırılsa ağın öğrendiği şey
değişmez, yalnız ağırlıkların yeri değişir. Abone tablosunda bu bir kayıp değildir, çünkü hane
sayısı ile ortalama tüketim arasında bir komşuluk yoktur.

Girdi bir **ızgara** olduğunda durum değişir. Aranan şey tek bir hücrede değil, birkaç bitişik
hücrenin oluşturduğu düzendedir. Tam bağlı katman bunu kullanmaz: her hücre için ayrı bir ağırlık
öğrenir ve aynı düzen başka bir yerde göründüğünde onu yeniden öğrenmek zorunda kalır. Bu dersin
ölçüsü budur — aynı işi tam bağlı katman kaç ağırlıkla, evrişim kaç ağırlıkla yapıyor.

- **MI1. Kapsama ızgarası kurgudur.** M26/K06'da bölgeler 12x12'lik bir hücre ızgarasına
  bölünmüştü; burada aynı ızgara bir öğrenme girdisine çevrilir. Her hücre bir kapsama birimidir
  ve değeri, o birimde eşik üstü okuma bulunup bulunmadığıdır. Tohum 20260218.
- **MI2. Etiket de kurgudur ve yapısaldır.** Bir ızgara, içine **bitişik üç hücrelik bir hat**
  ekilmişse 1 etiketlidir. Hat, bir hattın boyunca ilerleyen kaçak izinin karşılığıdır; dağınık
  tekil hücreler ise gürültüdür.
- **MI3. Etiket ızgaradan tam olarak okunamaz.** Hücrelerin yaklaşık yüzde 9'u kendiliğinden
  etkindir; hat ekilmemiş bazı ızgaralarda da rastlantıyla üç hücrelik bir dizilim oluşur.
- **MI4. Bölme 200/100/200'dür** ve bu ızgara kümesinde sabittir. Eğitim kümesi bilerek
  **küçültülmüştür**; ölçek küçük tutulur.
- **MI5. Taban çizgisi ızgara kümesinden okunur.** Sınamada en sık sınıfı söylemek 0,5850 verir.
  M27/K01–K03'ün 0,7579'u **abone tablosuna** aittir ve bu kümeyle karşılaştırılamaz.
- **MI6. Çekirdek**, ızgara üzerinde kaydırılan küçük bir ağırlık dizeyidir; **adım** iki komşu
  konum arasındaki kayma, **dolgu** kenara eklenen sıfır çerçevesinin kalınlığıdır.
- **MI7. Ağırlık paylaşımı** evrişimin tanımıdır: aynı çekirdek bütün konumlarda kullanılır. Bu,
  parametre sayısını konum sayısından bağımsız kılar.
- **MI8. Kütüphane çağrılmaz;** evrişim ve eğitim döngüsü ders içinde yazılır ve **modeldir**.
- **MI9. Her ağ iki kez koşulur.** İkinci koşumda yalnız başlangıç değerleri değişir; veri, bölme,
  tur sayısı ve öğrenme adımı aynıdır.

#### Kapsama Izgarası ve Parametre Sayısı

```python
# izgara.py — MODELDIR. Kapsama izgarasi KURGUDUR: M26/K06'nin 12x12'lik
# kapsama izgarasi burada bir ogrenme girdisine cevrilir. Her hucre bir
# kapsama birimidir ve degeri, o birimde esik ustu okuma olup olmadigidir.
import math

TOHUM, M32, BOY = 20260218, 0xFFFFFFFF, 12
YOGUNLUK, IZ_ORANI, KOSU = 0.09, 0.42, 3


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


def izgara(no):
    """Bir abonenin kapsama izgarasi. Etiket: sizinti izi ekilmis mi."""
    r = uretec(TOHUM + 300000 + no)
    g = [[1 if r() < YOGUNLUK else 0 for _ in range(BOY)] for _ in range(BOY)]
    iz = 1 if r() < IZ_ORANI else 0
    if iz:                                   # bitisik uc hucrelik bir hat
        yatay, a, b = r() < 0.5, int(r() * BOY), int(r() * (BOY - KOSU + 1))
        for k in range(KOSU):
            if yatay:
                g[a][b + k] = 1
            else:
                g[b + k][a] = 1
    return g, iz


def karistir(n, tohum):
    r, s = uretec(tohum), list(range(n))
    for i in range(n - 1, 0, -1):
        j = int(r() * (i + 1))
        s[i], s[j] = s[j], s[i]
    return s


HAM = [izgara(i) for i in range(500)]
VERI = [HAM[i] for i in karistir(500, TOHUM + 90000)]
EGT, DOG, SIN = VERI[:200], VERI[200:300], VERI[300:]
TABAN = max(sum(e for _, e in SIN), len(SIN) - sum(e for _, e in SIN)) / len(SIN)

ornek = next(g for g, e in VERI if e == 1 and any(
    all(g[i][j + k] for k in range(KOSU))
    for i in range(BOY) for j in range(BOY - KOSU + 1)))
print("yatay hat ekilmis bir izgara (1 = esik ustu okuma), etiket 1:")
for satir in ornek:
    print("   " + "".join("#" if x else "." for x in satir))
print(f"izgara {BOY}x{BOY} = {BOY * BOY} hucre, ortalama etkin hucre "
      f"{sum(sum(sum(s) for s in g) for g, _ in VERI) / len(VERI):.2f}")
print(f"bolme {len(EGT)}/{len(DOG)}/{len(SIN)}, sinamada en sik sinif "
      f"{TABAN:.4f}")

TB_H = 8
tb_par = BOY * BOY * TB_H + TB_H + TB_H + 1
tam_katman = (BOY * BOY) ** 2 + BOY * BOY
print(f"\n{'katman':<34}{'agirlik':>9}{'yanma':>7}{'toplam':>9}")
print(f"{'tam bagli 144 -> 144':<34}{(BOY * BOY) ** 2:>9}{BOY * BOY:>7}"
      f"{tam_katman:>9}")
print(f"{'evrisim 3x3, tek cekirdek':<34}{9:>9}{1:>7}{10:>9}")
print(f"ayni cikti boyutu icin oran {tam_katman / 10:.0f} kat")
```

```
yatay hat ekilmis bir izgara (1 = esik ustu okuma), etiket 1:
   #..#........
   ....#.......
   ..#...#.....
   ............
   #.#.........
   .....#..#...
   #....#.....#
   .####....##.
   .......##...
   ..........#.
   ..........#.
   ............
izgara 12x12 = 144 hucre, ortalama etkin hucre 13.96
bolme 200/100/200, sinamada en sik sinif 0.5850

katman                              agirlik  yanma   toplam
tam bagli 144 -> 144                  20736    144    20880
evrisim 3x3, tek cekirdek                 9      1       10
ayni cikti boyutu icin oran 2088 kat
```

Örnek ızgarada sekizinci satırdaki dört bitişik hücrenin üçü ekilmiş hattır, dördüncüsü
rastlantıyla yanına düşmüş bir gürültü hücresidir. Geri kalan etkin hücreler dağınıktır.

Alt tablo dersin sayısıdır. Her hücre için bir çıktı üreten tam bağlı katman **20.880** sayı tutar.
Aynı çıktı boyutunu üreten tek bir 3x3 çekirdek **10** sayı tutar: dokuz ağırlık ve bir yanma.
Oran **2.088 kat**tır.

Fark bir eniyileme numarası değil, bir **varsayımdır**. Tam bağlı katman "her konumun kendi kuralı
olabilir" der ve 144 ayrı kural için yer ayırır; evrişim "aranan düzen nerede olursa olsun aynı
düzendir" der ve tek bir kural öğrenir. Varsayım yanlışsa evrişim öğrenemez. Bu ızgarada doğrudur,
çünkü hat herhangi bir yere ekilir.

#### Çekirdek, Adım ve Dolgu

```python
# evrisim.py — evrisim islemi elle yazilir: cekirdek izgara uzerinde kaydirilir
# ve her konumda ayni agirliklar kullanilir. Girdi ikili oldugu icin dongu
# yalniz etkin hucrelerden yurur; hesaplanan sayi degismez, kosum kisalir.
def etkinler(g):
    return [(i, j) for i in range(BOY) for j in range(BOY) if g[i][j]]


def evris(ak, K, yanma, adim=1, dolgu=0):
    c = len(K)
    n = (BOY + 2 * dolgu - c) // adim + 1
    cikti = [[yanma] * n for _ in range(n)]
    for (i, j) in ak:
        for di in range(c):
            for dj in range(c):
                p, q = i + dolgu - di, j + dolgu - dj
                if p % adim == 0 and q % adim == 0 and 0 <= p // adim < n \
                        and 0 <= q // adim < n and p >= 0 and q >= 0:
                    cikti[p // adim][q // adim] += K[di][dj]
    return cikti


YATAY = [[0, 0, 0], [1, 1, 1], [0, 0, 0]]
DIKEY = [[0, 1, 0], [0, 1, 0], [0, 1, 0]]


def ates(g, dolgu):
    ak = etkinler(g)
    return (max(max(r) for r in evris(ak, YATAY, -2.5, 1, dolgu)) > 0
            or max(max(r) for r in evris(ak, DIKEY, -2.5, 1, dolgu)) > 0)


print("yatay cekirdek ciktisi (+ = hat bulundu), dolgu 1, 12x12:")
for satir in evris(etkinler(ornek), YATAY, -2.5, 1, 1):
    print("   " + "".join("+" if v > 0 else "." for v in satir))
for dolgu in (0, 1):
    u = sum(1 for g, e in VERI if ates(g, dolgu) == (e == 1))
    print(f"elle yazilmis iki cekirdek, dolgu {dolgu}: etiketle uyusma "
          f"{u / len(VERI):.4f}")

print(f"\n{'adim':>5}{'dolgu':>6}{'cikti':>8}{'agirlik':>9}{'carpma':>9}"
      f"{'tam bagli carpma':>18}")
for adim, dolgu in ((1, 0), (1, 1), (2, 0), (2, 1), (3, 1)):
    n = (BOY + 2 * dolgu - 3) // adim + 1
    print(f"{adim:>5}{dolgu:>6}{f'{n}x{n}':>8}{10:>9}{n * n * 9:>9}"
          f"{n * n * BOY * BOY:>18}")
```

```
yatay cekirdek ciktisi (+ = hat bulundu), dolgu 1, 12x12:
   ............
   ............
   ............
   ............
   ............
   ............
   ............
   ..++........
   ............
   ............
   ............
   ............
elle yazilmis iki cekirdek, dolgu 0: etiketle uyusma 0.8900
elle yazilmis iki cekirdek, dolgu 1: etiketle uyusma 0.9380

 adim dolgu   cikti  agirlik   carpma  tam bagli carpma
    1     0   10x10       10      900             14400
    1     1   12x12       10     1296             20736
    2     0     5x5       10      225              3600
    2     1     6x6       10      324              5184
    3     1     4x4       10      144              2304
```

Çekirdek elle yazıldığında ne yaptığı görünür olur. Yatay çekirdek üç bitişik hücrenin toplamını
alır ve $-2,5$ yanmasıyla ancak üçü birden etkinse pozitif değer üretir; örnek ızgarada yedinci
satırın iki konumunda ateş ediyor, çünkü orada dört bitişik hücre var. Bu iki çekirdek hiç
eğitilmeden bütün kümede **0,9380** uyuşma veriyor.

İki uyuşma sayısı arasındaki fark **dolgunun** tek başına ölçüsüdür. Dolgusuz çalışıldığında
çekirdeğin merkezi ilk ve son satıra oturamaz, kenardaki hatlar görülmez ve uyuşma 0,8900'e
düşer. Bir sıra sıfır eklemek farkı **0,0480** kapatır; dolgu bir ayar kolaylığı değil, kenardaki
bilgiyi görüp görmeme kararıdır.

Alttaki tablo çıktı boyutunun $n = \lfloor (12 + 2d - c)/s \rfloor + 1$ bağıntısıyla adım $s$,
dolgu $d$ ve çekirdek boyu $c$ değerlerinden çıktığını gösteriyor. Dikkat edilecek sütun
**ağırlık** sütunudur: adım ve dolgu ne olursa olsun 10'dur. Adım yalnız **çarpma** sayısını
değiştirir — 1.296'dan 144'e. Tam bağlı katman her satırda on altı kat daha fazla çarpma yapar ve
o çarpmaların her birinin ayrı bir ağırlığı vardır.

#### İki Ağ Yan Yana

Parametre sayısı bir vaattir; ayrılmış küme sayısı onun ne ettiğidir. İki ağ aynı veride, aynı
bütçeyle eğitilir; tek fark ilk katmanın biçimidir.

```python
# egit.py — MODELDIR: iki ag ayni veride, ayni tur butcesinde egitilir.
# Cikis sigmoit, kayip capraz duzensizlik, guncelleme ornek basina.
DOLGU, N = 1, BOY + 2 * 1 - 3 + 1
EGT_E = [(etkinler(g), e) for g, e in EGT]
SIN_E = [(etkinler(g), e) for g, e in SIN]


def sig(z):
    return 1 / (1 + math.exp(-z)) if z > -30 else 0.0


def tam_bagli(H, tohum):                     # 144 -> H -> 1
    r, a = uretec(tohum), (1 / (BOY * BOY)) ** 0.5
    return [[[(r() * 2 - 1) * a for _ in range(BOY * BOY)] for _ in range(H)],
            [0.0] * H, [(r() * 2 - 1) * (1 / H) ** 0.5 for _ in range(H)], [0.0]]


def tb_ileri(P, ak):
    W, b, v, c = P
    h = [max(0.0, b[k] + sum(W[k][i * BOY + j] for (i, j) in ak))
         for k in range(len(b))]
    return h, sig(c[0] + sum(v[k] * h[k] for k in range(len(h))))


def evrisimli(sayi, tohum):                  # sayi cekirdek -> en buyuk -> 1
    r, a = uretec(tohum), (1 / 9) ** 0.5
    return [[[[(r() * 2 - 1) * a for _ in range(3)] for _ in range(3)]
             for _ in range(sayi)], [0.0] * sayi,
            [(r() * 2 - 1) * (1 / sayi) ** 0.5 for _ in range(sayi)], [0.0]]


def ev_ileri(P, ak):
    Ks, b, v, c = P
    h, arg = [], []
    for k, K in enumerate(Ks):
        m = evris(ak, K, b[k], 1, DOLGU)
        en, ep, eq = m[0][0], 0, 0
        for p in range(N):
            for q in range(N):
                if m[p][q] > en:
                    en, ep, eq = m[p][q], p, q
        h.append(max(0.0, en))
        arg.append((ep, eq))
    return (h, arg), sig(c[0] + sum(v[k] * h[k] for k in range(len(h))))


def egit(P, ileri, veri, tur, gadim, tohum, evrisim):
    r, n = uretec(tohum), len(veri)
    W, b, v, c = P
    for _ in range(tur):
        s = list(range(n))
        for i in range(n - 1, 0, -1):
            j = int(r() * (i + 1))
            s[i], s[j] = s[j], s[i]
        for idx in s:
            ak, y = veri[idx]
            ic, p = ileri(P, ak)
            h = ic[0] if evrisim else ic
            d = p - y
            for k in range(len(b)):
                if h[k] > 0.0:
                    dh = d * v[k]
                    b[k] -= gadim * dh
                    if evrisim:
                        ep, eq = ic[1][k]
                        for (i, j) in ak:
                            di, dj = i + DOLGU - ep, j + DOLGU - eq
                            if 0 <= di < 3 and 0 <= dj < 3:
                                W[k][di][dj] -= gadim * dh
                    else:
                        for (i, j) in ak:
                            W[k][i * BOY + j] -= gadim * dh
                v[k] -= gadim * d * h[k]
            c[0] -= gadim * d
    return P


def dogruluk(P, ileri, veri, evrisim):
    return sum(1 for ak, y in veri
               if (ileri(P, ak)[1] >= 0.5) == (y == 1)) / len(veri)


ev_par = 2 * (9 + 1) + 2 + 1
print(f"{'ag':<22}{'parametre':>10}{'kosum':>7}{'egitim':>8}{'sinama':>8}")
print(f"{'taban cizgisi':<22}{0:>10}{'-':>7}{'-':>8}{TABAN:>8.4f}")
for ad, kur, ileri, ev, par in (("tam bagli 144-8-1", lambda t: tam_bagli(8, t),
                                 tb_ileri, False, tb_par),
                                ("evrisimli 2x3x3", lambda t: evrisimli(2, t),
                                 ev_ileri, True, ev_par)):
    for k, tohum in enumerate((TOHUM + 11, TOHUM + 12)):
        P = egit(kur(tohum), ileri, EGT_E, 60, 0.10, tohum + 500, ev)
        print(f"{ad if k == 0 else '':<22}{par if k == 0 else '':>10}{k + 1:>7}"
              f"{dogruluk(P, ileri, EGT_E, ev):>8.4f}"
              f"{dogruluk(P, ileri, SIN_E, ev):>8.4f}")
```

```
ag                     parametre  kosum  egitim  sinama
taban cizgisi                  0      -       -  0.5850
tam bagli 144-8-1           1169      1  1.0000  0.5100
                                      2  0.9950  0.5350
evrisimli 2x3x3               23      1  0.7850  0.8000
                                      2  0.8150  0.8150
```

Üç sayı yan yana duruyor. Taban çizgisi **0,5850**. Tam bağlı ağ **1.169** parametreyle eğitim
kümesini tamamen ezberliyor — birinci koşumda 1,0000 — ve sınama kümesinde **0,5100** okuyor,
yani taban çizgisinin 0,0750 **altında**. Evrişimli ağ **23** parametreyle sınamada **0,8000**
okuyor, taban çizgisini 0,2150 geçiyor.

Tam bağlı ağın başarısızlığı bir eğitim kusuru değildir. İki yüz ızgara 144 boyutlu ikili bir
uzayda birbirine hiç benzemez; ağ her birini ayrı ayrı ezberleyecek kadar geniştir ve ezberlemek,
hattın nerede olduğunu öğrenmekten kolaydır. Hat başka bir yerde göründüğünde ezberlenen
ağırlıkların hiçbiri işe yaramaz.

**Üçüncü sayı** her iki ağda da yazılıdır. Tam bağlı ağın iki koşumu 0,5100 ile 0,5350, fark
**0,0250**; evrişimli ağınki 0,8000 ile 0,8150, fark **0,0150**. Kapasite, veri ve bütçe sabitken
yalnız başlangıç değerlerinin değişmesi ölçülebilir bir fark açıyor. Tek bir koşumun sayısını
yazmak bu belirsizliği görünmez kılmak demektir.

Evrişimli ağ elle yazılmış iki çekirdeğin 0,9380'ine de ulaşamıyor. Nedeni kapasite değil, ilk
katmandan sonra yapılandır: her çekirdeğin bütün ızgaradaki **en büyük** değeri alınıp geri kalan
143 konum atılıyor. Bu ağ "hat var mı" sorusunu yanıtlar, "nerede" sorusunu yanıtlamaz.

#### Özet

- Kapsama ızgarası kurgudur: 12x12 hücre, yüzde 9 etkinlik, etiket bitişik üç hücrelik bir hat;
  sınamada en sık sınıf 0,5850.
- Aynı 144 çıktıyı üreten tam bağlı katman 20.880, tek bir 3x3 evrişim çekirdeği 10 sayı tutar;
  oran 2.088 kattır ve kaynağı ağırlık paylaşımıdır.
- Çıktı boyutu adım, dolgu ve çekirdek boyundan hesaplanır; ağırlık sayısı bu üçünden bağımsızdır,
  yalnız çarpma sayısı değişir (adım 1 dolgu 1'de 1.296, adım 3'te 144).
- Dolgusuz çalışmak kenardaki hatları görmez: uyuşma 0,8900'den 0,9380'e çıkar, fark 0,0480.
- 1.169 parametreli tam bağlı ağ eğitim kümesini ezberleyip sınamada 0,5100 ve 0,5350 okur, taban
  çizgisinin altında kalır; 23 parametreli evrişimli ağ 0,8000 ve 0,8150 okur.
- İkinci koşumun açtığı fark tam bağlı ağda 0,0250, evrişimli ağda 0,0150'dir.

#### Sonraki Adım

Evrişimli ağın ilk katmanı 144 konumda bir yanıt üretti, ama ağ yalnız **en büyüğünü** kullanıp
kalan 143 sayıyı attı. Bu, atılabilecek en uç örnektir: konum bilgisinin tamamı gitmiştir.
Sonraki ders bunu **ayarlanabilir bir adıma** çevirir; komşu konumların yanıtları küçük
pencerelerde birleştirilir. Ölçülecek üç şey vardır: çıktı boyutunun kaça düştüğü, atılan
hücrelerin kaçının geri kurulabildiği ve ızgara bir hücre kaydırıldığında kararın kaç örnekte
değiştiği.

### Havuzlama

Source: https://academia.sh/tr/kurslar/derin-ogrenme/havuzlama

Havuzlamanın attığı bilginin ve karşılığında aldığının sayılması: 2x2 en büyük havuzlama 144 hücreyi 36'ya indiriyor, ortalama 96,9 hücre geri kurulabiliyor ve geriye 46,0 bitlik bir belirsizlik kalıyor. Ham ızgara havuzlandığında hat bilgisi tümüyle gidiyor, uyuşma 0,9380'den 0,4220'ye düşüyor; aynı havuzlama öznitelik haritasına uygulandığında kaydırmaya dayanıklılık yüzde 0,0'dan yüzde 38,1'e, genel havuzlamada yüzde 88,7'ye çıkıyor. Taban çizgisi 0,5850 iken havuzlamasız ağ 309 parametreyle 0,5150 ve 0,5350, 2x2 havuzlamalı ağ 93 parametreyle 0,6100 ve 0,6150, genel havuzlamalı ağ 23 parametreyle 0,8050 ve 0,8050 veriyor; kaydırılan sınama kümesinde değişen karar sayısı sırasıyla 84, 49 ve 12.

Önceki dersin evrişimli ağı ilk katmanda 144 konumda bir yanıt üretti ve bunlardan yalnız en
büyüğünü kullandı. Kalan 143 sayı atıldı; ağ artık hattın **nerede** olduğunu bilmiyordu, yalnız
**olup olmadığını** biliyordu. Bu, atmanın en uç biçimidir.

Atma işleminin adı **havuzlamadır** ve uç biçimiyle sınırlı değildir: pencere boyutu bir ayar
değişkenidir ve 1'den ızgaranın tamamına kadar her değeri alabilir. Bu dersin ölçüsü iki
yönlüdür — havuzlama neyi geri kurulamaz biçimde atıyor ve karşılığında ne veriyor.

- **MI10. Küme, bölme ve taban çizgisi değişmez.** Önceki dersin kurgu kapsama ızgarası aynı
  tohumla üretilir: 12x12 hücre, yüzde 9 etkinlik, etiket olarak bitişik üç hücrelik bir hat.
  Bölme 200/100/200, sınamada en sık sınıf **0,5850**.
- **MI11. En büyük havuzlama**, $p \times p$'lik ayrık pencerelerin her birini o penceredeki en
  büyük değere indirir. **Ortalama havuzlama** aynı pencereyi ortalamaya indirir. İkisi de
  öğrenilecek parametre taşımaz.
- **MI12. Havuzlama, adımı pencere boyuna eşit bir indirgemedir**; çıktı boyu $12/p$'dir. Pencere
  boyu 12'ye çıktığında geriye tek sayı kalır; bu uç duruma **genel havuzlama** denir.
- **MI13. Geri kurulabilirlik sayılır.** İkili bir ızgarada en büyük havuzlama sıfır veren
  pencerenin bütün hücrelerini belirler, bir veren pencerenin hiçbirini belirlemez. Geriye kalan
  belirsizlik, aynı havuzlanmış çıktıyı verebilecek özgün ızgara sayısının ikili logaritmasıdır.
- **MI14. Havuzlama nereye uygulandığı önemlidir.** Ham ızgaraya uygulanan havuzlama ile evrişim
  çıktısına — **öznitelik haritasına** — uygulanan havuzlama aynı işlem, farklı sonuçtur.
- **MI15. Kaydırmaya dayanıklılık**, ızgara bir hücre kaydırıldığında gösterimin aynen korunduğu
  örnek oranıdır. Haritası tümüyle sıfır olan ızgaralar bu ölçünün dışında bırakılır, çünkü
  onlarda kaydırma zaten hiçbir şeyi değiştirmez.
- **MI16. Kaydırma bir hücre aşağıdır**; en üste sıfır satırı eklenir, en alt satır düşer. Hattın
  alt kenarda olduğu ızgaralarda bilgi gerçekten kaybolur; bu, ölçünün parçasıdır.
- **MI17. Kütüphane çağrılmaz;** havuzlama, evrişim ve eğitim döngüsü ders içinde yazılır ve
  **modeldir**.
- **MI18. Her ağ iki kez koşulur;** ikinci koşumda yalnız başlangıç değerleri değişir.

#### Havuzlama Neyi Atıyor

```python
# havuzlama.py — MODELDIR. 01'in KURGU kapsama izgarasi ayni tohumla uretilir.
import math

TOHUM, M32, BOY = 20260218, 0xFFFFFFFF, 12
YOGUNLUK, IZ_ORANI, KOSU = 0.09, 0.42, 3


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


def izgara(no):
    r = uretec(TOHUM + 300000 + no)
    g = [[1 if r() < YOGUNLUK else 0 for _ in range(BOY)] for _ in range(BOY)]
    iz = 1 if r() < IZ_ORANI else 0
    if iz:
        yatay, a, b = r() < 0.5, int(r() * BOY), int(r() * (BOY - KOSU + 1))
        for k in range(KOSU):
            if yatay:
                g[a][b + k] = 1
            else:
                g[b + k][a] = 1
    return g, iz


def karistir(n, tohum):
    r, s = uretec(tohum), list(range(n))
    for i in range(n - 1, 0, -1):
        j = int(r() * (i + 1))
        s[i], s[j] = s[j], s[i]
    return s


HAM = [izgara(i) for i in range(500)]
VERI = [HAM[i] for i in karistir(500, TOHUM + 90000)]
EGT, SIN = VERI[:200], VERI[300:]
TABAN = max(sum(e for _, e in SIN), len(SIN) - sum(e for _, e in SIN)) / len(SIN)


def havuzla(m, p, ortalama=False):
    n = len(m) // p
    return [[(sum(m[i * p + a][j * p + b] for a in range(p) for b in range(p)) / (p * p)
              if ortalama else
              max(m[i * p + a][j * p + b] for a in range(p) for b in range(p)))
             for j in range(n)] for i in range(n)]


def hat_var(m, k):
    n = len(m)
    for i in range(n):
        for j in range(n - k + 1):
            if all(m[i][j + t] > 0 for t in range(k)) or \
               all(m[j + t][i] > 0 for t in range(k)):
                return True
    return False


print(f"{'pencere':>8}{'cikti':>8}{'hucre':>7}{'atilan':>8}"
      f"{'geri kurulan':>14}{'olasi izgara (log2)':>21}")
for p in (1, 2, 3, 4):
    n = BOY // p
    kuru, belirsiz = 0, 0
    for g, e in VERI:
        s = sum(sum(r) for r in havuzla(g, p))
        kuru += (n * n - s) * p * p + (s * p * p if p == 1 else 0)
        belirsiz += s
    kuru, belirsiz = kuru / len(VERI), belirsiz / len(VERI)
    print(f"{f'{p}x{p}':>8}{f'{n}x{n}':>8}{n * n:>7}{BOY * BOY - n * n:>8}"
          f"{kuru:>13.1f} {belirsiz * math.log2(2 ** (p * p) - 1):>20.1f}")

print(f"\n{'havuzlama':>10}{'aranan hat':>12}{'etiketle uyusma':>17}")
for p, k in ((1, 3), (2, 2), (3, 2)):
    u = sum(1 for g, e in VERI if hat_var(havuzla(g, p), k) == (e == 1))
    print(f"{('yok' if p == 1 else f'{p}x{p}'):>10}{k:>12}{u / len(VERI):>17.4f}")
print(f"taban cizgisi (sinamada en sik sinif) {TABAN:.4f}")

gercek = sum(sum(sum(r) for r in g) for g, _ in VERI) / len(VERI)
enb = sum(sum(sum(r) for r in havuzla(g, 2)) for g, _ in VERI) / len(VERI)
ort = sum(sum(sum(r) for r in havuzla(g, 2, True)) * 4 for g, _ in VERI) / len(VERI)
print(f"etkin hucre sayisi {gercek:.2f}; 2x2 en buyuk havuzlamadan okunan alt "
      f"sinir {enb:.2f}, ortalama havuzlamadan okunan {ort:.2f}")
```

```
 pencere   cikti  hucre  atilan  geri kurulan  olasi izgara (log2)
     1x1   12x12    144       0        144.0                  0.0
     2x2     6x6     36     108         96.9                 46.0
     3x3     4x4     16     128         60.0                 84.0
     4x4     3x3      9     135         30.8                113.2

 havuzlama  aranan hat  etiketle uyusma
       yok           3           0.9380
       2x2           2           0.4220
       3x3           2           0.4060
taban cizgisi (sinamada en sik sinif) 0.5850
etkin hucre sayisi 13.96; 2x2 en buyuk havuzlamadan okunan alt sinir 11.78, ortalama havuzlamadan okunan 13.96
```

İlk tablo atmanın büyüklüğünü veriyor. 2x2 pencere 144 hücreyi 36'ya indirir; 108 hücre gitmiştir.
Gidenlerin hepsi geri kurulamaz değildir: sıfır veren bir pencere dört hücresinin de sıfır olduğunu
söyler, bu yüzden ortalama **96,9** hücrenin değeri belirlidir. Belirsiz kalan pay ise **46,0
bit**tir — aynı havuzlanmış çıktıyı veren $2^{46}$ mertebesinde özgün ızgara vardır. Pencere 4x4'e
çıktığında belirsizlik 113,2 bite yükselir ve geri kurulan hücre 30,8'e düşer.

İkinci tablo asıl uyarıdır. Ham ızgarada üç hücrelik hat aranınca uyuşma 0,9380'dir. Aynı ızgara
2x2 havuzlanıp iki hücrelik hat aranınca uyuşma **0,4220**'ye düşer, yani taban çizgisi 0,5850'nin
**altına**. Havuzlama ham girdiye uygulandığında gürültü hücreleri birbirine yaklaşıp sahte hatlar
üretir ve gerçek hat ile rastlantı ayırt edilemez hale gelir. Havuzlama burada bilgi **atmakla**
kalmaz, ayırt edici bilgiyi tam olarak atar.

Son satır iki havuzlama türünün farkını veriyor. Ortalama havuzlamadan etkin hücre sayısı tam
olarak geri okunur: 13,96. En büyük havuzlamadan okunan yalnız bir **alt sınırdır**, 11,78.
Ortalama havuzlama sayıyı korur, en büyük havuzlama varlığı korur; hangisinin işe yaradığı
sorulan soruya bağlıdır.

#### Öznitelik Haritasında Havuzlama

```python
# harita.py — havuzlama ham izgaraya degil, evrisimin urettigi OZNITELIK
# HARITASINA uygulanir. Cekirdekler 01'in elle yazilmis cekirdekleridir.
DOLGU = 1
YATAY = [[0, 0, 0], [1, 1, 1], [0, 0, 0]]
DIKEY = [[0, 1, 0], [0, 1, 0], [0, 1, 0]]


def etkinler(g):
    return [(i, j) for i in range(BOY) for j in range(BOY) if g[i][j]]


def evris(ak, K, yanma):
    n = BOY + 2 * DOLGU - 3 + 1
    cikti = [[yanma] * n for _ in range(n)]
    for (i, j) in ak:
        for di in range(3):
            for dj in range(3):
                p, q = i + DOLGU - di, j + DOLGU - dj
                if 0 <= p < n and 0 <= q < n:
                    cikti[p][q] += K[di][dj]
    return cikti


def gosterim(g, p):
    ak, d = etkinler(g), []
    for K in (YATAY, DIKEY):
        m = [[max(0.0, v) for v in s] for s in evris(ak, K, -2.5)]
        d += [v for s in (havuzla(m, p) if p > 1 else m) for v in s]
    return d


def kaydir(g):                               # bir hucre asagi kaydirma
    return [[0] * BOY] + [s[:] for s in g[:-1]]


ETKIN = [g for g, e in SIN if any(v > 0 for v in gosterim(g, 1))]
print(f"haritasi tumuyle sifir olmayan sinama izgarasi {len(ETKIN)}/{len(SIN)}")
print(f"{'havuzlama':>10}{'harita':>9}{'bas girdisi':>12}{'bas param':>11}"
      f"{'toplam param':>14}{'kaydirmada ayni':>17}")
for p in (1, 2, 3, 12):
    n = BOY // p
    bas = 2 * n * n
    ayni = sum(1 for g in ETKIN
               if all(abs(x - y) < 1e-9 for x, y in
                      zip(gosterim(g, p), gosterim(kaydir(g), p))))
    print(f"{('yok' if p == 1 else f'{p}x{p}'):>10}{f'{n}x{n}':>9}{bas:>12}"
          f"{bas + 1:>11}{20 + bas + 1:>14}{ayni / len(ETKIN):>16.1%}")
```

```
haritasi tumuyle sifir olmayan sinama izgarasi 97/200
 havuzlama   harita bas girdisi  bas param  toplam param  kaydirmada ayni
       yok    12x12         288        289           309            0.0%
       2x2      6x6          72         73            93           38.1%
       3x3      4x4          32         33            53           55.7%
     12x12      1x1           2          3            23           88.7%
```

Aynı işlem, farklı yer, ters sonuç. Havuzlama evrişimin çıktısına uygulandığında hat bilgisi
kaybolmaz, çünkü çekirdek hattı **zaten bulmuştur**; haritada kalan bilgi hattın yeri ve gücüdür,
havuzlama yalnız yeri kabalaştırır.

Kazanç son sütunda. Havuzlamasız gösterimde bir hücrelik kaydırma haritayı **her** ızgarada
değiştirir: dayanıklılık yüzde 0,0'dır. 2x2 havuzlamada gösterim ızgaraların yüzde **38,1**'inde
aynen korunur, 3x3'te yüzde 55,7'de, genel havuzlamada yüzde **88,7**'de. Sebep sayılabilir bir
şeydir: en büyük değer pencerenin içinde yer değiştirdiği sürece pencerenin çıktısı değişmez,
yani havuzlama pencere boyu kadar kaydırmayı yutar.

Kalan yüzde 11,3 kaydırmanın gerçekten bilgi götürdüğü paydır: hat en alt satırdaysa kaydırma onu
ızgaranın dışına atar. Ortadaki üç sütun bedeli yazıyor — başın girdisi 288'den 2'ye, toplam
parametre 309'dan 23'e düşüyor.

#### Üç Havuzlama, Üç Ağ

Şimdiye kadarki çekirdekler elle yazılmıştı. Aşağıda çekirdekler öğrenilir ve tek değişen şey
havuzlama penceresidir.

```python
# egit.py — MODELDIR: cekirdekler ogrenilir, havuzlama penceresi degisir.
# Cikis sigmoit, kayip capraz duzensizlik, guncelleme ornek basina.
EGT_E = [(etkinler(g), e) for g, e in EGT]
SIN_E = [(etkinler(g), e) for g, e in SIN]
KAY_E = [(etkinler(kaydir(g)), e) for g, e in SIN]


def sig(z):
    return 1 / (1 + math.exp(-z)) if z > -30 else 0.0


def kur(sayi, p, tohum):
    r, n = uretec(tohum), BOY // p
    return [[[[(r() * 2 - 1) / 3 for _ in range(3)] for _ in range(3)]
             for _ in range(sayi)], [0.0] * sayi,
            [(r() * 2 - 1) / (sayi * n * n) ** 0.5 for _ in range(sayi * n * n)],
            [0.0], p]


def ileri(P, ak):
    Ks, b, v, c, p = P
    n, z, kayit, idx = BOY // p, c[0], [], 0
    for k, K in enumerate(Ks):
        m = evris(ak, K, b[k])
        for i in range(n):
            for j in range(n):
                en, ep, eq = m[i * p][j * p], i * p, j * p
                for a in range(p):
                    for t in range(p):
                        if m[i * p + a][j * p + t] > en:
                            en, ep, eq = m[i * p + a][j * p + t], i * p + a, j * p + t
                h = max(0.0, en)
                kayit.append((k, ep, eq, h))
                z += v[idx] * h
                idx += 1
    return kayit, sig(z)


def egit(P, veri, tur, gadim, tohum):
    r, n = uretec(tohum), len(veri)
    Ks, b, v, c, p = P
    for _ in range(tur):
        s = list(range(n))
        for i in range(n - 1, 0, -1):
            j = int(r() * (i + 1))
            s[i], s[j] = s[j], s[i]
        for idx in s:
            ak, y = veri[idx]
            kayit, cikis = ileri(P, ak)
            d = cikis - y
            D = [[[0.0] * BOY for _ in range(BOY)] for _ in Ks]
            for t, (k, ep, eq, h) in enumerate(kayit):
                if h > 0.0:
                    D[k][ep][eq] += d * v[t]
                v[t] -= gadim * d * h
            c[0] -= gadim * d
            for k in range(len(Ks)):
                b[k] -= gadim * sum(sum(s2) for s2 in D[k])
                for di in range(3):
                    for dj in range(3):
                        Ks[k][di][dj] -= gadim * sum(
                            D[k][i + DOLGU - di][j + DOLGU - dj] for (i, j) in ak
                            if 0 <= i + DOLGU - di < BOY and 0 <= j + DOLGU - dj < BOY)
    return P


def dogruluk(P, veri):
    return sum(1 for ak, y in veri if (ileri(P, ak)[1] >= 0.5) == (y == 1)) / len(veri)


print(f"{'havuzlama':>10}{'param':>7}{'kosum':>7}{'egitim':>8}{'sinama':>8}"
      f"{'kaydirmada degisen karar':>26}")
print(f"{'taban':>10}{0:>7}{'-':>7}{'-':>8}{TABAN:>8.4f}{'-':>26}")
for p in (1, 2, 12):
    for k, tohum in enumerate((TOHUM + 11, TOHUM + 12)):
        P = egit(kur(2, p, tohum), EGT_E, 25, 0.05, tohum + 500)
        dev = sum(1 for (a1, y), (a2, _) in zip(SIN_E, KAY_E)
                  if (ileri(P, a1)[1] >= 0.5) != (ileri(P, a2)[1] >= 0.5))
        print(f"{('yok' if p == 1 else f'{p}x{p}') if k == 0 else '':>10}"
              f"{(20 + 2 * (BOY // p) ** 2 + 1) if k == 0 else '':>7}{k + 1:>7}"
              f"{dogruluk(P, EGT_E):>8.4f}{dogruluk(P, SIN_E):>8.4f}{dev:>26d}")
```

```
 havuzlama  param  kosum  egitim  sinama  kaydirmada degisen karar
     taban      0      -       -  0.5850                         -
       yok    309      1  1.0000  0.5150                        84
                       2  1.0000  0.5350                        88
       2x2     93      1  0.8950  0.6100                        49
                       2  0.7900  0.6150                        31
     12x12     23      1  0.8250  0.8050                        12
                       2  0.8200  0.8050                        11
```

Üç sayı tablonun içinde duruyor. Taban çizgisi **0,5850**. Havuzlamasız ağ 309 parametreyle eğitim
kümesini tamamen ezberliyor ve sınamada **0,5150** okuyor — tabanın altında. 2x2 havuzlamalı ağ 93
parametreyle **0,6100**, genel havuzlamalı ağ 23 parametreyle **0,8050** okuyor. Havuzlama arttıkça
ağ küçülüyor ve ayrılmış küme sayısı yükseliyor.

Son sütun aynı sırayı bağımsız bir ölçüyle doğruluyor. 200 sınama ızgarası bir hücre aşağı
kaydırıldığında havuzlamasız ağın kararı **84** örnekte değişiyor, 2x2 havuzlamalıda 49, genel
havuzlamalıda **12**. Kaydırma etiketi değiştirmiyor.

**İkinci koşum** üç satırda da yazılıdır ve en çok 2x2 havuzlamada konuşuyor: iki koşumun sınama
sayıları 0,6100 ile 0,6150, yani birbirine yakın, ama eğitim sayıları 0,8950 ile 0,7900 ve
kaydırmada değişen karar 49 ile 31. Aynı kapasitenin iki koşumu ayrılmış kümede benzer bir sayı
verirken kararın kaydırmaya karşı davranışında **on sekiz örneklik** fark açıyor. Ayrılmış küme
sayısı bu farkı hiçbir biçimde bildirmiyor.

#### Özet

- 2x2 en büyük havuzlama 144 hücreyi 36'ya indirir; ortalama 96,9 hücre geri kurulabilir, geriye
  46,0 bitlik belirsizlik kalır ve pencere 4x4'te belirsizlik 113,2 bite çıkar.
- Ham ızgaraya uygulanan havuzlama hat bilgisini yok eder: uyuşma 0,9380'den 0,4220'ye, yani taban
  çizgisinin altına düşer.
- Ortalama havuzlama etkin hücre sayısını tam olarak korur (13,96), en büyük havuzlama yalnız bir
  alt sınır verir (11,78).
- Aynı havuzlama öznitelik haritasına uygulandığında kaydırmaya dayanıklılık yüzde 0,0'dan yüzde
  38,1'e, genel havuzlamada yüzde 88,7'ye çıkar; bedeli baş girdisinin 288'den 2'ye inmesidir.
- Taban çizgisi 0,5850 iken havuzlamasız ağ 309 parametreyle 0,5150 ve 0,5350, 2x2 havuzlamalı ağ
  93 parametreyle 0,6100 ve 0,6150, genel havuzlamalı ağ 23 parametreyle 0,8050 ve 0,8050 okur.
- Kaydırılan sınama kümesinde değişen karar sayısı 84, 49 ve 12'dir; 2x2 havuzlamanın iki koşumu
  aynı sınama sayısını verirken bu sayıda 49 ile 31 arasında ayrışır.

#### Sonraki Adım

Buraya kadarki ağ **iki katmanlıdır**: bir evrişim, bir havuzlama, bir doğrusal baş. Genel
havuzlama en iyi sayıyı verdi, ama hattın yerini tümüyle attı — bu ağ "iki hat var mı" sorusunu
yanıtlayamaz. Bunun yolu haritayı bir kerede sıfıra indirmek yerine **evrişim ve havuzlamayı
sırayla yığmaktır**: her katman bir öncekinin çıktısında daha büyük bir alanı görür. Sonraki ders
bu yığmanın bedelini ölçer: katman sayısı arttıkça çıkıştan gelen eğimin ilk katmana ulaşıp
ulaşmadığı sayılır, **atlamalı bağlantının** bunu ne kadar düzelttiği ölçülür ve daha derin bir
ağın daha sığ bir ağı geçemediği bir nokta gösterilir.

### Evrişimli Ağ Mimarileri

Source: https://academia.sh/tr/kurslar/derin-ogrenme/evrisimli-ag-mimarileri

Derinliğin kattığının ve eğimin ilk katmana ulaşıp ulaşmadığının sayılması: düz yığında ilk katmana ulaşan eğim büyüklüğü derinlik 0'da 6,405e-01 iken derinlik 8'de 9,269e-07'ye iniyor, atlamalı bağlantı aynı derinlikte 6,779e-01 tutuyor ve oran 731.349 kat. Taban çizgisi 0,5850 iken 23 parametreli sığ ağ 0,7850 ve 0,8050, 63 parametreli düz derinlik 2 ağı iki koşumda da 0,5850 veriyor, yani daha derin ağ daha sığ ağı geçemiyor. Atlamalı bağlantı aynı derinlikte 0,7950 ve 0,8150, derinlik 5'te 0,8150 ve 0,8900 veriyor; derinliğin kattığı 0,0575'lik ortalama fark, aynı ağın iki koşumu arasındaki 0,0750'lik farktan küçüktür.

Önceki iki ders tek bir evrişim katmanı kullandı. O katman 3x3'lük bir pencereden bakar ve
ızgaranın yalnız o kadarını görür; "iki hat birbirine yakın mı" gibi bir soruyu yanıtlaması için
daha geniş bir alana bakması gerekir. Bunun yolu çekirdeği büyütmek değil, **katmanları
yığmaktır**: ikinci katman birincinin çıktısında 3x3'e bakar ve dolaylı olarak girdide çok daha
büyük bir alanı görür.

Yığmanın bir bedeli vardır ve bu dersin ölçüsü odur. Kayıptan gelen eğim, çıkıştan başlayıp katman
katman geriye taşınır; her katman onu bir kez daha çarpar. Yığın derinleştikçe **ilk katmana
ulaşan eğim** küçülür ve bir noktadan sonra ilk katman hiç güncellenmez. Ölçülecek üç şey vardır:
derinlikle büyüyen görme alanı, ilk katmana ulaşan eğimin büyüklüğü ve derinliğin ayrılmış küme
sayısına kattığı fark.

- **MI19. Küme, bölme ve taban çizgisi değişmez.** Kurgu kapsama ızgarası aynı tohumla üretilir;
  bölme 200/100/200, sınamada en sık sınıf **0,5850**.
- **MI20. Yığın sabittir, değişen tek şey blok sayısıdır.** Katman 0: iki 3x3 çekirdek, dolgu 1,
  doğrultulmuş doğrusal birim, ardından 4x4 havuzlama — geriye kanal başına 3x3 harita kalır.
  Sonra $D$ **blok**, sonra genel havuzlama ve doğrusal baş.
- **MI21. Blok**, bir kanalın haritasına uygulanan 3x3 evrişim ve doğrultulmuş doğrusal birimdir;
  kanallar birbirine karışmaz.
- **MI22. Atlamalı bağlantı**, bloğun **girdisini çıktısına eklemektir**. Blok artık girdiyi
  değiştirmez, girdiye bir **düzeltme** öğrenir; eğim geriye iki yoldan gider ve biri hiçbir
  çarpanla küçülmez.
- **MI23. Görme alanı**, bir çıktı biriminin değerini etkileyebilen girdi hücrelerinin oluşturduğu
  karenin kenar uzunluğudur. Havuzlama penceresi 4, blok başına genişleme 2 pencere olduğundan
  kenar $4(2D+1)+2$'dir.
- **MI24. Eğim ölçümü ilklendirmede yapılır** ve 80 eğitim ızgarasında ortalanır; ölçülen sayı ilk
  katmanın çekirdek eğimlerinin mutlak değer toplamıdır. Sorulan şey, eğitimin **başlayıp
  başlayamayacağıdır**.
- **MI25. İlklendirme sabittir** ve kazanç ölçekli değildir: bütün çekirdek ağırlıkları aynı
  aralıktan çekilir, böylece derinlikle ne olduğu görülebilir.
- **MI26. Kütüphane çağrılmaz;** yığın, ileri geçiş, geri yayılım ve eğitim döngüsü ders içinde
  yazılır ve **modeldir**. Hiçbir mimari bir kişi ya da kurum adıyla anılmaz; yapı adıyla anılır.
- **MI27. Her ağ iki kez koşulur;** ikinci koşumda yalnız başlangıç değerleri değişir.

#### Yığın ve Görme Alanı

```python
# mimari.py — MODELDIR. 01'in KURGU kapsama izgarasi ayni tohumla uretilir.
# Yigin: evrisim(3x3, dolgu 1, iki cekirdek) -> dogrultulmus -> havuzlama 4x4
# -> 3x3 harita; ardindan D blok (her kanala 3x3 evrisim + dogrultulmus,
# atlamali surumde
# blogun girdisi ciktiya eklenir); sonra genel havuzlama ve dogrusal bas.
import math

TOHUM, M32, BOY = 20260218, 0xFFFFFFFF, 12
YOGUNLUK, IZ_ORANI, KOSU = 0.09, 0.42, 3
DOLGU, KUCUK, YAN, KANAL = 1, 4, 3, 2


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


def izgara(no):
    r = uretec(TOHUM + 300000 + no)
    g = [[1 if r() < YOGUNLUK else 0 for _ in range(BOY)] for _ in range(BOY)]
    iz = 1 if r() < IZ_ORANI else 0
    if iz:
        yatay, a, b = r() < 0.5, int(r() * BOY), int(r() * (BOY - KOSU + 1))
        for k in range(KOSU):
            if yatay:
                g[a][b + k] = 1
            else:
                g[b + k][a] = 1
    return g, iz


def karistir(n, tohum):
    r, s = uretec(tohum), list(range(n))
    for i in range(n - 1, 0, -1):
        j = int(r() * (i + 1))
        s[i], s[j] = s[j], s[i]
    return s


HAM = [izgara(i) for i in range(500)]
VERI = [HAM[i] for i in karistir(500, TOHUM + 90000)]
EGT_E = [([(i, j) for i in range(BOY) for j in range(BOY) if g[i][j]], e)
         for g, e in VERI[:200]]
SIN_E = [([(i, j) for i in range(BOY) for j in range(BOY) if g[i][j]], e)
         for g, e in VERI[300:]]
TABAN = max(sum(e for _, e in SIN_E), len(SIN_E) - sum(e for _, e in SIN_E)) / len(SIN_E)


def kur(D, tohum, a=1 / 3):
    r = uretec(tohum)
    return [[[[[(r() * 2 - 1) * a for _ in range(3)] for _ in range(3)]
              for _ in range(KANAL)] for _ in range(D + 1)],
            [[0.0] * KANAL for _ in range(D + 1)],
            [(r() * 2 - 1) * 0.5 for _ in range(KANAL)], [0.0], D]


def ileri(P, ak, atlama):
    Ks, bs, v, c, D = P
    x, hav = [], []
    for k in range(KANAL):                   # katman 0: seyrek girdide evrisim
        m = [[bs[0][k]] * BOY for _ in range(BOY)]
        for (i, j) in ak:
            for di in range(3):
                for dj in range(3):
                    p, q = i + DOLGU - di, j + DOLGU - dj
                    if 0 <= p < BOY and 0 <= q < BOY:
                        m[p][q] += Ks[0][k][di][dj]
        kh, kx = [], [[0.0] * YAN for _ in range(YAN)]
        for i in range(YAN):
            for j in range(YAN):
                en, ep, eq = None, 0, 0
                for a in range(KUCUK):
                    for b in range(KUCUK):
                        u = m[i * KUCUK + a][j * KUCUK + b]
                        if en is None or u > en:
                            en, ep, eq = u, i * KUCUK + a, j * KUCUK + b
                kx[i][j] = max(0.0, en)
                kh.append((ep, eq, en))
        x.append(kx)
        hav.append(kh)
    ara, icler = [x], []
    for t in range(1, D + 1):                # D blok
        xp, yeni, ic = ara[-1], [], []
        for k in range(KANAL):
            z = [[bs[t][k]] * YAN for _ in range(YAN)]
            for p in range(YAN):
                for q in range(YAN):
                    s = bs[t][k]
                    for di in range(3):
                        i2 = p + di - DOLGU
                        if 0 <= i2 < YAN:
                            xi = xp[k][i2]
                            for dj in range(3):
                                j2 = q + dj - DOLGU
                                if 0 <= j2 < YAN:
                                    s += Ks[t][k][di][dj] * xi[j2]
                    z[p][q] = s
            ic.append(z)
            yeni.append([[max(0.0, z[i][j]) + (xp[k][i][j] if atlama else 0.0)
                          for j in range(YAN)] for i in range(YAN)])
        icler.append(ic)
        ara.append(yeni)
    son, h, arg = ara[-1], [], []
    for k in range(KANAL):                   # genel havuzlama
        en, ep, eq = son[k][0][0], 0, 0
        for i in range(YAN):
            for j in range(YAN):
                if son[k][i][j] > en:
                    en, ep, eq = son[k][i][j], i, j
        h.append(en)
        arg.append((ep, eq))
    z = c[0] + sum(v[k] * h[k] for k in range(KANAL))
    return 1 / (1 + math.exp(-max(-30, min(30, z)))), (hav, ara, icler, h, arg)


print(f"sinamada en sik sinif {TABAN:.4f}; egitim {len(EGT_E)} izgara")
print(f"{'derinlik':>9}{'blok':>6}{'parametre':>11}{'gorme alani':>13}"
      f"{'kapsanan izgara':>17}")
for D in (0, 1, 2, 3, 5, 8):
    alan = KUCUK * (2 * D + 1) + 2
    print(f"{D:>9}{D:>6}{20 * (D + 1) + 3:>11}{f'{alan}x{alan}':>13}"
          f"{min(alan, BOY) ** 2 / (BOY * BOY):>16.1%}")
```

```
sinamada en sik sinif 0.5850; egitim 200 izgara
 derinlik  blok  parametre  gorme alani  kapsanan izgara
        0     0         23          6x6           25.0%
        1     1         43        14x14          100.0%
        2     2         63        22x22          100.0%
        3     3         83        30x30          100.0%
        5     5        123        46x46          100.0%
        8     8        183        70x70          100.0%
```

Görme alanı derinlikle doğrusal büyür ve **bir blokta doyar**: derinlik 0'da bir çıktı birimi
ızgaranın yüzde 25'ini görürken derinlik 1'de kenar 14 hücreye çıkıp 12'lik ızgarayı aşar. Sonraki
bloklar **hiçbir yeni girdi hücresi getirmez**, yalnız parametre ekler. Burada derinlikten
beklenecek kazanç görme alanından gelemez.

#### Eğim İlk Katmana Ulaşıyor mu

```python
# egim.py — geri yayilim elle yazilir. Olculen sey: cikistan gelen egimin ILK
# katmanin cekirdeklerine ne kadari ulasiyor. Olcum ILKLENDIRMEDE yapilir.
def geri(P, ak, ic, d, atlama):
    Ks, bs, v, c, D = P
    hav, ara, icler, h, arg = ic
    dv = [d * h[k] for k in range(KANAL)]
    delta = [[[0.0] * YAN for _ in range(YAN)] for _ in range(KANAL)]
    for k in range(KANAL):
        ep, eq = arg[k]
        delta[k][ep][eq] = d * v[k]
    dK = [[[[0.0] * 3 for _ in range(3)] for _ in range(KANAL)] for _ in range(D + 1)]
    db = [[0.0] * KANAL for _ in range(D + 1)]
    for t in range(D, 0, -1):
        xp, ic2 = ara[t - 1], icler[t - 1]
        yeni = [[[delta[k][i][j] if atlama else 0.0 for j in range(YAN)]
                 for i in range(YAN)] for k in range(KANAL)]
        for k in range(KANAL):
            z = ic2[k]
            for p in range(YAN):
                for q in range(YAN):
                    g = delta[k][p][q] if z[p][q] > 0 else 0.0
                    if g == 0.0:
                        continue
                    db[t][k] += g
                    for di in range(3):
                        i2 = p + di - DOLGU
                        if not 0 <= i2 < YAN:
                            continue
                        for dj in range(3):
                            j2 = q + dj - DOLGU
                            if 0 <= j2 < YAN:
                                dK[t][k][di][dj] += g * xp[k][i2][j2]
                                yeni[k][i2][j2] += g * Ks[t][k][di][dj]
        delta = yeni
    for k in range(KANAL):
        d0 = [[0.0] * BOY for _ in range(BOY)]
        t2 = 0
        for i in range(YAN):
            for j in range(YAN):
                ep, eq, en = hav[k][t2]
                t2 += 1
                if en > 0 and delta[k][i][j] != 0.0:
                    d0[ep][eq] += delta[k][i][j]
        for di in range(3):
            for dj in range(3):
                dK[0][k][di][dj] = sum(
                    d0[i + DOLGU - di][j + DOLGU - dj] for (i, j) in ak
                    if 0 <= i + DOLGU - di < BOY and 0 <= j + DOLGU - dj < BOY)
        db[0][k] = sum(sum(s) for s in d0)
    return dK, db, dv


print(f"{'derinlik':>9}{'duz ilk katman':>17}{'atlamali ilk katman':>21}"
      f"{'oran':>12}")
for D in (0, 1, 2, 3, 5, 8):
    olcu = []
    for atlama in (False, True):
        P, tot = kur(D, TOHUM + 11), 0.0
        for ak, y in EGT_E[:80]:
            cikis, ic = ileri(P, ak, atlama)
            dK = geri(P, ak, ic, cikis - y, atlama)[0]
            tot += sum(abs(u) for k in range(KANAL) for s in dK[0][k] for u in s)
        olcu.append(tot / 80)
    print(f"{D:>9}{olcu[0]:>17.3e}{olcu[1]:>21.3e}{olcu[1] / olcu[0]:>12.1f}")
```

```
 derinlik   duz ilk katman  atlamali ilk katman        oran
        0        6.405e-01            6.405e-01         1.0
        1        2.393e-02            8.261e-01        34.5
        2        2.729e-03            1.925e-01        70.6
        3        2.457e-03            7.907e-01       321.8
        5        1.984e-04            1.043e+00      5256.1
        8        9.269e-07            6.779e-01    731349.2
```

Düz yığında ilk katmana ulaşan eğim derinlik 0'da $6{,}405 \times 10^{-1}$'dir. Bir blok onu
$2{,}393 \times 10^{-2}$'ye, beş blok $1{,}984 \times 10^{-4}$'e, sekiz blok $9{,}269 \times
10^{-7}$'ye indiriyor — yaklaşık **yedi yüz bin kat**. Bu bir eğitim kusuru değil, çarpımın
kendisidir: her blok geriye giden eğimi ağırlıklarıyla bir kez daha çarpar ve çarpanlar birden
küçükse çarpım derinlikle üstel küçülür.

Atlamalı bağlantı sütunu aynı derinliklerde $1{,}9 \times 10^{-1}$ ile $1{,}0$ arasında kalıyor;
derinlikle **azalmıyor**. Sebep MI22'de yazılıdır: bloğun çıktısı girdisini içerdiği için eğimin
geriye giden bir kopyası hiçbir çekirdekle çarpılmaz ve olduğu gibi taşınır. Oran sütunu düzeltmenin
büyüklüğüdür — derinlik 2'de 70,6 kat, derinlik 8'de **731.349 kat**.

#### Derinliğin Kattığı

```python
# egit.py — MODELDIR: ayni veri, ayni tur butcesi, ayni ogrenme adimi.
# Degisen yalniz derinlik ve atlamali baglantinin varligi.
def egit(P, veri, tur, gadim, tohum, atlama):
    r, n = uretec(tohum), len(veri)
    Ks, bs, v, c, D = P
    for _ in range(tur):
        s = list(range(n))
        for i in range(n - 1, 0, -1):
            j = int(r() * (i + 1))
            s[i], s[j] = s[j], s[i]
        for idx in s:
            ak, y = veri[idx]
            cikis, ic = ileri(P, ak, atlama)
            d = cikis - y
            dK, db, dv = geri(P, ak, ic, d, atlama)
            for t in range(D + 1):
                for k in range(KANAL):
                    bs[t][k] -= gadim * db[t][k]
                    for di in range(3):
                        for dj in range(3):
                            Ks[t][k][di][dj] -= gadim * dK[t][k][di][dj]
            for k in range(KANAL):
                v[k] -= gadim * dv[k]
            c[0] -= gadim * d
    return P


def dogruluk(P, veri, atlama):
    return sum(1 for ak, y in veri
               if (ileri(P, ak, atlama)[0] >= 0.5) == (y == 1)) / len(veri)


print(f"{'derinlik':>9}{'baglanti':>10}{'param':>7}{'kosum':>7}{'egitim':>8}"
      f"{'sinama':>8}{'tabana gore':>13}")
print(f"{'taban':>9}{'-':>10}{0:>7}{'-':>7}{'-':>8}{TABAN:>8.4f}{'0.0000':>13}")
for D, atlama in ((0, False), (2, False), (2, True), (5, False), (5, True)):
    for k, tohum in enumerate((TOHUM + 11, TOHUM + 12)):
        P = egit(kur(D, tohum), EGT_E, 25, 0.05, tohum + 500, atlama)
        s = dogruluk(P, SIN_E, atlama)
        print(f"{D if k == 0 else '':>9}"
              f"{('atlamali' if atlama else 'duz') if k == 0 else '':>10}"
              f"{(20 * (D + 1) + 3) if k == 0 else '':>7}{k + 1:>7}"
              f"{dogruluk(P, EGT_E, atlama):>8.4f}{s:>8.4f}{s - TABAN:>+13.4f}")
```

```
 derinlik  baglanti  param  kosum  egitim  sinama  tabana gore
    taban         -      0      -       -  0.5850       0.0000
        0       duz     23      1  0.8100  0.7850      +0.2000
                                2  0.8200  0.8050      +0.2200
        2       duz     63      1  0.5950  0.5850      +0.0000
                                2  0.5950  0.5850      +0.0000
        2  atlamali     63      1  0.8350  0.7950      +0.2100
                                2  0.8150  0.8150      +0.2300
        5       duz    123      1  0.5950  0.5850      +0.0000
                                2  0.5950  0.5850      +0.0000
        5  atlamali    123      1  0.8400  0.8150      +0.2300
                                2  0.9000  0.8900      +0.3050
```

Tablonun ortasındaki iki satır bu kursun ikinci iddiasının bu derste aldığı biçimdir ve
saklanmaz: **daha derin ağ daha sığ ağı geçemedi**. 23 parametreli sığ ağ 0,7850 ve 0,8050 okuyor;
63 parametreli, üç kat daha derin düz ağ iki koşumda da **0,5850** okuyor, yani tam olarak taban
çizgisini. Beş bloklu düz ağ 123 parametreyle aynı yerde. Bu ağlar eğitim kümesinde de 0,5950'de
kalıyor; öğrenmemişler, ezberlememişler de. Önceki tablo nedenini yazıyor: ilk katmana ulaşan eğim
$2{,}7 \times 10^{-3}$ ve $2{,}0 \times 10^{-4}$'tür, yani ilk katman ilklendirildiği yerde
kalmıştır ve ondan sonraki her şey rastgele bir haritanın üzerine kuruludur.

Atlamalı bağlantı aynı derinliği çalışır hale getiriyor: derinlik 2'de 0,7950 ve 0,8150,
derinlik 5'te 0,8150 ve **0,8900**. Yapı değişmedi, parametre sayısı değişmedi, tek fark bloğun
girdisinin çıktısına eklenmesi.

Son karşılaştırma dikkatle okunmalı. Sığ ağın iki koşumunun ortalaması 0,7950, beş bloklu atlamalı
ağınki 0,8525; derinliğin kattığı görünen fark **0,0575**. Ama beş bloklu ağın iki koşumu 0,8150 ile
0,8900 arasında, aralık **0,0750**. Derinliğin kattığı fark, aynı ağın yalnız başlangıç değerleri
değişerek verdiği farktan **küçüktür**; tek koşumla yapılan bir karşılaştırma bu ağı sığ ağın hem
0,0850 hem 0,0100 üstünde gösterebilirdi.

#### Özet

- Görme alanı derinlikle doğrusal büyür ve bu ızgarada bir blokta doyar: derinlik 0'da yüzde 25,
  derinlik 1'de yüzde 100. Sonraki bloklar yeni girdi hücresi getirmez, yalnız parametre ekler.
- Düz yığında ilk katmana ulaşan eğim derinlik 0'da $6{,}405 \times 10^{-1}$, derinlik 8'de
  $9{,}269 \times 10^{-7}$'dir; küçülme çarpımın kendisinden gelir.
- Atlamalı bağlantı aynı derinliklerde eğimi $1{,}9 \times 10^{-1}$ ile $1{,}0$ arasında tutar;
  düzeltme oranı derinlik 2'de 70,6, derinlik 8'de 731.349 kattır.
- Taban çizgisi 0,5850 iken 23 parametreli sığ ağ 0,7850 ve 0,8050 okur; 63 ve 123 parametreli düz
  derin ağlar iki koşumda da 0,5850'de kalır — **daha derin ağ daha sığ ağı geçemez**.
- Atlamalı bağlantı derinlik 2'de 0,7950 ve 0,8150, derinlik 5'te 0,8150 ve 0,8900 verir; parametre
  sayısı değişmeden.
- Derinliğin kattığı ortalama fark 0,0575, aynı ağın iki koşumu arasındaki fark 0,0750'dir;
  ikincisi büyük olduğu sürece birincisi tek koşumla ölçülemez.

#### Sonraki Adım

Üç derste girdinin yapısı **uzamsaldı** ve ızgaranın tamamı ağa bir kerede verildi; hangi hücrenin
önce geldiği diye bir soru yoktu. Abonenin sayaç okumaları böyle değildir: okumalar bir **sıra**
oluşturur, sıradaki yer anlamlıdır ve abone başına okuma sayısı aynı değildir. Sabit boyda bir
pencereden bakan çekirdek, pencere dışında kalan geçmişi göremez. Sonraki ders girdiyi baştan sona
**adım adım** okuyan ve gördüğünü bir **gizli durumda** biriktiren bir yapıyı kurar. Ölçülecek şey
o durumun ne taşıdığıdır: dizinin başındaki bilgi, dizi uzadıkça durumda ne kadar kalıyor.

### Yinelemeli Ağlar

Source: https://academia.sh/tr/kurslar/derin-ogrenme/yinelemeli-aglar

Gizli durumun dizi uzadıkça ne kadar bilgi taşıdığının sayılması: aynı dizinin yalnız ilk adımı değiştirildiğinde son gizli durumdaki fark uzunluk 2'de 0,92844 iken uzunluk 12'de 0,00913'e iniyor, adım başına çarpan 0,62. İlk adımdaki işaretin son durumdan geri okunma doğruluğu 1,0000'den 0,5300'e, yani rastlantı düzeyine düşüyor. Aynı 61 parametreli ağ uzunluk 2'de taban çizgisini 0,2300 ve 0,2800, uzunluk 8'de 0,2100 ve 0,1700, uzunluk 10'da 0,1950 ve 0,1850 geçerken uzunluk 12'de yalnız 0,0250 ve 0,0050 geçiyor: bağımlılık on adımda taşınıyor, on iki adımda taşınmıyor.

Üç derste girdi bir ızgaraydı ve ağa bir kerede verildi. Bir abonenin sayaç okumaları ise bir
**sıra** oluşturur: okumalar dönem dönem gelir, sıradaki yer anlamlıdır ve abone başına okuma
sayısı aynı olmak zorunda değildir. Sabit boyda bir pencereden bakan bir çekirdek bu veriye
uymaz — pencere dışında kalan geçmiş görünmez.

**Yinelemeli ağ** diziyi baştan sona adım adım okur ve o ana kadar gördüklerini bir **gizli
durumda** biriktirir. Her adımda aynı ağırlıklar kullanılır; bu, evrişimin uzamda yaptığı ağırlık
paylaşımının zaman eksenindeki karşılığıdır ve parametre sayısını dizi uzunluğundan bağımsız kılar.
Bu dersin ölçüsü şudur: dizinin **başındaki** bir bilgi, dizi uzadıkça gizli durumda ne kadar
kalıyor.

- **MI28. Okuma dizisi kurgudur.** Her abone için on iki dönemlik sayaç okuması üretilir; tohum
  20260218. Uzunluk **12'yi aşmaz** ve dizi bu konunun ilk üç dersindeki ızgaradan bağımsız,
  ayrı bir kurgudur.
- **MI29. İşaret dizinin başındadır.** Abonelerin yaklaşık yarısında **ilk dönemin okuması
  sıfırdır** — sayaç değişimi. Sıfır okuma yalnız ilk dönemde görülür, böylece işaret tektir ve
  yeri bellidir.
- **MI30. Etiket iki koşulun birlikte sağlanmasıdır:** ilk dönem sıfır okuma **ve** son dönemin
  okuması tarife basamağı 25 m³'ün üstünde. Ağın son adımda karar verebilmesi için dizinin başındaki
  bilgiyi sonuna kadar taşıması gerekir.
- **MI31. Her adımın girdisi iki sayıdır:** okumanın 40 m³'e bölünmüş değeri ve sıfır okuma
  göstergesi.
- **MI32. Etiket dizi uzunluğuna bağlıdır**, çünkü "son dönem" uzunlukla değişir. Bu yüzden
  **her uzunluk için taban çizgisi ayrıca hesaplanır** ve karşılaştırmalar tabana göre farkla
  yapılır.
- **MI33. Ağ sabittir:** 6 birimlik gizli durum, hiperbolik tanjant, çıkış son gizli durumdan
  okunan sigmoit. Parametre sayısı **61**'dir ve dizi uzunluğu ne olursa olsun değişmez.
- **MI34. Bilgi ölçümü eğitimsiz ağda yapılır.** Aynı dizinin yalnız ilk adımı değiştirilir ve iki
  son gizli durumun farkı ölçülür. Sorulan şey yapının ne **taşıyabildiğidir**, eğitimin ne
  başardığı değil.
- **MI35. Kütüphane çağrılmaz;** ileri geçiş, zaman içinde geri yayılım ve eğitim döngüsü ders
  içinde yazılır ve **modeldir**.
- **MI36. Her ağ iki kez koşulur;** ikinci koşumda yalnız başlangıç değerleri değişir.

#### Dizi ve Gizli Durum

```python
# dizi.py — MODELDIR. Okuma dizisi KURGUDUR: her abone icin on iki donemlik
# sayac okumasi uretilir. Ilk donemin okumasi bir kismi abonede SIFIRDIR
# (sayac degisimi); bu, dizinin basina konan ISARETTIR. Etiket, isaretin
# varligi ile son donemin tarife basamagini asmasinin BIRLIKTE saglanmasidir.
import math

TOHUM, M32 = 20260218, 0xFFFFFFFF
UZUN, TARIFE, OLCEK, GIZLI = 12, 25.0, 40.0, 6


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


def okuma_dizisi(no):
    r = uretec(TOHUM + 400000 + no)
    taban = 23.0 + 8.0 * r()
    d = [math.floor(taban * math.exp((r() + r() + r() - 1.5) * 0.62) * 100 + 0.5) / 100
         for _ in range(UZUN)]
    if r() < 0.5:
        d[0] = 0.0                           # isaret
    return d


def kes(d, T):
    """Ilk T donem; girdi adim basina iki sayi, etiket iki kosulun birlikte."""
    x = [[v / OLCEK, 1.0 if v == 0.0 else 0.0] for v in d[:T]]
    return x, 1 if (d[0] == 0.0 and d[T - 1] > TARIFE) else 0


def karistir(n, tohum):
    r, s = uretec(tohum), list(range(n))
    for i in range(n - 1, 0, -1):
        j = int(r() * (i + 1))
        s[i], s[j] = s[j], s[i]
    return s


HAM = [okuma_dizisi(i) for i in range(500)]
DZ = [HAM[i] for i in karistir(500, TOHUM + 95000)]
EGT, SIN = DZ[:200], DZ[300:]


def taban_cizgisi(T):
    p = sum(kes(d, T)[1] for d in SIN)
    return max(p, len(SIN) - p) / len(SIN)


def kur(tohum, H=GIZLI):
    r = uretec(tohum)
    a1, a2 = (1 / 2) ** 0.5, (1 / H) ** 0.5
    return [[[(r() * 2 - 1) * a1 for _ in range(2)] for _ in range(H)],
            [[(r() * 2 - 1) * a2 for _ in range(H)] for _ in range(H)],
            [0.0] * H, [(r() * 2 - 1) * a2 for _ in range(H)], [0.0]]


def ileri(P, x):
    """h_t = tanh(Wx x_t + Wh h_(t-1) + b); cikis son gizli durumdan okunur."""
    Wx, Wh, b, v, c = P
    H = len(b)
    h, izler = [0.0] * H, []
    for t in range(len(x)):
        h = [math.tanh(b[k] + Wx[k][0] * x[t][0] + Wx[k][1] * x[t][1]
                       + sum(Wh[k][j] * h[j] for j in range(H))) for k in range(H)]
        izler.append(h)
    z = c[0] + sum(v[k] * h[k] for k in range(H))
    return 1 / (1 + math.exp(-max(-30, min(30, z)))), izler


ornek = next(d for d in DZ if d[0] == 0.0 and d[UZUN - 1] > TARIFE)
print("ornek dizi (m3):", " ".join(f"{v:.2f}" for v in ornek))
print(f"isaret orani {sum(1 for d in DZ if d[0] == 0.0) / len(DZ):.3f}; "
      f"bolme {len(EGT)}/100/{len(SIN)}; gizli durum {GIZLI} birim; "
      f"parametre {GIZLI * 2 + GIZLI * GIZLI + GIZLI + GIZLI + 1}")
print(f"{'T':>3}{'pozitif':>9}{'taban cizgisi':>15}")
for T in (2, 4, 6, 8, 10, 12):
    print(f"{T:>3}{sum(kes(d, T)[1] for d in SIN):>9}{taban_cizgisi(T):>15.4f}")
```

```
ornek dizi (m3): 0.00 26.80 37.98 20.95 35.18 49.78 24.15 22.38 47.64 35.14 26.95 25.18
isaret orani 0.514; bolme 200/100/200; gizli durum 6 birim; parametre 61
  T  pozitif  taban cizgisi
  2       56         0.7200
  4       56         0.7200
  6       63         0.6850
  8       51         0.7450
 10       60         0.7000
 12       58         0.7100
```

Örnek dizide ilk okuma sıfırdır ve son okuma 25,18 m³ ile tarife basamağının üstündedir; etiket
1'dir. Aradaki on dönem karar için hiçbir şey söylemez — ağın taşıması gereken tek bilgi baştaki
sıfırdır.

Parametre sayısı **61**'dir ve alt tablodaki altı uzunluğun hepsinde aynıdır. Aynı ağırlıklar her
adımda yeniden kullanılır; bir dizi ne kadar uzarsa uzasın yeni ağırlık gerekmez. Bu, evrişimin
uzamda yaptığının zaman eksenindeki karşılığıdır ve tam bağlı bir katmanın yapamayacağı şeydir:
tam bağlı katman girdinin uzunluğunu baştan bilmek zorundadır.

Taban çizgileri uzunluğa göre 0,6850 ile 0,7450 arasında geziniyor, çünkü etiketin ikinci koşulu
"son dönem" ile tanımlıdır ve son dönem uzunlukla değişir. Bu yüzden uzunluklar arasındaki
karşılaştırma ham doğrulukla değil, **tabana göre farkla** yapılır.

#### Gizli Durum Neyi Taşıyor

```python
# iz.py — gizli durumun tasidigi bilgi. Ayni dizinin YALNIZ ilk adimi
# degistirilir (isaretli / isaretsiz) ve son gizli durumlarin farki olculur.
# Olcum EGITIMSIZ agda yapilir: sorulan sey yapinin ne tasiyabildigidir.
def ciftler(d, T):
    x, _ = kes(d, T)
    a = [s[:] for s in x]
    a[0] = [0.0, 1.0]
    b = [s[:] for s in x]
    b[0] = [d[1] / OLCEK, 0.0]
    return a, b


def geri_okuma(P, T):
    """En yakin merkez okuyucusu: h_T'den isaret geri okunabiliyor mu."""
    hs = [(ileri(P, kes(d, T)[0])[1][-1], 1 if d[0] == 0.0 else 0) for d in DZ]
    egt, sin = hs[:200], hs[300:]
    mer, say = [[0.0] * GIZLI, [0.0] * GIZLI], [0, 0]
    for h, s in egt:
        say[s] += 1
        for k in range(GIZLI):
            mer[s][k] += h[k]
    for s in (0, 1):
        mer[s] = [u / say[s] for u in mer[s]]
    ort = [(mer[0][k] * say[0] + mer[1][k] * say[1]) / len(egt) for k in range(GIZLI)]
    sd = [max(1e-9, (sum((h[k] - ort[k]) ** 2 for h, _ in egt) / len(egt)) ** 0.5)
          for k in range(GIZLI)]

    def uzak(h, s):
        return sum(((h[k] - mer[s][k]) / sd[k]) ** 2 for k in range(GIZLI))
    return sum(1 for h, s in sin if (uzak(h, 1) < uzak(h, 0)) == (s == 1)) / len(sin)


print(f"{'T':>3}{'h farki k1':>12}{'h farki k2':>12}{'adim basina k1':>16}"
      f"{'geri okuma k1':>15}{'geri okuma k2':>15}")
onceki = [None, None]
for T in (2, 4, 6, 8, 10, 12):
    sat = []
    for P in (kur(TOHUM + 11), kur(TOHUM + 12)):
        f = 0.0
        for d in DZ:
            a, b = ciftler(d, T)
            ia, ib = ileri(P, a)[1][-1], ileri(P, b)[1][-1]
            f += sum(abs(ia[k] - ib[k]) for k in range(GIZLI))
        sat.append((f / len(DZ), geri_okuma(P, T)))
    oran = "-" if onceki[0] is None else f"{(sat[0][0] / onceki[0]) ** 0.5:.3f}"
    onceki[0] = sat[0][0]
    print(f"{T:>3}{sat[0][0]:>12.5f}{sat[1][0]:>12.5f}{oran:>16}"
          f"{sat[0][1]:>15.4f}{sat[1][1]:>15.4f}")
```

```
  T  h farki k1  h farki k2  adim basina k1  geri okuma k1  geri okuma k2
  2     0.92844     1.39970               -         1.0000         0.9750
  4     0.34417     0.24972           0.609         0.7850         0.9350
  6     0.15338     0.06435           0.668         0.8000         0.6350
  8     0.05986     0.01560           0.625         0.5900         0.5500
 10     0.02362     0.00333           0.628         0.4600         0.4600
 12     0.00913     0.00067           0.622         0.5300         0.4750
```

İlk sütun dersin sayısıdır. Aynı dizinin yalnız ilk adımı değiştirildiğinde son gizli durumda
kalan fark uzunluk 2'de **0,92844**, uzunluk 12'de **0,00913**'tür — yüzde birinden az. Dördüncü
sütun küçülmenin biçimini veriyor: adım başına çarpan 0,609 ile 0,668 arasında, yani **sabit bir
çarpanla** üstel bir azalma. Gizli durum bilgiyi unutmaya karar vermiyor; her adımda aynı dizeyle
çarpılıyor ve çarpanın büyüklüğü birden küçük olduğu için iz kendiliğinden siliniyor.

İkinci koşum aynı biçimi farklı bir hızla gösteriyor: uzunluk 12'de fark 0,00067, birinci koşumun
on dörtte biri. Yalnız başlangıç değerleri değişti; unutma hızı bir mimari sabiti değil,
ilklendirmenin sonucudur.

Son iki sütun bunun ne anlama geldiğini yazıyor. Uzunluk 2'de işaret son gizli durumdan **1,0000**
doğrulukla geri okunuyor. Uzunluk 8'de 0,5900'e, uzunluk 10'da 0,4600'e iniyor — işaret oranı
0,514 olduğuna göre bu rastlantı düzeyidir. Uzunluk 12'deki 0,5300 bir toparlanma değil, aynı
düzeydeki ölçüm oynamasıdır. Bilgi gizli durumda **yoktur**; hiçbir okuyucu onu geri getiremez.

#### Ne Kadar Geriye Taşınıyor

```python
# egit.py — MODELDIR: zaman icinde geri yayilim elle yazilir. Ayni ag, ayni
# tur butcesi, degisen tek sey dizi uzunlugudur.
def egit(P, veri, tur, gadim, tohum):
    Wx, Wh, b, v, c = P
    H, r, n = len(b), uretec(tohum), len(veri)
    for _ in range(tur):
        s = list(range(n))
        for i in range(n - 1, 0, -1):
            j = int(r() * (i + 1))
            s[i], s[j] = s[j], s[i]
        for idx in s:
            x, y = veri[idx]
            p, izler = ileri(P, x)
            d = p - y
            dh = [d * v[k] for k in range(H)]
            for k in range(H):
                v[k] -= gadim * d * izler[-1][k]
            c[0] -= gadim * d
            for t in range(len(x) - 1, -1, -1):
                onceki = izler[t - 1] if t > 0 else [0.0] * H
                yeni = [0.0] * H
                for k in range(H):
                    g = dh[k] * (1 - izler[t][k] ** 2)
                    b[k] -= gadim * g
                    Wx[k][0] -= gadim * g * x[t][0]
                    Wx[k][1] -= gadim * g * x[t][1]
                    for j in range(H):
                        yeni[j] += g * Wh[k][j]
                        Wh[k][j] -= gadim * g * onceki[j]
                dh = yeni
    return P


def dogruluk(P, veri):
    return sum(1 for x, y in veri if (ileri(P, x)[0] >= 0.5) == (y == 1)) / len(veri)


print(f"{'T':>3}{'taban':>8}{'kosum 1':>9}{'kosum 2':>9}{'fark 1':>9}{'fark 2':>9}"
      f"{'kosum araligi':>15}")
for T in (2, 4, 6, 8, 10, 12):
    eg = [kes(d, T) for d in EGT]
    sn = [kes(d, T) for d in SIN]
    tb, s = taban_cizgisi(T), []
    for tohum in (TOHUM + 11, TOHUM + 12):
        P = kur(tohum)
        egit(P, eg, 30, 0.05, tohum + 500)
        s.append(dogruluk(P, sn))
    print(f"{T:>3}{tb:>8.4f}{s[0]:>9.4f}{s[1]:>9.4f}{s[0] - tb:>+9.4f}"
          f"{s[1] - tb:>+9.4f}{abs(s[0] - s[1]):>15.4f}")
```

```
  T   taban  kosum 1  kosum 2   fark 1   fark 2  kosum araligi
  2  0.7200   0.9500   1.0000  +0.2300  +0.2800         0.0500
  4  0.7200   0.9550   0.9550  +0.2350  +0.2350         0.0000
  6  0.6850   0.9350   0.9550  +0.2500  +0.2700         0.0200
  8  0.7450   0.9550   0.9150  +0.2100  +0.1700         0.0400
 10  0.7000   0.8950   0.8850  +0.1950  +0.1850         0.0100
 12  0.7100   0.7350   0.7150  +0.0250  +0.0050         0.0200
```

Eğitim, ölçümün söylediğini doğruluyor ama tam olarak aynı yerde değil. Uzunluk 2'den 10'a kadar
ağ taban çizgisini 0,1700 ile 0,2800 arasında geçiyor. Uzunluk 12'de fark **0,0250** ve
**0,0050**'ye düşüyor: ağ artık taban çizgisiyle aynı şeyi söylüyor, yani baştaki işareti hiç
kullanmıyor ve yalnız son dönemin okumasına bakan bir kurala dönüşüyor.

Eğitimsiz ölçüm işaretin uzunluk 10'da zaten geri okunamadığını söylemişti; eğitilen ağ ise
uzunluk 10'da hâlâ 0,1950 ve 0,1850 fark üretiyor. Çelişki değildir: eğitim, ağırlıkları başlangıç
değerlerinden uzaklaştırır ve yinelemeli dizeyi izin verdiği kadar bilgi taşıyacak biçimde
ayarlar. Kazanılan iki adımdır. On ikide o iki adım da yetmez, çünkü sorun ağırlıkların
ayarlanmasıyla çözülecek türden değildir: taşıma **çarpımla** yapılır ve çarpanı biraz büyütmek
uzun dizide patlamaya, biraz küçültmek sönmeye götürür.

**Koşum aralığı** sütunu tabloya kendi uyarısını yazıyor. Uzunluk 8'de iki koşum 0,0400 ayrılıyor;
bu, uzunluk 8 ile uzunluk 10 arasındaki farkın (0,0150) üstündedir. Uzunluğun kattığı fark ile
başlangıç değerlerinin kattığı fark aynı büyüklük sırasındadır ve tek koşumla ölçülen bir "kaç
adıma kadar çalışıyor" yanıtı bu yüzden güvenilir değildir.

#### Özet

- Okuma dizisi kurgudur: on iki dönemlik okuma, işaret olarak ilk dönemin sıfır okuması, etiket
  işaret ile son dönemin tarife basamağını aşmasının birlikte sağlanması.
- Yinelemeli ağ her adımda aynı ağırlıkları kullanır; parametre sayısı 61'dir ve dizi uzunluğundan
  bağımsızdır.
- İlk adımdaki işaretin son gizli durumda bıraktığı fark uzunluk 2'de 0,92844, uzunluk 12'de
  0,00913'tür; adım başına çarpan 0,609 ile 0,668 arasında sabittir.
- İşaretin son durumdan geri okunma doğruluğu 1,0000'den uzunluk 10'da 0,4600'e, yani rastlantı
  düzeyine iner; ikinci koşumda unutma daha da hızlıdır (uzunluk 12'de fark 0,00067).
- Eğitilen ağ taban çizgisini uzunluk 10'a kadar 0,1700–0,2800 geçer, uzunluk 12'de yalnız 0,0250
  ve 0,0050 geçer.
- Uzunluk 8'deki koşum aralığı 0,0400, uzunluk 8 ile 10 arasındaki farktan büyüktür; "kaç adıma
  kadar" sorusu tek koşumla yanıtlanamaz.

#### Sonraki Adım

Gizli durum bilgiyi tutmayı **seçmiyor**; her adımda aynı dizeyle çarpılıyor ve çarpanın
büyüklüğü neyin kalacağını belirliyor. Aynı çarpan hem yeni okumayı hem de baştaki işareti eşit
biçimde etkiliyor, oysa bu iki bilginin ömrü aynı olmamalı: okuma bir adım sonra gereksizdir,
işaret dizinin sonuna kadar gereklidir. Sonraki ders duruma iki karar ekler — neyin **silineceği**
ve neyin **yazılacağı** — ve bu kararları girdiye bakarak veren birimler kurar. Ölçü aynı kalır ve
doğrudan karşılaştırılır: yalın yinelemeli ağ ile kapı birimli ağ aynı görevde, aynı uzunluklarda,
her biri iki koşumla yan yana konur ve bağımlılığın kaç adım geriye taşınabildiği sayılır.

### Kapı Birimleri

Source: https://academia.sh/tr/kurslar/derin-ogrenme/kapi-birimleri

Uzun bağımlılığın kaç adım geriye taşınabildiğinin sayılması: eğitimsiz ağda ilk adımdaki işaretin son gizli durumda kalan payı yalın 6 birimli ağda yüzde 0,98 ve yüzde 0,05, 9 birimli yalın ağda yüzde 0,71 ve yüzde 0,05 iken kapı birimli ağda yüzde 9,34 ve yüzde 5,63. Aynı tur bütçesinde uzunluk 8'e kadar üç yapı da taban çizgisini 0,1700–0,2800 geçiyor; uzunluk 12'de 61 parametreli yalın ağ 0,0250 ve 0,0050'ye düşerken 115 parametreli kapı birimli ağ 0,2650 ve 0,2050, 118 parametreli geniş yalın ağ 0,0100 ve 0,1700 veriyor. Kapı yapısının eşit bütçeli yalın ağa üstünlüğü on iki adımda iki koşumla kesinleşmiyor: geniş yalın ağ bir koşumda dizinin tamamını taşıyor, ötekinde taşımıyor.

Önceki dersin gizli durumu bilgiyi tutmayı **seçmiyordu**. Her adımda aynı dizeyle çarpılıyor,
çarpanın büyüklüğü neyin kalacağını belirliyordu ve ölçülen çarpan adım başına 0,62 idi. Aynı
çarpan hem yeni okumaya hem baştaki işarete uygulanıyordu, oysa bu iki bilginin ömrü aynı
olmamalıdır: okuma bir adım sonra gereksizdir, işaret dizinin sonuna kadar gereklidir.

**Kapı birimi** duruma iki ayrı hesap ekler: ne kadarının **tutulacağı** ve yerine ne
**yazılacağı**. İkisi de o adımın girdisine ve o ana kadarki duruma bakarak hesaplanır, yani
birim her adımda ayrı bir karar verir. Bu dersin ölçüsü şudur: bu karar, bağımlılığı kaç adım
geriye taşıyor — ve kazanç gerçekten kapıdan mı geliyor.

- **MI37. Küme ve bölme değişmez.** Önceki dersin kurgu okuma dizisi aynı tohumla üretilir:
  on iki dönem, ilk dönemin sıfır okuması işaret, etiket işaret ile son dönemin tarife basamağını
  aşmasının birlikte sağlanması. Bölme 200/100/200, taban çizgisi her uzunluk için ayrı.
- **MI38. Kapı birimi iki bloktan kurulur.** **Tutma kapısı** $u_t$ sigmoit çıkışlıdır ve her
  birim için 0 ile 1 arasında bir sayı verir. **Aday değer** $a_t$ hiperbolik tanjant çıkışlıdır.
  Yeni durum ikisinin karışımıdır: $h_t = u_t h_{t-1} + (1 - u_t) a_t$.
- **MI39. Kapının açtığı yol çarpımsal değil seçimseldir.** $u_t$ bire yakınsa eski durum
  neredeyse olduğu gibi geçer; sıfıra yakınsa aday değer yazılır. Yalın birimde böyle bir seçenek
  yoktur, her adım aynı dönüşümü uygular.
- **MI40. Tutma kapısının yanması pozitif ilklendirilir** (değer 1). Kapı başlangıçta açıktır ve
  eğitim onu kapatmayı öğrenir; ters yönde ilklendirme, öğrenmenin başlaması için önce kapının
  açılmasını beklemeyi gerektirir.
- **MI41. Parametre sayısı karşılaştırılır.** Kapı birimi iki blok taşıdığı için aynı gizli birim
  sayısında yalın birimden yaklaşık iki kat fazla parametre tutar. Bu yüzden **eşit bütçeli** bir
  yalın ağ da tabloya konur: 9 birimli yalın ağ, 6 birimli kapı birimli ağla yaklaşık aynı
  parametreyi taşır.
- **MI42. Ölçü iki katmanlıdır.** Birincisi **eğitimsiz** ağda işaretin son gizli durumda kalan
  payıdır — yapının ne taşıyabildiği. İkincisi eğitilen ağın taban çizgisine göre farkıdır — ne
  taşıdığı.
- **MI43. Üç yapı aynı bütçeyle eğitilir:** 30 tur, öğrenme adımı 0,05, aynı bölme, aynı sıra
  üreteci. Yalın 6 birimli ağın sayıları önceki dersle birebir aynıdır.
- **MI44. Kütüphane çağrılmaz;** kapı birimi, zaman içinde geri yayılım ve eğitim döngüsü ders
  içinde yazılır ve **modeldir**. Yapı adıyla anılır, kısaltma kullanılmaz.
- **MI45. Her ağ iki kez koşulur;** ikinci koşumda yalnız başlangıç değerleri değişir.

#### Kapı Birimi

```python
# kapi.py — MODELDIR. 04'un KURGU okuma dizisi ayni tohumla uretilir.
# Yalin: h_t = tanh(...). Kapili: h_t = u_t * h_(t-1) + (1 - u_t) * a_t.
import math

TOHUM, M32 = 20260218, 0xFFFFFFFF
UZUN, TARIFE, OLCEK, GIZLI = 12, 25.0, 40.0, 6


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


def okuma_dizisi(no):
    r = uretec(TOHUM + 400000 + no)
    taban = 23.0 + 8.0 * r()
    d = [math.floor(taban * math.exp((r() + r() + r() - 1.5) * 0.62) * 100 + 0.5) / 100
         for _ in range(UZUN)]
    if r() < 0.5:
        d[0] = 0.0
    return d


def kes(d, T):
    return ([[v / OLCEK, 1.0 if v == 0.0 else 0.0] for v in d[:T]],
            1 if (d[0] == 0.0 and d[T - 1] > TARIFE) else 0)


def karistir(n, tohum):
    r, s = uretec(tohum), list(range(n))
    for i in range(n - 1, 0, -1):
        j = int(r() * (i + 1))
        s[i], s[j] = s[j], s[i]
    return s


DZ = [okuma_dizisi(i) for i in karistir(500, TOHUM + 95000)]
EGT, SIN = DZ[:200], DZ[300:]


def taban_cizgisi(T):
    p = sum(kes(d, T)[1] for d in SIN)
    return max(p, len(SIN) - p) / len(SIN)


def sig(z):
    return 1 / (1 + math.exp(-max(-30, min(30, z))))


def kur(tohum, H=GIZLI):
    r = uretec(tohum)
    return [[[(r() * 2 - 1) * (1 / 2) ** 0.5 for _ in range(2)] for _ in range(H)],
            [[(r() * 2 - 1) * (1 / H) ** 0.5 for _ in range(H)] for _ in range(H)],
            [0.0] * H, [(r() * 2 - 1) * (1 / H) ** 0.5 for _ in range(H)], [0.0]]


def ileri(P, x):
    Wx, Wh, b, v, c = P
    H = len(b)
    h, izler = [0.0] * H, []
    for t in range(len(x)):
        h = [math.tanh(b[k] + Wx[k][0] * x[t][0] + Wx[k][1] * x[t][1]
                       + sum(Wh[k][j] * h[j] for j in range(H))) for k in range(H)]
        izler.append(h)
    return sig(c[0] + sum(v[k] * h[k] for k in range(H))), izler


def kur_kapi(tohum, H=GIZLI, kapi_yanma=1.0):
    r = uretec(tohum)

    def blok(b0):
        return [[[(r() * 2 - 1) * (1 / 2) ** 0.5 for _ in range(2)] for _ in range(H)],
                [[(r() * 2 - 1) * (1 / H) ** 0.5 for _ in range(H)] for _ in range(H)],
                [b0] * H]
    return [blok(kapi_yanma), blok(0.0),
            [(r() * 2 - 1) * (1 / H) ** 0.5 for _ in range(H)], [0.0], H]


def ileri_kapi(P, x):
    U, A, v, c, H = P
    h, izler = [0.0] * H, []
    for t in range(len(x)):
        u = [sig(U[2][k] + U[0][k][0] * x[t][0] + U[0][k][1] * x[t][1]
                 + sum(U[1][k][j] * h[j] for j in range(H))) for k in range(H)]
        a = [math.tanh(A[2][k] + A[0][k][0] * x[t][0] + A[0][k][1] * x[t][1]
                       + sum(A[1][k][j] * h[j] for j in range(H))) for k in range(H)]
        yeni = [u[k] * h[k] + (1 - u[k]) * a[k] for k in range(H)]
        izler.append((h, u, a, yeni))
        h = yeni
    return sig(c[0] + sum(v[k] * h[k] for k in range(H))), izler


def par_yalin(H):
    return 2 * H + H * H + H + H + 1


def par_kapi(H):
    return 2 * (2 * H + H * H + H) + H + 1


print(f"{'yapi':<22}{'gizli birim':>12}{'parametre':>11}")
for ad, H, f in (("yalin yinelemeli", GIZLI, par_yalin), ("yalin yinelemeli", 9, par_yalin),
                 ("kapi birimli", GIZLI, par_kapi)):
    print(f"{ad:<22}{H:>12}{f(H):>11}")
print(f"\n{'T':>3}{'taban cizgisi':>15}")
for T in (2, 4, 8, 12):
    print(f"{T:>3}{taban_cizgisi(T):>15.4f}")
```

```
yapi                   gizli birim  parametre
yalin yinelemeli                 6         61
yalin yinelemeli                 9        118
kapi birimli                     6        115

  T  taban cizgisi
  2         0.7200
  4         0.7200
  8         0.7450
 12         0.7100
```

Kapı biriminin karışım bağıntısı tek satırdır ve önemli olan bu satırın **biçimidir**: eski durum
o adımın girdisinden hesaplanan bir katsayıyla çarpılır, üstüne bir aday eklenir. Yalın birimde
kalan payı ağırlıkların büyüklüğü belirlerdi ve bütün adımlar için aynıydı.

Parametre tablosu karşılaştırmanın kuralını koyuyor. Aynı 6 birimle kapı birimli ağ **115**,
yalın ağ **61** parametre tutar; bu ikisini yan yana koymak kapıya ait olmayan bir farkı kapıya
yazmak olurdu. Bu yüzden 9 birimli, **118** parametreli bir yalın ağ da tabloya konur.

#### İşaretin İzi Üç Yapıda

```python
# iz.py — 04'un olcusu uc yapida, EGITIMSIZ agda yinelenir: dizinin yalniz
# ilk adimi degistirilir, son gizli durumdaki fark olculur.
def ciftler(d, T):
    x = kes(d, T)[0]
    a = [s[:] for s in x]
    a[0] = [0.0, 1.0]
    b = [s[:] for s in x]
    b[0] = [d[1] / OLCEK, 0.0]
    return a, b


def iz(P, T, kapili):
    f = 0.0
    for d in DZ:
        a, b = ciftler(d, T)
        if kapili:
            ia, ib = ileri_kapi(P, a)[1][-1][3], ileri_kapi(P, b)[1][-1][3]
        else:
            ia, ib = ileri(P, a)[1][-1], ileri(P, b)[1][-1]
        f += sum(abs(ia[k] - ib[k]) for k in range(len(ia)))
    return f / len(DZ)


YAPI = [("yalin 6", lambda t: kur(t, 6), False),
        ("yalin 9", lambda t: kur(t, 9), False),
        ("kapi 6", lambda t: kur_kapi(t, 6), True)]
print(f"{'T':>3}" + "".join(f"{ad + ' k' + str(k + 1):>12}"
                            for ad, _, _ in YAPI for k in range(2)))
ilk = {}
for T in (2, 4, 8, 12):
    sat = []
    for ad, f, kapili in YAPI:
        for k, tohum in enumerate((TOHUM + 11, TOHUM + 12)):
            u = iz(f(tohum), T, kapili)
            sat.append(u)
            if T == 2:
                ilk[(ad, k)] = u
    print(f"{T:>3}" + "".join(f"{u:>12.5f}" for u in sat))
print("uzunluk 2'deki ize gore uzunluk 12'de kalan pay:")
for i, (ad, f, kapili) in enumerate(YAPI):
    for k, tohum in enumerate((TOHUM + 11, TOHUM + 12)):
        print(f"  {ad} k{k + 1}: {iz(f(tohum), 12, kapili) / ilk[(ad, k)]:.4%}")
```

```
  T  yalin 6 k1  yalin 6 k2  yalin 9 k1  yalin 9 k2   kapi 6 k1   kapi 6 k2
  2     0.92844     1.39970     2.23946     1.75462     0.32959     0.46329
  4     0.34417     0.24972     0.65803     0.40122     0.17443     0.22063
  8     0.05986     0.01560     0.10734     0.01796     0.07712     0.06693
 12     0.00913     0.00067     0.01600     0.00083     0.03077     0.02610
uzunluk 2'deki ize gore uzunluk 12'de kalan pay:
  yalin 6 k1: 0.9837%
  yalin 6 k2: 0.0478%
  yalin 9 k1: 0.7143%
  yalin 9 k2: 0.0473%
  kapi 6 k1: 9.3350%
  kapi 6 k2: 5.6329%
```

Ham sayılar yanıltıcıdır, oran satırları düzeltir. Kapı birimli ağ uzunluk 2'de yalın ağdan
**daha az** iz taşıyor (0,32959 ile 0,92844), çünkü tutma kapısı yeni bilgiyi de yavaşlatır.
Ölçülecek şey başlangıçtaki iz değil, **on adım sonra kalan paydır**.

O pay yalın 6 birimli ağda yüzde **0,98** ve yüzde **0,05**; kapı birimli ağda yüzde **9,34** ve
yüzde **5,63**. Kapı, işaretin kalan payını on ila yüz kat büyütüyor.

Ortadaki iki sütun kapının ne olmadığını yazıyor. Yalın ağı 6 birimden 9'a genişletmek kalan payı
yüzde 0,98'den 0,71'e **düşürüyor**: unutma hızı birim sayısının değil, her adımda uygulanan
çarpımın sonucudur. Taşıma kapasitesini değiştiren tek şey karışım bağıntısının biçimidir.

#### Kaç Adım Geriye

```python
# egit.py — MODELDIR: uc yapi ayni veride, 30 tur, ogrenme adimi 0,05.
# Zaman icinde geri yayilim elle yazilir.
def egit(P, veri, tur, gadim, tohum):
    Wx, Wh, b, v, c = P
    H, r, n = len(b), uretec(tohum), len(veri)
    for _ in range(tur):
        s = list(range(n))
        for i in range(n - 1, 0, -1):
            j = int(r() * (i + 1))
            s[i], s[j] = s[j], s[i]
        for idx in s:
            x, y = veri[idx]
            p, izler = ileri(P, x)
            d = p - y
            dh = [d * v[k] for k in range(H)]
            for k in range(H):
                v[k] -= gadim * d * izler[-1][k]
            c[0] -= gadim * d
            for t in range(len(x) - 1, -1, -1):
                onceki, yeni = (izler[t - 1] if t > 0 else [0.0] * H), [0.0] * H
                for k in range(H):
                    g = dh[k] * (1 - izler[t][k] ** 2)
                    b[k] -= gadim * g
                    Wx[k][0] -= gadim * g * x[t][0]
                    Wx[k][1] -= gadim * g * x[t][1]
                    for j in range(H):
                        yeni[j] += g * Wh[k][j]
                        Wh[k][j] -= gadim * g * onceki[j]
                dh = yeni
    return P


def egit_kapi(P, veri, tur, gadim, tohum):
    U, A, v, c, H = P
    r, n = uretec(tohum), len(veri)
    for _ in range(tur):
        s = list(range(n))
        for i in range(n - 1, 0, -1):
            j = int(r() * (i + 1))
            s[i], s[j] = s[j], s[i]
        for idx in s:
            x, y = veri[idx]
            p, izler = ileri_kapi(P, x)
            d = p - y
            dh = [d * v[k] for k in range(H)]
            for k in range(H):
                v[k] -= gadim * d * izler[-1][3][k]
            c[0] -= gadim * d
            for t in range(len(x) - 1, -1, -1):
                onceki, u, a, _ = izler[t]
                yeni = [0.0] * H
                for k in range(H):
                    du = dh[k] * (onceki[k] - a[k]) * u[k] * (1 - u[k])
                    da = dh[k] * (1 - u[k]) * (1 - a[k] ** 2)
                    U[2][k] -= gadim * du
                    A[2][k] -= gadim * da
                    for i2 in (0, 1):
                        U[0][k][i2] -= gadim * du * x[t][i2]
                        A[0][k][i2] -= gadim * da * x[t][i2]
                    yeni[k] += u[k] * dh[k]
                    for j in range(H):
                        yeni[j] += du * U[1][k][j] + da * A[1][k][j]
                        U[1][k][j] -= gadim * du * onceki[j]
                        A[1][k][j] -= gadim * da * onceki[j]
                dh = yeni
    return P


def dogruluk(P, veri, kapili):
    f = ileri_kapi if kapili else ileri
    return sum(1 for x, y in veri if (f(P, x)[0] >= 0.5) == (y == 1)) / len(veri)


print(f"{'T':>3}{'taban':>8}" + "".join(f"{ad + ' k' + str(k + 1):>12}"
                                        for ad, _, _ in YAPI for k in range(2)))
for T in (2, 4, 8, 12):
    eg = [kes(d, T) for d in EGT]
    sn = [kes(d, T) for d in SIN]
    tb, sat = taban_cizgisi(T), []
    for ad, kurucu, kapili in YAPI:
        for tohum in (TOHUM + 11, TOHUM + 12):
            P = kurucu(tohum)
            (egit_kapi if kapili else egit)(P, eg, 30, 0.05, tohum + 500)
            sat.append(dogruluk(P, sn, kapili) - tb)
    print(f"{T:>3}{tb:>8.4f}" + "".join(f"{u:>+12.4f}" for u in sat))
```

```
  T   taban  yalin 6 k1  yalin 6 k2  yalin 9 k1  yalin 9 k2   kapi 6 k1   kapi 6 k2
  2  0.7200     +0.2300     +0.2800     +0.2350     +0.2800     +0.2250     +0.2650
  4  0.7200     +0.2350     +0.2350     +0.2300     +0.2450     +0.2300     +0.2550
  8  0.7450     +0.2100     +0.1700     +0.2000     +0.1800     +0.1750     +0.1800
 12  0.7100     +0.0250     +0.0050     +0.0100     +0.1700     +0.2650     +0.2050
```

Sayılar tabana göre farktır: etiket son dönemle tanımlı olduğundan her uzunluğun kendi tabanı
vardır. İlk üç satırda üç yapı ayırt edilemez — uzunluk 8'e kadar hepsi tabanı 0,1700 ile 0,2800
arasında geçiyor ve bağımlılık yalın bir dizeyle de taşınabiliyor.

Son satır ayrımı açıyor. 61 parametreli yalın ağ **0,0250** ve **0,0050**'ye, yani tabanın
söylediğine düşüyor; kapı birimli ağ **0,2650** ve **0,2050** veriyor. Bağımlılık yalın 6 birimli
ağda sekiz ile on adım arası taşınıyor, kapı birimli ağda on iki — dizinin tamamı.

Üçüncü çift saklanmaz ve dersin en önemli satırıdır. **Eşit parametre bütçesindeki geniş yalın
ağ on iki adımı iki koşumdan yalnız birinde taşıyor:** 0,0100 ve 0,1700. Kapı birimli ağ iki
koşumda da taşıyor, 0,2650 ve 0,2050. Yön kapıdan yanadır; ama geniş yalın ağın iki koşumu
arasındaki fark **0,1600**'dür, kapı birimli ağınki 0,0600. Eğitimsiz ölçüm kapının kalan payı on
ila yüz kat büyüttüğünü söylemişti; eğitilen ağın sayısı bunu **yön olarak destekliyor, ama iki
koşumla kesinleştirmiyor** — çünkü eğitim, yalın ağın ağırlıklarını da yavaş unutan bir dize
kuracak biçimde uzaklaştırabiliyor.

Kural şudur: bir yapının kattığı fark ancak görev o farkı zorlayacak kadar zorsa ve yeterince
koşumla ölçülürse kesinleşir. Kurgunun sınırı on iki adımdır; daha uzun bir dizide ayrımın
açılması beklenir ama **ölçülmemiş bir beklenti sayılmaz**.

#### Özet

- Kapı birimi durumu $h_t = u_t h_{t-1} + (1 - u_t) a_t$ ile günceller; katsayı sabit değil, o
  adımın girdisinden hesaplanır.
- Aynı 6 birimde kapı birimli ağ 115, yalın ağ 61 parametre tutar; bütçeyi eşitlemek için 118
  parametreli 9 birimli yalın ağ da ölçülür.
- Eğitimsiz ağda uzunluk 12'de kalan pay yalın 6'da yüzde 0,98 ve 0,05, yalın 9'da 0,71 ve 0,05,
  kapı birimlide 9,34 ve 5,63'tür; genişlik unutma hızını değiştirmez.
- Uzunluk 8'e kadar üç yapı da tabanı 0,1700–0,2800 geçer ve ayırt edilemez.
- Uzunluk 12'de yalın 6 birimli ağ 0,0250 ve 0,0050'ye düşer; kapı birimli 0,2650 ve 0,2050,
  geniş yalın 0,0100 ve 0,1700 verir.
- Kapının eşit bütçeli yalın ağa üstünlüğü iki koşumla kesinleşmez: geniş yalın ağ bir koşumda
  dizinin tamamını taşır, ötekinde taşımaz.

#### Sonraki Adım

Kapı birimi uzun bağımlılığı taşıdı, ama taşıma biçimi değişmedi: bilgi hâlâ **tek bir gizli
durumdan** geçmek zorundaydı ve o durum her adımda yeniden yazıldı. Uzak bir adım gerektiğinde
aradaki bütün adımların üzerinden aktarılarak geliyor, doğrudan okunmuyor. Sonraki ders şunu
sorar: ağ, karar anında dizinin **hangi adımına** bakacağını kendisi seçebilseydi ne kazanırdı.
Ölçülecek şey ağırlıkların nereye düştüğüdür: seçimin kaçı doğru adıma gidiyor ve yüksek bir
ağırlık, o adımın kararı gerçekten belirlediği anlamına geliyor mu.

### Dikkat Mekanizması

Source: https://academia.sh/tr/kurslar/derin-ogrenme/dikkat-mekanizmasi

Dizinin uzak bir adımına doğrudan bakmanın ne kazandırdığının ve okunan ağırlıkların ne kadarının açıklama olduğunun ölçülmesi: en sık sınıf tabanı 0,6333 iken aynı dikkat ağının iki koşumu ayrılmış kümede 0,8889 ve 0,9944 veriyor, aradaki 0,1056 yalnız ilklendirme tohumundan geliyor; birinci koşum işaret adımına ağırlığın yalnız 0,2721'ini gönderip en büyük ağırlığı örneklerin 0,3444'ünde doğru adıma koyarken 0,8889 doğruluk üretiyor, ikinci koşum ise 0,9691 ve 1,0000 veriyor. Adım çıkarma sınamasında ağırlık ile etkinin uyumu birinci koşumda 0,5889'da kalıyor; ikinci koşumda ağırlığı 0,5'i aşan 180 örneğin 43'ünde o adımın çıkarılması tahmini 0,05'ten az oynatıyor.

Kapı birimleri bir soruyu çözdü. Yinelemeli bir ağda uzak bir adımdan gelen bilginin yolda
silinmesi engellendi ve taşınabilen bağımlılık uzunluğu ölçüldü. Çözümün biçimi ise değişmedi:
bilgi hâlâ adım adım ilerliyor, her adımda tek bir gizli duruma yazılıyor ve dizinin sonunda o tek
durumdan okunuyordu. Kapı, durumun içine neyin gireceğini düzenledi; durumun kendisini çoğaltmadı.

Bu dersin sorusu bir adım geridedir. Dizinin uzak bir adımına **doğrudan bakmak** ne kazandırır —
çıktı bütün adımları aynı anda görüp hangisine ne kadar ağırlık vereceğini kendisi seçebilseydi
hangi sayı oynardı. İkinci soru birincinin hemen ardından gelir ve bu dersin asıl ölçüsüdür:
seçilen ağırlıklar okunduğunda ağın niçin o cevabı verdiği anlaşılır mı.

- **MI46.** Dizi kurgusu bu derste **yeniden kurulur** ve **kurgudur**: abone başına on iki adımlık
  sayaç okuma dizisi, tohum 20260218, 720 dizi, bölme 360/180/180. `mimariler/04`'ün dizisinde
  işaret hep **ilk dönemdeydi**; ağırlıkların doğru adıma düşüp düşmediği ancak işaretin yeri
  diziden diziye değiştiğinde ölçülebilir, bu yüzden kurgu bu ölçüye göre kurulur.
- **MI47.** Okumalar, abonenin kendi düzeyi ve dönemsel bileşeni çıkarıldıktan sonra kalan sapma
  olarak yazılmıştır. Adım 0 her abonede aynı kalibrasyon okumasıdır ve değeri 0,0'dır.
- **MI48.** Her dizide bir **işaret adımı** vardır; ikinci ile on birinci adım arasında bulunur.
  Etiket yalnız o adımın okumasının 0,35'i aşıp aşmadığına bağlıdır. Öbür on bir adım etikete hiç
  girmez.
- **MI49.** Girdi adım başına iki kanaldır: okuma ve işaret göstergesi. Ağ hangi adımın işaretli
  olduğunu görür, etiketi görmez.
- **MI50.** Taban çizgisi **en sık sınıftır**: her diziye çoğunluk etiketini vermek. M27/K01–K03'ün
  tablo tabanı 0,7579 başka bir görevin sayısıdır ve buraya taşınmaz.
- **MI51.** Dikkat katmanı ders içinde yazılır ve **modeldir**. Sorgu tek ve öğrenilir; anahtar ile
  değer doğrusal izdüşümle üretilir; ağırlıklar yumuşak enbüyükle normalleştirilir.
- **MI52.** Eğitim tam toplu eğim inişidir: 200 tur, öğrenme adımı 0,6. Eğim inişi yordamı M27/K03
  `dogrusal-modeller` konusunda kuruldu ve tekrarlanmaz.
- **MI53.** Her sayı **iki koşumla** basılır ve koşumlar yalnız ilklendirme tohumunda ayrılır. Bu
  kursun üçüncü sayısı budur.
- **MI54.** Nedensellik ölçüsü **adım çıkarmadır**: bir adım dikkat dağılımından düşürülür, kalan
  ağırlıklar yeniden normalleştirilir ve çıktı olasılığının ne kadar oynadığı basılır.

#### Dizi Kurgusu ve Tabanı

Görev kasten dar seçilmiştir. Etiketi belirleyen tek bir adım vardır ve o adım işaretlidir; ağın
yapması gereken tek şey işaretli adımı bulup okumasını eşikle karşılaştırmaktır. Böyle bir görevde
"doğru adıma mı baktı" sorusunun kesin bir cevabı olur, çünkü doğru adım veriyi üreten kurguda
yazılıdır.

```python
# ORTAK — MODELDIR. KURGU dizi kumesi: abone basina 12 adimlik sayac okuma dizisi.
import math

TOHUM, M32, ADIM = 20260218, 0xFFFFFFFF, 12
BOLGE = [("kuzey", 0.28, 21), ("guney", 0.22, 17), ("dogu", 0.18, 26),
         ("bati", 0.14, 14), ("merkez", 0.18, 23)]


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


def ayrik(u, w):
    t = 0.0
    for i, x in enumerate(w):
        t += x
        if u < t:
            return i
    return len(w) - 1


def dizi_kur(n, tohum):
    D = []
    for i in range(n):
        r = uretec(tohum + i)
        b = BOLGE[ayrik(r(), [x[1] for x in BOLGE])]
        oku = [0.0] + [round((r() + r() + r() - 1.5) * 1.9, 3) for _ in range(ADIM - 1)]
        m = 2 + int(r() * (ADIM - 2))
        D.append({"oku": oku, "isaret": m, "y": 1 if oku[m] > 0.35 else 0, "bolge": b[0]})
    return D


VERI = dizi_kur(720, TOHUM)
EGT, DOG, SIN = VERI[:360], VERI[360:540], VERI[540:]
oran = sum(x["y"] for x in SIN) / len(SIN)
TABAN = max(oran, 1 - oran)
print(f"dizi {len(VERI)}, uzunluk {ADIM}, bolme {len(EGT)}/{len(DOG)}/{len(SIN)}")
print(f"pozitif oran egitim {sum(x['y'] for x in EGT) / len(EGT):.4f}, "
      f"ayrilmis {oran:.4f}")
print(f"taban cizgisi (en sik sinif) {TABAN:.4f}")
print(f"esigi asan adimi olan dizi orani "
      f"{sum(any(x['oku'][t] > 0.35 for t in range(2, ADIM)) for x in VERI) / len(VERI):.4f}")
print(f"en buyuk okuma isaret adimina dusuyor mu "
      f"{sum(max(range(2, ADIM), key=lambda t: x['oku'][t]) == x['isaret'] for x in SIN) / len(SIN):.4f}")
```

```
dizi 720, uzunluk 12, bolme 360/180/180
pozitif oran egitim 0.3806, ayrilmis 0.3667
taban cizgisi (en sik sinif) 0.6333
esigi asan adimi olan dizi orani 0.9903
en buyuk okuma isaret adimina dusuyor mu 0.0611
```

Son iki satır görevin gerçekten dizinin içine bakmayı gerektirdiğini gösterir. Dizilerin
0,9903'ünde eşiği aşan en az bir adım vardır, yani "herhangi bir yerde yüksek okuma var mı" sorusu
neredeyse her dizide evet der ve hiçbir şey ayırt etmez. En büyük okumaya bakmak da işe yaramaz:
dizinin en yüksek adımı ile işaret adımı ayrılmış kümenin yalnız 0,0611'inde çakışır. Ağın
seçmesi gereken adım ne en büyüktür ne de sabit bir yerdedir.

Taban çizgisi 0,6333'tür. Ayrılmış kümedeki pozitif oran 0,3667 olduğu için her diziye olumsuz
etiketi vermek bu sayıyı verir. Bu, öğrenmeyen en yalın yordamdır ve bundan sonraki her sayı onunla
yan yana okunur.

#### Sorgu, Anahtar ve Değer

Dikkat üç izdüşümle tanımlanır. Her adım kendi girdisinden bir **anahtar** ve bir **değer** üretir;
çıktıyı üretecek taraf bir **sorgu** taşır. Sorgu ile anahtarın iç çarpımı o adımın ne kadar ilgili
olduğunu veren bir puandır, puanlar yumuşak enbüyükten geçirilerek toplamı bire eşit ağırlıklara
çevrilir ve çıktı, değerlerin bu ağırlıklarla ortalamasıdır. İç çarpım anahtar boyutunun kareköküne
bölünür; $\sqrt{d}$ ile bölme, boyut büyüdükçe puanların da büyüyüp yumuşak enbüyüğü doyurmasını
engeller.

Sınıflandırmada sorgunun bir adımdan gelmesi gerekmez; tek bir öğrenilen sorgu yeterlidir. Ağ
"hangi adım bu karar için önemli" sorusunu bir kez sorar ve dizinin tamamından tek bir özet alır.
Gizli durum yoktur, yineleme yoktur, adımlar arasında sıra bağı yoktur.

```python
DK = DV = 3
OL = 1.0 / math.sqrt(DK)
GIR = [([[x["oku"][t], 1.0 if t == x["isaret"] else 0.0] for t in range(ADIM)],
        x["y"], x["isaret"]) for x in VERI]
EG, SG = GIR[:360], GIR[540:]


def ileri(P, X, atla=None):
    K = [[P["Wk"][i][0] * x[0] + P["Wk"][i][1] * x[1] for i in range(DK)] for x in X]
    V = [[P["Wv"][i][0] * x[0] + P["Wv"][i][1] * x[1] for i in range(DV)] for x in X]
    s = [sum(P["q"][i] * k[i] for i in range(DK)) * OL for k in K]
    d = [t for t in range(ADIM) if t != atla]
    mx = max(s[t] for t in d)
    e = [math.exp(s[t] - mx) if t in d else 0.0 for t in range(ADIM)]
    z = sum(e)
    a = [u / z for u in e]
    c = [sum(a[t] * V[t][i] for t in d) for i in range(DV)]
    return K, V, a, c, sum(P["w"][i] * c[i] for i in range(DV)) + P["b"]


def egit(tohum, tur=200, adim=0.6):
    r = uretec(tohum)
    g = lambda: (r() + r() + r() - 1.5) * 0.9
    P = {"Wk": [[g(), g()] for _ in range(DK)], "Wv": [[g(), g()] for _ in range(DV)],
         "q": [g() for _ in range(DK)], "w": [g() for _ in range(DV)], "b": 0.0}
    for _ in range(tur):
        gWk = [[0.0, 0.0] for _ in range(DK)]
        gWv = [[0.0, 0.0] for _ in range(DV)]
        gq, gw, gb = [0.0] * DK, [0.0] * DV, 0.0
        for X, y, _m in EG:
            K, V, a, c, o = ileri(P, X)
            d = 1.0 / (1.0 + math.exp(-max(-30.0, min(30.0, o)))) - y
            for i in range(DV):
                gw[i] += d * c[i]
            gb += d
            da = [sum(d * P["w"][i] * V[t][i] for i in range(DV)) for t in range(ADIM)]
            orta = sum(a[t] * da[t] for t in range(ADIM))
            for t in range(ADIM):
                ds = a[t] * (da[t] - orta) * OL
                for i in range(DK):
                    gq[i] += ds * K[t][i]
                    gWk[i][0] += ds * P["q"][i] * X[t][0]
                    gWk[i][1] += ds * P["q"][i] * X[t][1]
                for i in range(DV):
                    gWv[i][0] += d * a[t] * P["w"][i] * X[t][0]
                    gWv[i][1] += d * a[t] * P["w"][i] * X[t][1]
        n = len(EG)
        for i in range(DK):
            P["q"][i] -= adim * gq[i] / n
            P["Wk"][i][0] -= adim * gWk[i][0] / n
            P["Wk"][i][1] -= adim * gWk[i][1] / n
        for i in range(DV):
            P["w"][i] -= adim * gw[i] / n
            P["Wv"][i][0] -= adim * gWv[i][0] / n
            P["Wv"][i][1] -= adim * gWv[i][1] / n
        P["b"] -= adim * gb / n
    return P


def dogruluk(P, G):
    return sum((ileri(P, X)[4] > 0) == (y == 1) for X, y, _ in G) / len(G)


AG = [egit(TOHUM + 1), egit(TOHUM + 2)]
print(f"parametre sayisi {DK * 2 + DV * 2 + DK + DV + 1}, tur 200, "
      f"egitim ornegi {len(EG)}")
print(f"taban cizgisi (en sik sinif)   {TABAN:.4f}")
for i, P in enumerate(AG):
    print(f"dikkat agi kosum {i + 1}            egitim {dogruluk(P, EG):.4f}   "
          f"ayrilmis {dogruluk(P, SG):.4f}")
print(f"iki kosum arasindaki fark      {abs(dogruluk(AG[0], SG) - dogruluk(AG[1], SG)):.4f}")
```

```
parametre sayisi 19, tur 200, egitim ornegi 360
taban cizgisi (en sik sinif)   0.6333
dikkat agi kosum 1            egitim 0.9028   ayrilmis 0.8889
dikkat agi kosum 2            egitim 0.9889   ayrilmis 0.9944
iki kosum arasindaki fark      0.1056
```

Üç sayı tablodadır. Taban 0,6333; dikkat ağı ayrılmış kümede 0,8889 ve 0,9944. On dokuz parametre
uzunluğu on iki olan bir dizide doğru adımı bulmayı öğrenmekte ve tabanın en az 0,2556 üstüne
çıkmaktadır. Aynı işi yinelemeli bir ağ ancak on iki adım boyunca durum taşıyarak yapabilirdi.

Üçüncü sayı ikinciden daha çok şey söyler. İki koşum aynı kapasiteyi, aynı veriyi ve aynı tur
bütçesini paylaşır; yalnız ilklendirme tohumları ayrıdır. Aradaki fark 0,1056'dır — bu ağın
ayrılmış küme sayısının yaklaşık dokuzda biri, ağın ne olduğundan değil, o koşumda nereden
başladığından gelmektedir. Kursun kuralı burada doğrudan okunur: bir ağın sayısı kapasitesinden
değil eğitiminden gelebilir.

#### Ağırlıklar Nereye Düşüyor

Dikkatin ürettiği ağırlık vektörü ağın içindeki tek okunabilir ara üründür: her adım için bir sayı
verir ve toplamları bire eşittir. Bu okunabilirlik, ağırlıkların sık sık "modelin neye baktığı"
diye sunulmasının nedenidir. Kurgu bu iddiayı sınamaya elverişlidir, çünkü doğru adım bilinmektedir.

```python
def dikkat_olcu(P, G):
    kutle, isabet = 0.0, 0
    for X, _y, m in G:
        a = ileri(P, X)[2]
        kutle += a[m]
        isabet += max(range(ADIM), key=lambda t: a[t]) == m
    return kutle / len(G), isabet / len(G)


print(f"tekduze dagilimda bir adimin agirligi {1 / ADIM:.4f}")
print(f"{'':16}{'isaret adimina dusen':>21}{'en buyuk agirlik':>18}{'ayrilmis':>10}")
for i, P in enumerate(AG):
    k, s = dikkat_olcu(P, SG)
    print(f"kosum {i + 1:<10}{k:>21.4f}{s:>18.4f}{dogruluk(P, SG):>10.4f}")

X0, _y0, m0 = SG[0]
a0 = ileri(AG[0], X0)[2]
a1 = ileri(AG[1], X0)[2]
print(f"tek ornek, isaret adimi {m0}")
print("kosum 1 agirliklari " + " ".join(f"{u:.2f}" for u in a0))
print("kosum 2 agirliklari " + " ".join(f"{u:.2f}" for u in a1))
```

```
tekduze dagilimda bir adimin agirligi 0.0833
                 isaret adimina dusen  en buyuk agirlik  ayrilmis
kosum 1                        0.2721            0.3444    0.8889
kosum 2                        0.9691            1.0000    0.9944
tek ornek, isaret adimi 11
kosum 1 agirliklari 0.00 0.00 0.10 0.00 0.01 0.01 0.00 0.29 0.31 0.00 0.10 0.18
kosum 2 agirliklari 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.97
```

İkinci koşum beklenen davranışı gösterir: ağırlığın 0,9691'i işaret adımına düşer ve en büyük
ağırlık ayrılmış kümenin tamamında doğru adımdadır. Tekdüze bir dağılımda bir adımın payı 0,0833
olduğuna göre bu, tabanın on bir katından fazlasıdır.

Birinci koşum aynı görevi 0,8889 doğrulukla çözer, ama ağırlığın yalnız 0,2721'ini işaret adımına
gönderir ve en büyük ağırlığı örneklerin 0,3444'ünde doğru adıma koyar. Tek örnek satırı bunun
nasıl mümkün olduğunu gösterir: işaret adımı on birinci adımdır, koşum 1 oraya 0,18 verir ve
kalanı yedinci ile sekizinci adımlara dağıtır. Ağ, işaret kanalını kısmen kullanıp geri kalan
ağırlığı okuması yüksek adımlara yayan bir uzlaşma bulmuştur ve bu uzlaşma vakaların çoğunda doğru
cevabı üretmektedir. Doğruluk 0,8889 iken ağırlıkların doğru adıma isabeti 0,3444'tür; iki sayı
arasında hiçbir zorunlu bağ yoktur.

#### Yüksek Ağırlık Nedensellik Değildir

Bir ağırlığın büyük olması, o adımın çıktıyı belirlediği anlamına gelmez. İkisinin aynı şey olup
olmadığı ancak bir müdahaleyle sınanabilir: adım dikkat dağılımından düşürülür, kalan ağırlıklar
yeniden normalleştirilir ve çıktı olasılığının ne kadar oynadığına bakılır. Bu, ağırlığın
büyüklüğünden bağımsız bir ölçüdür.

```python
def olasilik(P, X, atla=None):
    o = ileri(P, X, atla)[4]
    return 1.0 / (1.0 + math.exp(-max(-30.0, min(30.0, o))))


def nedensellik(P, G, esik=0.05):
    uyum, yuksek, yuksek_etkisiz, orta_etki = 0, 0, 0, 0.0
    for X, _y, _m in G:
        a = ileri(P, X)[2]
        p0 = olasilik(P, X)
        etki = [abs(olasilik(P, X, t) - p0) for t in range(ADIM)]
        ta = max(range(ADIM), key=lambda t: a[t])
        uyum += ta == max(range(ADIM), key=lambda t: etki[t])
        orta_etki += etki[ta]
        if a[ta] > 0.5:
            yuksek += 1
            yuksek_etkisiz += etki[ta] < esik
    n = len(G)
    return uyum / n, orta_etki / n, yuksek, yuksek_etkisiz


print(f"{'':10}{'agirlik-etki uyumu':>19}{'en agir adimin etkisi':>23}"
      f"{'agirlik>0,5':>13}{'ama etki<0,05':>15}")
for i, P in enumerate(AG):
    u, e, y, ye = nedensellik(P, SG)
    print(f"kosum {i + 1:<4}{u:>19.4f}{e:>23.4f}{y:>13d}{ye:>15d}")
```

```
           agirlik-etki uyumu  en agir adimin etkisi  agirlik>0,5  ama etki<0,05
kosum 1                0.5889                 0.3318           81             27
kosum 2                1.0000                 0.4081          180             43
```

Birinci koşumda en ağır adım ile en etkili adım örneklerin yalnız 0,5889'unda aynıdır. Yani
ağırlık sıralamasını okuyup "model buraya baktı" diyen biri, on örnekten dördünde ağın çıktısını
gerçekte belirleyen adımı kaçırır. İkinci koşumda uyum 1,0000'dır. Aynı mimari, aynı veri, aynı
bütçe; ağırlıkların açıklama değeri koşumdan koşuma değişmektedir. Ağırlıklara bakan biri hangi
koşumda olduğunu ağırlıklardan anlayamaz — her iki koşum da yoğunlaşmış, düzenli görünen dağılımlar
üretir.

Son sütun ikinci koşumun kendi içinde de bir sınır olduğunu gösterir. Ayrılmış kümenin tamamında
en büyük ağırlık 0,5'i aşar, ama bu 180 örneğin 43'ünde o adımın çıkarılması tahmin olasılığını
0,05'ten az oynatır. Neden açıktır: dizinin geri kalan adımları da düşük okumalar taşıyorsa, işaret
adımı düşürüldüğünde ortalama aynı tarafta kalır ve karar değişmez. Yüksek ağırlık burada "bu adım
karara gitti" demek değil, "bu adım okundu" demektir.

Buradan çıkan kural şudur: dikkat ağırlıkları hata ayıklamada işe yarar bir ara üründür, tek
başlarına bir gerekçe belgesi değildir. Yanına ya bir çıkarma sınaması ya da koşum değişkenliği
yazılmayan ağırlık ölçülmemiş bir sayıdır.

#### Özet

- Dizi kurgusu bu derste kuruldu ve kurgudur: 720 dizi, uzunluk 12, bölme 360/180/180, tohum
  20260218; etiket yalnız işaret adımının okumasına bağlıdır.
- Taban çizgisi en sık sınıftır ve 0,6333'tür; on dokuz parametreli dikkat ağı ayrılmış kümede
  0,8889 ve 0,9944 verir, iki koşum arasındaki fark 0,1056'dır.
- Dikkat, sorgu ile anahtarın iç çarpımını $\sqrt{d}$ ile ölçekleyip yumuşak enbüyükten geçirir ve
  değerlerin ağırlıklı ortalamasını üretir; gizli durum ve yineleme yoktur.
- Ağırlıkların nereye düştüğü doğrulukla aynı şey değildir: birinci koşum 0,8889 doğrulukla işaret
  adımına ağırlığın 0,2721'ini gönderir ve en büyük ağırlığı 0,3444 isabetle koyar.
- Adım çıkarma sınamasında ağırlık ile etkinin uyumu birinci koşumda 0,5889'dur ve ikinci koşumda
  ağırlığı 0,5'i aşan 180 örneğin 43'ünde o adımın çıkarılması tahmini 0,05'ten az oynatır.

#### Sonraki Adım

Bu derste tek bir sorgu, tek bir ağırlık dağılımı üretti ve dizi tek bir özete indirildi. Kurgunun
görevi buna elverişliydi: etiket tek bir adımdan okunuyordu ve adımların sırası hiç işe
karışmıyordu. İki soru açık kalıyor. Birincisi, aynı dizide birden çok ilgi kalıbı varsa — biri
işaret adımını, öbürü genel düzeyi arıyorsa — tek dağılım ikisini taşıyabilir mi. İkincisi ve daha
keskini: dikkat bütün adımlara aynı anda baktığına göre adımların sırasını nereden bilecek. Sonraki
ders sorguyu çoğaltır, baş sayısının kattığı farkı ölçer ve konum kodlaması çıkarıldığında sıra
bilgisinin ne kadarının kaldığını aynı tabana karşı basar.

### Çok Başlı Dikkat ve Dönüştürücüler

Source: https://academia.sh/tr/kurslar/derin-ogrenme/cok-basli-dikkat-ve-donusturuculer

Sorgunun çoğaltılmasının ve konum kodlamasının aynı parametre bütçesinde ne kattığının ölçülmesi: 33 parametre sabit tutulup baş sayısı 1, 2 ve 4 yapıldığında ayrılmış küme ortalaması 0,8722, 0,8806 ve 0,8972 oluyor, yani baş sayısının kattığı 0,0250 iken tek bir kurulumun iki koşumu arasındaki fark 0,0500'e çıkıyor. İki başlı ağın ikinci koşumu başları dizinin iki ucuna ayırıyor (ağırlık merkezleri 3,30 ve 8,55, ayrıklık 0,7264) ama birinci koşum ayırmıyor (5,57 ve 6,30) ve doğruluğu düşmüyor. Konum kodlaması çıkarıldığında iki koşum da tam olarak taban çizgisine, 0,6611'e iniyor ve okumalar karıştırıldığında çıktı 0,0000 oynuyor.

Dikkat katmanı tek bir sorgu taşıdı ve dizinin tamamını tek bir ağırlık dağılımına indirdi. Görev
buna elverişliydi: etiket tek bir adımdan okunuyordu ve adımların hangi sırada geldiği hiçbir
şeyi değiştirmiyordu. Gerçek dizilerde iki şey birden değişir. Bir karar çoğu zaman dizinin birden
çok yerinden okunan bilginin birleşiminden çıkar ve o bilginin nerede durduğu bilginin kendisi
kadar önemlidir.

Bu ders iki eklemeyi ölçer. Birincisi sorgunun çoğaltılmasıdır: aynı iç boyut birden çok **başa**
bölünür, her baş kendi ağırlık dağılımını üretir ve çıktılar birleştirilir. İkincisi **konum
kodlamasıdır**: adımın dizideki yeri, girdinin yanına bir sayı olarak eklenir. Bu ikisi, adım başına
bir izdüşüm ve atlamalı bağlantılarla birlikte **dönüştürücü mimarinin** taşıyıcı parçalarıdır —
yinelemesiz, bütün adımlara aynı anda bakan bir yapı. Burada yalnız taşıyıcı iki parça yazılır ve
ölçülür.

- **MI55.** Bu konunun dizi kurgusu `mimariler/06`'da kuruldu ve **kurgudur**: 720 dizi, uzunluk 12,
  tohum 20260218. Aynı diziler aynı tohumla yeniden üretilir.
- **MI56.** Bu dersin sorusu ayrıdır ve **sıraya bağlıdır**: etiket, yedinci ile on birinci adımın
  ortalamasının birinci ile beşinci adımın ortalamasını 0,30'dan fazla aşıp aşmadığıdır. Altıncı
  adım iki bölgenin dışında bırakılır.
- **MI57.** Taban çizgisi yine **en sık sınıftır**. Etiket iki bölgenin farkından okunduğu için
  dizinin genel düzeyi tabanı geçmeye yetmez.
- **MI58.** Konum kodlaması bir sinüs ve bir kosinüs kanalıdır: adım $t$ için
  $\sin(\pi t / 11)$ ve $\cos(\pi t / 11)$. Tek frekans ölçeği küçük tutmak için seçilmiştir;
  gerçek kurulumlar birden çok frekans kullanır.
- **MI59.** Karşılaştırma **eşit parametre bütçesindedir**. Toplam iç boyut 4'te sabittir ve baş
  sayısı arttıkça baş başına boyut küçülür. Parametre sayısı üç kurulumda da aynıdır.
- **MI60.** Katman ders içinde yazılır ve **modeldir**. Kitaplık çağrılmaz.
- **MI61.** Eğitim **momentumlu iniştir**: 150 tur, öğrenme adımı 0,15, momentum 0,8. Momentum
  M27/K05 `sinir-agi-temelleri` konusunda kuruldu ve burada tekrarlanmaz.
- **MI62.** Her kurulum **iki koşumla** basılır; koşumlar yalnız ilklendirme tohumunda ayrılır.
- **MI63.** Sıra sınaması şudur: bir dizinin **okumaları** kendi aralarında karıştırılır, konum
  kanalları yerinde bırakılır ve çıktı olasılığının ne kadar oynadığı ölçülür.

#### Aynı Bütçe, Farklı Baş Sayısı

Önceki dersin dizileri aynen kullanılır, soru değişir. Yeni etiket iki bölgenin ortalaması
arasındaki farktan okunduğu için tek bir ağırlıklı ortalamayla üretilmesi zordur: bir dizi ortalama
iki bölgeyi ayıramaz.

```python
# ORTAK — MODELDIR. `mimariler/06`'da kurulan KURGU dizi kumesi ayni tohumla yeniden uretilir.
import math

TOHUM, M32, ADIM = 20260218, 0xFFFFFFFF, 12


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


def dizi_kur(n, tohum):
    D = []
    for i in range(n):
        r = uretec(tohum + i)
        r()  # bolge cekilisi: bu derste kullanilmaz, dizi ayni kalsin diye tuketilir
        oku = [0.0] + [round((r() + r() + r() - 1.5) * 1.9, 3) for _ in range(ADIM - 1)]
        r()
        D.append({"oku": oku})
    return D


VERI = dizi_kur(720, TOHUM)
ILK, SON = range(1, 6), range(7, 12)
for x in VERI:
    a = sum(x["oku"][t] for t in ILK) / 5
    b = sum(x["oku"][t] for t in SON) / 5
    x["y"] = 1 if b - a > 0.30 else 0
EGT, SIN = VERI[:200], VERI[540:]
oran = sum(x["y"] for x in SIN) / len(SIN)
TABAN = max(oran, 1 - oran)
print(f"dizi {len(VERI)}, uzunluk {ADIM}, egitim {len(EGT)}, ayrilmis {len(SIN)}")
print(f"artis etiketi orani egitim {sum(x['y'] for x in EGT) / len(EGT):.4f}, "
      f"ayrilmis {oran:.4f}")
print(f"taban cizgisi (en sik sinif) {TABAN:.4f}")
print(f"ornek dizi {VERI[0]['oku']}")
```

```
dizi 720, uzunluk 12, egitim 200, ayrilmis 180
artis etiketi orani egitim 0.3150, ayrilmis 0.3389
taban cizgisi (en sik sinif) 0.6611
ornek dizi [0.0, 0.893, -0.222, -0.542, -0.404, -1.114, 0.234, -1.03, -1.493, 0.534, -1.807, 0.05]
```

Çok başlı dikkatte her baş kendi anahtar, değer ve sorgu izdüşümüne sahiptir. Toplam iç boyut
sabit tutulduğu için baş sayısı iki katına çıktığında baş başına boyut yarıya iner; parametre
sayısı değişmez. Karşılaştırmanın anlamı buradadır — kazanç varsa kapasiteden değil, aynı
kapasitenin **bölünme biçiminden** gelir.

```python
DTOP, DIN = 4, 3


def girdi(x, kod=True):
    K = [[math.sin(math.pi * t / (ADIM - 1)), math.cos(math.pi * t / (ADIM - 1))]
         for t in range(ADIM)]
    return [[x["oku"][t]] + (K[t] if kod else [0.0, 0.0]) for t in range(ADIM)]


def ilklendir(tohum, H):
    d = DTOP // H
    r = uretec(tohum)
    g = lambda: (r() + r() + r() - 1.5) * 0.9
    return {"H": H, "d": d, "ol": 1.0 / math.sqrt(d),
            "Wk": [[[g() for _ in range(DIN)] for _ in range(d)] for _ in range(H)],
            "Wv": [[[g() for _ in range(DIN)] for _ in range(d)] for _ in range(H)],
            "q": [[g() for _ in range(d)] for _ in range(H)],
            "w": [g() for _ in range(DTOP)], "b": [0.0]}


def agirlik(P, X, h):
    # sorgu ile anahtar izdusumu tek bir yone katlanir: u = q^T Wk
    d, wk, q = P["d"], P["Wk"][h], P["q"][h]
    u = [sum(q[i] * wk[i][j] for i in range(d)) for j in range(DIN)]
    s = [(u[0] * x[0] + u[1] * x[1] + u[2] * x[2]) * P["ol"] for x in X]
    mx = max(s)
    e = [math.exp(v - mx) for v in s]
    z = sum(e)
    return [v / z for v in e]


def bas(P, X, h):
    a = agirlik(P, X, h)
    Xa = [sum(a[t] * X[t][j] for t in range(ADIM)) for j in range(DIN)]
    return a, Xa, [sum(P["Wv"][h][i][j] * Xa[j] for j in range(DIN))
                   for i in range(P["d"])]


def ileri(P, X):
    d, o = P["d"], P["b"][0]
    for h in range(P["H"]):
        c = bas(P, X, h)[2]
        o += sum(P["w"][h * d + i] * c[i] for i in range(d))
    return o


def egit(tohum, H, EG, tur=150, adim=0.15, mom=0.8):
    P = ilklendir(tohum, H)
    d, ol, n, hiz = P["d"], P["ol"], len(EG), None
    for _ in range(tur):
        gWk = [[[0.0] * DIN for _ in range(d)] for _ in range(H)]
        gWv = [[[0.0] * DIN for _ in range(d)] for _ in range(H)]
        gq = [[0.0] * d for _ in range(H)]
        gw, gb = [0.0] * DTOP, [0.0]
        for X, y in EG:
            B = [bas(P, X, h) for h in range(H)]
            o = P["b"][0] + sum(P["w"][h * d + i] * B[h][2][i]
                                for h in range(H) for i in range(d))
            df = 1.0 / (1.0 + math.exp(-max(-30.0, min(30.0, o)))) - y
            gb[0] += df
            for h in range(H):
                a, Xa, c = B[h]
                dc = [df * P["w"][h * d + i] for i in range(d)]
                mv = [sum(dc[i] * P["Wv"][h][i][j] for i in range(d)) for j in range(DIN)]
                da = [mv[0] * x[0] + mv[1] * x[1] + mv[2] * x[2] for x in X]
                orta = sum(a[t] * da[t] for t in range(ADIM))
                S = [0.0, 0.0, 0.0]
                for t in range(ADIM):
                    ds, x = a[t] * (da[t] - orta) * ol, X[t]
                    S[0] += ds * x[0]
                    S[1] += ds * x[1]
                    S[2] += ds * x[2]
                for i in range(d):
                    gw[h * d + i] += df * c[i]
                    gq[h][i] += sum(P["Wk"][h][i][j] * S[j] for j in range(DIN))
                    for j in range(DIN):
                        gWk[h][i][j] += P["q"][h][i] * S[j]
                        gWv[h][i][j] += dc[i] * Xa[j]
        par = [P["Wk"][h][i] for h in range(H) for i in range(d)] \
            + [P["Wv"][h][i] for h in range(H) for i in range(d)] \
            + P["q"] + [P["w"], P["b"]]
        egm = [gWk[h][i] for h in range(H) for i in range(d)] \
            + [gWv[h][i] for h in range(H) for i in range(d)] + gq + [gw, gb]
        if hiz is None:
            hiz = [[0.0] * len(u) for u in par]
        for u, v, g in zip(par, egm, hiz):   # momentumlu inis
            for i in range(len(u)):
                g[i] = mom * g[i] - adim * v[i] / n
                u[i] += g[i]
    return P


def dogruluk(P, G):
    return sum((ileri(P, X) > 0) == (y == 1) for X, y in G) / len(G)


GK = [(girdi(x), x["y"]) for x in VERI]
EG, SG = GK[:200], GK[540:]
AG = {}
print(f"toplam ic boyut {DTOP}, tur 150, egitim ornegi {len(EG)}, "
      f"taban cizgisi {TABAN:.4f}")
print(f"{'bas':>4}{'bas boyutu':>12}{'parametre':>11}{'kosum 1':>10}{'kosum 2':>10}"
      f"{'ortalama':>10}{'kosum farki':>13}")
for H in (1, 2, 4):
    AG[H] = [egit(TOHUM + k, H, EG) for k in (1, 2)]
    a, b = (dogruluk(P, SG) for P in AG[H])
    print(f"{H:>4}{DTOP // H:>12}{2 * DTOP * DIN + 2 * DTOP + 1:>11}{a:>10.4f}"
          f"{b:>10.4f}{(a + b) / 2:>10.4f}{abs(a - b):>13.4f}")
```

```
toplam ic boyut 4, tur 150, egitim ornegi 200, taban cizgisi 0.6611
 bas  bas boyutu  parametre   kosum 1   kosum 2  ortalama  kosum farki
   1           4         33    0.8889    0.8556    0.8722       0.0333
   2           2         33    0.8778    0.8833    0.8806       0.0056
   4           1         33    0.8722    0.9222    0.8972       0.0500
```

Ortalamalar tek yönde ilerliyor: 0,8722, 0,8806, 0,8972. Baş sayısını birden dörde çıkarmak
ayrılmış küme sayısına 0,0250 katıyor ve taban çizgisinin 0,2361 üstüne taşıyor. Sağdaki sütun
kazancı bağlama oturtuyor: dört başlı kurulumun iki koşumu arasındaki fark 0,0500, yani baş
sayısının kattığının iki katı. Aynı kapasiteyi başlara bölmenin getirdiği fark, o bölmenin
kendisini yeniden koşmanın getirdiği farktan küçüktür. Baş sayısı bu ölçekte bir ayar değişkenidir
ve tek koşumla seçilirse yanlış seçilir.

#### Başlar Neye Bakıyor

Baş sayısının niçin bir şey kattığı ağırlıkların nereye düştüğüne bakılarak sorulabilir. Görev iki
bölgenin ortalamasını istiyor; başlar bu iki bölgeye ayrılıyorsa yapı görevin biçimini bulmuş
demektir. Ölçü iki sayıdır: her başın ağırlık merkezi ve başlar arası ayrıklık — iki dağılım
arasındaki farkın yarısı, sıfırdan bire.

```python
def merkez(P, G, h):
    return sum(sum(t * agirlik(P, X, h)[t] for t in range(ADIM)) for X, _ in G) / len(G)


def ayriklik(P, G):
    H, s = P["H"], 0.0
    if H < 2:
        return 0.0
    for X, _ in G:
        A = [agirlik(P, X, h) for h in range(H)]
        for i in range(H):
            for j in range(i + 1, H):
                s += sum(abs(A[i][t] - A[j][t]) for t in range(ADIM)) / 2
    return s / (len(G) * H * (H - 1) / 2)


print(f"gorevin istedigi iki bolge: adim {min(ILK)}-{max(ILK)} ve {min(SON)}-{max(SON)}")
print(f"{'':18}{'agirlik merkezleri':>34}{'ayriklik':>10}{'ayrilmis':>10}")
for H in (1, 2, 4):
    for k in (0, 1):
        P = AG[H][k]
        m = ", ".join(f"{merkez(P, SG, h):.2f}" for h in range(H))
        print(f"{H} bas, kosum {k + 1:<5}{m:>34}{ayriklik(P, SG):>10.4f}"
              f"{dogruluk(P, SG):>10.4f}")
```

```
gorevin istedigi iki bolge: adim 1-5 ve 7-11
                                  agirlik merkezleri  ayriklik  ayrilmis
1 bas, kosum 1                                  5.51    0.0000    0.8889
1 bas, kosum 2                                  6.02    0.0000    0.8556
2 bas, kosum 1                            5.57, 6.30    0.4096    0.8778
2 bas, kosum 2                            3.30, 8.55    0.7264    0.8833
4 bas, kosum 1                5.84, 5.48, 5.79, 5.61    0.4782    0.8722
4 bas, kosum 2                3.24, 5.81, 8.37, 4.59    0.4291    0.9222
```

İki başlı kurulumun ikinci koşumu tam beklenen ayrımı yapıyor: bir baş 3,30'da, öbürü 8,55'te
duruyor ve bu iki nokta görevin istediği iki bölgenin ortasına düşüyor. Ayrıklık 0,7264, yani iki
dağılım büyük ölçüde ayrı adımlara bakıyor.

Aynı kurulumun birinci koşumu bunu yapmıyor. Başlar 5,57 ve 6,30'da, ikisi de dizinin ortasında
duruyor ve ayrıklık 0,4096'da kalıyor. Buna karşın ayrılmış küme sayısı 0,8778 — ayıran koşumdan
yalnız 0,0055 aşağıda. Aynı gözlem dört başlı kurulumda daha da nettir: birinci koşumun dört başı
5,48 ile 5,84 arasında sıkışmışken doğruluğu 0,8722'dir. Yapının "görevin biçimini bulması"
mimariden değil koşumdan gelmektedir ve bulmamış bir koşum da yakın bir sayı üretebilmektedir.

#### Konum Kodlaması Bir İyileştirme Değil, Önkoşuldur

Dikkat bütün adımlara aynı anda bakar ve adımlar arasında hiçbir sıra bağı taşımaz. Bir adımın
girdisinde yerine dair bir sayı yoksa, katman için dizi bir **çokluk kümesidir**: aynı okumaların
başka sırayla gelmesi aynı çıktıyı verir. Bu bir başarım kaybı değil, bilginin yokluğudur ve
doğrudan sınanabilir.

```python
def okumalari_karistir(X, tohum):
    r, s = uretec(tohum), list(range(ADIM))
    for i in range(ADIM - 1, 0, -1):
        j = int(r() * (i + 1))
        s[i], s[j] = s[j], s[i]
    return [[X[s[t]][0], X[t][1], X[t][2]] for t in range(ADIM)]


def olasilik(P, X):
    return 1.0 / (1.0 + math.exp(-max(-30.0, min(30.0, ileri(P, X)))))


def sira_sinamasi(P, G):
    e, en = 0.0, 0.0
    for i, (X, _y) in enumerate(G):
        d = abs(olasilik(P, okumalari_karistir(X, TOHUM + 4000 + i)) - olasilik(P, X))
        e, en = e + d, max(en, d)
    return e / len(G), en


TUM = [(girdi(x, False), x["y"]) for x in VERI]
KOD = [egit(TOHUM + k, 2, TUM[:200]) for k in (1, 2)]
print(f"taban cizgisi (en sik sinif) {TABAN:.4f}")
print(f"{'':28}{'kosum 1':>9}{'kosum 2':>9}{'ort |degisim|':>15}{'en buyuk':>10}")
for ad, M, G in (("konum kodlamasi var", AG[2], SG), ("konum kodlamasi yok", KOD, TUM[540:])):
    e, en = sira_sinamasi(M[1], G)
    print(f"{ad:<28}{dogruluk(M[0], G):>9.4f}{dogruluk(M[1], G):>9.4f}"
          f"{e:>15.4f}{en:>10.4f}")
```

```
taban cizgisi (en sik sinif) 0.6611
                              kosum 1  kosum 2  ort |degisim|  en buyuk
konum kodlamasi var            0.8778   0.8833         0.3173    0.9753
konum kodlamasi yok            0.6611   0.6611         0.0000    0.0000
```

Alt satır iki yerde birden keskindir. Kodlamasız kurulum iki koşumda da tam olarak 0,6611 verir —
tabanın kendisi. Ondalık basamaklarda bile fark yoktur, çünkü ağ her diziye aynı sınıfı vermekten
başka bir şey öğrenememektedir. Sıra sınaması nedenini söyler: okumalar karıştırıldığında çıktı
olasılığı ortalama 0,0000 ve en fazla 0,0000 oynar. Bu bir yuvarlama değildir; katman girdiyi
sırasız bir küme olarak gördüğü için çıktı bit düzeyinde aynıdır.

Kodlamalı kurulumda aynı karıştırma çıktıyı ortalama 0,3173, en fazla 0,9753 oynatır. Aradaki fark
kodlamanın "yardımcı olması" değil, sıranın ancak kodlamayla ağın erişimine girmesidir. Yinelemeli
bir ağda sıra yapının kendisinden gelir ve ayrıca kodlanması gerekmez; dikkat bu güvenceyi
vermediği için sırayı girdiye yazmak bir seçim değil, bir zorunluluktur.

#### Özet

- Aynı iç boyut farklı sayıda başa bölündüğünde parametre sayısı 33'te sabit kalır; ayrılmış küme
  ortalaması 0,8722, 0,8806 ve 0,8972 olur ve baş sayısının kattığı 0,0250'dir.
- Dört başlı kurulumun iki koşumu arasındaki fark 0,0500'dür, yani baş sayısının kattığının iki
  katı; baş sayısı tek koşumla seçilirse yanlış seçilir.
- Başlar görevin istediği iki bölgeye yalnız bazı koşumlarda ayrılır: iki başlı kurulumun ikinci
  koşumu 3,30 ve 8,55 merkezleriyle ayrıklık 0,7264 verir, birinci koşumu 5,57 ve 6,30 ile
  0,4096'da kalır ve doğruluğu yalnız 0,0055 düşüktür.
- Konum kodlaması olmadan iki koşum da tam olarak taban çizgisine, 0,6611'e iner; okumalar
  karıştırıldığında çıktı 0,0000 oynar, çünkü katman diziyi sırasız bir küme olarak görür.
- Konum kodlamalı kurulumda aynı karıştırma çıktıyı ortalama 0,3173 ve en fazla 0,9753 oynatır.

#### Sonraki Adım

Bu iki derste girdinin her adımı hazır bir sayıydı: okuma bir kayan noktalı değer, işaret bir sıfır
ya da bir, konum bir sinüs. Dizilerin çoğu böyle gelmez. Bir sayaç tipi, bir tarife basamağı, bir
bölge kodu ya da bir olay etiketi **ayrık** bir simgedir ve doğal bir sayısal değeri yoktur.
M27/K02'nin kodlama dersleri bu simgeleri bir-sıcak sütunlara çevirmişti; bu, kategori sayısı
büyüdükçe girdi boyutunu da aynı oranda büyütür ve simgeler arasındaki hiçbir yakınlığı taşımaz.
Sonraki ders ayrık girdiyi öğrenilen bir vektöre eşleyen gömme katmanını kurar, parametre sayısını
bir-sıcak kodlamaya karşı sayar ve öğrenilen bu temsili M27/K04'ün **öğrenilmeyen** izdüşümüyle
aynı ölçüde karşılaştırır.

### Gömme Katmanları

Source: https://academia.sh/tr/kurslar/derin-ogrenme/gomme-katmanlari

Ayrık bir olay kodunun sürekli bir vektöre eşlenmesinin ne kattığının ölçülmesi: en sık sınıf tabanı 0,6444 iken 103 parametreli öğrenilen gömme 150 turda 0,9722 ve 0,9833 veriyor, 157 parametreli bir-sıcak kodlama aynı turda 0,7167 ve 0,7000'de kalıp aynı sayıya ancak 600 turda ulaşıyor (0,9611 ve 0,9556). Aynı boyuttaki dondurulmuş tablo 0,6944 ve 0,7278'de kalıyor, sıralı sayısal kod ise dört tur bütçesinde de tam olarak tabanda duruyor. Öğrenilen tabloda şüpheli kodlarla öbür kodlar arasındaki uzaklık grup içi uzaklığın 3,9153 katı, dondurulmuş tabloda 1,0728 katıdır.

Önceki iki derste girdinin her adımı hazır bir sayıydı. Diziler böyle gelmez. Bir sayaç kaydında
okumanın yanında bir **olay kodu** durur — kalibrasyon, iletişim kesintisi, kapak açılması, elle
okuma — ve bu kod bir simgedir. Sayısal bir değeri yoktur; on yedinci kodun on altıncıdan büyük
olması hiçbir şey söylemez.

M27/K02 bu simgeleri bir-sıcak sütunlara çevirmişti: her kod için bir gösterge sütunu. Yordam
çalışır, ama iki bedeli vardır. Girdi boyutu kod sayısıyla birlikte büyür ve simgeler arasındaki
hiçbir yakınlık taşınmaz — birbirinin yerine geçebilen iki kod, ilgisiz iki kod kadar uzaktır. Bu
dersin sorusu şudur: kodun temsilini elle vermek yerine **öğrenmek** hangi sayıyı oynatır ve
öğrenilen temsil ile göreve hiç bakmadan sabitlenmiş bir temsil arasındaki fark nedir.

- **MI64.** Bu konunun dizi kurgusu `mimariler/06`'da kuruldu ve **kurgudur**. Bu derste her adıma
  **kurgu** bir olay kodu eklenir: 24 kod, adım başına bir tane, tohum 20260218. Okumalar değişmez.
- **MI65.** Sekiz kod **şüpheli** olarak işaretlidir ve bu sekizin dizideki numaraları bitişik
  değildir. Etiket, on iki adımın en az beşinde şüpheli bir kod bulunmasıdır.
- **MI66.** Taban çizgisi **en sık sınıftır**. Kod numaralarının sırası etiketle ilişkisiz olduğu
  için sıralı bir sayısal kodlamanın tabanı geçmesi beklenmez ve bu ölçülür.
- **MI67.** Model ders içinde yazılır ve **modeldir**: adımların temsilleri ortalanır, bir gizli
  katmandan (altı birim, doğrultulmuş doğrusal birim) geçirilir ve tek çıkışa bağlanır. Kitaplık
  çağrılmaz.
- **MI68.** Dört kurulum aynı gövdeyi paylaşır ve yalnız **kodun temsilinde** ayrılır: bir-sıcak,
  öğrenilen gömme, dondurulmuş gömme, sıralı sayısal kod.
- **MI69.** Bir-sıcak kurulumda tablo **birim dizeydir** ve saklanmaz; kod bunu sayımla
  gerçekleştirir. Parametre sayımında birim dizey parametre sayılmaz, çünkü serbest bir değeri
  yoktur.
- **MI70.** Dondurulmuş gömme, aynı boyutta bir tablonun ilklendirilip **hiç güncellenmemesidir**.
  M27/K04 `boyut-azaltma`'nın izdüşümü de göreve bakmadan sabitlenmişti; oradaki ölçü geri kurma
  hatasıydı, burada ayrılmış küme sayısıdır.
- **MI71.** Eğitim tam toplu eğim inişidir, öğrenme adımı 0,9 ve dört tur bütçesinde ölçülür:
  150, 300, 450, 600.
- **MI72.** Her kurulum **iki koşumla** basılır; koşumlar ilklendirme tohumunda ayrılır.

#### Aynı Gövde, Dört Temsil

Görev kodların sayımına bağlıdır, sırasına değil. Bu yüzden model adım temsillerini ortalar ve
ortalamayı küçük bir gizli katmana verir. Etiket kodlardan tam olarak belirlendiği için, şüpheli
kodları öbürlerinden ayırabilen bir temsil görevi kusursuz çözebilir; ayıramayan bir temsil ise
hiçbir tur bütçesinde çözemez.

```python
# ORTAK — MODELDIR. `mimariler/06`'nin KURGU dizi kumesi ayni tohumla yeniden uretilir;
# her adima KURGU bir olay kodu eklenir.
import math

TOHUM, M32, ADIM = 20260218, 0xFFFFFFFF, 12
KOD, SUP, ESIK = 24, (1, 4, 5, 9, 13, 16, 20, 22), 5


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


def dizi_kur(n, tohum):
    D = []
    for i in range(n):
        r = uretec(tohum + i)
        r()
        oku = [0.0] + [round((r() + r() + r() - 1.5) * 1.9, 3) for _ in range(ADIM - 1)]
        r()
        o = uretec(tohum + 8000 + i)
        kod = [int(o() * KOD) for _ in range(ADIM)]
        D.append({"oku": oku, "kod": kod,
                  "y": 1 if sum(c in SUP for c in kod) >= ESIK else 0})
    return D


VERI = dizi_kur(720, TOHUM)
EGT, SIN = VERI[:200], VERI[540:]
oran = sum(x["y"] for x in SIN) / len(SIN)
TABAN = max(oran, 1 - oran)
print(f"dizi {len(VERI)}, uzunluk {ADIM}, kod sayisi {KOD}, supheli kod {len(SUP)}")
print(f"etiket orani egitim {sum(x['y'] for x in EGT) / len(EGT):.4f}, ayrilmis {oran:.4f}")
print(f"taban cizgisi (en sik sinif) {TABAN:.4f}")
print(f"ornek kod dizisi {VERI[0]['kod']}, supheli sayisi "
      f"{sum(c in SUP for c in VERI[0]['kod'])}, etiket {VERI[0]['y']}")
```

```
dizi 720, uzunluk 12, kod sayisi 24, supheli kod 8
etiket orani egitim 0.3450, ayrilmis 0.3556
taban cizgisi (en sik sinif) 0.6444
ornek kod dizisi [0, 8, 0, 16, 22, 10, 17, 7, 14, 19, 7, 18], supheli sayisi 2, etiket 0
```

Gömme katmanı bir tablodur: kod sayısı kadar satır, gömme boyutu kadar sütun. Bir kodun temsili o
tablodan okunan satırdır ve satır bir parametredir — eğim onu da günceller. Bir-sıcak kurulumda
tablo yoktur, çünkü gösterge vektörünü bir doğrusal katmanla çarpmak zaten o katmanın sütununu
okumaktır. İki kurulum arasındaki fark bir ilke farkı değil, satırın **nereye** yazıldığı ve kaç
tane olduğudur.

```python
GIZ, DUR = 6, (150, 300, 450, 600)


def temsil(T, kod):
    if T is None:                       # bir-sicak: tablo birim dizeydir, sayim yeter
        h = [0.0] * KOD
        for c in kod:
            h[c] += 1.0 / ADIM
        return h
    h = [0.0] * len(T[0])
    for c in kod:
        for j in range(len(h)):
            h[j] += T[c][j] / ADIM
    return h


def tablo(tip, tohum, d=3):
    if tip == "bir-sicak":
        return None, KOD
    if tip == "sayisal":
        return [[c / (KOD - 1)] for c in range(KOD)], 1
    r = uretec(tohum)
    return [[(r() + r() + r() - 1.5) * 1.1 for _ in range(d)] for _ in range(KOD)], d


def egit(tohum, T, dm, ogren, EG, adim=0.9):
    r = uretec(tohum + 500)
    g = lambda: (r() + r() + r() - 1.5) * 0.9
    W1 = [[g() for _ in range(dm)] for _ in range(GIZ)]
    b1, w, b, n, olcum = [0.0] * GIZ, [g() for _ in range(GIZ)], [0.0], len(EG), {}
    for tur in range(1, max(DUR) + 1):
        gW1 = [[0.0] * dm for _ in range(GIZ)]
        gb1, gw, gb = [0.0] * GIZ, [0.0] * GIZ, 0.0
        gT = [[0.0] * dm for _ in range(KOD)] if ogren else None
        for h, kod, y in EG:
            z = [sum(W1[i][j] * h[j] for j in range(dm)) + b1[i] for i in range(GIZ)]
            o = sum(w[i] * z[i] for i in range(GIZ) if z[i] > 0) + b[0]
            df = 1.0 / (1.0 + math.exp(-max(-30.0, min(30.0, o)))) - y
            gb += df
            da = [df * w[i] if z[i] > 0 else 0.0 for i in range(GIZ)]
            for i in range(GIZ):
                gw[i] += df * max(0.0, z[i])
                gb1[i] += da[i]
                for j in range(dm):
                    gW1[i][j] += da[i] * h[j]
            if ogren:
                dh = [sum(da[i] * W1[i][j] for i in range(GIZ)) for j in range(dm)]
                for c in kod:
                    for j in range(dm):
                        gT[c][j] += dh[j] / ADIM
        for i in range(GIZ):
            w[i] -= adim * gw[i] / n
            b1[i] -= adim * gb1[i] / n
            for j in range(dm):
                W1[i][j] -= adim * gW1[i][j] / n
        b[0] -= adim * gb / n
        if ogren:                       # gomme tablosu da bir parametredir
            for c in range(KOD):
                for j in range(dm):
                    T[c][j] -= adim * gT[c][j] / n
            for k, (_h, kod, y) in enumerate(EG):
                EG[k] = (temsil(T, kod), kod, y)
        if tur in DUR:
            P = {"T": T, "dm": dm, "W1": [u[:] for u in W1], "b1": b1[:],
                 "w": w[:], "b": b[0]}
            olcum[tur] = dogruluk(P, SIN)
    return P, olcum


def cikti(P, kod):
    h = temsil(P["T"], kod)
    z = [sum(P["W1"][i][j] * h[j] for j in range(P["dm"])) + P["b1"][i]
         for i in range(GIZ)]
    return sum(P["w"][i] * max(0.0, z[i]) for i in range(GIZ)) + P["b"]


def dogruluk(P, D):
    return sum((cikti(P, x["kod"]) > 0) == (x["y"] == 1) for x in D) / len(D)


AG, KUR = {}, (("bir-sicak", "bir-sicak", False), ("gomme, ogrenilen", "gomme", True),
               ("gomme, dondurulmus", "gomme", False), ("sayisal kod", "sayisal", False))

print(f"gizli birim {GIZ}, egitim ornegi {len(EGT)}, "
      f"taban cizgisi {TABAN:.4f}")
print(f"{'kurulum':<21}{'parametre':>10}{'ogrenilen':>10}{'kosum':>7}"
      + "".join(f"{'tur ' + str(t):>10}" for t in DUR))
for ad, tip, ogren in KUR:
    AG[ad] = []
    for k in (1, 2):
        T, dm = tablo(tip, TOHUM + 900 + k)
        EG = [(temsil(T, x["kod"]), x["kod"], x["y"]) for x in EGT]
        P, olcum = egit(TOHUM + k, T, dm, ogren, EG)
        AG[ad].append(P)
        gom = KOD * dm if tip == "gomme" else 0
        par = GIZ * dm + 2 * GIZ + 1 + gom
        ogr = par - (0 if ogren else gom)
        print(f"{ad if k == 1 else '':<21}{par:>10}{ogr:>10}{k:>7}"
              + "".join(f"{olcum[t]:>10.4f}" for t in DUR))
```

```
gizli birim 6, egitim ornegi 200, taban cizgisi 0.6444
kurulum               parametre ogrenilen  kosum   tur 150   tur 300   tur 450   tur 600
bir-sicak                   157       157      1    0.7167    0.8000    0.9222    0.9611
                            157       157      2    0.7000    0.8111    0.8611    0.9556
gomme, ogrenilen            103       103      1    0.9722    1.0000    1.0000    1.0000
                            103       103      2    0.9833    1.0000    1.0000    1.0000
gomme, dondurulmus          103        31      1    0.6944    0.6778    0.6778    0.6833
                            103        31      2    0.7278    0.7389    0.7444    0.7444
sayisal kod                  19        19      1    0.6444    0.6444    0.6444    0.6444
                             19        19      2    0.6444    0.6444    0.6444    0.6444
```

Dört satır dört ayrı sonuç veriyor. Öğrenilen gömme 150 turda 0,9722 ve 0,9833'e çıkıyor,
300 turda iki koşumda da 1,0000'e oturuyor — görev kodlardan tam belirlendiği için bu beklenen
tavandır. Bir-sıcak kurulum aynı 150 turda 0,7167 ve 0,7000, yani tabanın az üstünde. Fark
ifade gücünden gelmiyor: 600 turda 0,9611 ve 0,9556'ya çıkıyor. Aynı yere dört kat tur bütçesiyle
varıyor ve bunu 157 parametreyle yapıyor, gömmenin 103'üne karşılık.

Dondurulmuş tablo aynı boyuttadır ve aynı gövdeye bağlıdır; tek farkı 72 satırlık tablonun hiç
güncellenmemesidir. Dört tur bütçesinde de 0,68 ile 0,75 arasında kalıyor. Tur eklemek işe
yaramıyor, çünkü eksik olan bütçe değil: göreve bakmadan seçilmiş üç yön, şüpheli sekiz kodu
öbür on altıdan ayırmıyor ve gövde ayrılmamış bir temsilden ayrım üretemiyor. M27/K04
`boyut-azaltma` aynı konumu geri kurma hatasıyla ölçmüştü — orada sütun ortalamalarıyla geri
kurmanın 3,3411'ine karşı iki bileşenli izdüşüm 2,7762 vermişti — ve oradaki yönler de veriden,
etiketten değil, seçilmişti. Bir temsilin veriyi iyi koruması, görevin istediği ayrımı taşıdığı
anlamına gelmez.

Son satır en serttir. Sıralı sayısal kod dört bütçenin dördünde de tam olarak 0,6444, yani taban
çizgisinin kendisidir. Kod numaraları arasındaki sıra etiketle ilişkisiz olduğu için tek kanal
hiçbir şey taşımıyor. M27/K02'nin kodlama dersinin uyarısı burada sayıya dönüşüyor.

#### Parametre Sayısı Kod Sayısıyla Nasıl Büyüyor

Yirmi dört kodda gömmenin parametre kazancı küçüktür: 103'e karşı 157. Kazancın nereden geldiği
ancak kod sayısı ve gizli katman büyüdükçe görünür. Hesap tek satırlıktır ve koşum gerektirmez.

```python
def sayim(V, giz, d=None):
    if d is None:
        return V * giz + 2 * giz + 1        # bir-sicak vektor dogrudan katmana
    return V * d + d * giz + 2 * giz + 1    # gomme tablosu, sonra katman


print(f"{'kod sayisi':>11}{'gizli birim':>13}{'bir-sicak':>11}{'gomme d=3':>11}"
      f"{'oran':>8}{'adim basina carpma':>20}")
for V in (KOD, 240, 2400):
    for giz in (GIZ, 64):
        a, b = sayim(V, giz), sayim(V, giz, 3)
        print(f"{V:>11}{giz:>13}{a:>11}{b:>11}{b / a:>8.3f}"
              f"{f'{V * giz} / {3 * giz}':>20}")
```

```
 kod sayisi  gizli birim  bir-sicak  gomme d=3    oran  adim basina carpma
         24            6        157        103   0.656            144 / 18
         24           64       1665        393   0.236          1536 / 192
        240            6       1453        751   0.517           1440 / 18
        240           64      15489       1041   0.067         15360 / 192
       2400            6      14413       7231   0.502          14400 / 18
       2400           64     153729       7521   0.049        153600 / 192
```

Bir-sıcak kurulumda parametre sayısı kod sayısı ile gizli birim sayısının **çarpımı** kadar
büyür. Gömmede tablo kod sayısıyla doğru orantılı büyür ama gizli katman yalnız gömme boyutuna
bağlıdır, dolayısıyla ikinci çarpan sabit kalır. 2.400 kod ve 64 gizli birimde oran 0,049'a
iner. Son sütun çarpma sayısını aynı biçimde okur: bir-sıcak vektörle çarpım 153.600 çarpma
ister ve bunların 153.536'sı sıfırla yapılır; tablodan satır okuyup 192 çarpma yapmak aynı sonucu
verir. Yalnız ilk satır ölçüldü; kalanlar aynı formülün değerleridir.

#### Öğrenilen Tablo Neyi Kodladı

Gömmenin sayısı yükseltmesi bir sonuçtur; hangi yapıyı bulduğu ayrı bir sorudur. Görev kodları
iki gruba ayırıyor ve bu ayrım tabloda görünüyorsa şüpheli kodların birbirine, öbürlerinden daha
yakın durması gerekir. Ölçü ölçek bağımsızdır: gruplar arası ortalama uzaklığın grup içi ortalama
uzaklığa oranı.

```python
def uzaklik(u, v):
    return sum((u[i] - v[i]) ** 2 for i in range(len(u))) ** 0.5


def ortalama_ikili(T, A, B):
    c = [uzaklik(T[i], T[j]) for i in A for j in B if i != j]
    return sum(c) / len(c)


S = [c for c in range(KOD) if c in SUP]
D = [c for c in range(KOD) if c not in SUP]
print(f"supheli kod {len(S)}, oteki {len(D)}")
print(f"{'tablo':<26}{'kosum':>7}{'supheli ici':>13}{'oteki ici':>11}"
      f"{'gruplar arasi':>15}{'ayrim orani':>13}")
for ad in ("gomme, ogrenilen", "gomme, dondurulmus"):
    for k in (0, 1):
        T = AG[ad][k]["T"]
        i, o, a = (ortalama_ikili(T, S, S), ortalama_ikili(T, D, D),
                   ortalama_ikili(T, S, D))
        print(f"{ad if k == 0 else '':<26}{k + 1:>7}{i:>13.4f}{o:>11.4f}"
              f"{a:>15.4f}{a / ((i + o) / 2):>13.4f}")
```

```
supheli kod 8, oteki 16
tablo                       kosum  supheli ici  oteki ici  gruplar arasi  ayrim orani
gomme, ogrenilen                1       0.7629     0.8020         3.0634       3.9153
                                2       0.8673     0.9887         3.0602       3.2977
gomme, dondurulmus              1       0.9898     1.0181         1.0771       1.0728
                                2       1.0155     1.1029         1.0766       1.0164
```

Öğrenilen tabloda iki grup birbirinden ayrılmıştır: gruplar arası ortalama uzaklık grup içi
ortalamanın 3,9153 ve 3,2977 katıdır. Dondurulmuş tabloda aynı oran 1,0728 ve 1,0164 — yani grup
içi ile gruplar arası uzaklık neredeyse eşittir, çünkü rastgele seçilmiş üç yön kodları görevin
tanımadığı bir düzende dağıtmıştır. İki koşumun ayrım oranları arasında 0,6176'lık bir fark
vardır ve her iki koşum da 1,0000 doğruluk üretmektedir; tablonun tam olarak nereye yerleştiği
koşuma bağlıdır, ayrımı yapması ise değildir.

#### Özet

- Bir-sıcak vektörü doğrusal bir katmana vermek, gömme tablosundan satır okumakla aynı işlemdir;
  fark parametre sayısında ve çarpma sayısındadır.
- Aynı gövdede öğrenilen gömme 103 parametreyle 150 turda 0,9722 ve 0,9833 verir; 157 parametreli
  bir-sıcak kurulum aynı turda 0,7167 ve 0,7000'de kalır ve benzer sayıya ancak 600 turda ulaşır.
- Göreve bakmadan dondurulmuş aynı boyuttaki tablo 0,68 ile 0,75 arasında kalır ve tur eklemek
  bunu düzeltmez; M27/K04'ün izdüşümü de aynı konumdaydı ve orada geri kurma hatasıyla ölçülmüştü.
- Sıralı sayısal kodlama dört tur bütçesinde de tam olarak taban çizgisini, 0,6444'ü verir, çünkü
  kod numaralarının sırası etiketle ilişkisizdir.
- Öğrenilen tabloda gruplar arası uzaklık grup içi uzaklığın 3,9153 ve 3,2977 katıdır;
  dondurulmuş tabloda 1,0728 ve 1,0164 katı, yani ayrım yoktur.

#### Sonraki Adım

Bu derste gömme tablosu görevin kendi etiketleriyle öğrenildi ve iki yüz eğitim örneği buna
yetti. Etiketin pahalı olduğu durumlarda bu varsayım düşer: elde yirmi ya da kırk etiketli dizi
varsa, yüz üç parametrenin hepsini o kırk örnekten öğrenmek aşırı uyumla biter. Bir yol daha
vardır ve bu derste kurulan yapı onu doğrudan kullanır — tablo başka bir görevde öğrenilip bu
göreve taşınabilir. Sonraki ders önceden eğitilmiş bir modeli kurgu bir kaynak görevden kendi
eliyle üretir, ağırlıkları ya dondurup ya ince ayar yaparak aktarır ve aktarımın kattığı farkı
**kaç etiketli örnekle** kattığıyla birlikte aynı tabana karşı basar.

### Öğrenme Aktarımı

Source: https://academia.sh/tr/kurslar/derin-ogrenme/ogrenme-aktarimi

Kurgu bir kaynak görevden kendi elimizle üretilen önceden eğitilmiş bir modelin hedef göreve taşınmasının ne kattığının ölçülmesi: en sık sınıf tabanı 0,6444 iken yirmi etiketle sıfırdan eğitim 0,7194, dondurmalı aktarım 0,8417 ve ince ayarlı aktarım 0,8083 veriyor. Dondurma dört ölçümde de 0,83 dolayında düz duruyor ve sıfırdan eğitim onu kırk ile seksen örnek arasında geçiyor; ince ayar dört noktanın üçünde sıfırdanın üstünde kalıyor ama yüz altmış örnekte fark 0,0028'e iniyor. Kaynak görevden gelen tablo bakım ayrımını 3,6373, şüpheli ayrımını 2,4767 taşıyor; ince ayardan sonra bu iki sayı 2,4685 ve 3,7991 oluyor.

Gömme tablosu önceki derste görevin kendi etiketleriyle öğrenildi ve iki yüz örnek buna yetti.
Etiketin pahalı olduğu durumlarda bu varsayım düşer. Şüpheli olarak işaretlenmiş bir abone
kaydı, bir denetçinin sahada geçirdiği saatin karşılığıdır; elde yirmi ya da kırk tane olabilir.
Yüz üç parametrenin hepsini yirmi etiketten öğrenmek, kapasitenin veriyi geçtiği durumdur ve
M27/K01 `genelleme` bunu ölçmüştü.

Bir yol daha vardır. Aynı kodlar başka bir soruya da cevap verir ve o soru için etiket boldur.
Temsil orada öğrenilip buraya taşınabilir. Bu dersin sorusu ikilidir: taşımak hangi sayıyı
oynatır ve **kaç etiketle**. İkinci soru birincisinden önemlidir, çünkü aktarımın değeri son
sayıda değil, o sayıya kaç etiketle varıldığındadır.

- **MI73.** Bu konunun dizi kurgusu `mimariler/06`'da, olay kodları `mimariler/08`'de kuruldu ve
  **kurgudur**. Bu derste ikinci bir **kurgu** etiket eklenir. Tohum 20260218.
- **MI74.** **Kaynak görev kurgudur ve etiketi boldur**: on iki adımın en az altısında bir **bakım
  kodu** bulunması. Bakım kodları on tanedir.
- **MI75.** **Hedef görev** `mimariler/08`'in görevidir: en az beş adımda **şüpheli kod**. Şüpheli
  kodlar sekiz tanedir ve sekizi de bakım kodları arasındadır; bakım kümesinde onların dışında iki
  kod daha vardır. İki görev ilişkilidir ama aynı değildir.
- **MI76.** **Önceden eğitilmiş model bu derste üretilir.** Hiçbir hazır model, ağırlık deposu ya
  da dış kaynak kullanılmaz; kaynak görev üç yüz örnekle burada eğitilir ve **modeldir**.
- **MI77.** Kaynak ile hedef **ayrı dizilerde** çalışır: kaynak ilk üç yüz dizi, hedef havuzu
  sonraki iki yüz kırk, ayrılmış küme son yüz seksen. Önceden eğitilmiş model hedef görevin hiçbir
  etiketini görmez.
- **MI78.** Üç kurulum karşılaştırılır: **sıfırdan** (tablo rastgele ilklendirilir), **aktarım +
  dondurma** (tablo kaynaktan alınır ve hiç güncellenmez), **aktarım + ince ayar** (tablo
  kaynaktan alınır ve güncellenir).
- **MI79.** Hedef etiket sayısı dört değerde ölçülür: 20, 40, 80, 160. Ayrılmış küme her dördünde
  aynıdır.
- **MI80.** Taban çizgisi **en sık sınıftır** ve ayrılmış kümeden okunur; etiket sayısı değişse de
  taban değişmez.
- **MI81.** Her sayı **iki koşumla** basılır; koşumlar ilklendirme tohumunda ayrılır.

#### Kaynak Görev ve Önceden Eğitilmiş Model

Aktarımın öznesi bir dosya değil, bir **temsildir**. Burada taşınan şey gömme tablosudur: yirmi
dört kodun üç boyutlu vektörleri. Kaynak görev bu tabloyu kendi sorusuna göre yerleştirir ve
hedef görev onu devralır.

```python
# ORTAK — MODELDIR. `mimariler/06`'nin KURGU dizi kumesi + `08`'in KURGU olay kodlari.
import math

TOHUM, M32, ADIM = 20260218, 0xFFFFFFFF, 12
KOD = 24
BAK = (1, 2, 4, 5, 7, 9, 13, 16, 20, 22)     # KURGU kaynak gorev: bakim kodlari
SUP = (1, 4, 5, 9, 13, 16, 20, 22)           # KURGU hedef gorev: supheli kodlar


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


def dizi_kur(n, tohum):
    D = []
    for i in range(n):
        r = uretec(tohum + i)
        r()
        [round((r() + r() + r() - 1.5) * 1.9, 3) for _ in range(ADIM - 1)]
        r()
        o = uretec(tohum + 8000 + i)
        kod = [int(o() * KOD) for _ in range(ADIM)]
        D.append({"kod": kod, "kaynak": 1 if sum(c in BAK for c in kod) >= 6 else 0,
                  "y": 1 if sum(c in SUP for c in kod) >= 5 else 0})
    return D


VERI = dizi_kur(720, TOHUM)
KAYNAK, HAVUZ, SIN = VERI[:300], VERI[300:540], VERI[540:]
oran = sum(x["y"] for x in SIN) / len(SIN)
TABAN = max(oran, 1 - oran)
ORTAK = [c for c in SUP if c in BAK]
print(f"kod {KOD}, bakim {len(BAK)}, supheli {len(SUP)}, ortak {len(ORTAK)}")
print(f"kaynak gorev orani {sum(x['kaynak'] for x in KAYNAK) / len(KAYNAK):.4f}, "
      f"kaynak ornek {len(KAYNAK)}")
print(f"hedef gorev orani ayrilmis {oran:.4f}, taban cizgisi {TABAN:.4f}, "
      f"havuz {len(HAVUZ)}")
```

```
kod 24, bakim 10, supheli 8, ortak 8
kaynak gorev orani 0.3533, kaynak ornek 300
hedef gorev orani ayrilmis 0.3556, taban cizgisi 0.6444, havuz 240
```

İki görevin ilişkisi tek satırdadır: sekiz şüpheli kodun sekizi de bakım kümesindedir, ama bakım
kümesinde iki fazla kod vardır. Kaynak görevi çözen bir temsil, hedef görevin istediği ayrımı
yaklaşık olarak taşır; tam olarak taşımaz.

```python
GIZ, GOM = 6, 3


def temsil(T, kod):
    h = [0.0] * GOM
    for c in kod:
        for j in range(GOM):
            h[j] += T[c][j] / ADIM
    return h


def yeni_tablo(tohum):
    r = uretec(tohum)
    return [[(r() + r() + r() - 1.5) * 1.1 for _ in range(GOM)] for _ in range(KOD)]


def egit(tohum, T, D, alan, tur, ogren, adim=0.9):
    r = uretec(tohum + 500)
    g = lambda: (r() + r() + r() - 1.5) * 0.9
    W1 = [[g() for _ in range(GOM)] for _ in range(GIZ)]
    b1, w, b, n = [0.0] * GIZ, [g() for _ in range(GIZ)], [0.0], len(D)
    for _ in range(tur):
        gW1 = [[0.0] * GOM for _ in range(GIZ)]
        gb1, gw, gb = [0.0] * GIZ, [0.0] * GIZ, 0.0
        gT = [[0.0] * GOM for _ in range(KOD)] if ogren else None
        for x in D:
            h = temsil(T, x["kod"])
            z = [sum(W1[i][j] * h[j] for j in range(GOM)) + b1[i] for i in range(GIZ)]
            o = sum(w[i] * z[i] for i in range(GIZ) if z[i] > 0) + b[0]
            df = 1.0 / (1.0 + math.exp(-max(-30.0, min(30.0, o)))) - x[alan]
            gb += df
            da = [df * w[i] if z[i] > 0 else 0.0 for i in range(GIZ)]
            for i in range(GIZ):
                gw[i] += df * max(0.0, z[i])
                gb1[i] += da[i]
                for j in range(GOM):
                    gW1[i][j] += da[i] * h[j]
            if ogren:                   # dondurmada tablonun egimi hic hesaplanmaz
                dh = [sum(da[i] * W1[i][j] for i in range(GIZ)) for j in range(GOM)]
                for c in x["kod"]:
                    for j in range(GOM):
                        gT[c][j] += dh[j] / ADIM
        for i in range(GIZ):
            w[i] -= adim * gw[i] / n
            b1[i] -= adim * gb1[i] / n
            for j in range(GOM):
                W1[i][j] -= adim * gW1[i][j] / n
        b[0] -= adim * gb / n
        if ogren:
            for c in range(KOD):
                for j in range(GOM):
                    T[c][j] -= adim * gT[c][j] / n
    return {"T": T, "W1": W1, "b1": b1, "w": w, "b": b[0]}


def dogruluk(P, D, alan="y"):
    s = 0
    for x in D:
        h = temsil(P["T"], x["kod"])
        z = [sum(P["W1"][i][j] * h[j] for j in range(GOM)) + P["b1"][i]
             for i in range(GIZ)]
        o = sum(P["w"][i] * max(0.0, z[i]) for i in range(GIZ)) + P["b"]
        s += (o > 0) == (x[alan] == 1)
    return s / len(D)


def kopya(T):
    return [u[:] for u in T]


ONCEDEN = []
print(f"kaynak gorev ornegi {len(KAYNAK)}, tur 400, gomme boyutu {GOM}, "
      f"gizli birim {GIZ}")
for k in (1, 2):
    P = egit(TOHUM + k, yeni_tablo(TOHUM + 900 + k), KAYNAK, "kaynak", 400, True)
    ONCEDEN.append(P)
    print(f"onceden egitilmis model kosum {k}: kaynak gorevde egitim "
          f"{dogruluk(P, KAYNAK, 'kaynak'):.4f}, ayrilmis "
          f"{dogruluk(P, SIN, 'kaynak'):.4f}")
print(f"bu iki model hedef gorevin hicbir etiketini gormedi")
```

```
kaynak gorev ornegi 300, tur 400, gomme boyutu 3, gizli birim 6
onceden egitilmis model kosum 1: kaynak gorevde egitim 1.0000, ayrilmis 1.0000
onceden egitilmis model kosum 2: kaynak gorevde egitim 1.0000, ayrilmis 1.0000
bu iki model hedef gorevin hicbir etiketini gormedi
```

#### Dondurma, İnce Ayar ve Kaç Etiket

Aktarımın iki biçimi vardır. **Dondurmada** taşınan tablo sabittir ve yalnız üstündeki gövde
öğrenilir: otuz bir parametre. **İnce ayarda** tablo da güncellenir: yüz üç parametre. İkisi
arasındaki seçim, elde kaç etiket olduğuna bağlıdır ve bu bağın kendisi ölçülebilir.

```python
ORNEK, KURULUM = (20, 40, 80, 160), (("sifirdan", False, True),
                                     ("aktarim + dondurma", True, False),
                                     ("aktarim + ince ayar", True, True))
SONUC = {}
print(f"hedef tur 250, taban cizgisi {TABAN:.4f}, ayrilmis {len(SIN)}")
print(f"{'kurulum':<21}{'ogrenilen':>10}{'kosum':>7}"
      + "".join(f"{'n=' + str(n):>9}" for n in ORNEK))
for ad, kaynakli, ogren in KURULUM:
    SONUC[ad] = {}
    for k in (1, 2):
        sat = []
        for n in ORNEK:
            T = kopya(ONCEDEN[k - 1]["T"]) if kaynakli else yeni_tablo(TOHUM + 900 + k)
            P = egit(TOHUM + 30 + k, T, HAVUZ[:n], "y", 250, ogren)
            SONUC[ad].setdefault(n, []).append(dogruluk(P, SIN))
            sat.append(SONUC[ad][n][-1])
            if n == ORNEK[-1] and k == 1:
                SONUC[ad]["T"] = P["T"]
        print(f"{ad if k == 1 else '':<21}"
              f"{GIZ * GOM + 2 * GIZ + 1 + (0 if not ogren else KOD * GOM):>10}"
              f"{k:>7}" + "".join(f"{v:>9.4f}" for v in sat))
```

```
hedef tur 250, taban cizgisi 0.6444, ayrilmis 180
kurulum               ogrenilen  kosum     n=20     n=40     n=80    n=160
sifirdan                    103      1   0.7222   0.8056   0.8167   0.9556
                            103      2   0.7167   0.8389   0.8611   0.9722
aktarim + dondurma           31      1   0.8333   0.8278   0.8389   0.8333
                             31      2   0.8500   0.8444   0.8278   0.8278
aktarim + ince ayar         103      1   0.8111   0.8556   0.8556   0.9556
                            103      2   0.8056   0.8500   0.8556   0.9667
```

Dondurma satırı yatay bir çizgidir: 0,8278 ile 0,8500 arasında, etiket sayısıyla neredeyse hiç
oynamıyor. Otuz bir parametre yirmi etiketten öğrenilebiliyor, ama yüz altmış etiket de aynı otuz
bir parametreye gidecek yeni bir yer bulmuyor. Aktarımın tavanı taşınan tablodadır.

```python
def ort(ad, n):
    return sum(SONUC[ad][n]) / 2


print(f"{'ornek':>7}{'sifirdan':>10}{'dondurma':>10}{'ince ayar':>11}"
      f"{'dondurma farki':>16}{'ince ayar farki':>17}")
for n in ORNEK:
    a, b, c = (ort(k, n) for k, *_ in KURULUM)
    print(f"{n:>7}{a:>10.4f}{b:>10.4f}{c:>11.4f}{b - a:>+16.4f}{c - a:>+17.4f}")
hedef = ort("aktarim + dondurma", 20)
yeter = [n for n in ORNEK if ort("sifirdan", n) >= hedef]
print(f"dondurma 20 ornekle {hedef:.4f}; sifirdan ayni sayiya "
      f"{yeter[0] if yeter else '>160'} ornekle ulasiyor")


def ikili(T, P, Q):
    d = [sum((T[i][j] - T[k][j]) ** 2 for j in range(GOM)) ** 0.5
         for i in P for k in Q if i != k]
    return sum(d) / len(d)


def ayrim(T, G):
    A = [c for c in range(KOD) if c in G]
    B = [c for c in range(KOD) if c not in G]
    return ikili(T, A, B) / ((ikili(T, A, A) + ikili(T, B, B)) / 2)


print(f"{'tablo':<28}{'bakim ayrimi':>14}{'supheli ayrimi':>16}")
for ad, T in (("kaynak gorevden gelen", ONCEDEN[0]["T"]),
              ("ince ayardan sonra n=160", SONUC["aktarim + ince ayar"]["T"]),
              ("sifirdan n=160", SONUC["sifirdan"]["T"])):
    print(f"{ad:<28}{ayrim(T, BAK):>14.4f}{ayrim(T, SUP):>16.4f}")
```

```
  ornek  sifirdan  dondurma  ince ayar  dondurma farki  ince ayar farki
     20    0.7194    0.8417     0.8083         +0.1222          +0.0889
     40    0.8222    0.8361     0.8528         +0.0139          +0.0306
     80    0.8389    0.8333     0.8556         -0.0056          +0.0167
    160    0.9639    0.8306     0.9611         -0.1333          -0.0028
dondurma 20 ornekle 0.8417; sifirdan ayni sayiya 160 ornekle ulasiyor
tablo                         bakim ayrimi  supheli ayrimi
kaynak gorevden gelen               3.6373          2.4767
ince ayardan sonra n=160            2.4685          3.7991
sifirdan n=160                      2.1087          3.3228
```

İlk tablo aktarımın kattığı farkı örnek sayısıyla birlikte okur ve tek bir sayı vermez. Yirmi
etikette dondurma sıfırdan eğitimin 0,1222 üstündedir; kırkta fark 0,0139'a düşer; seksende işaret
döner ve yüz altmışta dondurma sıfırdanın 0,1333 **altına** iner. İnce ayar dört noktanın üçünde
üsttedir ama yüz altmışta farkı 0,0028'e, yani ölçüm gürültüsünün içine iner.

İkinci satır bu dersin asıl sayısıdır. Dondurma yirmi etiketle 0,8417 veriyor; sıfırdan eğitim aynı
sayıya ancak yüz altmış etiketle ulaşıyor — sekiz katı. Aktarımın kazandırdığı şey son sayı değil,
o sayıya varmak için **toplanmayan etiketlerdir**. Etiket başına bir saha ziyareti düşünüldüğünde
ölçünün birimi doğruluk değil, yüz kırk ziyarettir.

Yüz altmış satırındaki eksi işaret üzerinde durmaya değer. Orada dondurmalı aktarım, hiçbir şey
aktarmayan kuruluma yenilmektedir; taşınan temsil bir başlangıç noktası olmaktan çıkıp bir kısıt
hâline gelmiştir. Aktarım her zaman kazandırmaz ve kazanıp kazandırmadığı ancak aktarımsız kurulum
aynı ayrılmış kümede koşulduğunda bilinir. Bu ölçünün taban çizgisi en sık sınıf değil, **sıfırdan
eğitimin kendisidir**.

Koşum değişkenliği bu dersin okumasını iki yerde belirler. Yirmi etikette üç kurulumun koşumları
arasındaki fark en fazla 0,0167'dir, aktarımın kattığı ise 0,1222 — yani fark koşum
değişkenliğinin yedi katıdır ve ölçülmüş sayılır. Yüz altmışta ise ince ayarın sıfırdan farkı
0,0028'dir ve aynı kurulumun iki koşumu 0,0111 ayrılmaktadır; orada fark koşumun içinde kaybolur
ve "ince ayar biraz daha iyi" demek ölçülmemiş bir cümledir.

Üçüncü tablo aktarımın niçin bir yerde durduğunu söyler. Kaynaktan gelen tablo bakım ayrımını
3,6373 taşıyor ama şüpheli ayrımını yalnız 2,4767; iki fazla bakım kodu tabloda şüphelilerin
yanına yerleşmiş durumda ve dondurulmuş bir tablo bunu düzeltemez. İnce ayar iki sayıyı yer
değiştiriyor: bakım ayrımı 2,4685'e düşerken şüpheli ayrımı 3,7991'e çıkıyor. Sıfırdan eğitilen
tablo da şüpheli ayrımını 3,3228'e getiriyor, ama bunun için sekiz kat etiket harcıyor.

#### Özet

- Önceden eğitilmiş model bu derste kurgu bir kaynak görevden üretildi; kaynak görevde iki koşum da
  1,0000 veriyor ve hedef görevin hiçbir etiketini görmedi.
- Yirmi etikette taban 0,6444, sıfırdan eğitim 0,7194, dondurma 0,8417 ve ince ayar 0,8083; aktarım
  bu noktada 0,1222'ye kadar fark katıyor.
- Dondurma otuz bir parametre öğrenir ve etiket sayısıyla oynamaz: dört ölçümde de 0,83 dolayında
  düz durur, yüz altmış etikette sıfırdan eğitimin 0,1333 altına iner.
- Aktarımın ölçüsü doğruluk değil etiket sayısıdır: dondurmanın yirmi etiketle verdiği 0,8417'ye
  sıfırdan eğitim ancak yüz altmış etiketle ulaşır.
- Tavanın nedeni taşınan temsildir: kaynak tablo bakım ayrımını 3,6373, şüpheli ayrımını 2,4767
  taşır; ince ayardan sonra bu iki sayı 2,4685 ve 3,7991 olur.

#### Sonraki Adım

Dokuz derste her mimari bir **etiketi** kestirdi. Girdi verildi, çıktı bir sayıya indirildi ve
ölçü hep aynı biçimdeydi: ayrılmış kümede kaç doğru. Bir ağın etiket kestirmekten başka bir işi
daha olabilir — girdinin kendisini yeniden üretmek, ya da girdiye benzeyen yeni örnekler kurmak.
Böyle bir ağın ölçüsü nedir, çünkü karşılaştırılacak bir etiket yoktur. Sonraki ders örtük uzay
üzerinden çalışan iki üretici düzeni ele alır: geri kurma hatasıyla ölçülen otokodlayıcıyı
(M27/K04'ün ölçüsüne atıfla) ve iki ağın birbirine karşı eğitildiği çekişmeli düzeni; ikincisinde
ölçülen şey başarım değil, aynı düzenin iki koşumunun ne kadar ayrıldığıdır.

### Üretici Modeller

Source: https://academia.sh/tr/kurslar/derin-ogrenme/uretici-modeller

Etiket olmadan çalışan iki üretici düzenin aynı kurgu dizi kümesinde ölçülmesi: ortalama diziyle geri kurma tabanı 2,9007 iken doğrusal otokodlayıcı bir örtük boyutta 1,2817 ve 1,2815, dört boyutta 0,7346 ve 0,7314 veriyor; iki koşumun hatası en fazla 0,0311 ayrılırken aynı koşumların bulduğu yönler 1,6330 ile 3,4005 arasında ayrılıyor. Çekişmeli düzende ayırt edicinin gerçek diziler üzerindeki doğruluğu 0,6133'ten 0,3467'ye inip 0,4600'e dönüyor ve iki koşumun ürettiği adım ortalamaları birbirinden 1,2707 uzaklaşıyor — her birinin gerçek kümeden sapmasından, 0,5321 ve 0,8877'den, daha fazla.

Dokuz derste her mimari bir etiketi kestirdi ve ölçü hep aynı biçimdeydi: ayrılmış kümede kaç
doğru. Bir ağın işi etiket kestirmek olmayabilir. Girdinin kendisini az sayıdan yeniden kurmak ya
da girdiye benzeyen yeni diziler üretmek de bir görevdir ve ikisinde de karşılaştırılacak bir
etiket yoktur.

Bu dersin sorusu ölçüyle ilgilidir: etiket yokken hangi sayı yazılır. İki düzen ele alınır. Birincisi
girdiyi bir **örtük uzaydan** geri kurar ve hatası doğrudan ölçülebilir. İkincisinde iki ağ
birbirine karşı eğitilir ve ortada tek bir hata bile yoktur; orada ölçülen şey başarım değil,
aynı düzenin iki koşumunun ne kadar ayrıldığıdır.

- **MI82.** Bu konunun dizi kurgusu `mimariler/06`'da kuruldu ve **kurgudur**. Bu derste dizi **ham**
  biçimiyle kullanılır: abone düzeyi, dönemsel bileşen ve önceki derslerin artığı. Önceki dersler
  diziyi sapma olarak ölçeklenmiş almıştı; sıkıştırılabilir yapı tam olarak orada çıkarılan
  bileşenlerdedir.
- **MI83.** Sütunlar **yalnız eğitim kümesinden** ölçeklenir ve hata standart sapma birimindedir.
  Bu, M27/K04 `boyut-azaltma`'nın birimiyle aynıdır.
- **MI84.** Taban çizgisi **ortalama diziyle geri kurmadır** ve bu, örtük boyutun sıfır olduğu
  durumdur. Öğrenmeyen en yalın geri kurma budur.
- **MI85.** **Geri kurma hatası yordamı M27/K04'te kuruldu ve burada tekrarlanmaz.** Orada yönler
  eşdeğişim dizeyinden hesaplanıyordu ve sütun ortalamalarıyla geri kurmanın 3,3411'ine karşı iki
  bileşen 2,7762 vermişti. Burada yönler hesaplanmaz, **eğim inişiyle öğrenilir**.
- **MI86.** Otokodlayıcı doğrusal bir kodlayıcı ve doğrusal bir çözücüdür; veri ortalandığı için
  yanma terimi yazılmaz. Ders içinde yazılır ve **modeldir**.
- **MI87.** **Çekişmeli üretici ağ** iki ağdan kurulu bir düzendir: **üretici** örtük bir
  vektörden dizi kurar, **ayırt edici**
  bir diziyi tek sayıya indirir. İkisi sırayla güncellenir.
- **MI88.** Çekişmeli düzenin ölçüsü doğruluk değildir. Üretilen dizilerin adım ortalamaları ve
  saçılımları gerçek kümeninkilerle karşılaştırılır ve **iki koşumun birbirinden** ne kadar
  ayrıldığı basılır.
- **MI89.** Bu ders yalnız **yapıyı ve ölçüyü** ele alır. Hiçbir üretim uygulaması, sahtecilik ya
  da denetim atlatma yordamı yazılmaz; bu konular M24 ve M25'in savunma çerçevesine bırakılmıştır.
- **MI90.** Her sayı **iki koşumla** basılır; koşumlar ilklendirme tohumunda ayrılır.

#### Otokodlayıcı ve Geri Kurma Hatası

Otokodlayıcı iki parçadır. Kodlayıcı on iki sayılık diziyi k sayıya indirir, çözücü o k sayıdan
on ikiyi geri kurar ve eğitim ikisini birlikte geri kurma hatasını küçültecek biçimde ayarlar.
Etiket yoktur; hedef girdinin kendisidir.

```python
# ORTAK — MODELDIR. `mimariler/06`'nin KURGU dizisi HAM biciminde kurulur:
# abone duzeyi + donemsel bilesen + onceki derslerin artigi.
import math

TOHUM, M32, ADIM = 20260218, 0xFFFFFFFF, 12


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


def dizi_kur(n, tohum):
    D = []
    for i in range(n):
        r = uretec(tohum + i)
        r()
        artik = [0.0] + [round((r() + r() + r() - 1.5) * 1.9, 3) for _ in range(ADIM - 1)]
        r()
        s = uretec(tohum + 6000 + i)
        duzey = 21.0 + (s() + s() + s() - 1.5) * 6.0
        a, b = (s() + s() - 1.0) * 2.6, (s() + s() - 1.0) * 2.6
        aci = [2 * math.pi * t / ADIM for t in range(ADIM)]
        D.append([round(duzey + a * math.sin(aci[t]) + b * math.cos(aci[t]) + artik[t], 3)
                  for t in range(ADIM)])
    return D


VERI = dizi_kur(720, TOHUM)
EGT, SIN = VERI[:150], VERI[540:]
ORT = [sum(x[t] for x in EGT) / len(EGT) for t in range(ADIM)]
SAC = [max(1e-9, (sum((x[t] - ORT[t]) ** 2 for x in EGT) / len(EGT)) ** 0.5)
       for t in range(ADIM)]
ZE = [[(x[t] - ORT[t]) / SAC[t] for t in range(ADIM)] for x in EGT]
ZS = [[(x[t] - ORT[t]) / SAC[t] for t in range(ADIM)] for x in SIN]


def uzaklik(u, v):
    return sum((u[t] - v[t]) ** 2 for t in range(ADIM)) ** 0.5


SIFIR = [0.0] * ADIM
TABAN = sum(uzaklik(z, SIFIR) for z in ZS) / len(ZS)
print(f"dizi {len(VERI)}, uzunluk {ADIM}, egitim {len(EGT)}, ayrilmis {len(SIN)}")
print(f"ornek ham dizi {VERI[0]}")
print(f"taban cizgisi (ortalama diziyle geri kurma) {TABAN:.4f}")
```

```
dizi 720, uzunluk 12, egitim 150, ayrilmis 180
ornek ham dizi [21.188, 21.247, 19.977, 20.223, 21.497, 22.188, 24.826, 24.397, 24.089, 25.549, 22.073, 22.529]
taban cizgisi (ortalama diziyle geri kurma) 2.9007
```

Kurgunun altında üç bileşen vardır: abone düzeyi ve dönemsel bileşenin iki katsayısı. On iki sayı
saklansa da dizinin taşıdığı bilgi bu üçün üstüne yalnız gürültü ekler. Otokodlayıcının bulması
beklenen şey budur ve hangi k'da bulduğu ölçülebilir.

```python
def otokodlayici(tohum, k, tur=300, adim=0.3):
    # veri sutun ortalamalariyla ortalandigi icin yanma terimi yazilmaz;
    # k=0 durumu tam olarak taban cizgisidir.
    r = uretec(tohum)
    g = lambda: (r() + r() + r() - 1.5) * 0.7
    W1 = [[g() for _ in range(ADIM)] for _ in range(k)]
    W2 = [[g() for _ in range(k)] for _ in range(ADIM)]
    n = len(ZE)
    for _ in range(tur):
        gW1 = [[0.0] * ADIM for _ in range(k)]
        gW2 = [[0.0] * k for _ in range(ADIM)]
        for z in ZE:
            h = [sum(W1[i][t] * z[t] for t in range(ADIM)) for i in range(k)]
            y = [sum(W2[t][i] * h[i] for i in range(k)) for t in range(ADIM)]
            d = [2.0 * (y[t] - z[t]) / ADIM for t in range(ADIM)]
            for t in range(ADIM):
                for i in range(k):
                    gW2[t][i] += d[t] * h[i]
            for i in range(k):
                dh = sum(d[t] * W2[t][i] for t in range(ADIM))
                for t in range(ADIM):
                    gW1[i][t] += dh * z[t]
        for i in range(k):
            for t in range(ADIM):
                W1[i][t] -= adim * gW1[i][t] / n
        for t in range(ADIM):
            for i in range(k):
                W2[t][i] -= adim * gW2[t][i] / n
    return {"k": k, "W1": W1, "W2": W2}


def geri_kur(P, z):
    h = [sum(P["W1"][i][t] * z[t] for t in range(ADIM)) for i in range(P["k"])]
    return [sum(P["W2"][t][i] * h[i] for i in range(P["k"])) for t in range(ADIM)]


def hata(P, Z):
    return sum(uzaklik(z, geri_kur(P, z)) for z in Z) / len(Z)


def yon_farki(A, B):
    # iki kosumun kodlayici yonlerinin normlanmis hallerine gore uzakligi
    f = 0.0
    for i in range(A["k"]):
        u, v = A["W1"][i], B["W1"][i]
        nu = sum(q * q for q in u) ** 0.5
        nv = sum(q * q for q in v) ** 0.5
        f += min(sum(abs(u[t] / nu - v[t] / nv) for t in range(ADIM)),
                 sum(abs(u[t] / nu + v[t] / nv) for t in range(ADIM)))
    return f / A["k"]


print(f"taban cizgisi (k=0) {TABAN:.4f}, tur 300, egitim {len(ZE)}")
print(f"{'k':>3}{'parametre':>11}{'egitim 1':>10}{'egitim 2':>10}{'ayrilmis 1':>12}"
      f"{'ayrilmis 2':>12}{'kosum farki':>13}{'yon farki':>11}")
for k in (1, 2, 3, 4):
    A, B = otokodlayici(TOHUM + 1, k), otokodlayici(TOHUM + 2, k)
    a, b = hata(A, ZS), hata(B, ZS)
    print(f"{k:>3}{2 * ADIM * k:>11}{hata(A, ZE):>10.4f}{hata(B, ZE):>10.4f}"
          f"{a:>12.4f}{b:>12.4f}{abs(a - b):>13.4f}{yon_farki(A, B):>11.4f}")
```

```
taban cizgisi (k=0) 2.9007, tur 300, egitim 150
  k  parametre  egitim 1  egitim 2  ayrilmis 1  ayrilmis 2  kosum farki  yon farki
  1         24    1.3001    1.2999      1.2817      1.2815       0.0003     1.6330
  2         48    1.0322    1.0278      1.0597      1.0576       0.0021     2.8634
  3         72    0.7936    0.7502      0.7949      0.7638       0.0311     3.4005
  4         96    0.7219    0.7123      0.7346      0.7314       0.0031     3.3412
```

Taban 2,9007. Tek bir örtük sayı hatayı 1,2817'ye, üç sayı 0,7949'a indiriyor; üçüncüden dördüncüye
geçerken düşüş 0,06 kadar, çünkü kurgunun taşıdığı yapı üç bileşende bitiyor ve dördüncü yön
büyük ölçüde gürültüye oturuyor. M27/K04 aynı ölçüyü hesaplanmış yönlerle almıştı; buradaki
otokodlayıcı yönleri hesaplamıyor, eğim inişiyle arıyor ve tabanın 0,7346'ya kadar altına iniyor.

Son iki sütun bu kursun okumasıdır. İki koşumun hatası dört satırda da neredeyse aynı: en büyük
ayrılık k=3'te 0,0311. Buna karşılık aynı iki koşumun bulduğu yönler 1,6330 ile 3,4005 arasında
ayrılıyor — normlanmış on iki bileşenli yönler için bu büyük bir uzaklıktır. Otokodlayıcı bir
**altuzay** buluyor ve o altuzay koşumdan koşuma tekrarlanıyor; altuzayın içindeki **eksenler**
tekrarlanmıyor. Bir örtük boyutu adlandırmak isteyen biri, adlandırdığı şeyin tohumla birlikte
değiştiğini bilmelidir.

#### Çekişmeli Üretici Ağ ve Kararsızlık

Çekişmeli üretici ağda geri kurulacak bir girdi yoktur. Üretici örtük bir vektörden dizi kurar, ayırt
edici gerçekle üretileni ayırmaya çalışır ve üreticinin kaybı ayırt edicinin yanılmasıdır. İki
ağın hedefi birbirinin tersidir; bu yüzden hiçbir tarafın kaybı tek başına iyiye gitmez ve
"kayıp düştü" cümlesi burada bir ilerleme belirtisi değildir.

```python
GZ, GG, DG, DUR = 3, 6, 6, (30, 60, 90, 120)


def cekismeli(tohum, tur=120, adim=0.6):
    r = uretec(tohum)
    g = lambda: (r() + r() + r() - 1.5) * 0.8
    U = {"W1": [[g() for _ in range(GZ)] for _ in range(GG)],
         "b1": [[0.0] for _ in range(GG)],
         "W2": [[g() for _ in range(GG)] for _ in range(ADIM)],
         "b2": [[0.0] for _ in range(ADIM)]}
    A = {"W1": [[g() for _ in range(ADIM)] for _ in range(DG)],
         "b1": [[0.0] for _ in range(DG)], "w": [[g()] for _ in range(DG)],
         "b": [[0.0]]}
    z, N, iz = uretec(tohum + 77), len(ZE), []

    def uret(v):                        # uretici: ortuk vektorden diziye
        h = [math.tanh(sum(U["W1"][i][j] * v[j] for j in range(GZ)) + U["b1"][i][0])
             for i in range(GG)]
        return h, [sum(U["W2"][t][i] * h[i] for i in range(GG)) + U["b2"][t][0]
                   for t in range(ADIM)]

    def ayirt(x):                       # ayirt edici: diziden tek sayiya
        u = [sum(A["W1"][i][t] * x[t] for t in range(ADIM)) + A["b1"][i][0]
             for i in range(DG)]
        return u, sum(A["w"][i][0] * u[i] for i in range(DG) if u[i] > 0) + A["b"][0][0]

    def inis(P, G):
        for ad in P:
            for i in range(len(P[ad])):
                for j in range(len(P[ad][i])):
                    P[ad][i][j] -= adim * G[ad][i][j]

    def bos(P):
        return {ad: [[0.0] * len(u) for u in P[ad]] for ad in P}

    for t in range(1, tur + 1):
        Z = [[(z() + z() + z() - 1.5) * 1.6 for _ in range(GZ)] for _ in range(N)]
        SAHTE = [uret(v)[1] for v in Z]
        gA = bos(A)
        for x, y in [(u, 1) for u in ZE] + [(u, 0) for u in SAHTE]:
            u, o = ayirt(x)
            d = (1.0 / (1.0 + math.exp(-max(-30.0, min(30.0, o)))) - y) / (2 * N)
            gA["b"][0][0] += d
            for i in range(DG):
                gA["w"][i][0] += d * max(0.0, u[i])
                du = d * A["w"][i][0] if u[i] > 0 else 0.0
                gA["b1"][i][0] += du
                for j in range(ADIM):
                    gA["W1"][i][j] += du * x[j]
        gU = bos(U)
        for v in Z:
            h, x = uret(v)
            u, o = ayirt(x)
            d = (1.0 / (1.0 + math.exp(-max(-30.0, min(30.0, o)))) - 1) / N
            dx = [sum(d * A["w"][i][0] * A["W1"][i][j] for i in range(DG) if u[i] > 0)
                  for j in range(ADIM)]
            for j in range(ADIM):
                gU["b2"][j][0] += dx[j]
                for i in range(GG):
                    gU["W2"][j][i] += dx[j] * h[i]
            for i in range(GG):
                dh = sum(dx[j] * U["W2"][j][i] for j in range(ADIM)) * (1 - h[i] * h[i])
                gU["b1"][i][0] += dh
                for j in range(GZ):
                    gU["W1"][i][j] += dh * v[j]
        inis(A, gA)
        inis(U, gU)
        if t in DUR:
            iz.append((t, sum(ayirt(x)[1] > 0 for x in ZE) / N,
                       sum(ayirt(x)[1] <= 0 for x in SAHTE) / N))
    ort = [sum(x[t] for x in SAHTE) / N for t in range(ADIM)]
    return iz, ort, [(sum((x[t] - ort[t]) ** 2 for x in SAHTE) / N) ** 0.5
                     for t in range(ADIM)]
```

```python
GER_ORT = [sum(x[t] for x in ZE) / len(ZE) for t in range(ADIM)]
GER_SAC = [(sum((x[t] - GER_ORT[t]) ** 2 for x in ZE) / len(ZE)) ** 0.5
           for t in range(ADIM)]
K = [cekismeli(TOHUM + j) for j in (1, 2)]
print(f"{'tur':>5}" + "".join(f"{'k' + str(j + 1) + ' gercek':>12}{'k' + str(j + 1) + ' sahte':>11}"
                              for j in (0, 1)))
for i, (t, _g, _s) in enumerate(K[0][0]):
    print(f"{t:>5}" + "".join(f"{K[j][0][i][1]:>12.4f}{K[j][0][i][2]:>11.4f}"
                             for j in (0, 1)))


def sap(a, b):
    return sum(abs(a[t] - b[t]) for t in range(ADIM)) / ADIM


print(f"{'olcu':<28}{'kosum 1':>10}{'kosum 2':>10}{'iki kosum farki':>18}")
print(f"{'ortalamanin gercekten sapmasi':<28}{sap(K[0][1], GER_ORT):>10.4f}"
      f"{sap(K[1][1], GER_ORT):>10.4f}{sap(K[0][1], K[1][1]):>18.4f}")
print(f"{'sacilimin gercekten sapmasi':<28}{sap(K[0][2], GER_SAC):>10.4f}"
      f"{sap(K[1][2], GER_SAC):>10.4f}{sap(K[0][2], K[1][2]):>18.4f}")
```

```
  tur   k1 gercek   k1 sahte   k2 gercek   k2 sahte
   30      0.6133     0.8067      0.5200     1.0000
   60      0.3933     0.7800      0.6267     1.0000
   90      0.3467     0.6600      0.5800     1.0000
  120      0.4600     0.8533      0.6400     0.9333
olcu                           kosum 1   kosum 2   iki kosum farki
ortalamanin gercekten sapmasi    0.5321    0.8877            1.2707
sacilimin gercekten sapmasi     0.3669    0.5434            0.3418
```

İlk tablo düzenin kararsızlığını doğrudan gösterir. Birinci koşumda ayırt edicinin gerçek diziler
üzerindeki doğruluğu 0,6133'ten 0,3467'ye iniyor ve sonra 0,4600'e dönüyor; bu arada üretilenleri
tanıma oranı 0,8067'den 0,6600'e inip 0,8533'e çıkıyor. İkinci koşumda ayırt edici üretilenlerin
tamamını üç ölçümde de yakalıyor — orada üretici hiç ilerlemedi. Hangi turda durulduğu sonucu
değiştirir ve durma noktasını söyleyecek tek yönlü bir eğri yoktur.

İkinci tablo bu dersin kapanış sayısıdır. İki koşumun ürettiği adım ortalamaları gerçek kümeden
0,5321 ve 0,8877 sapıyor, ama **birbirinden** 1,2707 sapıyor. İki koşum arasındaki uzaklık, her
birinin hedefe uzaklığından büyüktür; yani iki koşum aynı yere doğru değil, iki ayrı yere
gitmiştir. Otokodlayıcıda aynı karşılaştırma 0,0311'i geçmiyordu. Kararlılık farkı düzenin
kapasitesinden değil, hedefinin biçiminden gelir: sabit bir hedefi küçültmek ile hareketli bir
rakibi yanıltmak aynı problem değildir.

#### Özet

- Etiket olmadan da ölçü vardır: otokodlayıcının tabanı ortalama diziyle geri kurmadır ve
  2,9007'dir; bu taban, örtük boyutun sıfır olduğu durumdur.
- Bir örtük boyut hatayı 1,2817'ye, üç boyut 0,7949'a indirir; dördüncü boyut yalnız 0,06 kadar
  ekler, çünkü kurgunun yapısı üç bileşende biter.
- İki koşumun geri kurma hatası en fazla 0,0311 ayrılırken buldukları yönler 1,6330 ile 3,4005
  arasında ayrılır: altuzay tekrarlanır, eksenler tekrarlanmaz.
- Çekişmeli düzende ayırt edicinin gerçek diziler üzerindeki doğruluğu 0,6133 ile 0,3467 arasında
  oynar ve tek yönlü bir eğri vermez; ikinci koşumda üretici hiç ilerlemez.
- İki koşumun ürettiği adım ortalamaları birbirinden 1,2707 ayrılır — her birinin gerçek kümeden
  sapmasından, 0,5321 ve 0,8877'den, daha fazla.

#### Sonraki Adım

On derste mimari seçildi. Evrişim girdinin ızgara yapısını, yineleme ve kapı birimleri sıra
yapısını, dikkat ve çok başlı dikkat uzak adımlara doğrudan erişimi, gömme ayrık simgeleri,
aktarım başka bir görevden gelen temsili, üretici düzenler ise etiketsiz bir hedefi kullandı. Her
birinin kattığı fark tabanına karşı ölçüldü ve her sayının yanına ikinci koşumu yazıldı. Bu on
dersin tamamının ortak bir yanı var ve hiç sorulmadı: hepsi elle yazılmış küçük bir eğitim
döngüsünde koştu. Eğim her seferinde bu sayfada türetildi, veri belleğe sığdı, toplu boyut
örneklem sayısına eşitti, tohum tek bir yerde duruyordu ve hiçbir koşumun kaydı tutulmadı. Sonraki
konu mimariyi değil eğitimin **düzeneğini** ele alır: eğimin elle değil hesap çizgesinden
türetilmesi, verinin toplu üretilmesi, belleğin toplu boyutla ilişkisi, koşumların yeniden
üretilebilir kaydı ve ayar aramasının koşum değişkenliğiyle nasıl yanıldığı.

## Eğitim Pratiği

Eğitimin düzeneğinin sayıyı ne kadar oynattığının ölçülmesi: hesap çizgesi ve otomatik türevin elle yazılan geri yayılımla verdiği eğim farkı ve tuttuğu kod, veri artırmanın kattığı fark ile artırmanın sızıntı ürettiği durum ve toplu üretim sırasının sonucu oynatması, toplu boyutun parametre, etkinleştirme ve eğim için tutulan sayı adediyle ilişkisi ve öğrenme adımıyla birlikte değişmesi gerektiği, eğitime özgü sabitlenecek kalemler ve biri serbest bırakıldığında sonucun oynaması, koşum değişkenliği adaylar arasındaki farktan büyük olduğunda aramanın neyi seçtiği.

### Hesap Çizgesi ve Otomatik Türev

Source: https://academia.sh/tr/kurslar/derin-ogrenme/hesap-cizgesi-ve-otomatik-turev

Eğim hesabını mimariden ayıran soyutlamanın ders içinde yazılması ve elle yazılan geri yayılımla karşılaştırılması: otuz iki satırlık dört işlemli bir düzenek, seksen bir parametrenin eğimini elle yazılan on sekiz satırlık geri yayılımdan 2,78e-17 farkla veriyor ve otuz örnekli bir toplu için 6.622 düğüm kuruyor. Kursun üç sayısı burada kurulur: taban çizgisi 0,7579, ağın sayısı 0,8095 ve yalnız başlangıç değerleri değişen ikinci koşum 0,7937. On ilklendirmenin aralığı 0,7857 ile 0,8095 arasındadır ve M27/K03'ün karar ağacı (0,7857) ile doğrusal modelinin (0,8016) sayıları bu aralığın içine düşer.

Önceki on derste mimari seçildi: evrişim, havuzlama, atlamalı bağlantı, yinelemeli durum, kapı
birimi, dikkat, gömme, aktarım, otokodlayıcı. Her birinde ağın yapısı değişti ve eğim hesabı
**yeniden türetilip yeniden yazıldı**; hepsi elle yazılmış küçük bir eğitim döngüsünde koştu.
Gerçek eğitimin **düzeneği** hiç ele alınmadı.

Bu konu o düzeneği ele alır ve ilk parçası eğim hesabını mimariden ayıran soyutlamadır. Katalogda
bu ders derin öğrenme kütüphanelerini anar; burada anlatılan **kütüphaneler değil, kütüphanelerin
sattığı soyutlamadır** — hesap çizgesi (computation graph) ve otomatik türev (automatic
differentiation) — ve soyutlama ders içinde yazılır. Ölçü üç sayıdır: elle yazılan geri yayılım
ile otomatik türevin verdiği eğim arasındaki **fark**, iki yolun **kaç satır** tuttuğu ve
çizgenin kaç **düğüm** kurduğu.

- **EP1.** Küme M27/K01–K04'ün **kurgu** abone tablosudur, tohum 20260218, 1.260 abone; etiket
  kaçak ya da arıza şüphesidir ve kurgudur. Taban çizgisi **en sık sınıfı söylemektir**: sınamada
  0,7579, M27/K01–K03'ten devralınır.
- **EP2.** Eğitim kümesi bu konuda **756 yerine 300 satırdır**; bir ölçek kararıdır ve konunun
  bütün blokları birkaç saniyede koşar. Sınama kümesi 252 satırdır ve bir abone 0,0040 eder.
- **EP3.** Ağ bu konu boyunca sabittir: sekiz öznitelik, sekiz birimli tek gizli katman
  (doğrultulmuş doğrusal birim), tek çıkış; kayıp **çapraz düzensizliktir**. Katmanın sabit terimi
  **yanma** diye anılır ve istatistikteki **yanlılık**tan ayrıdır. Ölçekleme yalnız **eğitim
  kümesinden** öğrenilir (M27/K02, boru hattı).
- **EP4.** Kursun üçüncü sayısı **ikinci koşumdur**: aynı ağ, aynı veri, aynı örnek sırası, yalnız
  **başlangıç değerleri** değişir. Ölçü ham süre değildir: çizgenin bedeli **düğüm**, kodun bedeli
  **satır** sayısıyla ölçülür.
- **EP5.** Kayıp düğümü **kaynaşıktır**: sigmoit ile çapraz düzensizlik tek düğümde tutulur, çünkü
  ayrı tutulduğunda büyük çıkışlarda taşma olur. Yerel türevi iki yolda da aynıdır. Düzenek
  **modeldir** ve hiçbir çerçeve, kitaplık ya da satıcı adı anılmaz.

#### Küme, Ölçek ve Taban Çizgisi

```python
# ORTAK — KURGUDUR. M27/K01-K04'un abone tablosu ayni tohumla (20260218) uretilir;
# etiket kacak/ariza suphesidir. Egitim kumesi bu konuda 756'dan 300 satira
# KUCULTULMUSTUR: konunun butun bloklari birkac saniyede kosar.
import math

TOHUM, HAM, M32 = 20260218, 1400, 0xFFFFFFFF
BOLGE = [("kuzey", 0.28, 21, 0.00), ("guney", 0.22, 17, -0.10),
         ("dogu", 0.18, 26, 0.30), ("bati", 0.14, 14, -0.05),
         ("merkez", 0.18, 23, 0.05)]
ALAN = ["b_guney", "b_dogu", "b_bati", "b_merkez",
        "hane", "memnuniyet", "donem", "ortalama"]


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


def ayrik(u, w):
    t = 0.0
    for i, x in enumerate(w):
        t += x
        if u < t:
            return i
    return len(w) - 1


def karistir(dizi, tohum):
    r, s = uretec(tohum), list(dizi)
    for i in range(len(s) - 1, 0, -1):
        j = int(r() * (i + 1))
        s[i], s[j] = s[j], s[i]
    return s


VERI = []
for i in range(HAM):
    r = uretec(TOHUM + i)
    b = BOLGE[ayrik(r(), [x[1] for x in BOLGE])]
    hane = 1 + ayrik(r(), [0.06, 0.24, 0.30, 0.24, 0.11, 0.05])
    memnun = 1 + ayrik(r(), [0.08, 0.14, 0.27, 0.34, 0.17])
    if r() < 0.046:
        continue
    no = 10001 + i
    r, v = uretec(TOHUM + 7000 + no), []
    for d in range(ayrik(r(), [0.05, 0.12, 0.21, 0.62])):
        v.append(0.0 if r() < 0.038 else math.floor(
            b[2] * math.exp((r() + r() + r() - 1.5) * 0.62)
            * (1 - d * 0.05) * 100 + 0.5) / 100)
        r()
    if not v:
        continue
    ort, oyn, r = sum(v) / len(v), max(v) - min(v), uretec(TOHUM + 51000 + no)
    z = (0.052 * (ort - 20) + 0.85 * (min(v) == 0.0) + 0.026 * oyn
         + 0.24 * (hane >= 5) - 0.20 * (memnun >= 4) + b[3]
         + 0.9 * (no - 10001) / 1399 + (r() + r() + r() - 1.5) * 1.30)
    x = {"hane": hane, "memnuniyet": memnun, "donem": len(v),
         "ortalama": round(ort, 2), "supheli": int(z > 1.35)}
    for q in BOLGE[1:]:
        x["b_" + q[0]] = int(b[0] == q[0])
    VERI.append(x)

K = karistir(VERI, TOHUM + 90000)
EGT, SIN = K[:300], K[1008:]


def tablo(satirlar, ist=None):
    X = [[float(s[a]) for a in ALAN] for s in satirlar]
    if ist is None:                       # olcek yalniz egitim kumesinden ogrenilir
        ist = []
        for j in range(4, 8):
            m = sum(v[j] for v in X) / len(X)
            ist.append((j, m, math.sqrt(sum((v[j] - m) ** 2 for v in X) / len(X))))
    for v in X:
        for j, m, sd in ist:
            v[j] = (v[j] - m) / sd
    return X, [s["supheli"] for s in satirlar], ist


XE, yE, IST = tablo(EGT)
XS, yS, _ = tablo(SIN, IST)
TABAN = sum(v == 0 for v in yS) / len(yS)
print(f"kurgu abone {len(VERI)}; egitim {len(XE)} (756'dan kucultuldu), sinama "
      f"{len(XS)}, oznitelik {len(ALAN)}, egitimde supheli pay "
      f"{sum(yE) / len(yE):.4f}")
print(f"taban cizgisi (en sik sinifi soylemek, sinamada) {TABAN:.4f}")
```

```
kurgu abone 1260; egitim 300 (756'dan kucultuldu), sinama 252, oznitelik 8, egitimde supheli pay 0.2200
taban cizgisi (en sik sinifi soylemek, sinamada) 0.7579
```

#### Çizge Bir Veri Yapısıdır

Elle türetmenin sıkıntısı hesabın zorluğu değil, **yapıya bağlı olmasıdır**: katman eklendiğinde
türev yeniden yazılır. Hesap çizgesi bu bağı koparır. Her ara değer bir **düğüm** olarak tutulur ve
düğüm kendi değerini, **atalarını** ve **atalarına göre yerel türevini** saklar; geri geçiş çizgeyi
tersten gezip her düğümün eğimini atalarına dağıtır. Zincir kuralı bu dağıtımdır ve yalnız bir kez
yazılır.

```python
# Hesap cizgesi duzenegi — MODELDIR. Dort islem: toplama, carpma, dogrultma ve
# kaynasik kayip. Her dugum degerini, egimini, atalarini ve ATALARINA GORE YEREL
# TUREVINI tutar; geri adim yalnizca bunlari kullanir.
import inspect


class Deger:
    __slots__ = ("v", "e", "ata", "yerel")

    def __init__(self, v, ata=(), yerel=()):
        self.v, self.e, self.ata, self.yerel = float(v), 0.0, ata, yerel

    def __add__(self, o):
        o = o if isinstance(o, Deger) else Deger(o)
        return Deger(self.v + o.v, (self, o), (1.0, 1.0))

    def __mul__(self, o):
        o = o if isinstance(o, Deger) else Deger(o)
        return Deger(self.v * o.v, (self, o), (o.v, self.v))

    def dogrult(self):
        return Deger(self.v if self.v > 0 else 0.0, (self,),
                     (1.0 if self.v > 0 else 0.0,))

    def kayip(self, y):                  # capraz duzensizlik, dogrudan cikisa
        p = 1.0 / (1.0 + math.exp(-self.v)) if self.v > -30 else 0.0
        k = max(0.0, self.v) + math.log(1.0 + math.exp(-abs(self.v))) - self.v * y
        return Deger(k, (self,), (p - y,))


def geriye(kok):
    sira, gorulen = [], set()

    def gez(d):
        if id(d) in gorulen:
            return
        gorulen.add(id(d))
        for a in d.ata:
            gez(a)
        sira.append(d)

    gez(kok)
    kok.e = 1.0
    for d in reversed(sira):
        for a, y in zip(d.ata, d.yerel):
            a.e += d.e * y
    return len(sira)


SATIR = sum(len([s for s in inspect.getsource(o).splitlines() if s.strip()])
            for o in (Deger, geriye))
print(f"duzenek {SATIR} satir, 4 islem;  L = 5 * dogrult(a*b + c)")
for bd in (3.0, -3.0):
    a, b, c = Deger(2.0), Deger(bd), Deger(4.0)
    L = (a * b + c).dogrult() * Deger(5.0)
    n = geriye(L)
    print(f"  a=2 b={bd:+.0f} c=4 -> L={L.v:5.1f}, {n} dugum;  dL/da {a.e:>6.1f}"
          f"   dL/db {b.e:>6.1f}   dL/dc {c.e:>6.1f}")
```

```
duzenek 32 satir, 4 islem;  L = 5 * dogrult(a*b + c)
  a=2 b=+3 c=4 -> L= 50.0, 8 dugum;  dL/da   15.0   dL/db   10.0   dL/dc    5.0
  a=2 b=-3 c=4 -> L=  0.0, 8 dugum;  dL/da    0.0   dL/db    0.0   dL/dc    0.0
```

Otuz iki satır ve dört işlem. Türevler elle denetlenebilir: $L = 5\,(ab+c)$ pozitif bölgede
$\partial L/\partial a = 5b = 15$, $\partial L/\partial b = 5a = 10$ ve $\partial L/\partial c = 5$
verir; çıktı bunu söylüyor. İkinci çağrıda yalnız $b$ eksi üç oldu: toplam eksiye düştü, doğrultma
kapısı kapandı, **üç türev de sıfır** oldu. Çizge aynı, kod aynı; değişen yalnız verinin çizgede
açtığı yol.

#### Aynı Eğim, İki Yol

```python
# Ayni agin egimi iki yoldan: cizgeyi gezerek ve zincir kuralini ELLE yazarak.
# Parametreler tek duz liste: p[j*G+i] agirlik, p[H*G+j] yanma, p[H*G+H+j] ve
# p[-1] cikis katmani.
G, H = len(ALAN), 8


def ilklendir(tohum):                        # kazanc olcekli ilklendirme
    r = uretec(tohum)
    return [(r() * 2 - 1) * math.sqrt(2.0 / G) for _ in range(H * G)] + [0.0] * H \
        + [(r() * 2 - 1) * math.sqrt(2.0 / H) for _ in range(H)] + [0.0]


def cizgeyle(p, X, y, par):
    d, top = [Deger(v) for v in p], None
    for k in par:
        x, o = X[k], d[-1]
        for j in range(H):
            z = d[H * G + j]
            for i in range(G):
                z = z + d[j * G + i] * x[i]
            o = o + d[H * G + H + j] * z.dogrult()
        L = o.kayip(y[k])
        top = L if top is None else top + L
    kok = top * (1.0 / len(par))
    return kok, geriye(kok), [u.e for u in d]


def elle(p, X, y, par):
    g, kayip = [0.0] * len(p), 0.0
    for k in par:
        x, hh = X[k], [0.0] * H
        for j in range(H):
            s = p[H * G + j] + sum(p[j * G + i] * x[i] for i in range(G))
            hh[j] = s if s > 0 else 0.0
        o = p[-1] + sum(p[H * G + H + j] * hh[j] for j in range(H))
        kayip += max(0.0, o) + math.log(1.0 + math.exp(-abs(o))) - o * y[k]
        d = 1.0 / (1.0 + math.exp(-o)) - y[k]    # kayip dugumunun yerel turevi
        g[-1] += d
        for j in range(H):
            g[H * G + H + j] += d * hh[j]
            if hh[j] > 0:                        # dogrultma kapisi kapaliysa gecmez
                g[H * G + j] += d * p[H * G + H + j]
                for i in range(G):
                    g[j * G + i] += d * p[H * G + H + j] * x[i]
    return kayip / len(par), [v / len(par) for v in g]


P0, TOPLU = ilklendir(TOHUM + 1), list(range(30))
kok, DUGUM, oto = cizgeyle(P0, XE, yE, TOPLU)
kayip, el = elle(P0, XE, yE, TOPLU)
print(f"parametre {len(P0)}; 30 ornekli toplu icin cizge {DUGUM} dugum, "
      f"ornek basina {DUGUM / 30:.1f}")
print(f"kayip  cizge {kok.v:.10f}   elle {kayip:.10f}")
print(f"egimlerin en buyuk mutlak farki {max(abs(u - v) for u, v in zip(oto, el)):.2e}"
      f"  (en buyuk egim {max(abs(v) for v in oto):.4f})")
print(f"elle yazilan yol {len(inspect.getsource(elle).splitlines())} satir "
      f"ve yalniz bu aga ait; duzenek {SATIR} satir ve agi hic bilmiyor")
```

```
parametre 81; 30 ornekli toplu icin cizge 6622 dugum, ornek basina 220.7
kayip  cizge 0.7366651135   elle 0.7366651135
egimlerin en buyuk mutlak farki 2.78e-17  (en buyuk egim 0.3097)
elle yazilan yol 18 satir ve yalniz bu aga ait; duzenek 32 satir ve agi hic bilmiyor
```

Dersin birinci sayısı burada. Seksen bir parametrenin eğimi iki yoldan hesaplandı ve en büyük
mutlak fark **2,78e-17** çıktı: kayan noktalı toplama sırasının ürettiği fark. En büyük eğim
0,3097 olduğuna göre iki yol **on beş basamak boyunca** aynı sayıyı veriyor; eşitlik `==` ile
değil, farkın en büyük eğime oranıyla denetlenir.

İkinci sayı tersini söyler. Elle yazılan yol on sekiz satır tuttu ve bu satırlar **yalnız bu ağa**
aittir; katman eklenirse yeniden yazılır. Otuz iki satırlık düzenek ağın yapısını hiç bilmez,
ileri geçişi yazan kim olursa olsun eğimi aynı `geriye` çağrısı verir. Bedeli üçüncü sayıdadır:
otuz örneklik toplu için çizge **6.622 düğüm** kurdu, örnek başına 220,7. Elle yazılan yol düğüm
tutmaz, ara değerleri yerinde toplar.

#### Kursun Üç Sayısı

```python
# Egitim ELLE yazilan geri yayilimla koser; cizge dogrulama icin kuruldu. Iki
# kosum yalnizca BASLANGIC DEGERLERINDE ayrilir: ornek sirasi ikisinde de ayni.
ADIM, TUR, TOPLU_BOY, SIRA_TOHUMU = 0.30, 40, 30, TOHUM + 700


def egit(tohum):
    p = ilklendir(tohum)
    for t in range(TUR):
        dizin = karistir(range(len(XE)), SIRA_TOHUMU + t)
        for bas in range(0, len(dizin), TOPLU_BOY):
            _, g = elle(p, XE, yE, dizin[bas:bas + TOPLU_BOY])
            p = [a - ADIM * b for a, b in zip(p, g)]
    return p


def dogruluk(p, X, y):
    n = 0
    for k in range(len(X)):
        x = X[k]
        o = p[-1] + sum(p[H * G + H + j] * max(0.0, p[H * G + j]
                        + sum(p[j * G + i] * x[i] for i in range(G)))
                        for j in range(H))
        n += (o >= 0.0) == (y[k] == 1)
    return n / len(X)


S = [dogruluk(egit(TOHUM + t), XS, yS) for t in range(1, 11)]
print(f"ag {G}-{H}-1, {len(P0)} parametre, {TUR} tur, toplu boy {TOPLU_BOY}, "
      f"ogrenme adimi {ADIM}, {TUR * (len(XE) // TOPLU_BOY)} guncelleme")
print(f"  taban cizgisi   {TABAN:.4f}")
print(f"  agin sayisi     {S[0]:.4f}   (fark {S[0] - TABAN:+.4f})")
print(f"  ikinci kosum    {S[1]:.4f}   (fark {S[1] - TABAN:+.4f})")
print(f"on ilklendirmede aralik {min(S):.4f} - {max(S):.4f}, genislik "
      f"{max(S) - min(S):.4f} ({round((max(S) - min(S)) * len(XS))} abone)")
AGAC, DOGRUSAL = 198, 202       # M27/K03'un sayilari, ayni 252 satirlik sinamada
en_az, en_cok = round(min(S) * len(XS)), round(max(S) * len(XS))
print(f"karsilastirma cizgileri (756 satirlik egitim kumesiyle): karar agaci {AGAC / len(XS):.4f}, "
      f"dogrusal model {DOGRUSAL / len(XS):.4f}; agin araligi {en_az}-{en_cok} abone"
      f" -> {sum(en_az <= v <= en_cok for v in (AGAC, DOGRUSAL))}/2 iceride")
print(f"ayni egitim cizge uzerinden kossaydi "
      f"{TUR * (len(XE) // TOPLU_BOY) * DUGUM:,} dugum kurulurdu")
```

```
ag 8-8-1, 81 parametre, 40 tur, toplu boy 30, ogrenme adimi 0.3, 400 guncelleme
  taban cizgisi   0.7579
  agin sayisi     0.8095   (fark +0.0516)
  ikinci kosum    0.7937   (fark +0.0357)
on ilklendirmede aralik 0.7857 - 0.8095, genislik 0.0238 (6 abone)
karsilastirma cizgileri (756 satirlik egitim kumesiyle): karar agaci 0.7857, dogrusal model 0.8016; agin araligi 198-204 abone -> 2/2 iceride
ayni egitim cizge uzerinden kossaydi 2,648,800 dugum kurulurdu
```

Üç sayı yan yana: taban çizgisi 0,7579, ağın sayısı 0,8095, ikinci koşum 0,7937. Aradaki fark
0,0158, yani dört abone; iki koşum arasındaki bu fark, tabanın üstündeki kazancın (+0,0516) üçte
birine yakındır. On ilklendirmede aralık **0,7857 ile 0,8095** arasına yayılıyor, altı abone
genişliğinde. Kapasitede, veride, öğrenme adımında ve tur sayısında **hiçbir şey değişmeden** ağın
sayısı bu aralıkta herhangi bir yere düşebilir.

M27/K03'ün karar ağacı sınama kümesinde 198, doğrusal modeli 202 aboneyi doğru ayırdı; ağın on
koşumdaki aralığı 198–204 ve **ikisi de içeride**. Karşılaştırma birebir değildir, o sayılar 756
satırlık eğitim kümesinden geldi; ama yön nettir: ağın tek koşumda ürettiği sayıyla iki eski
aileyi geçtiğini söylemek, koşum değişkenliğini bulgu diye okumaktır. Kursun kuralı bu yüzden
vardır — **aynı kapasitenin iki koşumda iki ayrı sayı verdiği yazılmayan sonuç ölçülmemiş
sayılır.**

#### Özet

- Hesap çizgesi bir veri yapısıdır: her düğüm değerini, atalarını ve yerel türevini tutar; geri
  geçiş çizgeyi tersten gezer ve zincir kuralı yalnız bir kez yazılır.
- Otuz iki satırlık dört işlemli düzenek, seksen bir parametrenin eğimini elle yazılan on sekiz
  satırlık geri yayılımdan **2,78e-17** farkla veriyor; en büyük eğim 0,3097.
- Otuz iki satır ağın yapısını bilmez, on sekiz satır yalnız bu ağa aittir; bedel otuz örneklik
  toplu için 6.622 düğüm, örnek başına 220,7.
- Kursun üç sayısı: taban çizgisi 0,7579, ağın sayısı 0,8095, ikinci koşum 0,7937; aradaki fark
  0,0158, tabanın üstündeki kazancın üçte birine yakın.
- On ilklendirmenin aralığı 0,7857–0,8095 ve M27/K03'ün karar ağacı (0,7857) ile doğrusal modelinin
  (0,8016) sayıları bu aralığın içine düşüyor; tek koşumla okunan üstünlük koşum değişkenliğinden
  ayrılamaz.

#### Sonraki Adım

Eğim doğru hesaplandı, ama ağa hangi örneklerin hangi sırayla verildiği tek bir satırda geçti:
eğitim kümesi her turda karıştırıldı ve otuzarlık topluya bölündü. O satır bir karardır. Sonraki
ders veri yükleme hattını ele alır: toplu üretim sırasının sayıyı ne kadar oynattığı, veri
artırmanın ne kattığı ve artırmanın hangi durumda ayrılmış kümeye sızıntı ürettiği ölçülür.

### Veri Yükleme Hattı

Source: https://academia.sh/tr/kurslar/derin-ogrenme/veri-yukleme-hatti

Toplu üretim sırasının, veri artırmanın ve artırmanın ürettiği sızıntının ayrı ayrı ölçülmesi: aynı ağ ve aynı 400 güncellemeyle dört toplu sırası sınama kümesinde 0,8016 ile 0,8095 arasında dört sayı verirken, aynı sırada yalnız başlangıç değerleri değiştiğinde fark 0,0159'a çıkıyor — sıra kararı koşum değişkenliğinin yarısı kadar oynatıyor. Artırmanın kattığı fark üç koşumun ortalamasında +0,0026, +0,0013 ve −0,0079; üçü de tek bir sıranın koşum aralığından küçüktür. Artırma bölmeden önce yapıldığında sınama kümesinin 138 satırının ikizi eğitim kümesine giriyor ve ikizli-temiz alt küme farkı −0,0211'den −0,0008'e kayıyor: kayma +0,0203.

Önceki ders eğimi iki yoldan hesapladı ve ikisinin makine duyarlığında aynı sayıyı verdiğini
gösterdi. O dersin eğitim döngüsünde bir satır sorgusuz geçti: eğitim kümesi her turda karıştırıldı
ve otuzarlık topluya bölündü. Bu satır ağın **ne gördüğünü** değil **hangi sırayla gördüğünü**
belirler.

Veri yükleme hattı üç karardan oluşur: hangi örnekler, hangi sırayla, kaç tanesi bir arada.
Üçüncüsü toplu boyudur ve sonraki derse bırakılır. Bu ders ilk ikisini ölçer ve bir dördüncüyü
ekler: **veri artırma** (augmentation). Ölçü iki sayıdır: artırmanın kattığı fark ve artırmanın
**sızıntı ürettiği** durumdaki şişme.

- **EP7.** Küme, ağ, taban çizgisi ve elle yazılan geri yayılım önceki dersten devralınır: kurgu
  abone tablosu, 300 satırlık eğitim kümesi, 8-8-1 ağ, 81 parametre, sınamada taban 0,7579.
- **EP8.** Karşılaştırmaların koşabilmesi için **güncelleme sayısı 400'de sabit tutulur**. Artırılmış
  küme iki kat büyük olduğu için tur sayısı kırktan yirmiye iner; ağ her iki kurulumda da aynı
  sayıda eğim adımı atar.
- **EP9.** Artırma burada **tablo verisine gürültü eklemektir** ve bir modeldir: sürekli dört sütuna
  standart sapma birimiyle ölçülen gürültü eklenmiş kopya satırlar üretilir, etiket kopyalanır ve
  değiştirilmez. Alana özgü artırma yordamları M27/K06'ya bırakılır.
- **EP10.** Sızıntı kurulumunda **sınama kümesi her iki durumda da aynı 252 orijinal satırdır**;
  değişen yalnız eğitim kümesine hangi satırların ikizinin girdiğidir. Sızıntı M27/K02'de ölçüldü,
  yordamı tekrarlanmaz.
- **EP11.** Koşum değişkenliği bir gürültü değil, ölçülen bir büyüklüktür: her karşılaştırma **en az
  iki koşumla** basılır ve kattığı fark bu aralıkla birlikte okunur.

#### Küme, Ağ ve Taban Çizgisi

```python
# ORTAK — KURGUDUR. M27/K01-K04'un abone tablosu ayni tohumla (20260218) uretilir;
# egitim kumesi 756'dan 300 satira kucultulmustur. Ag ve elle yazilan geri yayilim
# onceki dersten devralinir: 8-8-1, 81 parametre, 400 guncelleme, adim 0.30.
import math

TOHUM, HAM, M32 = 20260218, 1400, 0xFFFFFFFF
BOLGE = [("kuzey", 0.28, 21, 0.00), ("guney", 0.22, 17, -0.10),
         ("dogu", 0.18, 26, 0.30), ("bati", 0.14, 14, -0.05),
         ("merkez", 0.18, 23, 0.05)]
ALAN = ["b_guney", "b_dogu", "b_bati", "b_merkez",
        "hane", "memnuniyet", "donem", "ortalama"]


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


def ayrik(u, w):
    t = 0.0
    for i, x in enumerate(w):
        t += x
        if u < t:
            return i
    return len(w) - 1


def karistir(dizi, tohum):
    r, s = uretec(tohum), list(dizi)
    for i in range(len(s) - 1, 0, -1):
        j = int(r() * (i + 1))
        s[i], s[j] = s[j], s[i]
    return s


VERI = []
for i in range(HAM):
    r = uretec(TOHUM + i)
    b = BOLGE[ayrik(r(), [x[1] for x in BOLGE])]
    hane = 1 + ayrik(r(), [0.06, 0.24, 0.30, 0.24, 0.11, 0.05])
    memnun = 1 + ayrik(r(), [0.08, 0.14, 0.27, 0.34, 0.17])
    if r() < 0.046:
        continue
    no = 10001 + i
    r, v = uretec(TOHUM + 7000 + no), []
    for d in range(ayrik(r(), [0.05, 0.12, 0.21, 0.62])):
        v.append(0.0 if r() < 0.038 else math.floor(
            b[2] * math.exp((r() + r() + r() - 1.5) * 0.62)
            * (1 - d * 0.05) * 100 + 0.5) / 100)
        r()
    if not v:
        continue
    ort, oyn, r = sum(v) / len(v), max(v) - min(v), uretec(TOHUM + 51000 + no)
    z = (0.052 * (ort - 20) + 0.85 * (min(v) == 0.0) + 0.026 * oyn
         + 0.24 * (hane >= 5) - 0.20 * (memnun >= 4) + b[3]
         + 0.9 * (no - 10001) / 1399 + (r() + r() + r() - 1.5) * 1.30)
    x = {"hane": hane, "memnuniyet": memnun, "donem": len(v),
         "ortalama": round(ort, 2), "supheli": int(z > 1.35)}
    for q in BOLGE[1:]:
        x["b_" + q[0]] = int(b[0] == q[0])
    VERI.append(x)

K = karistir(VERI, TOHUM + 90000)
EGT, SIN = K[:300], K[1008:]


def tablo(satirlar, ist=None):
    X = [[float(s[a]) for a in ALAN] for s in satirlar]
    if ist is None:                       # olcek yalniz egitim kumesinden ogrenilir
        ist = []
        for j in range(4, 8):
            m = sum(v[j] for v in X) / len(X)
            ist.append((j, m, math.sqrt(sum((v[j] - m) ** 2 for v in X) / len(X))))
    for v in X:
        for j, m, sd in ist:
            v[j] = (v[j] - m) / sd
    return X, [s["supheli"] for s in satirlar], ist


XE, yE, IST = tablo(EGT)
XS, yS, _ = tablo(SIN, IST)
TABAN = sum(v == 0 for v in yS) / len(yS)

G, H = len(ALAN), 8


def ilklendir(tohum):                    # kazanc olcekli ilklendirme
    r = uretec(tohum)
    return [(r() * 2 - 1) * math.sqrt(2.0 / G) for _ in range(H * G)] + [0.0] * H \
        + [(r() * 2 - 1) * math.sqrt(2.0 / H) for _ in range(H)] + [0.0]


def egim(p, X, y, par):                  # onceki dersin elle yazilan geri yayilimi
    g = [0.0] * len(p)
    for k in par:
        x, hh = X[k], [0.0] * H
        for j in range(H):
            s = p[H * G + j] + sum(p[j * G + i] * x[i] for i in range(G))
            hh[j] = s if s > 0 else 0.0
        s = p[-1] + sum(p[H * G + H + j] * hh[j] for j in range(H))
        d = (1.0 / (1.0 + math.exp(-s)) if s > -30 else 0.0) - y[k]
        g[-1] += d
        for j in range(H):
            g[H * G + H + j] += d * hh[j]
            if hh[j] > 0:
                g[H * G + j] += d * p[H * G + H + j]
                for i in range(G):
                    g[j * G + i] += d * p[H * G + H + j] * x[i]
    return [v / len(par) for v in g]


ADIM, TOPLU = 0.30, 30


def egit(X, y, tohum, sira, guncelleme=400):
    p, t = ilklendir(tohum), 0
    while t * (len(X) // TOPLU) < guncelleme:
        d = sira(t, len(X))
        for b in range(0, len(d) - TOPLU + 1, TOPLU):
            p = [a - ADIM * v for a, v in zip(p, egim(p, X, y, d[b:b + TOPLU]))]
        t += 1
    return p


def dogruluk(p, X, y):
    n = 0
    for k in range(len(X)):
        x = X[k]
        o = p[-1] + sum(p[H * G + H + j] * max(0.0, p[H * G + j]
                        + sum(p[j * G + i] * x[i] for i in range(G)))
                        for j in range(H))
        n += (o >= 0.0) == (y[k] == 1)
    return n / len(X)


print(f"kurgu: egitim {len(XE)} satir (756'dan kucultuldu), sinama {len(XS)}, "
      f"oznitelik {G}, parametre {len(ilklendir(TOHUM))}")
print(f"taban cizgisi (en sik sinifi soylemek, sinamada) {TABAN:.4f}")
```

```
kurgu: egitim 300 satir (756'dan kucultuldu), sinama 252, oznitelik 8, parametre 81
taban cizgisi (en sik sinifi soylemek, sinamada) 0.7579
```

#### Toplu Üretim Sırası

Dört sıra kararı vardır ve dördü de savunulabilir. **Sırasız**: satırlar dosyadaki sırayla verilir,
her tur aynı toplular kurulur. **Bir kez**: küme başlangıçta bir kez karıştırılır ve o sıra kırk tur
korunur. **Her tur**: küme her turda yeniden karıştırılır ve toplular her turda başka satırlardan
kurulur; bu sonuncusu iki ayrı tohumla denenir.

```python
# Toplu uretim SIRASI bir karardir: ayni veri, ayni ag, ayni 400 guncelleme.
# Dort sira, her biri iki ilklendirmeyle.
DIZI = {"sirasiz": lambda t, n: list(range(n)),
        "bir kez": lambda t, n: karistir(range(n), TOHUM + 700),
        "her tur A": lambda t, n: karistir(range(n), TOHUM + 700 + t),
        "her tur B": lambda t, n: karistir(range(n), TOHUM + 800 + t)}
S = {}
print(f"{'toplu sirasi':<13} {'kosum 1':>8} {'kosum 2':>8} {'fark':>8}")
for ad, s in DIZI.items():
    S[ad] = [dogruluk(egit(XE, yE, TOHUM + k, s), XS, yS) for k in (1, 2)]
    print(f"{ad:<13} {S[ad][0]:>8.4f} {S[ad][1]:>8.4f} {S[ad][1] - S[ad][0]:>+8.4f}")
ilk = [v[0] for v in S.values()]
en = max(abs(v[1] - v[0]) for v in S.values())
print(f"siranin oynattigi (ayni ilklendirme, dort sira) {max(ilk) - min(ilk):.4f} "
      f"({round((max(ilk) - min(ilk)) * len(XS))} abone)")
print(f"ilklendirmenin oynattigi (ayni sira, iki kosum) en cok {en:.4f} "
      f"({round(en * len(XS))} abone)")
SIRA = DIZI["her tur A"]
```

```
toplu sirasi   kosum 1  kosum 2     fark
sirasiz         0.8056   0.7897  -0.0159
bir kez         0.8016   0.8016  +0.0000
her tur A       0.8095   0.7937  -0.0159
her tur B       0.8016   0.8056  +0.0040
siranin oynattigi (ayni ilklendirme, dort sira) 0.0079 (2 abone)
ilklendirmenin oynattigi (ayni sira, iki kosum) en cok 0.0159 (4 abone)
```

Dört sıra, aynı ağ, aynı 400 güncelleme: sınama sayıları 0,8056, 0,8016, 0,8095 ve 0,8016. Sıranın
oynattığı **0,0079**, iki abone. Bu bir bulgu değildir ama bir karardır: hangi sıra seçilirse
seçilsin gerekçesi yazılmalıdır, çünkü sonucu oynatır.

Aynı tablo ikinci sütunuyla okunduğunda ölçek yerine oturuyor. Sıra sabit tutulup yalnız başlangıç
değerleri değiştiğinde fark **0,0159**'a, dört aboneye çıkıyor — sıranın oynattığının iki katı.
"Sırasız" ve "her tur A" satırlarında ikinci koşum birincinin dört abone altına düşüyor, "bir kez"
satırında iki koşum tıpatıp aynı sayıyı veriyor. Aynı satırda iki koşumun eşit çıkması, sıranın
etkisiz olduğunu değil, **iki koşumun bütün koşumlar olmadığını** gösterir.

#### Veri Artırma

```python
# Veri artirma: surekli dort sutuna gurultu eklenmis KOPYA satirlar; gurultu
# olcegi standart sapma birimindedir. GUNCELLEME SAYISI 400'de SABIT tutulur —
# artirilmis kume iki kat buyuk oldugu icin tur sayisi yariya iner.
def artir(X, y, tohum, sapma):
    r, XA, yA = uretec(tohum), list(X), list(y)
    for k in range(len(X)):
        v = list(X[k])
        for j in range(4, 8):
            v[j] += (r() + r() + r() - 1.5) * 2 * sapma
        XA.append(v)
        yA.append(y[k])
    return XA, yA


MODEL, ORT = {}, {}
print(f"{'artirma':<13} {'satir':>6} {'tur':>4} {'kosum1':>7} {'kosum2':>7} "
      f"{'kosum3':>7} {'ort':>7}")
for sapma in (0.0, 0.05, 0.15, 0.40):
    XA, yA = (XE, yE) if sapma == 0.0 else artir(XE, yE, TOHUM + 11000, sapma)
    MODEL[sapma] = [egit(XA, yA, TOHUM + k, SIRA) for k in (1, 2, 3)]
    r = [dogruluk(p, XS, yS) for p in MODEL[sapma]]
    ORT[sapma] = sum(r) / len(r)
    ad = "yok" if sapma == 0.0 else f"sapma {sapma:.2f}"
    print(f"{ad:<13} {len(XA):>6} {400 // (len(XA) // 30):>4} "
          + " ".join(f"{v:>7.4f}" for v in r) + f" {ORT[sapma]:>7.4f}")
for sapma in (0.05, 0.15, 0.40):
    print(f"artirmanin kattigi (sapma {sapma:.2f}) {ORT[sapma] - ORT[0.0]:+.4f}")
```

```
artirma        satir  tur  kosum1  kosum2  kosum3     ort
yok              300   40  0.8095  0.7937  0.8016  0.8016
sapma 0.05       600   20  0.8016  0.8095  0.8016  0.8042
sapma 0.15       600   20  0.8016  0.8095  0.7976  0.8029
sapma 0.40       600   20  0.7937  0.7937  0.7937  0.7937
artirmanin kattigi (sapma 0.05) +0.0026
artirmanin kattigi (sapma 0.15) +0.0013
artirmanin kattigi (sapma 0.40) -0.0079
```

Artırmanın kattığı fark üç koşumun ortalamasından okunur: gürültü 0,05 iken **+0,0026**, 0,15 iken
**+0,0013**, 0,40 iken **−0,0079**. İlk ikisi artı, üçüncüsü eksi; ama üçü de artırmasız kurulumun
kendi koşum aralığından (0,7937–0,8095, yani 0,0158) küçüktür. Bu tabloda dürüst cümle şudur:
**artırma bu veride ölçülebilir bir fark katmıyor.** Katkı sıfırdan ayırt edilemiyor, çünkü aynı
kurulumun iki koşumu arasındaki fark katkıdan büyük.

Son satırda başka bir şey görünüyor. Gürültü 0,40'a çıktığında üç koşum da **tıpatıp aynı sayıyı**
veriyor: 0,7937. Kuvvetli gürültü bir düzenlileştirme gibi davranıp başlangıç değerlerinin açtığı
farkı siliyor, ama sildiği farkla birlikte kazancı da siliyor. Ağın gördüğü satır sayısı iki kat
arttı; tur sayısı yarıya indiği için attığı eğim adımı aynı kaldı ve artırmanın kazandırdığı
çeşitlilik, kaybettirdiği sinyalden büyük çıkmadı.

#### Artırmanın Sızdırdığı Yer

Artırma bir sıra kararıdır. Doğru sıra **böl, sonra artır**: kopyalar yalnız eğitim satırlarından
türetilir. Yanlış sıra **artır, sonra böl**: bir sınama satırının gürültülü ikizi eğitim kümesine
düşer ve ağ o satırı neredeyse görmüş olur.

```python
# SIZINTI: artirma BOLMEDEN ONCE yapilirsa sinama satirinin gurultulu ikizi
# egitim kumesine girer (M27/K02, veri sizintisi). Sinama kumesi iki kurulumda
# da AYNI 252 orijinal satirdir; kaydirma alt kume karsilastirmasindan okunur.
def sizintili(sapma, tohum):
    r, XA, yA = uretec(tohum), list(XE), list(yE)
    havuz = karistir(range(len(XE) + len(XS)), tohum + 5)[:len(XE)]
    for k in havuz:
        x, e = (XE[k], yE[k]) if k < len(XE) else (XS[k - len(XE)], yS[k - len(XE)])
        v = list(x)
        for j in range(4, 8):
            v[j] += (r() + r() + r() - 1.5) * 2 * sapma
        XA.append(v)
        yA.append(e)
    return XA, yA, sorted(k - len(XE) for k in havuz if k >= len(XE))


def alt(p, idx):
    return dogruluk(p, [XS[k] for k in idx], [yS[k] for k in idx])


XL, yL, IKIZ = sizintili(0.05, TOHUM + 11000)
TEMIZ = [k for k in range(len(XS)) if k not in set(IKIZ)]
print(f"sinama kumesinin {len(IKIZ)} satirinin ikizi egitim kumesinde, "
      f"{len(TEMIZ)} satirinki degil")
print(f"{'egitim':<11} {'kosum':>5} {'hepsi':>7} {'ikizli':>7} {'temiz':>7} {'fark':>8}")
K = {}
for ad, P in (("durust", MODEL[0.05]),
              ("sizintili", [egit(XL, yL, TOHUM + k, SIRA) for k in (1, 2, 3)])):
    K[ad] = []
    for k, p in enumerate(P, 1):
        a, b = alt(p, IKIZ), alt(p, TEMIZ)
        K[ad].append(a - b)
        print(f"{ad:<11} {k:>5} {dogruluk(p, XS, yS):>7.4f} {a:>7.4f} {b:>7.4f} "
              f"{a - b:>+8.4f}")
d, s = sum(K["durust"]) / 3, sum(K["sizintili"]) / 3
print(f"ikizli-temiz farkinin ortalamasi: durust {d:+.4f}, sizintili {s:+.4f}; "
      f"kayma {s - d:+.4f}")
```

```
sinama kumesinin 138 satirinin ikizi egitim kumesinde, 114 satirinki degil
egitim      kosum   hepsi  ikizli   temiz     fark
durust          1  0.8016  0.7899  0.8158  -0.0259
durust          2  0.8095  0.8043  0.8158  -0.0114
durust          3  0.8016  0.7899  0.8158  -0.0259
sizintili       1  0.8095  0.8116  0.8070  +0.0046
sizintili       2  0.8095  0.8043  0.8158  -0.0114
sizintili       3  0.8095  0.8116  0.8070  +0.0046
ikizli-temiz farkinin ortalamasi: durust -0.0211, sizintili -0.0008; kayma +0.0203
```

Toplam sayılar tek başına okunamıyor: sızıntılı eğitimin üç koşumu 0,8095'te duruyor, dürüst
eğitimin üç koşumu 0,8016–0,8095 arasında. Fark koşum aralığının içinde kalıyor ve **bu ölçekte
sızıntı toplam sayıdan görülmüyor**. M27/K02'de aynı türden bir sızıntı ayrılmış küme sayısını
0,0476 şişirmişti.

Alt küme karşılaştırması koşum değişkenliğini iptal ediyor, çünkü iki alt küme **aynı koşumdan**
okunuyor. İkizi eğitim kümesinde olan 138 satır ile ikizi olmayan 114 satır arasındaki fark, dürüst
eğitimde ortalama **−0,0211**: ikizli grup zaten biraz daha zor. Sızıntılı eğitimde aynı fark
**−0,0008**'e çıkıyor. Kayma **+0,0203**, yani beş abone; ve bu kayma toplam sayıda görünmeyen
sızıntının bıraktığı izdir. Sızıntının varlığı toplam sayıdan değil, **kimin şiştiğinden** okunur.

#### Özet

- Toplu üretim sırası dört ayrı kararla kurulduğunda sınama sayısı 0,8016 ile 0,8095 arasında
  değişiyor; sıranın oynattığı 0,0079, iki abone.
- Aynı sırada yalnız başlangıç değerleri değiştiğinde fark 0,0159'a, dört aboneye çıkıyor: koşum
  değişkenliği sıra kararının iki katı kadar oynatıyor.
- Artırmanın kattığı fark üç koşumun ortalamasında +0,0026, +0,0013 ve −0,0079; üçü de artırmasız
  kurulumun koşum aralığından küçük, yani katkı sıfırdan ayırt edilemiyor.
- Gürültü 0,40'ta üç koşum da 0,7937 veriyor: kuvvetli artırma başlangıç farkını da kazancı da
  siliyor.
- Artırma bölmeden önce yapıldığında sınama kümesinin 138 satırının ikizi eğitim kümesine giriyor;
  toplam sayı şişmeyi göstermiyor ama ikizli-temiz farkı −0,0211'den −0,0008'e kayıyor, kayma
  +0,0203.

#### Sonraki Adım

Toplu boyu bu derste otuzda, güncelleme sayısı dört yüzde sabit tutuldu. İkisi de birer karardır ve
ikisi de bir kaynağa bağlıdır: bir güncellemede kaç örneğin ileri ve geri geçişinin **aynı anda**
bellekte durabileceğine. Sonraki ders donanım kullanımını ele alır: toplu boyut ile bellekte tutulan
sayı adedi arasındaki ilişki hesaplanır ve toplu boyun öğrenme adımıyla birlikte değişmesi gerektiği
sayıyla gösterilir.

### Donanım Kullanımı

Source: https://academia.sh/tr/kurslar/derin-ogrenme/donanim-kullanimi

Toplu boy ile bellekte tutulan sayı adedi arasındaki ilişkinin hesaplanması ve toplu boyun öğrenme adımıyla birlikte değişmesi gerektiğinin ölçülmesi: bir katmanlı sekiz birimli ağ toplu 30'da 1.182 sayı tutuyor ve bunun 0,8629'u etkinleştirme; dört katmanlı altmış dört birimli ağda toplu 1'de pay 0,0198'e düşerken toplu 300'de 185.242 sayının 0,8583'üne çıkıyor. Yüz bin sayılık bir bütçede en büyük toplu boy sırasıyla 2.936, 676 ve 139'dur. Tur sayısı sabitken öğrenme adımı 0,30'da bırakılırsa dört toplu boyun açıklığı 0,0476 (on iki abone) olur ve en düşüğü 0,7619 ile tabanın yalnız 0,0040 üstünde kalır; adım toplu boyla ölçeklendiğinde açıklık 0,0159'a iner.

Önceki ders toplu boyu otuzda sabit tuttu. Bu sayı bir kaynağa bağlıdır: bir güncellemede kaç
örneğin ileri ve geri geçişinin **aynı anda** bellekte durabileceğine. Hızlandırıcı bir donanım
sınıfıdır ve bu dersin konusu hiçbir ürünün özellikleri değil, **her hızlandırıcıda aynı olan
hesaptır**: toplu boy büyüdükçe hangi büyüklük ne kadar büyür.

İkinci soru ilkinin gölgesinde durur. Toplu boy bir bellek kararı gibi görünür, ama eğim inişinin
attığı adımın büyüklüğünü de değiştirir: bir toplunun eğimi o toplunun **ortalamasıdır** ve toplu
büyüdükçe ortalama sakinleşir. Dersin ölçüsü iki sayıdır: toplu boyun **sayı adedini** ne kadar
büyüttüğü ve toplu boy tek başına değiştirildiğinde sınama sayısının ne kadar düştüğü.

- **EP12.** Küme, ağ, taban çizgisi ve geri yayılım 01. dersten devralınır; tur sayısı bu derste
  **40'ta sabittir** ve toplu boy değiştikçe güncelleme sayısı buna göre değişir.
- **EP13.** Ölçü **sayı adedidir**, bayt değil. Bir sayının kaç bayt tuttuğu bir **tip kararıdır**
  ve M26/K04'ün bellek dersinde ölçüldü: orada aynı sütun gösterimine göre 173.837, 19.251 ve
  3.628 bayt tutmuş, genişlik 8 bayttan 1 bayta indirildiğinde bellek 31,4 kat küçülürken toplam
  6,9 m³ kaymıştı. **O hesap tekrarlanmaz**, girdi alınır.
- **EP14.** Sayılan üç yığın şudur: **parametreler**, **parametrelerin eğimleri** ve topludaki her
  örneğin **etkinleştirmeleri** ile onların eğimleri. Etkinleştirmeler geri geçiş için saklanır;
  saklanmasalar ileri geçiş yeniden koşardı.
- **EP15.** Eniyileyicinin kendi durumu ayrıca sayılır: momentumlu iniş parametre başına bir sayı
  daha ister. Bu ders yalın inişle koşar ve durum sıfırdır.
- **EP16.** Bellek bütçesi bir **kurgu** sayıdır (100.000 sayı) ve hiçbir ürünün belleği değildir;
  amacı bütçeden toplu boya giden hesabı göstermektir.
- **EP17.** Ölçekli adım kuralı **toplu boyla doğru orantılıdır**: otuzluk toplu için 0,30 olan
  adım, üç yüzlük toplu için 3,00 olur. Bu bir kural değil bir **adaydır** ve ölçülür.

#### Küme, Ağ ve Taban Çizgisi

```python
# ORTAK — KURGUDUR. M27/K01-K04'un abone tablosu ayni tohumla (20260218) uretilir;
# egitim kumesi 756'dan 300 satira kucultulmustur. Ag, ilklendirme ve elle yazilan
# geri yayilim 01. dersten devralinir; gizli birim sayisi h ile degistirilebilir.
import math

TOHUM, HAM, M32 = 20260218, 1400, 0xFFFFFFFF
BOLGE = [("kuzey", 0.28, 21, 0.00), ("guney", 0.22, 17, -0.10),
         ("dogu", 0.18, 26, 0.30), ("bati", 0.14, 14, -0.05),
         ("merkez", 0.18, 23, 0.05)]
ALAN = ["b_guney", "b_dogu", "b_bati", "b_merkez",
        "hane", "memnuniyet", "donem", "ortalama"]


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


def ayrik(u, w):
    t = 0.0
    for i, x in enumerate(w):
        t += x
        if u < t:
            return i
    return len(w) - 1


def karistir(dizi, tohum):
    r, s = uretec(tohum), list(dizi)
    for i in range(len(s) - 1, 0, -1):
        j = int(r() * (i + 1))
        s[i], s[j] = s[j], s[i]
    return s


VERI = []
for i in range(HAM):
    r = uretec(TOHUM + i)
    b = BOLGE[ayrik(r(), [x[1] for x in BOLGE])]
    hane = 1 + ayrik(r(), [0.06, 0.24, 0.30, 0.24, 0.11, 0.05])
    memnun = 1 + ayrik(r(), [0.08, 0.14, 0.27, 0.34, 0.17])
    if r() < 0.046:
        continue
    no = 10001 + i
    r, v = uretec(TOHUM + 7000 + no), []
    for d in range(ayrik(r(), [0.05, 0.12, 0.21, 0.62])):
        v.append(0.0 if r() < 0.038 else math.floor(
            b[2] * math.exp((r() + r() + r() - 1.5) * 0.62)
            * (1 - d * 0.05) * 100 + 0.5) / 100)
        r()
    if not v:
        continue
    ort, oyn, r = sum(v) / len(v), max(v) - min(v), uretec(TOHUM + 51000 + no)
    z = (0.052 * (ort - 20) + 0.85 * (min(v) == 0.0) + 0.026 * oyn
         + 0.24 * (hane >= 5) - 0.20 * (memnun >= 4) + b[3]
         + 0.9 * (no - 10001) / 1399 + (r() + r() + r() - 1.5) * 1.30)
    x = {"hane": hane, "memnuniyet": memnun, "donem": len(v),
         "ortalama": round(ort, 2), "supheli": int(z > 1.35)}
    for q in BOLGE[1:]:
        x["b_" + q[0]] = int(b[0] == q[0])
    VERI.append(x)

K = karistir(VERI, TOHUM + 90000)
EGT, SIN = K[:300], K[1008:]


def tablo(satirlar, ist=None):
    X = [[float(s[a]) for a in ALAN] for s in satirlar]
    if ist is None:                       # olcek yalniz egitim kumesinden ogrenilir
        ist = []
        for j in range(4, 8):
            m = sum(v[j] for v in X) / len(X)
            ist.append((j, m, math.sqrt(sum((v[j] - m) ** 2 for v in X) / len(X))))
    for v in X:
        for j, m, sd in ist:
            v[j] = (v[j] - m) / sd
    return X, [s["supheli"] for s in satirlar], ist


XE, yE, IST = tablo(EGT)
XS, yS, _ = tablo(SIN, IST)
TABAN = sum(v == 0 for v in yS) / len(yS)

G, H = len(ALAN), 8


def ilklendir(tohum, h=H):               # kazanc olcekli ilklendirme
    r = uretec(tohum)
    return [(r() * 2 - 1) * math.sqrt(2.0 / G) for _ in range(h * G)] + [0.0] * h \
        + [(r() * 2 - 1) * math.sqrt(2.0 / h) for _ in range(h)] + [0.0]


def egim(p, X, y, par, h=H):             # 01. dersin elle yazilan geri yayilimi
    g = [0.0] * len(p)
    for k in par:
        x, hh = X[k], [0.0] * h
        for j in range(h):
            s = p[h * G + j] + sum(p[j * G + i] * x[i] for i in range(G))
            hh[j] = s if s > 0 else 0.0
        s = p[-1] + sum(p[h * G + h + j] * hh[j] for j in range(h))
        d = (1.0 / (1.0 + math.exp(-s)) if s > -30 else 0.0) - y[k]
        g[-1] += d
        for j in range(h):
            g[h * G + h + j] += d * hh[j]
            if hh[j] > 0:
                g[h * G + j] += d * p[h * G + h + j]
                for i in range(G):
                    g[j * G + i] += d * p[h * G + h + j] * x[i]
    return [v / len(par) for v in g]


def egit(X, y, tohum, toplu=30, adim=0.30, tur=40, h=H):
    p = ilklendir(tohum, h)
    for t in range(tur):
        d = karistir(range(len(X)), TOHUM + 700 + t)
        for b in range(0, len(d) - toplu + 1, toplu):
            p = [a - adim * v for a, v in zip(p, egim(p, X, y, d[b:b + toplu], h))]
    return p


def dogruluk(p, X, y, h=H):
    n = 0
    for k in range(len(X)):
        x = X[k]
        o = p[-1] + sum(p[h * G + h + j] * max(0.0, p[h * G + j]
                        + sum(p[j * G + i] * x[i] for i in range(G)))
                        for j in range(h))
        n += (o >= 0.0) == (y[k] == 1)
    return n / len(X)


print(f"kurgu: egitim {len(XE)} satir (756'dan kucultuldu), sinama {len(XS)}, "
      f"oznitelik {G}, gizli birim {H}, parametre {len(ilklendir(TOHUM))}")
print(f"taban cizgisi (en sik sinifi soylemek, sinamada) {TABAN:.4f}")
```

```
kurgu: egitim 300 satir (756'dan kucultuldu), sinama 252, oznitelik 8, gizli birim 8, parametre 81
taban cizgisi (en sik sinifi soylemek, sinamada) 0.7579
```

#### Bir Güncellemede Kaç Sayı Tutulur

Parametre sayısı toplu boydan bağımsızdır; etkinleştirme sayısı toplu boyla **doğru orantılıdır**.
İki büyüklüğün oranı ağın biçimine bağlıdır ve tablo bunu üç ağda okur.

```python
# Bellekte tutulan SAYI ADEDI. Bir guncelleme icin uc yigin tutulur: parametreler,
# onlarin egimleri, ve topludaki her ornegin etkinlestirmeleri (ileri gecisin ara
# degerleri geri gecis icin saklanir) ile o etkinlestirmelerin egimleri.
def adet(g, h, katman, toplu, durum=0):
    par = g * h + h + (katman - 1) * (h * h + h) + h + 1
    return par, par * (1 + durum), 2 * toplu * (g + katman * h + 1)


print(f"{'katman':>7} {'gizli':>6} {'toplu':>6} {'parametre':>10} {'egim':>7} "
      f"{'etkinlestirme':>14} {'toplam':>9} {'etkin pay':>10}")
for katman, h in ((1, 8), (1, 64), (4, 64)):
    for toplu in (1, 30, 300):
        p, e, a = adet(G, h, katman, toplu)
        print(f"{katman:>7} {h:>6} {toplu:>6} {p:>10} {e:>7} {a:>14} {p + e + a:>9} "
              f"{a / (p + e + a):>10.4f}")

p, e, a = adet(G, H, 1, 30)
print(f"\nbu dersin agi (1 katman, {H} birim, toplu 30): {p + e + a} sayi; "
      f"toplu 300'de {sum(adet(G, H, 1, 300)):,}")
print(f"momentumlu inis eniyileyici durumu icin parametre basina bir sayi daha "
      f"ister: {sum(adet(G, H, 1, 30, 1))} sayi")
BUTCE = 100000
print(f"\nbutce {BUTCE:,} sayi olsaydi en buyuk toplu boy:")
for katman, h in ((1, 8), (1, 64), (4, 64)):
    par = adet(G, h, katman, 1)[0]
    print(f"  {katman} katman, {h:>2} birim: {(BUTCE - 2 * par) // (2 * (G + katman * h + 1)):>6,}")
```

```
 katman  gizli  toplu  parametre    egim  etkinlestirme    toplam  etkin pay
      1      8      1         81      81             34       196     0.1735
      1      8     30         81      81           1020      1182     0.8629
      1      8    300         81      81          10200     10362     0.9844
      1     64      1        641     641            146      1428     0.1022
      1     64     30        641     641           4380      5662     0.7736
      1     64    300        641     641          43800     45082     0.9716
      4     64      1      13121   13121            530     26772     0.0198
      4     64     30      13121   13121          15900     42142     0.3773
      4     64    300      13121   13121         159000    185242     0.8583

bu dersin agi (1 katman, 8 birim, toplu 30): 1182 sayi; toplu 300'de 10,362
momentumlu inis eniyileyici durumu icin parametre basina bir sayi daha ister: 1263 sayi

butce 100,000 sayi olsaydi en buyuk toplu boy:
  1 katman,  8 birim:  2,936
  1 katman, 64 birim:    676
  4 katman, 64 birim:    139
```

Üç satır üçlüsü üç ayrı düzen gösteriyor. Bir katmanlı sekiz birimli ağda toplu 1'de etkinleştirme
payı 0,1735; toplu 30'da 0,8629'a, toplu 300'de 0,9844'e çıkıyor. Bu ağ o kadar küçüktür ki
belleğin neredeyse tamamını **veri** kaplar. Dört katmanlı altmış dört birimli ağda tablo tersine
dönüyor: toplu 1'de pay 0,0198, yani bellek parametrelerin ve eğimlerin; ama toplu 300'e
çıkıldığında aynı ağda pay 0,8583 oluyor ve toplam 26.772'den 185.242'ye, altı katın üstünde
büyüyor. Parametre sayısı bu iki satırda **hiç değişmedi**.

Hesabın kullanışlı yönü tersten okunduğunda çıkıyor. Bellek bütçesi verildiğinde en büyük toplu boy
çözülebilir: yüz bin sayılık kurgu bütçede küçük ağ 2.936, geniş tek katmanlı ağ 676, dört katmanlı
ağ 139 örnek alabiliyor. Aynı bütçe, aynı donanım, **yirmi kat fark**. Toplu boyu bir alışkanlık
olarak değil bu bölmenin sonucu olarak seçmek gerekir; ve seçilen sayı bir sonraki bölümün
gösterdiği gibi tek başına gelmez.

#### Toplu Boy ile Öğrenme Adımı Birlikte Değişir

```python
# Toplu boy ile ogrenme adimi BIRLIKTE degisir. Tur sayisi 40'ta sabit; toplu boy
# buyudukce guncelleme sayisi duser. Olcekli adim toplu boyla dogru orantilidir.
print(f"{'toplu':>6} {'guncelleme':>11} {'sabit adim 0.30':>25} {'olcekli adim':>25}")
SABIT, OLCEK = [], []
for toplu in (10, 30, 100, 300):
    a = [dogruluk(egit(XE, yE, TOHUM + k, toplu, 0.30), XS, yS) for k in (1, 2)]
    o = 0.30 * toplu / 30
    b = [dogruluk(egit(XE, yE, TOHUM + k, toplu, o), XS, yS) for k in (1, 2)]
    SABIT += a
    OLCEK += b
    print(f"{toplu:>6} {40 * (len(XE) // toplu):>11} {a[0]:>13.4f} {a[1]:>6.4f}"
          f"   {'adim ' + format(o, '.2f'):>12} {b[0]:>6.4f} {b[1]:>6.4f}")
print(f"sabit adimla dort toplu boyun acikligi  {max(SABIT) - min(SABIT):.4f} "
      f"({round((max(SABIT) - min(SABIT)) * len(XS))} abone)")
print(f"olcekli adimla ayni aciklik             {max(OLCEK) - min(OLCEK):.4f} "
      f"({round((max(OLCEK) - min(OLCEK)) * len(XS))} abone)")
print(f"taban cizgisi {TABAN:.4f}; sabit adimda en dusuk {min(SABIT):.4f} "
      f"({min(SABIT) - TABAN:+.4f}), olcekli adimda en dusuk {min(OLCEK):.4f} "
      f"({min(OLCEK) - TABAN:+.4f})")
```

```
 toplu  guncelleme           sabit adim 0.30              olcekli adim
    10        1200        0.7619 0.7857      adim 0.10 0.8056 0.7937
    30         400        0.8095 0.7937      adim 0.30 0.8095 0.7937
   100         120        0.7897 0.8056      adim 1.00 0.8016 0.8016
   300          40        0.7619 0.7738      adim 3.00 0.8056 0.7937
sabit adimla dort toplu boyun acikligi  0.0476 (12 abone)
olcekli adimla ayni aciklik             0.0159 (4 abone)
taban cizgisi 0.7579; sabit adimda en dusuk 0.7619 (+0.0040), olcekli adimda en dusuk 0.7937 (+0.0357)
```

Sol sütun toplu boyun tek başına değiştirilmesinin bedelini gösteriyor. Adım 0,30'da bırakıldığında
dört toplu boyun açıklığı **0,0476**, on iki abone: koşum değişkenliğinin (dört abone) üç katı. İki
uçta iki ayrı sebep var. Toplu 300'de yalnız kırk güncelleme yapılıyor ve ağ eğitimi bitmeden
duruyor; sonuç 0,7619, tabanın **yalnız 0,0040 üstünde**, yani bir abone. Toplu 10'da güncelleme
sayısı 1.200'e çıkıyor ama her eğim yalnız on örneğin ortalaması olduğu için gürültülü; 0,30'luk
adım o gürültüyle birlikte fazla büyük kalıyor ve sonuç yine 0,7619'a düşüyor.

Sağ sütun adımı toplu boyla ölçekliyor: 0,10, 0,30, 1,00 ve 3,00. Dört toplu boyun açıklığı
**0,0159**'a iniyor, dört aboneye — yani aynı kurulumun iki koşumu arasındaki farkla aynı
büyüklüğe. En düşük sayı 0,7619'dan 0,7937'ye çıkıyor ve tabanın üstündeki fark 0,0040'tan
0,0357'ye. Toplu boy tek başına bir ayar değişkeni değildir: değiştirildiğinde öğrenme adımı da
değişmelidir, yoksa ölçülen şey bellek kararının kendisi değil, o kararın yanında unutulmuş adımdır.

#### Özet

- Bir güncellemede tutulan sayı üç yığındır: parametreler, eğimleri ve topludaki örneklerin
  etkinleştirmeleriyle onların eğimleri; ilk ikisi toplu boydan bağımsız, üçüncüsü doğru orantılı.
- Bir katmanlı sekiz birimli ağ toplu 30'da 1.182 sayı tutuyor ve bunun 0,8629'u etkinleştirme;
  dört katmanlı altmış dört birimli ağda pay toplu 1'de 0,0198, toplu 300'de 0,8583.
- Aynı ağda toplu 1'den 300'e çıkmak toplamı 26.772'den 185.242'ye taşıyor; parametre sayısı hiç
  değişmiyor.
- Yüz bin sayılık kurgu bütçede en büyük toplu boy üç ağ için 2.936, 676 ve 139; aynı bütçe yirmi
  kat fark üretiyor.
- Tur sayısı sabitken adım 0,30'da bırakılırsa dört toplu boyun açıklığı 0,0476 (on iki abone) ve
  en düşüğü 0,7619 ile tabanın bir abone üstünde kalıyor; adım toplu boyla ölçeklendiğinde açıklık
  0,0159'a, en düşük sayı 0,7937'ye geliyor.

#### Sonraki Adım

Üç derste sabitlenen kalem sayısı hızla arttı: tohum, örnek sırası, toplu boy, öğrenme adımı, tur
sayısı, artırma ölçeği, ölçekleme istatistiklerinin hangi kümeden okunduğu. Bunların hiçbiri modelin
kendisi değildir ve hepsi sonucu oynatır; bu derste tek bir kalemin — adımın — yerinde bırakılması
sayıyı on iki abone düşürdü. Bir eğitimin ikinci kez aynı sayıyı vermesi için kaç kalemin
sabitlenmesi gerektiği ise hiç sayılmadı. Sonraki ders deney takibini ele alır: sabitlenecek
kalemler önceki kursların listelerinin üstüne sayılır ve biri serbest bırakıldığında sonucun ne
kadar oynadığı basılır.

### Deney Takibi

Source: https://academia.sh/tr/kurslar/derin-ogrenme/deney-takibi

Aynı eğitimin ikinci kez aynı sayıyı vermesi için sabitlenmesi gereken kalemin sayılması: M26/K03'ün 39, M26/K04'ün 9 ve M26/K06'nın 11 kaleminin üstüne eğitime özgü 8 kalem eklenir ve toplam 67 olur. Sekiz kalemin 6'sı tek başına serbest bırakıldığında sonucu oynatıyor ve en büyük oynama 0,0159, yani dört abone — o kalem modelin hiçbir ayarı değil, başlangıç değerleri. Toplama sırası parametreleri 6,66e-16 oynatıp hiçbir kararı değiştirmezken tur sayısı parametreleri 0,2098 oynatıp yine hiçbir kararı değiştirmiyor; tek başına oynatmayan tur sayısı toplu boyla birlikte serbest bırakıldığında sonucu iki abone kaydırıyor.

Önceki üç derste eğitimin düzeneği parça parça açıldı ve her parçada bir karar çıktı: eğim hangi
yolla hesaplanacak, örnekler hangi sırayla verilecek, kaç tanesi bir arada, adım ne olacak. Her
karar sonucu oynattı ve hiçbiri modelin kendisi değildi. Bir eğitimin **ikinci kez** aynı sayıyı
vermesi için bu kararların kaçının yazılı olması gerektiği ise sorulmadı.

Soru yeni değil ve bir bölümü kapandı. Veri Toplama ve Hazırlama kursu hazırlama defterini otuz
dokuz karar olarak yazdı; Python ile Veri Analizi kursu çalışma ortamını dokuz kalem olarak; Veri
Görselleştirme ve Raporlama kursu raporun kendisini on bir kalem olarak saydı ve toplamı elli
dokuz buldu. M27/K02 boru hattı dersinde bu listenin yanına bir sayı daha koydu: hazırlama zinciri
eğitim kümesinden **131 sayı** öğreniyordu ve o sayıların hepsinin doğru kümeden okunması gerekti.
**Bu hesaplar tekrarlanmaz**, girdi alınır. Bu dersin eklediği şey **eğitimin kendisidir**.

- **EP18.** Küme, ağ, taban çizgisi ve geri yayılım 01. dersten devralınır. Eğitim döngüsünün
  kalemleri tek bir sözlükte toplanır ve koşum bu sözlükten okunur; yalnız ölçekleme kalemi
  döngünün dışında, veri hazırlanırken uygulanır.
- **EP19.** Bir kalemi **serbest bırakmak**, onu silmek değil, **eşit ölçüde savunulabilir** bir
  başka değere geçirmek demektir. Otuz yerine yirmi beşlik toplu, 0,30 yerine 0,25'lik adım,
  kırk yerine elli tur: hiçbiri yanlış değildir.
- **EP20.** Kalemler **tek tek** serbest bırakılır, öbürleri sabit kalır. Ölçüt sınama kümesindeki
  doğruluktur ve sınama kümesi hiçbir kurulumda değişmez.
- **EP21.** "Toplama sırası" kalemi **eşzamanlılığın izidir**: bir toplunun eğimleri paralel
  toplandığında hangi terimin önce eklendiği koşumdan koşuma değişebilir. Burada bu, topludaki
  örneklerin ters sırada toplanmasıyla modellenir; kayan noktalı toplama birleşmeli olmadığı için
  sonuç son basamaklarda ayrılır.
- **EP22.** İki büyüklük ayrı sayılır: **parametrelerin** oynaması ve **sonucun** oynaması. Birinci
  sıfır değilken ikincisi sıfır olabilir; eşik, kararın sınırından ne kadar uzakta durulduğudur.
- **EP23.** Hiçbir deney takip aracı, not defteri uygulaması ya da depo adı anılmaz. Takip burada
  **kalem listesinin kendisidir**: liste taşınabiliyorsa koşum taşınabilir.

#### Küme, Ağ ve Kalem Sözlüğü

```python
# ORTAK — KURGUDUR. M27/K01-K04'un abone tablosu ayni tohumla (20260218) uretilir;
# egitim kumesi 756'dan 300 satira kucultulmustur. Egitim dongusunun kalemleri tek
# bir sozlukte toplanir ve kosum bu sozlukten okunur.
import math

TOHUM, HAM, M32 = 20260218, 1400, 0xFFFFFFFF
BOLGE = [("kuzey", 0.28, 21, 0.00), ("guney", 0.22, 17, -0.10),
         ("dogu", 0.18, 26, 0.30), ("bati", 0.14, 14, -0.05),
         ("merkez", 0.18, 23, 0.05)]
ALAN = ["b_guney", "b_dogu", "b_bati", "b_merkez",
        "hane", "memnuniyet", "donem", "ortalama"]


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


def ayrik(u, w):
    t = 0.0
    for i, x in enumerate(w):
        t += x
        if u < t:
            return i
    return len(w) - 1


def karistir(dizi, tohum):
    r, s = uretec(tohum), list(dizi)
    for i in range(len(s) - 1, 0, -1):
        j = int(r() * (i + 1))
        s[i], s[j] = s[j], s[i]
    return s


VERI = []
for i in range(HAM):
    r = uretec(TOHUM + i)
    b = BOLGE[ayrik(r(), [x[1] for x in BOLGE])]
    hane = 1 + ayrik(r(), [0.06, 0.24, 0.30, 0.24, 0.11, 0.05])
    memnun = 1 + ayrik(r(), [0.08, 0.14, 0.27, 0.34, 0.17])
    if r() < 0.046:
        continue
    no = 10001 + i
    r, v = uretec(TOHUM + 7000 + no), []
    for d in range(ayrik(r(), [0.05, 0.12, 0.21, 0.62])):
        v.append(0.0 if r() < 0.038 else math.floor(
            b[2] * math.exp((r() + r() + r() - 1.5) * 0.62)
            * (1 - d * 0.05) * 100 + 0.5) / 100)
        r()
    if not v:
        continue
    ort, oyn, r = sum(v) / len(v), max(v) - min(v), uretec(TOHUM + 51000 + no)
    z = (0.052 * (ort - 20) + 0.85 * (min(v) == 0.0) + 0.026 * oyn
         + 0.24 * (hane >= 5) - 0.20 * (memnun >= 4) + b[3]
         + 0.9 * (no - 10001) / 1399 + (r() + r() + r() - 1.5) * 1.30)
    x = {"hane": hane, "memnuniyet": memnun, "donem": len(v),
         "ortalama": round(ort, 2), "supheli": int(z > 1.35)}
    for q in BOLGE[1:]:
        x["b_" + q[0]] = int(b[0] == q[0])
    VERI.append(x)

K = karistir(VERI, TOHUM + 90000)
EGT, SIN = K[:300], K[1008:]


def tablo(satirlar, ist=None):
    X = [[float(s[a]) for a in ALAN] for s in satirlar]
    if ist is None:                       # olcek yalniz egitim kumesinden ogrenilir
        ist = []
        for j in range(4, 8):
            m = sum(v[j] for v in X) / len(X)
            ist.append((j, m, math.sqrt(sum((v[j] - m) ** 2 for v in X) / len(X))))
    for v in X:
        for j, m, sd in ist:
            v[j] = (v[j] - m) / sd
    return X, [s["supheli"] for s in satirlar], ist


XE, yE, IST = tablo(EGT)
XS, yS, _ = tablo(SIN, IST)
TABAN = sum(v == 0 for v in yS) / len(yS)

G, H = len(ALAN), 8


def ilklendir(tohum):                    # kazanc olcekli ilklendirme
    r = uretec(tohum)
    return [(r() * 2 - 1) * math.sqrt(2.0 / G) for _ in range(H * G)] + [0.0] * H \
        + [(r() * 2 - 1) * math.sqrt(2.0 / H) for _ in range(H)] + [0.0]


def egim(p, X, y, par):                  # 01. dersin elle yazilan geri yayilimi
    g = [0.0] * len(p)
    for k in par:
        x, hh = X[k], [0.0] * H
        for j in range(H):
            s = p[H * G + j] + sum(p[j * G + i] * x[i] for i in range(G))
            hh[j] = s if s > 0 else 0.0
        s = p[-1] + sum(p[H * G + H + j] * hh[j] for j in range(H))
        d = (1.0 / (1.0 + math.exp(-s)) if s > -30 else 0.0) - y[k]
        g[-1] += d
        for j in range(H):
            g[H * G + H + j] += d * hh[j]
            if hh[j] > 0:
                g[H * G + j] += d * p[H * G + H + j]
                for i in range(G):
                    g[j * G + i] += d * p[H * G + H + j] * x[i]
    return [v / len(par) for v in g]


VARSAYILAN = {"tohum": TOHUM + 1, "sira": TOHUM + 700, "toplu": 30, "adim": 0.30,
              "tur": 40, "bolme": "dilim", "toplama": "ileri", "olcek": "egitim"}


def egit(X, y, **kalem):
    a = dict(VARSAYILAN, **kalem)
    p = ilklendir(a["tohum"])
    for t in range(a["tur"]):
        d = karistir(range(len(X)), a["sira"] + t)
        n = len(d) // a["toplu"]
        for b in range(n):
            par = d[b * a["toplu"]:(b + 1) * a["toplu"]] if a["bolme"] == "dilim" \
                else d[b::n]
            if a["toplama"] == "geri":
                par = par[::-1]
            p = [u - a["adim"] * v for u, v in zip(p, egim(p, X, y, par))]
    return p


def dogruluk(p, X, y):
    n = 0
    for k in range(len(X)):
        x = X[k]
        o = p[-1] + sum(p[H * G + H + j] * max(0.0, p[H * G + j]
                        + sum(p[j * G + i] * x[i] for i in range(G)))
                        for j in range(H))
        n += (o >= 0.0) == (y[k] == 1)
    return n / len(X)


print(f"kurgu: egitim {len(XE)} satir (756'dan kucultuldu), sinama {len(XS)}, "
      f"parametre {len(ilklendir(TOHUM))}; taban cizgisi {TABAN:.4f}")
```

```
kurgu: egitim 300 satir (756'dan kucultuldu), sinama 252, parametre 81; taban cizgisi 0.7579
```

#### Kaç Kalem

```python
# Sabitlenecek kalemler. Ilk uc kaynak ONCEKI KURSLARDAN devralinir ve burada
# tekrarlanmaz; bu ders yalniz EGITIME OZGU olanlari ekler.
DEVRALINAN = [("hazirlama defteri (M26/K03)", 39),
              ("calisma ortami (M26/K04)", 9),
              ("raporun kendisi (M26/K06)", 11)]
EGITIM = ["ilklendirme tohumu", "ornek sirasi tohumu", "toplu boy",
          "toplu bolme bicimi", "ogrenme adimi", "tur sayisi",
          "toplama sirasi (eszamanlilik)", "olcegin okundugu kume"]
for ad, n in DEVRALINAN:
    print(f"  {ad:<30} {n:>3} kalem")
print(f"  {'egitimin kendisi (bu ders)':<30} {len(EGITIM):>3} kalem")
print(f"  {'toplam':<30} {sum(n for _, n in DEVRALINAN) + len(EGITIM):>3} kalem")
print("\negitime ozgu kalemler ve varsayilan degerleri:")
print("  " + ", ".join(f"{a}={VARSAYILAN[k]}" for a, k in
                       zip(EGITIM, ("tohum", "sira", "toplu", "bolme", "adim",
                                    "tur", "toplama", "olcek"))))
```

```
  hazirlama defteri (M26/K03)     39 kalem
  calisma ortami (M26/K04)         9 kalem
  raporun kendisi (M26/K06)       11 kalem
  egitimin kendisi (bu ders)       8 kalem
  toplam                          67 kalem

egitime ozgu kalemler ve varsayilan degerleri:
  ilklendirme tohumu=20260219, ornek sirasi tohumu=20260918, toplu boy=30, toplu bolme bicimi=dilim, ogrenme adimi=0.3, tur sayisi=40, toplama sirasi (eszamanlilik)=ileri, olcegin okundugu kume=egitim
```

Toplam **altmış yedi**. Elli dokuzu bu dersten önce sayıldı ve burada tekrarlanmadı; sekizi
eğitimin kendisine aittir. Sekizin hiçbiri modelin mimarisi değildir — katman sayısı, birim sayısı
ve etkinleştirme bu listeye girmez, çünkü onlar **raporlanan modelin tanımıdır**. Listedekiler
rapor edilen sayının **nasıl** üretildiğine dair kararlardır ve çoğu tek satırda geçer.

#### Her Kalem Tek Tek

```python
# Her kalem TEK BASINA serbest birakilir: esit olcude savunulabilir bir baska
# degere gecirilir, oburleri sabit kalir. Olcek kalemi serbest birakildiginda
# olcek istatistigi egitim yerine egitim+sinama kumesinden okunur.
XE2, yE2, _ = tablo(EGT, tablo(EGT + SIN)[2])
TEMEL, P0 = dogruluk(egit(XE, yE), XS, yS), egit(XE, yE)
ALTERNATIF = [({"tohum": TOHUM + 2}, "20260220"), ({"sira": TOHUM + 800}, "20261018"),
              ({"toplu": 25}, "25"), ({"bolme": "adimli"}, "adimli"),
              ({"adim": 0.25}, "0.25"), ({"tur": 50}, "50"),
              ({"toplama": "geri"}, "geri"), (None, "egitim+sinama")]
print(f"taban cizgisi {TABAN:.4f}, butun kalemler sabitken {TEMEL:.4f}\n")
print(f"{'serbest birakilan kalem':<30} {'yeni deger':<14} {'sinama':>7} {'oynama':>8} "
      f"{'abone':>6} {'parametre':>10}")
OYNAMA = []
for ad, (d, yeni) in zip(EGITIM, ALTERNATIF):
    p = egit(XE, yE, **d) if d else egit(XE2, yE2)
    v = dogruluk(p, XS, yS)
    OYNAMA.append(abs(v - TEMEL))
    print(f"{ad:<30} {yeni:<14} {v:>7.4f} {v - TEMEL:>+8.4f} "
          f"{round(abs(v - TEMEL) * len(XS)):>6} "
          f"{max(abs(a - b) for a, b in zip(p, P0)):>10.2e}")
print(f"\n{len(OYNAMA)} kalemin {sum(1 for u in OYNAMA if u > 1e-9)} tanesi tek basina "
      f"sonucu oynatiyor; en buyuk oynama {max(OYNAMA):.4f} "
      f"({round(max(OYNAMA) * len(XS))} abone)")
for d, ad in (({"tur": 50, "toplama": "geri"}, "tur 50 + toplama geri"),
              ({"tur": 50, "toplu": 25}, "tur 50 + toplu 25")):
    v = dogruluk(egit(XE, yE, **d), XS, yS)
    print(f"  {ad:<24} {v:.4f}  oynama {v - TEMEL:+.4f} "
          f"({round(abs(v - TEMEL) * len(XS))} abone)")
```

```
taban cizgisi 0.7579, butun kalemler sabitken 0.8095

serbest birakilan kalem        yeni deger      sinama   oynama  abone  parametre
ilklendirme tohumu             20260220        0.7937  -0.0159      4   1.46e+00
ornek sirasi tohumu            20261018        0.8016  -0.0079      2   7.45e-02
toplu boy                      25              0.8056  -0.0040      1   2.76e-01
toplu bolme bicimi             adimli          0.8135  +0.0040      1   4.80e-01
ogrenme adimi                  0.25            0.8056  -0.0040      1   1.98e-01
tur sayisi                     50              0.8095  +0.0000      0   2.10e-01
toplama sirasi (eszamanlilik)  geri            0.8095  +0.0000      0   6.66e-16
olcegin okundugu kume          egitim+sinama   0.8056  -0.0040      1   3.18e-01

8 kalemin 6 tanesi tek basina sonucu oynatiyor; en buyuk oynama 0.0159 (4 abone)
  tur 50 + toplama geri    0.8095  oynama +0.0000 (0 abone)
  tur 50 + toplu 25        0.8016  oynama -0.0079 (2 abone)
```

Sekiz kalemin altısı tek başına sonucu oynatıyor ve en büyük oynama **0,0159**, dört abone. O
kalem şudur: **ilklendirme tohumu**. Modelin hiçbir ayarı değil, hiçbir hazırlama kararı değil;
ağırlıkların başladığı yer. Bu kursun imzası olan üçüncü sayı, yeniden üretilebilirlik listesinde
de en büyük satırdır. Öğrenme adımının ve toplu boyun oynattığı birer abone, tohumun oynattığının
dörtte biri kadardır.

Son sütun iki kalemi birbirinden ayırıyor. Toplama sırası serbest bırakıldığında parametreler
**6,66e-16** oynuyor, yani kayan noktalı toplamanın son basamağı kadar; sınama kümesinin hiçbir
kararı değişmiyor. Tur sayısı kırktan elliye çıktığında parametreler **0,2098** oynuyor — toplama
sırasının on dört basamak üstünde — ve sınama kümesinin yine hiçbir kararı değişmiyor. İki sıfır
aynı sıfır değildir: birincisinde ağ aynı ağdır, ikincisinde ağ başka bir ağdır ve yalnızca
kararların hiçbiri sınırı geçmemiştir.

Bu ayrımın bedeli son iki satırda. Tur sayısı tek başına sıfır oynatıyor, toplu boy tek başına bir
abone; ikisi birlikte serbest bırakıldığında **iki abone** oynuyor. Tek başına oynatmayan bir
kalem, sabitlenmesi gerekmeyen bir kalem değildir. Ölçeğin okunduğu küme kalemi de bunu doğruluyor:
sınama kümesi ölçek istatistiğine karıştığında sayı yalnız bir abone oynuyor, oysa aynı sızıntı
M27/K02'de karar ağacıyla 0,0476 şişme üretmişti. Sızıntının küçük görünmesi yokluğunun kanıtı
değildir.

#### Özet

- Bir eğitimin yeniden üretilmesi 67 kalemin sabitlenmesini istiyor: M26/K03'ün 39, M26/K04'ün 9 ve
  M26/K06'nın 11 kaleminin üstüne eğitime özgü 8 kalem eklenir.
- Sekiz kalemin altısı tek başına serbest bırakıldığında sonucu oynatıyor; bütün kalemler sabitken
  sınama sayısı 0,8095, taban çizgisi 0,7579.
- En büyük oynama 0,0159 (dört abone) ve kaynağı ilklendirme tohumudur — modelin hiçbir ayarı değil,
  bu kursun üçüncü sayısı.
- Parametrelerin oynaması ile sonucun oynaması ayrı şeylerdir: toplama sırası parametreleri 6,66e-16,
  tur sayısı 0,2098 oynatıyor ve ikisi de hiçbir kararı değiştirmiyor.
- Tek başına sıfır oynatan tur sayısı, toplu boyla birlikte serbest bırakıldığında iki abone
  oynatıyor; ve ölçeğin sınama kümesinden okunması burada bir abone oynatırken M27/K02'de aynı
  sızıntı 0,0476 şişirmişti.

#### Sonraki Adım

Bu derste kalemlerin hepsi **sabit** tutuldu ve teker teker serbest bırakıldı. Gerçek bir eğitimde
bunun tersi yapılır: birkaç kalem bilerek serbest bırakılır, bir aday listesi kurulur ve en iyisi
seçilir. Arama yöntemleri M27/K03'te ölçüldü ve tekrarlanmayacak; ama o kursta her adayın sayısı
**tek bir koşumdan** okunuyordu. Bu derste ölçülen şey bunu sorgulatıyor: aynı adayın iki koşumu
arasındaki fark dört aboneyse ve iki aday arasındaki fark bir aboneyse, arama neyi seçmektedir.
Sonraki ders ayar değişkeni aramasını bu soruyla ele alır ve kursu kapatır.

### Ayar Değişkeni Araması

Source: https://academia.sh/tr/kurslar/derin-ogrenme/hiperparametre-ayari

Koşum değişkenliğinin aramayı yanıltmasının ölçülmesi: on aday aynı bütçeyle iki kez koşturulduğunda adaylar arası açıklık doğrulama kümesinde 0,0317 iken tek bir adayın iki koşumu arasındaki fark 0,0238'e çıkıyor ve kırk beş aday çiftinin yirmi üçü ayırt edilemiyor, yedisinde sıralama ters dönüyor. Birinci koşumdan bakan arama on altı birimli adayı seçip sınamada 0,8135 alırken ikinci koşumdan bakan arama dört birimli adayı seçip 0,8016 alıyor; on adayın sınama ortalaması 0,8036, taban çizgisi 0,7579. Kurs kapanışı yirmi dört dersin taban çizgisini, ağın sayısını ve ikinci koşumunu tek tabloda toplar.

Önceki ders eğitimin kalemlerini saydı ve hepsini sabitledi; en büyük oynamayı yapan kalem
başlangıç değerleriydi. Gerçek bir eğitimde kalemlerin bir bölümü bilerek serbest bırakılır: bir
aday listesi kurulur, hepsi koşturulur ve doğrulama kümesinden en iyisi seçilir.

Arama yöntemleri M27/K03'ün model değerlendirme konusunda ölçüldü — ızgara, rastgele ve model
temelli arama aynı elli adaylık bütçede sınamada 0,7937, 0,7857 ve 0,8016 vermişti — ve **burada
tekrarlanmaz**. Değişen tek şey şudur: orada her adayın sayısı **tek bir koşumdan** okunuyordu.
Dersin sorusu şudur: aday sayısı aynıyken, aynı adayın iki koşumu arasındaki fark adaylar
arasındaki farktan büyük olduğunda arama neyi seçiyor.

- **EP24.** Küme, ağ ve taban çizgisi 01. dersten devralınır; ayrıca **doğrulama kümesi** kullanılır
  (252 satır) ve seçim ondan, rapor sınamadan okunur.
- **EP25.** Aday sayısı **on**, bütçe her adayda eşittir (40 tur) ve adaylar elle listelenir; arama
  yöntemi seçimi bu dersin konusu değildir.
- **EP26.** Ayar uzayı üç eksenlidir: gizli birim (4, 8, 16), öğrenme adımı (0,15, 0,30, 0,60) ve
  toplu boy (20, 30, 50). Her aday **iki kez** koşturulur ve iki koşum yalnız **başlangıç
  değerlerinde** ayrılır; öbür kalemler 04. dersteki gibi sabittir.
- **EP27.** İki aday, farkları **her ikisinin de koşum farkından küçükse** ayırt edilemez sayılır;
  eşik ölçünün kendisinden gelir. Beraberlik listedeki ilk adaya verilir ve bu da bir karardır.

#### Küme, Ağ ve Aday Listesi

```python
# ORTAK — KURGUDUR. M27/K01-K04'un abone tablosu ayni tohumla (20260218) uretilir;
# egitim kumesi 756'dan 300 satira kucultulmustur. Bu derste DOGRULAMA kumesi de
# kullanilir: secim ondan, rapor sinama kumesinden okunur. Ag 01. dersten gelir,
# gizli birim sayisi h adaya gore degisir.
import math

TOHUM, HAM, M32 = 20260218, 1400, 0xFFFFFFFF
BOLGE = [("kuzey", 0.28, 21, 0.00), ("guney", 0.22, 17, -0.10),
         ("dogu", 0.18, 26, 0.30), ("bati", 0.14, 14, -0.05),
         ("merkez", 0.18, 23, 0.05)]
ALAN = ["b_guney", "b_dogu", "b_bati", "b_merkez",
        "hane", "memnuniyet", "donem", "ortalama"]


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


def ayrik(u, w):
    t = 0.0
    for i, x in enumerate(w):
        t += x
        if u < t:
            return i
    return len(w) - 1


def karistir(dizi, tohum):
    r, s = uretec(tohum), list(dizi)
    for i in range(len(s) - 1, 0, -1):
        j = int(r() * (i + 1))
        s[i], s[j] = s[j], s[i]
    return s


VERI = []
for i in range(HAM):
    r = uretec(TOHUM + i)
    b = BOLGE[ayrik(r(), [x[1] for x in BOLGE])]
    hane = 1 + ayrik(r(), [0.06, 0.24, 0.30, 0.24, 0.11, 0.05])
    memnun = 1 + ayrik(r(), [0.08, 0.14, 0.27, 0.34, 0.17])
    if r() < 0.046:
        continue
    no = 10001 + i
    r, v = uretec(TOHUM + 7000 + no), []
    for d in range(ayrik(r(), [0.05, 0.12, 0.21, 0.62])):
        v.append(0.0 if r() < 0.038 else math.floor(
            b[2] * math.exp((r() + r() + r() - 1.5) * 0.62)
            * (1 - d * 0.05) * 100 + 0.5) / 100)
        r()
    if not v:
        continue
    ort, oyn, r = sum(v) / len(v), max(v) - min(v), uretec(TOHUM + 51000 + no)
    z = (0.052 * (ort - 20) + 0.85 * (min(v) == 0.0) + 0.026 * oyn
         + 0.24 * (hane >= 5) - 0.20 * (memnun >= 4) + b[3]
         + 0.9 * (no - 10001) / 1399 + (r() + r() + r() - 1.5) * 1.30)
    x = {"hane": hane, "memnuniyet": memnun, "donem": len(v),
         "ortalama": round(ort, 2), "supheli": int(z > 1.35)}
    for q in BOLGE[1:]:
        x["b_" + q[0]] = int(b[0] == q[0])
    VERI.append(x)

K = karistir(VERI, TOHUM + 90000)
EGT, DOG, SIN = K[:300], K[756:1008], K[1008:]


def tablo(satirlar, ist=None):
    X = [[float(s[a]) for a in ALAN] for s in satirlar]
    if ist is None:                       # olcek yalniz egitim kumesinden ogrenilir
        ist = []
        for j in range(4, 8):
            m = sum(v[j] for v in X) / len(X)
            ist.append((j, m, math.sqrt(sum((v[j] - m) ** 2 for v in X) / len(X))))
    for v in X:
        for j, m, sd in ist:
            v[j] = (v[j] - m) / sd
    return X, [s["supheli"] for s in satirlar], ist


XE, yE, IST = tablo(EGT)
XD, yD, _ = tablo(DOG, IST)
XS, yS, _ = tablo(SIN, IST)
TABAN = sum(v == 0 for v in yS) / len(yS)

G = len(ALAN)


def ilklendir(tohum, h):
    r = uretec(tohum)
    return [(r() * 2 - 1) * math.sqrt(2.0 / G) for _ in range(h * G)] + [0.0] * h \
        + [(r() * 2 - 1) * math.sqrt(2.0 / h) for _ in range(h)] + [0.0]


def egim(p, X, y, par, h):
    g = [0.0] * len(p)
    for k in par:
        x, hh = X[k], [0.0] * h
        for j in range(h):
            s = p[h * G + j] + sum(p[j * G + i] * x[i] for i in range(G))
            hh[j] = s if s > 0 else 0.0
        s = p[-1] + sum(p[h * G + h + j] * hh[j] for j in range(h))
        d = (1.0 / (1.0 + math.exp(-s)) if s > -30 else 0.0) - y[k]
        g[-1] += d
        for j in range(h):
            g[h * G + h + j] += d * hh[j]
            if hh[j] > 0:
                g[h * G + j] += d * p[h * G + h + j]
                for i in range(G):
                    g[j * G + i] += d * p[h * G + h + j] * x[i]
    return [v / len(par) for v in g]


def egit(tohum, h, adim, toplu, tur):
    p = ilklendir(tohum, h)
    for t in range(tur):
        d = karistir(range(len(XE)), TOHUM + 700 + t)
        for b in range(0, len(d) - toplu + 1, toplu):
            p = [u - adim * v for u, v in zip(p, egim(p, XE, yE, d[b:b + toplu], h))]
    return p


def dogruluk(p, X, y, h):
    n = 0
    for k in range(len(X)):
        x = X[k]
        o = p[-1] + sum(p[h * G + h + j] * max(0.0, p[h * G + j]
                        + sum(p[j * G + i] * x[i] for i in range(G)))
                        for j in range(h))
        n += (o >= 0.0) == (y[k] == 1)
    return n / len(X)


print(f"kurgu: egitim {len(XE)} satir (756'dan kucultuldu), dogrulama {len(XD)}, "
      f"sinama {len(XS)}; taban cizgisi {TABAN:.4f}")
```

```
kurgu: egitim 300 satir (756'dan kucultuldu), dogrulama 252, sinama 252; taban cizgisi 0.7579
```

#### On Aday, İki Koşum

```python
# ON ADAY, her biri IKI KOSUM. Arama yontemleri M27/K03'te olculdu ve burada
# tekrarlanmaz; degisen tek sey her adayin sayisinin KAC KOSUMDAN okundugudur.
# Secim dogrulama kumesinden yapilir, rapor sinama kumesinden.
ADAY = [(4, 0.15, 30), (4, 0.30, 30), (8, 0.15, 30), (8, 0.30, 30), (8, 0.60, 30),
        (8, 0.30, 20), (8, 0.30, 50), (16, 0.15, 30), (16, 0.30, 30), (16, 0.60, 30)]
DOGRULAMA, SINAMA = [], []
print(f"{'aday':>4} {'gizli':>6} {'adim':>5} {'toplu':>6} {'dog k1':>7} {'dog k2':>7} "
      f"{'|fark|':>7} {'sin k1':>7} {'sin k2':>7}")
for no, (h, adim, toplu) in enumerate(ADAY, 1):
    P = [egit(TOHUM + k, h, adim, toplu, 40) for k in (1, 2)]
    d = [dogruluk(p, XD, yD, h) for p in P]
    s = [dogruluk(p, XS, yS, h) for p in P]
    DOGRULAMA.append(d)
    SINAMA.append(s)
    print(f"{no:>4} {h:>6} {adim:>5.2f} {toplu:>6} {d[0]:>7.4f} {d[1]:>7.4f} "
          f"{abs(d[0] - d[1]):>7.4f} {s[0]:>7.4f} {s[1]:>7.4f}")
```

```
aday  gizli  adim  toplu  dog k1  dog k2  |fark|  sin k1  sin k2
   1      4  0.15     30  0.8135  0.8175  0.0040  0.8095  0.8056
   2      4  0.30     30  0.8016  0.8254  0.0238  0.8095  0.8016
   3      8  0.15     30  0.8135  0.8175  0.0040  0.8016  0.8056
   4      8  0.30     30  0.8095  0.8175  0.0079  0.8095  0.7937
   5      8  0.60     30  0.8016  0.8056  0.0040  0.7857  0.8056
   6      8  0.30     20  0.7976  0.8095  0.0119  0.7976  0.7976
   7      8  0.30     50  0.8095  0.8175  0.0079  0.8016  0.8056
   8     16  0.15     30  0.8294  0.8254  0.0040  0.8135  0.8056
   9     16  0.30     30  0.8294  0.8175  0.0119  0.8095  0.8016
  10     16  0.60     30  0.8016  0.8016  0.0000  0.7976  0.7976
```

Birinci doğrulama sütunu alışıldık bir sonuç veriyor: en yüksek iki sayı 0,8294 ve ikisi de on
altı birimli adaylara ait, yani kapasite kazandırmış görünüyor. İkinci sütun bunu bozuyor: iki
numaralı aday — listenin **en küçük** ağı — birinci koşumda 0,8016 verirken ikinci koşumda
0,8254'e çıkıp sekiz numaralı adayla başa baş geliyor.

#### Arama Neyi Seçiyor

```python
# Aramanin sectigi aday, hangi kosumdan bakildigina bagli.
ADAYLAR_ARASI = max(d[0] for d in DOGRULAMA) - min(d[0] for d in DOGRULAMA)
KOSUM_ICI = [abs(d[0] - d[1]) for d in DOGRULAMA]
print(f"adaylar arasi yayilim (kosum 1, dogrulama) {ADAYLAR_ARASI:.4f}")
print(f"ayni adayin iki kosumu arasindaki fark: en cok {max(KOSUM_ICI):.4f}, "
      f"ortanca {sorted(KOSUM_ICI)[len(KOSUM_ICI) // 2]:.4f}")
CIFT = [(i, j) for i in range(len(ADAY)) for j in range(i + 1, len(ADAY))]
belirsiz = sum(1 for i, j in CIFT
               if abs(DOGRULAMA[i][0] - DOGRULAMA[j][0]) <= max(KOSUM_ICI[i], KOSUM_ICI[j]))
ters = sum(1 for i, j in CIFT
           if (DOGRULAMA[i][0] - DOGRULAMA[j][0]) * (DOGRULAMA[i][1] - DOGRULAMA[j][1]) < 0)
print(f"{len(CIFT)} aday ciftinin {belirsiz}'i kosum farkiyla ayirt edilemiyor; "
      f"{ters} ciftte siralama iki kosum arasinda TERS donuyor")
for k in (0, 1):
    en = max(range(len(ADAY)), key=lambda i: (DOGRULAMA[i][k], -i))
    print(f"kosum {k + 1}'e gore secilen aday {en + 1} (gizli {ADAY[en][0]}, "
          f"adim {ADAY[en][1]:.2f}, toplu {ADAY[en][2]}): dogrulama "
          f"{DOGRULAMA[en][k]:.4f}, sinama {SINAMA[en][k]:.4f}")
ort = sum(s[0] for s in SINAMA) / len(SINAMA)
print(f"on adayin sinama ortalamasi {ort:.4f}; taban cizgisi {TABAN:.4f}")
```

```
adaylar arasi yayilim (kosum 1, dogrulama) 0.0317
ayni adayin iki kosumu arasindaki fark: en cok 0.0238, ortanca 0.0079
45 aday ciftinin 23'i kosum farkiyla ayirt edilemiyor; 7 ciftte siralama iki kosum arasinda TERS donuyor
kosum 1'e gore secilen aday 8 (gizli 16, adim 0.15, toplu 30): dogrulama 0.8294, sinama 0.8135
kosum 2'e gore secilen aday 2 (gizli 4, adim 0.30, toplu 30): dogrulama 0.8254, sinama 0.8016
on adayin sinama ortalamasi 0.8036; taban cizgisi 0.7579
```

Dersin sayısı ilk iki satırda. Adaylar arası açıklık **0,0317**, aynı adayın iki koşumu arasındaki
en büyük fark **0,0238**; ikisi aynı büyüklük sırasındadır. Kırk beş aday çiftinin **yirmi üçü**,
yani yarıdan fazlası, koşum farkıyla ayırt edilemiyor ve yedi çiftte sıralama iki koşum arasında
**ters dönüyor**.

Birinci koşumdan bakan arama sekiz numaralı adayı seçiyor: on altı birim. İkinci koşumdan bakan
arama iki numaralı adayı: dört birim. Aynı liste, aynı bütçe ve **kapasite sorusuna iki ayrı
yanıt**; seçilenlerin sınama sayıları 0,8135 ve 0,8016.

On adayın sınama ortalaması 0,8036: birinci koşumdan seçilen aday bunun 0,0099 üstünde, ikinci
koşumdan seçilen 0,0020 altında. Arama, hangi koşumdan bakıldığına göre iki buçuk abone
kazandırıyor ya da yarım abone kaybettiriyor. Ayar bütçesi M27/K03'te sayının şişmesini
üretiyordu; burada ondan önce gelen bir sorun var — **arama sıralaması gürültüden kurulmuşsa
şişecek bir kazanç da yoktur.** Çaresi pahalıdır: her adayı birden çok koşumla ölçüp sayısını
koşumların ortalaması olarak yazmak; bütçe on adaydan beşe iner.

#### Özet

- Adaylar arası açıklık doğrulama kümesinde 0,0317, tek bir adayın iki koşumu arasındaki en büyük
  fark 0,0238; ikisi aynı büyüklük sırasındadır.
- Kırk beş aday çiftinin yirmi üçü koşum farkıyla ayırt edilemiyor, yedisinde sıralama ters
  dönüyor.
- Birinci koşumdan bakan arama on altı birimli, ikinci koşumdan bakan dört birimli adayı seçiyor:
  aynı liste kapasite sorusuna iki ayrı yanıt veriyor, sınama sayıları 0,8135 ile 0,8016.
- On adayın sınama ortalaması 0,8036 ve taban çizgisi 0,7579; arama hangi koşumdan bakıldığına göre
  iki buçuk abone kazandırıyor ya da yarım abone kaybettiriyor.

#### Kurs Kapanışı

Yirmi dört dersin hesabı tek tabloda ve her sayı kendi dersinden okundu. **Satırlar ortak birim
taşımaz**: kurs üç ayrı kurgu küme kullandı ve son sütun hangisinden okunduğunu yazar. Ölçüt yirmi
üç satırda **doğruluktur** ve büyük olan iyidir; **Mimariler 10** satırı etiketsizdir,
**geri kurma hatasıyla** okunur ve orada küçük olan iyidir. İkinci koşum, aynı kurulumun
yalnız başlangıç değerleri değiştirilerek yeniden eğitilmesidir.

| Ders | Taban çizgisi | Ağın sayısı | İkinci koşum | Küme |
|---|---|---|---|---|
| Temeller 01 | 0,7579 | 0,7857 | 0,7698 | abone |
| Temeller 02 | 0,7579 | 0,7937 | 0,7976 | abone |
| Temeller 03 | 0,7579 | 0,7540 | 0,7738 | abone |
| Temeller 04 | 0,7579 | 0,7619 | 0,7897 | abone |
| Temeller 05 | 0,7579 | 0,7857 | 0,7698 | abone |
| Temeller 06 | 0,7579 | 0,7857 | 0,7698 | abone |
| Temeller 07 | 0,7579 | 0,7817 | 0,7778 | abone |
| Temeller 08 | 0,7579 | 0,7937 | 0,7738 | abone |
| Temeller 09 | 0,7579 | 0,7698 | 0,7857 | abone |
| Mimariler 01 | 0,5850 | 0,8000 | 0,8150 | ızgara |
| Mimariler 02 | 0,5850 | 0,8050 | 0,8050 | ızgara |
| Mimariler 03 | 0,5850 | 0,8150 | 0,8900 | ızgara |
| Mimariler 04 | 0,7100 | 0,7350 | 0,7150 | dizi |
| Mimariler 05 | 0,7100 | 0,9750 | 0,9150 | dizi |
| Mimariler 06 | 0,6333 | 0,8889 | 0,9944 | dizi |
| Mimariler 07 | 0,6611 | 0,8778 | 0,8833 | dizi |
| Mimariler 08 | 0,6444 | 0,9722 | 0,9833 | olay kodu |
| Mimariler 09 | 0,6444 | 0,8333 | 0,8500 | olay kodu |
| Mimariler 10 | 2,9007 | 0,7949 | 0,7638 | dizi (hata) |
| Eğitim 01 | 0,7579 | 0,8095 | 0,7937 | abone |
| Eğitim 02 | 0,7579 | 0,8016 | 0,8095 | abone |
| Eğitim 03 | 0,7579 | 0,8056 | 0,7937 | abone |
| Eğitim 04 | 0,7579 | 0,8095 | 0,7937 | abone |
| Eğitim 05 | 0,7579 | 0,8135 | 0,8016 | abone |

**Kursun kuralı budur: bir ağın sayısı, kapasitesinden değil eğitiminden gelebilir; aynı
kapasitenin iki koşumda iki ayrı sayı verdiği yazılmayan sonuç ölçülmemiş sayılır.** Üçüncü sütun
tek bir sayıya iner: kapasitenin ya da mimarinin kattığı farkın kendi dersinde yazıldığı yirmi bir
derste **on dördünde** ikinci koşumun farkı o farktan büyük çıktı — evrişimli mimaride derinliğin
kattığı 0,0575'e karşı 0,0750, çok başlı dikkatte baş sayısının kattığı 0,0250'ye karşı 0,0500,
algılayıcıda kapasitenin kattığı bir aboneye karşı dört abone. Kalan yedide kapasitenin kattığı
fark koşum farkına eşit ya da ondan büyüktü.

Kursun ikinci iddiası aynı tablodan okunur ve saklanmaz. Abone tablosunun on dört satırında
karşılaştırma çizgileri M27/K03'ten gelir: karar ağacı 0,7857, doğrusal model 0,8016. Sinir ağı
temellerinin dokuz dersinde ağın sayısı **hiçbir koşumda 0,8016'yı geçmedi**; on sekiz koşumun en
yükseği 0,7976 ve üç dersin ağın sayısı tam olarak ağacın sayısında durdu. Eğitim pratiğinin beş
dersinde ağın sayısı 0,8016 ile 0,8135 arasında, yani doğrusal modelin çizgisinde ya da üstünde
kaldı; ama sekiz sütunlu bir öznitelik kümesiyle koştular ve birinci dersin on ilklendirmesi
0,7857–0,8095 arasına yayıldı, iki çizgi de bu aralığın içinde. **Derin ağ bu kurgu
tablo verisinde karar ağacını ve doğrusal modeli, koşum değişkenliğinden ayrılabilir biçimde
geçemedi.** Kazanç kapasiteden değil eğitim pratiğinden geldi ve en az bir derste daha derin ağ
daha sığ ağı geçemedi.

Yirmi dört derste mimari kuruldu ve her sayının yanına ikinci koşumu yazıldı. Ama girdiler hep
**hazır sayılardı**: bir sütun, bir ızgara hücresi, bir okuma dizisi, bir olay kodu. Bir metnin ya
da bir görüntünün sayıya nasıl çevrildiği, o çevirinin **hangi tabana karşı** ölçüldüğü ve alanın
kendi ölçütlerinin ne olduğu hiç sorulmadı. Sonraki kurs, Doğal Dil İşleme ve Bilgisayarla Görme,
bu soruyla açılır.

