Semplici considerazioni per persone semplici che costruiscono reti neurali sofisticate

'Semplici considerazioni per costruttori di reti neurali sofisticati'

Foto di Henry & Co. su Unsplash

Mentre l’apprendimento automatico continua a penetrare in tutti gli aspetti dell’industria, le reti neurali non sono mai state così acclamate. Ad esempio, modelli come GPT-3 sono stati ovunque sui social media nelle ultime settimane e continuano a far parlare di sé anche al di fuori delle testate di notizie tecnologiche con titoli allarmistici.

Allo stesso tempo, i framework, gli strumenti e le librerie specializzate di deep learning democratizzano la ricerca sull’apprendimento automatico, rendendo la ricerca all’avanguardia più facile da usare che mai. È abbastanza comune vedere queste 5 linee di codice quasi-magiche/plug-and-play che promettono risultati (quasi) all’avanguardia. Lavorando presso Hugging Face 🤗, ammetto di essere in parte colpevole di ciò. 😅 Può dare all’utente inesperto l’errata impressione che le reti neurali siano ora una tecnologia matura mentre, in realtà, il campo è in continua evoluzione.

In realtà, creare e addestrare reti neurali può spesso essere un’esperienza estremamente frustrante:

  • A volte è difficile capire se le prestazioni dipendono da un bug nel tuo modello/codice o sono semplicemente limitate dalla sua espressività.
  • Puoi commettere piccoli errori ad ogni passo del processo senza rendermene conto all’inizio, e il tuo modello continuerà comunque ad addestrarsi e a fornire prestazioni decenti.

In questo post, cercherò di evidenziare alcuni passaggi del mio processo mentale quando si tratta di creare e risolvere problemi delle reti neurali. Con “risolvere i problemi”, intendo assicurarmi che ciò che hai costruito sia allineato con ciò che hai in mente. Indicherò anche le cose a cui puoi guardare quando non sei sicuro del tuo prossimo passo elencando le domande tipiche che mi pongo.

Molte di queste considerazioni derivano dalla mia esperienza nella ricerca del processing del linguaggio naturale, ma la maggior parte di questi principi possono essere applicati ad altri campi dell’apprendimento automatico.

1. 🙈 Inizia mettendo da parte l’apprendimento automatico

Potrebbe sembrare controintuitivo, ma il primo passo nella costruzione di una rete neurale è mettere da parte l’apprendimento automatico e concentrarsi semplicemente sui dati. Guarda gli esempi, le loro etichette, la diversità del vocabolario se stai lavorando con del testo, la distribuzione della loro lunghezza, ecc. Dovresti immergerti nei dati per avere una prima idea del prodotto grezzo con cui stai lavorando e concentrarti sull’estrazione di modelli generali che un modello potrebbe essere in grado di catturare. Speriamo che, guardando alcuni centinaia di esempi, sarai in grado di identificare pattern ad alto livello. Alcune domande standard che puoi farti:

  • Le etichette sono equilibrate?
  • Ci sono etichette d’oro con cui non sei d’accordo?
  • Come sono stati ottenuti i dati? Quali sono le possibili fonti di rumore in questo processo?
  • Ci sono passaggi di pre-elaborazione che sembrano naturali (tokenizzazione, rimozione di URL o hashtag, ecc.)?
  • Quanto sono diversi gli esempi?
  • Quale algoritmo basato su regole potrebbe dare prestazioni decenti per questo problema?

È importante ottenere una sensazione generale (qualitativa) del tuo set di dati insieme a un’analisi dettagliata (quantitativa). Se stai lavorando con un set di dati pubblico, è possibile che qualcun altro si sia già immerso nei dati e abbia segnalato la propria analisi (è piuttosto comune nelle competizioni Kaggle, ad esempio), quindi assolutamente dovresti dare un’occhiata a queste analisi!

2. 📚 Continua come se avessi appena iniziato l’apprendimento automatico

