Quelques éléments pour comprendre les enjeux du NLP

Les corpus textuels étant des objets de très grande dimension où le ratio signal/bruit est faible, il est nécessaire de mettre en oeuvre une série d’étapes de nettoyage de texte. Ce chapitre va explorer quelques méthodes classiques de nettoyage en s’appuyant sur le Comte de Monte Cristo d’Alexandre Dumas.

NLP
Tutoriel
Author

Lino Galiana

Published

2024-05-08

Cette partie est une introduction à la question du nettoyage de données textuelles. Il s’agit de montrer la logique, quelques exemples avec Python et s’amuser avec comme base d’exemple un livre formidable 📖 : Le Comte de Monte Cristo.

L’objectif est de découvrir les principaux enjeux du nettoyage de données en NLP et les enjeux de l’analyse de fréquence.

1 Base d’exemple

La base d’exemple est le Comte de Monte Cristo d’Alexandre Dumas. Il est disponible gratuitement sur le site Project Gutemberg comme des milliers d’autres livres du domaine public.

La manière la plus simple de le récupérer est de télécharger avec le package Request le fichier texte et le retravailler légèrement pour ne conserver que le corpus du livre :

from urllib import request

url = "https://www.gutenberg.org/files/17989/17989-0.txt"
response = request.urlopen(url)
raw = response.read().decode("utf8")

dumas = raw.split(
    "*** START OF THE PROJECT GUTENBERG EBOOK LE COMTE DE MONTE-CRISTO, TOME I ***"
)[1].split(
    "*** END OF THE PROJECT GUTENBERG EBOOK LE COMTE DE MONTE-CRISTO, TOME I ***"
)[
    0
]

import re


def clean_text(text):
    text = text.lower()  # mettre les mots en minuscule
    text = " ".join(text.split())
    return text


dumas = clean_text(dumas)

dumas[10000:10500]
" mes yeux. --vous avez donc vu l'empereur aussi? --il est entré chez le maréchal pendant que j'y étais. --et vous lui avez parlé? --c'est-à-dire que c'est lui qui m'a parlé, monsieur, dit dantès en souriant. --et que vous a-t-il dit? --il m'a fait des questions sur le bâtiment, sur l'époque de son départ pour marseille, sur la route qu'il avait suivie et sur la cargaison qu'il portait. je crois que s'il eût été vide, et que j'en eusse été le maître, son intention eût été de l'acheter; mais je lu"

2 La particularité des données textuelles

2.1 Objectif

Le natural language processing (NLP) ou traitement automatisé du langage (TAL) en Français, vise à extraire de l’information de textes à partir d’une analyse statistique du contenu. Cette définition permet d’inclure de nombreux champs d’applications au sein du NLP (traduction, analyse de sentiment, recommandation, surveillance, etc. ).

Cette approche implique de transformer un texte, qui est une information compréhensible par un humain, en un nombre, information appropriée pour un ordinateur dans le cadre d’une approche statistique ou algorithmique.

Transformer une information textuelle en valeurs numériques propres à une analyse statistique n’est pas une tâche évidente. Les données textuelles sont non structurées puisque l’information cherchée, qui est propre à chaque analyse, est perdue au milieu d’une grande masse d’informations qui doit, de plus, être interprétée dans un certain contexte (un même mot ou une phrase n’ayant pas la même signification selon le contexte).

Si cette tâche n’était pas assez difficile comme ça, on peut ajouter d’autres difficultés propres à l’analyse textuelle car ces données sont :

  • bruitées : ortographe, fautes de frappe…
  • changeantes : la langue évolue avec de nouveaux mots, sens…
  • complexes : structures variables, accords…
  • ambiguës : synonymie, polysémie, sens caché…
  • propres à chaque langue : il n’existe pas de règle de passage unique entre deux langues
  • de grande dimension : des combinaisons infinies de séquences de mots

2.2 Méthode

L’analyse textuelle vise à transformer le texte en données numériques manipulables. Pour cela il est nécessaire de se fixer une unité sémantique minimale. Cette unité textuelle peut être le mot ou encore une séquence de n mots (un n-gramme) ou encore une chaîne de caractères (e.g. la ponctuation peut être signifiante). On parle de token.

On peut ensuite utiliser diverses techniques (clustering, classification supervisée) suivant l’objectif poursuivi pour exploiter l’information transformée. Mais les étapes de nettoyage de texte sont indispensables. Sinon un algorithme sera incapable de détecter une information pertinente dans l’infini des possibles.

3 Nettoyer un texte

Les wordclouds sont des représentations graphiques assez pratiques pour visualiser les mots les plus fréquents, lorsqu’elles ne sont pas utilisées à tort et à travers. Les wordclouds sont très simples à implémenter en Python avec le module Wordcloud. Quelques paramètres de mise en forme permettent même d’ajuster la forme du nuage à une image :

import wordcloud
import numpy as np
import io
import requests
import PIL
import matplotlib.pyplot as plt

img = "https://minio.lab.sspcloud.fr/lgaliana/generative-art/pythonds/book.png"
book_mask = np.array(PIL.Image.open(io.BytesIO(requests.get(img).content)))


