9.4 Aktivációk és gradiensáramlás

9.4.1 Cél, előismeret és induló becslés

A 9.3. Expresszivitás és approximációs állítások egységben láttuk, hogy egy elég széles ReLU-háló képes tetszőleges folytonos függvényt közelíteni kompakt tartományon. Ez reprezentációs állítás volt: megmondja, hogy létezik jó súlykonfiguráció, de semmit sem ígér arról, hogy a gradiensalapú tanítás megtalálja. Ebben az egységben a másik irányt vizsgáljuk: mit mond egyetlen lokális derivált, és hogyan szorzódnak össze a lokális deriváltak mély hálóban.

Előismeret: a 9.3. Expresszivitás és approximációs állítások aktivációi, valamint a derivált és a láncszabály 4.1.–4.3. fogalmai; a tanulási célfüggvény és a gradienslépés visszahívása a 8.4. II. ellenőrző pont: korrekt tanulási állítás alfejezetből elegendő.

Induló kérdés. Egy 12 rétegű skaláris hálóban minden réteg σ(z)\sigma(z) szigmoidot használ, súlya wℓ=1w_\ell=1. Körülbelül mekkora lehet a bemenetre vonatkozó gradiens abszolút értéke? A választ a helyi deriváltak felső korlátja adja, amelyet a 36.4 szakaszban pontosan levezetünk; jó becslés a (1/4)12≈5.96⋅10−8(1/4)^{12}\approx 5.96\cdot 10^{-8}.

9.4.2 Aktiváció mint elemenkénti függvény és lokális deriváltja

Legyen ϕ:ℝ→ℝ\phi:\mathbb R\to\mathbb R egy aktiváció. Egy A∈ℝN×mA\in\mathbb R^{N\times m} preaktivációs mátrixon az aktivációs réteg elemenként hat:

Φ(A)ij=ϕ(Aij),H=Φ(A)∈ℝN×m. \Phi(A)_{ij}=\phi(A_{ij}),\qquad H=\Phi(A)\in\mathbb R^{N\times m}.

Ha ϕ\phi differenciálható az AijA_{ij} pontban, akkor HijH_{ij}-re csak AijA_{ij} hat, ezért a parciális derivált

∂Hij∂Aij=ϕ′(Aij), \frac{\partial H_{ij}}{\partial A_{ij}}=\phi'(A_{ij}),

minden más parciális derivált nulla. A skaláris veszteségre visszavezetett lokális VJP tehát

∂L∂Aij=ϕ′(Aij)∂L∂Hij, \frac{\partial L}{\partial A_{ij}} = \phi'(A_{ij})\,\frac{\partial L}{\partial H_{ij}},

ahol ∂L/∂A\partial L/\partial A alakja megegyezik AA alakjával. Ez a 36.2.1 képlet az egész fejezet központi lokális szabálya; a teljes háló gradiense ilyen lokális szabályok kompozíciója lesz a 10.1. Számítási gráf és lokális derivált alfejezetben.

Három gyakori aktiváció és a definiált pontokon vett deriváltja:

Aktiváció Képlet Lokális derivált, ahol létezik
szigmoid σ(z)=11+e−z\sigma(z)=\frac{1}{1+e^{-z}} σ′(z)=σ(z)(1−σ(z))\sigma'(z)=\sigma(z)(1-\sigma(z))
tanh tanh(z)=ez−e−zez+e−z\tanh(z)=\frac{e^{z}-e^{-z}}{e^{z}+e^{-z}} tanh′(z)=1−tanh(z)2\tanh'(z)=1-\tanh(z)^2
ReLU ReLU(z)=max(0,z)\operatorname{ReLU}(z)=\max(0,z) 00 ha z<0z<0, 11 ha z>0z>0

A szigmoid deriváltja egyetlen lépésben ellenőrizhető:

ddz11+e−z=e−z(1+e−z)2=σ(z)e−z1+e−z=σ(z)(1−σ(z)), \frac{d}{dz}\frac{1}{1+e^{-z}} = \frac{e^{-z}}{(1+e^{-z})^2} = \sigma(z)\frac{e^{-z}}{1+e^{-z}} = \sigma(z)(1-\sigma(z)),

ahol az utolsó egyenlőségnél 1−σ(z)=e−z/(1+e−z)1-\sigma(z)=e^{-z}/(1+e^{-z}).

