Traitement de données massives
Traitement automatique des langues naturelles (TAL)
John Samuel
CPE Lyon
Année: 2024-2025
Courriel: john.samuel@cpe.fr
Le traitement automatique des langues (TAL) est un domaine interdisciplinaire de la linguistique informatique qui se concentre sur l'analyse et la compréhension du langage naturel (celui utilisé par les humains). Cette section aborde plusieurs aspects clés du TAL, notamment :
Quelques exemples d'issues potentiellement non valides :
L'objectif est de réduire les mots à leur forme de base ou racine, en éliminant les suffixes, ce qui permet de regrouper différentes formes d'un mot sous une forme commune.
L'algorithme de Porter, également connu sous le nom de stemmer de Porter, est un algorithme de racination (stemming) développé par Martin Porter en 1980. Son objectif est de réduire les mots à leur forme racine ou base en éliminant les suffixes couramment utilisés en anglais.
L'algorithme de Porter utilise une série de règles de racination pour réduire les mots à leur forme racine. Quelques-unes des règles de l'algorithme de Porter :
from nltk.stem.porter import PorterStemmer
words = ["words", "eating", "went", "engineer", "tried"]
porter = PorterStemmer()
for word in words:
print(porter.stem(word), end=" ")
Affichage
word eat went engin tri
L'algorithme de Snowball, également connu sous le nom de Snowball stemmer, est un algorithme de racination (stemming) développé par Martin Porter comme une extension de son algorithme de Porter. Snowball a été conçu pour être plus modulaire et extensible, permettant aux utilisateurs de créer des stemmers pour différentes langues en utilisant un ensemble commun de conventions.
Les caractéristiques principales de l'algorithme de Snowball :
from nltk.stem.snowball import SnowballStemmer
words = ["words", "eating", "went", "engineer", "tried"]
snowball = SnowballStemmer("english")
for word in words:
print(snowball.stem(word))
Affichage
word eat went engin tri
from nltk import ngrams
sentence = "He went to school yesterday and attended the classes"
for n in range(1, 5):
print("\n{}-grams".format(n))
n_grams = ngrams(sentence.split(), n)
for ngram in n_grams:
print(ngram, end=" ")
1-grams
('He',) ('went',) ('to',) ('school',) ('yesterday',) ('and',) ('attended',) ('the',) ('classes',)
2-grams
('He', 'went') ('went', 'to') ('to', 'school') ('school', 'yesterday') ('yesterday', 'and') ('and', 'attended') ('attended', 'the') ('the', 'classes')
3-grams
('He', 'went', 'to') ('went', 'to', 'school') ('to', 'school', 'yesterday') ('school', 'yesterday', 'and') ('yesterday', 'and', 'attended') ('and', 'attended', 'the') ('attended', 'the', 'classes')
4-grams
('He', 'went', 'to', 'school') ('went', 'to', 'school', 'yesterday') ('to', 'school', 'yesterday', 'and') ('school', 'yesterday', 'and', 'attended') ('yesterday', 'and', 'attended', 'the') ('and', 'attended', 'the', 'classes')
from nltk import pos_tag, word_tokenize
sentence = "He goes to school daily"
tokens = word_tokenize(sentence)
print(pos_tag(tokens))
Affichage
[('He', 'PRP'), ('goes', 'VBZ'), ('to', 'TO'), ('school', 'NN'), ('daily', 'RB')]
[('He', 'PRP'), ('goes', 'VBZ'), ('to', 'TO'), ('school', 'NN'), ('daily', 'RB')]
Balise | Signification |
---|---|
PRP | pronoun, personal |
VBZ | verb, present tense, 3rd person singular |
TO | "to" as preposition |
NN | "noun, common, singular or mass |
RB | adverb |
Installation
$ pip3 install spacy
$ python3 -m spacy download en_core_web_sm
Usage
import spacy
nlp = spacy.load("en_core_web_sm")
import spacy
nlp = spacy.load("en_core_web_sm")
doc = nlp("He goes to school daily")
for token in doc:
print(token.text, token.pos_, token.dep_)
He PRON nsubj
goes VERB ROOT
to ADP prep
school NOUN pobj
daily ADV advmod
import spacy
nlp = spacy.load("en_core_web_sm")
doc = nlp("He goes to school daily")
for token in doc:
print(token.text, token.lemma_, token.pos_, token.tag_, token.dep_,
token.shape_, token.is_alpha, token.is_stop)
He -PRON- PRON PRP nsubj Xx True True
goes go VERB VBZ ROOT xxxx True False
to to ADP IN prep xx True True
school school NOUN NN pobj xxxx True False
daily daily ADV RB advmod xxxx True False
import nltk
nltk.download('punkt')
nltk.download('wordnet')
nltk.download('averaged_perceptron_tagger')
from nltk.stem import WordNetLemmatizer
sentence = "He went to school yesterday and attended the classes"
lemmatizer = WordNetLemmatizer()
for word in sentence.split():
print(lemmatizer.lemmatize(word), end=' ')
Affichage
He went to school yesterday and attended the class
from nltk.stem import WordNetLemmatizer
from nltk import word_tokenize, pos_tag
from nltk.corpus import wordnet as wn
# Check the complete list of tags http://www.nltk.org/book/ch05.html
def wntag(tag):
if tag.startswith("J"):
return wn.ADJ
elif tag.startswith("R"):
return wn.ADV
elif tag.startswith("N"):
return wn.NOUN
elif tag.startswith("V"):
return wn.VERB
return None
lemmatizer = WordNetLemmatizer()
sentence = "I went to school today and he goes daily"
tokens = word_tokenize(sentence)
for token, tag in pos_tag(tokens):
if wntag(tag):
print(lemmatizer.lemmatize(token, wntag(tag)), end=' ')
else:
print(lemmatizer.lemmatize(token), end=' ')
Affichage
I go to school today and he go daily
import spacy
nlp = spacy.load("en_core_web_sm")
doc = nlp("I went to school today and he goes daily")
for token in doc:
print(token.lemma_, end=' ')
-PRON- go to school today and -PRON- go daily
import spacy
from spacy import displacy
nlp = spacy.load("en_core_web_sm")
doc = nlp("He goes to school daily")
displacy.render(doc, style="dep", jupyter=True)
Les embeddings de mots sont une technique d'apprentissage de caractéristiques où des mots ou des phrases du vocabulaire sont associés à des vecteurs de nombres réels.
Avantages de Word Embeddings
Applications de Word Embeddings
spaCy est une bibliothèque open-source pour le traitement du langage naturel (NLP) en Python. Elle offre des outils performants et efficaces pour effectuer diverses tâches de traitement du langage naturel, de l'analyse syntaxique à la reconnaissance d'entités nommées. spaCy est conçu pour être rapide, précis et facile à utiliser.
spaCy propose différents modèles linguistiques pré-entraînés pour différentes langues et tâches. Le modèle en_core_web_lg est un modèle vectoriel large d'anglais.
$ python3 -m spacy download en_core_web_lg
import spacy
# Charger le modèle spaCy
nlp = spacy.load("en_core_web_lg")
Avantages de spaCy :
Limites de spaCy :
import spacy
# Charger le modèle spaCy
nlp = spacy.load("en_core_web_lg")
# Définir les mots à comparer
words_to_compare = ["dog", "cat", "apple"]
# Calculer la similarité entre les paires de mots
for i in range(len(words_to_compare)):
for j in range(i + 1, len(words_to_compare)):
word1, word2 = words_to_compare[i], words_to_compare[j]
doc1, doc2 = nlp(word1), nlp(word2)
similarity_score = doc1.similarity(doc2)
print("Similarité ({} / {}): {:.4f}".format(word1, word2,
similarity_score))
Similarité (dog / cat): ...
Similarité (dog / apple): ...
Similarité (cat / apple): ...
import spacy
# Charger le modèle spaCy
nlp = spacy.load("en_core_web_sm")
# Texte à analyser
text_to_analyze = "cat"
doc = nlp(text_to_analyze)
# Imprimer les vecteurs de chaque jeton sur une seule ligne
vector_list = [token.vector for token in doc]
print("Vecteurs de '{}' : {}".format(text_to_analyze, vector_list))
Word2Vec a marqué un tournant significatif dans la représentation des mots dans le domaine de l'apprentissage automatique.
L'implémentation de Word2Vec se déroule en plusieurs étapes :
CBOW est un modèle spécifique de Word2Vec. Dans ce modèle, la prédiction du mot courant se fait en utilisant une fenêtre de mots contextuels voisins. L'ordre des mots de contexte n'influence pas la prédiction, ce qui en fait une approche robuste.
import gensim
from nltk.tokenize import sent_tokenize, word_tokenize
# Données d'exemple
data = "This is a class. This is a table"
# Prétraitement des données en utilisant nltk pour obtenir des phrases et des mots
sentences = [word_tokenize(sentence.lower()) for sentence in sent_tokenize(data)]
# Construction du modèle CBOW avec Gensim
# min_count: Ignorer tous les mots dont la fréquence totale est inférieure à cette valeur.
# vector_size: Dimension des embeddings de mots
# window: Distance maximale entre le mot courant et le mot prédit dans une phrase
cbow_model = gensim.models.Word2Vec(sentences, min_count=1, vector_size=100,
window=3, sg=0)
# Affichage du vecteur du mot "this"
print("Vecteur du mot 'this':", cbow_model.wv["this"])
# Similarité entre les mots "this" et "class"
print("Similarité entre 'this' et 'class':", cbow_model.wv.similarity("this",
"class"))
# Prédiction des deux mots les plus probables suivant le mot "is"
predicted_words = cbow_model.wv.most_similar(positive=["is"], topn=2)
print("Prédiction des mots suivant 'is':", predicted_words)
Le modèle Skip-gram est une autre variante de Word2Vec qui se concentre sur la prédiction de la fenêtre voisine des mots de contexte à partir du mot courant.
import gensim
from nltk.tokenize import sent_tokenize, word_tokenize
# Données d'exemple
data = "This is a class. This is a table"
# Prétraitement des données en utilisant nltk pour obtenir des phrases et des mots
sentences = [word_tokenize(sentence.lower()) for sentence in sent_tokenize(data)]
# Construction du modèle Skip-gram avec Gensim
# min_count: Ignorer tous les mots dont la fréquence totale est inférieure à cette valeur.
# vector_size: Dimension des embeddings de mots
# window: Distance maximale entre le mot courant et le mot prédit dans une phrase
# sg: 1 pour skip-gram ; sinon CBOW.
skipgram_model = gensim.models.Word2Vec(sentences, min_count=1, vector_size=100,
window=5, sg=1)
# Affichage du vecteur du mot "this"
print("Vecteur du mot 'this':", skipgram_model.wv["this"])
# Similarité entre les mots "this" et "class"
print("Similarité entre 'this' et 'class':", skipgram_model.wv.similarity("this", "class"))
# Prédiction des mots les plus probables dans le contexte entourant le mot "is"
predicted_words = skipgram_model.wv.most_similar(positive=["is"], topn=2)
print("Prédiction des mots dans le contexte de 'is':", predicted_words)
La Reconnaissance d'Entités Nommées (NER) consiste à identifier et classer des entités spécifiques dans un texte. Ces entités peuvent inclure des personnes, des lieux, des organisations, des dates, des montants monétaires, etc. Le but est d'extraire des informations structurées à partir de données textuelles non structurées.
La Reconnaissance d'Entités Nommées (NER) est souvent réalisée à l'aide de modèles d'apprentissage automatique, et plusieurs algorithmes peuvent être utilisés dans ce contexte. Quelques-uns des algorithmes couramment employés :
import spacy
# Charger le modèle spaCy
nlp = spacy.load("en_core_web_sm")
# Texte à analyser
text_to_analyze = "Paris is the capital of France." + "In 2015, its population was recorded as 2,206,488"
# Analyser le texte
doc = nlp(text_to_analyze)
# Afficher les informations sur les entités
for entity in doc.ents:
entity_text = entity.text
start_char = entity.start_char
end_char = entity.end_char
label = entity.label_
print("Entité: {}, Début: {}, Fin: {}, Catégorie: {}".format(entity_text,
start_char, end_char, label))
Entité: Paris, Début: 0, Fin: 5, Catégorie: GPE
Entité: France, Début: 24, Fin: 30, Catégorie: GPE
Entité: 2015, Début: 35, Fin: 39, Catégorie: DATE
Entité: 2,206,488, Début: 72, Fin: 81, Catégorie: CARDINAL
import spacy
from spacy import displacy
def visualize_entities(text):
# Charger le modèle spaCy
nlp = spacy.load("en_core_web_sm")
# Analyser le texte
doc = nlp(text)
# Visualiser les entités nommées avec displaCy
displacy.serve(doc, style="ent")
# Texte à analyser et visualiser
text_to_analyze = "Paris is the capital of France." + "In 2015, its population was recorded as 2,206,488"
# Appeler la fonction pour analyser et visualiser les entités
visualize_entities(text_to_analyze)
import spacy
from spacy import displacy
def visualize_entities(text):
# Charger le modèle spaCy
nlp = spacy.load("en_core_web_sm")
# Analyser le texte
doc = nlp(text)
# Visualiser les entités nommées avec displaCy
displacy.render(doc, style="ent", jupyter=True)
# Texte à analyser et visualiser
text_to_analyze = "Paris is the capital of France. In 2015, its population was recorded as 2,206,488"
# Appeler la fonction pour analyser et visualiser les entités
visualize_entities(text_to_analyze)
Balise | Signification |
---|---|
GPE | Pays, villes, états. |
DATE | Dates ou périodes absolues ou relatives |
CARDINAL | Les chiffres qui ne correspondent à aucun autre type. |
Le lexique VADER (Valence Aware Dictionary and sEntiment Reasoner) est spécifiquement conçu pour analyser les sentiments dans du texte en attribuant des scores de positivité, négativité et neutralité aux mots ainsi qu'aux expressions.
import nltk
nltk.download('vader_lexicon')
VADER est une bibliothèque d'analyse de sentiment conçue pour évaluer le sentiment d'un morceau de texte, généralement une phrase ou un paragraphe.
VADER est souvent utilisé pour l'analyse de sentiment rapide et basée sur des règles. Bien qu'il soit efficace dans de nombreux cas, il peut ne pas être aussi précis que des méthodes plus complexes basées sur l'apprentissage automatique, notamment dans des contextes où l'analyse nécessite une compréhension plus profonde du langage et de la syntaxe.
from nltk.sentiment.vader import SentimentIntensityAnalyzer
sia = SentimentIntensityAnalyzer()
sentiment = sia.polarity_scores("this movie is good")
print(sentiment)
sentiment = sia.polarity_scores("this movie is not very good")
print(sentiment)
sentiment = sia.polarity_scores("this movie is bad")
print(sentiment)
Les scores renvoyés par VADER représentent différentes mesures du sentiment dans un texte. Une explication de chaque score :
Les scores sont normalisés dans une échelle de -1 à 1, où -1 représente un sentiment extrêmement négatif, 1 représente un sentiment extrêmement positif, et 0 représente la neutralité. Les scores peuvent être interprétés individuellement ou conjointement pour obtenir une compréhension complète du sentiment dans le texte analysé.
Affichage
{'neg': 0.0, 'neu': 0.508, 'pos': 0.492, 'compound': 0.4404}
{'neg': 0.344, 'neu': 0.656, 'pos': 0.0, 'compound': -0.3865}
{'neg': 0.538, 'neu': 0.462, 'pos': 0.0, 'compound': -0.5423}