Yoğun katman geri geçişi
Zorluk: Zor Çözüldüsinir ağları
Bir yoğun katman (dense layer), örneklik (sample) bir yığın (batch) için çıktıyı şöyle hesaplar:
Burada:
- : ağırlık matrisi (weight matrix).
- : sapma vektörü (bias). Her satıra eklenir.
Geri geçişte (backward pass) layer, kaybın (loss) kendi çıktısına göre gradyanını (gradient) bir sonraki layer’dan alır:
‘nin şekli (shape) ‘dur.
dense_backward(X, W, dZ) fonksiyonunu yaz. Zincir kuralıyla (chain rule), ‘nin layer’ın girdisine, ağırlıklarına ve sapmasına göre gradyanlarını hesapla:
Her gradyanın shape’i, türevi alınan şeyin shape’iyle aynıdır. Sapmanın değeri gradyanlara girmediği için fonksiyon ‘yi almaz.
(dX, dW, db) demetini (tuple) döndür.
Örnekler
Girdi: X = [[1.0, 2.0], [3.0, 4.0], [5.0, 6.0]], W = [[1.0, 0.0, -1.0, 2.0], [0.5, 1.0, 0.0, -2.0]], dZ = [[1.0, 0.0, 0.0, 1.0], [0.0, 1.0, 0.0, -1.0], [2.0, 0.0, 1.0, 0.0]]
Çıktı: (array([[ 3. , -1.5],
[-2. , 3. ],
[ 1. , 1. ]]), array([[11., 3., 5., -2.],
[14., 4., 6., -2.]]), array([3., 1., 1., 0.]))
Girdi: X = [[2.0, -1.0, 0.5]], W = [[1.0, 0.0], [0.0, 1.0], [1.0, -1.0]], dZ = [[1.0, -2.0]]
Çıktı: (array([[ 1., -2., 3.]]), array([[ 2. , -4. ],
[-1. , 2. ],
[ 0.5, -1. ]]), array([ 1., -2.]))
Girdi: X = [[-1.0, 2.0], [0.5, -3.0]], W = [[1.5, -0.5], [2.0, 1.0]], dZ = [[-1.0, 0.5], [2.0, -2.0]]
Çıktı: (array([[-1.75, -1.5 ],
[ 4. , 2. ]]), array([[ 2. , -1.5],
[-8. , 7. ]]), array([ 1. , -1.5]))
İpucu 1
Shape’ler hangi matris çarpımının geçerli olduğunu söyler. ‘in shape’i ‘in shape’iyle, yani ile aynıdır.
Elinde iki matris var:
- : shape’inde.
- : shape’inde.
Bu ikisinden çıkaran bir matris çarpımı için birinin devriği (transpose) gerekir. Aynı bulmacayı için de çöz: elinde ve var.
İpucu 2
yalnızca ‘nin . sütununu etkiler. Bunu ‘nin tanımında görürsün:
Her satırında bu etkiyi ölçekler. Bu yüzden:
Bu toplam bir matris çarpımının tanımıdır.
İpucu 3
, ‘nin . sütunundaki değerlerin toplamıdır. Çünkü , ‘nin . sütununun her satırına eklenir ve yerel türevi her yerde ‘dir. Hangi eksen (axis) boyunca toplayacağını (d_out,) shape’i söyler.
Gereksinimler
X(n, d_in),W(d_in, d_out)vedZ(n, d_out)shape’inde array’lerdir.- Dönüş değeri, sırasıyla
(n, d_in),(d_in, d_out)ve(d_out,)shape’inde üç NumPy array’inden oluşan bir tuple’dır:(dX, dW, db). Liste değil. db,(d_out,)shape’inde bir vektördür.(n,)ya da(1, d_out)değil.dZzaten kaybın gradyanıdır. Sonuçların’ye bölme ya da başka bir sayıyla ölçekleme.X’i,W’yi vedZ’yi değiştirme. Fonksiyon bittiğinde çağıran kodun array’leri aynı kalmalı.- Örnekler üzerinde döngü kullanma.
Geri geçişte her layer iki iş yapar.
- Kendi parametrelerinin gradyanını hesaplar.
- Gradyanı bir önceki layer’a iletir.
İkisi de zincir kuralından çıkar. Tek bir örnekle başlayalım: ve olsun.
- ağırlığı çıktının . elemanına ile çarpılarak katılır. Bu yüzden olur.
- , ile vektörlerinin dış çarpımıdır (outer product): ilk satır , ikinci satır .
- doğrudan çıktının . elemanına eklenir. Bu yüzden çıkar.
Bir batch’te her örnek kendi dış çarpımını getirir. ile bütün örnekler için ortak olduğundan hepsi toplanır:
ise girdinin her elemanının çıktıyı üzerinden etkilemesinden gelir:
Shape’lere bakmak yanlışları ucuza yakalar. İki kontrol var:
- için , yani çıkar.
- için , yani çıkar.
Kayıp bir ortalamaysa çarpanı ‘nin içinde zaten vardır. Gradyanları ayrıca ‘ye bölmezsin.
Daha fazlası için Yoğun katmanın geri geçişi ve gradyan kontrolü dersine bak.
Üç gradyan da birer matris çarpımı ya da toplamdır. Her birinin shape’i, türevi alınan şeyin shape’iyle uyuşur.
import numpy as npdef dense_backward(X: np.ndarray, W: np.ndarray, dZ: np.ndarray) -> tuple[np.ndarray, np.ndarray, np.ndarray]: dX = dZ @ W.T dW = X.T @ dZ db = dZ.sum(axis=0) return dX, dW, db
Sık yapılan hata, sapma gradyanını yanlış axis boyunca toplamaktır:
dZ.sum(axis=1),(d_out,)yerine(n,)shape’inde bir vektör verir.niled_outeşitse shape bile uyuşur. Hata yalnızca değerlerde görünür.
Sapma her satıra eklenir. Gradyanını satırlar boyunca, yani axis=0 üzerinden toplarsın.
Bu problemde bir sorun mu var?