4.2 Parciális derivált és gradiens

4.2.1 Cél, előismeret és induló kérdés

A 4.1. Függvény, határérték és derivált egyetlen valós paraméter esetén értelmezte a deriváltat: a függvény lokális lineáris közelítésének meredekségét. A neurális hálózat tanítása során azonban a veszteség egyszerre sok súlytól függ, ezért azt kérdezzük: ha egy dd dimenziós ww paramétervektort egyszerre több irányban is elmozdíthatunk, melyik irányban változik a leggyorsabban a veszteség, és hogyan foglalható össze a változás egyetlen vektorban? A fejezet a parciális deriváltat, a gradienst, az iránymenti deriváltat és a többváltozós differenciálhatóságot építi fel. Előismeret: határérték és egyváltozós derivált a 4.1. Függvény, határérték és derivált alfejezetből, valamint a mátrixszorzás és az oszlopvektor-konvenció a 3.2. Mátrixszorzás és affín réteg alfejezetből. Induló becslésként gondoljuk végig: ha f(w1,w2)=w12+4w22f(w_1,w_2)=w_1^2+4w_2^2, akkor a (2,1)(2,1) pontból a (−1,1)(-1,1) irányba tett kis lépés vajon növeli vagy csökkenti az értéket? A válaszhoz mindkét koordináta menti változást össze kell kapcsolnunk.

4.2.2 Parciális derivált

Legyen U⊆ℝdU\subseteq\mathbb R^d nyílt halmaz, f:U→ℝf:U\to\mathbb R, és x∈Ux\in U. Az ii-edik koordináta szerinti parciális derivált (partial derivative) az xx pontban az egyváltozós derivált mintájára definiálható:

∂f∂xi(x)=limh→0f(x+hei)−f(x)h, \frac{\partial f}{\partial x_i}(x) =\lim_{h\to 0}\frac{f(x+h e_i)-f(x)}{h},

ahol ei∈ℝde_i\in\mathbb R^d az ii-edik standard bázisvektor, h∈ℝ\{0}h\in\mathbb R\setminus\{0\} pedig olyan, hogy x+hei∈Ux+h e_i\in U. A parciális derivált tehát úgy vizsgálja a függvényt, hogy csak az ii-edik koordinátát mozgatjuk, a többit rögzítjük. A ∂f/∂xi(x)\partial f/\partial x_i(x), Dif(x)D_i f(x) és fxi(x)f_{x_i}(x) jelölések mind ugyanezt jelentik. Az eredmény skalár, mértékegysége a függvényérték és a koordináta mértékegységének hányadosa; a könyv későbbi fejezeteiben jellemzően „veszteségegység per súlyegység”.

1. példa. Legyen f:ℝ2→ℝf:\mathbb R^2\to\mathbb R, f(w1,w2)=w12+3w1w2+2w22f(w_1,w_2)=w_1^2+3w_1w_2+2w_2^2. Az első parciális derivált a w2w_2 rögzítése mellett a w1↦w12+3w1w2+2w22w_1\mapsto w_1^2+3w_1w_2+2w_2^2 egyváltozós függvény deriváltja:

∂f∂w1(w1,w2)=2w1+3w2, \frac{\partial f}{\partial w_1}(w_1,w_2)=2w_1+3w_2,

és hasonlóan

∂f∂w2(w1,w2)=3w1+4w2. \frac{\partial f}{\partial w_2}(w_1,w_2)=3w_1+4w_2.

A (1,−1)(1,-1) pontban a két parciális derivált ∂f/∂w1=−1\partial f/\partial w_1=-1 és ∂f/∂w2=−1\partial f/\partial w_2=-1. Az első azt mondja meg, hogy csak a w1w_1 koordinátát mozgatva a függvény lokálisan −1-1 meredekséggel változik; a második ugyanezt mondja a w2w_2 irányra.

A parciális deriváltakból képzett vektort gradiensnek (gradient) nevezzük:

∇f(x)=(∂f∂x1(x)⋮∂f∂xd(x))∈ℝd. \nabla f(x) =\begin{pmatrix} \frac{\partial f}{\partial x_1}(x)\\ \vdots\\ \frac{\partial f}{\partial x_d}(x) \end{pmatrix} \in\mathbb R^d.

