Zincir kuralı (backprop'un kalbi)
Önkoşul:Türev: değişim hızı
Kanca
Bir sinir ağının ONLARCA katmanı olduğunda, EN BAŞTAKİ bir parametrenin, EN SONDAKİ hatayı NASIL etkilediğini nasıl hesaplarsın? Cevap, aslında, İLKOKULDAN beri bildiğin bir fikrin GENELLEŞTİRİLMİŞ hâli.
Sezgi
Bazı fonksiyonlar, BAŞKA fonksiyonların İÇİNE yerleştirilmiştir. ZİNCİR KURALI, böyle bir “iç içe” fonksiyonun türevini bulmanın yoludur: DIŞ fonksiyonun türevini, İÇ fonksiyonun türeviyle ÇARP. BACKPROPAGATION, bu fikrin, bir sinir ağının TÜM katmanlarına ZİNCİRLEME uygulanmasından BAŞKA bir şey DEĞİLDİR.
Mekanizma
fonksiyonu, aslında İKİ fonksiyonun İÇ İÇE geçmesidir:
İç içe fonksiyonlar: h(x) = f(g(x))
# Bazı fonksiyonlar, BAŞKA bir fonksiyonun İÇİNE yerleştirilmiştir --
# h(x) = (3x+1)^2, aslında İKİ fonksiyonun BİRLEŞİMİDİR: önce u=g(x)=3x+1,
# sonra h=f(u)=u^2.
def g(x):
return 3 * x + 1
def f(u):
return u ** 2
def h(x):
return f(g(x)) # h(x) = (3x+1)^2 -- İÇ İÇE fonksiyonlar
x0 = 1.0
print(f"x0 = {x0}")
print(f"g({x0}) = 3*{x0}+1 = {g(x0)} (İÇ fonksiyon)")
print(f"f(g({x0})) = {g(x0)}^2 = {f(g(x0))} (DIŞ fonksiyon, İÇ fonksiyonun SONUCUNA uygulanıyor)")
print(f"h({x0}) = {h(x0)} (aynı sonuç, TEK adımda)")x0 = 1.0
g(1.0) = 3*1.0+1 = 4.0 (İÇ fonksiyon)
f(g(1.0)) = 4.0^2 = 16.0 (DIŞ fonksiyon, İÇ fonksiyonun SONUCUNA uygulanıyor)
h(1.0) = 16.0 (aynı sonuç, TEK adımda)Şimdi bu iç içe fonksiyonun türevini ZİNCİR KURALIYLA bulalım:
Zincir kuralı: dışın türevi çarpı için türevi
# ZİNCİR KURALI: h(x)=f(g(x)) türevi, f'(g(x)) * g'(x)'TİR -- yani "DIŞ
# fonksiyonun türevi (İÇ fonksiyonun DEĞERİNDE) ÇARPI İÇ fonksiyonun türevi".
def g_turev(x):
return 3 # g(x)=3x+1 -> g'(x)=3
def f_turev(u):
return 2 * u # f(u)=u^2 -> f'(u)=2u
zincir_sonucu = f_turev(g(x0)) * g_turev(x0)
print(f"\nZincir kuralı: h'(x0) = f'(g(x0)) * g'(x0) = f'({g(x0)}) * {g_turev(x0)} = {f_turev(g(x0))} * {g_turev(x0)} = {zincir_sonucu}")
# SONLU FARK ile doğrulama (9. dersteki gibi):
h_ = 0.0001
sonlu_fark = (h(x0 + h_) - h(x0)) / h_
print(f"Sonlu fark ile: (h({x0}+{h_}) - h({x0})) / {h_} = {sonlu_fark:.4f}")
print(f"Zincir kuralı ile SONLU FARK AYNI sonucu veriyor: {np.isclose(zincir_sonucu, sonlu_fark, atol=0.01)}")
Zincir kuralı: h'(x0) = f'(g(x0)) * g'(x0) = f'(4.0) * 3 = 8.0 * 3 = 24.0
Sonlu fark ile: (h(1.0+0.0001) - h(1.0)) / 0.0001 = 24.0009
Zincir kuralı ile SONLU FARK AYNI sonucu veriyor: TrueMatematik
Zincir kuralı
Bu, kelimenin tam anlamıyla bir ZİNCİRDİR: her “halka” (katman), kendi YEREL türevini hesaplar, ve hepsi birbirine ÇARPILARAK bağlanır.
Kod
Şimdi bunu, minik bir “sinir ağı” üzerinde, TAM OLARAK backpropagation’ın yaptığı gibi uygulayalım:
Backprop = zincir kuralının katman katman uygulanması
# BACKPROPAGATION, ZİNCİR KURALININ, birden fazla KATMANDAN geçerek TEKRAR
# TEKRAR uygulanmasıdır. Minik bir "sinir ağı": w (parametre) -> z=w*x -> a=z^2 -> Kayıp
girdi_x = 2.0
hedef = 10.0
w = 3.0
z = w * girdi_x # katman 1: doğrusal
a = z ** 2 # katman 2: "aktivasyon" (kare)
kayip = (a - hedef) ** 2 # katman 3: kayıp fonksiyonu
print(f"\nİLERİ YÖN (forward pass): w={w}, x={girdi_x}")
print(f" z = w*x = {w}*{girdi_x} = {z}")
print(f" a = z^2 = {z}^2 = {a}")
print(f" Kayıp = (a-hedef)^2 = ({a}-{hedef})^2 = {kayip}")
# GERİ YÖN (backward pass): zincir kuralını KATMAN KATMAN geriye doğru uygula.
dKayip_da = 2 * (a - hedef) # Kayıp'ın a'ya göre türevi
da_dz = 2 * z # a'nın z'ye göre türevi
dz_dw = girdi_x # z'nin w'ya göre türevi
dKayip_dw = dKayip_da * da_dz * dz_dw # ZİNCİR KURALI: hepsini ÇARP
print(f"\nGERİ YÖN (backward pass), zincir kuralıyla:")
print(f" dKayıp/da = 2*(a-hedef) = 2*({a}-{hedef}) = {dKayip_da}")
print(f" da/dz = 2*z = 2*{z} = {da_dz}")
print(f" dz/dw = x = {dz_dw}")
print(f" dKayıp/dw = dKayıp/da * da/dz * dz/dw = {dKayip_da} * {da_dz} * {dz_dw} = {dKayip_dw}")
# SONLU FARK ile doğrulama:
def kayip_fonksiyonu(w_):
z_ = w_ * girdi_x
a_ = z_ ** 2
return (a_ - hedef) ** 2
h_ = 0.0001
sonlu_fark_dw = (kayip_fonksiyonu(w + h_) - kayip_fonksiyonu(w)) / h_
print(f"\nSonlu fark ile dKayıp/dw: {sonlu_fark_dw:.2f}")
print(f"Zincir kuralı ile SONLU FARK AYNI sonucu veriyor: {np.isclose(dKayip_dw, sonlu_fark_dw, rtol=0.01)}")
print("\nİşte BACKPROPAGATION budur: HER katmanın 'yerel' türevini hesaplayıp,")
print("zincir kuralıyla ÇARPARAK, en baştaki parametreye (w) kadar GERİ YAYMAK.")
İLERİ YÖN (forward pass): w=3.0, x=2.0
z = w*x = 3.0*2.0 = 6.0
a = z^2 = 6.0^2 = 36.0
Kayıp = (a-hedef)^2 = (36.0-10.0)^2 = 676.0
GERİ YÖN (backward pass), zincir kuralıyla:
dKayıp/da = 2*(a-hedef) = 2*(36.0-10.0) = 52.0
da/dz = 2*z = 2*6.0 = 12.0
dz/dw = x = 2.0
dKayıp/dw = dKayıp/da * da/dz * dz/dw = 52.0 * 12.0 * 2.0 = 1248.0
Sonlu fark ile dKayıp/dw: 1248.08
Zincir kuralı ile SONLU FARK AYNI sonucu veriyor: True
İşte BACKPROPAGATION budur: HER katmanın 'yerel' türevini hesaplayıp,
zincir kuralıyla ÇARPARAK, en baştaki parametreye (w) kadar GERİ YAYMAK.Nerede işe yarar
Zincir kuralı, TÜM derin öğrenmenin eğitim sürecinin MOTORUDUR:
- DL Görüntü ve DL NLP kategorilerinde, bir ağın “eğitilmesi”, TAM OLARAK bu dersteki gibi, kayıptan geriye doğru, katman katman ZİNCİR KURALI uygulanmasıdır.
- Bir ağın 100 katmanı OLSA BİLE, mantık DEĞİŞMEZ — SADECE zincirdeki halka SAYISI artar.
- 11-12. derslerde (kısmi türev, gradyan inişi), bu zincirleme türev hesabının, BİRDEN FAZLA parametre için NASIL genelleştiği göreceğiz.
Bu 2 hatayı yaparsın:
- Zincir kuralını “İÇ ve DIŞ fonksiyonların türevini TOPLAMAK” sanmak — HAYIR, TOPLANMAZ, ÇARPILIR.
- Backpropagation’ı “ayrı, gizemli bir algoritma” sanmak — HAYIR, SADECE zincir kuralının, bir hesaplama grafiğinin TÜM katmanlarına GERİYE doğru uygulanmasıdır.
Kendini test et
1. zincir-kurali-elle bloğunda h'(1.0)=24.0 çıkıyor ve sonlu fark da 24.0009 veriyor. Bu hesap NASIL yapıldı?
- f'(1.0) ile g'(1.0) toplanarak
- DIŞ fonksiyonun türevi İÇ fonksiyonun DEĞERİNDE hesaplanıp (f'(g(1))=f'(4)=8), İÇ fonksiyonun türeviyle (g'(1)=3) ÇARPILARAK: 8*3=24 (doğru cevap)
- Rastgele bir sayı seçilerek
- Sadece g(x) türevi alınarak
Neden: zincir-kurali-elle bloğunda bu adım adım gösteriliyor: h'(x0) = f'(g(x0)) * g'(x0) = 8.0 * 3 = 24.0.
2. backprop-mini-graf bloğunda dKayıp/dw, üç YEREL türevin (dKayıp/da, da/dz, dz/dw) ÇARPILMASIYLA bulunuyor. Bu NEYİ temsil ediyor?
- Rastgele bir hesaplama
- Backpropagation'ın TAM OLARAK NASIL çalıştığını -- bir sinir ağının HER katmanı kendi YEREL türevini hesaplar, ve bunlar zincir kuralıyla ÇARPILARAK en baştaki parametreye (w) kadar GERİ YAYILIR (doğru cevap)
- Sadece son katmanın önemli olduğunu
- w parametresinin etkisiz olduğunu
Neden: backprop-mini-graf bloğunun sonunda bu AÇIKÇA belirtiliyor: 'İşte BACKPROPAGATION budur: HER katmanın yerel türevini hesaplayıp, zincir kuralıyla ÇARPARAK ... GERİ YAYMAK'.
3. Bir sinir ağının 100 katmanı olsa, zincir kuralının UYGULANMA MANTIĞI NASIL değişir?
- Tamamen farklı bir yöntem gerekir
- Mantık DEĞİŞMEZ -- SADECE zincirdeki YEREL türev SAYISI artar; her katman kendi yerel türevini hesaplar ve hepsi ÇARPILIR, katman sayısı ne olursa olsun (doğru cevap)
- Zincir kuralı sadece 3 katmana kadar çalışır
- Türev alma işlemi gereksiz hale gelir
Neden: kullanım bölümünde bu AÇIKÇA belirtiliyor: 'Bir ağın 100 katmanı OLSA BİLE, mantık DEĞİŞMEZ -- SADECE zincirdeki halka SAYISI artar'.
Özet
Özet
- Zincir kuralı, iç içe geçmiş fonksiyonların (h(x)=f(g(x))) türevini bulmanın yoludur: f'(g(x)) · g'(x).
- Bu ders, dış fonksiyonun türevinin İÇ fonksiyonun türeviyle ÇARPILDIĞINI (toplanmadığını) gösterdi.
- Backpropagation, zincir kuralının bir hesaplama grafiğinin TÜM katmanlarına GERİYE doğru uygulanmasıdır.
- Bu dersteki mini "sinir ağı" örneğinde (w→z→a→Kayıp), üç yerel türev ÇARPILARAK dKayıp/dw=1248 bulundu.
- Katman sayısı ne olursa olsun (2 ya da 200), mantık AYNIDIR: her katmanın yerel türevini ÇARP.