9.4.3 Telítődés: a lokális derivált mérete

Definíció. Azt mondjuk, hogy egy differenciálható ϕ\phi aktiváció a zz pont közelében telítődik, ha |ϕ′(z)||\phi'(z)| nagyon kicsi. A szigmoid esetében ez minden zz-re korlátozott, sőt:

Állítás. Minden z∈ℝz\in\mathbb R esetén 0<σ′(z)≤1/40<\sigma'(z)\le 1/4, és |z|→∞|z|\to\infty mellett σ′(z)→0\sigma'(z)\to 0.

Bizonyítás. Legyen t=σ(z)∈(0,1)t=\sigma(z)\in(0,1). Ekkor σ′(z)=t(1−t)\sigma'(z)=t(1-t). A t↦t(1−t)t\mapsto t(1-t) parabola maximuma 1/41/4, amelyet t=1/2t=1/2 esetén vesz fel. A határérték z→∞z\to\infty esetén σ(z)→1\sigma(z)\to 1, tehát σ′(z)=σ(z)(1−σ(z))→0\sigma'(z)=\sigma(z)(1-\sigma(z))\to 0; z→−∞z\to-\infty esetén analóg módon σ′(z)→0\sigma'(z)\to 0. ▫\square

A tanh esetében tanh′(z)=1−tanh(z)2∈(0,1]\tanh'(z)=1-\tanh(z)^2\in(0,1], és |z|→∞|z|\to\infty esetén ugyancsak nullához tart. A ReLU ezzel szemben a pozitív oldalon konstans 11 deriváltat ad, tehát a pozitív tartományban nem telítődik; a negatív oldalon a derivált nem kicsi, hanem pontosan nulla.

A telítődés önmagában még lokális jelenség. Ahhoz, hogy egy mély háló bemeneti gradiensére gyakorolt hatását lássuk, láncszabályra és a lokális deriváltak szorzatára van szükség.

9.4.4 Szorzatos láncszabály és eltűnő gradiens

Tekintsük a skaláris, bias nélküli, LL rétegű

h0=x,aℓ=wℓhℓ−1,hℓ=ϕ(aℓ),fL(x)=hL h_0=x,\qquad a_\ell=w_\ell h_{\ell-1},\qquad h_\ell=\phi(a_\ell),\qquad f_L(x)=h_L

rekurziót, ahol wℓ∈ℝw_\ell\in\mathbb R és ϕ\phi differenciálható minden fellépő aℓa_\ell pontban.

Lemma 36.4.1 (szorzatos gradiens). A fenti rekurzióra

$$ \frac{d f_L}{dx} = \prod_{\ell=1}^{L} \Bigl(w_\ell\,\phi'(a_\ell)\Bigr). $$

Bizonyítás. L=1L=1-re a láncszabály közvetlenül df1dx=w1ϕ′(a1)\frac{d f_1}{dx}=w_1\phi'(a_1). Tegyük fel, hogy az állítás L−1L-1-re igaz. Ekkor

$$ \frac{d f_L}{dx} = \frac{d}{dh_{L-1}}\phi(w_L h_{L-1}) \cdot \frac{d h_{L-1}}{dx} = w_L\phi'(a_L) \cdot \prod_{\ell=1}^{L-1} \Bigl(w_\ell\phi'(a_\ell)\Bigr). $$

A szorzat tehát LL-re is teljesül; az indukció lezárja a bizonyítást. ▫\square

A lemma közvetlen következménye az eltűnő gradiens egy egyszerű alakja. Ha minden ℓ\ell-re |wℓϕ′(aℓ)|≤q<1|w_\ell\phi'(a_\ell)|\le q<1, akkor

|dfLdx|≤qL, \left|\frac{d f_L}{dx}\right| \le q^L,

és qLq^L exponenciálisan nullához tart. A szigmoidra a 36.3 szakasz állítása miatt |σ′(aℓ)|≤1/4|\sigma'(a_\ell)|\le 1/4, tehát |wℓ|≤1|w_\ell|\le 1 esetén q=1/4q=1/4 választható. Például L=12L=12 esetén

|df12dx|≤(14)12=5.9605⋅10−8. \left|\frac{d f_{12}}{dx}\right| \le \left(\frac14\right)^{12} = 5.9605\cdot 10^{-8}.