def make_wordcloud(corpus):
    wc = wordcloud.WordCloud(
        background_color="white",
        max_words=2000,
        mask=book_mask,
        contour_width=3,
        contour_color="steelblue",
    )
    wc.generate(corpus)
    return wc


wordcloud_dumas = make_wordcloud(dumas)
plt.imshow(wordcloud_dumas, interpolation="bilinear")
plt.axis("off")
Figure 3.1: Nuage de mot produit à partir du Comte de Monte Cristo

Cela montre clairement qu’il est nécessaire de nettoyer notre texte. Le nom du personnage principal, Dantès, est ainsi masqué par un certain nombre d’articles ou mots de liaison qui perturbent l’analyse. Ces mots sont des stop words.

La librairie NLTK (Natural Language ToolKit), librairie de référence dans le domaine du NLP, permet de facilement retirer ces stop words (cela pourrait également être fait avec la librairie plus récente, spaCy). Avant cela, il est nécessaire de transformer notre texte en le découpant par unités fondamentales (les tokens).

Les exemples suivants, extraits de Galiana and Castillo (2022), montrent l’intérêt du nettoyage de textes lorsqu’on désire comparer des corpus entre eux. En l’occurrence, il s’agit de comparer un corpus de noms de produits dans des collectes automatisées de produits de supermarché (scanner-data) avec des noms de produits dans les données de l’OpenFoodFacts, une base de données contributive. Sans nettoyage, le bruit l’emporte sur le signal et il est impossible de déceler des similarités entre les jeux de données. Le nettoyage permet d’harmoniser un peu ces jeux de données pour avoir une chance d’être en mesure de les comparer.

OpenFoodFacts avant nettoyage

OpenFoodFacts avant nettoyage

Scanner-data avant nettoyage

Scanner-data avant nettoyage

OpenFoodFacts après nettoyage

OpenFoodFacts après nettoyage

Scanner-data après nettoyage

Scanner-data après nettoyage

3.1 Tokenisation

import nltk

nltk.download("punkt")
[nltk_data] Downloading package punkt to /github/home/nltk_data...
[nltk_data]   Unzipping tokenizers/punkt.zip.
True

La tokenisation consiste à découper un texte en morceaux. Ces morceaux pourraient être des phrases, des chapitres, des n-grammes ou des mots. C’est cette dernière option que l’on va choisir, plus simple pour retirer les stop words :

import nltk

words = nltk.word_tokenize(dumas, language="french")
words[1030:1050]
['que',
 'voulez-vous',
 ',',
 'monsieur',
 'edmond',
 ',',
 'reprit',
 "l'armateur",
 'qui',
 'paraissait',
 'se',
 'consoler',
 'de',
 'plus',
 'en',
 'plus',
 ',',
 'nous',
 'sommes',
 'tous']

On remarque que les mots avec apostrophes sont liés en un seul, ce qui est peut-être faux sur le plan de la grammaire mais peu avoir un sens pour une analyse statistique. Il reste des signes de ponctuation qu’on peut éliminer avec la méthode isalpha:

words = [word for word in words if word.isalpha()]
words[1030:1050]
['assez',
 'sombre',
 'obséquieux',
 'envers',
 'ses',
 'supérieurs',
 'insolent',
 'envers',
 'ses',
 'subordonnés',
 'aussi',
 'outre',
 'son',
 'titre',
 'comptable',
 'qui',
 'est',
 'toujours',
 'un',
 'motif']

3.2 Retirer les stop words

Le jeu de données est maintenant propre. On peut désormais retirer les mots qui n’apportent pas de sens et servent seulement à faire le lien entre deux prépositions. On appelle ces mots des stop words dans le domaine du NLP.

Comme indiqué ci-dessus, pour télécharger le corpus de stop words1, il est nécessaire d’exécuter la ligne de commande suivante :

import nltk

nltk.download("stopwords")
[nltk_data] Downloading package stopwords to /github/home/nltk_data...
[nltk_data]   Unzipping corpora/stopwords.zip.
True
from nltk.corpus import stopwords

print(stopwords.words("french"))

stop_words = set(stopwords.words("french"))


