Elaborazione del linguaggio naturale: una questione di strutture
Sappiamo bene che i computer sono bravissimi a lavorare con dati strutturati come i fogli di calcolo e con le tabelle di un database; noi umani invece di solito comunichiamo a parole, non con tabelle. Questo può portare ad un problema di comunicazione: non tutte le informazioni del mondo reale sono strutturate.
Un testo che per un umano è perfettamente comprensibile, per un computer rappresenta una serie di stringhe senza alcun senso apparente.
L’elaborazione del linguaggio naturale, o NLP da Natural Language Processing, è un sottocampo dell’intelligenza artificiale che si concentra sul consentire ai computer di comprendere ed elaborare i linguaggi umani. Da quando esistono i computer, i programmatori hanno cercato di scrivere programmi che capissero diversi tipi di lingue.
Il motivo è abbastanza ovvio: gli esseri umani scrivono e comunicano da migliaia di anni e sarebbe davvero utile se un computer potesse leggere e comprendere tutte le informazioni raccolte finora. Il verbo comprendere non è sicuramente il più adatto, perché al momento un computer difficilmente può capire veramente una lingua nel modo in cui lo fanno gli esseri umani, ma è comunque in grado di svolgere operazioni non affatto banali.
Divide et programma
Il processo di analisi del linguaggio, a livello basilare, ha un processo piuttosto strutturato: diamo un’occhiata a come funziona e vediamo come potremmo scrivere dei programmi in grado di estrarre informazioni da un testo qualsiasi, ovviamente usando Python!
L’idea di base, così come avviene in molti campi nel settore scientifico, è suddividere un dato problema in pezzi molto piccoli così da poter sfruttare tecniche specifiche per il singolo sottoproblema e risolvere separatamente ogni pezzo, per poi unire i risultati. Prendiamo come esempio il seguente testo preso da Wikipedia nella biografia dell’attore Jim Parsons:
Jim Parsons nasce e cresce a Houston, Texas; figlio di Milton Joseph “Mickey/Jack” Parsons, deceduto in un incidente d’auto nel 2001, e dell’insegnante Judy Ann McKnight. Ha una sorella, Julie, che fa l’insegnante e che l’ha reso zio. Decide fin da piccolo di diventare attore. Studia all’Università di Houston, dove diviene un membro della confraternita Pi Kappa Alpha. Ha poi conseguito la laurea specialistica presso l’Università di San Diego, dove si esibiva all’Old School Theatre. Si trasferisce a New York per continuare la sua carriera di attore. Alcuni dei ruoli più importanti da lui interpretati includono l’apparizione come personaggio ricorrente nella serie Giudice Amy e un’apparizione speciale nella serie Ed.
Questo testo contiene diverse informazioni utili; sarebbe interessante se un computer potesse leggerlo e capire che Jim Parsons è una persona, che è un attore di mestiere e che ha fatto diverse apparizioni nel settore dello spettacolo. Per arrivarci, dobbiamo effettuare alcuni passaggi:
Step 1: segmentazione
La tokenizzazione (chiamata anche segmentazione) delle frasi è il problema di dividere nelle sue frasi elementari una stringa di linguaggio scritto. L’idea può sembrare molto semplice: in inglese e in alcune altre lingue, possiamo dividere le frasi ogni volta che vediamo un segno di punteggiatura.
Tuttavia questo problema spesso non è banale, a causa dell’uso del carattere di punto per le abbreviazioni: ad esempio la stringa J. Parsons in una frase potrebbe dare origine a un po’ di confusione nel sistema. In molti casi andranno usate librerie che facciano questo lavoro al posto nostro, quindi bypassiamo questo problema per ora; possiamo presumere per semplicità che ogni frase presente sia separata dalle altre per mezzo di un simbolo di punteggiatura.
Libreria Python: NLTK (PunktSentenceTokenizer).
Step 2: tokenizzazione
Ora che abbiamo diviso il nostro testo in frasi, possiamo elaborarle una alla volta. Cominciamo con la prima frase:
“Jim”, “Parsons”, “nasce”, “e”, “cresce”, “a”, “Houston”, …
La tokenizzazione è un’attività piuttosto semplice da eseguire e Python offre diverse librerie: divideremo semplicemente le parole ogni volta che c’è uno spazio tra di loro, trattando anche i segni di punteggiatura come segni separati poiché anche la punteggiatura ha un significato.
Libreria Python: NLTK (word_tokenize).
Step 3: POS
A questo punto, ogni token andrà esaminato per provare a indovinare di che parte del discorso si tratta: se parliamo di un sostantivo, un verbo, un aggettivo e così via. Conoscere il ruolo di ogni parola nella frase ci aiuterà a iniziare a capire il contesto della frase stessa.
Possiamo farlo inserendo ogni parola come input in un modello di classificazione del cosiddetto Part-of-Speech tagging: questo classificatore prenderà ogni parola e cercherà di assegnargli una categoria sulla base dell’esperienza maturata dal modello. Spesso questa tipologia di classificatori è basata su statistiche, quindi il sistema non capisce realmente il significato delle parole, ma piuttosto mette in correlazione quelle che di solito sono “accoppiate” con altre parole e quindi rendono plausibile l’interpretazione del loro uso all’interno di una frase.
Token |
Categoria |
Jim |
Sostantivo |
Parsons |
sostantivo |
nasce |
Verbo |
a |
Preposizione |
… |
… |
Libreria Python: NLTK (pos_tag).
Step 4: Lemmatizzazione e stemming
Per motivi grammaticali, i testi possono contenere diverse forme di una parola come parlare, parlati, parlante, parlai… A volte potremmo anche avere parole correlate con un significato simile, come nazione, nazionale, nazionalità.
L’obiettivo sia dello stemming che della lemmatizzazione è ridurre le forme più complesse in forma base, o forma radice: ad esempio, se avessimo sono, siamo, siano, la forma dopo l’operazione di stemming dovrebbe risultare essere.
La lemmatizzazione viene in genere eseguita a partire da una tabella di ricerca dei lemmi delle parole in base alla loro parte del discorso e possibilmente usando alcune regole personalizzate per gestire le parole che non sono mai state incontrate.
Libreria Python: NLTK (WordNetLemmatizer).
Step 5: Stopword
Le stopword sono parole che vengono filtrate prima o dopo l’elaborazione del testo. Quando si applicano delle tecniche di apprendimento automatico al testo, queste parole possono aggiungere molto rumore, senza aggiungere alcuna informazione al contesto di interesse.
Le parole non significative di solito si riferiscono alle parole più comuni come le congiunzioni, le preposizioni o simboli di punteggiatura come la virgola, ma non esiste un unico elenco universale di parole chiave. L’elenco delle parole chiave può cambiare a seconda dell’applicazione, e a seconda della lingua; per questo è importante usare strumenti che forniscano degli elenchi ad hoc per il tipo di attività che dobbiamo eseguire, elenchi che spesso richiedono anche lavoro aggiuntivo per adattarsi alle esigenze del momento.
Libreria Python: NLTK (stopwords).
Step 6: NER
L’obiettivo della Named Entity Recognition è rilevare ed etichettare i nomi con i concetti del mondo reale che rappresentano e che spesso sono la rappresentazione delle informazioni di cui abbiamo bisogno. Alcuni esempi di token estratti attraverso il nostro modello di tagging NER potrebbero essere i seguenti:
“Jim” “Parsons”, “Houston”, “actor”
I sistemi NER non eseguono solo una semplice ricerca nel dizionario: usano il contesto di come una parola appare nella frase e un modello statistico per indovinare quale tipo di nome rappresenta una parola.
Di seguito sono riportati solo alcuni dei tipi di entità che un tipico sistema NER può cercare e taggare:
-
I nomi delle persone;
-
Località geografiche;
-
Nomi dei servizi, aziende o prodotti;
-
Date e orari;
-
Importi di denaro;
-
Nomi di eventi.
Libreria Python: spaCy.
Questi naturalmente sono solo alcuni dei metodi e degli strumenti di base utilizzati nella NLP. Token, stopword, stemming e quant’altro hanno tutti un ruolo fondamentale all’interno di un processo di questo tipo, ma sono componenti piuttosto elementari di un sistema sofisticato di elaborazione del linguaggio.
Puoi approfondire questi concetti e trovare esempi che potrebbero fare al caso tuo per mezzo del mio libro sull’analisi del linguaggio con Python.
Immagine di apertura di Marcel Strauß su Unsplash.
L'autore
Corsi che potrebbero interessarti
Progettare una Landing Page - Che Funziona
Machine Learning & Big Data per tutti
Data governance: diritti, licenze e privacy