Uno degli aspetti più delicati nella computazione legata a modelli di deep learning è relativa al numero enorme di parametri, dati e calcoli coinvolti, organizzati in modo pratico in vettori e matrici, e al relativo calcolo del gradiente della funzione di costo rispetto a tali parametri.

E' quindi opportuno capire come impostare in modo efficiente i calcoli nel grafo computazionale del modello, applicando correttamente la chain rule e ricavando in modo elegante i gradienti anche rispetto a grandezze di tipo vettoriale e matriciale - passaggio essenziale nello sviluppo della backpropagation e della vettorizzazione del training set per processare batch di dati senza essere costretti ad iterare per ogni singolo campione.

Utilizziamo in seguito una notazione semplificata, indicando con \(\text d \boldsymbol x \) il gradiente di una nostra funzione costo \(J\) rispetto alla grandezza \(\boldsymbol x\)  della quale conserverà ovviamente le stesse dimensioni per essere utilizzata direttamente negli algoritmi della discesa del gradiente.

Proponiamo subito una pratica tabella riassuntiva di sviluppo di gradienti utili nella backprogation per modelli di reti neurali densamente connesse (Fully Connected), calcolati rispetto a un gradiente noto \(\text d \boldsymbol z\) 

Per ogni voce è sviluppato in calce il calcolo di dettaglio, sebbene quasi tutti i casi possano essere derivati dal caso generale del calcolo di \(\text d \boldsymbol W \ \) per \(\boldsymbol Z_{(n \times p)} = \boldsymbol W_{(n \times m)} \boldsymbol X_{(m \times p)} \)

 

