Skip to content

Commit

Permalink
Travail partie NLP (#328)
Browse files Browse the repository at this point in the history
* Relec ka 2711 (début NLP) (#327)

* descriptif NLP

* 01_intro

* 02_exoclean

* dev

* Automated changes

* Automated changes

* uo

* wordcloud

* Automated changes

* Automated changes

* ddd

* Automated changes

* Automated changes

* spacyu

* fini chap 1

* relevanc

* reoordonne

* Automated changes

* Automated changes

* Automated changes

* Automated changes

* exo 2 start

* Add files via upload

* word

* spooky

* Automated changes

* Automated changes

* Automated changes

* Automated changes

* horror

* Automated changes

* Automated changes

* update

* Automated changes

* Automated changes

* box

* evol

* index

* fear

* refs

* Automated changes

* Automated changes

* corrige erreur

* Automated changes

* Automated changes

* petit mot

* Automated changes

* Automated changes

* dd

* Automated changes

* Automated changes

* dd

* Automated changes

* Automated changes

Co-authored-by: Kim A <kim.antunez@ensae.fr>
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
Co-authored-by: root <root@vscode-python-717802-0.vscode-python-717802.projet-cartiflette.svc.cluster.local>
  • Loading branch information
4 people committed Nov 30, 2022
1 parent f479f12 commit 164fa68
Show file tree
Hide file tree
Showing 4 changed files with 490 additions and 202 deletions.
209 changes: 161 additions & 48 deletions content/course/NLP/01_intro/index.qmd
@@ -1,5 +1,5 @@
---
title: "Quelques éléments pour comprendre les enjeux"
title: "Quelques éléments pour comprendre les enjeux du NLP"
date: 2020-10-15T13:00:00Z
draft: false
weight: 10
Expand All @@ -20,6 +20,7 @@ summary: |
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.
bibliography: ../../../../reference.bib
---

::: {.cell .markdown}
Expand All @@ -39,23 +40,36 @@ print_badges("content/course/NLP/01_intro.qmd")
:::



{{% box status="warning" title="Warning" icon="fa fa-exclamation-triangle" %}}
Le NLP est un domaine immense de recherche. Cette page est une introduction
Le _NLP_ est un domaine immense de recherche. Cette page est une introduction
fort incomplète à la question. Il s'agit de montrer la logique, quelques exemples
avec `Python` <i class="fab fa-python"></i>
et s'amuser avec comme base d'exemple un livre formidable :books: :
*Le Comte de Monte Cristo*
{{% /box %}}
*Le Comte de Monte Cristo*.

Dans le cadre de l'introduction au NLP que vous pouvez retrouver dans
les différents chapitres, nous évoquons principalement les champs suivants du NLP:

- _Preprocessing_
- Approches _bag of words_ et contextuelles (n-grams, etc.)
- _Topics modelling_
- _Word embedding_

Cela laisse de côté des champs très actifs de recherche
du NLP, notamment l'analyse de sentiment ou les modèles de
langage (modèles GPT par exemple). Les outils découverts
dans cette partie du cours permettront, si vous le désirez,
de bénéficier d'une base solide pour approfondir tel ou tel
sujet.


## Base d'exemple
# 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](http://www.gutenberg.org/ebooks/author/492) 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 module `urllib` le fichier texte et le retravailler
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 :

```{python}
Expand All @@ -80,12 +94,13 @@ dumas[10000:10500]
```


## La particularité des données textuelles
# La particularité des données textuelles

### Objectif
## Objectif

Le *natural language processing* (NLP) ou
*traitement automatisé de la langue* (TAL) en Français, vise à extraire de l'information de textes à partir d'une analyse statistique du contenu.
*traitement automatisé de la langue* (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. ) ainsi que de méthodes.

Expand All @@ -102,7 +117,7 @@ Si cette tâche n'était pas assez difficile comme ça, on peut ajouter d'autres
* propres à chaque langue : il n'existe pas de règle de passage unique entre deux langues
* grande dimension : des combinaisons infinies de séquences de mots

### Méthode
## Méthode

L’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
Expand All @@ -116,7 +131,7 @@ l’information transformée. Mais les étapes de nettoyage de texte sont indisp



## Nettoyer un texte
# Nettoyer un texte

Les *wordclouds* sont des représentations graphiques assez pratiques pour visualiser
les mots les plus fréquents. Elles sont très simples à implémenter en `Python`
Expand All @@ -125,8 +140,8 @@ une image :


```{python}
#| include: false
#| echo: true
import wordcloud
import numpy as np
import io
Expand Down Expand Up @@ -158,9 +173,59 @@ d'articles ou mots de liaison qui perturbent l'analyse. Ces mots sont des
de référence dans le domaine du NLP, permet de facilement retirer ces
stopwords (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)
de transformer notre texte en le découpant par unités fondamentales (les tokens).

Les exemples suivants, extraits de @galianafuzzy, 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.

::: {layout-ncol=2}
![`OpenFoodFacts` avant nettoyage](wordcloud_openfood_start.png)

![_Scanner-data_ avant nettoyage](wordcloud_relevanc_start.png)
:::

::: {layout-ncol=2}
![`OpenFoodFacts` après nettoyage](wordcloud_openfood_clean.png)

![_Scanner-data_ après nettoyage](wordcloud_relevanc_clean.png)
:::


## Tokenisation

::: {.cell .markdown}
```{=html}
<div class="alert alert-warning" role="alert">
<h3 class="alert-heading"><i class="fa-solid fa-lightbulb"></i> Hint</h3>
```

Lors de la première utilisation de `NLTK`, il est nécessaire de télécharger
quelques éléments nécessaires à la tokenisation, notamment la ponctuation.
Pour cela, il est recommandé d'utiliser la commande suivante:

### Tokenisation
~~~python
import nltk
nltk.download('punkt')
~~~

```{=html}
</div>
```
:::

```{python}
import nltk
nltk.download('punkt')
```

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
Expand All @@ -169,7 +234,6 @@ cette dernière option que l'on va choisir, plus simple pour retirer les

```{python}
import nltk
nltk.download('punkt')
words = nltk.word_tokenize(dumas, language='french')
words[1030:1050]
Expand All @@ -185,34 +249,55 @@ words = [word for word in words if word.isalpha()]
words[1030:1050]
```

{{% box status="hint" title="Hint" icon="fa fa-lightbulb" %}}
Lors de la première utilisation de `NLTK`, il est nécessaire de télécharger
quelques éléments nécessaires à la tokenisation, notamment la ponctuation.
Pour cela,
Comme indiqué ci-dessus, pour télécharger
le corpus de ponctuation, il est
nécessaire d'exécuter la ligne de
commande suivante :



~~~python
import nltk
nltk.download('punkt')
~~~
{{% /box %}}


### Retirer les stopwords
## Retirer les stop-words

Le jeu de données est maintenant propre. On peut désormais retirer les
*stop words*.
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.

{{% box status="hint" title="Hint" icon="fa fa-lightbulb" %}}
::: {.cell .markdown}
```{=html}
<div class="alert alert-warning" role="alert">
<h3 class="alert-heading"><i class="fa-solid fa-lightbulb"></i> Hint</h3>
```
Lors de la première utilisation de `NLTK`, il est nécessaire de télécharger
les stopwords.

```{python}
~~~python
import nltk
nltk.download('stopwords')
~~~

```{=html}
</div>
```
:::

Comme indiqué ci-dessus, pour télécharger
le corpus de stopwords[^2], il est
nécessaire d'exécuter la ligne de
commande suivante :

{{% /box %}}
```{python}
import nltk
nltk.download('stopwords')
```

[^2]: 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.

```{python}
from nltk.corpus import stopwords
Expand All @@ -230,8 +315,6 @@ de sens commencent à se dégager, notamment les noms des personnages
(Fernand, Mercédès, Villefort, etc.)


<!-- KA : ne s'affichait pas sur le site sans que je comprenne pourquoi. J'ai ajouté echo=TRUE... -->

```{python}
#| echo: true
wc = make_wordcloud(' '.join(words))
Expand All @@ -242,15 +325,11 @@ plt.imshow(wc, interpolation='bilinear')
plt.axis("off")
```

```{python}
#| echo: false
plt.savefig("featured.png")
```

### *Stemming*
## *Stemming*

Pour réduire la complexité d'un texte, on peut tirer partie de
"classes d'équivalence" : on peut
_"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 :
Expand All @@ -271,6 +350,7 @@ conjugaisons ou variations comme les pluriels, on applique une méthode 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
Expand All @@ -287,41 +367,72 @@ print(stemmed[1030:1050])
A ce niveau, les mots commencent à être moins intelligibles par un humain.
La machine prendra le relais, on lui a préparé le travail

{{% box status="note" title="Note" icon="fa fa-comment" %}}
Il existe aussi le stemmer suivant :
::: {.cell .markdown}
```{=html}
<div class="alert alert-info" role="alert">
<h3 class="alert-heading"><i class="fa-solid fa-comment"></i> Note</h3>
```
Il existe aussi le _stemmer_ suivant :

~~~python
from nltk.stem.snowball import FrenchStemmer
stemmer = FrenchStemmer()
~~~
{{% /box %}}
```{=html}
</div>
```
:::


### Reconnaissance des entités nommées
# 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, ce qui peut
être pratique pour extraire rapidement certains personnages de notre oeuvre
être pratique pour extraire rapidement certains personnages de notre oeuvre.

::: {.cell .markdown}
```{=html}
<div class="alert alert-info" role="alert">
<h3 class="alert-heading"><i class="fa-solid fa-comment"></i>La librairie spaCy</h3>
```

`NTLK` est la librairie historique d'analyse textuelle en `Python`. Elle existe
depuis les années 1990. L'utilisation industrielle du NLP dans le monde
de la _data-science_ est néanmoins plus récente et doit beaucoup à la collecte
accrue de données non structurées par les réseaux sociaux. Cela a amené à
un renouvelement du champ du NLP, tant dans le monde de la recherche que dans
sa mise en application dans l'industrie de la donnée.

Le _package_ [`spaCy`](https://spacy.io/) est l'un des packages qui a permis
cette industrialisation des méthodes de NLP. Conçu autour du concept
de _pipelines_ de données, il est beaucoup plus pratique à mettre en oeuvre
pour une chaîne de traitement de données textuelles mettant en oeuvre
plusieurs étapes de transformation des données.

```{=html}
</div>
```
:::

~~~python
#!pip install deplacy
#!python -m spacy download fr_core_news_sm
import pkg_resources,imp
imp.reload(pkg_resources)
import spacy

nlp=spacy.load("fr_core_news_sm")
doc = nlp(dumas)
import spacy
from spacy import displacy
displacy.render(doc, style="ent", jupyter=True)
~~~


## Représentation d'un texte sous forme vectorielle
# 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, utilisation),
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 les occurrences de
chaque *token* dans plusieurs documents (par exemple plusieurs livres,
Expand All @@ -334,3 +445,5 @@ 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.

# Références

0 comments on commit 164fa68

Please sign in to comment.