Aller au contenu principal

Gradients & backward pass sur le graphe

Définition

Soit f:TR une fonction diffeˊrentiable, ouˋ T est l’espace des tenseurs.\text{Soit } f : \mathcal{T} \to \mathbb{R} \text{ une fonction différentiable, où } \mathcal{T} \text{ est l'espace des tenseurs.} Le gradient de f en AT est le tenseur f(A)T deˊfini par :\text{Le gradient de } f \text{ en } A \in \mathcal{T} \text{ est le tenseur } \nabla f(A) \in \mathcal{T} \text{ défini par :} dAT, t.q. ddA(1)=dA(1),Df(A)[dA]=f(A),dA\forall\, dA \in \mathcal{T}, \text{ t.q. } \mathcal{d}_{dA}(-1) = \mathcal{d}_A(-1), \qquad \mathrm{D}f(A)[dA] = \langle \nabla f(A),\, dA \rangle

Ceci se lit comme la variation de ff évalué en AA pour une petite variation dAdA quelconque.

Pour des scalaires, c'est la définition attendue:

dA=hRdA = h \in \mathbb R et Df(A)[h]=f(A),h=hf(A)=f(A+h)f(A)Df(A)[h] = \langle f'(A), h \rangle = h*f'(A) = f(A+h) -f(A) pour hh assez petit. (f(A)=f(A)\nabla f(A) = f'(A))

Lorsqu'on a introduit le graphe, on a vu que les noeuds représentaient une opération et pointaient vers d'autres opérations (ou un scalaire si on était à la fin du graphe). Ce scalaire (souvent noté LL) représentera une fonction de perte. On reviendra sur cette fonction plus tard. Il faut juste comprendre que LL montrera les performances du modèle, donc que plus LL est faible, mieux le modèle se comporte. On cherche donc à optimiser les paramètres selon LL.

Opérations usuelles - gradients

Pour ce faire, on va commencer par calculer les gradients de chaque tenseur selon l'ordre topologique donné précédemment. On va donc commencer par LL, car son gradient vaut 1 trivialement.

Puis, on va calculer le gradient de chaque noeud dans l'ordre topologique inversé en utilisant les gradients déjà calculés.

Le but et de calculer le gradiant de A, B (ou A) sachant le gradiant de f(A, B) (ou f(A))

Addition

Soit L:TRL:\mathcal T\to\mathbb R différentiable et f:T2Tf:\mathcal T^2\to\mathcal T, f(A,B)=A+Bf(A,B)=A+B. Posons Y=f(A,B)Y=f(A,B) et G=YLY=f(A,B)TG=\nabla_Y L\big|_{Y=f(A,B)} \in \mathcal T

Un bout du graphe (l'application de ff) ressemble donc à ça :

Notons d'abord que

dY=Df(A,B)[dA,dB]=dA+dBdY = Df(A, B)[dA, dB] = dA+dB car f(A+dA,B+dB)f(A,B)=dA+dB\text{car } f(A+dA, B+dB)-f(A, B) = dA+dB

En développant LfL\circ f et d'après la chain rule et la définition de la différentielle, on a :

D(Lf)(A,B)[dA,dB]=DL(f(A,B))[Df(A,B)[dA,dB]]\mathrm D(L \circ f)(A,B)[\mathrm dA,\mathrm dB] = \mathrm DL\big(f(A,B)\big)\big[\,\mathrm Df(A,B)[\mathrm dA,\mathrm dB]\,\big] =dL(Y)[dY]=G,dY= dL(Y)[dY] = \langle G, dY \rangle =G, dA+dB=G,dA+G,dB= \langle G,\ \mathrm dA+\mathrm dB\rangle = \langle G, \mathrm dA \rangle + \langle G, \mathrm dB \rangle

Par ailleurs, (définition)

D(Lf)(A,B)[dA,dB]=AL,dA+BL,dB.\mathrm D(L \circ f)(A,B)[\mathrm dA,\mathrm dB] = \langle \nabla_A L,\,\mathrm dA\rangle + \langle \nabla_B L,\,\mathrm dB\rangle.

En identifiant (valable pour tout (dA,dB)(\mathrm dA,\mathrm dB)) :

 AL=BL =Gouˋ G=YLY=A+B\boxed{\ \nabla_A L = \nabla_B L\ = G } \qquad\text{où } G=\nabla_Y L\big|_{Y=A+B}

Multiplication

Soit L:TRL:\mathcal T\to\mathbb R différentiable et f:T2Tf:\mathcal T^2\to\mathcal T, f(A,B)=A@Bf(A,B)=A@B. (multiplication tensorielle) Posons Y=f(A,B)Y=f(A,B) et G=YLY=f(A,B)TG=\nabla_Y L\big|_{Y=f(A,B)} \in \mathcal T

Un bout du graphe (l'application de ff) ressemble donc à ça :

Notons d'abord que

dY=Df(A,B)[dA,dB]=A@dB+dA@BdY = Df(A, B)[dA, dB] = A@dB + dA@B car f(A+dA,B+dB)f(A,B)=A@dB+dA@B+dA@dB=A@dB+dA@B\text{car } f(A+dA, B+dB)-f(A, B) = A@dB + dA@B + dA@dB = A@dB + dA@B

En développant LfL\circ f et d'après la chain rule et la définition de la différentielle, on a :

D(Lf)(A,B)[dA,dB]=DL(f(A,B))[Df(A,B)[dA,dB]]\mathrm D(L \circ f)(A,B)[\mathrm dA,\mathrm dB] = \mathrm DL\big(f(A,B)\big)\big[\,\mathrm Df(A,B)[\mathrm dA,\mathrm dB]\,\big] =DL(Y)[dY]=G,dY= DL(Y)[dY] = \langle G, dY \rangle =G, dA+dB=G,A@dB+G,dA@B= \langle G,\ \mathrm dA+\mathrm dB\rangle = \langle G, \mathrm A@dB \rangle + \langle G, \mathrm dA@B \rangle =A@G,dB+G@B,dA (deˊfinition du produit scalaire)= \langle A^\top @ G, dB \rangle + \langle G @ B^\top, dA \rangle \text{ (définition du produit scalaire)}

Par ailleurs, (définition)

D(Lf)(A,B)[dA,dB]=AL,dA+BL,dB.\mathrm D(L \circ f)(A,B)[\mathrm dA,\mathrm dB] = \langle \nabla_A L,\,\mathrm dA\rangle + \langle \nabla_B L,\,\mathrm dB\rangle.

En identifiant (valable pour tout (dA,dB)(\mathrm dA,\mathrm dB)) :

 AL=G@B,BL =A@Gouˋ G=YLY=A@B\boxed{\ \nabla_A L = G @ B^\top, \nabla_B L\ = A^\top @ G} \qquad\text{où } G=\nabla_Y L\big|_{Y=A@B}

Application de fonction

Soit L:TRL:\mathcal T\to\mathbb R différentiable et f:TTf:\mathcal T\to\mathcal T. (appliquée élément par élément) (ex: tanh, ReLU)

On peut donc définir ff' comme la dérivée de ff dans R\mathbb{R} (appliquable à un tenseur), car en réalité f:RRf: \mathbb{R} \to \mathbb{R}, on l'a juste étendue pour l'appliquer sur chaque élément du tenseur.

Posons Y=f(A)Y=f(A) et G=YLY=f(A)TG=\nabla_Y L\big|_{Y=f(A)} \in \mathcal T

Un bout du graphe (l'application de ff) ressemble donc à ça :

Notons d'abord que comme ff agit point par point, avec i=(i1,...,iN)i = (i_1, ..., i_N) un indice (TiT_i est donc scalaire)

[Df(T)[dT]]i=f(Ti)dTidY=Df(T)[dT]=f(T)dT.\big[\mathrm Df(T)[\mathrm dT]\big]_{i}=f'(T_i)\,\mathrm dT_i \quad\Longrightarrow\quad dY = \mathrm Df(T)[\mathrm dT]=f'(T)\odot \mathrm dT.

\odot signifie la multiplication élément par élément. (hadamard)

En développant LfL\circ f et d'après la chain rule et la définition de la différentielle, on a :

D(Lf)(A)[dA]=DL(f(A))[Df(A)[dA]]\mathrm D(L \circ f)(A)[\mathrm dA] = \mathrm DL\big(f(A)\big)\big[\,\mathrm Df(A)[\mathrm dA]\,\big] =DL(Y)[dY]=G,dY= DL(Y)[dY] = \langle G, dY \rangle =G, f(A)dA=f(A)G,dA(*)= \langle G,\ f'(A) \odot dA\rangle = \langle f'(A)\odot G, dA \rangle \tag{*}

Par ailleurs, (définition)

D(Lf)(A)[dA]=AL,dA.\mathrm D(L \circ f)(A)[\mathrm dA] = \langle \nabla_A L,\,\mathrm dA\rangle .

En identifiant (valable pour tout (dA,dB)(\mathrm dA,\mathrm dB)) :

 AL=f(A)G,ouˋ G=YLY=f(A)\boxed{\ \nabla_A L = f'(A) \odot G, } \qquad\text{où } G=\nabla_Y L\big|_{Y=f(A)}

(*) est très simple à dériver: X,YZ=xbijybijzbij\langle X, Y \odot Z \rangle = x_{bij}y_{bij}z_{bij} avec bb l'indice de batch. On voit bien que tout commute, et que donc X,YZ=YX,Z\langle X, Y \odot Z \rangle =\langle Y \odot X , Z \rangle