Una volta acquisita una comprensione approfondita e ampia dei tuoi dati, consiglio sempre di mettersi nei panni del tuo vecchio io quando hai appena iniziato l’apprendimento automatico e stavano guardando le lezioni introduttive di Andrew Ng su Coursera. Inizia con qualcosa di semplice possibile per avere un’idea della difficoltà del tuo compito e di come si comporterebbero i baselines standard. Ad esempio, se lavori con il testo, i baselines standard per la classificazione binaria del testo possono includere una regressione logistica addestrata su word2vec o fastText embeddings. Con gli strumenti attuali, eseguire questi baselines è tanto facile (se non di più) quanto eseguire BERT, che può essere considerato uno degli strumenti standard per molti problemi di processing del linguaggio naturale. Se sono disponibili altri baselines, esegui (o implementa) alcuni di essi. Ti aiuteranno a familiarizzare ancora di più con i dati.

Come sviluppatori, è facile sentirsi bene quando si costruisce qualcosa di fantastico, ma a volte è difficile giustificarlo razionalmente se batte solo di pochi punti i baselines facili, quindi è fondamentale assicurarsi di avere punti di confronto ragionevoli:

  • Come si comporterebbe un predittore casuale (soprattutto in problemi di classificazione)? Il set di dati può essere sbilanciato…
  • Che aspetto avrebbe la perdita per un predittore casuale?
  • Quali sono le migliori metriche per misurare il progresso nel mio compito?
  • Quali sono i limiti di questa metrica? Se è perfetta, cosa posso concludere? Cosa non posso concludere?
  • Cosa manca agli “approcci semplici” per raggiungere un punteggio perfetto?
  • Ci sono architetture nel mio set di strumenti di reti neurali che sarebbero buone per modellare il bias induttivo dei dati?

3. 🦸‍♀️ Non aver paura di guardare sotto il cappuccio di questi template di 5 linee

Successivamente, puoi iniziare a costruire il tuo modello basandoti sulle intuizioni e la comprensione acquisite in precedenza. Come accennato in precedenza, implementare reti neurali può diventare rapidamente piuttosto complicato: ci sono molte parti in movimento che lavorano insieme (l’ottimizzatore, il modello, la pipeline di elaborazione dell’input, ecc.), e molte piccole cose possono andare storte durante l’implementazione di queste parti e la loro connessione tra loro. La sfida sta nel fatto che puoi commettere questi errori, addestrare un modello senza che si blocchi mai e ottenere comunque una buona prestazione…

Tuttavia, è una buona abitudine, quando pensi di aver finito di implementare, farti overfitting su un piccolo batch di esempi (ad esempio 16). Se la tua implementazione è (quasi) corretta, il tuo modello sarà in grado di fare overfitting e ricordare questi esempi mostrando una perdita pari a 0 (assicurati di rimuovere qualsiasi forma di regolarizzazione come il decay dei pesi). Se non lo fa, è molto probabile che tu abbia fatto qualcosa di sbagliato nella tua implementazione. In alcuni casi rari, significa che il tuo modello non è sufficientemente espressivo o ha una capacità insufficiente. Di nuovo, inizia con un modello su piccola scala (ad esempio con meno strati): stai cercando di debuggare il tuo modello, quindi vuoi un ciclo di feedback rapido, non prestazioni elevate.

Suggerimento professionale: basandomi sulla mia esperienza di lavoro con modelli di linguaggio pre-addestrati, congelare i moduli di embedding ai loro valori pre-addestrati non influisce molto sulle prestazioni del fine-tuning, ma velocizza considerevolmente l’addestramento.

