7 tecniche di NLP facilmente implementabili con Python
Sono sufficienti alcune righe di codice per implementare le tecniche di NLP con Python.
L’elaborazione del linguaggio naturale (NLP) si occupa di consentire ai computer di comprendere ed elaborare il linguaggio umano. I computer sono bravissimi a lavorare con dati strutturati come i fogli di calcolo; tuttavia, molte informazioni che scriviamo o parliamo sono non strutturate.
L’obiettivo della NLP è far sì che i computer comprendano i testi non strutturati e ne ricavino informazioni significative. Grazie a librerie open-source come spaCy e NLTK, è possibile implementare molte tecniche di NLP con poche righe di codice in Python.
In questo articolo, impareremo i concetti fondamentali di 7 tecniche di NLP e come implementarle facilmente in Python.
1. Analisi del sentiment
L’analisi del sentimento è una delle tecniche NLP più popolari che consiste nel prendere un pezzo di testo (ad esempio, un commento, una recensione o un documento) e determinare se i dati sono positivi, negativi o neutrali. Ha molte applicazioni nel settore sanitario, nel servizio clienti, nelle banche, ecc.
Implementazione in Python
Per casi semplici, in Python possiamo utilizzare VADER (Valence Aware Dictionary for Sentiment Reasoning), disponibile nel pacchetto NLTK, che può essere applicato direttamente ai dati di testo non etichettati. A titolo di esempio, vediamo di ottenere tutti i punteggi di sentiment delle battute pronunciate dai personaggi di un programma televisivo.
Per prima cosa, si utilizza un set di dati disponibile su Kaggle o sul mio Github denominato “avatar.csv”, quindi con VADER si calcola il punteggio di ogni battuta pronunciata. Tutto questo viene memorizzato nel dataframe df_character_sentiment.
Nel df_character_sentiment qui sotto, possiamo vedere che ogni frase riceve un punteggio negativo, neutro e positivo.
Potremmo anche raggruppare i punteggi per carattere e calcolare la media per ottenere il punteggio di sentiment per un carattere e poi rappresentarlo con diagrammi a barre orizzontali utilizzando la libreria matplotlib (il risultato è mostrato in questo articolo).
Nota: VADER è ottimizzato per i testi dei social media, quindi i risultati vanno presi con le molle. È possibile utilizzare un algoritmo più completo o svilupparne uno proprio con le librerie di apprendimento automatico. Nel link qui sotto, c’è una guida completa su come crearne uno da zero con Python utilizzando la libreria sklearn.
2. Riconoscimento di entità denominate (NER)
Il Named Entity Recognition è una tecnica utilizzata per individuare e classificare le entità nominate in un testo in categorie quali persone, organizzazioni, luoghi, espressioni di tempo, quantità, valori monetari, percentuali, ecc. È utilizzata per ottimizzare gli algoritmi dei motori di ricerca, i sistemi di raccomandazione, l’assistenza clienti, la classificazione dei contenuti, ecc.
Implementazione in Python
In Python, possiamo utilizzare il riconoscimento di entità denominate di SpaCy che supporta i seguenti tipi di entità.
Per vederla in azione, importiamo prima spacy e poi creiamo una variabile nlp che memorizzerà la pipelineen_core_web_sm. Si tratta di una piccola pipeline inglese addestrata su testi web scritti (blog, notizie, commenti), che include vocabolario, vettori, sintassi ed entità. Per trovare le entità, applichiamo nlp a una frase.
Vengono stampati i seguenti valori
Spacy ha scoperto che “Biden” è una persona, “Ukranian” è GPE (Paesi, città, Stati), “White House” è un’organizzazione e “this summer” è una data.
Se siete curiosi di vedere altre applicazioni di Spacy e di approfondire l’argomento del NLP, trovate più informazioni nel nostro corso “Natural Language Processing Hands-on (1)”
import spacynlp = spacy.load("en_core_web_sm")
doc = nlp("Biden invites Ukrainian president to White House this summer")print([(X.text, X.label_) for X in doc.ents])
[('Biden', 'PERSON'), ('Ukrainian', 'GPE'), ('White House', 'ORG'), ('this summer', 'DATE')]
3. Stemmatizzazione e lemmatizzazione
La stemmatizzazione e la lemmatizzazione sono due tecniche popolari in NLP. Entrambe normalizzano una parola, ma in modi diversi.
– Stemming: Tronca una parola alla sua radice. Ad esempio, le parole “amici”, “amicizia”, “amicizie” saranno ridotte a “amico”. La diramazione può non fornire una parola grammaticale del dizionario per un particolare insieme di parole.
– Lemmatizzazione: A differenza della tecnica di stemming, la lemmatizzazione trova la parola del dizionario invece di troncare la parola originale. Gli algoritmi di lemmatizzazione estraggono il lemma corretto di ogni parola, quindi spesso richiedono un dizionario della lingua per poter classificare correttamente ogni parola.
Entrambe le tecniche sono ampiamente utilizzate e devono essere scelte in modo oculato in base agli obiettivi del progetto. La lemmatizzazione ha una velocità di elaborazione inferiore rispetto alla stemmatizzazione, quindi se l’obiettivo del progetto non è l’accuratezza, ma la velocità, la stemmatizzazione è un approccio appropriato; tuttavia, se l’accuratezza è fondamentale, si può prendere in considerazione la lemmatizzazione.
La libreria NLTK di Python permette di lavorare facilmente con entrambe le tecniche. Vediamola in azione.
Implementazione di Python (Stemming)
Per la lingua inglese, sono disponibili due librerie popolari in nltk: Porter Stemmer e LancasterStemmer.
L’algoritmo PorterStemmer non segue la linguistica, ma un insieme di 5 regole per casi diversi che vengono applicate in fasi successive per generare gli stem. Il codice print(porter.stem(“amicizia”)) stamperà la parola amicizia.
LancasterStemmer è semplice, ma è possibile che si verifichino pesanti stemming dovuti a iterazioni e over-stemming. Questo fa sì che gli stem non siano linguistici o che non abbiano alcun significato. Il codice print(lancaster.stem(“amicizia”)) stamperà la parola amico.
Si può provare con qualsiasi altra parola per vedere come differiscono i due algoritmi. Nel caso di altri linguaggi, è possibile importare SnowballStemme da nltk.stem
Implementazione Python (lemmatizzazione)
Utilizzeremo ancora NLTK, ma questa volta importeremo WordNetLemmatizer come mostrato nel codice seguente.
La lemmatizzazione genera output diversi per diversi valori di Part Of Speech (POS). Alcuni dei valori POS più comuni sono verbo (v), nome (n), aggettivo (a) e avverbio (r). Il valore POS predefinito nella lemmatizzazione è un nome, quindi i valori stampati per l’esempio precedente saranno articolo, amicizia, studio e telefono.
Cambiamo il valore POS in verbo (v).
In questo caso, Python stamperà la parola be per tutti i valori dell’elenco.
from nltk.stem import PorterStemmer
from nltk.stem import LancasterStemmer# PorterStemmer
porter = PorterStemmer()
# LancasterStemmer
lancaster = LancasterStemmer()print(porter.stem("friendship"))
print(lancaster.stem("friendship"))
da nltk import WordNetLemmatizerlemmatizer = WordNetLemmatizer()
words = ['articoli', 'amicizia', 'studi', 'telefoni']for word in words:
print(lemmatizer.lemmatize(word))
da nltk import WordNetLemmatizerlemmatizer = WordNetLemmatizer()
words = ['be', 'is', 'are', 'were', 'was']for word in words:
print(lemmatizer.lemmatize(word, pos='v'))
4. Sacco di parole
Il modello Bag of Words (BoW) è una rappresentazione che trasforma il testo in vettori di lunghezza fissa. Questo ci aiuta a rappresentare il testo in numeri, in modo da poterlo utilizzare per i modelli di apprendimento automatico. Il modello non si preoccupa dell’ordine delle parole, ma solo della loro frequenza nel testo. Trova applicazione nella PNL, nel reperimento di informazioni dai documenti e nella classificazione dei documenti.
Il tipico flusso di lavoro di BoW prevede la pulizia del testo grezzo, la tokenizzazione, la costruzione di un vocabolario e la generazione di vettori.
Implementazione Python
La libreria sklearn di Python contiene uno strumento chiamato CountVectorizer che si occupa della maggior parte del flusso di lavoro BoW.
Utilizziamo le due frasi seguenti come esempio.
Frase 1: “Amo scrivere codice in Python. Adoro il codice Python”.
Frase 2: “Odio scrivere codice in Java. Odio il codice Java”.
Entrambe le frasi saranno memorizzate in un elenco chiamato testo. Poi creeremo un dataframe df per memorizzare questo elenco di testi. Dopodiché, avvieremo un’istanza di CountVectorizer(cv), e quindi adatteremo e trasformeremo i dati di testo per ottenere la rappresentazione numerica. Questa sarà memorizzata in una matrice documento-termine df_dtm.
importare pandas come pd
La rappresentazione BoW realizzata con CountVectorizer e memorizzata in df_dtm ha l’aspetto della figura seguente. Si tenga presente che le parole con 2 o meno lettere non vengono prese in considerazione dal CountVectorizer.
Come si può vedere, i numeri all’interno della matrice rappresentano il numero di volte in cui ogni parola è stata menzionata in ogni recensione. Parole come “amore”, “odio” e “codice” hanno la stessa frequenza (2) in questo esempio.
Nel complesso, possiamo dire che CountVectorizer fa un buon lavoro di tokenizzazione del testo, costruzione di un vocabolario e generazione di vettori; tuttavia, non pulisce i dati grezzi. Ho realizzato una guida su come pulire e preparare i dati in Python; consultatela nel caso vogliate imparare le migliori pratiche.
from sklearn.feature_extraction.text import CountVectorizertext = ["Amo scrivere codice in Python. Amo il codice Python",
"Odio scrivere codice in Java. Odio il codice Java"]df = pd.DataFrame({'recensione': ['recensione1', 'recensione2'], 'testo':text})
cv = CountVectorizer(stop_words='english')
cv_matrix = cv.fit_transform(df['text'])
df_dtm = pd.DataFrame(cv_matrix.toarray(),
indice=df['recensione'].valori,
colonne=cv.get_feature_names())
df_dtm
5. Frequenza dei termini - frequenza inversa dei documenti (TF-IDF)
A differenza del CountVectorizer, il TF-IDF calcola dei “pesi” che rappresentano la rilevanza di una parola per un documento in un insieme di documenti (alias corpus). Il valore TF-IDF aumenta proporzionalmente al numero di volte in cui una parola compare nel documento ed è compensato dal numero di documenti del corpus che la contengono. In parole povere, più alto è il punteggio TF-IDF, più raro o unico o prezioso è il termine e viceversa. Trova applicazione nel reperimento delle informazioni, come i motori di ricerca che mirano a fornire i risultati più pertinenti a ciò che si sta cercando.
Prima di vedere l’implementazione di Python, vediamo un esempio per avere un’idea di come vengono calcolati TF e IDF. Per l’esempio seguente, utilizzeremo le stesse frasi usate per l’esempio di CountVectorizer.
Frase 1: “Amo scrivere codice in Python. Adoro il codice Python”.
Frase 2: “Odio scrivere codice in Java. Odio il codice Java”.
Frequenza dei termini (TF)
Esistono diversi modi per definire la frequenza dei termini. Uno suggerisce il conteggio grezzo (cioè quello che fa il Vettorizzatore di conteggi), ma altri suggeriscono che si tratta della frequenza della parola nella frase divisa per il numero totale di parole nella frase. Per questo semplice esempio, utilizzeremo il primo criterio e la frequenza dei termini è mostrata nella tabella seguente.
Come si può vedere, i valori sono gli stessi calcolati in precedenza per il CountVectorizer. Inoltre, le parole con 2 o meno lettere non vengono prese in considerazione.
Frequenza inversa del documento (IDF)
Anche l’IDF viene calcolato in modi diversi. Sebbene la notazione standard dei libri di testo definisca l’IDF come idf(t) = log [ n / (df(t) + 1), la libreria sklearn che utilizzeremo in seguito in Python calcola la formula per impostazione predefinita come segue.
Inoltre, sklearn assume il logaritmo naturale ln invece del log e lo smoothing (smooth_idf=True). Calcoliamo i valori IDF per ogni parola come farà sklearn.
TF-IDF
Una volta ottenuti i valori TF e IDF, possiamo ottenere il TF-IDF moltiplicando entrambi i valori (TF-IDF = TF * IDF). I valori sono riportati nella tabella seguente.
Implementazione in Python
Il calcolo del TF-IDF mostrato nella tabella precedente in Python richiede poche righe di codice grazie alla libreria sklearn.
Nota: per impostazione predefinita, TfidfVectorizer() utilizza la normalizzazione l2, ma per utilizzare le stesse formule mostrate sopra si imposta come parametro norm=None. Per maggiori dettagli sulle formule utilizzate di default in sklearn e su come è possibile personalizzarle, consultare la documentazione.
import pandas as pd
from sklearn.feature_extraction.text import TfidfVectorizer
text = ["I love writing code in Python. I love Python code",
"I hate writing code in Java. I hate Java code"]df = pd.DataFrame({'review': ['review1', 'review2'], 'text':text})
tfidf = TfidfVectorizer(stop_words='english', norm=None)
tfidf_matrix = tfidf.fit_transform(df['text'])
df_dtm = pd.DataFrame(tfidf_matrix.toarray(),
index=df['review'].values,
columns=tfidf.get_feature_names())
df_dtm
6. Nube di parole
Wordcloud è una tecnica popolare che ci aiuta a identificare le parole chiave in un testo. In una wordcloud, le parole più frequenti hanno un carattere più grande e più grande, mentre le parole meno frequenti hanno un carattere più piccolo o più sottile. In Python, è possibile creare semplici wordcloud con la libreria wordcloud e wordcloud di bell’aspetto con la libreria stylecloud.
Di seguito è riportato il codice per creare una wordcloud in Python. Sto usando un file di testo di un discorso di Steve Jobs che potete trovare sul mio Github.
Questo è il risultato del codice precedente.
Le nuvole di parole sono così popolari perché sono coinvolgenti, facili da capire e da creare.
È possibile personalizzare ulteriormente il testo cambiando i colori, rimuovendo le stopword, scegliendo l’immagine o addirittura aggiungendo la propria immagine per utilizzarla come maschera della wordcloud. Per maggiori dettagli, consultate la guida qui sotto.
Articolo originale di Frank Andrade
import stylecloud.gen_stylecloud(file_path='SJ-Speech.txt',
icon_name="fas fa-apple-alt")