words = [w for w in words if not w in stop_words]
print(words[1030:1050])
['au', 'aux', 'avec', 'ce', 'ces', 'dans', 'de', 'des', 'du', 'elle', 'en', 'et', 'eux', 'il', 'ils', 'je', 'la', 'le', 'les', 'leur', 'lui', 'ma', 'mais', 'me', 'même', 'mes', 'moi', 'mon', 'ne', 'nos', 'notre', 'nous', 'on', 'ou', 'par', 'pas', 'pour', 'qu', 'que', 'qui', 'sa', 'se', 'ses', 'son', 'sur', 'ta', 'te', 'tes', 'toi', 'ton', 'tu', 'un', 'une', 'vos', 'votre', 'vous', 'c', 'd', 'j', 'l', 'à', 'm', 'n', 's', 't', 'y', 'été', 'étée', 'étées', 'étés', 'étant', 'étante', 'étants', 'étantes', 'suis', 'es', 'est', 'sommes', 'êtes', 'sont', 'serai', 'seras', 'sera', 'serons', 'serez', 'seront', 'serais', 'serait', 'serions', 'seriez', 'seraient', 'étais', 'était', 'étions', 'étiez', 'étaient', 'fus', 'fut', 'fûmes', 'fûtes', 'furent', 'sois', 'soit', 'soyons', 'soyez', 'soient', 'fusse', 'fusses', 'fût', 'fussions', 'fussiez', 'fussent', 'ayant', 'ayante', 'ayantes', 'ayants', 'eu', 'eue', 'eues', 'eus', 'ai', 'as', 'avons', 'avez', 'ont', 'aurai', 'auras', 'aura', 'aurons', 'aurez', 'auront', 'aurais', 'aurait', 'aurions', 'auriez', 'auraient', 'avais', 'avait', 'avions', 'aviez', 'avaient', 'eut', 'eûmes', 'eûtes', 'eurent', 'aie', 'aies', 'ait', 'ayons', 'ayez', 'aient', 'eusse', 'eusses', 'eût', 'eussions', 'eussiez', 'eussent']
['celui', 'dantès', 'a', 'déposé', 'passant', 'comment', 'paquet', 'déposer', 'danglars', 'rougit', 'passais', 'devant', 'porte', 'capitaine', 'entrouverte', 'vu', 'remettre', 'paquet', 'cette', 'lettre']

Ces retraitements commencent à porter leurs fruits puisque des mots ayant plus de sens commencent à se dégager, notamment les noms des personnages (Fernand, Mercédès, Villefort, etc.)

wc = make_wordcloud(" ".join(words))

fig = plt.figure()

plt.imshow(wc, interpolation="bilinear")
plt.axis("off")

3.3 Stemming

Pour réduire la complexité d’un texte, on peut tirer partie de “classes d’équivalence” : on peut considérer que différentes formes d’un même mot (pluriel, singulier, conjugaison) sont équivalentes et les remplacer par une même forme dite canonique. Il existe deux approches dans le domaine :

  • la lemmatisation qui requiert la connaissance des statuts grammaticaux (exemple : chevaux devient cheval)
  • la racinisation (stemming) plus fruste mais plus rapide, notamment en présence de fautes d’orthographes. Dans ce cas, chevaux peut devenir chev mais être ainsi confondu avec chevet ou cheveux

La racinisation est plus simple à mettre en oeuvre car elle peut s’appuyer sur des règles simples pour extraire la racine d’un mot.

Pour réduire un mot dans sa forme “racine”, c’est-à-dire en s’abstrayant des conjugaisons ou variations comme les pluriels, on applique une méthode de stemming. Le but du stemming est de regrouper de nombreuses variantes d’un mot comme un seul et même mot. Par exemple, une fois que l’on applique un stemming, “chats” et “chat” deviennent un même mot.

Cette approche a l’avantage de réduire la taille du vocabulaire à maîtriser pour l’ordinateur et le modélisateur. Il existe plusieurs algorithmes de stemming, notamment le Porter Stemming Algorithm ou le Snowball Stemming Algorithm. Nous pouvons utiliser ce dernier en Français :

from nltk.stem.snowball import SnowballStemmer

stemmer = SnowballStemmer(language="french")

stemmed = [stemmer.stem(word) for word in words]
print(stemmed[1030:1050])
['celui', 'dantes', 'a', 'dépos', 'pass', 'comment', 'paquet', 'dépos', 'danglar', 'roug', 'pass', 'dev', 'port', 'capitain', 'entrouvert', 'vu', 'remettr', 'paquet', 'cet', 'lettr']

A ce niveau, les mots commencent à être moins intelligibles par un humain. La machine prendra le relais, on lui a préparé le travail.

4 Reconnaissance des entités nommées

Cette étape n’est pas une étape de préparation mais illustre la capacité des librairies Python a extraire du sens d’un texte. La librairie spaCy permet de faire de la reconnaissance d’entités nommées (named entity recognition, NER), ce qui peut être pratique pour extraire rapidement certains personnages de notre oeuvre.

Voici un exemple de reconnaissance d’entités nommées sur les premières phrases de l’ouvrage :

#!pip install deplacy
!python -m spacy download fr_core_news_sm
import spacy
import spacy
from spacy import displacy

nlp=spacy.load("fr_core_news_sm")
doc = nlp(dumas[15000:17000])
displacy.render(doc, style="ent", jupyter=True)
Collecting fr-core-news-sm==3.7.0
  Downloading https://github.com/explosion/spacy-models/releases/download/fr_core_news_sm-3.7.0/fr_core_news_sm-3.7.0-py3-none-any.whl (16.3 MB)
     ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 0.0/16.3 MB ? eta -:--:--     ━━━━━╸━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 2.4/16.3 MB 71.9 MB/s eta 0:00:01     ━━━━━━━━━━━━━━━━━━━━━╸━━━━━━━━━━━━━━━━━━ 8.8/16.3 MB 129.6 MB/s eta 0:00:01     ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╸━━ 15.4/16.3 MB 190.1 MB/s eta 0:00:01     ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╸ 16.3/16.3 MB 186.0 MB/s eta 0:00:01     ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 16.3/16.3 MB 107.2 MB/s eta 0:00:00