Alcuni errori comuni includono:

  • Indicizzazione errata… (questi sono davvero i peggiori 😅). Assicurati di raccogliere i tensori nelle dimensioni corrette, ad esempio…
  • Hai dimenticato di chiamare model.eval() in modalità di valutazione (in PyTorch) o model.zero_grad() per pulire i gradienti
  • Qualcosa è andato storto nella pre-elaborazione degli input
  • La perdita ha ricevuto argomenti errati (ad esempio passando probabilità quando si aspetta logit)
  • L’inizializzazione non rompe la simmetria (di solito accade quando si inizializza una matrice intera con un singolo valore costante)
  • Alcuni parametri non vengono mai chiamati durante il passaggio in avanti (e quindi non ricevono gradienti)
  • Il tasso di apprendimento assume valori strani come 0 tutto il tempo
  • I tuoi input vengono troncati in modo non ottimale

Suggerimento professionale: quando lavori con il linguaggio, dai un’occhiata seria agli output dei tokenizzatori. Non posso contare il numero di ore perse cercando di riprodurre risultati (e a volte i miei vecchi risultati) perché qualcosa è andato storto con la tokenizzazione. 🤦‍♂️

Un altro strumento utile è immergersi nella dinamica dell’addestramento e tracciare (ad esempio in Tensorboard) l’evoluzione di molteplici scalari durante l’addestramento. Come minimo, dovresti guardare la dinamica delle tue perdite, dei parametri e dei loro gradienti.

Alla diminuzione della perdita, vuoi anche osservare le previsioni del modello: sia valutando sul tuo set di sviluppo o, la mia preferenza personale, stampando un paio di output del modello. Ad esempio, se stai addestrando un modello di traduzione automatica, è piuttosto soddisfacente vedere le generazioni diventare sempre più convincenti durante l’addestramento. Devi prestare particolare attenzione all’overfitting: la tua perdita di addestramento continua a diminuire mentre la tua perdita di valutazione punta alle stelle. 💫

4. 👀 Sintonizza, ma non sintonizzarti ciecamente

Una volta che hai tutto in funzione, potresti voler ottimizzare i tuoi iperparametri per trovare la migliore configurazione per il tuo setup. In genere, io preferisco utilizzare una ricerca a griglia casuale in quanto si è dimostrata piuttosto efficace nella pratica.

Alcune persone riportano successi utilizzando metodi più avanzati per l’ottimizzazione degli iperparametri come l’ottimizzazione bayesiana, ma nella mia esperienza, una ricerca a griglia casuale definita manualmente è ancora una base difficile da battere.

La cosa più importante è che non ha senso avviare 1000 esecuzioni con diversi iperparametri (o regolazioni dell’architettura come funzioni di attivazione): confronta un paio di esecuzioni con diversi iperparametri per capire quali iperparametri hanno il maggior impatto, ma in generale è illusorio aspettarsi di ottenere miglioramenti significativi delle prestazioni semplicemente regolando alcuni valori. Ad esempio, se il tuo miglior modello ha una velocità di apprendimento di 4e2, probabilmente sta accadendo qualcosa di più fondamentale all’interno della tua rete neurale e vuoi identificare e comprendere questo comportamento in modo da poterlo riutilizzare al di fuori del contesto specifico attuale.

In media, gli esperti utilizzano meno risorse per trovare soluzioni migliori.

Per concludere, un consiglio generale che mi ha aiutato a diventare migliore nella costruzione di reti neurali è quello di preferire (quanto più possibile) una comprensione approfondita di ogni componente della tua rete neurale invece di regolarla ciecamente (per non dire magicamente). Mantieni la semplicità e evita piccole regolazioni che non puoi giustificare ragionevolmente, anche dopo averci provato molto duramente. Ovviamente, c’è il giusto equilibrio da trovare tra un approccio “prova ed errore” e un approccio “analitico”, ma molte di queste intuizioni diventano più naturali man mano che accumuli esperienza pratica. Anche tu stai allenando il tuo modello interno. 🤯

Alcuni punti correlati per completare la tua lettura:

  • Reproducibilità (in ML) come veicolo per le migliori pratiche di ingegneria di Joel Grus
  • Checklist per il debug delle reti neurali di Cecelia Shao
  • Come effettuare test unitari per il codice di apprendimento automatico di Chase Roberts
  • Una ricetta per l’addestramento delle reti neurali di Andrej Karpathy