import tempfile
import os
import spacy
= tempfile.NamedTemporaryFile()
temp_dir = temp_dir.name
temp_dir
"wget -O {} https://dl.fbaipublicfiles.com/fasttext/supervised-models/lid.176.bin".format( "%s.model.bin" % temp_dir))
os.system('fr_core_news_sm') spacy.cli.download(
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
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
-m spacy download fr_core_news_sm python
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
'fr_core_news_sm') spacy.cli.download(
{{% /box %}}
- Importer le modèle de reconnaissance de langage qui sera utilisé par la suite
ainsi que le corpus Français utilisé par
spacy
- Importer les données de l’openfood database à partir du code suivant
import pandas as pd
import urllib.request
'https://static.openfoodfacts.org/data/en.openfoodfacts.org.products.csv', "%s.openfood.csv" % temp_dir)
urllib.request.urlretrieve(= pd.read_csv("%s.openfood.csv" % temp_dir, delimiter="\t",
df_openfood =['product_name'], encoding = 'utf-8', dtype = "str") usecols
Ces données devraient avoir l’aspect suivant :
2, :5] df_openfood.iloc[:
- 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
)
- 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):
= data[data[by]==valueby][yvar].astype(str)
txt else:
= data[yvar].astype(str)
txt = ' '.join([text for text in txt])
all_text = wc.WordCloud(width=800, height=500,
wordcloud =21,
random_state=2000).generate(all_text)
max_wordsreturn wordcloud
def graph_wordcloud_by(data, by, yvar = "Text"):
= data[by].unique().tolist()
n_topics =20
width=80
height= len(n_topics)//2
rows = 2
cols =plt.figure(figsize=(width, height))
fig= []
axes for i in range(cols*rows):
= graph_wordcloud(data, by = by, valueby = n_topics[i], yvar = yvar)
b +1) )
axes.append( fig.add_subplot(rows, cols, i-1].set_title("{}".format(n_topics[i]))
axes[
plt.imshow(b)'off')
plt.axis('{}.png'.format(yvar), bbox_inches='tight')
plt.savefig(
def wordcount_words(data, yvar, by = None):
=(15,15) )
plt.figure( figsizeif by is None:
= graph_wordcloud(data, yvar = yvar, by = by)
wordcloud
plt.imshow(wordcloud)'off')
plt.axis('{}.png'.format(yvar), bbox_inches='tight')
plt.savefig(else:
= by, yvar = yvar)
graph_wordcloud_by(data, by
= "product_name")
wordcount_words(df_openfood, yvar "tokenized") wordcount_words(df_openfood,
- 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
= "%s.model.bin" % temp_dir
PRETRAINED_MODEL_PATH = fasttext.load_model(PRETRAINED_MODEL_PATH)
model = ['language','score_language']
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[newcols] 'language'] = df_openfood['language'].str.replace("__label__","")
df_openfood[= df_openfood[df_openfood['language'] == "fr"]
df_openfood_french 2) df_openfood_french.head(
- 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
= fr_core_news_sm.load()
nlp
= " \n ".join(df_openfood_french['product_name'].astype("str").sample(50))
example
from spacy import displacy
= displacy.render(nlp(example), style='ent', page=True) html
print(html)
- 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
for ent in doc.ents])
x.append([(ent.text, ent.label_)
x
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}
}