Gyakori tévhit, hogy a neurális hálózatok működése valami megfoghatatlan, szinte misztikus „fekete doboz” mágia. A Red Teaming során azonban nem engedhetjük meg magunknak ezt a homályt. Ha meg akarjuk törni a rendszert, ismernünk kell a gépezetet.
A valóság az, hogy a neurális hálózatok lelke – a legkomplexebb architektúrák esetében is – meglepően egyszerű, ismétlődő matematikai műveletek sorozata. Ebben a részben lehúzzuk a leplet ezekről a számításokról, hogy a „mágia” helyett a tiszta, érthető matematikát lásd.
Az egyetlen neuron: a rendszer atomja
Minden egyetlen neuronnal kezdődik. Tekints rá úgy, mint egy egyszerű döntési egységre. Két alapvető számítást végez:
- Súlyozott összegzés: Fogja az összes bemeneti értékét (
x), megszorozza őket a hozzájuk tartozó súlyokkal (w), majd hozzáad egy torzítási (bias) értéket (b). Ez lényegében egy lineáris transzformáció. - Aktivációs függvény alkalmazása: A súlyozott összeg eredményét (ezt gyakran
z-nek vagy logitnak nevezik) átküldi egy nem-lineáris aktivációs függvényen (σvagyg), ami a neuron végső kimenetét (a, mint aktiváció) adja.
Formulával kifejezve, egyetlen neuron számítása a következő:
A pont (·) a vektorok skaláris szorzatát jelöli. A bias (b) lehetővé teszi a modell számára, hogy eltolja az aktivációs függvényt, növelve a rugalmasságát. A nem-linearitás (σ) pedig kritikus, enélkül az egész hálózat csupán egyetlen nagy lineáris regresszióvá egyszerűsödne, ami képtelen lenne komplex mintázatok megtanulására.
Rétegek és a Forward Propagation
Egy neurális hálózat rétege nem más, mint sok ilyen neuron párhuzamosan. A számításokat itt már sokkal hatékonyabb mátrixműveletekkel végezni. Egy teljes réteg (l) előrecsatolási (forward propagation) lépése a következőképpen néz ki:
- Bemenet: Az előző réteg aktivációinak vektora,
A[l-1]. - Súlyok: Egy
W[l]mátrix, ahol minden sor egy neuron súlyvektorának felel meg. - Biasok: Egy
B[l]vektor, ahol minden elem a réteg egy-egy neuronjának bias értéke.
A számítási képlet a réteg szintjén:
Itt g[l] a réteg aktivációs függvénye, és a műveletet elemenként kell elvégezni a Z[l] vektor minden elemére. A teljes hálózaton való végighaladás (forward propagation) csupán ennek a két lépésnek az ismétlése rétegről rétegre, az elsőtől az utolsóig.
A tanulás matematikája: Visszaterjesztés (Backpropagation)
A tanulás a súlyok és biasok finomhangolását jelenti. Ehhez tudnunk kell, hogy egy adott súly vagy bias megváltoztatása milyen mértékben befolyásolja a hálózat végső hibáját (amit egy költségfüggvény, L, mér). Ezt a befolyást a parciális deriváltak (gradiensek) mérik: ∂L / ∂W[l] és ∂L / ∂B[l].
A visszaterjesztés (backpropagation) egy okos algoritmus ezen gradiensek hatékony kiszámítására. Lényegében a láncszabály (calculus) rekurzív alkalmazása, visszafelé haladva a hálózaton:
- Kiszámítja a hibát az utolsó rétegen.
- Visszaterjeszti ezt a hibajelet az eggyel korábbi rétegre, hogy kiszámítsa annak a rétegnek a „felelősségét” a teljes hibáért.
- Ezt ismétli, amíg el nem éri a bemeneti réteget.
Minden rétegben a kapott hibajel alapján kiszámíthatók a gradiensek az adott réteg súlyaira és biasaira. Ezeket a gradienseket használják az optimalizációs algoritmusok (pl. SGD, Adam) a paraméterek frissítésére.
Kulcsformulák (koncepcionális)
A backpropagation matematikai levezetése mély, de a kulcsgondolatok megragadhatók néhány formulával. A δ[l] jelöli a hibát a l-edik rétegben:
- Hiba az utolsó (L) rétegen:
δ[L] = ∇a L ⊙ g'[L](Z[L])
Ez a költségfüggvény gradiense az aktivációk szerint, elemenként szorozva az aktivációs függvény deriváltjával. - Hiba terjesztése egy belső (l) rétegre:
δ[l] = ((W[l+1])T δ[l+1]) ⊙ g'[l](Z[l])
A következő réteg hibáját „visszavetítjük” a súlyokon keresztül, majd ezt is elemenként szorozzuk az aktuális réteg aktivációs függvényének deriváltjával. - Gradiensek számítása:
∂L / ∂W[l] = δ[l] (A[l-1])T
∂L / ∂B[l] = δ[l]
Itt ⊙ az elemenkénti szorzást (Hadamard-szorzat), T pedig a transzponálást jelöli.
Számítási folyamat összefoglaló pszeudokóddal
Egy egyszerű, több rétegű hálózat teljes számítási ciklusa (egyetlen forward és backward pass) a következőképpen néz ki:
# Pszeudokód egy neurális hálózat számítási ciklusára
# Paraméterek:
# X: bemeneti adatok mátrixa
# Y: valós címkék
# parameters: egy szótár, ami a W1, b1, W2, b2, ... súlyokat és biasokat tárolja
# 1. FORWARD PROPAGATION
# ---------------------
# A[0] = X
# FOR l = 1 TO L: # L a rétegek száma
# Z[l] = W[l] * A[l-1] + b[l]
# A[l] = activation_function(Z[l])
#
# # Az utolsó réteg kimenete a predikció
# Y_pred = A[L]
# 2. KÖLTSÉG KISZÁMÍTÁSA
# --------------------
# cost = compute_loss(Y_pred, Y)
# 3. BACKWARD PROPAGATION
# -----------------------
# # Kezdés az utolsó rétegnél
# dAL = derivative_of_loss(Y_pred, Y)
# dZ[L] = dAL * activation_derivative(Z[L])
# dW[L] = (1/m) * dZ[L] dot A[L-1].T
# db[L] = (1/m) * sum(dZ[L], axis=1)
#
# # Visszaterjesztés a többi rétegen
# FOR l = L-1 DOWNTO 1:
# dZ[l] = (W[l+1].T dot dZ[l+1]) * activation_derivative(Z[l])
# dW[l] = (1/m) * dZ[l] dot A[l-1].T
# db[l] = (1/m) * sum(dZ[l], axis=1)
#
# # A grads szótár most tartalmazza az összes ∂L/∂W és ∂L/∂b értéket
# 4. PARAMÉTER FRISSÍTÉS (Optimalizáló végzi)
# --------------------------------------
# FOR l = 1 TO L:
# parameters["W" + l] = parameters["W" + l] - learning_rate * dW[l]
# parameters["b" + l] = parameters["b" + l] - learning_rate * db[l]
Bár a modern keretrendszerek (PyTorch, TensorFlow) ezt a folyamatot automatizálják, a Red Teaming szakértő számára elengedhetetlen, hogy pontosan értse, mi történik a „motorháztető alatt”. Ez a tudás teszi lehetővé a célzott támadások, például a gradiensekre épülő adverzárius példák létrehozását vagy a modell belső állapotainak manipulálását.