Lo stato attuale dell’apprendimento continuo nell’AI

L'attuale stato dell'apprendimento continuo nell'IA

Perché ChatGPT è addestrato solo fino al 2021?

Immagine generata dall'autore utilizzando DALL-E 3

Conoscenze preliminari:

Un paio di anni fa ho imparato le basi dell’apprendimento profondo attraverso video di StatQuest, blog di NLP di Lena Voita e libri come “Deep Learning for Coders” e “Talking Nets”. Ora vorrei capire lo stato attuale dell’apprendimento continuo nell’apprendimento profondo. Ho scoperto che non ci sono molte informazioni disponibili che riassumono questo argomento in termini più semplici e richiede di sfogliare paper di ricerca degli esperti. Pertanto, questo articolo è destinato ai lettori che hanno una conoscenza di base dell’argomento ma trovano la ricerca difficile da leggere e potrebbero non essere esperti. Si concentra sugli assistenti virtuali, quindi conoscere le fasi di addestramento di chatGPT è anche utile.

Introduzione

ChatGPT dice all'utente che è addestrato solo fino a settembre 2021 (screenshot dell'autore)

Se i modelli di linguaggio di grandi dimensioni come ChatGPT potessero essere continuamente aggiornati con nuovi dati, accelererebbero una vasta gamma di compiti, dallo sviluppo di software ai processi legali all’apprendimento. Renderemmo anche obsoleti articoli come questo.

L’apprendimento continuo è la capacità di mettere in pausa il processo di addestramento del modello, salvare lo stato corrente del modello e successivamente riprendere l’addestramento con nuovi dati. Il modello dovrebbe essere in grado di generalizzare bene su nuovi dati, pur mantenendo la sua capacità di generalizzare su vecchi dati. Si fa riferimento a questo paper per una definizione più formale.

Attualmente, la tendenza nell’industria per potenziare gli assistenti virtuali con più dati è quella di utilizzare archivi vettoriali, combinando vettori interrogati con la tecnica dell’ingegneria dei prompt per rispondere alle domande, anziché continuare ad addestrare il LLM con nuovi dati. La capacità di apprendimento con zero istruzioni di ChatGPT, che gli consente di rispondere a domande su dati nuovi e non visti, rende molto interessante questo approccio. Ad esempio, potresti insegnargli un nuovo linguaggio di programmazione e poi fargli domande su quel linguaggio, con solo alcuni prompt, anche se le prestazioni diminuiscono proporzionalmente alla quantità di token in input. Continuare ad addestrare il modello per rispondere a domande basate su un nuovo argomento come questo richiede risorse di calcolo significative e, ancora più importante, una vasta varietà di dati sull’argomento rilevante. Inoltre, se un argomento ha una prevalenza molto bassa nel set di addestramento, generalizzerà male su di esso. Ad esempio, prendi un repository pubblico impopolare e non ne saprà nulla, nonostante l’abbia visto in qualche momento durante il processo di addestramento. Le finestre contestuali stanno diventando sempre più grandi molto rapidamente, rendendo ancora più interessante l’approccio dell’archivio vettoriale. Idealmente, però, non vorremmo un modello intelligente che sappia tutto, senza bisogno di alcun database esterno?

L’apprendimento continuo è un passaggio essenziale verso l’AGI, e alcuni dubitano che riusciremo a raggiungerlo senza cambiamenti significativi nelle architetture delle reti di apprendimento profondo. Jeff Hawkins nel suo libro, “A Thousand Brains”, afferma di non credere che le attuali reti neurali artificiali siano capaci di un apprendimento continuo efficace e ritiene che i modelli futuri probabilmente dovranno essere progettati in modo più simile al cervello umano utilizzando la sua teoria sui frame di riferimento nelle colonne corticali del neocortex.

Pubblicità

Ho una proposta di progetto open-source che mira ad aiutare nell’apprendimento continuo e nel potenziare gli assistenti virtuali con dati aggiuntivi. Ho parlato con Dan Meier di VectorFlow e nonostante le dimensioni dell’industria, ci sono stati pochi progressi in questo senso. Qui puoi trovare la presentazione 🙂

Apprendimento continuo nelle fasi di pre-addestramento rispetto alle fasi di messa a punto dei modelli di linguaggio

All’inizio di quest’anno, è stato pubblicato un articolo di ricerca chiamato “LIMA: Less Is More for Alignment”. Ha introdotto un chatbot che non è stato addestrato utilizzando il Reinforcement Learning from Human Feedback (RLHF), ma è stato invece raffinato su soli 1.000 campioni di domande e risposte attentamente annotati. Sorprendentemente, i ricercatori hanno affermato che nel 43% dei casi, “le risposte del chatbot erano allo stesso livello di quelle di GPT-4”. Non ho analizzato approfonditamente come sono state valutate queste risposte, ma è universalmente riconosciuto che una quantità sostanziale di conoscenze e capacità del modello vengono acquisite durante la fase di pre-training, e ricerche come queste lo dimostrano ulteriormente.

