Skip to content

Commit 09b60a1

Browse files
linogalianaantukigithub-actions[bot]
authored
Relecture suite du NLP (#205)
* Relec ka 2012 [coquilles modelisation + relec LDA et debut word2vec] (#204) * coquilles TP SVM * coquilles 02_exoclean (beaucoup d'erreurs de paramètres de chunck echo et include, cf site web). * relecture NLP : 03_lda * LDA : mettre en commentaire la partie sur word2vec * relecture NLP : 04_word2vec (TP to be continued) * coquilles modelisation : 5_clustering * Update content/course/NLP/04_word2vec.Rmd Co-authored-by: Lino Galiana <33896139+linogaliana@users.noreply.github.com> * 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>
1 parent b25457a commit 09b60a1

File tree

5 files changed

+111
-53
lines changed

5 files changed

+111
-53
lines changed

content/course/NLP/02_exoclean.Rmd

Lines changed: 20 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -206,7 +206,6 @@ Si vous ne faites pas l'exercice 1, pensez à charger les données en executant
206206
```{python, echo = TRUE}
207207
import requests
208208
209-
#url = 'https://raw.githubusercontent.com/linogaliana/python-datascientist/master/content/course/NLP/get_data.py'
210209
url = 'https://raw.githubusercontent.com/linogaliana/python-datascientist/master/content/course/NLP/get_data.py'
211210
r = requests.get(url, allow_redirects=True)
212211
open('getdata.py', 'wb').write(r.content)
@@ -232,9 +231,12 @@ sampsize = train.shape[0]
232231

233232
On peut se rendre compte que les extraits des 3 auteurs ne sont pas forcément équilibrés dans le jeu de données. Il faudra en tenir compte dans la prédiction.
234233

235-
```{python, echo=TRUE, eval=TRUE}
234+
```{python, echo=TRUE, eval=TRUE, include=FALSE}
236235
fig = plt.figure()
237236
sns.barplot(x=['Edgar Allen Poe', 'Mary W. Shelley', 'H.P. Lovecraft'], y=train['Author'].value_counts())
237+
```
238+
239+
```{python, echo=FALSE, eval=TRUE}
238240
plt.savefig("wordfreq.png", bbox_inches='tight')
239241
```
240242

@@ -351,7 +353,7 @@ que Lovecraft n'a pas volé sa réputation d'écrivain de l'horreur !
351353

352354
Pour aller plus loin dans l'analyse du champ lexical de chaque auteur,
353355
on peut représenter un `wordcloud` qui permet d'afficher chaque mot avec une
354-
taille proportionnelle au nombre d'occurrence de celui-ci
356+
taille proportionnelle au nombre d'occurrence de celui-ci.
355357

356358
{{% panel status="exercise" title="Exercice" icon="fas fa-pencil-alt" %}}
357359

@@ -406,7 +408,8 @@ count_words = pd.DataFrame({'counter' : train
406408
.apply(lambda s: s.most_common(25))
407409
.explode()}
408410
)
409-
count_words[['word','count']] = pd.DataFrame(count_words['counter'].tolist(), index=count_words.index)
411+
count_words[['word','count']] = pd.DataFrame(count_words['counter'].tolist(),
412+
index=count_words.index)
410413
count_words = count_words.reset_index()
411414
g = sns.FacetGrid(count_words, row="Author")
412415
g.map_dataframe(sns.barplot, x="word", y="count")
@@ -491,7 +494,7 @@ exog = sm.add_constant(np.log(count_words['rank'].astype(float)))
491494
492495
model = sm.GLM(count_words['freq'].astype(float), exog, family = sm.families.Poisson()).fit()
493496
494-
# Display model results
497+
# Afficher les résultats du modèle
495498
print(model.summary())
496499
```
497500

@@ -520,14 +523,14 @@ Plutôt que de faire soi-même ce travail de nettoyage, avec des fonctions mal o
520523

521524
Repartir de `train`, notre jeu de données d'entraînement. Pour rappel, `train` a la structure suivante:
522525

523-
```{python, echo=TRUE}
526+
```{python, echo=FALSE}
524527
train.head(2)
525528
```
526529

527530
1. Tokeniser chaque phrase avec `nltk`. Le `DataFrame` devrait maintenant avoir cet aspect :
528531

529532
```{python}
530-
#| include: false
533+
#| include: true
531534
#| echo: false
532535
533536
#1. Tokenisation
@@ -566,7 +569,7 @@ sur notre `DataFrame` grâce à `apply`, sans le diviser.
566569

567570
Ce petit nettoyage permet d'arriver à un texte plus intéressant en termes d'analyse lexicale. Par exemple, si on reproduit l'analyse précédente... :
568571

569-
```{python, echo=TRUE}
572+
```{python, echo=TRUE, include=FALSE}
570573
train_clean["Text"] = train_clean['tokenized'].apply(lambda s: " ".join(map(str, s)))
571574
572575
n_topics = ["HPL","EAP","MWS"]
@@ -580,6 +583,9 @@ for i in range(len(n_topics)):
580583
ax.axis('off')
581584
582585
fig
586+
```
587+
588+
```{python, echo=FALSE}
583589
plt.savefig('wordcloud2.png', bbox_inches='tight')
584590
```
585591

@@ -682,7 +688,7 @@ tfs = tfidf.fit_transform(train['Text'])
682688

683689
2. Après avoir construit la matrice de documents x terms avec le code suivant, rechercher les lignes où les termes ayant la structure `abandon` sont non-nuls.
684690

685-
```{python, echo = TRUE}
691+
```{python, echo = FALSE, include = FALSE}
686692
feature_names = tfidf.get_feature_names()
687693
corpus_index = [n for n in list(tfidf.vocabulary_.keys())]
688694
import pandas as pd
@@ -694,7 +700,7 @@ df.head()
694700
Les lignes sont les suivantes :
695701

696702
```{python}
697-
#| include: false
703+
#| include: true
698704
#| echo: false
699705
700706
#2. Lignes où les termes de abandon sont non nuls.
@@ -706,7 +712,7 @@ tempdf.head(5)
706712
3. Trouver les 50 extraits où le score TF-IDF est le plus élevé et l'auteur associé. Vous devriez obtenir le classement suivant:
707713

708714
```{python}
709-
#| include: false
715+
#| include: true
710716
#| echo: false
711717
712718
#3. 50 extraits avec le TF-IDF le plus élevé.
@@ -763,7 +769,7 @@ On va, rapidement, regarder dans quel contexte apparaît le mot `fear` dans
763769
l'oeuvre d'Edgar Allan Poe (EAP). Pour cela, on transforme d'abord
764770
le corpus EAP en tokens `nltk` :
765771

766-
```{python, echo = TRUE}
772+
```{python, echo = TRUE, include=FALSE}
767773
eap_clean = train_clean[train_clean["Author"] == "EAP"]
768774
eap_clean = ' '.join(eap_clean['Text'])
769775
#Tokenisation naïve sur les espaces entre les mots => on obtient une liste de mots
@@ -776,7 +782,7 @@ print(text)
776782
1. Utiliser la méthode `concordance` pour afficher le contexte dans lequel apparaît le terme `fear`. La liste devrait ressembler à celle-ci:
777783

778784
```{python}
779-
#| include: false
785+
#| include: true
780786
#| echo: false
781787
782788
# 1. Methode concordance
@@ -799,7 +805,7 @@ from nltk.collocations import BigramCollocationFinder
799805
from nltk.metrics import BigramAssocMeasures
800806
```
801807

802-
Une approche ingénue de la `collocation` amène ainsi à considérer les mots suivants :
808+
<!-- Une approche ingénue de la `collocation` amène ainsi à considérer les mots suivants : -->
803809

804810
```{python}
805811
#| include: false

content/course/NLP/03_lda.Rmd

Lines changed: 36 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -44,9 +44,9 @@ print_badges()
4444

4545

4646

47-
Cette page approfondit continue les exercices présentés dans la
47+
Cette page approfondit les exercices présentés dans la
4848
[section précédente](#nlpexo).
49-
On va ainsi continuer notre exploration de la littérature anglophones:
49+
On va ainsi continuer notre exploration de la littérature anglophones :
5050

5151
* Edgar Allan Poe, (EAP) ;
5252
* HP Lovecraft (HPL) ;
@@ -55,10 +55,13 @@ On va ainsi continuer notre exploration de la littérature anglophones:
5555
Les données sont disponibles ici : [spooky.csv](https://github.com/GU4243-ADS/spring2018-project1-ginnyqg/blob/master/data/spooky.csv) et peuvent être requétées via l'url
5656
<https://github.com/GU4243-ADS/spring2018-project1-ginnyqg/raw/master/data/spooky.csv>.
5757

58-
Le but va être dans un premier temps de regarder dans le détail les termes les plus fréquents utilisés par les auteurs, de les représenter graphiquement puis on va ensuite essayer de prédire quel texte correspond à quel auteur à partir d'un modèle `Word2Vec`.
5958

59+
Le but va être dans un premier temps de regarder dans le détail les termes les plus fréquents utilisés par les auteurs, et les représenter graphiquement.
6060

61-
Ce notebook librement inspiré de :
61+
<!-- puis on va ensuite essayer de prédire quel texte correspond à quel auteur à partir d'un modèle `Word2Vec`. -->
62+
63+
64+
Ce notebook est librement inspiré de :
6265

6366
* https://www.kaggle.com/enerrio/scary-nlp-with-spacy-and-keras
6467
* https://github.com/GU4243-ADS/spring2018-project1-ginnyqg
@@ -72,7 +75,7 @@ les fondements de cette technique.
7275

7376
## Librairies nécessaires
7477

75-
Cette page évoquera, les principales librairies pour faire du NLP, notamment:
78+
Cette page évoquera les principales librairies pour faire du NLP, notamment :
7679

7780
* [WordCloud](https://github.com/amueller/word_cloud)
7881
* [nltk](https://www.nltk.org/)
@@ -98,6 +101,12 @@ nltk.download('wordnet')
98101
La liste des modules à importer est assez longue, la voici:
99102

100103
```{python}
104+
import nltk
105+
nltk.download('stopwords')
106+
nltk.download('punkt')
107+
nltk.download('genesis')
108+
nltk.download('wordnet')
109+
101110
import numpy as np # linear algebra
102111
import pandas as pd # data processing, CSV file I/O (e.g. pd.read_csv)
103112
import seaborn as sns
@@ -126,6 +135,7 @@ from sklearn.decomposition import NMF, LatentDirichletAllocation
126135
pouvez passer à la section suivante*
127136

128137
Le code suivant permet d'importer le jeu de données `spooky`:
138+
129139
```{python, echo = TRUE}
130140
import pandas as pd
131141
@@ -145,7 +155,7 @@ Le jeu de données met ainsi en regard un auteur avec une phrase qu'il a écrite
145155
train.head()
146156
```
147157

148-
Les étapes de *preprocessing* sont expliquées au [chapitre précédent](#nlpexo). On applique les étapes suivantes:
158+
Les étapes de *preprocessing* sont expliquées dans le [chapitre précédent](#nlpexo). On applique les étapes suivantes :
149159

150160
1. Tokeniser
151161
2. Retirer la ponctuation et les stopwords
@@ -187,7 +197,7 @@ des documents par sujet, recherche, compréhension et analyse du texte, ou même
187197
textes.
188198

189199
Aujourd’hui, ce genre de méthodes s’utilisent fréquemment dans le web, par exemple pour
190-
analyser des ensemble d’articles d’actualité, les regrouper par sujet, faire de la recommendation
200+
analyser des ensemble d’articles d’actualité, les regrouper par sujet, faire de la recommandation
191201
d’articles, etc.
192202

193203
La LDA est une méthode qui considère les corpus comme des __mélanges__ de sujets et
@@ -211,14 +221,13 @@ La matrice termes-documents qui sert de point de départ est la suivante:
211221
| ... | ... | ... | ... | ... | ... |
212222
|doc_N| 1 | 0 | 0 | ... | 5 |
213223

214-
La LDA consiste à transformer cette matrice *sparse*
215-
(creuse en Français) document-terme en deux matrices de moindre dimension:
224+
On dit que cette matrice est *sparse* (creuse en Français) car elle contient principalement des 0. En effet, un document n'utilise qu'une partie mineure du vocabulaire complet.
225+
226+
La LDA consiste à transformer cette matrice *sparse*document-terme en deux matrices de moindre dimension:
216227

217228
1. Une matrice document-sujet
218229
2. Une matrice sujet-mots
219230

220-
On dit que cette matrice est sparse car elle contient principalement des 0. En effet, un document n'utilise qu'une partie mineure du vocabulaire complet.
221-
222231
En notant $K_i$ le sujet $i$. On obtient donc
223232

224233
* Une __matrice document-sujet__ ayant la structure suivante:
@@ -256,10 +265,10 @@ corpus = train_clean[train_clean["Author"] == "EAP"]
256265
Il existe plusieurs manières d'entraîner une LDA.
257266

258267
Nous allons utiliser `scikit` ici avec la méthode `LatentDirichletAllocation`.
259-
Comme expliqué dans la partie [modélisation](#modelisation):
268+
Comme expliqué dans la partie [modélisation](#modelisation) :
260269

261-
1. On initialise le modèle
262-
2. On le met à jour avec la méthode `fit`
270+
1. On initialise le modèle ;
271+
2. On le met à jour avec la méthode `fit`.
263272

264273
```{python}
265274
from sklearn.feature_extraction.text import CountVectorizer
@@ -283,7 +292,7 @@ lda.fit(count_data)
283292
## Visualiser les résultats
284293

285294
On peut déjà commencer par utiliser une fonction pour afficher les
286-
résultats
295+
résultats :
287296

288297
```{python}
289298
# Helper function
@@ -300,7 +309,7 @@ print_topics(lda, count_vectorizer, number_words)
300309

301310
La représentation sous forme de liste de mots n'est pas la plus pratique...
302311

303-
On peut essayer de se représenter un *wordcloud* de chaque sujet pour mieux voir si cette piste est pertinente:
312+
On peut essayer de se représenter un *wordcloud* de chaque sujet pour mieux voir si cette piste est pertinente :
304313

305314
```{python, results = "hide"}
306315
tf_feature_names = count_vectorizer.get_feature_names()
@@ -338,10 +347,11 @@ knitr::include_graphics("wordcloud_lda.png")
338347

339348

340349
Le module `pyLDAvis` offre quelques visualisations bien pratiques lorsqu'on
341-
désire représenter de manière synthétique les résultats d'une LDA
350+
désire représenter de manière synthétique les résultats d'une LDA et observer la distribution sujet x mots.
351+
342352

343353
{{% panel status="hint" title="Hint" icon="fa fa-lightbulb" %}}
344-
Dans un *notebook*
354+
Dans un *notebook* faire :
345355

346356
~~~python
347357
import pyLDAvis.sklearn
@@ -358,6 +368,7 @@ argument.
358368
{{% /panel %}}
359369

360370
```{python, eval = FALSE, echo = TRUE}
371+
#!pip install pyLDAvis #à faire en haut du notebook sur colab
361372
import pyLDAvis
362373
import pyLDAvis.sklearn
363374
@@ -386,6 +397,13 @@ print(
386397
{{< /rawhtml >}}
387398

388399

400+
* Chaque **bulle** représente un sujet. Plus la bulle est grande, plus il y a de documents qui traitent de ce sujet.
401+
402+
Plus les barres sont loin les unes des autres, plus elles sont différentes. Un bon modèle aura donc tendance à avoir de grandes bulles qui ne se recoupent pas. Ce n'est pas vraiment le cas ici...
403+
404+
* Les **barres bleues** représentent la fréquence de chaque mot dans le corpus.
405+
406+
* Les **barres rouges** représentent une estimation du nombre de termes générés dans un sujet précis. La barre rouge la plus longue correspond au mot le plus utilisé dans ce sujet.
389407

390408

391409
# Références

0 commit comments

Comments
 (0)