---
title: 'Geri Yayılım'
source: 'https://academia.sh/tr/kurslar/derin-ogrenme/geri-yayilim'
course: 'Derin Öğrenme'
language: tr
updated: '2026-08-17T18:10:09+00:00'
license: 'CC BY-SA 4.0'
---

# Geri Yayılım

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 6,441e-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        6.441e-11       1.227e-09
100 tur egitimden sonra    1e-07        113        5.694e-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 6,441e-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 6,441e-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 6,441e-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.