Modelli come ChatGPT e Llama-chat sono stati sottoposti a un’ampia fase di raffinamento per generare risposte più allineate ed efficaci. Attualmente, OpenAI offre un’API per il raffinamento ulteriore di un modello, che utilizza i dati Q&A come input. Tuttavia, ciò non dovrebbe essere utilizzato per insegnare al modello nuovi dati, ma piuttosto per personalizzarne il tono e la direzionalità. Il raffinamento di un modello nel tentativo di insegnargli nuovi dati può causare il cosiddetto “catastrophic forgetting”, un problema in cui il modello dimentica ciò che ha già imparato. Questo articolo illustrerà alcune tecniche volte a mitigare questo problema.

Ciò ci porta anche a un paio di domande chiave sulla fattibilità e la strategia dell’apprendimento continuo:

  • In quale fase dello sviluppo è più vantaggioso ed è più facile introdurre l’apprendimento continuo?
  • Dato che sia il raffinamento che il RLHF modificano i parametri dell’intero modello, è possibile tornare alla fase di pre-training per ulteriori modifiche?

Nota: Fornisco del pseudocodice simile a PyTorch per alcuni degli articoli discussi di seguito. Non è stato testato e potrebbe non funzionare, ma viene utilizzato per suddividere le tecniche passo dopo passo e tradurre qualsiasi notazione matematica confusa per aiutare il lettore a comprendere.

Le 5 sottocategorie di tecniche di apprendimento continuo

La panoramica completa dell’articolo sull’apprendimento continuo afferma che le strategie di addestramento per l’apprendimento continuo possono essere divise in 5 sottocategorie:

  1. Approccio basato sulla regolarizzazione: questo approccio aggiunge vincoli o penalità al processo di apprendimento durante il processo di addestramento.
  2. Approccio basato sull’ottimizzazione: questa tecnica si concentra sulla modifica dell’algoritmo di ottimizzazione.
  3. Approccio basato sulla rappresentazione: questo mira a imparare una rappresentazione delle caratteristiche condivisa tra diverse attività, aiutando il modello a generalizzare meglio a nuove attività correlate.
  4. Approccio basato sul replay: questo coinvolge la memorizzazione di alcuni dati o caratteristiche apprese dalle attività precedenti e il loro ripristino durante l’addestramento su nuove attività per mantenere le prestazioni sulle attività apprese in precedenza. In altre parole, si mescolano sia i vecchi che i nuovi dataset durante l’addestramento sulle nuove attività.
  5. Approccio basato sull’architettura: in questo approccio, l’architettura della rete viene regolata in modo dinamico, spesso con crescita o partizionamento, delegando diverse parti della rete a diverse attività.

1. Approcci basati sulla regolarizzazione

Maschera soffice dei parametri

Le seguenti tecniche di mascheramento soffice mascherano e regolano i gradienti di ciascun parametro durante il processo di addestramento. Gli approcci basati sull’ottimizzazione che verranno descritti di seguito utilizzano anche i gradienti per l’apprendimento continuo. Ricorda che i gradienti non sono solo numeri temporanei che appaiono e scompaiono durante l’addestramento; sono segnali che guidano l’evoluzione dei pesi.

SPG

Questo articolo propone una tecnica chiamata SPG (Flusso di Gradienti a Livello di Parametro con Maschera Soffice) che ha i seguenti obiettivi:

  1. Addestrare il modello su ogni attività fino alla convergenza.
  2. Dopo l’addestramento, calcolare “l’importanza” di ogni parametro per l’attività.
  3. Applicare una maschera soffice ai parametri in base all’importanza accumulata, rendendo meno probabile che i parametri importanti cambino durante l’apprendimento di nuove attività.

Suddividiamo l’approccio passo dopo passo:

1. Addestramento della Prima Attività

Addestrare il modello sul dataset della prima attività come al solito.

2. Calcolare l’Importanza dei Parametri per la Prima Attività

Dopo che l’addestramento della prima attività è completo, calcoliamo l’importanza di ciascun parametro del modello. L’intuizione qui è semplice, utilizziamo i gradienti di ciascun parametro per calcolare la sua importanza. Un gradiente maggiore implica che una piccola variazione di quel parametro comporterà una variazione maggiore della perdita, il che significa che le prestazioni del modello potrebbero variare in modo più significativo, quindi quel parametro è importante.

I gradienti sono anche normalizzati, perché i gradienti nello strato iniziale potrebbero essere piccoli, mentre quelli nello strato finale potrebbero essere grandi. Se stai calcolando l’importanza basata su questi valori di gradiente grezzi, i parametri nello strato finale sembrerebbero più importanti a causa della scala dei loro gradienti, non necessariamente perché sono realmente più cruciali per l’attività.

Equations for calculating the importance of the model parameters in SPG (section 3.1 of paper)

Traduciamo questo calcolo in pseudocodice simile a PyTorch:

import torchdef calcola_importanza_finale(modello, funzione_perdita, caricatore_dati):    # Ottieni un singolo batch dal caricatore dati    input, etichette = next(iter(caricatore_dati))    # Passo in avanti e all'indietro per calcolare i gradienti per tutti i parametri    output = modello(input)    perdita = funzione_perdita(output, etichette)    perdita.backward()    importanze = []    # Calcola l'importanza basata sui gradienti    for parametro in modello.parametri():        if parametro.grad is not None:  # I gradienti possono essere None per alcuni parametri non utilizzati            gradiente_normalizzato = (parametro.grad - torch.mean(parametro.grad)) / torch.std(parametro.grad)            importanza = torch.tanh(gradiente_normalizzato)            importanze.append(importanza)    return torch.stack(importanze).mean(dim=0)

3. Accumulazione dell’Importanza tra le Attività

L’importanza accumulata di ciascun parametro tra le attività è semplicemente calcolata prendendo il valore massimo in ogni stadio.

4. Addestramento delle Attività Successive, perdita combinata e meccanismo di soft-masking:

Quando si addestra su nuove attività, i ricercatori utilizzano una funzione di perdita combinata composta da due parti. Una è la funzione di perdita standard che viene utilizzata normalmente sulla nuova attività e sui dati, e la seconda è una funzione di perdita aggiuntiva che coinvolge il passaggio dei nuovi dati attraverso il vecchio modello (il punto di controllo del modello convergente dopo l’attività precedente) e sommando i logits prodotti. Nelle reti di classificazione, i logits sono di solito le previsioni non normalizzate generate dal modello in uno degli ultimi strati prima di essere elaborati tramite una funzione come softmax. Questa somma di logits serve come forma di perdita. L’idea è che se i logits sommati sono significativamente influenzati quando i parametri del modello cambiano, quei parametri sono cruciali per le prestazioni dell’attività appresa in precedenza.

I gradienti generati da questa perdita aggiuntiva fungono da guida durante la retropropagazione, spingendo i parametri condivisi a cambiare in una direzione che è meno probabile che danneggi le prestazioni della prima attività. Pertanto, funge da sorta di termine di penalità per garantire che eventuali aggiornamenti apportati al modello non comportino una perdita significativa di informazioni relative alle attività precedenti.

Addestra il modello sulla prossima attività. Utilizza un ciclo di addestramento standard, ma modifica i gradienti durante la retropropagazione in base alla loro importanza accumulata. Questo è il meccanismo di soft-masking:

import torchimportance_accumulata = # calcolata alla fine di ogni attivitàfor epoca in range(num_epoche):    for x, y in caricatore_addestramento:        # Passo in avanti: Calcola la perdita per l'attività corrente utilizzando la corretta funzione di perdita        logits = nuovo_modello(x)        perdita_attuale = nn.CrossEntropyLoss()(logits, y)        # Passo in avanti: Calcola le perdite aggiuntive per le attività precedenti (meccanismo CHI)        perdite_attività_precedenti = 0        for indice_attività_precedente in range(id_attività):            logits_precedenti = vecchio_modello(x, indice_attività_precedente)            perdite_attività_precedenti += logits_precedenti.sum()        # Combina le perdite        perdita_combinata = perdita_attuale + perdite_attività_precedenti        # Retropropagazione        ottimizzatore.zero_grad()        perdita_combinata.backward()        # Aggiorna l'importanza accumulata        for parametro, imp_acc in zip(modello.parametri(), importance_accumulata):            gradiente = parametro.grad            imp_acc = torch.max(imp_acc, torch.abs(gradiente))        # Soft-masking dei gradienti prima di fare un passo di ottimizzazione        for parametro, imp in zip(modello.parametri(), importance_accumulata):            parametro.grad *= (1 - importanza)        ottimizzatore.step()

5. Casi speciali di soft-masking

  • Estrazione delle caratteristiche: i gradienti dei parametri nell’estrazione delle caratteristiche condivise vengono modificati in base alla loro importanza accumulata specifica.
  • Testa di classificazione: per la testa di classificazione, i gradienti vengono modificati in base all’importanza media dell’estrattore di caratteristiche.

Applicazione a LLMs

Tieni presente che questo articolo non sperimenta questo con un modello di linguaggio, ma suppongo che in un modello di linguaggio si possa pensare agli strati del trasformatore come analoghi all'”estrattore di caratteristiche” e lo strato finale di classificazione (che prevede la parola o il token successivo nella sequenza) come la “testa di classificazione”.

Applicazione del soft-masking al pre-training continuo in un modello di linguaggio

Successivamente, analizzeremo un articolo che applica un soft-masking simile alla fase di pre-training nella modellistica del linguaggio.

Questo articolo introduce una tecnica chiamata DAS (Pre-training DA continuo di LMs con soft-masking) per l’apprendimento continuo nella fase di pre-training di un grande modello di linguaggio. Applica una tecnica di soft-masking simile a quella appena discussa insieme ad altre tecniche nel tentativo di continuare il pre-training di un LLM senza incorrere in un oblio catastrofico.

Analizziamolo passo dopo passo:

Fase di pre-training iniziale