A könyv oszlopvektor-konvenciót használ: a gradiens alakja megegyezik az input xx alakjával. Ha a függvény argumentuma mátrix vagy magasabb dimenziós tensor, a gradiens a parciális deriváltaknak ugyanolyan alakú, komponensenkénti rendezett gyűjteménye. A PyTorch-ban a .grad mező alakja ezért megegyezik annak a tensornak az alakjával, amelyre a skalár veszteséget deriváltuk [D05]. Az 1. példában ∇f(1,−1)=(−1,−1)⊤\nabla f(1,-1)=(-1,-1)^\top.

4.2.3 Iránymenti derivált és kapcsolata a gradienssel

A parciális deriváltak csak a koordinátatengelyek menti változást írják le. Általános irányhoz rögzítsünk egy v∈ℝdv\in\mathbb R^d, v≠0v\neq 0 vektort. A vv irányú iránymenti derivált (directional derivative) az

Dvf(x)=limh→0f(x+hv)−f(x)h D_v f(x)=\lim_{h\to 0}\frac{f(x+h v)-f(x)}{h}

határérték, ha létezik. Ez a t↦f(x+tv)t\mapsto f(x+t v) egyváltozós függvény deriváltja a t=0t=0 pontban. Ha ∥v∥=1\|v\|=1, az érték a vv irányú meredekség; ha vv nem egységvektor, a definíció arányosan nagyobb lépést vizsgál, ezért Dαvf(x)=αDvf(x)D_{\alpha v}f(x)=\alpha D_v f(x) minden α≠0\alpha\neq 0-ra.

A gradiens és az iránymenti derivált kapcsolatát a következő lemma adja.

Lemma (iránymenti derivált a gradiensből). Ha ff differenciálható az xx pontban, akkor minden v∈ℝdv\in\mathbb R^d vektorra

Dvf(x)=∇f(x)⊤v. D_v f(x)=\nabla f(x)^\top v.

Bizonyítás. A többváltozós differenciálhatóság definíciója szerint létezik olyan ∇f(x)∈ℝd\nabla f(x)\in\mathbb R^d vektor, amellyel

f(x+u)=f(x)+∇f(x)⊤u+r(u), f(x+u)=f(x)+\nabla f(x)^\top u+r(u),

és a maradéktag teljesíti a limu→0r(u)/∥u∥=0\lim_{u\to 0}r(u)/\|u\|=0 feltételt. Rögzítsünk egy v≠0v\neq 0 irányt, és helyettesítsünk u=hvu=h v-t:

f(x+hv)−f(x)h=∇f(x)⊤v+r(hv)h. \frac{f(x+h v)-f(x)}{h} =\nabla f(x)^\top v+\frac{r(h v)}{h}.

Mivel ∥hv∥=|h|∥v∥\|h v\|=|h|\,\|v\|,

limh→0|r(hv)||h|=limh→0|r(hv)|∥hv∥∥v∥=0, \lim_{h\to 0}\frac{|r(h v)|}{|h|} =\lim_{h\to 0}\frac{|r(h v)|}{\|h v\|}\,\|v\|=0,

tehát a differenciahányados határértéke ∇f(x)⊤v\nabla f(x)^\top v. A v=0v=0 esetre mindkét oldal nulla. ▫\square

A lemma közvetlen következménye a legmeredekebb változás iránya. Ha ∥v∥=1\|v\|=1, akkor a Cauchy–Schwarz-egyenlőtlenséggel

Dvf(x)=∇f(x)⊤v≤∥∇f(x)∥∥v∥=∥∇f(x)∥, D_v f(x)=\nabla f(x)^\top v\le \|\nabla f(x)\|\,\|v\|=\|\nabla f(x)\|,

és egyenlőség pontosan akkor áll, ha v=∇f(x)/∥∇f(x)∥v=\nabla f(x)/\|\nabla f(x)\| (pozitív gradiensű irány). A gradiens iránya tehát a legmeredekebb növekedés iránya, nagysága pedig az egységnyi hosszúságú lépésre jutó maximális növekedés. A negatív gradiens iránya a legmeredekebb csökkenésé; erre épül majd a gradienslépés a 6.1. Objektív, reguláris tag és gradienslépés alfejezetben.

4.2.4 Többváltozós differenciálhatóság

A parciális deriváltak puszta létezése nem elegendő ahhoz, hogy a fenti lineáris közelítés igaz legyen. A pontos definíció a következő. Az f:U→ℝf:U\to\mathbb R függvény differenciálható (differentiable) az x∈Ux\in U pontban, ha létezik olyan a∈ℝda\in\mathbb R^d vektor, amellyel