\(\boldsymbol z_{(n \times 1)} = \boldsymbol W_{(n \times m)} \boldsymbol x_{(m \times 1)}\) \(\text d \boldsymbol x_{(m \times 1)} = {\boldsymbol W}^\top_{(m \times n)} \text d {\boldsymbol z}_{(n \times 1)}\)
\(\boldsymbol z_{(1 \times n)} = \boldsymbol x_{(1 \times m)} \boldsymbol W_{(m \times n)} \) \(\text d \boldsymbol x_{(1 \times m)} = \text d {\boldsymbol z}_{(1 \times n)} {\boldsymbol W}^\top_{(n \times m)}\)
\(\boldsymbol Z = \boldsymbol X\) \(\text d \boldsymbol X = \text d \boldsymbol Z \ \)
\(Z_{ij} = f(Z_{ij})\) \(\text d \boldsymbol X = \text d \boldsymbol Z * f'(\boldsymbol X)\)
\(\boldsymbol z_{(n \times 1)} = \boldsymbol W_{(n \times m)} \boldsymbol x_{(m \times 1)}\) \(\text d \boldsymbol W_{(n \times m)} = \text d \boldsymbol z_{(n \times 1)} \ \boldsymbol x^\top_{(1 \times m)} \)
\(\boldsymbol z_{(1 \times n)} = \boldsymbol x_{(1 \times m)} \boldsymbol W_{(m \times n)} \) \(\text d \boldsymbol W_{(m \times n)} = \boldsymbol x^\top_{(m \times 1)} \text d \boldsymbol z_{(1 \times n)} \)
\(\boldsymbol Z_{(n \times p)} = \boldsymbol W_{(n \times m)} \boldsymbol X_{(m \times p)} \) \(\text d \boldsymbol W_{(n \times m)} = \text d \boldsymbol Z_{(n \times p)} \ \boldsymbol X^\top_{(p \times m)}\)
\(\boldsymbol Z_{(n \times p)} = \boldsymbol X_{(n \times m)} \boldsymbol W_{(m \times p)} \) \(\text d \boldsymbol W_{(m \times p)} = \boldsymbol X^\top_{(m \times n)} \text d \boldsymbol Z_{(n \times p)} \ \)
\(\boldsymbol Z=\text{softmax}(\boldsymbol X) \\ J=\text CE(\boldsymbol Z, \boldsymbol Y)\) \(\text d \boldsymbol X = \boldsymbol {(Z-Y)}\)

 

Jacobiano

Partiamo dalla definizione di jacobiano, che generalizza il concetto di derivata a una funzione \(\Bbb R^n \rightarrow \Bbb R^m\) e al quale è possibile applicare la chain rule in modo assolutamente trasparente:

Sia \(\boldsymbol f : \Bbb R^n \rightarrow \Bbb R^m \ \ , \ \ \boldsymbol f (\boldsymbol {x} )= \left[ f_1(x_1 \cdots x_n), \cdots, f_m(x_1 \cdots x_n) \right]\)

Definiamo quindi il jacobiano  \(\frac{\partial \boldsymbol f}{\partial \boldsymbol x}=\begin{bmatrix} \frac{\partial f_1}{\partial x_1} & \cdots & \frac{\partial f_1}{\partial x_n} \\ \vdots & \ddots & \vdots \\ \frac{\partial f_m}{\partial x_1} & \cdots & \frac{\partial f_m}{\partial x_n} \end{bmatrix} = \begin{bmatrix} \frac{\partial \boldsymbol f}{\partial x_1} & \cdots & \frac{\partial \boldsymbol f}{\partial x_n} \end{bmatrix} = \begin{bmatrix} \nabla f_1^\top \\ \vdots \\ \nabla f_m^\top \end{bmatrix} \)

Come detto il jacobiano supporta pienamente la chain rule, per cui è facile verificare che se \(\boldsymbol f : \Bbb R^n \rightarrow \Bbb R^m\)  e  \(\boldsymbol g : \Bbb R^m \rightarrow \Bbb R^l\)  allora \(\frac{\partial \boldsymbol g(\boldsymbol f(\boldsymbol x))}{\partial \boldsymbol x} = \frac{\partial \boldsymbol g}{\partial \boldsymbol f}\frac{\partial \boldsymbol f}{\partial \boldsymbol x}\)

Notiamo che il jacobiano è la trasposta del gradiente, per cui, ogni qualvolta avremo un jacobiano esplicitamente direttamente coinvolto nel calcolo del gradiente, dovremo fare attenzione a verificare che la dimensione del gradiente sia quella effettivamente attesa e nel caso applicare la trasposizione - in particolare quando operiamo con vettori colonna.

 

\(\boldsymbol z_{(n \times 1)} = \boldsymbol W_{(n \times m)} \boldsymbol x_{(m \times 1)}\) : jacobiano \(\frac{\partial \boldsymbol z}{\partial \boldsymbol x} \) e gradiente \(\text d \boldsymbol x \)

In questo caso abbiamo che \(\displaystyle z_i=\sum_{i=1}^m W_{ij} x_j\)  e \(\frac{\partial z_i}{\partial x_j} = W_{ij}\) , pertanto avremo un jacobiano \(\displaystyle \frac{\partial \boldsymbol z}{\partial \boldsymbol x}={\boldsymbol W} \ \).

Attraverso la chain rule tra jacobiani \(\frac{\partial J}{\partial \boldsymbol x}=\frac{\partial J}{\partial \boldsymbol z}\frac{\partial \boldsymbol z}{\partial \boldsymbol x}=\frac{\partial J}{\partial \boldsymbol z}\boldsymbol W \ \)

Vediamo ora per riprova il calcolo del gradiente, che ci attendiamo essere ricavabile dalla trasposta dello jacobiano. 
 

\(\text d \boldsymbol x = \begin{bmatrix} \frac{\partial J}{\partial x_1} \\ \vdots \\ \frac{\partial J}{\partial x_m} \end{bmatrix}\) e  \(\text d \boldsymbol z = \begin{bmatrix} \frac{\partial J}{\partial z_1} \\ \vdots \\ \frac{\partial J}{\partial z_n} \end{bmatrix}\)  e per la regola della chain rule \(\frac{\partial J}{\partial x_j}=\sum_{i=1}^n \frac{\partial J}{\partial z_i}\frac{\partial z_i}{\partial x_j}=(W_{:j})^\top \text d \boldsymbol z \ \) , e quindi concludiamo esplicitando le dimensioni che:

\(\text d \boldsymbol x_{(m \times 1)} = \begin{bmatrix} (W_{:1})^\top \text d \boldsymbol z \\ \vdots \\ (W_{:m})^\top \text d \boldsymbol z \end{bmatrix} = {\boldsymbol W}^\top_{(m \times n)} \text d {\boldsymbol z}_{(n \times 1)}\)

a conferma della relazione di trasposizione tra jacobiano e gradiente.

 

\(\boldsymbol z_{(1 \times n)} = \boldsymbol x_{(1 \times m)} \boldsymbol W_{(m \times n)} \) : jacobiano \(\frac{\partial \boldsymbol z}{\partial \boldsymbol x} \) e gradiente \(\text d \boldsymbol x \)

In questo caso abbiamo che \(\displaystyle z_i=\sum_{i=1}^m W_{ji} x_j\)  e \(\frac{\partial z_i}{\partial x_j} = W_{ji}\) , pertanto avremo un jacobiano \(\displaystyle \frac{\partial \boldsymbol z}{\partial \boldsymbol x}={\boldsymbol W}^\top \ \).

Attraverso la chain rule tra jacobiani \(\frac{\partial J}{\partial \boldsymbol x}=\frac{\partial J}{\partial \boldsymbol z}\frac{\partial \boldsymbol z}{\partial \boldsymbol x}=\frac{\partial J}{\partial \boldsymbol z}\boldsymbol W^\top \ \)

Vediamo ora per riprova il calcolo del gradiente. Abbiamo:
\(\text d \boldsymbol x = \begin{bmatrix} \frac{\partial J}{\partial x_1} \ \cdots \ \frac{\partial J}{\partial x_m} \end{bmatrix}\) e  \(\text d \boldsymbol z = \begin{bmatrix} \frac{\partial J}{\partial z_1} \ \cdots \ \frac{\partial J}{\partial z_n} \end{bmatrix}\)  e per la regola della chain rule \(\displaystyle \frac{\partial J}{\partial x_j}=\sum_{i=1}^n \frac{\partial J}{\partial z_i}\frac{\partial z_i}{\partial x_j}= \text d \boldsymbol z \ (\boldsymbol W_{j:})^\top\) , e quindi concludiamo esplicitando le dimensioni che:

\(\text d \boldsymbol x_{(1 \times m)} = \begin{bmatrix} \text d \boldsymbol z \ (\boldsymbol W_{1:})^\top \ \cdots \ \text d \boldsymbol z \ (\boldsymbol W_{m:})^\top \end{bmatrix} = \text d {\boldsymbol z}_{(1 \times n)} {\boldsymbol W}^\top_{(n \times m)}\)

 

\(\boldsymbol z = \boldsymbol x\) : jacobiano \(\frac{\partial \boldsymbol z}{\partial \boldsymbol x} \) e gradiente \(\text d \boldsymbol x \)

In questo caso \(\frac{\partial z_i}{\partial x_j} = \begin{cases} 0 \ \text {se} \ i \ne j \\ 1 \ \text {se} \ i = j \end{cases}\) pertanto \(\frac { \partial \boldsymbol z}{\partial \boldsymbol x} = \bf I \ \)

Per quanto riguarda il gradiente è immediato che \(\text d \boldsymbol x = \text d \boldsymbol z \ \)

 

\(z_i = f(x_i)\) : jacobiano \(\frac{\partial \boldsymbol z}{\partial \boldsymbol x} \) e gradiente \(\text d \boldsymbol x \)

Ipotizziamo di avere una funzione \(f:\Bbb R \rightarrow \Bbb R\) applicata ad ogni componente del vettore \(\boldsymbol x\)

In questo caso \(\frac{\partial z_i}{\partial x_j} = \begin{cases} 0 \ \text {se} \ i \ne j \\ f'(x_i) \ \text {se} \ i = j \end{cases}\) pertanto \(\frac { \partial \boldsymbol z}{\partial \boldsymbol x} = \text {diag} (f'(\boldsymbol {x} ))\)