Ez a felső korlát: a tényleges gradiens ennél csak kisebb lehet. A korlát nem bizonyítja, hogy a tanítás szükségképpen sikertelen, csupán azt mutatja, hogy a nyers SGD-lépés irányvektorának egyes komponensei tetszőlegesen kicsik lehetnek.

Érdemes megkülönböztetni a jelenség két okát. A szigmoidos példában a lokális derivált maximuma 1/41/4, tehát a szorzat akkor is lecseng, ha minden súly egységnyi. A tanh lánc az x=0x=0, wℓ=0.8w_\ell=0.8 választással ezzel szemben nem telített pontokon halad át, mert tanh′(0)=1\tanh'(0)=1, és a gradiens mégis (0.8)12≈0.0687(0.8)^{12}\approx 0.0687: itt a kis súlyok szorzata okozza a lecsengést. Az eltűnő gradiens tehát termékjelenség, nem feltétlenül telítődési jelenség.

9.4.5 A ReLU töréspontja és a szubgradiens-konvenció

A ReLU nullpontja külön kezelést igényel. A z=0z=0 pontban a bal oldali derivált

limh→0−ReLU(h)−ReLU(0)h=limh→0−0h=0, \lim_{h\to 0^-}\frac{\operatorname{ReLU}(h)-\operatorname{ReLU}(0)}{h} = \lim_{h\to 0^-}\frac{0}{h} = 0,

míg a jobb oldali derivált

limh→0+h−0h=1. \lim_{h\to 0^+}\frac{h-0}{h} = 1.

A két egyoldali derivált nem egyenlő, ezért a klasszikus értelemben vett ReLU′(0)\operatorname{ReLU}'(0) nem létezik.

A konvex függvények elméletében a 00 pontbeli szubdifferenciál azokból a gg értékekből áll, amelyekre minden zz-re

ReLU(z)≥ReLU(0)+g(z−0)=gz. \operatorname{ReLU}(z)\ge \operatorname{ReLU}(0)+g(z-0)=gz.

z>0z>0 esetén ez z≥gzz\ge gz, azaz g≤1g\le 1; z<0z<0 esetén 0≥gz0\ge gz, azaz g≥0g\ge 0. A szubdifferenciál tehát a [0,1][0,1] intervallum. A PyTorch relu backward szabálya a z=0z=0 pontban a 00 értéket választja. Ez a szubdifferenciál egy eleme, tehát szubgradiens-konvenció, de nem klasszikus derivált. A könyvtári választás más könyvtárban lehet 0.50.5 vagy 11 is.

Dead ReLU. Ha egy neuron preaktivációja minden tanítópéldára nempozitív, akkor kimenete mindig 00, lokális gradiensértéke a fenti konvenció szerint szintén 00, ezért a bemenő súlyokra és a biasra eső gradiens minden tanítópéldában nulla lesz. Az ilyen neuron „halott”: a standard SGD alatt a bejövő paraméterei nem változnak, így a hálózat reprezentációs kapacitásából ez a neuron kiesik. Ez heurisztikus megfigyelés, nem tétel: súlycsökkentéssel vagy az adateloszlás megváltozásával a neuron elvileg újra aktiválódhat, de a tiszta gradiensalapú tanításban erre nincs garancia.

Kis ellenőrző példa: h=ReLU(x−5)h=\operatorname{ReLU}(x-5) a x∈{1,2,3}x\in\{1,2,3\} bemeneteken. A preaktiváció mindig −4,−3,−2-4,-3,-2, tehát h=0h=0 és a lokális gradiens minden mintára 00. Ha a tanítóhalmaz csak ezt a három pontot tartalmazza, a bemenő súly és a bias gradiense a veszteség láncszabálya szerint nulla.

9.4.6 Labor: aktivációrajz és gradiens két mélységnél

A labor célja: ábrázoljuk az aktivációkat és deriváltjaikat, majd mérjük meg kézi láncszabállyal ugyanannak a skaláris hálónak a bemeneti gradiensét L=4L=4 és L=12L=12 mélységben. A kód NumPy-t használ, CPU-n fut, és determinisztikus.

# lab/n036/activation_gradients.py
import numpy as np
import matplotlib
matplotlib.use("Agg")
import matplotlib.pyplot as plt

# A labor determinisztikus; a seed a későbbi véletlen kiegészítések felületét rögzíti.
rng = np.random.default_rng(20261020)

def sigmoid(z):
    return np.float32(1.0) / (np.float32(1.0) + np.exp(-z))