Effettua il pre-training del LLM come di consueto.

Ulteriore pre-training su un nuovo dominio

Preparare i dati del nuovo dominio:

Viene preparato un nuovo set di dati proveniente da un dominio diverso.

Calcolare l’importanza di ogni neurone

SPG utilizza i gradienti per determinare l’importanza di ogni parametro, e quindi applica il valore di importanza calcolato per mascherare gli aggiustamenti di gradienti dei parametri durante il training. Questo articolo cerca di determinare l’importanza di ogni unità/neurone, piuttosto che del parametro, e quindi utilizza questo metodo nello stesso modo mascherando il gradiente durante il training.

Questo articolo utilizza due diversi metodi per calcolare l’importanza dei neuroni, a seconda del compito da svolgere. Uno è un metodo di rilevazione dell’importanza basato sui gradienti (originariamente descritto in questo articolo), e due, una “funzione di perdita proxy” personalizzata.

Il primo metodo introdotto non viene utilizzato affatto nell’apprendimento continuo del primo nuovo dominio. Perché? Ha bisogno dei dati del set di dati di addestramento per funzionare e gli autori affermano che gli utenti “non hanno accesso all’ammasso di dati di pre-training originale”, il che è un’assunzione corretta.

Essi propongono una funzione di perdita proxy:

All’inizio ho trovato questo termine confusionario, ma viene chiamato così perché il metodo di rilevazione dell’importanza basato sui gradienti originale è definito come una funzione di perdita stessa, che poi puoi utilizzare per far passare gli output della rete per ottenere i gradienti di ogni neurone, che poi possono essere utilizzati per derivare l’importanza, proprio come la tecnica dell’SPG.

Secondo l’articolo, l’importanza è calcolata per ogni “unità” nella rete, dove un’unità può essere un neurone o una testa di attenzione.

Funzione di perdita proxy (“Perdita di divergenza KL proxy”):

  • Prendi un subset del nuovo dominio su cui desideri fare l’addestramento e alimentalo due volte attraverso il modello per ottenere due rappresentazioni diverse. Queste rappresentazioni saranno leggermente diverse a causa delle maschere di eliminazione casuale esistenti nell’architettura del Transformer.
  • Calcola la divergenza KL tra queste due rappresentazioni.

Flusso di backpropagation modificato con perdita proxy e perdita combinata

  1. Passaggio in avanti: I dati attraversano un passaggio in avanti nella rete neurale.
  2. Backpropagation:

Applica la perdita proxy per l’aggiustamento del gradiente: L’importanza a livello di unità della funzione di perdita proxy viene utilizzata per mascherare in modo soft i gradienti originali. Questo viene espresso come:

adjusted_grad *= (1 − unit_level_importance)

Calcola la Perdita Combinata (MLM + Perdita Contrastiva): Calcola la perdita combinata utilizzando sia MLM che la perdita contrastiva.

Ulteriore Pre-allenamento su Più Domini

  1. Calcolo Diretto dell’Importanza: Per ogni nuovo dominio, l’importanza di ogni unità può essere calcolata direttamente utilizzando i dati del nuovo dominio tramite il metodo basato sui gradienti descritto nell’equazione 3, eliminando la necessità della funzione di perdita proxy che viene utilizzata solo una volta dopo il pre-allenamento iniziale.
  2. L’importanza dei neuroni viene aggiornata incrementalmente man mano che si impara ogni nuovo compito. Questo aggiornamento viene effettuato utilizzando il massimo elemento per elemento. L’operazione “massimo elemento per elemento (EMax)” si riferisce al confronto di due vettori elemento per elemento e all’estrazione del valore massimo per ogni elemento corrispondente per creare un nuovo vettore. Ad esempio: se si ha due vettori A e B della stessa lunghezza, il massimo elemento per elemento porterà a un nuovo vettore C in cui ogni elemento C[i] è il massimo tra A[i] e B[i].

2. Approcci basati sull’ottimizzazione

Ci riferiremo alle due tecniche descritte nel documento di riepilogo completo nella sezione 3.1

Conservazione della Direzione del Gradiente

Il documento parla della manipolazione del processo di ottimizzazione basato sui gradienti per rendere le direzioni dei gradienti dei nuovi campioni di allenamento simili a quelle dei vecchi campioni di allenamento. La formula

⟨ ∇θ Lₖ(θ; Dₖ), ∇θ Lₖ(θ; Mₜ) ⟩ ≥ 0

impon

Il testo evidenzia anche che la proiezione del gradiente può essere eseguita anche senza memorizzare i vecchi campioni. NCL (Natural Continual Learning, link al paper) è la tecnica riassunta qui. Nota che questa può essere classificata come un approccio basato sia sulla regolarizzazione che sull’ottimizzazione.

Processo di formazione passo dopo passo:

Passaggio in avanti:

Eseguiresti i nuovi dati attraverso la rete e calcoleresti la perdita come al solito.

Passaggio all’indietro:

Obiettivo: L’obiettivo è quello di minimizzare la perdita specifica del compito ℓk(θ) rispettando un vincolo di distanza d(θ,θ+δ)≤r.

Algoritmo passo dopo passo:

  1. Come al solito, calcola il gradiente della perdita rispetto ai parametri del modello ∇θ​ℓk​(θ).
  2. Il δ viene calcolato utilizzando la regola di aggiornamento. Questo fornisce le modifiche “suggerite” ai parametri del modello θ in base alle esigenze del nuovo compito.
  3. Quindi, inserisci questo δ nella formula del vincolo di distanza: d(θ,θ+δ)=radicequadrata(δ⊤Λ_k-1​δ)​. Il vincolo agisce come un confine intorno ai parametri attuali θ, definito dalla metrica di distanza d(θ,θ+δ) e dal raggio r. Ho faticato a capire perché lo chiamassero “raggio”, e non semplicemente “numero di vincolo” o qualcosa del genere. Penso che sia perché i ricercatori visualizzano i gradienti e il processo di apprendimento in uno spazio ad alta dimensione. Quando si applica un vincolo sulla base della metrica di distanza, si sta essenzialmente definendo una “sfera” intorno ai valori dei parametri attuali in quell’alto spazio dimensionale. Il “raggio” r di questa sfera stabilisce un limite su quanto può muoversi il parametro durante l’apprendimento di un nuovo compito.
  4. Se il δ proposto farebbe muovere θ troppo lontano secondo questa metrica di distanza, cioè al di là di questo confine, lo ridimensioni in modo che rimanga all’interno della regione consentita definita dal raggio r.

Esaminiamo ogni parte più approfonditamente:

Regola di aggiornamento: La regola di aggiornamento fornisce una direzione in cui θ dovrebbe muoversi.

Regola di aggiornamento NCL dalla sezione 3.1 nella panoramica completa del paper sul continuo apprendimento

Scomponendola:

  • ∇θ ℓk(θ) rappresenta i gradienti per tutti i parametri (θ) calcolati dalla funzione di perdita.
  • Calcolo dell’importanza dei parametri (Λ^(k-1)_(-1)): Questo termine rappresenta una matrice di precisione ed è un altro modo per calcolare l’importanza dei parametri nella rete. Ulteriori dettagli di seguito
  • Termine di regolarizzazione (θ — μ_(k-1)): Questo termine avvicina i parametri aggiornati ai parametri ottimali μ_(k-1)​ del compito precedente. Come le tecniche precedenti, agisce come un regolarizzatore per evitare deviazioni da ciò che è stato già appreso.
  • Tasso di apprendimento (λ)

Vincolo di distanza: Prima di applicare questo aggiornamento, di solito controlli se questa modifica δ violerebbe il vincolo di distanza d(θ,θ+δ)≤r. In caso contrario, solitamente ridimensioni δ in modo che soddisfi il vincolo.

Spiegazione della matrice di precisione: nelle metodologie di soft-masking precedenti abbiamo visto il calcolo dell’importanza tramite l’output di tutti i neuroni o i loro gradienti. In questo metodo viene utilizzata una matrice di precisione. Ciò è un po’ più complesso, quindi cercherò di spiegarlo:

Calcoliamo prima la matrice di covarianza per i parametri della rete. Nel contesto delle reti neurali, le colonne nella matrice di gradienti G corrispondono ai parametri (pesi e bias) del modello. Ogni riga in G rappresenta il vettore di gradienti per un singolo esempio di addestramento, rispetto a tutti quei parametri.

Quindi, se hai una rete neurale con P parametri (che include tutti i pesi e i bias di tutti gli strati), ogni vettore gradiente avrà P elementi, uno per ciascun parametro. Di conseguenza, G sarà una matrice di forma N × P, N rappresentante ciascun batch e quindi ogni riga rappresenta il vettore gradiente medio su tutti gli esempi di addestramento in un dato batch.

Quando calcoli la matrice di covarianza Σ da G, la matrice risultante avrà dimensioni P × P. Le voci sulla diagonale Σii indicheranno la varianza del gradiente rispetto all’i-esimo parametro, mentre le voci fuori diagonale Σij indicheranno la covarianza tra i gradienti rispetto all’i-esimo e j-esimo parametro. Questo ti dà un’idea di come questi parametri interagiscano o si correlino durante il processo di addestramento. L’inversa di questa matrice è la matrice di precisione, che è ciò che usiamo per determinare l’importanza.

Perché la matrice di precisione invece della matrice di covarianza? Sebbene la matrice di covarianza Σ catturi come i parametri interagiscono tra di loro durante l’addestramento, non indica specificamente quanto sia cruciale ciascun parametro per il compito in questione quando si considerano tutti gli altri parametri. In contrasto, la matrice di precisione ci permette di valutare l’indipendenza condizionale (questo è un concetto nella teoria delle probabilità, cercalo) dei parametri. Grandi valori nella matrice di precisione indicano che conoscere un parametro è altamente informativo su un altro, date tutti gli altri parametri. Non andrò ad esempi su come funziona quindi chiedi a ChatGPT di generare alcuni esempi utilizzando una rete neurale molto piccola per vedere come i valori possono essere interpretati.