Per quanto riguarda il gradiente, ipotizzando due vettori colonna, abbiamo \(\displaystyle \frac{\partial J}{\partial x_j}=\sum_{i=1}^n \frac{\partial J}{\partial z_i}\frac{\partial z_i}{\partial x_j}= \text d z_j \ f'(x_j)\) 

e quindi \(\text d \boldsymbol x = \text d \boldsymbol z * f'(\boldsymbol x)\)  , dove l'operatore \(*\) effettua una moltiplicazione componente per componente delle due grandezze.

Il risultato relativo al gradiente è valido anche se consideriamo \(\boldsymbol {Z, X} \in \Bbb R^{n \times m}\) infatti \(\frac{\partial Z_{ij}}{\partial X_{kl}}=\begin{cases} 0 \ \text se \ i,j \ne k,l \\ f'(X_{ij})\ \text se\ i,j=k,l \end{cases}\) e quindi

\(\displaystyle \frac{\partial J}{\partial X_{kl}}=\sum_{i=1}^m \sum_{j=1}^n \frac{\partial J}{\partial Z_{ij}} \frac{\partial Z_{ij}}{\partial X_{kl}}= \text d Z_{kl} f'(X_{kl})\)   che infatti porta ad un gradiente \(\text d \boldsymbol X = \text d \boldsymbol Z * f'(\boldsymbol X )\)

 

\(\boldsymbol z_{(n \times 1)} = \boldsymbol W_{(n \times m)} \boldsymbol x_{(m \times 1)}\) : jacobiano \(\frac{\partial \boldsymbol z}{\partial \boldsymbol W} \) e gradiente \(\text d \boldsymbol W\)

In questo caso e nei successivi dove andremo a calcolare il gradiente rispetto a grandezze strutturate in matrici, andremo convenientemente a definire il ns.gradiente con la stessa dimensione della struttra originaria, cosa che ne permetterà anche l'utilizzo in modo diretto negli algoritimi di discesa del gradiente:

\(\text d \boldsymbol W = \begin{bmatrix} \text d W_{11} & \cdots & \text d W_{1n} \\ \vdots & \ddots & \vdots \\ \text d W_{m1} & \cdots & \text d W_{mn} \end{bmatrix}\). Questo tipo di organizzazione tuttavia rende problematica la definizione diretta dello jacobiano \(\frac{\partial \boldsymbol z}{\partial \boldsymbol W} \)che si attende invece un vettore di dimensione \(m n\) e non una matrice, che darebbe teoricamente origine a un jacobiano in forma di tensore.

Per tale motivo ci focalizziamo direttamente sul calcolo del gradiente \(\text d \boldsymbol W\)  e delle singole componenti \(\frac {\partial z_k}{\partial W_{ij}} \)senza entrare nella esplicitazione della struttura dello jacobiano.

Abbiamo innanzitutto che \(\displaystyle z_k=\sum_{l=1}^m W_{kl}x_l\)  e quindi  \(\displaystyle \frac {\partial z_k}{\partial W_{ij}} =\begin{cases} 0 \ \ se \ \ k \ne i \\ x_j \ se \ \ k = i \end{cases} \) che possiamo anche scrivere come

\(\frac {\partial \boldsymbol z}{\partial W_{ij}}=\begin{bmatrix} \boldsymbol 0 \\ x_j \\ \boldsymbol 0 \end{bmatrix} \leftarrow i \text {-ma riga}\)    e applicando la chain rule \(\displaystyle \frac{\partial J}{\partial W_{ij}}=\frac{\partial J}{\partial \boldsymbol z}\frac{\partial \boldsymbol z}{\partial W_{ij}}=\sum_{k=1}^n \frac{\partial J}{\partial z_k}\frac{\partial z_k}{\partial W_{ij}}=\text d z_i \ x_j\) 

e quindi abbiamo che il gradiente \(\text d \boldsymbol W_{(n \times m)} = \text d \boldsymbol z_{(n \times 1)} \ \boldsymbol x^\top_{(1 \times m)} \)

 

\(\boldsymbol z_{(1 \times n)} = \boldsymbol x_{(1 \times m)} \boldsymbol W_{(m \times n)} \) : jacobiano \(\frac{\partial \boldsymbol z}{\partial \boldsymbol W} \) e gradiente \(\text d \boldsymbol W\)

In questo caso \(\displaystyle z_k=\sum_{l=1}^m W_{lk}x_l\)  e quindi  \(\displaystyle \frac {\partial z_k}{\partial W_{ij}} =\begin{cases} 0 \ \ se \ \ k \ne j \\ x_i \ se \ \ k = j \end{cases} \) che possiamo anche scrivere come

\(\frac {\partial \boldsymbol z}{\partial W_{ij}}=\begin{bmatrix} \boldsymbol 0 \\ x_i \\ \boldsymbol 0 \end{bmatrix} \leftarrow j \text {-ma riga}\) e applicando la chain rule \(\displaystyle \frac{\partial J}{\partial W_{ij}}=\frac{\partial J}{\partial \boldsymbol z}\frac{\partial \boldsymbol z}{\partial W_{ij}}=\sum_{k=1}^n \frac{\partial J}{\partial z_k}\frac{\partial z_k}{\partial W_{ij}}=\text d z_j \ x_i\) 

e otteniamo il gradiente \(\text d \boldsymbol W_{(m \times n)} = \boldsymbol x^\top_{(m \times 1)} \text d \boldsymbol z_{(1 \times n)} \)

 

\(\boldsymbol Z_{(n \times p)} = \boldsymbol W_{(n \times m)} \boldsymbol X_{(m \times p)} \) : jacobiano \(\frac{\partial \boldsymbol Z}{\partial \boldsymbol W} \) e gradiente \(\text d \boldsymbol W\)

Questo caso e il successivo generalizzano i 2 casi precedenti con l'utilizzo di matrici al posto di vettori.

Abbiamo \(\displaystyle Z_{ij}= \sum_{h=1}^m W_{ih}X_{hj}\) e quindi \(\displaystyle \frac {\partial Z_{ij}}{\partial W_{kl}} =\begin{cases} \ 0 \ \ se \ \ k \ne i \\ X_{lj} \ se \ k = i \end{cases} \)

Applicando la chain rule \(\displaystyle \frac{\partial J}{\partial W_{kl}}=\sum_{i=1}^n \sum_{j=1}^p \frac{\partial J}{\partial Z_{ij}} \frac{\partial Z_{ij}}{\partial W_{kl}}= \sum_{j=1}^p \text d Z_{kj} X_{lj}=\text d \boldsymbol Z_{k:} (\boldsymbol X_{l:})^\top\)

E pertanto \(\text d \boldsymbol W_{(n \times m)} = \text d \boldsymbol Z_{(n \times p)} \ \boldsymbol X^\top_{(p \times m)}\)

 

\(\boldsymbol Z_{(n \times p)} = \boldsymbol X_{(n \times m)} \boldsymbol W_{(m \times p)} \) : jacobiano \(\frac{\partial \boldsymbol Z}{\partial \boldsymbol W} \) e gradiente \(\text d \boldsymbol W\)

Abbiamo \(\displaystyle Z_{ij}= \sum_{h=1}^m X_{ih}W_{hj}\) e quindi \(\displaystyle \frac {\partial Z_{ij}}{\partial W_{kl}} =\begin{cases} \ 0 \ \ se \ \ j \ne l \\ X_{ik} \ se \ j = l \end{cases} \)

Applicando la chain rule \(\displaystyle \frac{\partial J}{\partial W_{kl}}=\sum_{i=1}^n \sum_{j=1}^p \frac{\partial J}{\partial Z_{ij}} \frac{\partial Z_{ij}}{\partial W_{kl}}= \sum_{i=1}^n \text d Z_{il} X_{ik}=(\boldsymbol X_{:k})^\top \text d \boldsymbol Z_{:l} \)

E pertanto \(\text d \boldsymbol W_{(m \times p)} = \boldsymbol X^\top_{(m \times n)} \text d \boldsymbol Z_{(n \times p)} \ \)

 

\(\boldsymbol z_{(n \times 1)}= \text {softmax} (\boldsymbol x_{(n \times 1)}) \ , \ J=\text {CE} (\boldsymbol z , \boldsymbol y)\) : jacobiano \(\frac{\partial \boldsymbol z}{\partial \boldsymbol x}\) e gradiente \(\text d \boldsymbol x\)

Un caso di funzione che troviamo frequentemente nelle reti neurali e merita di essere trattata specificamente è la funzione \( \text {softmax} (\boldsymbol x_{(n \times 1)})=\begin{bmatrix} \frac{e^{x_1}}{\sum_{k=1}^n e^{x_k}} \\ \vdots \\ \frac{e^{x_n}}{\sum_{k=1}^n e^{x_k}} \\ \end{bmatrix}\) .     Iniziamo a calcolare il jacobiano:

\(\frac{\partial z_i}{\partial x_j}=\begin{cases} \text{se} \ i \ne j \Rightarrow \ -\frac{e^{x_i} e^{x_j}}{(\sum_{k=1}^n e^{x_k})^2} = -z_i z_j\\ \text{se} \ i = j \Rightarrow \ \frac{e^{x_j}}{\sum_{k=1}^n e^{x_k}} -\frac{e^{x_j} e^{x_j}}{(\sum_{k=1}^n e^{x_k})^2} = z_j(1-z_j) \end{cases}\)  e quindi \(\frac{\partial \boldsymbol z}{\partial \boldsymbol x} = \begin{bmatrix} z_1(1-z_1) & \cdots & -z_1 z_n \\ \vdots & \ddots & \vdots \\ -z_n z_1 & \cdots & z_n(1-z_n) \end{bmatrix}\)

La funzione softmax è quasi sempre presente nel livello di uscita, abbinata ad una funzione di costo entropia incrociata (Cross Entropy)   \(J=\text{CE}(\boldsymbol z, \boldsymbol y) = {-\boldsymbol y}^\top \log \boldsymbol z\)  , nella quale la somma delle componenti del vettore dato y è uguale a 1. Procederemo in questo caso a prendere a esplicitare il jacobiano \(\frac{\partial J}{\partial \boldsymbol z} = \begin{bmatrix} -\frac {y_1}{z_1} \cdots -\frac {y_n}{z_n} \end{bmatrix}\)

Applicando la chain rule agli jacobiani  abbiamo \(\frac{\partial J}{\partial \boldsymbol x}=\frac{\partial J}{\partial \boldsymbol z}\frac{\partial \boldsymbol z}{\partial \boldsymbol x}=\begin{bmatrix} \cdots -\frac{y_j}{z_j}z_j(1-z_j)+\sum_{k \ne j} \frac{y_k}{z_k}z_j z_k \cdots \end{bmatrix} = \begin{bmatrix} \cdots -y_j+z_jy_j+z_j\sum_{k \ne j} y_k \cdots \end{bmatrix}= \begin{bmatrix} \cdots z_j-y_j \cdots \end{bmatrix}=(\boldsymbol z - \boldsymbol x)^\top\)

Per cui trasponendo otteremo il gradiente  \(\text d \boldsymbol x = \boldsymbol {z-x}\)

Il risultato può essere esteso anche nel caso di matrici, dove con \(\boldsymbol Z_{(n \times m)}=\text{softmax}(\boldsymbol X_{(n \times m)})\)  applichiamo la funzione softmax colonna per colonna, ovvero \(\begin{bmatrix} \boldsymbol z_{:1} \cdots \boldsymbol z_{:m} \end{bmatrix} = \begin{bmatrix} \text{softmax}(\boldsymbol x_{:1}) \cdots \text{softmax}(\boldsymbol x_{:m}) \end{bmatrix} \) .  La funzione di costo che utilizzeremo in questo caso è estesa alla matrice come \(\displaystyle J= \sum_{i=1}^m \sum_{j=1}^n -Y_{ij} \ \log Z_{ij}\)   e   \(\frac{\partial J}{\partial Z_{ij}} = -\frac{Y_{ij}}{Z_{ij}}\)

In questo caso abbiamo:

 \(\frac{\partial Z_{ij}}{\partial X_{kl}}=\begin{cases} \text{se} \ j \ne l \Rightarrow \ 0 \\ \text{se} \ j=l \ , \ i \ne k \Rightarrow \ -\frac{e^{X_{il}} \ e^{X_{kl}}}{(\sum_{t=1}^n e^{X_{tl}})^2} = -Z_{il} Z_{kl} \\ \text{se} \ j=l \ , \ i = k \Rightarrow \ \frac{e^{X_{kl}} }{\sum_{t=1}^n e^{X_{tl}}} -\frac{e^{X_{kl}} \ e^{X_{kl}}}{(\sum_{t=1}^n e^{X_{tl}})^2} = Z_{kl}(1-Z_{kl}) \end{cases}\)

\(\displaystyle \frac{\partial J}{\partial X_{kl}}= \sum_{i=1}^m \sum_{j=1}^n \frac{\partial J}{\partial Z_{ij}} \frac{\partial Z_{ij}}{\partial X_{kl}} = \sum_{i=1}^m -\frac{Y_{il}}{Z_{il}} \frac{\partial Z_{il}}{\partial X_{kl}}= -\frac{Y_{kl}}{Z_{kl}} Z_{kl}(1-Z_{kl}) + \sum_{i \ne k} \frac{Y_{il}}{Z_{il}} Z_{il}Z_{kl}= -Y_{kl}+Y_{kl}Z_{kl}+Z_{kl}\sum_{i \ne k}Y_{il}=Z_{kl}-Y_{kl}\)

Per cui otteniamo \(\text d \boldsymbol X = \boldsymbol {(Z-Y)}\)

Nella pratica la funzione di costo viene moltiplicata per un coefficiente \(\frac{1}{m}\) per ottenere valori non legati alla numerica delle colonne/campioni in matrice.

 

Come abbiamo visto precedentemente il metodo della discesa del gradiente presenta alcune problematicità di efficienza nel caso di plateau e di disomogeneità rilevanti del gradiente nelle varie dimensioni.

Per rendere il metodo più efficiente vengono solitamente utilizzate delle versioni più evolute del metodo, in grado di accelerare la ricerca e contrastare i casi patologici.

Discesa del gradiente con momento

Un metodo particolarmente efficiente nello smorzare ampie oscillazioni nei passi dovute a disomogeneità forti del gradiente lungo diverse dimensioni, è quello di utilizzare al posto del gradiente \(\nabla f ({\bf x}^{(t-1)}) \) la media esponenziale \({\bf v}_t\) sui valori del gradiente stesso:

\(\begin{cases} {\bf v}_t=\beta {\bf v}_{t-1} + (1 -\beta)\nabla f({\bf x}^{(t-1)}) \quad , \quad {\bf v}_0=0 \\ {\bf x}^{(t)} = {\bf x}^{(t-1)}-\alpha {\bf v}_t \end{cases}\)

dove il coefficiente \(\beta <1\) indica il peso assegnato nella media ai gradienti precedenti. Generalmente viene utilizzato un \(\beta \approx 0.9\) e la media viene calcolata biased come presentato nella formula, ovvero senza correttivo per i primi  \({\bf v}_t\) che avranno modulo ridotto.

L'utilizzo del momento smorzerà le oscillazioni e contribuirà ad una discesa verso il minimo con meno passi.

RMSprop

Un'altra variante consiste nell'armonizzare i passi nelle varie dimensioni, smorzando o amplificando le varie componenti del gradiente in ragione della loro media.
In particolare prenderemo in considerazione la radice della media esponenziale biased dei quadrati:
\(\displaystyle \forall \ i \ \begin{cases} s_i^{(t)}=\beta s_i^{(t-1)}+(1-\beta) \left[ \frac{\partial f}{\partial x_i}({\bf x}^{(t-1)}) \right]^2 \ \ , \ \ s_i^{(0)}=0 \\ x_i^{(t)}=x_i^{(t-1)} - \alpha \frac{\frac{\partial f}{\partial x_i}({\bf x}^{(t-1)})}{\sqrt{s_i^{(t)}}+\varepsilon} \end{cases} \)

dove il coefficiente \(\beta <1\) indica il peso assegnato nella media ai coefficienti \(s_i \) precedenti. Generalmente viene utilizzato un \(\beta \approx 0.99\) e la media viene calcolata unbiased come presentato nella formula, ovvero senza correttivo per i primi  \(s_i\) che avranno modulo ridotto.
Viene anche introdotto un \(\varepsilon \approx 10^{-8}\) al denominatore per evitare errori dovuti a \(s_i\) prossimi a zero.

RMSprop da un lato armonizza lo sviluppo dei passi tra le dimensioni non omogenee del gradiente, smorzando quelle di modulo maggiore e amplificando quelle di modulo minore, dall'altro "accelera" la fuga da zone di plateau, dove le componenti del gradiente diventano prossime allo zero.

Adam

L' algoritmo Adam combina la discesa con Momento e RMSprop per integrare in modo efficace i benefici di entrambi gli algoritmi. 

A differenza degli algoritmi singoli, Adam utilizza generalmente le medie esponenziali unbiased ovvero normalizzate dividendole per un fattore \((1-\beta ^t)\) che riequilibri in particolare i primi valori della media.

Per ogni dimensione avremo quindi:

\(\displaystyle \forall \ i \ \begin{cases} v_i^{(t)}=\beta_1 v_i^{(t-1)}+(1-\beta_1) \left[ \frac{\partial f}{\partial x_i}({\bf x}^{(t-1)}) \right] \ \ , \ \ v_i^{(0)}=0 \\ s_i^{(t)}=\beta_2 s_i^{(t-1)}+(1-\beta_2) \left[ \frac{\partial f}{\partial x_i}({\bf x}^{(t-1)}) \right]^2 \ \ , \ \ s_i^{(0)}=0 \\ x_i^{(t)}=x_i^{(t-1)} - \alpha \frac{v_i^{(t)}}{(1-\beta_1^t)\sqrt{\frac{s_i^{(t)}}{(1-\beta_2^t)}}+\varepsilon} \end{cases} \)

Dove valori tipici dei parametri sono \(\beta_1=0.9 \ , \ \beta_2=0.99 \ , \ \varepsilon=10^{-8}\)

Adam è frequentemente utilizzato come algoritmo di discesa del gradiente in ambito di deep learning