def relu(z):
    return np.maximum(np.float32(0.0), z)

def dsigmoid(z):
    s = sigmoid(z)
    return s * (np.float32(1.0) - s)

def dtanh(z):
    t = np.tanh(z)
    return np.float32(1.0) - t * t

def scalar_mlp(x, depth, w, phi, dphi):
    """Skaláris, bias nélküli MLP. Visszaadja a kimenetet és a dx gradienst."""
    h = np.float32(x)
    local_derivatives = []
    for _ in range(depth):
        a = np.float32(w) * h
        local_derivatives.append(np.float32(w) * np.float32(dphi(a)))
        h = phi(a)
    grad = np.prod(local_derivatives, dtype=np.float32)
    return np.float32(h), np.float32(grad)

def main():
    x = np.float32(0.0)   # tanh-nál nem telített pont
    w = np.float32(0.8)
    for depth in (4, 12):
        y, g = scalar_mlp(x, depth, w, np.tanh, dtanh)
        print(f"depth={depth:2d}  output={y:.6f}  input_grad={g:.6f}")

    z = np.linspace(-5, 5, 501, dtype=np.float32)
    plt.figure(figsize=(8, 4))
    plt.plot(z, sigmoid(z), label="sigmoid")
    plt.plot(z, dsigmoid(z), label="sigmoid derivált")
    plt.plot(z, np.tanh(z), label="tanh")
    plt.plot(z, dtanh(z), label="tanh derivált")
    plt.plot(z, relu(z), label="ReLU")
    plt.grid(True)
    plt.legend()
    plt.title("Aktivációk és lokális deriváltak")
    plt.savefig("lab/n036/activations.png", dpi=150)
    print("mentve: lab/n036/activations.png")

if __name__ == "__main__":
    main()

Futtatási parancs a könyv munkakönyvtárából:

python lab/n036/activation_gradients.py

Várható kimenet és értelmezés. Mivel x=0x=0 esetén tanh(0)=0\tanh(0)=0, minden réteg preaktivációja nulla, így minden tanh′(aℓ)=1\tanh'(a_\ell)=1; a gradiens pontosan a súlyok szorzata. A kód által kiírt értékek így kézzel ismert kontrollt adnak:

depth= 4  output=0.000000  input_grad=0.409600
depth=12  output=0.000000  input_grad=0.068719

A fenti két sor a képletből számított várható érték, mert 0.84=0.40960.8^4=0.4096 és 0.812=0.0687194767360.8^{12}=0.068719476736; ezt a kézirat írásakor nem futtattuk, ezért a későbbi futtatás során a float32 kerekítés utolsó jegyeken eltérhet. Az értelmezés nem az, hogy a hálózat „elromlott”, hanem az, hogy az inputgradiens egy qLq^L alakú felső korláttal csökken; q=0.8q=0.8-nál tizenkét réteg után a bemeneti réteg súlyfrissítése jóval kisebb tényezővel skálázódik, mint négy rétegnél.

A szigmoidot és deriváltját egyszerű diagramon is érdemes látni:

Szigmoid deriváltja - Képletből számított szemléltetés, nem mérés.

A teljes activations.png ábrán a ReLU törése is látható: a derivált 00-ról 11-re ugrik a nullpontnál, ahol klasszikus derivált nincs.

9.4.7 Tipikus tévedés: a töréspontbeli konvenció nem derivált

A következő visszaterjesztési kód gyakori:

def relu_backward(a, grad_out):
    return (a > 0).astype(np.float32) * grad_out

A kommentben gyakran „ReLU-derivált” szerepel. Ez hibás elnevezés: a kód a 00 pontban a PyTorch-hoz hasonlóan 00-t ad, miközben a ReLU-nak ott nincs deriváltja. A különbség mérhető: a középső differencia

ReLU(h)−ReLU(−h)2h=h−02h=0.5 \frac{\operatorname{ReLU}(h)-\operatorname{ReLU}(-h)}{2h} = \frac{h-0}{2h} = 0.5

minden h>0h>0-ra, tehát a véges differencia 0.50.5-öt ad a 00 pontban, a fenti kód pedig 00-t. Ez nem a kód numerikus hibája, hanem annak következménye, hogy a véges differencia nemdifferenciálható pontban nem definiál semmit. A 10.3. Gradiensellenőrzés és numerikus hibamérce gradiensellenőrzési protokollja ezért a vizsgálati pontot a törésponttól távol veszi fel, vagy a vizsgált konvenciót előre rögzíti.