Requirement already satisfied: spacy<3.8.0,>=3.7.0 in /opt/mamba/lib/python3.11/site-packages (from fr-core-news-sm==3.7.0) (3.7.4)
Requirement already satisfied: spacy-legacy<3.1.0,>=3.0.11 in /opt/mamba/lib/python3.11/site-packages (from spacy<3.8.0,>=3.7.0->fr-core-news-sm==3.7.0) (3.0.12)
Requirement already satisfied: spacy-loggers<2.0.0,>=1.0.0 in /opt/mamba/lib/python3.11/site-packages (from spacy<3.8.0,>=3.7.0->fr-core-news-sm==3.7.0) (1.0.5)
Requirement already satisfied: murmurhash<1.1.0,>=0.28.0 in /opt/mamba/lib/python3.11/site-packages (from spacy<3.8.0,>=3.7.0->fr-core-news-sm==3.7.0) (1.0.10)
Requirement already satisfied: cymem<2.1.0,>=2.0.2 in /opt/mamba/lib/python3.11/site-packages (from spacy<3.8.0,>=3.7.0->fr-core-news-sm==3.7.0) (2.0.8)
Requirement already satisfied: preshed<3.1.0,>=3.0.2 in /opt/mamba/lib/python3.11/site-packages (from spacy<3.8.0,>=3.7.0->fr-core-news-sm==3.7.0) (3.0.9)
Requirement already satisfied: thinc<8.3.0,>=8.2.2 in /opt/mamba/lib/python3.11/site-packages (from spacy<3.8.0,>=3.7.0->fr-core-news-sm==3.7.0) (8.2.3)
Requirement already satisfied: wasabi<1.2.0,>=0.9.1 in /opt/mamba/lib/python3.11/site-packages (from spacy<3.8.0,>=3.7.0->fr-core-news-sm==3.7.0) (1.1.2)
Requirement already satisfied: srsly<3.0.0,>=2.4.3 in /opt/mamba/lib/python3.11/site-packages (from spacy<3.8.0,>=3.7.0->fr-core-news-sm==3.7.0) (2.4.8)
Requirement already satisfied: catalogue<2.1.0,>=2.0.6 in /opt/mamba/lib/python3.11/site-packages (from spacy<3.8.0,>=3.7.0->fr-core-news-sm==3.7.0) (2.0.10)
Requirement already satisfied: weasel<0.4.0,>=0.1.0 in /opt/mamba/lib/python3.11/site-packages (from spacy<3.8.0,>=3.7.0->fr-core-news-sm==3.7.0) (0.3.4)
Requirement already satisfied: typer<0.10.0,>=0.3.0 in /opt/mamba/lib/python3.11/site-packages (from spacy<3.8.0,>=3.7.0->fr-core-news-sm==3.7.0) (0.9.4)
Requirement already satisfied: smart-open<7.0.0,>=5.2.1 in /opt/mamba/lib/python3.11/site-packages (from spacy<3.8.0,>=3.7.0->fr-core-news-sm==3.7.0) (6.4.0)
Requirement already satisfied: tqdm<5.0.0,>=4.38.0 in /opt/mamba/lib/python3.11/site-packages (from spacy<3.8.0,>=3.7.0->fr-core-news-sm==3.7.0) (4.66.2)
Requirement already satisfied: requests<3.0.0,>=2.13.0 in /opt/mamba/lib/python3.11/site-packages (from spacy<3.8.0,>=3.7.0->fr-core-news-sm==3.7.0) (2.31.0)
Requirement already satisfied: pydantic!=1.8,!=1.8.1,<3.0.0,>=1.7.4 in /opt/mamba/lib/python3.11/site-packages (from spacy<3.8.0,>=3.7.0->fr-core-news-sm==3.7.0) (2.7.1)
Requirement already satisfied: jinja2 in /opt/mamba/lib/python3.11/site-packages (from spacy<3.8.0,>=3.7.0->fr-core-news-sm==3.7.0) (3.1.3)
Requirement already satisfied: setuptools in /opt/mamba/lib/python3.11/site-packages (from spacy<3.8.0,>=3.7.0->fr-core-news-sm==3.7.0) (69.2.0)
Requirement already satisfied: packaging>=20.0 in /opt/mamba/lib/python3.11/site-packages (from spacy<3.8.0,>=3.7.0->fr-core-news-sm==3.7.0) (23.2)
Requirement already satisfied: langcodes<4.0.0,>=3.2.0 in /opt/mamba/lib/python3.11/site-packages (from spacy<3.8.0,>=3.7.0->fr-core-news-sm==3.7.0) (3.4.0)
Requirement already satisfied: numpy>=1.19.0 in /opt/mamba/lib/python3.11/site-packages (from spacy<3.8.0,>=3.7.0->fr-core-news-sm==3.7.0) (1.26.4)
Requirement already satisfied: language-data>=1.2 in /opt/mamba/lib/python3.11/site-packages (from langcodes<4.0.0,>=3.2.0->spacy<3.8.0,>=3.7.0->fr-core-news-sm==3.7.0) (1.2.0)
Requirement already satisfied: annotated-types>=0.4.0 in /opt/mamba/lib/python3.11/site-packages (from pydantic!=1.8,!=1.8.1,<3.0.0,>=1.7.4->spacy<3.8.0,>=3.7.0->fr-core-news-sm==3.7.0) (0.6.0)
Requirement already satisfied: pydantic-core==2.18.2 in /opt/mamba/lib/python3.11/site-packages (from pydantic!=1.8,!=1.8.1,<3.0.0,>=1.7.4->spacy<3.8.0,>=3.7.0->fr-core-news-sm==3.7.0) (2.18.2)
Requirement already satisfied: typing-extensions>=4.6.1 in /opt/mamba/lib/python3.11/site-packages (from pydantic!=1.8,!=1.8.1,<3.0.0,>=1.7.4->spacy<3.8.0,>=3.7.0->fr-core-news-sm==3.7.0) (4.11.0)
Requirement already satisfied: charset-normalizer<4,>=2 in /opt/mamba/lib/python3.11/site-packages (from requests<3.0.0,>=2.13.0->spacy<3.8.0,>=3.7.0->fr-core-news-sm==3.7.0) (3.3.2)
Requirement already satisfied: idna<4,>=2.5 in /opt/mamba/lib/python3.11/site-packages (from requests<3.0.0,>=2.13.0->spacy<3.8.0,>=3.7.0->fr-core-news-sm==3.7.0) (3.6)
Requirement already satisfied: urllib3<3,>=1.21.1 in /opt/mamba/lib/python3.11/site-packages (from requests<3.0.0,>=2.13.0->spacy<3.8.0,>=3.7.0->fr-core-news-sm==3.7.0) (1.26.18)
Requirement already satisfied: certifi>=2017.4.17 in /opt/mamba/lib/python3.11/site-packages (from requests<3.0.0,>=2.13.0->spacy<3.8.0,>=3.7.0->fr-core-news-sm==3.7.0) (2024.2.2)
Requirement already satisfied: blis<0.8.0,>=0.7.8 in /opt/mamba/lib/python3.11/site-packages (from thinc<8.3.0,>=8.2.2->spacy<3.8.0,>=3.7.0->fr-core-news-sm==3.7.0) (0.7.11)
Requirement already satisfied: confection<1.0.0,>=0.0.1 in /opt/mamba/lib/python3.11/site-packages (from thinc<8.3.0,>=8.2.2->spacy<3.8.0,>=3.7.0->fr-core-news-sm==3.7.0) (0.1.4)
Requirement already satisfied: click<9.0.0,>=7.1.1 in /opt/mamba/lib/python3.11/site-packages (from typer<0.10.0,>=0.3.0->spacy<3.8.0,>=3.7.0->fr-core-news-sm==3.7.0) (8.1.7)
Requirement already satisfied: cloudpathlib<0.17.0,>=0.7.0 in /opt/mamba/lib/python3.11/site-packages (from weasel<0.4.0,>=0.1.0->spacy<3.8.0,>=3.7.0->fr-core-news-sm==3.7.0) (0.16.0)
Requirement already satisfied: MarkupSafe>=2.0 in /opt/mamba/lib/python3.11/site-packages (from jinja2->spacy<3.8.0,>=3.7.0->fr-core-news-sm==3.7.0) (2.1.5)
Requirement already satisfied: marisa-trie>=0.7.7 in /opt/mamba/lib/python3.11/site-packages (from language-data>=1.2->langcodes<4.0.0,>=3.2.0->spacy<3.8.0,>=3.7.0->fr-core-news-sm==3.7.0) (1.1.1)
Installing collected packages: fr-core-news-sm
Successfully installed fr-core-news-sm-3.7.0
WARNING: Running pip as the 'root' user can result in broken permissions and conflicting behaviour with the system package manager. It is recommended to use a virtual environment instead: https://pip.pypa.io/warnings/venv
✔ Download and installation successful
You can now load the package via spacy.load('fr_core_news_sm')
us LOC donne tout loisir de faire les vôtres. avez LOC -vous besoin d'argent? --non, monsieur; j'ai tous mes appointements du voyage, c'est-à-dire près de trois mois de solde. --vous êtes un garçon rangé, edmond. PER --ajoutez que j'ai un père pauvre, monsieur morrel. --oui, oui, je sais que vous êtes un bon fils. allez donc voir votre père: j'ai un fils aussi, et j'en voudrais fort à celui qui, après un voyage de trois mois, le retiendrait loin de moi. --alors, vous permettez? dit le jeune homme en saluant. --oui, si vous n'avez rien de plus à me dire. --non MISC . --le capitaine leclère ne vous a pas, en mourant, donné une lettre pour moi? --il lui eût été impossible d'écrire, monsieur; mais cela me rappelle que j'aurai un congé de quinze jours à vous demander. --pour vous marier? --d'abord; puis pour aller à paris LOC . --bon, bon! vous prendrez le temps que vous voudrez, dantès; le temps de décharger le bâtiment nous prendra bien six semaines, et nous ne nous remettrons guère en mer avant trois mois.... seulement, dans trois mois, il faudra que vous soyez là. le _pharaon_, continua l'armateur en frappant sur l'épaule du jeune marin, ne pourrait pas repartir sans son capitaine. --sans son capitaine! s'écria dantès les yeux brillants de joie; faites bien attention à ce que vous dites là, monsieur, car vous venez de répondre aux plus secrètes espérances de mon coeur. votre intention serait-elle de me nommer capitaine du _pharaon_? --si j'étais seul, je vous tendrais la main, mon cher dantès LOC , et je vous dirais: «c'est fait.» mais j'ai un associé, et vous savez le proverbe italien: _che a compagne a padrone_. mais la moitié de la besogne LOC est faite au moins, puisque sur deux voix vous en avez déjà une. rapportez-vous-en à moi pour avoir l'autre, et je ferai de mon mieux. --oh! MISC monsieur morrel, s'écria le jeune marin, saisissant, les larmes aux yeux, les mains de l'armateur; monsieur morrel, je vous remercie, au nom de mon père et de mercédès. --c' PER est bien, c'est bien, edmond, il y a un dieu

