Sıradaki

Yoğun katman ileri geçişi

Zorluk: Orta

sinir ağları

Yoğun katman (dense layer), sinir ağlarının temel yapı taşıdır. Layer’daki her nöron (neuron) bir örnek (sample) için şunları yapar:

  1. Örneğin bütün özniteliklerini (feature) kendi ağırlıklarıyla (weight) çarpar ve toplar.
  2. Bir sapma (bias) ekler.
  3. Sonucu bir aktivasyon fonksiyonundan (activation function) geçirir.

Bütün nöronları ve bütün örnekleri tek bir matris çarpımıyla (matrix product) hesaplayabilirsin.

dense_forward(X, W, b, activation) fonksiyonunu yaz. Fonksiyon, layer’ın ileri geçişini (forward pass) hesaplar. Girdiler şunlardır:

  • X: şekli (shape) (n, d_in) olan bir dizi (array). Her satır bir örnektir.
  • W: (d_in, d_out) shape’inde weight matrisi. jj. sütunu jj. nöronun weight’leridir.
  • b: (d_out,) shape’inde bir vektör. Her nöron için bir bias içerir.
  • activation: aktivasyon fonksiyonunun adı, bir str.
Z=XW+b,A=g(Z)Z = XW + \mathbf{b}, \qquad A = g(Z)

ZZ aktivasyon öncesi değerlerdir (pre-activation). b\mathbf{b}, XWXW‘nin her satırına eklenir. Aktivasyon, bias eklendikten sonra uygulanır.

gg, activation adıyla seçilen fonksiyondur. ZZ‘nin her elemanına ayrı uygulanır. Seçenekler şunlardır:

  • "linear": g(z)=zg(z) = z, yani aktivasyon yok.

  • "relu": g(z)=max⁡(0,z)g(z) = \max(0, z). ReLU (rectified linear unit) negatifleri sıfıra çeker.

  • "sigmoid": sigmoid her değeri 00 ile 11 arasına sıkıştırır.

    g(z)=11+e−zg(z) = \dfrac{1}{1 + e^{-z}}
  • "tanh": g(z)=tanh⁡(z)g(z) = \tanh(z). Tanh (hiperbolik tanjant) her değeri −1-1 ile 11 arasına sıkıştırır.

Fonksiyon (n, d_out) shape’inde A’yı döndürmeli. Tanınmayan bir isim verilirse ValueError fırlat.

Örnekler

Girdi: X = [[1.0, -2.0], [0.5, 3.0], [-1.0, 0.0]], W = [[0.5, -1.0, 2.0], [1.5, 0.25, -0.5]], b = [0.1, -0.2, 0.3], activation = 'relu'
Çıktı: array([[0. , 0. , 3.3 ], [4.85, 0.05, 0. ], [0. , 0.8 , 0. ]])

Girdi: X = [[1.0, 2.0, 3.0]], W = [[0.5], [-1.0], [2.0]], b = [-6.0], activation = 'linear'
Çıktı: array([[-1.5]])

Girdi: X = [[-1.0, 2.0, 0.5], [0.0, -3.0, 1.0]], W = [[1.0, -0.5], [0.25, 1.0], [-2.0, 0.5]], b = [0.5, -1.0], activation = 'sigmoid'
Çıktı: array([[0.26894142, 0.8519528 ], [0.09534946, 0.02931223]])

İpucu 1

Z = X @ W + b ile başla. Shape’lere bak: (n, d_in) @ (d_in, d_out), (n, d_out) verir.

NumPy, (d_out,) shape’indeki b’yi her satıra yayınlar (broadcasting).

İpucu 2

activation’a göre bir if / elif zinciri ya da bir sözlük kullanabilirsin. Hiçbirine uymayan bir isimde raise ValueError(...) yaz.

Aktivasyonlar eleman bazında (element-wise) çalışır. ReLU için np.maximum(0.0, Z), tanh için np.tanh(Z) yeter.

İpucu 3

Sigmoid’i Kararlı sigmoid probleminde yazdığın gibi hesapla: np.exp’e hiç büyük pozitif bir sayı verme. İki ifade de sorunludur:

  • 1 / (1 + np.exp(-Z)), büyük negatif Z’de np.exp’i taşırır. Sonuç yine 0 çıkar.
  • np.exp(Z) / (1 + np.exp(Z)), büyük pozitif Z’de inf / inf, yani nan verir.