9.4.8 Önellenőrzés és visszahívás

Ellenőrizze, hogy tudja-e: (1) igazolni a σ′≤1/4\sigma'\le 1/4 korlátot; (2) levezetni a dfL/dx=∏ℓwℓϕ′(aℓ)d f_L/dx=\prod_\ell w_\ell\phi'(a_\ell) képletet; (3) megmondani, miért nem létezik a klasszikus ReLU-derivált nullában, és mi a szubdifferenciál.

Visszahívás a 8.4. II. ellenőrző pont: korrekt tanulási állítás alfejezetből: a gradiens az empirikus kockázat plusz regularizáló cél szerinti frissítési irány része; a gradiens kicsinysége a nyers lépés skáláját csökkenti, de Adam-szerű normalizáló optimizálók ezt részben ellensúlyozhatják. Ugyanakkor az eltűnő gradiens itteni levezetése semmit nem mond az általánosításról, és a kis gradiensből nem következik, hogy a tesztkockázat kicsi vagy nagy lesz: ez pontosan a 8.4. II. ellenőrző pont: korrekt tanulási állítás tanítási állítások határa, amelyet itt nem lépünk át.

9.4.9 Feladatok

F1 (fogalmi, nehézség 1). Definiálja egy mondatban a telítődést és a dead ReLU jelenséget, majd adjon mindkettőre egy-egy konkrét egyváltozós számszerű esetet. Elvárt eredmény: két definíció, egy-egy kiszámolt lokális derivált vagy gradiensérték, és egy mondat arról, miben más a kettő.

F2 (levezetési, nehézség 2). Vezesse le a 36.4 szakasz rekurziójából a gradiens szorzatképletét L=3L=3-ra, bias nélkül, tetszőleges differenciálható ϕ\phi-vel. Ezután számítsa ki x=0x=0, ϕ=tanh\phi=\tanh, w1=0.7w_1=0.7, w2=0.9w_2=0.9, w3=1.2w_3=1.2 esetén a pontos gradiensértéket. Elvárt eredmény: teljes láncszabály-lépések, a fellépő aℓa_\ell értékek és a 0.7560.756 numerikus eredmény a kerekítés indoklásával.

F3 (implementációs, nehézség 2). Készítsen egy lab/n036/feladat_f3.py programot, amely egy háromrétegű, tanh aktivációjú skaláris MLP gradiensét kézi szorzatképlettel és középső differenciával is kiszámítja. Input: x=1.0x=1.0; a három súlyt np.random.default_rng(20261020) generálja float64 pontossággal a [0.5,1.5][0.5,1.5] intervallumból; a differencialépés h=10−6h=10^{-6}. Elvárt átadandó eredmény: a teljes program, a kiírt analitikus és numerikus gradiens, valamint egy assert ellenőrzés, hogy az abszolút eltérés 10−510^{-5} alatt van. Magyarázza meg a float64 választását.

F4 (hibakeresési, nehézség 2). Egy társa a következő kódot mutatja:

def relu_backward(a, grad_out):
    # ReLU deriváltja
    return (a > 0) * grad_out

A függvényt az a=0a=0, grad_out=1.0 pontban teszteli, és arra panaszkodik, hogy a középső differencia szerint 0.50.5-nek kellene lennie, a kód viszont 00-t ad. Lokalizálja a hibát, nevezze meg a tényleges okot, és adjon olyan javítást, amely nem nevezi deriváltnak a 00 pontbeli visszaterjesztési értéket. Elvárt átadandó eredmény: ok, következmény, javított függvény dokumentációval és két olyan tesztpont, ahol a klasszikus derivált létezik, valamint a numerikus visszaellenőrzés.

F5 (kísérleti/transzfer, nehézség 3). Tervezzen GlyphLab-protokollt annak eldöntésére, hogy azonos szélesség és mélység mellett a tanh vagy a ReLU MLP ér el kisebb validációs loss-t a három orientáció osztályozásában. A terv kövesse a 8.4. II. ellenőrző pont: korrekt tanulási állítás és 5.4. Függő képek, seedek és resampling tanulságait: a képeket lapítsa 24⋅24=57624\cdot 24=576 hosszú vektorrá, a scene_id csoportosítást ne sértse meg, a tesztet ne használja modellválasztásra, és legalább öt tanítási seeddel mérje a seedek közötti szórást. Adjon baseline-t, optimalizálót, epochszámot, batchméretet és kiértékelési metrikát, valamint két módszertani korlátot. Elvárt átadandó eredmény: egy bekezdésnyi protokoll-leírás a fenti elemekkel és a korlátokkal.