La reconnaissance d’entités nommées disponible par défaut est souvent décevante ; il est souvent nécessaire d’enrichir les règles par défaut par des règles ad hoc, propres à chaque corpus.

5 Représentation d’un texte sous forme vectorielle

Une fois nettoyé, le texte est plus propice à une représentation vectorielle. En fait, implicitement, on a depuis le début adopté une démarche bag of words. Il s’agit d’une représentation, sans souci de contexte (ordre des mots, contexte d’utilisation), où chaque token représente un élément dans un vocabulaire de taille \(|V|\). On peut ainsi avoir une représentation matricielle des occurrences de chaque token dans plusieurs documents (par exemple plusieurs livres, chapitres, etc.) pour par exemple en déduire une forme de similarité.

Afin de réduire la dimension de la matrice bag of words, on peut s’appuyer sur des pondérations. On élimine ainsi certains mots très fréquents ou au contraire très rares. La pondération la plus simple est basée sur la fréquence des mots dans le document. C’est l’objet de la métrique tf-idf (term frequency - inverse document frequency) abordée dans un prochain chapitre.

6 Références

Informations additionnelles

environment files have been tested on.

Latest built version: 2024-05-08

Python version used:

'3.11.6 | packaged by conda-forge | (main, Oct  3 2023, 10:40:35) [GCC 12.3.0]'
Package Version
affine 2.4.0
aiobotocore 2.12.2
aiohttp 3.9.3
aioitertools 0.11.0
aiosignal 1.3.1
alembic 1.13.1
aniso8601 9.0.1
annotated-types 0.6.0
appdirs 1.4.4
archspec 0.2.3
astroid 3.1.0
asttokens 2.4.1
attrs 23.2.0
Babel 2.15.0
bcrypt 4.1.2
beautifulsoup4 4.12.3
black 24.4.2
blinker 1.7.0
blis 0.7.11
bokeh 3.4.0
boltons 23.1.1
boto3 1.34.51
botocore 1.34.51
branca 0.7.1
Brotli 1.1.0
cachetools 5.3.3
cartiflette 0.0.2
Cartopy 0.23.0
catalogue 2.0.10
cattrs 23.2.3
certifi 2024.2.2
cffi 1.16.0
charset-normalizer 3.3.2
chromedriver-autoinstaller 0.6.4
click 8.1.7
click-plugins 1.1.1
cligj 0.7.2
cloudpathlib 0.16.0
cloudpickle 3.0.0
colorama 0.4.6
comm 0.2.2
commonmark 0.9.1
conda 24.3.0
conda-libmamba-solver 24.1.0
conda-package-handling 2.2.0
conda_package_streaming 0.9.0
confection 0.1.4
contextily 1.6.0
contourpy 1.2.1
cryptography 42.0.5
cycler 0.12.1
cymem 2.0.8
cytoolz 0.12.3
dask 2024.4.1
dask-expr 1.0.10
debugpy 1.8.1
decorator 5.1.1
dill 0.3.8
distributed 2024.4.1
distro 1.9.0
docker 7.0.0
duckdb 0.10.1
en-core-web-sm 3.7.1
entrypoints 0.4
et-xmlfile 1.1.0
exceptiongroup 1.2.0
executing 2.0.1
fastjsonschema 2.19.1
fiona 1.9.6
flake8 7.0.0
Flask 3.0.2
folium 0.16.0
fontawesomefree 6.5.1
fonttools 4.51.0
fr-core-news-sm 3.7.0
frozenlist 1.4.1
fsspec 2023.12.2
GDAL 3.8.4
gensim 4.3.2
geographiclib 2.0
geopandas 0.12.2
geoplot 0.5.1
geopy 2.4.1
gitdb 4.0.11
GitPython 3.1.43
google-auth 2.29.0
graphene 3.3
graphql-core 3.2.3
graphql-relay 3.2.0
graphviz 0.20.3
great-tables 0.5.1
greenlet 3.0.3
gunicorn 21.2.0
h11 0.14.0
htmltools 0.5.1
hvac 2.1.0
idna 3.6
imageio 2.34.1
importlib_metadata 7.1.0
importlib_resources 6.4.0
inflate64 1.0.0
ipykernel 6.29.3
ipython 8.22.2
ipywidgets 8.1.2
isort 5.13.2
itsdangerous 2.1.2
jedi 0.19.1
Jinja2 3.1.3
jmespath 1.0.1
joblib 1.3.2
jsonpatch 1.33
jsonpointer 2.4
jsonschema 4.21.1
jsonschema-specifications 2023.12.1
jupyter-cache 1.0.0
jupyter_client 8.6.1
jupyter_core 5.7.2
jupyterlab_widgets 3.0.10
kaleido 0.2.1
kiwisolver 1.4.5
kubernetes 29.0.0
langcodes 3.4.0
language_data 1.2.0
lazy_loader 0.4
libmambapy 1.5.7
llvmlite 0.42.0
locket 1.0.0
lxml 5.2.1
lz4 4.3.3
Mako 1.3.2
mamba 1.5.7
mapclassify 2.6.1
marisa-trie 1.1.1
Markdown 3.6
MarkupSafe 2.1.5
matplotlib 3.8.3
matplotlib-inline 0.1.6
mccabe 0.7.0
menuinst 2.0.2
mercantile 1.2.1
mizani 0.11.2
mlflow 2.11.3
mlflow-skinny 2.11.3
msgpack 1.0.7
multidict 6.0.5
multivolumefile 0.2.3
munkres 1.1.4
murmurhash 1.0.10
mypy 1.9.0
mypy-extensions 1.0.0
nbclient 0.10.0
nbformat 5.10.4
nest_asyncio 1.6.0
networkx 3.3
nltk 3.8.1
numba 0.59.1
numpy 1.26.4
oauthlib 3.2.2
opencv-python-headless 4.9.0.80
openpyxl 3.1.2
outcome 1.3.0.post0
OWSLib 0.28.1
packaging 23.2
pandas 2.2.1
paramiko 3.4.0
parso 0.8.4
partd 1.4.1
pathspec 0.12.1
patsy 0.5.6
Pebble 5.0.7
pexpect 4.9.0
pickleshare 0.7.5
pillow 10.3.0
pip 24.0
pkgutil_resolve_name 1.3.10
platformdirs 4.2.0
plotly 5.19.0
plotnine 0.13.5
pluggy 1.4.0
polars 0.20.18
preshed 3.0.9
prometheus_client 0.20.0
prometheus-flask-exporter 0.23.0
prompt-toolkit 3.0.42
protobuf 4.25.3
psutil 5.9.8
ptyprocess 0.7.0
pure-eval 0.2.2
py7zr 0.20.8
pyarrow 15.0.0
pyarrow-hotfix 0.6
pyasn1 0.5.1
pyasn1-modules 0.3.0
pybcj 1.0.2
pycodestyle 2.11.1
pycosat 0.6.6
pycparser 2.21
pycryptodomex 3.20.0
pydantic 2.7.1
pydantic_core 2.18.2
pyflakes 3.2.0
Pygments 2.17.2
PyJWT 2.8.0
pylint 3.1.0
PyNaCl 1.5.0
pynsee 0.1.7
pyOpenSSL 24.0.0
pyparsing 3.1.2
pyppmd 1.1.0
pyproj 3.6.1
pyshp 2.3.1
PySocks 1.7.1
python-dateutil 2.9.0
python-dotenv 1.0.1
python-magic 0.4.27
pytz 2024.1
pyu2f 0.1.5
pywaffle 1.1.0
PyYAML 6.0.1
pyzmq 25.1.2
pyzstd 0.15.10
QtPy 2.4.1
querystring-parser 1.2.4
rasterio 1.3.10
referencing 0.34.0
regex 2023.12.25
requests 2.31.0
requests-cache 1.2.0
requests-oauthlib 2.0.0
rpds-py 0.18.0
rsa 4.9
Rtree 1.2.0
ruamel.yaml 0.18.6
ruamel.yaml.clib 0.2.8
s3fs 2023.12.2
s3transfer 0.10.1
scikit-image 0.23.2
scikit-learn 1.4.1.post1
scipy 1.13.0
seaborn 0.13.2
selenium 4.20.0
setuptools 69.2.0
shapely 2.0.3
six 1.16.0
smart-open 6.4.0
smmap 5.0.0
sniffio 1.3.1
snuggs 1.4.7
sortedcontainers 2.4.0
soupsieve 2.5
spacy 3.7.4
spacy-legacy 3.0.12
spacy-loggers 1.0.5
SQLAlchemy 2.0.29
sqlparse 0.4.4
srsly 2.4.8
stack-data 0.6.2
statsmodels 0.14.1
tabulate 0.9.0
tblib 3.0.0
tenacity 8.2.3
texttable 1.7.0
thinc 8.2.3
threadpoolctl 3.4.0
tifffile 2024.5.3
tomli 2.0.1
tomlkit 0.12.4
toolz 0.12.1
topojson 1.8
tornado 6.4
tqdm 4.66.2
traitlets 5.14.2
trio 0.25.0
trio-websocket 0.11.1
truststore 0.8.0
typer 0.9.4
typing_extensions 4.11.0
tzdata 2024.1
Unidecode 1.3.8
url-normalize 1.4.3
urllib3 1.26.18
wasabi 1.1.2
wcwidth 0.2.13
weasel 0.3.4
webcolors 1.13
webdriver-manager 4.0.1
websocket-client 1.7.0
Werkzeug 3.0.2
wheel 0.43.0
widgetsnbextension 4.0.10
wordcloud 1.9.3
wrapt 1.16.0
wsproto 1.2.0
xgboost 2.0.3
xlrd 2.0.1
xyzservices 2024.4.0
yarl 1.9.4
yellowbrick 1.5
zict 3.0.0
zipp 3.17.0
zstandard 0.22.0