f(x+u)=f(x)+a⊤u+r(u),éslimu→0r(u)∥u∥=0. f(x+u)=f(x)+a^\top u+r(u), \quad\text{és}\quad \lim_{u\to 0}\frac{r(u)}{\|u\|}=0.

Ekkor az aa vektor éppen a gradiens: a=∇f(x)a=\nabla f(x). Szavakkal: a függvény jól közelíthető egy a⊤ua^\top u lineáris funkcionállal, és a hiba a ∥u∥\|u\|-nál gyorsabban tart nullához. A gradiens ennek a lineáris funkcionálnak a reprezentánsa a standard belső szorzatban.

A gyakorlatban hasznos elégséges feltétel a következő.

Tétel (folytonos parciális deriváltak). Ha az ff függvény minden parciális deriváltja létezik az xx egy környezetében, és azok folytonosak az xx pontban, akkor ff differenciálható xx-ben.

A tétel bizonyítása az egyváltozós középértéktétel koordinátánkénti alkalmazásával történik; a teljes levezetést itt nem ismételjük meg, mert a 4.1. Függvény, határérték és derivált nem építette fel a többváltozós középértéktételt. Az állítás standard anyag, lásd [B01] többváltozós differenciálszámítási fejezeteit (a forrásstátuszt a fejezet végi lista rögzíti). A fontos gyakorlati üzenet: ha a parciális deriváltakat zárt képletből, folytonos elemi műveletekkel kapjuk, a differenciálhatóság általában teljesül; a nem folytonos pontokban külön vizsgálat szükséges.

4.2.5 A kvadratikus veszteség gradiense

A neurális hálózatok tanításában gyakran előforduló kvadratikus veszteség a következő. Legyen X∈ℝN×dX\in\mathbb R^{N\times d} a batchelt bemenet (NN megfigyelés, dd jellemző), y∈ℝNy\in\mathbb R^N a célvektor, w∈ℝdw\in\mathbb R^d a paramétervektor. A közönséges legkisebb négyzetek felezett négyzetösszege:

f(w)=12∥Xw−y∥22=12∑i=1N((Xw)i−yi)2. f(w)=\frac12\|Xw-y\|_2^2 =\frac12\sum_{i=1}^{N}\Big((Xw)_i-y_i\Big)^2.

A 12\frac12 konstans a későbbi gradiens egyszerűsítésére szolgál; a minimum helyét nem befolyásolja. Számítsuk ki a jj-edik parciális deriváltat komponensenként. Az (Xw)i=∑k=1dXikwk(Xw)_i=\sum_{k=1}^{d}X_{ik}w_k lineáris kifejezés wjw_j szerinti deriváltja XijX_{ij}. A láncszabály és az összeg deriválási szabálya szerint

∂f∂wj(w)=∑i=1N((Xw)i−yi)Xij=(X⊤(Xw−y))j. \frac{\partial f}{\partial w_j}(w) =\sum_{i=1}^{N}\Big((Xw)_i-y_i\Big) X_{ij} =\Big(X^\top(Xw-y)\Big)_j.

Mivel ez minden j=1,…,dj=1,\ldots,d-re fennáll, a teljes gradiens:

∇f(w)=X⊤(Xw−y)∈ℝd. \nabla f(w)=X^\top(Xw-y)\in\mathbb R^d.

Ez a levezetés a könyv saját kidolgozása; a mátrixderivált-szabályok ugyanezt adják. Az alakellenőrzés kulcsa: X⊤∈ℝd×NX^\top\in\mathbb R^{d\times N}, (Xw−y)∈ℝN(Xw-y)\in\mathbb R^N, így a szorzat dd dimenziós, pontosan a ww alakja. A bias nélküli lineáris réteg veszteségének gradiense ezzel a képlettel számítható; a biasos affin esetben a konstans tag deriváltja a konstans bemenetre vonatkozó X⊤(Xw+b−y)X^\top(Xw+b-y) képletben kap szerepet, de ezt a 4.3. Jacobi-mátrix, láncszabály és VJP és 10.2. Affín réteg és aktiváció backward fejti ki.

4.2.6 Kontúrok és a gradiens merőlegessége

Egy c∈ℝc\in\mathbb R szinthez tartozó kontúrvonal vagy szintvonal (contour, level set) az

Cc={x∈U:f(x)=c} C_c=\{x\in U: f(x)=c\}