I metodi precedenti che abbiamo visto per calcolare l’importanza si concentrano su singoli neuroni o parametri, ignorando le relazioni tra di loro. Al contrario, la matrice di precisione può catturare queste relazioni. Come tutto nell’apprendimento profondo, se questo è un modo migliore per calcolare l’importanza di una rete sarà empirico e potrebbe differire a seconda del compito e della scala della rete.

Algoritmo passo dopo passo in PyTorch:

import torch# Raggio di vincoloraio = 0,1for epoch in range(num_epochs):      for batch_idx, (data, target) in enumerate(data_loader):        optimizer.zero_grad()        # Passaggio in avanti        output = model(data)        loss = loss_function(output, target)        # Passaggio all'indietro per ottenere i gradienti per i parametri        loss.backward()        model_grad = torch.cat([p.grad.data.view(-1) for p in model.parameters()])        # Calcola δ utilizzando il metodo NCL        # δ = Λ^(-1) * grad - (θ - µ)        delta = torch.matmul(torch.inverse(covarianceMatrix), model_grad) - (torch.cat([p.data.view(-1) for p in model.parameters()]) - parametersForPrevTask)        # Verifica del vincolo        if torch.norm(delta) > radius:            delta = radius * delta / torch.norm(delta)        # Aggiorna i parametri del modello (θ) utilizzando δ        idx = 0        for p in model.parameters():            length = p.data.numel()            p.data += delta[idx: idx + length].view(p.data.shape)            idx += length        # Aggiorna Λ e µ per il prossimo compito, probabilmente specifico del compito e non banale

3. Approccio basato sulla rappresentazione

Innanzitutto, è importante notare che la preformazione dei LLM per essere successivamente ottimizzati su un compito successivo è un esempio di apprendimento continuo in questa sottocategoria. Penso che la capacità di ChatGPT di ragionare su dati mai visti prima sia anche un esempio di questo approccio. Anche se tecnicamente lo chiamiamo apprendimento a zero tiri e il termine “apprendimento continuo” richiede l’aggiornamento dei parametri del modello, va oltre tutto ciò che abbiamo visto prima. Come discusso nell’introduzione, il progetto degli input potrebbe essere il futuro dell’apprendimento continuo, invece di aggiornare continuamente i parametri.

Di seguito daremo un’occhiata all’utilizzo della distillazione delle conoscenze per l’apprendimento continuo. Non sono sicuro in quale sottocategoria rientri, ma suppongo che sia probabilmente un mix tra approcci basati sulla rappresentazione, sull’architettura e su tecniche di riproduzione. Anche se alcune delle tecniche che stiamo esaminando possono sembrare casuali e non comprovate su larga scala, le svolte in questo campo sono spesso imprevedibili. Pertanto, è importante mantenere una prospettiva ampia.

Distillazione delle conoscenze per l’apprendimento continuo

Puoi trasferire (o “distillare”) le conoscenze di una rete in un’altra rete e la seconda rete fa un buon lavoro nell’approssimare la funzione appresa dalla rete originale.

Il modello distillato (lo studente) viene addestrato per imitare l’output della rete più grande (l’insegnante), anziché addestrarlo direttamente sui dati grezzi. Ad esempio, supponiamo che tu voglia addestrare un modello studente più piccolo per imitare un grande modello di linguaggio preaddestrato (l’insegnante). Esegui il dataset di preaddestramento originale attraverso il modello insegnante per generare “target soft”. Queste sono distribuzioni di probabilità sugli output potenziali, ad esempio: previsioni della parola successiva. Ad esempio, per un compito di previsione della parola successiva, invece di prevedere “gatto”, l’insegnante potrebbe fornire probabilità come 90% per “gatto”, 5% per “micino”, 3% per “felino”, ecc.

Di solito si fa questo per trasferire conoscenze a modelli molto più piccoli e nonostante la modella più piccola si ottengono ottimi risultati.

Vediamo come alcuni ricercatori hanno applicato con successo questo ad un modello NER (riconoscimento di entità nominate). Il processo di addestramento è abbastanza semplice:

Processo di addestramento passo dopo passo

Nell’articolo sono indicate due metodologie principali: AddNER e ExtendNER.

Modello AddNER

Si noti che i modelli NER lavorano prendendo in input una sequenza di token (di solito una frase) e producendo in output una distribuzione di probabilità (per i diversi tipi di entità) per ciascun token. L’etichettatura IOB viene comunemente utilizzata per i modelli NER, ogni token può essere etichettato come ‘O’, o come inizio (‘B-‘) o interno (‘I-‘) di un’entità di tipo X. ‘O’ sta per ‘Outside’ e significa che il token corrente non appartiene ad alcuna entità. Pertanto, per n tipi di entità, avrai 2n neuroni di output nel livello di classificazione: n per le etichette ‘B-‘ (uno per ogni tipo di entità) e n per le etichette ‘I-‘ (ancora, uno per ogni tipo di entità). Aggiungendo l’etichetta ‘O’, che indica che un token non appartiene ad alcuna entità, si ottengono complessivamente 2n + 1 possibili etichette per ogni token. Le dimensioni finali possono essere scritte come h × (2n + 1), dove h è la dimensione dell’output del livello nascosto. È importante ricordare che questo si applica solo ai modelli in cui i token possono appartenere a una sola entità. Ad esempio: “Apple” potrebbe essere etichettata come “FOOD” e “COMPANY”.

