I neuroni sono le più importanti cellule del sistema nervoso. Le connessioni sinaptiche (o sinapsi) agiscono come porte di collegamento per il passaggio dell'informazione tra neuroni. I dendriti sono fibre minori che si ramificano a partire dal corpo cellulare del neurone (detto soma). Attraverso le sinapsi, i dendriti raccolgono input da neuroni afferenti e li propagano verso il soma. L'assone è la fibra principale che parte dal soma e si allontana da esso per portare ad altri neuroni (anche distanti) l'output.
Il passaggio delle informazioni attraverso le sinapsi avviene con processi elettro-chimici: il neurone presinaptico libera delle sostanze, chiamate neurotrasmettitori, che attraversano il breve gap sinaptico e sono captati da appositi recettori, detti canali ionici, sulla membrana del neurone postsinaptico. L'ingresso di ioni attraverso i canali ionici determina la formazione di una differenza di potenziale tra il corpo del neurone postsinaptico e l'esterno. Quando questo potenziale supera una certa soglia, detta di attivazione, si produce uno spike o impulso: il neurone propaga un breve segnale elettrico detto potenziale d'azione lungo il proprio assone: questo potenziale determina il rilascio di neurotrasmettitori dalle sinapsi dell'assone.
Il reweighting delle sinapsi, ovvero la modifica della loro efficacia di trasmissione, è direttamente collegato ai processi di apprendimento e memoria in accordo con la regola di Hebb.
Hebbian Rule: se due neuroni, tra loro connessi da una o più sinapsi, sono ripetutamente attivati simultaneamente allora le sinapsi che li connettono sono rinforzate.
Il cervello umano contiene circa 100 miliardi di neuroni, ciascuno dei quali connesso con circa altri 1000 neuroni (
Il primo modello di neurone artificiale fu progettato da McCulloch e Pitts: gli input e gli output erano binari ed erano in grado di eseguire delle computazioni logiche.
Un neurone artificiale moderno prende in ingresso
Il neurone somma i prodotti tra gli input ed i corrispettivi pesi (compresa la costante di bias) e produce un valore
Le reti neurali sono composte da gruppi di neuroni artificiali organizzati in livelli o layer. Tipicamente sono presenti un layer di input, un layer di output, ed uno o più layer intermedi o nascosti (hidden). Ogni layer contiene uno o più neuroni.
Il layer di input è costituito da un vettore di
Nel contesto delle reti neurali, un tensore è un array
Una rete neurale in cui ogni nodo di un certo layer riceve tutti gli output del layer precedente è detta densa. In questo caso si parla di layer totalmente connessi. Altre tipologie di connessioni tra layer sono possibili:
- Connessione random: fissato
$m$ , ogni nodo riceve output solamente da$m$ nodi (generalmente casuali) del precedente layer. - Connessione pooled: i nodi di un layer sono partizionati in
$k$ cluster. Il layer successivo, chiamato pooled layer, sarà formato da$k$ nodi, uno per ogni cluster. Il nodo associato al cluster$C_i$ riceverà tutti e soli gli output dei nodi del layer precedente appartenenti al cluster$C_i$ . - Connessione convolutional: i nodi di ogni layer sono visti come se fossero disposti su una griglia. Il nodo di coordinate
$(i,j)$ riceve tutti e soli gli input dei nodi del layer precedente che si trovano in una regione piccola della griglia intorno al punto$(i,j)$ (vediamo una immagine che rappresenti cosa si intende per convoluzione).
La rete neurale si presenta come un modello black-box: un osservatore esterno vede l'output prodotto dal modello a partire da un input, ma il modello non è in grado di giustificare il risultato ottenuto, ovvero non è in grado di spiegare il procedimento logico per cui si arriva a produrre quel risultato. Il termine Explanable AI indica una serie di tecniche a supporto di modelli di intelligenza artificiale per far sì che un risultato prodotto da tali modelli possa essere compreso da un essere umano. Tali tecniche sono molto importanti in ambito medico, nella guida autonoma, nella computer vision, etc.
La costruzione di una rete neurale è fondamentale per ottenere un modello di machine learning in grado di classificare o predire accuratamente. Per prima cosa bisogna definire la struttura della rete:
- Quanti hidden layer definire?
- Quanti nodi deve contenere ciascun layer?
- Come connettere i nodi di layer consecutivi?
- Quale funzione di attivazione scegliere per ogni layer?
Una volta definita la struttura, il modello deve essere addestrato su un training set al fine di trovare i valori ottimali dei pesi degli input ricevuti da ogni nodo della rete neurale in ogni layer. Per fare ciò occorre definire una funzione di costo globale
- Come deve essere organizzato il training set? Da quanti elementi?
- Quale funzione loss scegliere?
La progettazione di una rete neurale è per lo più uno studio empirico, fatto di tentativi. Le linee guida per la progettazione sono le seguenti:
- Una rete neurale con meno layer richiede tempi di addestramento ed esecuzione minori.
- Una rete neurale con più layer permette di risolvere problemi decisionali più complessi.
- Troppi layer producono un modello troppo complesso con un concreto rischio di overfitting.
- Tre layer sono spesso buoni nella pratica.
- Definire molti nodi in un hidden layer permette di identificare pattern più complessi nei dati.
- Per prevenire l'overfitting è conveniente partire da un basso numero di nodi ed aumentarlo gradualmente, monitorando le performance del modello.
Sia
La scelta della funzione di attivazione si lega al metodo scelto per ottimizzare i pesi della rete basato sulla minimizzazione della funzione loss. Il metodo di minimizzazione più popolare è quello della discesa del gradiente (gradient descent). Affinché il gradient descend lavori al meglio, la funzione di attivazione deve avere delle proprietà desiderate:
- La funzione deve essere continua e differenziabile in ogni punto (o quasi).
- La derivata della funzione non deve saturare, ovvero tendere a zero nel proprio dominio: questo potrebbe portare ad uno stallo nel processo di ricerca dei pesi ottimali.
- La derivata della funzione non deve esplodere, ovvero tendere all'infinito nel proprio dominio: questo potrebbe portare instabilità numerica nel processo di ricerca dei pesi ottimali.
La più semplice funzione di attivazione è la funzione step, chiamata anche heaviside step o unit step function. Il nodo che usa la funzione step restituisce valori binari e viene per questo chiamato percettrone. La funzione è definita come segue: $$ \text{step}(z) = \begin{cases} 1 \text{ if } z > 0 \ 0 \text{ otherwise } \end{cases} $$
La derivata della funzione unit step function
Può essere utilizzata per costruire un classificatore discriminativo binario o multi-classe. Il Perceptron è un esempio di classificatore binario, con un solo nodo nell'output layer che restituisce 1 se un oggetto è di una classe, 0 se è dell'altra. Per ottenere un classificatore discriminativo multi-classe occorre creare nell'output layer un percettrone per ogni classe da riconoscere. La rete neurale produrrà in output un vettore binario
La funzione logistica, affrontata nel capitolo sulla predizione, appartiene alla classe delle funzioni sigmoidee, aventi cioé una curva a forma di
Dal grafico osserviamo la somiglianza con la funzione unit-step. La differenza chiave sta nell'approccio della funzione tendendo allo zero: l'andamento è graduale anziché diretto. Dato un vettore di valori
Anche la tangente iperbolica appartiene alla classe delle funzioni sigmoidee ed è definita come: $$ \tanh(x) = \frac {\exp(x) - \exp(-x)} {\exp(x) + \exp(-x)} $$ La tangente iperbolica risulta legata alla funzione logistica dalla seguente relazione: $$ \tanh(x) = 2\sigma(2x) - 1 $$
In altre parole, la tangente iperbolica è una versione scalata e traslata della funzione logistica. Essa ha valori compresi tra -1 ed 1 ed è simmetrica rispetto all'asse
A differenza delle funzioni sigmoidee, la funzione softmax non opera sulla singola componente del vettore, ma sull'intero vettore. Sia
Il denominatore della funzione softmax coinvolge una somma di esponenziazioni. Quando i valori
Osserviamo che per una qualsiasi costante
La funzione ReLU prende spunto dai raddrizzatori a singola semionda (half-wave rectifiers) usati in elettronica per trasformare un segnale alternato in un segnale unidirezionale (sempre positivo o sempre negativo) facendo passare solo semionde positive. È formalmente definita come segue: $$ \text{ReLU}(x) = \max(0, x) = \begin{cases} x \text { if } x \ge 0 \ 0 \text { if } x < 0 \end{cases} $$ Rappresentabile con il seguente grafico:
La funzione ReLU non satura mai per valori di
Un miglioramento per ReLU che attenua il problema della saturazione per
La loss function, o funzione costo, è quella funzione utilizzata nel processo di learning dei pesi del modello. Essa quantifica la differenza tra le predizioni di un modello e i valori corretti di output osservati nel training set, quindi l'errore medio di predizione tra valori predetti e valori reali. I pesi ottimali sono quelli che minimizzano la funzione loss. Distinguiamo due tipologie di funzioni loss in base al problema che affronta la rete neurale:
- Regression loss nei problemi di regressione, da in output uno scalare o un vettore di valori reali
- Classification loss nei problemi di classificazione, da in output una distribuzione di probabilità, con valori che indicano la probabilità di appartenenza ad una classe.
Sia
La Huber loss penalizza di meno le differenze tra i valori reali e quelli predetti, mentre la squared error loss tende all'infinito anche con errori relativamente piccoli. La variante Huber loss protegge il processo di learning nel caso di outlier, dove la squared error segnalerebbe un errore molto grande.
Le funzioni squared error ed Huber loss funzionano per un solo dato. Nel caso volessimo calcolare l'errore su un insieme di dati su cui è stata effettuata una predizione, dovremmo affidarci ad altri metodi.
Sia
Nel caso in cui l'output è un vettore di valori
Poniamoci in un generale problema di classificazione con
Supponiamo che la rete neurale sia progettata, ad esempio attraverso una softmax, per produrre in output una distribuzione di probabilità
Supponiamo di avere un alfabeto di
Il teorema di Shannon afferma che, in un sistema di codifica ottimale, il numero medio di bit per simbolo necessari per codificare il messaggio è dato dall'entropia
Nella teoria dell'informazione, l'entropia incrociata (o cross-entropy) tra due distribuzioni di probabilità
Supponiamo di cambiare lo schema di codifica, usando una diversa distribuzione di probabilità
In generale sappiamo che
Come abbiamo già detto, la cross-entropy può essere utilizzata per definire una funzione loss. Poniamoci nel caso binario in cui le sole due classi di appartenenza sono
Utilizziamo una funzione di attivazione che dia in output delle probabilità, come la softmax. Data una tupla
Avendo fissato le notazioni
-y\times \log\hat{y} - (1-y)\times\log(1-\hat{y})
\right] = \
- \frac 1 n \sum_{i=1}^n \left[
y\times \log\hat{y} + (1-y)\times\log(1-\hat{y}) \right] $$ Tale funzione loss è chiamata binary cross-entropy loss.
Il processo di training consiste nel trovare i parametri della rete (pesi) che minimizzano l'average loss (quantificato mediante la funzione di loss scelta) su un training set di dati. L'obiettivo finale è costruire un modello che garantisca un loss medio basso su tutti i possibili input. Dato l'elevato numero di parametri di una rete neurale (specialmente se deep) il rischio di overfitting è alto. Concentriamoci inizialmente sulla minimizzazione della funzione di loss sul training set.
È possibile estendere l'idea della derivata alle funzioni multivariate. Sia
$$
\nabla_{\bar{x}} f(\bar x) = \left(
\frac {\partial f(\bar{x})}{ \partial x_1},
\frac {\partial f(\bar{x})}{ \partial x_2},
...,
\frac {\partial f(\bar{x})}{ \partial x_n}
\right)
$$
Sia
$\forall A \in \R^{m \times n}, \nabla_{\bar{x}} A x = A^T$ $\forall A \in \R^{n \times m}, \nabla_{\bar{x}} x^T A = A$ $\forall A \in \R^{n \times n}, \nabla_{\bar{x}} x^T A x = (A + A^T) x$ $\nabla_{\bar x} ||\bar{x}||^2 = \nabla_{\bar{x}} x^T x = 2x $
Similmente, per ogni matrice
Sia
Il metodo di discesa del gradiente (gradient descent) è una tecnica atta ad individuare i punti di minimo (o di massimo) di una funzione di più variabili. Nel contesto delle reti neurali la funzione da minimizzare è la funzione loss calcolata sui parametri correnti del modello.
Partendo da un valore iniziale assunto dai parametri della funzione, il metodo iterativamente cerca la direzione di massima discesa del valore della funzione e aggiorna i valori dei parametri seguendo tale direzione. La direzione di massima discesa è quella opposta al gradiente (o alla matrice jacobiana nel caso in cui il codominio della funzione è multidimensionale).
Sia
- Per
$t = 0$ inizializzare la matrice dei pesi$W_0$ con valori casuali. - Calcolare la funzione loss con i parametri
$W_t$ ed il gradiente$\nabla_{W_t} f$ . - Aggiornare la matrice dei pesi
$W_{t+1} = W_t - \eta \nabla_{W_t}f$ - Passare alla iterazione successiva
$t = t + 1$ e ripartire dal secondo step.
Il metodo viene iterato sino a quando i valori del vettore non cambiano in maniera significativa. Analogo metodo per la matrice Jacobiana. Essendo basato su una scelta greedy, non garantisce l'individuazione di minimi assoluti, per cui può convergere ad un minimo locale. Il vettore
Il parametro
Per applicare il metodo di discesa del gradiente occorre partire da un valore iniziale della funzione loss, poiché quest'ultima deve essere calcolata su una rete neurale già definita con dei pesi assegnati. Si pone quindi il problema di inizializzare i pesi della rete. Intuitivamente, se vogliamo che i nodi di un layer si comportino in maniera diversa (e riconoscano feature diverse sugli input ricevuti) occorre scegliere dei pesi diversi. Vi sono due approcci:
- Scegliere casualmente pesi in
$[-1, 1]$ seguendo una distribuzione uniforme - Scegliere casualmente secondo una distribuzione normale
Il metodo stochastic gradient descent è una variante della discesa del gradiente in cui, ad ogni iterazione del metodo, si lavora su un piccolo campione di dati del training set selezionato in maniera casuale. Tale variante risulta più veloce del gradient descent originale quando il training set è troppo grande.
Una volta calcolata la funzione loss su un vettore di output, occorre calcolare il gradiente della funzione loss rispetto ai pesi della rete in quel determinato momento. Un algoritmo efficiente per il calcolo del gradiente è l'algoritmo di backpropagation, che sfrutta il concetto di grafo computazionale.
Il termine forward propagation (o forward pass) si riferisce al calcolo e all'archiviazione ordinata di variabili intermedie della rete neurale, dall'input layer all'output layer.
Per semplicità assumiamo che l'input d'esempio sia
Un grafo computazionale è un grafo aciclico diretto (DAG) che permette di visualizzare il flusso di dati di una rete neurale. Ogni nodo può avere due forme: un nodo quadrato indica un valore (tensore di dimensione arbitraria), mentre un nodo circolare indica una operazione. La direzione indica che il nodo mittente è operando del nodo destinatario, o che il nodo destinatario è output del nodo mittente. Visualizziamo il grafo computazionale della rete neurale descritta dalla forward propagation:
La regola della catena, in inglese chain rule, è una regola di derivazione che permette di calcolare la derivata di una funzione composta da due funzioni derivabili.
Supponiamo che le funzioni
L'algoritmo di backpropagation è utilizzato nel calcolo del gradiente della funzione loss rispetto ai parametri (pesi) della rete neurale. In breve, il metodo percorre la rete neurale in verso opposto, dall'output layer all'input layer, e calcola il gradiente sfruttando la regola della catena.
L'algoritmo conserva le derivate parziali intermedie ad ogni iterazione e le ri-utilizza per calcolare altre derivate parziali andando indietro nel grafo computazionale. Ipotizziamo due funzioni
$$
\frac {\partial Z}{\partial X} = \text{prod} \left(
\frac {\partial Z}{\partial Y} \frac {\partial Y}{\partial X}
\right)
$$
Dove l'operatore prod generalizza la chain rule in base alla dimensione dei tensori. Riprendiamo l'esempio visto nella forward propagation di rete neurale ad un solo hidden layer, in cui
Sia
Partendo in ordine inverso, il primo step consiste nel calcolare il gradiente della funzione costo regolarizzata rispetto al termine di loss
Ricapitolando, data una rete neurale
- Si assegna ad
$R$ una matrice$W$ di pesi iniziali scelti casualmente. - Si addestra la rete neurale con la matrice attuale di pesi
$W$ su$T$ . - A partire dagli output prodotti dalla rete neurale su
$T$ e dagli output noti per$T$ , viene calcolata la loss media su$L$ (su tutti gli esempi del training set). - Usando l'algoritmo di backpropagation si calcola il gradiente
$\nabla_{W}L$ di L rispetto a$W$ . - Si effettua una iterazione del metodo di discesa del gradiente per aggiornare la matrice dei pesi.
- Si iterano i passi da 2 a 5 sino a quando la loss media non decresce più significativamente oppure dopo un numero fissato di iterazioni (dette anche epoche).
Con i pesi ottenuti ad ogni iterazione del learning sul training set, si testa la rete neurale sul test set e si calcola la loss. L'obiettivo è quello di far diminuire ad ogni epoca il valore della funzione loss sia sul training set che sul test set.
Lo scopo finale del processo di training è minimizzare la loss media su nuovi input. Un problema abbastanza comune è quello di costruire un modello che funziona molto bene sul training set, ma non generalizzabile e funzionante su nuovi input, ovvero il famoso problema dell'overfitting. Le deep neural network sono particolarmente suscettibili all'overfitting, tuttavia esistono dei metodi di regolarizzazione che aiutano a ridurlo.
Il metodo di discesa del gradiente potrebbe convergere ad un minimo locale che non corrisponde al minimo assoluto della funzione di loss. Nella pratica si osserva che soluzioni in cui i pesi hanno valori assoluti piccoli producono modelli migliori e più generalizzabili rispetto a soluzioni con pesi grandi. È possibile forzare il metodo del gradiente a favorire soluzioni con peso piccolo aggiungendo un termine di penalità alla loss function
Nei capitoli precedenti si è vista la tecnica di bootstrapping utilizzata nella classificazione. Analogamente, viene utilizzata una tecnica che prende il nome di dropout nelle reti neurali. Lo scopo è quello di creare un consenso sui valori ottimali dei pesi, considerando il risultato ottenuto da diverse sottoreti neurali. Ad ogni epoca si seleziona in maniera random una frazione dei nodi della rete, chiamata dropout rate, e si rimuovono. Sulla rete neurale ridotta si effettua una iterazione del metodo di discesa del gradiente. Dal momento in cui la rete neurale completa contiene più nodi rispetto a quella utilizzata durante il training, alla fine del processo di allenamento i pesi ottenuti vengono ri-scalati, ovvero moltiplicati per il dropout rate.
Nella pratica si osservano comportamenti diversi della funzione di loss sul training set e sul test set. Nel training set la funzione loss decresce durante l'addestramento. Nel test set potrebbe succedere che la funzione loss decresca sino a raggiungere un minimo e, dopo un certo numero di iterazioni, cresca (overfitting). Per evitare questo problema, si può fermare prematuramente il training non appena la loss smette di decrescere nel test set.
Il rischio che si corre con l'early stopping è quello di produrre overfitting sul test set. Per evitare ciò si può costruire un validation set indipendente dai primi due. Si effettua l'early stopping osservando l'andamento dalla funzione loss sul training set e sul validation set. Si ferma il processo quando, mentre la loss sul training set decresce, sul validation set comincia a crescere.
L'accuratezza delle reti neurali è proporzionale alla quantità di dati nel training set. Training set più grandi producono meno overfitting. È possibile arricchire un training set aggiungendo dati artificiali ottenuti applicando trasformazioni ai dati reali o inserendo del rumore. Ad esempio, se la rete neurale è addestrata per classificare immagini (es. convolutional network), si potrebbe incrementare il training set ruotando le immagini o distorcendole con del rumore.
Una rete neurale feed-forward ("rete neurale con flusso in avanti") o rete feed-forward è una rete neurale artificiale dove le connessioni tra le unità non formano cicli, differenziandosi dalle reti neurali ricorrenti. Questo tipo di rete neurale fu la prima e più semplice tra quelle messe a punto. In questa rete neurale le informazioni si muovono solo in una direzione, avanti, rispetto a nodi d'ingresso, attraverso nodi nascosti (se esistenti) fino ai nodi d'uscita. Nella rete non ci sono cicli. Le reti feed-forward non hanno memoria di input avvenuti a tempi precedenti, per cui l'output è determinato solamente dall'attuale input.
Una rete neurale convoluzionale (CNN o ConvNet dall'inglese convolutional neural network) è un tipo di rete neurale artificiale feed-forward in cui il pattern di connettività tra i neuroni è ispirato dall'organizzazione della corteccia visiva animale, i cui neuroni individuali della retina (fotorecettori) sono disposti in layer. Hanno diverse applicazioni nel riconoscimento di immagini e video, nei sistemi di raccomandazione, nell'elaborazione del linguaggio naturale e, recentemente, in bioinformatica.
Una rete neurale convoluzionale contiene uno o più layer convoluzionali. I nodi all'interno di un layer convoluzionale condividono gli stessi pesi per gli input. Generalmente si alternano i layer convoluzionali a dei layer pooled (o a volte densi) con un numero di nodi progressivamente minore.
Il primo layer coglie le informazioni che rappresentano i pixel essenziali delle immagini, ovvero i contorni. Lo schema di riconoscimento dei contorni è sempre lo stesso e non dipende dal punto in cui viene osservato un contorno (in analogia col fatto che in una CNN i nodi dello stesso layer condividono i pesi degli input). I successivi layer della retina combinano i risultati dei precedenti layer per riconoscere strutture via via più complesse (es. regioni dello stesso colore e infine volti e oggetti).
Un layer convoluzionale è formato da una griglia di nodi. Ogni nodo può essere immaginato come un filtro di dimensione
A seconda delle dimensioni della matrice di input ricevuta, la matrice di output prodotta potrebbe avere dimensioni inferiori anche con stride pari ad 1.Nell'esempio sottostante, partendo dai pixel nell'angolo in basso a destra dell'input potrebbe essere impossibile costruire un quadrato di dimensione
Un pooling layer prende in input l'output di un layer convoluzionale e produce un output più piccolo. La riduzione è effettuata mediante una funzione di pooling (es. funzione max) che aggrega i valori di una piccola regione intorno all'input. La funzione di pooling agisce su un quadrato di lato
In un'immagine a colori l'input è costituito da 3 canali (RGB). Ogni canale è formato da una matrice di valori (intensità dei pixel). In questo caso, il filtro applicato sia nel convolutional layer che nel pooling layer ha dimensione
Una Recurrent Neural Network (RNN) è una rete neurale che può contenere dei cicli. L'output di un layer può diventare l'input per un layer posto precedentemente o per se stesso. Questa disposizione è equivalente ad una rete neurale in cui uno o più layer ricorrono più volte.
I layer ricorrenti possono essere utilizzati come memoria dello stato, per ricordare i valori osservati in passato. Fornendo una sequenza temporale di valori è possibile modellare un comportamento dinamico temporale che dipende dalle informazioni agli istanti di tempo precedenti. Ciò rende le RNN adatte alla predizione di valori successivi a partire da una sequenza di eventi osservati. In breve, mentre le CNN possono processare in maniera efficiente dati tabulari, le RNN sono progettate per gestire al meglio le informazioni sequenziali. Le applicazioni tipiche risiedono nel language processing e nel riconoscimento vocale.
Definiamo l'input e l'output di un layer ricorrente come due sequenze
Lo stato nascosto $\bar{s}0$ è definito come vettore di zeri. Lo stato nascosto $\bar s_t$ al tempo $t$ si ottiene applicando una funzione di attivazione non lineare (es. sigmoid, tanh) considerando l'input al tempo $t$ e lo stato nascosto $\bar{s}{t-1}$ al tempo
In alcune applicazioni (es. la traduzione di una frase) è necessario un unico output da produrre alla fine del processo. In questo caso gli output prodotti ad ogni step dalla RNN vengono passati ad uno o più layer totalmente connessi che genereranno l'output finale.
Per gestire sequenze di lunghezza variabile si possono utilizzare due tecniche:
-
Zero padding: si fissa
$n$ come lunghezza massima della sequenza che la RNN può gestire e, se una sequenza è più corta, si aggiungono zeri fino ad ottenere una sequenza lunga$n$ . - Bucketing: raggruppa le sequenze sulla base della loro lunghezza e costruisce una RNN diversa per ogni valore di lunghezza.
È possibile combinare le due tecniche: si costruiscono diversi bucket, ciascuno dei quali è in grado di gestire sequenze di lunghezza simile in un piccolo intervallo di valori. Si assegna la sequenza in input al bucket in grado di gestire sequenze della stessa lunghezza o di lunghezza leggermente più alta. In quest'ultimo caso si effettua il padding.
Le RNN sono efficaci solo nell'apprendimento di relazioni o connessioni tra elementi vicini nella sequenza, mentre non sono in grado di apprendere relazioni tra elementi distanti. Ciò può essere problematico nell'apprendimento di un testo. Un verbo o un pronome possono essere separati da molte parole dal soggetto della frase. A livello di calcolo del gradiente, ciò si riflette in una instabilità dei valori, con una saturazione o una esplosione della derivata prima della funzione di attivazione.
La tecnica Long Short-Term Memory (LSTM) è un raffinamento delle RNN che affronta il problema delle connessioni a lunga distanza. Le proprietà di una rete LSTM possono essere riassunte da tre verbi:
- Forget, la capacità di eliminare dalla memoria informazioni che non servono più. Ad esempio, nell'analisi di un testo potremmo scartare informazioni su una frase quando termina.
- Save, la capacità di salvare determinate informazioni in memoria. Ad esempio, nell'analisi di un testo potremmo salvare solo le parole chiave di una frase quando termina.
- Focus, la capacità di focalizzarsi solo su aspetti della memoria immediatamente rilevanti. Ad esempio, nell'analisi di un testo possiamo concentrarci solo su parole che riguardano il contesto della frase attualmente analizzata.
Per realizzare tali proprietà si necessita di una memoria a lungo termine (con informazioni sulla parte di sequenza già analizzata) e di una memoria corrente (con informazioni di immediata rilevanza).
Gli stati rapresentano le due tipologie di memoria:
-
Stato nascosto: vettore
$\bar{s}_t$ al tempo$t$ che indica la memoria corrente; -
Cell state: vettore
$\bar{c}_t$ al tempo$t$ che indica la memoria a lungo termine;
IL vettore
- L'input gate
$\bar{i}_t$ determina quali parti del vettore$\bar{h}_t$ salvare nella memoria long-term; - Il forget gate
$\bar{f}_t$ che determina quali aspetti della memoria long-term mantenere; - L'output gate
$\bar{o}_t$ che indica quali parti della memoria long-term spostare nella memoria corrente.
Il primo passo per aggiornare il cell state è calcolare l'update temporaneo dello stato nascosto
Per calcolare lo stato nascosco (ovvero la memoria corrente) è necessario calcolare l'output gate
$$
\bar{o}t = \sigma(W_o \bar{s}{t-1} + U_o \bar{x}_t + \bar{b}_o)
$$
E aggiornare la memoria come segue
$$
\bar{s}_t = \tanh(\bar{c}_t \circ \bar{o}_t)
$$
Dove
L'output è calcolato allo stesso modo di qualsiasi RNN:
$$
\bar{y}_t = g(V\bar{s}_t + \bar{d})
$$
Dove