Gereksinimler

  • X (n, d_in), W (d_in, d_out), b (d_out,) shape’indedir. X @ W doğrudan çalışır. W’nin devriğini (transpose) almana gerek yok.
  • Dönüş değeri (n, d_out) shape’inde bir NumPy array’idir. n = 1 ya da d_out = 1 olsa bile iki boyutlu kalmalı.
  • Bias, aktivasyondan önce eklenir. g(XW+b)g(XW + \mathbf{b}) hesapla, g(XW)+bg(XW) + \mathbf{b} değil.
  • Tanınmayan bir activation adı için ValueError fırlat. Sessizce Z’yi döndürme.
  • Sigmoid ve tanh, büyük girdilerde de (1000 ya da -1000 gibi) nan ya da inf üretmemeli.
  • X’i, W’yi ve b’yi değiştirme. Fonksiyon bittiğinde çağıran kodun array’leri aynı kalmalı.
  • Örnekler üzerinde döngü kullanma: tek bir matris çarpımı yeter.

Layer her nöron için ağırlıklı toplamı hesaplar, bias ekler ve aktivasyonu uygular. İki özniteliği olan tek bir örnek, X=(1,2)X = (1, 2), ve iki nöronlu bir layer alalım:

W=(3−112),b=(−6,1)W = \begin{pmatrix} 3 & -1 \\ 1 & 2 \end{pmatrix}, \qquad \mathbf{b} = (-6, 1)

Hesap üç adımdır:

  1. Ağırlıklı toplamları bul: XW=(1⋅3+2⋅1,  1⋅(−1)+2⋅2)=(5,3)XW = (1 \cdot 3 + 2 \cdot 1,\; 1 \cdot (-1) + 2 \cdot 2) = (5, 3).
  2. Bias ekle: Z=(−1,4)Z = (-1, 4).
  3. ReLU uygula: A=(0,4)A = (0, 4). Birinci nöron kapanır, ikincisi geçirir.

Birçok örnek olduğunda her satır için aynı işlem yapılır. Matris çarpımı hepsini tek seferde hesaplar.

Aktivasyon gereklidir. Aktivasyonsuz iki layer’ı üst üste koyarsan sonuç yine tek bir doğrusal layer olur:

(XW1+b1)W2+b2=X(W1W2)+(b1W2+b2)(XW_1 + \mathbf{b}_1)W_2 + \mathbf{b}_2 = X(W_1 W_2) + (\mathbf{b}_1 W_2 + \mathbf{b}_2)

Layer’lar arasındaki doğrusal olmayan aktivasyon, ağın doğrusal bir modelin yapamadığı şeyleri öğrenmesini sağlar. "linear" seçeneği, çıktı layer’ı gibi aktivasyonun gerekmediği yerlere uygundur.

Bu kursta layer X @ W + b olarak yazılır. Başka bir kaynak okurken WW‘nin shape’ine bak:

KaynakWW shape’i
Bu kurs(d_in, d_out)
PyTorch nn.Linear(d_out, d_in), yani devriği

Daha fazlası için Nöronlar ve aktivasyonlar dersine bak.

Layer X @ W + b ile başlar ve aktivasyonu bias’tan sonra uygular.

  1. X @ W + b ile ZZ‘yi hesapla.
  2. Aktivasyonu activation adına göre seç.
  3. Tanınmayan bir ad için ValueError fırlat.

Sigmoid için kararlı biçimi kullan. e = np.exp(-np.abs(Z)) her Z’de güvenlidir, çünkü argümanı hiçbir zaman pozitif olmaz. Sigmoid iki durumda şöyle olur:

  • Z >= 0 için 1/(1+e)1 / (1 + e).
  • Z < 0 için e/(1+e)e / (1 + e).
import numpy as npdef dense_forward(X: np.ndarray, W: np.ndarray, b: np.ndarray, activation: str) -> np.ndarray:    Z = X @ W + b    if activation == "linear":        return Z    if activation == "relu":        return np.maximum(0.0, Z)    if activation == "sigmoid":        e = np.exp(-np.abs(Z))        return np.where(Z >= 0, 1 / (1 + e), e / (1 + e))    if activation == "tanh":        return np.tanh(Z)    raise ValueError(f"Tanınmayan aktivasyon adı: {activation}")

Sık yapılan üç hata var:

  • Bias’ı aktivasyondan sonra eklemek: np.maximum(0.0, X @ W) + b. Bias negatifse ReLU’dan sonra negatif bir değer kalır. Oysa ReLU’nun çıktısı hiçbir zaman negatif olmaz.
  • W’nin devriğini almak: W zaten (d_in, d_out) shape’indedir.
  • Sigmoid’i 1 / (1 + np.exp(-Z)) olarak yazmak: büyük negatif Z’de np.exp’i taşırır. Sonuç yine doğru çıksa da Kararlı sigmoid probleminde öğrendiğin kuralı bozar.

Bu problemde bir sorun mu var?

solution.py
import numpy as npdef dense_forward(X: np.ndarray, W: np.ndarray, b: np.ndarray, activation: str) -> np.ndarray:    """Yoğun katmanın çıktısını döndürür; şekli (n, d_out) olan bir dizi."""    # Kodunu buraya yaz.    return np.zeros((X.shape[0], W.shape[1]))

İçindekiler

Geri bildirim

Tür