Adattamento di Dominio Affinamento di Modelli NLP Pre-Allenati
Domain Adaptation for Fine-tuning Pre-trained NLP Models
Tutorial pratici
Una guida passo-passo per il fine-tuning dei modelli NLP pre-addestrati per qualsiasi dominio
Prefazione: Questo articolo presenta un riassunto delle informazioni sul tema fornite. Non dovrebbe essere considerato una ricerca originale. Le informazioni e il codice inclusi in questo articolo possono essere influenzati da cose che ho letto o visto in passato su vari articoli online, paper di ricerca, libri e codice open-source.
Co-Autore: Billy Hines
Indice
- Introduzione
- Quadro teorico
- Panoramica dei dati
- Punto di partenza: Il modello di base
- Fine-tuning del modello
- Valutazione dei risultati
- Pensieri finali
Introduzione
Nel mondo di oggi, la disponibilità di modelli NLP pre-addestrati ha semplificato notevolmente l’interpretazione dei dati testuali utilizzando tecniche di deep learning. Tuttavia, sebbene questi modelli eccellano in compiti generici, spesso mancano di adattabilità a domini specifici. Questa guida completa si propone di guidarti nel processo di fine-tuning dei modelli NLP pre-addestrati per ottenere una migliore performance in un dominio particolare.
Motivazione
Anche se i modelli NLP pre-addestrati come BERT e Universal Sentence Encoder (USE) sono efficaci nel catturare le sfumature linguistiche, le loro prestazioni nelle applicazioni specifiche di un dominio possono essere limitate a causa della vasta gamma di set di dati su cui sono stati addestrati. Questo limite diventa evidente quando si analizzano le relazioni all’interno di un dominio specifico.
- Edizione di luglio Risorse sul clima per i Data Scientist
- Spiegazione dei Database Vettoriali in 3 Livelli di Difficoltà
- 10 Domande sulla lista Python più frequentemente poste su Stack Overflow
Ad esempio, quando si lavora con dati di lavoro, ci aspettiamo che il modello riconosca la stretta correlazione tra i ruoli di “Data Scientist” e “Machine Learning Engineer”, o l’associazione più forte tra “Python” e “TensorFlow”. Purtroppo, i modelli ad uso generale spesso non catturano queste relazioni sfumate.
La tabella di seguito mostra le discrepanze nella similarità ottenuta da un modello USE multilingue di base:
Per affrontare questo problema, è possibile effettuare il fine-tuning dei modelli pre-addestrati utilizzando set di dati specifici di alta qualità. Questo processo di adattamento migliora significativamente le prestazioni e la precisione del modello, sbloccando appieno il potenziale del modello NLP.
Quando si lavora con grandi modelli NLP pre-addestrati, è consigliabile utilizzare inizialmente il modello di base e considerare il fine-tuning solo se le sue prestazioni non sono sufficienti per il problema specifico.
Questo tutorial si concentra sul fine-tuning del modello Universal Sentence Encoder (USE) utilizzando dati open-source facilmente accessibili.
Panoramica teorica
Il fine-tuning di un modello di machine learning può essere ottenuto attraverso diverse strategie, come l’apprendimento supervisionato e l’apprendimento per rinforzo. In questo tutorial, ci concentreremo su un approccio di apprendimento one(few)-shot combinato con un’architettura siamese per il processo di fine-tuning.
Metodologia
In questo tutorial, utilizziamo una rete neurale siamese, che è un tipo specifico di rete neurale artificiale. Questa rete sfrutta pesi condivisi mentre elabora contemporaneamente due vettori di input distinti per calcolare vettori di output confrontabili. Ispirato all’apprendimento one-shot, questo approccio si è dimostrato particolarmente efficace nel catturare la similarità semantica, anche se potrebbe richiedere tempi di addestramento più lunghi e non fornire una probabilità di output.
Una rete neurale siamese crea uno “spazio di embedding” in cui i concetti correlati sono posizionati vicini, consentendo al modello di discernere meglio le relazioni semantiche.
- Rami gemelli e pesi condivisi: L’architettura consiste di due rami identici, ciascuno contenente uno strato di incorporamento con pesi condivisi. Questi rami gemelli gestiscono contemporaneamente due input, simili o dissimili.
- Similarità e trasformazione: Gli input vengono trasformati in incorporamenti vettoriali utilizzando il modello NLP pre-addestrato. L’architettura calcola quindi la similarità tra i vettori. Il punteggio di similarità, che va da -1 a 1, quantifica la distanza angolare tra i due vettori, servendo come metrica per la loro similarità semantica.
- Contrastive Loss e apprendimento: L’apprendimento del modello è guidato dalla “Contrastive Loss”, che è la differenza tra l’output atteso (punteggio di similarità dai dati di addestramento) e la similarità calcolata. Questa perdita guida la regolazione dei pesi del modello per minimizzare la perdita e migliorare la qualità degli incorporamenti appresi.
Per saperne di più su one(few)-shot learning, architettura siamese e contrastive loss, consulta le seguenti risorse:
Un’introduzione semplice all’architettura delle reti neurali siamesi
Architettura delle reti neurali siamesi: Panoramica e concetti chiave spiegati con esempi | ProjectPro
www.projectpro.io
Cos’è il one-shot learning? — TechTalks
Il one-shot learning permette agli algoritmi di deep learning di misurare la similarità e la differenza tra due immagini.
bdtechtalks.com
Contrastive Loss spiegata
La Contrastive Loss è stata utilizzata di recente in diversi articoli che mostrano risultati all’avanguardia con l’apprendimento non supervisionato…
towardsdatascience.com
Il codice completo è disponibile come Jupyter Notebook su GitHub
Panoramica dei dati
Per il fine-tuning dei modelli NLP pre-addestrati utilizzando questo metodo, i dati di addestramento dovrebbero consistere in coppie di stringhe di testo accompagnate da punteggi di similarità tra di loro.
I dati di addestramento seguono il formato mostrato di seguito:
In questo tutorial, utilizziamo un dataset proveniente dal dataset di classificazione ESCO, che è stato trasformato per generare punteggi di similarità basati sulle relazioni tra diversi elementi di dati.
La preparazione dei dati di addestramento è un passaggio cruciale nel processo di fine-tuning. Si presume che tu abbia accesso ai dati necessari e a un metodo per trasformarli nel formato specificato. Poiché l’obiettivo di questo articolo è dimostrare il processo di fine-tuning, ometteremo i dettagli su come i dati sono stati generati utilizzando il dataset ESCO.
Il dataset ESCO è disponibile per gli sviluppatori per essere utilizzato liberamente come base per varie applicazioni che offrono servizi come completamento automatico, sistemi di suggerimento, algoritmi di ricerca e algoritmi di corrispondenza delle offerte di lavoro. Il dataset utilizzato in questo tutorial è stato trasformato e fornito come esempio, consentendo un utilizzo illimitato per qualsiasi scopo.
Iniziamo esaminando i dati di addestramento:
import pandas as pd# Leggi il file CSV in un DataFrame pandasdata = pd.read_csv("./data/training_data.csv")# Stampa l'intestazionedata.head()
Punto di partenza: il modello di base
Per iniziare, stabiliamo l’encoder di frasi universale multilingue come nostro modello di base. È essenziale impostare questa base prima di procedere con il processo di fine-tuning.
Per questo tutorial, utilizzeremo il benchmark STS e una visualizzazione di similarità campione come metriche per valutare i cambiamenti e le migliorie ottenute attraverso il processo di fine-tuning.
Il dataset del benchmark STS consiste in coppie di frasi in inglese, ciascuna associata a un punteggio di similarità. Durante il processo di addestramento del modello, valutiamo le prestazioni del modello su questo set di benchmark. I punteggi conservati per ciascuna esecuzione di addestramento sono la correlazione di Pearson tra i punteggi di similarità previsti e i punteggi di similarità effettivi nel dataset.
Questi punteggi garantiscono che, durante il fine-tuning del modello con i nostri dati di addestramento specifici per il contesto, mantenga un certo livello di generalizzabilità.
# Carica il modulo Universal Sentence Encoder Multilingual da TensorFlow Hub.base_model_url = "https://tfhub.dev/google/universal-sentence-encoder-multilingual/3"base_model = tf.keras.Sequential([ hub.KerasLayer(base_model_url, input_shape=[], dtype=tf.string, trainable=False)])# Definisce una lista di frasi di test. Queste frasi rappresentano varie posizioni lavorative.test_text = ['Data Scientist', 'Data Analyst', 'Data Engineer', 'Nurse Practitioner', 'Registered Nurse', 'Medical Assistant', 'Social Media Manager', 'Marketing Strategist', 'Product Marketing Manager']# Crea gli embeddings per le frasi nella lista test_text. # La funzione np.array() viene utilizzata per convertire il risultato in un array numpy.# La funzione .tolist() viene utilizzata per convertire l'array numpy in una lista, che potrebbe essere più facile da gestire.vectors = np.array(base_model.predict(test_text)).tolist()# Chiama la funzione plot_similarity per creare un grafico di similarità.plot_similarity(test_text, vectors, 90, "base model")# Calcola il punteggio di benchmark STS per il modello di basepearsonr = sts_benchmark(base_model)print("STS Benachmark: " + str(pearsonr))
STS Benchmark (dev): 0.8325
Fine Tuning del Modello
Il passo successivo prevede la costruzione dell’architettura del modello siamese utilizzando il modello di base e il suo fine-tuning con i nostri dati specifici del dominio.
# Carica il modello di embedding di parole pre-addestratoembedding_layer = hub.load(base_model_url)# Crea un livello Keras dal modello di embedding caricatoshared_embedding_layer = hub.KerasLayer(embedding_layer, trainable=True)# Definisci gli input del modelloleft_input = keras.Input(shape=(), dtype=tf.string)right_input = keras.Input(shape=(), dtype=tf.string)# Passa gli input attraverso il livello di embedding condivisoembedding_left_output = shared_embedding_layer(left_input)embedding_right_output = shared_embedding_layer(right_input)# Calcola la similarità coseno tra i vettori di embeddingcosine_similarity = tf.keras.layers.Dot(axes=-1, normalize=True)( [embedding_left_output, embedding_right_output])# Converti la similarità coseno in distanza angolarepi = tf.constant(math.pi, dtype=tf.float32)clip_cosine_similarities = tf.clip_by_value( cosine_similarity, -0.99999, 0.99999)acos_distance = 1.0 - (tf.acos(clip_cosine_similarities) / pi)# Pacchetta il modelloencoder = tf.keras.Model([left_input, right_input], acos_distance)# Compila il modelloencoder.compile( optimizer=tf.keras.optimizers.Adam( learning_rate=0.00001, beta_1=0.9, beta_2=0.9999, epsilon=0.0000001, amsgrad=False, clipnorm=1.0, name="Adam", ), loss=tf.keras.losses.MeanSquaredError( reduction=keras.losses.Reduction.AUTO, name="mean_squared_error" ), metrics=[ tf.keras.metrics.MeanAbsoluteError(), tf.keras.metrics.MeanAbsolutePercentageError(), ],)# Stampa il riassunto del modelloencoder.summary()
Fit del modello
# Definisci il callback di stop anticipatoearly_stop = keras.callbacks.EarlyStopping( monitor="loss", patience=3, min_delta=0.001)# Definisci il callback di TensorBoardlogdir = os.path.join(".", "logs/fit/" + datetime.now().strftime("%Y%m%d-%H%M%S"))tensorboard_callback = keras.callbacks.TensorBoard(log_dir=logdir)# Input del modelloleft_inputs, right_inputs, similarity = process_model_input(data)# Addestra il modello encoderhistory = encoder.fit( [left_inputs, right_inputs], similarity, batch_size=8, epochs=20, validation_split=0.2, callbacks=[early_stop, tensorboard_callback],)# Definisci l'input del modelloinputs = keras.Input(shape=[], dtype=tf.string)# Passa l'input attraverso il livello di embeddingembedding = hub.KerasLayer(embedding_layer)(inputs)# Crea il modello taratuned_model = keras.Model(inputs=inputs, outputs=embedding)
Valutazione
Ora che abbiamo il modello ottimizzato, rievalutiamolo e confrontiamo i risultati con quelli del modello di base.
# Crea gli embedding per le frasi nella lista test_text. # La funzione np.array() viene utilizzata per convertire il risultato in un array numpy.# La funzione .tolist() viene utilizzata per convertire l'array numpy in una lista, che potrebbe essere più facile da gestire.vectors = np.array(tuned_model.predict(test_text)).tolist()# Chiama la funzione plot_similarity per creare un grafico di similarità.plot_similarity(test_text, vectors, 90, "modello ottimizzato")# Calcola il punteggio STS benchmark per il modello ottimizzatopearsonr = sts_benchmark(tuned_model)print("STS Benachmark: " + str(pearsonr))
STS Benchmark (dev): 0.8349
Sulla base dell’ottimizzazione del modello sul dataset relativamente piccolo, il punteggio STS benchmark è paragonabile a quello del modello di base, indicando che il modello ottimizzato mostra ancora una generalizzabilità. Tuttavia, la visualizzazione della similarità mostra punteggi di similarità rafforzati tra titoli simili e una riduzione dei punteggi per quelli non simili.
Considerazioni finali
L’ottimizzazione dei modelli NLP pre-addestrati per l’adattamento al dominio è una tecnica potente per migliorare le loro prestazioni e precisione in contesti specifici. Utilizzando dataset di qualità specifici del dominio e sfruttando reti neurali siamesi, possiamo migliorare la capacità del modello di catturare la similarità semantica.
Questo tutorial fornisce una guida passo-passo al processo di ottimizzazione, utilizzando il modello Universal Sentence Encoder (USE) come esempio. Abbiamo esplorato il quadro teorico, la preparazione dei dati, la valutazione del modello di base e il processo effettivo di ottimizzazione. I risultati hanno dimostrato l’efficacia dell’ottimizzazione nel rafforzare i punteggi di similarità all’interno di un dominio.
Seguendo questo approccio e adattandolo al tuo dominio specifico, puoi sfruttare appieno il potenziale dei modelli NLP pre-addestrati e ottenere risultati migliori nelle tue attività di elaborazione del linguaggio naturale.
Grazie per la lettura. Se hai qualche feedback, non esitare a commentare questo post, a contattarmi su LinkedIn o a inviarmi un’email (smhkapadia[at]gmail.com)
Se hai apprezzato questo articolo, visita gli altri miei articoli
Valutare i modelli di argomento: Latent Dirichlet Allocation (LDA)
Una guida passo-passo per creare modelli di argomento interpretabili
towardsdatascience.com
L’evoluzione dell’elaborazione del linguaggio naturale
Una prospettiva storica sullo sviluppo dei modelli di lingua
Nisoo.com
Sistema di raccomandazione in Python: LightFM
Una guida passo-passo per creare un sistema di raccomandazione in Python utilizzando LightFM
towardsdatascience.com