halmaz. Két paraméter esetén ez a felület szintvonala; magasabb dimenzióban szintfelületről beszélünk.

Lemma (gradiens merőleges a szintvonalra). Legyen ff differenciálható, és legyen γ:(a,b)→Cc\gamma:(a,b)\to C_c differenciálható görbe a szintvonalon, γ(t0)=x\gamma(t_0)=x. Ekkor

∇f(x)⊤γ′(t0)=0, \nabla f(x)^\top \gamma'(t_0)=0,

vagyis a gradiens merőleges a szintvonal xx pontbeli érintőjére.

Bizonyítás. Mivel γ(t)∈Cc\gamma(t)\in C_c minden tt-re, f(γ(t))=cf(\gamma(t))=c konstans. Deriváljuk mindkét oldalt tt szerint a t0t_0 pontban. A láncszabály és az iránymenti derivált lemma szerint

0=ddtf(γ(t))|t=t0=∇f(γ(t0))⊤γ′(t0). 0=\frac{d}{dt}f(\gamma(t))\bigg|_{t=t_0} =\nabla f(\gamma(t_0))^\top \gamma'(t_0).

Ez pontosan a merőlegességi állítás. ▫\square

A lemma indokolja, miért mutat a gradiens a szintvonalakra merőlegesen: ha egy szintvonalon mozogva a függvényérték nem változik, akkor a leggyorsabb változás irányának merőlegesnek kell lennie erre a mozgásra. A gradiens iránya ezen felül a növekvő függvényértékek felé mutat; nagysága heurisztikusan a szintvonalak sűrűségéhez köthető, de ez utóbbi nem pontos, általános tétel, csak szemlélet.

4.2.7 Eredeti kézi példa és ellenőrzés

Tekintsük a

f(w1,w2)=(w1−1)2+2(w2+1)2 f(w_1,w_2)=(w_1-1)^2+2(w_2+1)^2

kétparaméteres veszteséget. A parciális deriváltak:

∂f∂w1=2(w1−1),∂f∂w2=4(w2+1), \frac{\partial f}{\partial w_1}=2(w_1-1),\qquad \frac{\partial f}{\partial w_2}=4(w_2+1),

tehát a gradiens

∇f(w1,w2)=(2(w1−1)4(w2+1)). \nabla f(w_1,w_2)=\begin{pmatrix}2(w_1-1)\\4(w_2+1)\end{pmatrix}.

A w(0)=(2,−2)⊤w^{(0)}=(2,-2)^\top pontban:

f(w(0))=(2−1)2+2(−2+1)2=1+2=3,∇f(w(0))=(2−4). f(w^{(0)})=(2-1)^2+2(-2+1)^2=1+2=3, \qquad \nabla f(w^{(0)})=\begin{pmatrix}2\\-4\end{pmatrix}.

Ellenőrizzük először az iránymenti deriváltat a v=(1,0.25)⊤v=(1,0.25)^\top irányban. A lemmából Dvf(w(0))=∇f(w(0))⊤v=2⋅1+(−4)⋅0.25=1D_v f(w^{(0)})=\nabla f(w^{(0)})^\top v=2\cdot 1+(-4)\cdot 0.25=1. Numerikusan, h=10−5h=10^{-5} mellett a differenciahányados:

f(w(0)+hv)−f(w(0))h \frac{f(w^{(0)}+h v)-f(w^{(0)})}{h}

a számított közelítésben 1,00001{,}0000-hez közeli értéket ad; a részletes numerikus kontrollt a labor F3 feladata végzi el.

Végezzünk egy gradienslépést η=0,1\eta=0{,}1 lépésközzel a negatív gradiens irányában:

w(1)=w(0)−η∇f(w(0))=(2−2)−0,1(2−4)=(1,8−1,6). w^{(1)}=w^{(0)}-\eta\nabla f(w^{(0)}) =\begin{pmatrix}2\\-2\end{pmatrix}-0{,}1\begin{pmatrix}2\\-4\end{pmatrix} =\begin{pmatrix}1{,}8\\-1{,}6\end{pmatrix}.

Az új függvényérték:

f(w(1))=(1,8−1)2+2(−1,6+1)2=0,64+0,72=1,36, f(w^{(1)})=(1{,}8-1)^2+2(-1{,}6+1)^2 =0{,}64+0{,}72=1{,}36,

