Dans un précédent article nous avons vu comment la librairie SpaCy pouvait nous aider à analyser et surtout exploiter des données textuelles. Nous allons voir dans cet article comment utiliser l’autre librairie (quelque peu concurrente, mais pas tant que ça finalement) NLTK de Python.
Installation de NLTK
Pour commencer nous devons installer la librairie. Pour celà vous devez bien sur déjà disposer de Python sur votre machine et ensuite utiliser PIP (package installer for Python) pour installer la librairie nltk :
pip install nltk
Ce n’est pas vraiment fini, car une fois la librairie installée, il faut maintenant télécharger tout le corpus NLTK afin de pouvoir utiliser ses fonctionnalités correctement.
Un corpus est un ensemble de documents, artistiques ou non (textes, images, vidéos, etc.), regroupés dans une optique précise.
Wikipédia
Dans notre cas, on n’entend par corpus que les éléments textuels.
Pour installer ces fameux corpus NLTK, et si comme moi vous utilisez Jupyter tapez simplement :
import nltk
nltk.download()
Attendez quelques secondes et une fenêtre devrait s’ouvrir :
Nous n’allons pas être sélectif et tout prendre pour ce tuto. Sélectionnez « All » et cliquez sur le bouton Download dans le coin inférieur gauche de la fenêtre. Puis patientez jusqu’à ce que tout soit téléchargé dans votre dossier de destination …
Commençons !
Maintenant que notre environnement NLTK est prêt, nous allons voir ensemble les fonctions de base de cette librairie. Pour celà nous allons utiliser ce texte :
Wikipédia est un projet wiki d’encyclopédie collective en ligne, universelle, multilingue et fonctionnant sur le principe du wiki. Aimez-vous l’encyclopédie wikipedia ?
Ensuite importons les librairies qui nous seront nécessaire:
from nltk.corpus import stopwords
from nltk import word_tokenize
from nltk.tokenize import sent_tokenize
import re
data = u"""Wikipédia est un projet wiki d’encyclopédie collective en ligne, universelle, multilingue et fonctionnant sur le principe du wiki. Aimez-vous l'encyclopédie wikipedia ?"""
Les « stops words »
Avant toute chose il faudra retirer tous les mots qui n’apportent pas vraiment de valeurs à l’analyse globale du texte. On appelle ces mots les « stop words » et bien sur cette liste est propre à chaque langue. Bonne nouvelle, NLTK propose une liste de stop words en Français (toutes les langues ne sont en effet pas disponibles) :
french_stopwords = set(stopwords.words('french'))
filtre_stopfr = lambda text: [token for token in text if token.lower() not in french_stopwords]
Grâce à la fonction lambda de Python on créé une petite fonction qui nous permettra en une seule ligne de filtrer un texte à partir de la liste des stop words français.
french_stopwords = set(stopwords.words(‘french’)) filtre_stopfr = lambda text: [token for token in text if token.lower() not in french_stopwords]
Grâce à la fonction lambda de Python on créé une petite fonction qui nous permettra en une seule ligne de filtrer un texte à partir de la liste des stop words français.
filtre_stopfr( word_tokenize(data, language="french") )
['Wikipédia',
'projet',
'wiki',
'’',
'encyclopédie',
'collective',
'ligne',
',',
'universelle',
',',
'multilingue',
'fonctionnant',
'principe',
'wiki',
'.',
'Aimez-vous',
"l'encyclopédie",
'wikipedia',
'?']
Voilà tous les mots (du genre articles, etc.) on été supprimés de la liste globale de mots. Cette fonction est vraiment utile, comparez par exemple avec un filtre qui n’utiliserait que des RegEx :
sp_pattern = re.compile( """[\.\!\"\s\?\-\,\']+""", re.M).split
sp_pattern(data)
Tokenisation
Avec NLTK on peut découper par mot avec la fonction word_tokenize(…) ou par phrase sent_tokenize(…). Commençons par un découpage par phrase :
sent_tokenize(data, language="french")
['Wikipédia est un projet wiki d’encyclopédie collective en ligne, universelle, multilingue et fonctionnant sur le principe du wiki.',
"Aimez-vous l'encyclopédie wikipedia ?"]
Intéressant mais la tokenization par mot l’est encore plus bien sur :
word_tokenize(data, language="french")
['Wikipédia',
'est',
'un',
'projet',
'wiki',
'd',
...
'Aimez-vous',
"l'encyclopédie",
'wikipedia',
'?']
Et si on combine cette fonction avec le filtre des stops words vu précédemment, c’est encore plus intéressant :
filtre_stopfr( word_tokenize(data, language="french") )
['Wikipédia',
'projet',
'wiki',
'’',
'encyclopédie',
'collective',
'ligne',
',',
'universelle',
',',
'multilingue',
'fonctionnant',
'principe',
'wiki',
'.',
'Aimez-vous',
"l'encyclopédie",
'wikipedia',
'?']
Fréquence de distribution des valeurs
Il peut être intéressant d’avoir la fréquence de distribution des valeurs, pour celà il existe bien entendu une fonction FreqDist():
fd = nltk.FreqDist(phfr)
print(fd.most_common())
[('wiki', 2), (',', 2), ('Wikipédia', 1), ('projet', 1), ('’', 1), ('encyclopédie', 1), ('collective', 1), ('ligne', 1), ('universelle', 1), ('multilingue', 1), ('fonctionnant', 1), ('principe', 1), ('.', 1), ('Aimez-vous', 1), ("l'encyclopédie", 1), ('wikipedia', 1), ('?', 1)]
Cette fonction renvoit un Tableau a deux dimensions dans lequel on trouve chaque valeur du corpus avec sa fréquence de distribution. A titre d’exemple le mot wiki est placé 2 fois dans le texte.
Stemmatisation
Maintenant il serait interressant de regrouper les mots ayant la même racine synthaxique, pour cela nous allons utiliser la fonction de stemmatisation de NLTK : stem(). Bonne nouvelle encore il existe une fonction pour le français FrenchStemmer() ! nous allons bien sur l’utiliser ici :
example_words = ["donner","don","donne","donnera","dons","test"]
stemmer = FrenchStemmer()
for w in example_words:
print(stemmer.stem(w))
don
don
don
don
don
test
La fonction de stemmatisation a bien retrouvé les racines du mot « don ». Honnêtement ça ne marche pas toujours aussi bien malheureusement, mais cette fonction peut néanmoins s’avérer utile pour un premier débroussaillage.
Conclusion
L’objectif de cet article étant de montrer les fonctionnalités de base de NLTK nous ne sommes pas entré dans le détail. Cette librairie est riche, très riche même mais nécessite pas mal d’ajustement si vous voulez créer des fonctions à base de NLP puissante. Les différences avec SpaCy ? en fait il en a beaucoup, la philosophie des ces deux librairie est totalement différente (objet vs approche traditionnelle pour NLTK par exemple) … en fait je pense qu’il faut plutot voir ces deux librairies comme complémentaires, chacune apportant à l’autre ses propres manques.
Ingénieur en informatique avec plus de 20 ans d’expérience dans la gestion et l’utilisation de données, Benoit CAYLA a mis son expertise au profit de projets très variés tels que l’intégration, la gouvernance, l’analyse, l’IA, la mise en place de MDM ou de solution PIM pour le compte de diverses entreprises spécialisées dans la donnée (dont IBM, Informatica et Tableau). Ces riches expériences l’ont naturellement conduit à intervenir dans des projets de plus grande envergure autour de la gestion et de la valorisation des données, et ce principalement dans des secteurs d’activités tels que l’industrie, la grande distribution, l’assurance et la finance. Également, passionné d’IA (Machine Learning, NLP et Deep Learning), l’auteur a rejoint Blue Prism en 2019 et travaille aujourd’hui en tant qu’expert data/IA et processus. Son sens pédagogique ainsi que son expertise l’ont aussi amené à animer un blog en français (datacorner.fr) ayant pour but de montrer comment comprendre, analyser et utiliser ses données le plus simplement possible.
Merci beaucoup pour votre super article très clair et concis 🙂
Merci pour cet article qui m’a permis de monter mon colab en y ajoutant BeautifulSoup pour aller un epu plus loin et scraper le contenu d’un site puis d’en analyser les entitées.
Ce que je trouve dommage : la liste de stopwords n’est pas assez large. En effet, il reste à la fin des , . / ? ! $…
Je ne suis pas dev et pas bon en python. j’ai essayé d’appliqyer la regex que tu mentionnes, en plus de la liste de stopwords, mais je me retrouve avec une erreur…
Au plaisir,
Clément
Bonjour Benoit,
A mon tour je te remercie pour ta présentation.
Je partage l’avis de Clément, les « : » et « / » qui restent dans le texte proviennent de la concaténation des mots pour passer d’un filtre à l’autre.
Une fois modifié ce point, je te proposerai également d’enlever le « set » de la ligne :
french_stopwords = set(stopwords.words(‘french’)) D’ailleurs il apparaît en rouge
Sans le « set » il est faile de « french_stopwords.append(‘re’) pour enrichir la liste de ‘re’ par exemple
Qu’en penses tu ?
Bien codialement,
Maussa
Merci bcp pour cet article et ce site, très intéressants.
A la ligne fd = nltk.FreqDist(phfr), la variable phfr n’existe pas, mais il suffit de l’affecter à filtre_stopfr(word_tokenize(data, language= »french »))
A la ligne stemmer = FrenchStemmer(), FrenchStemmer() n’est pas reconnu par Python. J’ai remplacé par stemmer=nltk.stem.SnowballStemmer(‘french’)