Exercices supplémentaires

Des exercices supplémentaires pour pratiquer les concepts du NLP

Exercice
NLP
Author

Lino Galiana

Published

2024-05-08

Cette page approfondit certains aspects présentés dans les autres tutoriels. Il s’agit d’une suite d’exercice, avec corrections, pour présenter d’autres aspects du NLP ou pratiquer sur des données différentes.

1 NLP & Sentiment Analysis : Analyse textuelle des commentaires Trustpilot

Pour en savoir plus sur le sentiment analysis, vous pouvez regarder le sujet 5 de l’édition 2023 du Funathon, disponible sur Github ou sur le SSP Cloud. Très guidé, ce sujet vous permettra d’avoir les bases sur un projet lié à de l’analyse textuelle.

Là où la première partie consiste en quelques petits rappels sur le web scraping, la seconde consiste à analyser les données collectées. En particulier, étant donné que l’on dispose des commentaires laissés par les clients ainsi que leur note, il est intéressant de se demander dans quelle mesure il est possible de prédire la note laissée par un client selon l’évaluation associée. Pour ce faire, on va devoir coupler les méthodes de traitement du langage naturel (NLP) et celles d’apprentissage statistique (machine learning).

2 Exploration des libellés de l’openfood database

{{% box status=“exercise” title=“Exercise: les noms de produits dans l’openfood database” icon=“fas fa-pencil-alt” %}} L’objectif de cet exercice est d’analyser les termes les plus fréquents dans les noms de produits de l’openfood database. Au passage, cela permet de réviser les étapes de preprocessing (LIEN XXXXX) et d’explorer les enjeux de reconnaissance d’entités nommées. {{% /box %}}

Dans cet exercice:

  • tokenisation (nltk)
  • retrait des stop words (nltk)
  • nuage de mots (wordcloud)
  • reconnaissance du langage (fasttext)
  • reconnaissance d’entités nommées (spacy)

le tout sur l’OpenFood Database, une base de données alimentaire qui est enrichie de manière collaborative.

{{% box status=“hint” title=“Hint” icon=“fa fa-lightbulb” %}} Pour pouvoir utiliser les modèles pré-entraînés de spaCy, il faut les télécharger. La méthode préconisée est d’utiliser, depuis un terminal, la commande suivante

python -m spacy download fr_core_news_sm

Dans un notebook jupyter, il se peut qu’il soit nécessaire de relancer le kernel.

Si l’accès à la ligne de commande n’est pas possible, ou si la commande échoue, il est possible de télécharger le modèle pré-entraîné directement depuis une session Python

import spacy

spacy.cli.download("fr_core_news_sm")

{{% /box %}}

  1. Importer le modèle de reconnaissance de langage qui sera utilisé par la suite ainsi que le corpus Français utilisé par spacy
import tempfile
import os
import spacy

temp_dir = tempfile.NamedTemporaryFile()
temp_dir = temp_dir.name

os.system(
    "wget -O {} https://dl.fbaipublicfiles.com/fasttext/supervised-models/lid.176.bin".format(
        "%s.model.bin" % temp_dir
    )
)
spacy.cli.download("fr_core_news_sm")
  1. Importer les données de l’openfood database à partir du code suivant
import pandas as pd
import urllib.request


urllib.request.urlretrieve(
    "https://static.openfoodfacts.org/data/en.openfoodfacts.org.products.csv",
    "%s.openfood.csv" % temp_dir,
)
df_openfood = pd.read_csv(
    "%s.openfood.csv" % temp_dir,
    delimiter="\t",
    usecols=["product_name"],
    encoding="utf-8",
    dtype="str",
)

Ces données devraient avoir l’aspect suivant :

df_openfood.iloc[:2, :5]
  1. Créer une fonction de nettoyage des noms de produits effectuant les étapes suivantes :
  • tokeniser le texte en question
  • retirer la ponctuation et les stopwords

Appliquer cette fonction à l’ensemble des noms de produits (variable product_name)

  1. Effectuer un nuage de mot sur les libellés avant et après nettoyage pour comprendre la structure du corpus en question. Le résultat devrait avoir l’apparence suivante
import wordcloud as wc
import matplotlib.pyplot as plt


def graph_wordcloud(data, by=None, valueby=None, yvar="Text"):
    if (by is not None) & (valueby is not None):
        txt = data[data[by] == valueby][yvar].astype(str)
    else:
        txt = data[yvar].astype(str)
    all_text = " ".join([text for text in txt])
    wordcloud = wc.WordCloud(
        width=800, height=500, random_state=21, max_words=2000
    ).generate(all_text)
    return wordcloud