ami kisebb, mint a kezdeti 33. A lépés irányában a veszteség tehát csökkent. Hangsúlyozzuk: ez egy konkrét numerikus példa, nem általános konvergenciaállítás; a lépésköz megválasztásának feltételeit a 6.2. Konvexitás és sima optimalizálási határ tárgyalja.

4.2.8 Labor: gradienslépés kétparaméteres felületen

A labor a fenti ff függvényre rajzol szintvonalakat és egy gradienslépést, majd kézzel ellenőrzi a lépést. A kód NumPy-t és Matplotlibet használ; a függvény számításához float64 típust, a kiindulóponthoz w(0)=(2,−2)⊤w^{(0)}=(2,-2)^\top értéket rögzítünk.

# lab/n014_grad_demo.py
# Futtatas: python lab/n014_grad_demo.py
import numpy as np
import matplotlib.pyplot as plt

def f(w):
    w = np.asarray(w, dtype=np.float64)
    return (w[0] - 1.0) ** 2 + 2.0 * (w[1] + 1.0) ** 2

def grad_f(w):
    w = np.asarray(w, dtype=np.float64)
    return np.array([2.0 * (w[0] - 1.0),
                     4.0 * (w[1] + 1.0)], dtype=np.float64)

w0 = np.array([2.0, -2.0], dtype=np.float64)
eta = 0.1
g0 = grad_f(w0)
w1 = w0 - eta * g0
print("w0 =", w0, " f(w0) =", f(w0))
print("grad f(w0) =", g0)
print("w1 =", w1, " f(w1) =", f(w1))

# Szintvonalak es a lepes szamitott abrazolasa
w1_vals = np.linspace(-1.0, 3.0, 101)
w2_vals = np.linspace(-3.0, 1.0, 101)
W1, W2 = np.meshgrid(w1_vals, w2_vals)
F = (W1 - 1.0) ** 2 + 2.0 * (W2 + 1.0) ** 2
plt.contour(W1, W2, F, levels=[0.25, 0.5, 1.0, 2.0, 4.0])
plt.quiver(w0[0], w0[1], -eta * g0[0], -eta * g0[1],
           angles='xy', scale_units='xy', scale=1,
           color='tab:red', width=0.012)
plt.scatter([w0[0], w1[0]], [w0[1], w1[1]], color='black', s=25)
plt.gca().set_aspect('equal')
plt.xlabel('w1')
plt.ylabel('w2')
plt.title('Gradiens lepes: szamitott szemleltetes')
plt.savefig('lab/n014_grad_step.png', dpi=120)

A kézirat ezt a kódot nem futtatta; az alábbi kimenet ezért analitikus kézzel számított érték, nem mért futás. A futtatás után a várt értékek:

w0 = [ 2. -2.]  f(w0) = 3.0
grad f(w0) = [ 2. -4.]
w1 = [ 1.8 -1.6]  f(w1) = 1.36

A lépés szemléltetése a szintvonalakkal együtt:

Veszteség a gradienslépés mentén - Kézzel számított szemléltetés, nem futtatott kimenet.

Az ábra és a kimenet ellenőrzése három ponton történik: a gradiens értéke (2,−4)(2,-4); a frissített pont (1,8,−1,6)(1{,}8,-1{,}6); a veszteség 33-ról 1,361{,}36-ra csökken. Ha a lépés irányát a pozitív gradiensre cserélnénk, a veszteség nőne; ez a labor lehetséges negatív kontrollja.

4.2.9 Feladatok

F1 (fogalmi, nehézség 1). Definiálja pontosan a parciális deriváltat és a gradienst egy f:ℝ3→ℝf:\mathbb R^3\to\mathbb R függvényre. Magyarázza el, miért nem elegendő a három parciális derivált létezése a differenciálhatósághoz. Adjon rövid ellenpélda-vázlatot.

F2 (levezetési, nehézség 2). Legyen f(w1,w2)=w12+3w1w2+2w22f(w_1,w_2)=w_1^2+3w_1w_2+2w_2^2. Számítsa ki ∇f(1,−1)\nabla f(1,-1) vektort, a v=(1,2)⊤v=(1,2)^\top irányú Dvf(1,−1)D_v f(1,-1) iránymenti deriváltat, és a legmeredekebb növekedés irányába mutató egységvektort az (1,−1)(1,-1) pontban. Ellenőrizze az eredményt a DvfD_v f definíciójából is egy konkrét kis hh-ra.

