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
Exercise: les noms de produits dans l’openfood database
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.
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.
Hint
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')
- 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')
- 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]
- 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):
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")
- Utiliser la librairie
Fasttext
pour extraire les noms de produits français
- Appliquer le modèle téléchargé précedemment 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)
- 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)
- 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