Questo è il primo di una serie di articoli che riguardano quella parte del machine learning nota come Natural Language Processing (NLP).
In questo articolo si fa riferimento a diversi concetti chiave in ambito Machine Learning.
Leggere l'articolo Machine learning e applicazioni per l'industria
per le principali definizioni.
Con Natural Language Processing si fa riferimento a quel campo di ricerca interdisciplinare che abbraccia informatica, intelligenza artificiale e linguistica, il cui scopo è quello di sviluppare algoritmi in grado di analizzare, rappresentare e quindi “comprendere” il linguaggio naturale, scritto o parlato, in maniera similare o addirittura più performante rispetto agli esseri umani.
Al giorno d'oggi vengono generati e memorizzati quantità enormi di contenuti testuali e vocali. Si tratta di dati dei quali molto spesso non si fa uso, non consci del fatto che invece rappresentano una fonte inestimabile di valore, grazie ai quali è possibile realizzare strumenti e applicazioni che possono portare un valore aggiunto non indifferente.
Sfruttando i contenuti testuali e vocali a disposizione è possibile realizzare ad esempio strumenti di:
- Named Entity Recognition: riconoscere ed estrarre entità e informazioni di tipo semantico dal testo.
- Text Classification: classificare contenuti testuali, ad esempio l'analisi del sentiment di un testo(positivo o negativo).
- Entity linking: disambiguare le entità individuate nel testo(collegare le entità testuali a concetti identificativi).
- Topic Modeling: estrarre in modo automatico i topic principali presenti in un corpus testuale.
- Autocompletion: autocompletamento di una query ad esempio.
- Machine translation: traduzione di un contenuto testuale da una lingua ad un'altra.
- Speech Recognition: trasformazione di contenuti vocali in contenuti testuali (tecnologia alla base dei chatbot)
In questo primo articolo verrà trattato il task noto come Named Entity Recognition (NER). Vedremo come è possibile realizzare uno strumento in grado di riconoscere entità nel testo e quali sono alcune delle sue possibili applicazioni.
Named Entity Recognition
La Named Entity Recognition si colloca all'interno di quella sottoclasse di task che in NLP è definita come Information Extraction. Attraverso la NER è possibile identficare entità nel testo e associarle alle corrispondenti categorie semantiche come persone, organizzazioni, entità di tipo geopolitico, geografico, numeri, espressioni temporali e via dicendo.
Stiamo parlando di un task che negli ultimi tempi ha avuto un forte sviluppo, soprattutto grazie all'avvento del Deep Learning.
L'utilizzo di reti neurali molto profonde ha incrementato e migliorato molto l'efficacia di strumenti per il riconoscimento delle entità.
Prima dell'avvento del Deep Learning, lo strumento più utilizzato risultava essere il cosiddetto Hidden Markov Model,
un modello statistico basato su Processo di Markov, ma che non garantiva
le stesse prestazioni degli odierni modelli basati su Deep Learning.
Più avanti nell'articolo verranno mostrati due esempi di addestramento di modelli per il riconoscimento delle entità, entrambi basati sull'utilzzo di algoritmi
realizzati con reti neurali.
Tecniche di annotazione e tool
Il task della Named Entity Recognition viene affrontato tramite approcci di tipo supervisionato, e per questo motivo è necessario avere a disposizione un insieme di dati etichettati per poter addestrare un modello per riconoscere le entità. Ogni contenuto testuale deve essere etichettato con la lista dei token e i relativi tag, per ogni entità che si vuole riconoscere nel testo.
Esistono diversi formati per rappresentare un dataset di addestramento per la Named Entity Recognition. Vediamo i due più utilizzati.
Un primo formato è quello che prende il nome di schema BILUO, dove le diverse parti che costituiscono le entità sono mappate secondo lo schema in Figura 2. Le entità sono etichettate con la categoria semantica precededuta da uno dei prefissi definiti, specificando quindi se si tratta di entità multi-token o no, e la posizione dei diversi token che costituiscono l'entità.
Il mapping tra i token e le entità viene poi salvato in un file csv, utilizzando un'etichetta a parte per tutti i token che non rientrano nelle categorie semantiche di riferimento.
Lo schema BILUO è forse il formato più diffuso.
Un secondo formato è una versione semplificata dello schema BILUO. Prende il nome di schema IOB. Si tratta di uno schema a granularità meno fine, dove
il prefisso associato all'entità indica solo se si tratta di un token all'inizio o all'interno dell'entità composta da più parole.
Lo schema segue le specifiche definite nella figura sottostante.
Una terza rappresentazione è in formato jsonl. In questo formato si associa ad ogni contenuto testuale una lista che indica, per ogni entità, la posizione nel testo e la categoria semantica associata.
Gli esperti individuano lo schema BILUO come il migliore per realizzare modelli per la Named Entity Recognition il più accurati possibile.
Questo perchè, attraverso lo schema a più prefissi, specificano informazioni più dettagliate nel testo, che migliorano le capacità di
apprendimento dell'algoritmo di Machine Learning utilizzato.
Ma anche utilizzando lo schema in formato IOB e jsonl, molto spesso si riescono a raggiungere prestazioni degne di nota.
Il passaggio da un formato all'altro è relativamente semplice e può essere eseguito attraverso la definizione di procedure basate su regole di
facile intuizione.
Inoltre molte librerie di NLP definiscono già funzioni predefinite per trasformare il proprio dataset nel formato desiderato.
Per etichettare e trasformare i dati in uno di questi formati, esistono degli strumenti ad hoc chiamati annotatori. Un annotatore permette di caricare i propri dati come plain text e poi etichettarli in un ambiente grafico che rende più agile il processo di annotazione. Gli annotatori permettono di etichettare dati per la NER, ma anche per task di classificazione testuale piuttosto che task di tipo sequence-to-sequence.
Nel caso della NER, un annotatore presenta una grafica come quella che segue in figura, con delle funzionalità che permettono di svolgere l'attività di annotazione semplicemente evidenziando il testo e specificando l'etichetta da assegnare.
La schermata di esempio proviene da doccano, un'annotatore ben strutturato e open source. Doccano, una volta etichettati i dati, permette di esportare il dataset in formato jsonl. Da citare invece tra quelli a pagamento Prodigy, un annotatore avanzato e potenziato attraverso il concetto di active learning; è sviluppato da Explosion.ai, creatori della libreria opensource di NLP Spacy.
Dataset
Qualora si voglia addestrare dei modelli per il riconscimento delle entità, un opzione è quella di analizzare prima alcuni dataset etichettati presenti allo stato dell'arte. Si tratta tendenzialmente di dataset generici, con entità etichettate con categorie semantiche relative a nomi di persona, organizzazioni, località, date, entità temporali; è comunque possibile anche trovare dataset etichettati rispetto a domini più specifici. Questi dataset sono quasi sempre in lingua inglese, ma molto spesso questo problema può essere superato utilizzando dei tool di machine translation prima di svolgere l'attività di Named Entity Recognition, traducendo il contenuto dalla lingua italiana alla lingua inglese, e viceversa.
Ecco una lista di alcuni dei dataset etichettati presenti in rete:
- Annotated Corpus for Named Entity Recognition: dataset in BILUO Schema contenente contenuti testuali etichettati con entità geografiche, geopolitiche, temporali, ecc...
- CoNLL 2003: dataset in BILUO Schema contenente articoli di news annotati con (LOC) località, ORG (organizzazioni), PER (persone) and MISC (varie).
- Enron Email Dataset: più di 500.000 email taggate con nomi, date e entità temporali.
- OntoNotes 5: si tratta di un dataset di news, conversazioni telefoniche, contenuti di blog etichettati con entità di diverso genere.
Panoramica sui tool per la Named Entity Recognition
Allo stato dell'arte sono presenti molti tool e librerie che si occupano della realizzazione e dell'implementazione di strumenti in ambito
Natural Language Processing. Questi tool forniscono sia dei modelli preaddestrati, facili da utilizzare e integrare velocemente nel proprio codice, sia la
possibilità di addestrarne dei nuovi con i propri dati, sfruttando moduli predefiniti che semplificano l'addestramento di nuovi strumenti di Machine Learning.
Nella sezione successiva vedremo come addestrare modelli custom su dati propri.
Vediamo ora, invece, alcuni tool, di facile utilizzo, che forniscono modelli preaddestrati per il riconoscimento delle entità nel testo.
Spacy
Spacy è un framework di Natural Language Processing, che si occupa dello sviluppo e dell'implementazione di tecniche di Machine Learning per molti dei più diffusi task di nlp. Spacy, tool completamente open source, fornisce inoltre una lista di modelli preaddestrati, con supporto per diverse lingue, tramite i quali è possibile eseguire su contenuti testuali processi di elaborazione del linguaggio naturale, come il riconoscimento delle entità.
In questi due snippet di codice vediamo come installare attraverso pip nel proprio ambiente Python la libreria e fare il download del modello scelto. Successivamente, con due semplici righe di codice, è possibile caricare il modello ed eseguirlo sul contenuto testuale a piacere.
Stanford NLP
Stanford NLP è un gruppo di ricerca della Stanford University che si dedica al NLP e che ha realizzato una suite di strumenti per diversi task tra cui anche la Named Entity Recognition.
In questo snippet viene utilizzata la libreria nltk per tokenizzare il contenuto testuale e trasformarlo in una lista di parole. Successivamente questa lista viene data in pasto al "ner tagger" che restituisce le entità in output.
Training di modelli custom
Abbiamo visto come allo stato dell'arte siano presenti tool e modelli già addestrati e come questi possono essere utilizzati per individuare
le entità sui propri contenuti testuali.
Ma in molti casi si rivelano insufficienti, sia perchè si vogliono individuare entità relative a categorie semantiche diverse, sia perchè i modelli
preaddestrati non sono adatti alla sorgente dati sulla quale vuole svolgere l'attività di riconoscimento delle entità.
In questi casi risulta più conveniente addestrare dei propri modelli per la Named Entity Recognition, utilizzando i propri dati, che sono
stati etichettati tramite l'ausilio di annotatori, come visto nella sezione precedente.
Seguono due esempi di addestramento di modelli custom, attraverso l'utilizzo della libreria Spacy e della libreria di Deep Learning Tensorflow.
Visita il repository Github dove è presente il codice sorgente degli esempi descritto ed eseguibile in jupyter notebook ben documentati.
Spacy
Spacy, come già detto, è una libreria di Machine Learning, dedicata completamente allo sviluppo di strumenti per i diversi task di
Natural Language Processing. Si tratta di un framework ben strutturato e con funzionalità avanzate, che fanno si che sia molto adatto anche a
contesti di produzione.
Oltre a strumenti già addestrati e rapidamente utilizzabili, come visto nella sezione precedente, fornisce tutta una
serie di api e funzioni attraverso le quali è possibile realizzare e addestrare dei propri modelli, in modo rapido ed efficiente, senza doversi preoccupare di
dover gestire tutti gli aspetti di più basso livello, che solitamente vanno affrontati durante il training e la creazione di un modello di Machine Learning.
Spacy fornisce delle pipeline già definite e configurabili per molti task di NLP, tra cui la Named Entity Recognition. Andiamo a vedere come addestrare rapidamente un modello per questo task con poche linee di codice, senza dover gestire aspetti che riguardano la definizione dell'architettura del modello, la gestione dei dati, piuttosto che la gestione dei modelli.
In questo primo snippet di codice:
- vengono importate le librerie necessarie
- viene definito un sample dei dati di training in formato jsonl, che in un contesto reale dovrebbero essere invece letti da un'apposito file con i dati di training
- viene inizializzato un nuovo modello o viene caricato un modello già esistente da cui partire per l'addestramento
- viene inizializzata la pipeline per la "ner" nel modello, se questa già non è presente
Nel codice che segue è invece implementata la vera e propria logica di addestramento.
Inizialmente vengono filtrate le pipeline del modello, disabilitando tutte quelle non necessarie per addestrare un modello
per il riconoscimento delle entità.
Successivamente sulla base del numero iterazioni da svolgere specificato, si itera sui dati, che vengono divisi in minibatch,
e si aggiornano i parametri del modello di iterazione in iterazione. Il Dropout può essere configurato a seconda
delle esigenze.
Nell'esempio viene stampata la loss del modello al termine di ogni iterazione di addestramento.
Infine, per terminare il processo di addestramento, il modello, in modo molto semplice, può essere salvato su disco, ed in modo altrettanto semplice, caricato per essere essere utilizzato in contesti reali, andando a specificare il path dove il modello è stato salvato.
In questo esempio non viene in alcun modo definita l'architettura del modello, nè tanto meno viene gestito il vocabolario alla base del modello, cosi come
il processo di archiviazione e salvataggio di quest'ultimo.
Viene tutto gestito da Spacy, che definisce tutta la logica della Named Entity Recognition nella pipeline di
riferimento. Questo permette anche a chi è meno esperto di poter intraprendere l'addestramento di un modello per un task del genere.
In ogni caso, indagando in profondità nell'implementazione della pipeline, troviamo che l'architettura utilizzata è quella di una rete convolutiva con connessioni residue. Si tratta di reti convolutive che, similmente a quanto avviene nelle celle piramidali della nostra corteccia cerebrale, definiscono delle connessioni residue con altre parti della rete neurale; per alcuni task di NLP queste reti dimostrano di performare in modo molto efficace e superare le prestazioni di altri algoritmi di Deep Learning.
Per approfondimenti e maggiori dettagli è presente un'ottima documentazione sul sito di Spacy, sia riguardo la
procedura di addestramento, sia riguardo l'architettura utilizzata.
La configurazione utilizzata può in molti casi portare sin da subito a delle ottime prestazioni; rimane sempre consigliato svolgere
un'attività di ottimizzazione dei parametri al fine di individuare quella che è la configurazione migiore. Per consigli su come svolgere
questa ottimizzazione visita https://spacy.io/usage/training#tips.
Tensorflow
Tensorflow è tra le librerie di Deep Learning più utilizzate sia per le sperimentazioni, sia in contesto di produzione. Definisce una moltitudine di strumenti e tecniche comunemente utilizzate per realizzare modelli di Machine Learning basati su reti neurali molto profonde. Viene gestita da Google ed è completamente open source.
Tensorflow permette di realizzare qualsiasi modello basato su Deep Learning, dando la possibilità di progettare le reti sia attraverso tecniche molto avanzate che permettono la codifica degli aspetti di più basso livello, sia utilizzando layer predefiniti per creare la propria rete neurale con l'architettura che più fa al caso proprio, configurando i diversi layer e la logica di addestramento a proprio piacere, ricercando le migliori performance.
In Spacy siamo di fatto costretti ad utilizzare l'architettura scelta dagli sviluppatori, potendo agire in alcuni suoi parametri di configurazione, ma senza
poter definire nel dettaglio l'algoritmo di addestramento.
L'architettura fornita dallo strumento di Spacy in molti casi si può rivelare la migliore,
ma potrebber anche essere che, per una determinare sorgente dati e per la natura delle entità che si vogliono riconoscere,
ci sia un algoritmo migliore delle reti convolutive scelte in Spacy.
Con Tensorflow, come detto, si può realizzare qualsiasi algoritmo e modello, basato su Deep Learning. Vediamo quindi come definire un modello
per la Named Entity Recognition utilizzando Tensorflow Keras e
reti neurali ricorrenti bidirezionali di tipo
LSTM.
Le reti neurali ricorrenti si adattano ottimamente laddove risulta rilevante individuare relazioni tra feature per il task da svolgere. E per questo motivo
sono molto utilizzate per i task di NLP, dove le relazioni nel testo sono molto importanti, come il riconoscimento delle entità.
Dovendo definire la logica a più basso livello, anche la gestione dei dati va fatta in modo differente, andando a gestire aspetti che
in Spacy vengono gestite dalla libreria stessa.
Nello snippet seguente vengono letti i dati di training, in formato BILUO, in un pandas dataframe. Vengono successivamente create le liste senza duplicati dei
token e dei tag presenti nel dataset. Infine, secondo la logica definita dalla classe SentenceGetter, il dataset viene splittato in frasi diverse, e vengono
creati dei vocabolari che mappano le liste delle parole e dei tag su degli identificativi numerici.
A questo punto i vocabolari creati vengono utilizzati per mappare ogni contenuto testuale su una sequenza di interi, potendo poi così
dare queste in input alla rete neurale definita per le epoche di addestramento.
Una volta fatto ciò gli insiemi dei dati e dei tag assiociati vengono splittati in insieme di training e insieme di test, che verrà utilizzato
per la valutazione del modello addestrato.
A questo punto viene definita l'architettura del modello. Si tratta di una rete con un layer di Embedding iniziale, un layer LSTM di tipo bidirezionale e infine un layer TimeDistributed, che definisce uno strato fully connected sulle stesse finestre temporali. Per approfondimenti sulla natura dei diversi layer si rimanda alla documentazione ufficiale.
Il modello viene poi addestrato su un certo numero di epoche, utilizzando EarlyStopping come callback che monitora l'addestramento e lo interrompe qualora la rete inizi a soffrire di overfitting, cioè di eccessivo adattamento dei dati training, con conseguente perdita di accuratezza sui dati di test.
Infine il modello viene salvato su disco, archiviando ogni componente necessaria per i futuri utilizzi. Non viene salvato solo il modello, ma anche tutti i vocabolari necessari per le trasformazioni sui dati.
Per riutilizzare il modello basta caricarlo specificando il path dove è stato archiviato, importando anche i dizionari. Definiamo anche una funzione per svolgere tokenizzazione sul testo sfruttando nltk.
A questo punto tokenizziamo il testo, ne facciamo il padding alla lunghezza massima specificata e lo diamo in input al modello, che restituirà per ogni token il tag e la probabilità associata.
Come già detto, utilizzare Tensorflow, piuttosto che un'altra libreria di Deep Learning, per addestrare modelli per task di questo
genere, risulta più complesso e richiede maggiore conoscenza di tutti gli aspetti alla base del Machine Learning.
In molti casi strumenti come Spacy permettono di raggiungere livelli di prestazioni molto alti, ma qualora non si riescano
a raggiungere prestazioni degne di nota, allora strumenti come Tensorflow, possono essere utilizzati per ricercare la rete neurale e la
configurazione che più fa al proprio caso.
Applicazioni delle NER
La capacità di individuare in modo intelligente e efficace entità nel testo, permette di fatto di taggare i contenuti testuali con quelli che possono risultare dei concetti rilevanti per quest'ultimi. Questo si traduce nella possibilità di realizzare o migliorare una serie di possibili applicazioni.
🔍 Sistemi di ricerca
Attraverso l'utilizzo della NER è possibile migliorare sia in efficienza che in efficacia i sistemi di ricerca.
In efficienza, andando di fatto, a svolgere le ricerche direttamente sulla lista di tag o entità associate ai diversi contenuti,
invece di svolgere una ricerca full text.
In efficacia, permettendo di svolgere delle ricerche mirate, su determinati tipi di entità.
Ad esempio, se voglio cercare i documenti che fanno riferimento ad una determinata persona o organizzazione, posso riconoscere attraverso
la NER questi tipi di entità, e mapparli su appositi campi, andando di fatto a svolgere una ricerca che filtra in base al tipo di categoria e al
valore specificato.
O ad esempio, taggare le email passsate, con persone e indirizzi email, specificandone anche il contesto.
Un'applicazione di questo genere può risultare molto importante in un contesto enterprise, con lo scopo di cercare in modo rapido ed efficacie,
i contenuti di un'azienda, di un dipendente piuttosto che di un cliente.
☎️ Customer Service
Il customer care delle aziende si trova a dover navigare tra centinaia o migliaia di messaggi di assistenza al giorno. La possibilità di taggare i diversi messaggi e ticket in arrivo, può velocizzare di molto la capacità di inviare in modo corretto e rapido i ticket ai reparti specializzati nel prendere in carico una specifica tipologia di problema.
👀 Sistemi di raccomandazione
Nei sistemi di raccomandazione risulta fondamentale analizzare ciò che un utente esplora, e nel caso di un sistema di raccomandazione testuale, come può essere un strumento di raccomandazione di news ad esempio, la capacità di riconoscere entità nel testo permette di analizzare i contenuti che l'utente visita, in modo da poi raccomandarne dei simili.