9.4.10 Megoldások és indoklás

F1. A telítődés lokális tulajdonság: |ϕ′(z)||\phi'(z)| kicsi. Például σ′(0)=0.25\sigma'(0)=0.25, de σ′(5)=σ(5)(1−σ(5))≈0.00665\sigma'(5)=\sigma(5)(1-\sigma(5))\approx 0.00665, tehát a függvény az 55 környezetében telített. A dead ReLU ezzel szemben adatfüggő, globálisabb jelenség: ha minden tanítópéldára a≤0a\le 0, a neuron kimenete és lokális gradiense is nulla. Például h=ReLU(x−5)h=\operatorname{ReLU}(x-5) a x∈{1,2,3}x\in\{1,2,3\} tanítóhalmazon mindig 00 kimenetet ad, így a bemenő súly gradiense minden mintára 00. A különbség: a telített szigmoid deriváltja kicsi, de nem nulla, és más bemenetre azonnal „felébredhet”; a holt ReLU bejövő paraméterei a rögzített tanítóhalmazon nulla gradiensük miatt nem frissülnek.

F2. A láncszabályt hátulról felírva:

df3dx=w3ϕ′(a3)⋅w2ϕ′(a2)⋅w1ϕ′(a1),a1=w1x,a2=w2h1,a3=w3h2. \frac{d f_3}{dx} = w_3\phi'(a_3) \cdot w_2\phi'(a_2) \cdot w_1\phi'(a_1), \qquad a_1=w_1 x,\; a_2=w_2 h_1,\; a_3=w_3 h_2.

Az x=0x=0 kezdőpont miatt minden preaktiváció nulla, hiszen a bias nincs jelen, és tanh(0)=0\tanh(0)=0. Mivel tanh′(0)=1−tanh(0)2=1\tanh'(0)=1-\tanh(0)^2=1, a szorzat

df3dx=0.7⋅0.9⋅1.2=0.756. \frac{d f_3}{dx} = 0.7\cdot 0.9\cdot 1.2 = 0.756.

Az alakellenőrzés: minden tényező skalár, ezért az eredmény is skalár. A tanh′(0)=1\tanh'(0)=1 érték pontos, a 0.7560.756 véges tizedestörtként egzakt.

F3. Egy teljes megoldás:

# lab/n036/feladat_f3.py
import numpy as np

def tanh(x):
    return np.tanh(x)

def dtanh(x):
    return 1.0 - np.tanh(x) ** 2

def forward(x, ws):
    acts = []
    h = x
    for w in ws:
        a = np.float64(w) * np.float64(h)
        acts.append(a)
        h = tanh(a)
    return np.float64(h), acts

def analytic_grad(ws, acts):
    g = np.float64(1.0)
    for w, a in reversed(list(zip(ws, acts))):
        g = g * np.float64(w) * dtanh(a)
    return g

rng = np.random.default_rng(20261020)
ws = [np.float64(rng.uniform(0.5, 1.5)) for _ in range(3)]
x0 = np.float64(1.0)

y, acts = forward(x0, ws)
g_an = analytic_grad(ws, acts)

h = np.float64(1e-6)
yp, _ = forward(np.float64(x0 + h), ws)
ym, _ = forward(np.float64(x0 - h), ws)
g_num = (yp - ym) / (np.float64(2.0) * h)

print("sulyok:", ws)
print("analitikus:", g_an)
print("numerikus:  ", g_num)
print("abszolut elteres:", abs(g_an - g_num))
assert abs(g_an - g_num) < 1e-5

A float64 azért szükséges, mert a középső differencia két közeli kimenet kivonását végzi; float32-ben a kivonásnál a kerekítési zaj nagyobb lehet, mint a h2h^2-es módszerhiba. A tanh sima az x0=1x_0=1 környezetében, ezért a klasszikus derivált létezik, és a véges differencia jogos ellenőrzés. Alakellenőrzés: a gradiens skalár, mert a bemenet, a súlyok és a kimenet is skalár.