Architettura e configurazione insegnante-studente

Il modello studente in questo caso è una copia del modello insegnante, con un ulteriore livello di classificazione di output per ciascun nuovo tipo di entità che il modello dovrebbe imparare. Durante l’addestramento, il nuovo livello di output apprende dai nuovi dati annotati e gli strati precedenti vengono guidati dagli output del modello insegnante per minimizzare l’oblio.

Dopo l’addestramento, i vecchi livelli di output non vengono scartati. Viene quindi utilizzato l’algoritmo e l’euristica descritti nella sezione risolutore dei conflitti (fine della sezione 3.3) per combinare questi output in una singola previsione finale per ciascun token nella sequenza.

Diagramma del modello AddNER della sezione 3.2 dell'articolo

Passaggio in avanti

  1. Vecchi tipi di entità: la frase in input viene analizzata dal modello insegnante per ottenere le distribuzioni di probabilità (i “target soft” in questo contesto) per i vecchi tipi di entità.
  2. Nuovi tipi di entità: la stessa frase viene analizzata anche dal nuovo modello studente con ulteriori livelli di output specifici per i nuovi tipi di entità​.

Passaggio un retro

Funzione di perdita combinata:

  1. Perdita di Knowledge Distillation (KD): calcolata confrontando quanto sono simili le probabilità di output dei vecchi tipi di entità tra il nuovo modello (studente) e il vecchio modello (insegnante). Viene utilizzata la divergenza KL per calcolare questo valore. Probabilmente viene calcolata token per token e poi sommata o media sulla frase o sul batch, ma non credo che il documento ne parli esplicitamente.
  2. Perdita di Cross-Entropy: questa è la solita funzione di perdita che confronta le previsioni del modello per i nuovi tipi di entità con le etichette effettive del nuovo set di dati.
  3. Combina le due funzioni: queste due perdite vengono combinate in una perdita combinata prendendo una somma pesata di entrambe. I pesi per la combinazione di queste perdite vengono stabiliti dagli iperparametri alpha e beta, che vengono regolati come qualsiasi altro iperparametro per migliorare le prestazioni in base a esperimenti.
# Iperparametri alpha e beta per pesare le due funzioni di perditaalpha = 0.5beta = 0.5for epoch in range(num_epochs):    for sentence, labels in D_new:        # Passaggio in avanti nel modello insegnante per i vecchi tipi di entità        teacher_probs_Ei = teacher_model(sentence)                # Passaggio in avanti nel modello studente per vecchi e nuovi tipi di entità        # Nota: i nuovi tipi di entità devono passare attraverso il nuovo livello di output (non mostrato in questo pseudocodice)        student_probs_Ei, student_probs_Enew = student_model(sentence)                # Calcolo della perdita di KD        kd_loss = KL_divergence(teacher_probs_Ei, student_probs_Ei)                # Calcolo della perdita di CE per i nuovi tipi di entità        ce_loss = cross_entropy(labels, student_probs_Enew)                # Perdita combinata        total_loss = alpha * kd_loss + beta * ce_loss                # Passaggio all'indietro        total_loss.backward()                # Aggiornamento dei parametri del modello studente        optimizer.step()

Modello ExtendNER

Architettura e configurazione insegnante-studente

Il modello ExtendNER estende le dimensioni del livello di output per ospitare nuovi tipi di entità, invece di aggiungere nuovi livelli di output. Il documento spiega abbastanza semplicemente come dovrebbero essere le dimensioni:

“Assumendo che Mi sia in grado di riconoscere n tipi di entità, il suo ultimo livello può essere considerato come una matrice con dimensione h × (2n + 1). Il livello di output di Mi+1 sarà quindi esteso per essere una matrice con dimensione h × (2n + 2m + 1) al fine di ospitare i nuovi tipi di entità.”

Diagramma del modello ExtendNER dalla sezione 3.4 del documento

Passaggio in avanti

Come in AddNER, ma con dimensioni estese.

Passaggio all’indietro

Il calcolo della perdita utilizza la perdita di divergenza KL o la perdita di cross-entropia, a seconda di quanto segue:

  • Quando l’etichetta di categoria NER y è “O” (dallo schema di marcatura IOB), viene utilizzata la perdita di divergenza KL.
  • Quando l’etichetta di categoria y NON è “O”, viene utilizzata la perdita di cross-entropia.

Previsione finale

Viene applicato l’algoritmo di Viterbi per decodificare i tipi di entità finali.