def graph_wordcloud_by(data, by, yvar="Text"):
    n_topics = data[by].unique().tolist()
    width = 20
    height = 80
    rows = len(n_topics) // 2
    cols = 2
    fig = plt.figure(figsize=(width, height))
    axes = []
    for i in range(cols * rows):
        b = graph_wordcloud(data, by=by, valueby=n_topics[i], yvar=yvar)
        axes.append(fig.add_subplot(rows, cols, i + 1))
        axes[-1].set_title("{}".format(n_topics[i]))
        plt.imshow(b)
        plt.axis("off")
        plt.savefig("{}.png".format(yvar), bbox_inches="tight")


def wordcount_words(data, yvar, by=None):
    plt.figure(figsize=(15, 15))
    if by is None:
        wordcloud = graph_wordcloud(data, yvar=yvar, by=by)
        plt.imshow(wordcloud)
        plt.axis("off")
        plt.savefig("{}.png".format(yvar), bbox_inches="tight")
    else:
        graph_wordcloud_by(data, by=by, yvar=yvar)


wordcount_words(df_openfood, yvar="product_name")
wordcount_words(df_openfood, "tokenized")
  1. Utiliser la librairie Fasttext pour extraire les noms de produits français
  • Appliquer le modèle téléchargé précédemment pour déterminer le langage
  • Ne récupérer que les libellés français
import fasttext

PRETRAINED_MODEL_PATH = "%s.model.bin" % temp_dir
model = fasttext.load_model(PRETRAINED_MODEL_PATH)
newcols = ["language", "score_language"]
df_openfood[newcols] = pd.DataFrame(
    df_openfood["product_name"]
    .astype(str)
    .apply(lambda s: list(model.predict(s)))
    .apply(lambda l: [l[0][0], l[1][0]])
    .tolist(),
    columns=newcols,
)
df_openfood["language"] = df_openfood["language"].str.replace("__label__", "")
df_openfood_french = df_openfood[df_openfood["language"] == "fr"]
df_openfood_french.head(2)
  1. Visualiser avec spacy.displacy le résultat d’une reconnaissance d’entités nommées sur 50 données aléatoires. Cela vous semble-t-il satisfaisant ?
import spacy
import fr_core_news_sm

nlp = fr_core_news_sm.load()

example = " \n ".join(df_openfood_french["product_name"].astype("str").sample(50))

from spacy import displacy

html = displacy.render(nlp(example), style="ent", page=True)
print(html)
  1. Récupérer dans un vecteur les entités nommées reconnues par spaCy. Regarder les entités reconnues dans les 20 premiers libellés de produits
x = []
for doc in nlp.pipe(
    df_openfood_french.head(20)["product_name"].astype("unicode"),
    disable=["tok2vec", "tagger", "parser", "attribute_ruler", "lemmatizer"],
):
    # Do something with the doc here
    x.append([(ent.text, ent.label_) for ent in doc.ents])

x

Informations additionnelles

environment files have been tested on.

Python version used:

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
c9f9f8a 2024-04-24 15:09:35 Lino Galiana Dark mode and CSS improvements (#494)
005d89b 2023-12-20 17:23:04 Lino Galiana Finalise l’affichage des statistiques Git (#478)
3fba612 2023-12-17 18:16:42 Lino Galiana Remove some badges from python (#476)
4cd44f3 2023-12-11 17:37:50 Antoine Palazzolo Relecture NLP (#474)
889a71b 2023-11-10 11:40:51 Antoine Palazzolo Modification TP 3 (#443)
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)
3bdf3b0 2023-08-25 11:23:02 Lino Galiana Simplification de la structure 🤓 (#393)
29ff3f5 2023-07-07 14:17:53 linogaliana description everywhere
f21a24d 2023-07-02 10:58:15 Lino Galiana Pipeline Quarto & Pages 🚀 (#365)
f10815b 2022-08-25 16:00:03 Lino Galiana Notebooks should now look more beautiful (#260)
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)
2a8809f 2021-10-27 12:05:34 Lino Galiana Simplification des hooks pour gagner en flexibilité et clarté (#166)
2e4d586 2021-09-02 12:03:39 Lino Galiana Simplify badges generation (#130)
80877d2 2021-06-28 11:34:24 Lino Galiana Ajout d’un exercice de NLP à partir openfood database (#98)
Back to top

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.