F4. A hiba típusa: fogalmi tévedés, nem numerikus implementációs hiba. A (a > 0) kifejezés a nullpontban False, ezért 00-t ad, de a ReLU-nak a nullpontban nincs klasszikus deriváltja, így a középső differencia 0.50.5 értéke sem „helyes derivált”. A konvenciót dokumentálni kell, a tesztet pedig olyan pontokra vinni, ahol a derivált létezik. Javított változat:

def relu_backward(a, grad_out):
    # Visszaterjesztési konvenció: a 0-beli érték 0, nem klasszikus derivált.
    # A klasszikus derivált csak a != 0 pontokban létezik.
    return (a > 0).astype(np.float32) * grad_out

Visszaellenőrzés: a=1a=1-nél a kód 1⋅g1\cdot g-t, a=−1a=-1-nél 00-t ad, mindkettő megegyezik a klasszikus deriválttal, mert ott a ReLU sima. A 00 pontot ellenőrzésként ki kell zárni vagy külön konvenciótesztként kell jelölni.

F5. Egy lehetséges protokoll. Kérdés: tanh vagy ReLU aktivációjú, azonos kapacitású MLP ér el kisebb validációs loss-t a GlyphLab orientációfeladatán? Baseline: lineáris logisztikus regresszió az ellapított 576576 dimenziós bemeneten, így látható, hogy a nemlinearitás egyáltalán hoz-e javulást. Adat: data/images.npy, data/labels.npy, a megadott train/val/test scene-split; a tesztet a modell- és hiperparaméter-választás lezárásáig nem értékeljük. Modellek: két rejtett réteg, szélesség 6464, tanh illetve ReLU, kimeneti logits, CrossEntropyLoss. Optimalizáló: Adam, learning rate 10−210^{-2}, batchméret 3232, 2525 epoch, legjobb checkpoint a validációs loss szerint. Ismétlés: öt tanítási seed; minden seednél ugyanaz a tanítóhalmaz, csak az inicializálás és a batchsorrend változik. Kiértékelés: validációs accuracy átlaga és szórása a seedek között, a korlátozott tesztet csak a kiválasztott konfiguráción futtatjuk egyszer. Korlátok: a GlyphLab nem természeteskép-benchmark, ezért a sorrend nem vihető át általános látási feladatra; az öt seed az algoritmikus bizonytalanságot méri, nem az adatbázis más jeleneteire vonatkozó bizonytalanságot, amelyhez az 5.4. Függő képek, seedek és resampling szerint scene-alapú bootstrap kellene. A 8.4. II. ellenőrző pont: korrekt tanulási állítás tanulsága szerint az eredményt nem szabad „bizonyítottan jobb aktivációként” közölni, csak ezen a rögzített adaton és spliten mért empirikus különbségként.

9.4.11 Rövid összefoglaló

Az aktivációs réteg elemenként hat, lokális VJP-je ϕ′(Aij)\phi'(A_{ij}) szorzó. A szigmoid deriváltjának maximuma 1/41/4, és nagy abszolút preaktivációnál nullához tart, ez a telítődés. A mély skaláris háló bemeneti gradiense a lokális deriváltak szorzata; ha minden tényező abszolút értékét q<1q<1 korlátozza, a gradiens qLq^L ütemben eltűnhet. A ReLU nullpontjában nincs klasszikus derivált; a [0,1][0,1] szubdifferenciálból a könyvtárak csak konvenció szerint választanak értéket. A dead ReLU adatfüggő jelenség, amely a bejövő súlyok gradiensét nullázza. A 36.6 labor a tanh láncon 0.840.8^4 és 0.8120.8^{12} mért gradienst ad, és az aktivációkat is ábrázolja.

9.4.12 Következő alkalmazás és források

A következő, 10.1. Számítási gráf és lokális derivált egység a számítási gráfot és a lokális deriváltak összeillesztését formalizálja; a jelen szorzatos képlet annak speciális, lineáris lánca. A ReLU töréspontbeli konvenció a 10.3. Gradiensellenőrzés és numerikus hibamérce gradiensellenőrzési protokolljában tér vissza, ahol a véges differencia értéke a nullpontban tudatosan kizárt.

Források. A szakasz levezetései saját, elemi levezetések; a Cybenko-tétel itt nem szerepel. Háttérjelöléshez:

A jelen egységben oldalszámot, táblázatot vagy idézetet e forrásokból nem közlünk.