Sia i modelli AddNER che ExtendNER si sono comportati bene per l’apprendimento continuo e i risultati non differivano molto tra di loro.

4. Approccio basato su replay

“I modelli di linguaggio tarati sono apprendisti continui”

link al documento

Il modello nel documento non è un modello generico per singole attività come GPT addestrato solo per risposte conversazionali. Invece, è tarato per una sequenza di attività specializzate, che vanno dalla semplificazione del testo alla generazione di Haiku. Ognuna di queste attività ha requisiti unici, metriche di valutazione e set di dati di addestramento specializzati.

I ricercatori combinano parti del vecchio set di dati con il nuovo set di dati e ottengono ottimi risultati mescolando solo l’1% del set di dati della precedente attività durante il taraggio per una nuova attività. Questo viene fatto sequenzialmente per molte attività (8). Il modello si comporta bene anche in impostazioni di apprendimento a zero, il che significa che può generalizzare bene alle attività per cui non è stato addestrato. Ad esempio, può generare un Haiku con il conteggio corretto delle sillabe quando gli viene dato un argomento mai visto prima, dimostrando la sua capacità di generalizzazione. I ricercatori citano anche che il loro approccio è invariante all’ordine delle attività, il che significa che la sequenza in cui le attività vengono apprese non influisce sulle prestazioni del modello. Gli esperimenti mostrano che la quantità del vecchio set di dati mescolata con quello nuovo non influenza significativamente le prestazioni della principale attività. Tuttavia, influisce sull’apprendimento a zero. Con il 0% di esercitazione, il modello tende a dimenticare le attività a zero, mentre con l’1% di esercitazione, il modello mantiene molto bene le sue prestazioni in quelle attività.

Tutto questo sembra positivo, il fatto che possiamo aggiungere solo l’1% del vecchio set di dati e risolvere l’apprendimento continuo, ma ovviamente, applicarlo a un chatbot come chatGPT sarà empirico e potrebbe essere completamente diverso. Anche se, ipoteticamente, chatGPT potrebbe essere continuamente addestrato nelle fasi di taraggio e RLHF in questo modo, richiederebbe una quantità immensa di dati di conversazione etichettati.

5. Approccio basato sull’architettura

Non entrerò nel dettaglio di un documento o di un’implementazione specifica qui, ma fornirò una breve panoramica di questo approccio e un paio di tecniche diverse. Consiglio di leggere questa sezione (4.5) del documento di survey completo. È anche più facile da leggere rispetto alle altre sezioni.

  1. Allocazione dei parametri: Qui, un sottoinsieme dei parametri della rete è dedicato a ciascun compito. Ciò può essere fatto sia mascherando i neuroni irrilevanti che identificando esplicitamente quelli importanti per il compito corrente.
  2. Rete modulare: Questo implica l’uso di sotto-reti o moduli separati per ciascun compito.

Le sotto-reti possono essere collegate in vari modi per formare un insieme o un’architettura più complessa. Di seguito sono riportati alcuni metodi comuni per collegare le sotto-reti:

Concatenazione degli output:

In questo approccio, gli output di più sotto-reti sono concatenati in un unico tensore, che quindi può essere passato attraverso ulteriori livelli per produrre l’output finale.

Meccanismo di voto:

In alcuni modelli, ogni sotto-rete emette un “voto” sull’esito probabile e la decisione finale viene presa prendendo il voto della maggioranza o un voto ponderato. Ciò ha un’ispirazione biologica in quanto è simile al modo in cui diverse colonne corticali nella neocorteccia emettono voti.

Connessioni di salto:

Alcune architetture consentono alle sotto-reti di avere connessioni di salto con altre parti del modello, consentendo il flusso delle informazioni attraverso i moduli.

Sequenziale:

In questo caso, l’output di una sotto-rete funge da input per la successiva.

Tornando a parlare dei chatbot, trovo particolarmente interessante la possibilità di creare un’architettura del genere con due sotto-reti. La prima è il modello pre-addestrato che detiene la “conoscenza” generale. La seconda detiene la conoscenza per allineare il modello. Una volta che il modello è allineato, non avrebbe più bisogno di dati conversazionali etichettati. Invece, potrebbe essere continuamente aggiornato addestrando la sotto-rete pre-addestrata in modo non supervisionato.

Conclusioni

In conclusione, il sotto-campo dell’apprendimento continuo nell’apprendimento profondo è sfidante e in gran parte sconosciuto. Questo perché non comprendiamo appieno come funzionano i neuroni nelle reti LLMs e come delineato nell’introduzione, potrebbe anche essere che le architetture di rete attuali o l’apprendimento profondo in generale non siano adatte per questo.

Ho notato il mese scorso che ChatGPT (solo GPT-4) è stato aggiornato poiché ora afferma “Dal mio taglio addestramento di gennaio 2022”, quindi mi chiedo cosa abbiano fatto i ragazzi di OpenAI per ottenere questo.

ChatGPT (variante GPT-4) che informa l'utente di essere addestrato fino a gennaio 2022 (screenshot dell'autore)