View file history

SHA Date Author Description
06d003a 2024-04-23 10:09:22 Lino Galiana Continue la restructuration des sous-parties (#492)
005d89b 2023-12-20 17:23:04 Lino Galiana Finalise l’affichage des statistiques Git (#478)
3437373 2023-12-16 20:11:06 Lino Galiana Améliore l’exercice sur le LASSO (#473)
4cd44f3 2023-12-11 17:37:50 Antoine Palazzolo Relecture NLP (#474)
deaafb6 2023-12-11 13:44:34 Thomas Faria Relecture Thomas partie NLP (#472)
4c060a1 2023-12-01 17:44:17 Lino Galiana Update book image location
1f23de2 2023-12-01 17:25:36 Lino Galiana Stockage des images sur S3 (#466)
a1ab3d9 2023-11-24 10:57:02 Lino Galiana Reprise des chapitres NLP (#459)
a771183 2023-10-09 11:27:45 Antoine Palazzolo Relecture TD2 par Antoine (#418)
154f09e 2023-09-26 14:59:11 Antoine Palazzolo Des typos corrigées par Antoine (#411)
8082302 2023-08-25 17:48:36 Lino Galiana Mise à jour des scripts de construction des notebooks (#395)
3bdf3b0 2023-08-25 11:23:02 Lino Galiana Simplification de la structure 🤓 (#393)
f2905a7 2023-08-11 17:24:57 Lino Galiana Introduction de la partie NLP (#388)
78ea2cb 2023-07-20 20:27:31 Lino Galiana Change titles levels (#381)
a9b384e 2023-07-18 18:07:16 Lino Galiana Sépare les notebooks (#373)
29ff3f5 2023-07-07 14:17:53 linogaliana description everywhere
f21a24d 2023-07-02 10:58:15 Lino Galiana Pipeline Quarto & Pages 🚀 (#365)
164fa68 2022-11-30 09:13:45 Lino Galiana Travail partie NLP (#328)
f10815b 2022-08-25 16:00:03 Lino Galiana Notebooks should now look more beautiful (#260)
494a85a 2022-08-05 14:49:56 Lino Galiana Images featured ✨ (#252)
d201e3c 2022-08-03 15:50:34 Lino Galiana Pimp la homepage ✨ (#249)
12965ba 2022-05-25 15:53:27 Lino Galiana :launch: Bascule vers quarto (#226)
9c71d6e 2022-03-08 10:34:26 Lino Galiana Plus d’éléments sur S3 (#218)
3299f1d 2022-01-08 16:50:11 Lino Galiana Clean NLP notebooks (#215)
495599d 2021-12-19 18:33:05 Lino Galiana Des éléments supplémentaires dans la partie NLP (#202)
4f67528 2021-12-12 08:37:21 Lino Galiana Improve website appareance (#194)
2a8809f 2021-10-27 12:05:34 Lino Galiana Simplification des hooks pour gagner en flexibilité et clarté (#166)
04f8b8f 2021-09-08 11:55:35 Lino Galiana echo = FALSE sur la page tuto NLP
048e3dd 2021-09-02 18:36:23 Lino Galiana Fix problem with Dumas corpus (#134)
2e4d586 2021-09-02 12:03:39 Lino Galiana Simplify badges generation (#130)
49e2826 2021-05-13 18:11:20 Lino Galiana Corrige quelques images n’apparaissant pas (#108)
4cdb759 2021-05-12 10:37:23 Lino Galiana :sparkles: :star2: Nouveau thème hugo :snake: :fire: (#105)
48ed9d2 2021-05-01 08:58:58 Lino Galiana lien mort corrigé
7f9f97b 2021-04-30 21:44:04 Lino Galiana 🐳 + 🐍 New workflow (docker 🐳) and new dataset for modelization (2020 🇺🇸 elections) (#99)
d164635 2020-12-08 16:22:00 Lino Galiana :books: Première partie NLP (#87)
Back to top

References

Galiana, Lino, and Milena Suarez Castillo. 2022. “Fuzzy Matching on Big-Data an Illustration with Scanner Data and Crowd-Sourced Nutritional Data.”

Footnotes

  1. Le corpus de stop words de NLTK est relativement limité. Il est recommandé de privilégier celui de SpaCy, plus complet, pour éliminer plus de mots valises.↩︎

Citation

BibTeX citation:
@book{galiana2023,
  author = {Galiana, Lino},
  title = {Python Pour La Data Science},
  date = {2023},
  url = {https://pythonds.linogaliana.fr/},
  doi = {10.5281/zenodo.8229676},
  langid = {en}
}
For attribution, please cite this work as:
Galiana, Lino. 2023. Python Pour La Data Science. https://doi.org/10.5281/zenodo.8229676.