Reti Neurali Ricorrenti, Spiegate e Visualizzate dalle Basi
Recurrent Neural Networks, Explained and Visualized from the Basics
Con un’applicazione alla traduzione automatica
Le Reti Neurali Ricorrenti (RNN) sono reti neurali che possono operare in sequenza. Anche se non sono più popolari come lo erano solo pochi anni fa, rappresentano un importante sviluppo nella progressione del deep learning e sono un’estensione naturale delle reti feedforward.
In questo post, copriremo i seguenti argomenti:
- Il passaggio dalle reti feedforward alle reti ricorrenti
- Reti ricorrenti multistrato
- Reti LSTM
- Output sequenziale (‘output di testo’)
- Bidirezionalità
- Generazione autoregressiva
- Un’applicazione alla traduzione automatica (una comprensione a livello alto dell’architettura del modello di Google Translate del 2016)
Lo scopo di questo post non è solo spiegare come funzionano le RNN (ci sono molti post che lo fanno), ma esplorare le loro scelte di progettazione e la logica intuitiva a livello alto con l’aiuto di illustrazioni. Spero che questo articolo fornisca un valore unico non solo alla vostra comprensione di questo particolare argomento tecnico, ma anche alla flessibilità del design del deep learning in generale.
La progettazione della Rete Neurale Ricorrente (1985) si basa su due osservazioni su come un modello ideale, come una persona che legge il testo, elaborerebbe le informazioni sequenziali:
- L’IA si mangerà da sola? Questo documento sull’IA introduce un fenomeno chiamato collasso del modello che si riferisce a un processo di apprendimento degenerativo in cui i modelli iniziano a dimenticare gli eventi improbabili nel tempo.
- Sbloccare il Potenziale dell’Intelligenza Artificiale con MINILLM Una Profonda Immersione nella Distillazione della Conoscenza dai Modelli Linguistici Più Grandi ai loro Corrispettivi Più Piccoli.
- 50+ Nuovi Strumenti AI All’avanguardia (Luglio 2023)
- Dovrebbe tenere traccia delle informazioni ‘apprese’ fino ad ora in modo da poter relazionare le nuove informazioni alle informazioni precedentemente viste. Per capire la frase “La volpe marrone veloce ha saltato sopra il cane pigro”, devo tenere traccia delle parole ‘veloce’ e ‘marrone’ per capire in seguito che queste si applicano alla parola ‘volpe’. Se non conservo alcuna di queste informazioni nella mia ‘memoria a breve termine’, per così dire, non comprenderò il significato sequenziale delle informazioni. Quando finisco la frase su ‘cane pigro’, leggo questo sostantivo in relazione alla ‘volpe marrone veloce’ che ho incontrato in precedenza.
- Anche se le informazioni successive verranno sempre lette nel contesto delle informazioni precedenti, vogliamo elaborare ogni parola (token) in modo simile indipendentemente dalla sua posizione. Non dovremmo trasformare sistematicamente la parola in terza posizione in modo diverso dalla parola in prima posizione, anche se potremmo leggere la prima alla luce della seconda. Notate che l’approccio proposto in precedenza, in cui gli embedding per tutti i token sono impilati uno accanto all’altro e presentati contemporaneamente al modello, non possiede questa proprietà, poiché non c’è garanzia che l’embedding corrispondente alla prima parola sia letto con le stesse regole dell’embedding corrispondente alla terza. Questa proprietà generale è anche nota come invarianza posizionale.
Una Rete Neurale Ricorrente è composta, al suo nucleo, da strati ricorrenti. Uno strato ricorrente, come uno strato feed-forward, è un insieme di trasformazioni matematiche apprendibili. Si scopre che possiamo capire approssimativamente gli strati ricorrenti in termini di Perceptron Multistrato.
La ‘memoria a breve termine’ di uno strato ricorrente è denominata stato nascosto. Questo è un vettore, solo un elenco di numeri, che comunica informazioni cruciali su ciò che la rete ha appreso fino ad ora. Quindi, per ogni token nel testo standardizzato, incorporiamo le nuove informazioni nello stato nascosto. Facciamo questo usando due MLP: uno MLP trasforma l’embedding corrente, e l’altro trasforma lo stato nascosto corrente. Le uscite di questi due MLP sono sommate insieme per formare lo stato nascosto aggiornato, o la ‘memoria a breve termine aggiornata’.
Ripetiamo quindi questo per il token successivo: l’embedding viene passato a un MLP e lo stato nascosto aggiornato viene passato a un altro; le uscite di entrambi vengono sommate. Questo viene ripetuto per ogni token nella sequenza: un MLP trasforma l’input in una forma pronta per l’incorporazione nella memoria a breve termine (stato nascosto), mentre un altro prepara la memoria a breve termine (stato nascosto) per l’aggiornamento. Ciò soddisfa il nostro primo requisito: vogliamo leggere le nuove informazioni nel contesto delle vecchie informazioni. Inoltre, entrambi questi MLP sono gli stessi in ogni intervallo di tempo. Vale a dire, usiamo le stesse regole per come unire lo stato nascosto corrente con le nuove informazioni. Ciò soddisfa il nostro secondo requisito: dobbiamo usare le stesse regole per ogni intervallo di tempo.
Entrambi questi MLP sono generalmente implementati come uno strato solo: cioè, è solo una grande pila di regressioni logistiche. Ad esempio, la figura seguente mostra come potrebbe apparire l’architettura per MLP A, assumendo che ogni embedding sia composto da otto numeri e che lo stato nascosto consista anche di otto numeri. Questa è una trasformazione semplice ma efficace per mappare il vettore di embedding in un vettore adatto per la fusione con lo stato nascosto.
Quando incorporiamo l’ultimo token nello stato nascosto, il compito del layer ricorrente è finito. Ha prodotto un vettore, una lista di numeri, che rappresenta le informazioni accumulate leggendo una sequenza di token in modo sequenziale. Possiamo quindi passare questo vettore attraverso un terzo MLP, che apprende la relazione tra lo “stato corrente della memoria” e il compito di previsione (in questo caso, se il prezzo delle azioni è sceso o salito).
Le meccaniche per l’aggiornamento dei pesi sono troppo complesse per essere discusse in dettaglio in questo libro, ma sono simili alla logica dell’algoritmo di backpropagation. La complicazione aggiuntiva consiste nel tracciare l’effetto composto di ciascun parametro che agisce ripetutamente sul proprio output (da qui il carattere “ricorrente” del modello), che può essere affrontato matematicamente con un algoritmo modificato denominato “backpropagation attraverso il tempo”.
La Rete Neurale Ricorrente è un modo abbastanza intuitivo di affrontare la modellizzazione dei dati sequenziali. È un altro caso di disposizioni complesse di modelli di regressione lineare, ma è abbastanza potente: ci consente di affrontare sistematicamente problemi di apprendimento sequenziale difficili come il linguaggio.
Per convenienza di diagrammi e semplicità, spesso vedremo il layer ricorrente rappresentato semplicemente come un blocco, anziché come una cella espansa che agisce in modo sequenziale su una serie di input.
Questo è il tipo più semplice di Rete Neurale Ricorrente per il testo: i token di input standardizzati vengono mappati in embedding, che vengono alimentati in un layer ricorrente; l’output del layer ricorrente (lo “stato di memoria più recente”) è elaborato da un MLP e mappato su un target previsto.
Varianti complesse di Reti Ricorrenti
I layer ricorrenti consentono alle reti di affrontare problemi sequenziali. Tuttavia, ci sono alcuni problemi con il nostro attuale modello di Rete Neurale Ricorrente. Per capire come le reti neurali ricorrenti vengono utilizzate in applicazioni reali per modellare problemi difficili, dobbiamo aggiungere alcune funzionalità aggiuntive.
Uno di questi problemi è la mancanza di profondità: un layer ricorrente passa semplicemente una volta sul testo e quindi ottiene solo una lettura di livello superficiale e sommaria del contenuto. Consideriamo la frase “La felicità non è un ideale della ragione, ma dell’immaginazione”, del filosofo Immanuel Kant. Per comprendere questa frase nella sua vera profondità, non possiamo semplicemente passare una volta sulle parole. Invece, leggiamo le parole e poi – questo è il passaggio critico – leggiamo i nostri pensieri. Valutiamo se la nostra interpretazione immediata della frase ha senso e forse la modificiamo per conferirle un senso più profondo. Potremmo persino leggere i nostri pensieri sui nostri pensieri. Tutto ciò accade molto rapidamente e spesso senza la nostra consapevolezza, ma è un processo che ci consente di estrarre più livelli di profondità dal contenuto del testo.
Corrispondentemente, possiamo aggiungere più layer ricorrenti per aumentare la profondità della comprensione. Mentre il primo layer ricorrente coglie informazioni a livello superficiale dal testo, il secondo layer ricorrente legge i “pensieri” del primo layer ricorrente. Lo “stato di memoria più recente” a doppia informazione del secondo layer viene quindi utilizzato come input per l’MLP che prende la decisione finale. In alternativa, potremmo aggiungere più di due layer ricorrenti.
Per essere specifici su come funziona questo meccanismo di impilamento, consultare la figura seguente: anziché semplicemente passare ogni stato nascosto per l’aggiornamento, diamo anche questo stato di input al successivo layer ricorrente. Mentre il primo input al primo layer ricorrente è un embedding, il primo input al secondo layer ricorrente è “ciò che il primo layer ricorrente ha pensato del primo input”.
Quasi tutte le Reti Neurali Ricorrenti impiegate per problemi reali di modellizzazione del linguaggio utilizzano stack di layer ricorrenti anziché un singolo layer ricorrente a causa dell’aumento della profondità della comprensione e del ragionamento linguistico. Per grandi stack di layer ricorrenti, spesso usiamo connessioni residue ricorrenti. Ricordiamo il concetto di una connessione residua, in cui una versione precedente di informazioni viene aggiunta a una versione successiva di informazioni. Allo stesso modo, possiamo inserire connessioni residue tra gli stati nascosti di ciascun layer in modo che i layer possano fare riferimento a varie “profondità di pensiero”.
Mentre i modelli ricorrenti possono funzionare bene con frasi brevi e semplici come “le autorità annunciano la recessione”, i documenti finanziari e gli articoli di notizie sono spesso molto più lunghi di poche parole. Per sequenze più lunghe, i modelli ricorrenti standard incontrano un problema persistente di perdita di memoria a lungo termine: spesso il segnale o l’importanza delle parole all’inizio della sequenza sono diluiti e oscurati dalle parole successive. Poiché ogni passo aggiunge la propria influenza allo stato nascosto, distrugge parzialmente un po’ delle informazioni precedenti. Alla fine, quindi, la maggior parte delle informazioni all’inizio diventa irrecuperabile. Il modello ricorrente ha una finestra ristretta di attenzione/focus di memoria. Se vogliamo creare un modello che possa esaminare e analizzare documenti con una comprensione e profondità comparabili a quelle di un essere umano, dobbiamo affrontare questo problema di memoria.
Il layer Long Short-Term Memory (LSTM) (1997) è un layer ricorrente più complesso. La sua meccanica specifica è troppo complessa per essere discussa accuratamente o completamente in questo libro, ma possiamo capirla grossolanamente come un tentativo di separare la “memoria a lungo termine” dalla “memoria a breve termine”. Entrambi i componenti sono rilevanti quando si “legge” una sequenza: abbiamo bisogno della memoria a lungo termine per tenere traccia delle informazioni nel tempo, ma anche della memoria a breve termine per concentrarsi su informazioni specifiche e localizzate. Pertanto, invece di memorizzare un singolo stato nascosto, il layer LSTM utilizza anche uno “stato di cella” (rappresentante la “memoria a lungo termine”).
Ad ogni passo, l’input viene incorporato nello stato nascosto allo stesso modo del layer ricorrente standard. Successivamente, però, seguono tre passaggi:
- Pulizia della memoria a lungo termine. La memoria a lungo termine è preziosa; contiene informazioni che manterremo nel tempo. Lo stato corrente della memoria a breve termine viene utilizzato per determinare quale parte della memoria a lungo termine non è più necessaria e “la taglia” per fare spazio a nuove informazioni.
- Aggiornamento della memoria a lungo termine. Ora che lo spazio è stato liberato nella memoria a lungo termine, la memoria a breve termine viene utilizzata per aggiornare (aggiungere) la memoria a lungo termine, impegnando così nuove informazioni nella memoria a lungo termine.
- Informazione della memoria a breve termine. A questo punto, lo stato della memoria a lungo termine è completamente aggiornato rispetto al passo corrente. Poiché vogliamo che la memoria a lungo termine informi la funzione della memoria a breve termine, la memoria a lungo termine aiuta a tagliare e modificare la memoria a breve termine. Idealmente, la memoria a lungo termine ha una maggiore supervisione su ciò che è importante e ciò che non è importante da mantenere nella memoria a breve termine.
Pertanto, la memoria a breve termine e la memoria a lungo termine – che, ricordiamo, sono entrambe elenchi di numeri – interagiscono tra loro e con l’input ad ogni passaggio per leggere la sequenza di input in modo che permette una lettura attenta senza dimenticanze catastrofiche. Questo processo a tre fasi è rappresentato graficamente nella figura seguente. Un +
indica l’aggiunta di informazioni, mentre la x
indica la rimozione o la pulizia delle informazioni. (L’addizione e la moltiplicazione sono le operazioni matematiche utilizzate per implementare queste idee nella pratica. Diciamo che il valore corrente dello stato nascosto è 10. Se lo moltiplico per 0,1, diventa 1 – quindi ho “ridotto” le informazioni nello stato nascosto.)
Utilizzando pile di LSTM con connessioni residue, possiamo costruire potenti modelli di interpretazione del linguaggio in grado di leggere (“comprendere”, se vogliamo) paragrafi e persino interi articoli di testo. Oltre ad essere utilizzati nell’analisi finanziaria per esaminare grandi volumi di report finanziari e di notizie, tali modelli possono anche essere utilizzati per prevedere individui potenzialmente suicidi o terroristici dai loro testi di post sui social media e messaggi, per consigliare ai clienti nuovi prodotti che sono probabilmente acquistare in base alle loro recensioni di prodotti precedenti, e per rilevare commenti e post tossici o molesti su piattaforme online.
Tali applicazioni ci costringono a pensare criticamente alle loro implicazioni filosofiche. Il governo ha un forte interesse nel rilevare potenziali terroristi, e i tiratori dietro le recenti stragi sono spesso stati mostrati come avere un preoccupante record pubblico sui social media – ma la tragedia è stata che non sono stati trovati in un mare di informazioni su Internet. I modelli linguistici come i modelli ricorrenti, come hai visto tu stesso, funzionano puramente matematicamente: cercano di trovare i pesi e i bias che meglio modellano la relazione tra il testo di input e il testo di output. Ma per quanto questi pesi e bias significhino qualcosa, possono “leggere” le informazioni in modo efficace e estremamente rapido – molto più velocemente e forse anche più efficacemente dei lettori umani. Questi modelli possono consentire al governo di rilevare, monitorare e fermare potenziali terroristi prima che agiscano. Naturalmente, ciò può comportare il costo della privacy. Inoltre, abbiamo visto come i modelli linguistici – pur capaci di rintracciare meccanicamente modelli e relazioni all’interno dei dati – siano realmente solo algoritmi matematici in grado di commettere errori. Come dovrebbe essere riconciliata l’etichettatura errata di un individuo come potenziale terrorista da parte di un modello?
Le piattaforme di social media, sotto pressione da parte degli utenti e del governo, vogliono ridurre il bullismo e la tossicità sui forum online. Questo potrebbe sembrare un compito ingannevolmente semplice, concettualmente parlando: etichettare un corpus di commenti sui social media come tossici o non tossici, poi addestrare un modello linguistico a predire la tossicità di un particolare campione di testo. Il problema immediato è che il discorso digitale è incredibilmente sfidante a causa della dipendenza da riferimenti in rapida evoluzione (meme), inside joke, sarcasmo ben celato e conoscenza contestuale di base. Il problema filosofico più interessante, tuttavia, è se si possa e si debba davvero addestrare un modello matematico (un modello “oggettivo”) a predire un obiettivo apparentemente “soggettivo” come la tossicità. Dopotutto, ciò che è tossico per un individuo potrebbe non esserlo per un altro.
Man mano che ci addentriamo in modelli che lavorano con forme di dati sempre più personali – il linguaggio è il mezzo attraverso il quale comunichiamo e assorbiamo quasi tutta la nostra conoscenza – troviamo una significativa importanza nel pensare e lavorare per rispondere a queste domande. Se sei interessato a questa linea di ricerca, potresti voler approfondire l’allineamento, l’apprendimento della giuria, l’AI costituzionale, l’RLHF e il pluralismo dei valori.
Traduzione automatica neurale
Concetti: modelli ricorrenti multi-output, bidirezionalità, attenzione
La traduzione automatica è una tecnologia incredibile: consente a individui che in precedenza non potevano comunicare affatto senza significative difficoltà di dialogare liberamente. Un parlante hindi può leggere un sito web scritto in spagnolo con un clic del pulsante “Traduci questa pagina”, e viceversa. Un parlante inglese che guarda un film russo può abilitare le trascrizioni tradotte in tempo reale. Un turista cinese in Francia può ordinare cibo ottenendo una traduzione basata su foto del menu. La traduzione automatica, in modo molto letterale, fonde insieme lingue e culture.
Prima della diffusione dell’apprendimento profondo, l’approccio dominante alla traduzione automatica si basava su tabelle di lookup. Ad esempio, in cinese, “io” si traduce in “我”, “guidare” si traduce in “开”, e “auto” si traduce in “车”. Quindi, “Io guido l’auto” sarebbe tradotto parola per parola come “我开车”. Tuttavia, qualsiasi parlante bilingue conosce le debolezze di questo sistema. Molte parole che sono scritte allo stesso modo hanno significati diversi. Una lingua può avere molte parole che vengono tradotte in un’altra lingua come una sola parola. Inoltre, diverse lingue hanno diverse strutture grammaticali, quindi le parole tradotte stesse dovrebbero essere riorganizzate. Gli articoli in inglese hanno molteplici traduzioni dipendenti dal contesto in lingue con genere come lo spagnolo e il francese. Molti tentativi di conciliare questi problemi con soluzioni linguistiche intelligenti sono stati ideati, ma sono limitati nell’efficacia per frasi brevi e semplici.
L’apprendimento profondo, d’altra parte, ci offre la possibilità di costruire modelli che comprendono più profondamente il linguaggio, forse anche più vicino a come gli esseri umani comprendono il linguaggio, e quindi svolgono in modo più efficace il compito importante della traduzione. In questa sezione, presenteremo molte altre idee dalla modellizzazione profonda del linguaggio e culmineremo in una esplorazione tecnica di come funziona Google Translate.
Modelli ricorrenti a output di testo
Attualmente, l’ostacolo più evidente per la costruzione di un modello ricorrente valido è l’incapacità di produrre testo in output. I modelli ricorrenti precedentemente discussi potevano “leggere”, ma non “scrivere”: l’output, invece, era un singolo numero (o una collezione di numeri, un vettore). Per affrontare questo problema, dobbiamo dotare i modelli linguistici della capacità di produrre intere serie di testo.
Fortunatamente, non dobbiamo fare molto lavoro. Ricorda il concetto di impilamento di layer ricorrenti introdotto in precedenza: anziché raccogliere solo lo “stato di memoria” dopo che il layer ricorrente ha eseguito l’intera sequenza, raccogliamo lo “stato di memoria” ad ogni timestep. Pertanto, per produrre una sequenza, possiamo raccogliere l’output di uno stato di memoria ad ogni timestep. Quindi, passiamo ogni stato di memoria in un MLP designato che prevede quale parola del vocabolario di output prevedere dato lo stato di memoria (contrassegnato come “MLP C”). La parola con la probabilità predetta più alta viene selezionata come output.
Per essere assolutamente chiari su come ogni stato di memoria venga trasformato in una previsione di output, consideriamo la seguente progressione di figure.
Nella prima figura, il primo stato nascosto in output (cioè lo stato nascosto derivato dopo che il layer ha letto la prima parola, “il”) viene passato in MLP C. MLP C restituisce una distribuzione di probabilità sul vocabolario di output; cioè, dà a ogni parola nel vocabolario di output una probabilità che indica quanto è probabile che quella parola sia scelta come traduzione in quel momento. Questa è una rete feedforward: essenzialmente stiamo eseguendo una regressione logistica sullo stato nascosto per determinare la probabilità di una data parola. Idealmente, la parola con la probabilità più alta dovrebbe essere “les”, poiché questa è la traduzione francese di “il”.
Lo stato nascosto successivo, derivato dopo che il livello ricorrente ha letto sia ‘the’ che ‘machines’, viene nuovamente passato a MLP C. Questa volta, la parola con la probabilità più alta dovrebbe essere idealmente ‘machine’ (questa è la traduzione plurale di ‘machines’ in francese).
La parola più probabile selezionata nell’ultimo passaggio dovrebbe essere ‘gagnent’, che è la traduzione per ‘win’ nel suo particolare tempo. Il modello dovrebbe selezionare ‘gagnent’ e non ‘gagner’, o qualche altro tempo della parola, in base alle informazioni precedenti che ha letto. Qui risplendono i vantaggi dell’utilizzo di un modello di deep learning per la traduzione: la capacità di comprendere le regole grammaticali che si manifestano in tutta la frase.
In termini pratici, spesso vogliamo impilare più livelli ricorrenti insieme anziché solo un singolo livello ricorrente. Ciò ci consente di sviluppare più livelli di comprensione, prima ‘comprendendo’ ciò che significa il testo di input, quindi riequilibrando il ‘significato’ del testo di input in termini di lingua di output.
Bidirezionalità
Si noti che il livello ricorrente procede in modo sequenziale. Quando legge il testo “the machines win”, legge prima “the”, poi “machines”, poi “win”. Mentre l’ultima parola, “win”, viene letta in contesto delle parole precedenti “the” e “machines”, non vale il contrario: la prima parola, “the”, non viene letta in contesto delle parole successive “machines” e “win”. Questo è un problema, perché la lingua spesso viene parlata in previsione di ciò che diremo successivamente. In una lingua con genere come il francese, un articolo come “the” può assumere molte forme diverse – “la” per un oggetto femminile, “le” per un oggetto maschile e “les” per oggetti plurali. Non sappiamo quale versione di “the” tradurre. Naturalmente, una volta che leggiamo il resto della frase – “the machines” – sappiamo che l’oggetto è plurale e che dovremmo usare “les”. Questo è un caso in cui le parti precedenti di un testo sono informate dalle parti successive. In generale, quando rileggiamo una frase – che spesso facciamo istintivamente senza rendercene conto – stiamo leggendo l’inizio in contesto dell’inizio. Anche se la lingua viene letta in sequenza, spesso deve essere interpretata ‘fuori sequenza’ (vale a dire, non strettamente unidirezionalmente dall’inizio alla fine).
Per affrontare questo problema, possiamo utilizzare la bidirezionalità – una semplice modifica ai modelli ricorrenti che consente ai livelli di ‘leggere’ sia in avanti che all’indietro. Un livello ricorrente bidirezionale è in realtà due diversi livelli ricorrenti. Un livello legge in avanti nel tempo, mentre l’altro legge all’indietro. Dopo che entrambi hanno finito di leggere, le loro uscite ad ogni passaggio temporale vengono sommate insieme.
La bidirezionalità consente al modello di leggere il testo in modo tale che il passato venga letto nel contesto del futuro, oltre a leggere il futuro nel contesto del passato (la funzionalità predefinita di un livello ricorrente). Si noti che l’output del livello ricorrente bidirezionale ad ogni passaggio temporale viene informato da tutta la sequenza anziché solo tutti i passaggi temporali precedenti ad esso. Ad esempio, in una sequenza a 10 passaggi temporali, il passaggio temporale al t = 3 è informato da uno ‘stato di memoria’ che ha già letto attraverso la sequenza [t = 0] → [t = 1] → [t = 2] → [t = 3] così come un altro ‘stato di memoria’ che ha già letto attraverso la sequenza [t = 9] → [t = 8] → [t = 7] → [t = 6] → [t = 5] → [t = 4] → [t = 3].
Questa semplice modifica consente una comprensione del linguaggio significativamente più profonda.
Generazione Autoregressiva
Il nostro modello di lavoro corrente per un modello di traduzione è un grande stack di livelli ricorrenti (bidirezionali). Tuttavia, c’è un problema: quando traduciamo un testo A in un altro testo B, non scriviamo solo B in riferimento ad A, ma anche in riferimento a se stesso.
Non possiamo tradurre direttamente frasi complesse dal russo “Грузовик внезапно остановился потому что дорогу переходила курица” all’inglese “The truck suddenly stopped because a chicken was crossing the road” leggendo direttamente il russo: se traducessimo la parola per parola in ordine, otterremmo “Truck suddenly stopped because road was crossed by chicken”. In russo, l’oggetto viene posto dopo il sostantivo, ma mantenere questa forma in inglese è sicuramente leggibile ma non fluido né “ottimale”, per così dire. L’idea chiave è questa: per ottenere una traduzione comprensibile e utilizzabile, non solo dobbiamo assicurarci che la traduzione sia fedele al testo originale ma anche “fedele a se stessa” (auto-coerente).
Per fare ciò, abbiamo bisogno di una diversa generazione di testo chiamata generazione autoregressiva. Ciò consente al modello di tradurre ogni parola non solo in relazione al testo originale, ma anche a ciò che il modello ha già tradotto. La generazione autoregressiva è il paradigma dominante non solo per i modelli di traduzione neurale ma anche per tutti i tipi di modelli di generazione di testo moderni, tra cui chatbot avanzati e generatori di contenuti.
Iniziamo con un modello di “codificatore”. Il modello di codificatore, in questo caso, può essere rappresentato come uno stack di livelli ricorrenti. Il codificatore legge la sequenza di input e deriva un singolo output, la rappresentazione codificata. Questo singolo elenco di numeri rappresenta l'”essenza” della sequenza di testo di input in forma quantitativa, il suo “vero significato universale”, per così dire. L’obiettivo del codificatore è quello di distillare la sequenza di input in questo pacchetto fondamentale di significato.
Una volta ottenuta questa rappresentazione codificata, iniziamo il compito di decodifica. Il decodificatore è strutturato in modo simile al codificatore: possiamo pensarlo come un altro stack di livelli ricorrenti che accetta una sequenza e produce un output. In questo caso, il decodificatore accetta la rappresentazione codificata (cioè l’output del codificatore) e un “token di inizio” speciale (denotato </s>). Il token di inizio rappresenta l’inizio di una frase. Il compito del decodificatore è predire la prossima parola nella frase data; in questo caso, viene dato un “urto di zero parole” e quindi deve predire la prima parola. In questo caso, non c’è contenuto tradotto precedente, quindi il decodificatore si basa interamente sulla rappresentazione codificata: predice la prima parola, “The”.
Segue il passaggio autoregressivo chiave: prendiamo le uscite precedenti del decodificatore e le riportiamo nel decodificatore. Ora abbiamo una “singola parola di frase” (il token di inizio seguito dalla parola “The”). Entrambi i token vengono passati al decodificatore, insieme alla rappresentazione codificata – la stessa di prima, prodotta dal codificatore – e ora il decodificatore predice la prossima parola, “truck”.
Questo token viene quindi trattato come un altro input. Qui, possiamo realizzare più chiaramente perché la generazione autoregressiva è un utile impalcatura algoritmica per la generazione di testo: sapere che la frase di lavoro corrente è “The truck” limita il modo in cui possiamo completarla. In questo caso, la prossima parola sarà probabilmente un verbo o un avverbio, che “sappiamo” essere una struttura grammaticale. D’altra parte, se il decodificatore avesse accesso solo al testo russo originale, non sarebbe in grado di limitare efficacemente l’insieme di possibilità. In questo caso, il decodificatore è in grado di fare riferimento sia a ciò che è stato precedentemente tradotto che al significato della frase russa originale per predire correttamente la prossima parola come “suddenly”.
Questo processo di generazione autoregressivo continua:
Infine, per terminare una frase, il modello di decodifica prevede un designato “token finale” (indicato come </e>). In questo caso, il decodificatore avrà “abbinato” la frase tradotta corrente alla rappresentazione codificata per determinare se la traduzione è soddisfacente e interrompere il processo di generazione della frase.
Google Translate del 2016
Adesso, abbiamo coperto molta strada. Ora, abbiamo la maggior parte dei pezzi necessari per sviluppare una comprensione piuttosto approfondita di come il modello per Google Translate è stato progettato. Non c’è bisogno di dire molto sull’importanza di un modello come quello fornito da Google Translate: anche se approssimativo, un sistema di traduzione automatica neurale accurato e accessibile rompe molte barriere linguistiche. Per noi, questo modello particolare aiuta a unificare molti dei concetti che abbiamo discusso in un’applicazione coerente.
Questa informazione è tratta dal paper di traduzione automatica neurale di Google del 2016, che ha introdotto il sistema di apprendimento profondo di Google per la traduzione automatica. Sebbene sia quasi certo che il modello in uso sia cambiato nei molti anni trascorsi da allora, questo sistema fornisce comunque uno studio di caso interessante sui sistemi di traduzione automatica neurale. Per chiarezza, ci riferiremo a questo sistema come “Google Translate”, riconoscendo che probabilmente non è attuale.
Google Translate utilizza un modello autoregressivo di codifica-decodifica. In altre parole, il modello consiste in una componente di codifica e una componente di decodifica; il decodificatore è autoregressivo (ricorda quanto detto in precedenza: accetta le uscite generate in precedenza come input, oltre ad altre informazioni, in questo caso l’output del codificatore).
Il codificatore è una pila di sette strati di memoria a breve termine (LSTM). Il primo strato è bidirezionale (ci sono quindi tecnicamente 8 strati, poiché uno strato bidirezionale “conta come due”), il che gli consente di catturare importanti schemi nel testo di input in entrambe le direzioni (figura inferiore, sinistra). Inoltre, l’architettura utilizza connessioni residue tra ogni strato (figura inferiore, destra). Ricorda dalla precedente discussione che le connessioni residue nelle reti neurali ricorrenti possono essere implementate aggiungendo l’input ad un layer ricorrente all’output ad ogni passaggio di tempo, in modo che il layer ricorrente finisca per apprendere la differenza ottimale da applicare all’input.
Il decodificatore è anche una pila di otto strati LSTM. Accetta la sequenza generata in precedenza in modo autoregressivo, partendo dal token di inizio </s>
. L’architettura della traduzione automatica neurale di Google, tuttavia, utilizza sia la generazione autoregressiva che l’attenzione.
Le punteggi di attenzione vengono calcolati per ciascuna delle parole nel testo originale (rappresentate da stati nascosti nel codificatore, che trasformano iterativamente il testo ma lo rappresentano ancora posizionalmente). Possiamo pensare all’attenzione come un dialogo tra il decodificatore e il codificatore. Il decodificatore dice: “Ho generato [frase] finora, voglio prevedere la prossima parola tradotta. Quali parole nella frase originale sono più rilevanti per questa prossima parola tradotta?” Il codificatore risponde: “Lascia che guardi a cosa stai pensando e lo abbinerò a ciò che ho imparato su ogni parola dell’input originale… ah, dovresti prestare attenzione a [parola A] ma non così tanto a [parola B] e [parola C], sono meno rilevanti per prevedere la prossima parola particolare.” Il decodificatore ringrazia il codificatore: “Penserò a queste informazioni per determinare come generare, in modo da concentrarmi effettivamente su [parola A]”. Le informazioni sull’attenzione sono inviate ad ogni strato LSTM, in modo che queste informazioni sull’attenzione siano note a tutti i livelli di generazione.
Questo rappresenta la maggior parte del sistema di traduzione automatica neurale di Google. Il modello è addestrato su un grande dataset di compiti di traduzione: dato l’input in inglese, ad esempio, prevedere l’output in spagnolo. Il modello apprende i modi ottimali di lettura (cioè i parametri nel codificatore), i modi ottimali di attenzione all’input (cioè il calcolo dell’attenzione) e i modi ottimali di relazionare l’input attenzionato ad un output in spagnolo (cioè i parametri nel decodificatore).
Lavori successivi hanno ampliato i sistemi di traduzione automatica neurale alla capacità multilingue, in cui un singolo modello può essere utilizzato per tradurre tra molteplici coppie di lingue. Questo non è solo necessario da un punto di vista pratico – sarebbe irrealizzabile addestrare e memorizzare un modello per ogni coppia di lingue – ma ha anche dimostrato di migliorare la traduzione tra qualsiasi coppia di lingue. Inoltre, il paper GNMT fornisce dettagli sul processo di addestramento – si tratta di un’architettura molto profonda che è limitata dall’hardware – e sulla distribuzione effettiva – i modelli grandi sono lenti non solo da addestrare, ma anche per ottenere previsioni, ma gli utenti di Google Translate non vogliono dover attendere più di pochi secondi per tradurre del testo.
Sebbene il sistema GNMT sia senz’altro un punto di riferimento nell’ambito della comprensione del linguaggio computazionale, solo pochi anni dopo un nuovo approccio, in alcuni modi radicalmente semplificato, avrebbe completamente rivoluzionato la modellizzazione del linguaggio – e avrebbe eliminato del tutto gli strati ricorrenti che abbiamo faticosamente cercato di comprendere. Restate sintonizzati per un secondo post sui Transformers!
Grazie per aver letto!
In questo post, abbiamo effettuato un’approfondita indagine delle reti neurali ricorrenti: la logica di progettazione, le funzionalità più complesse e le applicazioni.
Alcuni punti chiave:
- Le RNN sono un’estensione naturale delle reti feedforward e possono essere utilizzate per la traduzione automatica. Le RNN sono progettate per tenere traccia delle informazioni apprese finora e relazionare le nuove informazioni alle informazioni precedentemente viste, simili a come gli esseri umani elaborano le informazioni sequenziali.
- Le RNN utilizzano strati ricorrenti che hanno uno stato nascosto che rappresenta la memoria a breve termine.
- Gli strati ricorrenti possono essere impilati per aumentare la profondità di comprensione e ragionamento nella rete.
- Le reti Long Short-Term Memory (LSTM) sono un tipo più complesso di strato ricorrente che separa la memoria a lungo termine dalla memoria a breve termine. Le LSTM hanno meccanismi per cancellare, aggiornare e informare sia la memoria a lungo termine che quella a breve termine.
- Le RNN hanno applicazioni in vari campi come l’analisi finanziaria, l’analisi dei social media, i sistemi di raccomandazione e la traduzione di lingue.
- L’uso delle RNN in applicazioni reali solleva questioni filosofiche ed etiche riguardanti la privacy, gli errori del modello e la soggettività nell’etichettatura di contenuti tossici o dannosi.
- La traduzione automatica neurale è una potente applicazione delle RNN che consente la traduzione tra lingue diverse, facilitando la comunicazione e lo scambio culturale.
Tutte le foto sono dell’autore.