F3 (implementációs, nehézség 2). Írjon Python függvényt, amely centrális differenciával közelíti egy f:ℝ2→ℝf:\mathbb R^2\to\mathbb R függvény gradiensét: ∂f/∂wi≈[f(w+hei)−f(w−hei)]/(2h)\partial f/\partial w_i\approx [f(w+h e_i)-f(w-h e_i)]/(2h). Használja a labor f(w1,w2)=(w1−1)2+2(w2+1)2f(w_1,w_2)=(w_1-1)^2+2(w_2+1)^2 függvényét, h=10−5h=10^{-5}, float64 típust és a w=(2,−2)⊤w=(2,-2)^\top pontot. Az elvárt átadandó eredmény: a numerikus gradiens és az analitikus (2,−4)(2,-4) közötti abszolút hiba mindkét komponensben 10−410^{-4} alatt van.

F4 (hibakeresési, nehézség 2). A következő függvény a labor gradiensét hivatott számítani:

def hibas_grad(w):
    w = np.asarray(w, dtype=np.float64)
    return np.array([4.0 * (w[0] - 1.0),
                     2.0 * (w[1] + 1.0)], dtype=np.float64)

A w=(2,−2)w=(2,-2) pontban a helyes gradiens (2,−4)(2,-4), a függvény azonban (4,−2)(4,-2) értéket ad. Lokalizálja a hibát, magyarázza el a következményét egy gradienslépésre, javítsa a kódot, és ellenőrizze a javítást ugyanabban a pontban.

F5 (kísérleti/transzfer, nehézség 3). Tervezzen protokollt annak ellenőrzésére, hogy a negatív gradiens irányú lépés mikor csökkenti a veszteséget. Megfigyelési egység: egy rögzített ww pont; a változó tényező: a η\eta lépésköz; a metrika: f(w−η∇f(w))−f(w)f(w-\eta\nabla f(w))-f(w) előjeles különbség. Számítsa ki a labor függvényére a w(0)=(2,−2)⊤w^{(0)}=(2,-2)^\top, η=0,1;0,5;1,0\eta=0{,}1;0{,}5;1{,}0 eseteket, és indokolja, miért nő a veszteség η=1,0\eta=1{,}0-nál. Adja meg, milyen további η\eta értékeket vizsgálna, és mi a kísérlet érvényességi korlátja.

4.2.10 Megoldások és indoklás

F1 megoldás. A parciális derivált definíciója f:ℝ3→ℝf:\mathbb R^3\to\mathbb R esetén i=1,2,3i=1,2,3-ra:

∂f∂xi(x)=limh→0f(x+hei)−f(x)h, \frac{\partial f}{\partial x_i}(x) =\lim_{h\to 0}\frac{f(x+h e_i)-f(x)}{h},

ahol eie_i a háromdimenziós standard bázisvektor. A gradiens

∇f(x)=(∂f∂x1(x),∂f∂x2(x),∂f∂x3(x))⊤∈ℝ3. \nabla f(x)=\left(\frac{\partial f}{\partial x_1}(x), \frac{\partial f}{\partial x_2}(x), \frac{\partial f}{\partial x_3}(x)\right)^\top\in\mathbb R^3.

A puszta létezés nem elég, mert a differenciálhatóság ennél erősebb, közös lineáris közelítést követel: a maradéktagnak minden irányból ∥u∥\|u\|-nál gyorsabban kell nullához tartania. Ellenpélda-vázlat: az origón kívül f(x1,x2)=x1x2/(x12+x22)f(x_1,x_2)=x_1x_2/(x_1^2+x_2^2), az origóban 00; mindkét parciális derivált létezik és nulla az origóban, de a függvény nem folytonos ott, így nem differenciálható.

F2 megoldás. A parciális deriváltak ∂f/∂w1=2w1+3w2\partial f/\partial w_1=2w_1+3w_2 és ∂f/∂w2=3w1+4w2\partial f/\partial w_2=3w_1+4w_2. A (1,−1)(1,-1) pontban:

∇f(1,−1)=(2⋅1+3(−1)3⋅1+4(−1))=(−1−1). \nabla f(1,-1)=\begin{pmatrix}2\cdot1+3(-1)\\3\cdot1+4(-1)\end{pmatrix} =\begin{pmatrix}-1\\-1\end{pmatrix}.

Az iránymenti derivált a lemma alapján Dvf(1,−1)=(−1)(1)+(−1)(2)=−3D_v f(1,-1)=(-1)(1)+(-1)(2)=-3. A ∥v∥=5\|v\|=\sqrt5 normájú vektor miatt az egységirányra normált érték −3/5-3/\sqrt5. A legmeredekebb növekedés egységvektora ∇f/∥∇f∥=(−1,−1)⊤/2\nabla f/\|\nabla f\|=(-1,-1)^\top/\sqrt2. Numerikus ellenőrzés h=10−5h=10^{-5}-tel: f(1+h,−1+2h)≈f(1,−1)+h(−3)f(1+h,-1+2h)\approx f(1,-1)+h(-3), így a differenciahányados −3-3-hoz tart; a hh melletti eltérés O(h)O(h), mert ff sima.

F3 megoldás. A teljes függvény:

import numpy as np

def f(w):
    w = np.asarray(w, dtype=np.float64)
    return (w[0] - 1.0) ** 2 + 2.0 * (w[1] + 1.0) ** 2

def numerical_grad(f, w, h=1e-5):
    w = np.asarray(w, dtype=np.float64)
    g = np.zeros_like(w)
    for i in range(w.size):
        e = np.zeros_like(w)
        e[i] = 1.0
        g[i] = (f(w + h * e) - f(w - h * e)) / (2.0 * h)
    return g

w = np.array([2.0, -2.0], dtype=np.float64)
g_num = numerical_grad(f, w)
g_an = np.array([2.0, -4.0], dtype=np.float64)
print("numerikus:", g_num)
print("abszolut hiba:", np.abs(g_num - g_an))

A centrális differencia O(h2)O(h^2) csonkolási hibája és a 10−510^{-5} lépésköz melletti kerekítési hiba együttesen 10−1010^{-10} nagyságrendű eltérést ad, ami bőven a 10−410^{-4} korlát alatt van. A kódot a hallgató futtassa; a kézirat itt nem állít mért kimenetet, csak a képletből következő várt értéket.

F4 megoldás. A hiba oka: a hibas_grad a w1w_1 szerinti parciális derivált együtthatójának 22 helyett 44-et, a w2w_2 szerintinek 44 helyett 22-t használ; a két komponens együtthatója fel van cserélve. Következmény: a frissítés η=0,1\eta=0{,}1 mellett Δw=−0,1⋅(4,−2)=(−0,4;0,2)\Delta w=-0{,}1\cdot(4,-2)=(-0{,}4;0{,}2) lenne, ami a helyes Δw=(−0,2;0,4)\Delta w=(-0{,}2;0{,}4) helyett rossz irányú és hibás nagyságú lépést ad; a ff ebben a konkrét pontban még csökkenhetne ugyan, de más pontokban növekedést is okozhat, és a tanítás torzul. Javítás: az együtthatókat rendre 22-re és 44-re kell cserélni:

def javitott_grad(w):
    w = np.asarray(w, dtype=np.float64)
    return np.array([2.0 * (w[0] - 1.0),
                     4.0 * (w[1] + 1.0)], dtype=np.float64)

Ellenőrzés a (2,−2)(2,-2) pontban: javitott_grad(w) értéke (2,−4)(2,-4), megegyezik az analitikus gradienssel.

F5 megoldás. A protokoll rögzíti a w(0)=(2,−2)⊤w^{(0)}=(2,-2)^\top pontot és a ∇f(w(0))=(2,−4)⊤\nabla f(w^{(0)})=(2,-4)^\top gradienst. A változó az η∈{0,1;0,5;1,0}\eta\in\{0{,}1;0{,}5;1{,}0\} lépésköz, a kimenet f(w(0)−η∇f(w(0)))−f(w(0))f(w^{(0)}-\eta\nabla f(w^{(0)}))-f(w^{(0)}). Számolás:

A növekedés oka: a kvadratikus függvény mentén a gradiens maga is változik; túl nagy lépésköz átugorja a minimumot, és a túloldalon nagyobb értéket talál. A kísérlet ezért csak azt állíthatja, hogy elég kis η\eta-ra a lépés csökkenti a veszteséget, nem azt, hogy minden η\eta-ra csökken. Tovább vizsgálandó η\eta értékek: 0,25;0,33;0,40{,}25;0{,}33;0{,}4 a csökkenés tartományának határához; az érvényességi korlát, hogy az eredmény erre az egy függvényre és pontra vonatkozik, nem általános optimalizálási garancia.

4.2.11 Tipikus tévedés ellenpéldával

A leggyakoribb tévedés: ha minden parciális derivált létezik egy pontban, akkor a függvény ott differenciálható. Ez hamis. A klasszikus ellenpélda a

f(x1,x2)={x1x2x12+x22,(x1,x2)≠(0,0),0,(x1,x2)=(0,0) f(x_1,x_2)= \begin{cases} \frac{x_1x_2}{x_1^2+x_2^2},&(x_1,x_2)\neq(0,0),\\ 0,&(x_1,x_2)=(0,0) \end{cases}

függvény. Az origóban mindkét parciális derivált létezik és nulla:

∂f∂x1(0,0)=limh→0f(h,0)−f(0,0)h=limh→00h=0, \frac{\partial f}{\partial x_1}(0,0) =\lim_{h\to0}\frac{f(h,0)-f(0,0)}{h} =\lim_{h\to0}\frac{0}{h}=0,

és szimmetrikusan ∂f/∂x2(0,0)=0\partial f/\partial x_2(0,0)=0. A függvény mégsem differenciálható az origóban, mert nem is folytonos ott: az x1=x2=t≠0x_1=x_2=t\neq0 egyenes mentén f(t,t)=t2/(2t2)=1/2f(t,t)=t^2/(2t^2)=1/2, ami nem tart a 00-hoz, ha t→0t\to0. A 4.1. Függvény, határérték és derivált alfejezetbeli egyváltozós tétel analógiája itt is érvényes: a differenciálhatóságból következik a folytonosság, ezért a folytonosság hiánya kizárja a differenciálhatóságot. Ráadásul az (1,1)(1,1) irányú iránymenti derivált sem létezik, mert

f(h,h)−f(0,0)h=1/2h \frac{f(h,h)-f(0,0)}{h} =\frac{1/2}{h}

nem konvergál h→0h\to0 esetén. A gradiens-képletből számított ∇f(0,0)⊤(1,1)=0\nabla f(0,0)^\top(1,1)=0 tehát nem adná a tényleges iránymenti viselkedést; ez is mutatja, hogy a lemma feltétele, a differenciálhatóság, lényeges.

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

Ellenőrizze a fejezet állításait három ponton. (1) A kvadratikus veszteség gradiensének alakja: X∈ℝ3×2X\in\mathbb R^{3\times2}, w∈ℝ2w\in\mathbb R^2, y∈ℝ3y\in\mathbb R^3 esetén X⊤(Xw−y)∈ℝ2X^\top(Xw-y)\in\mathbb R^2, azonos alakú a ww paraméterrel. (2) Az iránymenti derivált homogenitása: D2vf=2DvfD_{2v}f=2D_vf a definícióból közvetlenül látszik, és a lemmával is konzisztens. (3) A kontúr-merőlegesség: a szintvonalon ff konstans, így az érintő irányú derivált nulla. Visszahívás a 3.2. Mátrixszorzás és affín réteg alfejezetből: a mátrixszorzás alak-egyeztetése itt a gradiens alakjának ellenőrzésében ismétlődik; a 4.1. Függvény, határérték és derivált alfejezetből: az egyváltozós határértékes definíciót terjesztettük ki irányonként.

4.2.13 Rövid összefoglaló

A parciális derivált egy többváltozós függvény egy koordinátája szerinti, rögzített többi változójú deriváltja. A gradiens a parciális deriváltak oszlopvektora, alakja az input alakjával egyezik. Az iránymenti derivált a vv irányú egyváltozós derivált; differenciálható függvény esetén Dvf(x)=∇f(x)⊤vD_vf(x)=\nabla f(x)^\top v. Ebből következik, hogy a gradiens a legmeredekebb növekedés iránya, és merőleges a szintvonalakra. A differenciálhatóság erősebb, mint a parciális deriváltak létezése: a lineáris közelítés maradékának minden irányból ∥u∥\|u\|-nál gyorsabban kell nullához tartania. A kvadratikus veszteség gradiense X⊤(Xw−y)X^\top(Xw-y); a labor ezt két paraméteren, kézi értékekkel és gradienslépéssel ellenőrizte.

4.2.14 Következő alkalmazás

A 4.3. Jacobi-mátrix, láncszabály és VJP a többváltozós láncszabályt és a Jacobi-mátrixot vezeti be. A gradiens itt tanult alak-egyeztetése ott válik a vektor–Jacobi-szorzat alapjává: a rétegenkénti visszafelé számításban a skalár veszteség gradiense mindig a megfelelő tensor alakjában jelenik meg.

4.2.15 Források