Détecter les fake news avec scikit-learn
Ce tutoriel scikit-learn vous guide pas à pas pour construire un classifieur de fake news à l’aide de modèles bayésiens.
· 15 min lire
Explorez l'IA
Contenus associés
Tutoriel
Instructions IF, ELIF et ELSE en Python
Dans ce tutoriel, vous apprendrez exclusivement les instructions if else en Python.
Tutoriel
if…elif…else dans le tutoriel Python
Découvrez comment créer des instructions if…elif…else en Python.
Tutoriel
Tutoriel sur les boucles « for » en Python
Apprenez à implémenter des boucles « for » en Python pour itérer une séquence ou les lignes et colonnes d'un DataFrame pandas.
Détecter les fameuses « fake news » n’a rien d’évident. D’abord, il faut en définir le périmètre – le terme a désormais une connotation politique. Une fois la définition établie, il faut collecter des articles et les étiqueter correctement comme vrais ou faux (de préférence sur des thématiques similaires pour bien distinguer les deux). Une fois la collecte faite, reste à identifier des caractéristiques utiles pour différencier le vrai du faux.
Pour un tour d’horizon plus approfondi, je vous recommande l’article de Miguel Martinez-Alvarez : « How can Machine Learning and AI Help Solve the Fake News Problem ».
À peu près au même moment, j’ai découvert un article d’Open Data Science sur la création d’un détecteur de fake news performant avec des modèles bayésiens. L’auteur a même mis à disposition un répertoire contenant un jeu de données d’articles vrais et faux étiquetés. J’étais curieux de voir si je pouvais reproduire facilement les résultats et, surtout, si je pouvais comprendre ce que le modèle avait appris.
Dans ce tutoriel, vous allez parcourir avec moi quelques étapes d’exploration initiale et vérifier si vous parvenez à construire un détecteur de fake news convaincant.
Astuce : pour approfondir les bases du traitement automatique du langage (NLP), suivez le cours Natural Language Processing Fundamentals in Python.
Exploration des données
Commencez toujours par un rapide tour d’horizon des données pour en prendre le pouls. Pour cela, utilisez un DataFrame Pandas, vérifiez sa forme, affichez les premières lignes et appliquez les transformations nécessaires.
Extraction des données d’entraînement
Maintenant que le DataFrame ressemble davantage à ce dont vous avez besoin, séparez les étiquettes et constituez des jeux d’entraînement et de test.
Pour ce notebook, j’ai décidé de me concentrer sur le texte long des articles. Sachant que j’allais utiliser le sac de mots et la mesure TF-IDF (Term Frequency–Inverse Document Frequency) pour extraire des caractéristiques, ce choix était pertinent. Un texte plus long permettra, espérons-le, de mieux distinguer des mots et des caractéristiques entre mes données de vraies et de fausses informations.
Construction des classifieurs avec vectorisation
Maintenant que vous avez vos jeux d’entraînement et de test, vous pouvez construire vos classifieurs. Pour évaluer l’impact des mots et jetons des articles sur la détection du vrai/faux, commencez avec
CountVectorizeretTfidfVectorizer.Dans l’exemple, un seuil maximal de
.7est défini pour le vectoriseur TF-IDFtfidf_vectorizervia l’argumentmax_df. Cela retire les mots présents dans plus de 70 % des articles. Par ailleurs, le paramètre intégréstop_wordssupprimera les stop words anglais avant la vectorisation.De nombreux autres paramètres sont disponibles : consultez la documentation scikit-learn pour
TfidfVectorizeretCountVectorizer.Maintenant que vous avez vos vecteurs, vous pouvez examiner les caractéristiques extraites, stockées dans
count_vectorizerettfidf_vectorizer.Voyez-vous des problèmes visibles ? (Oui !)
Il y a clairement des commentaires, des mesures ou d’autres éléments incohérents, ainsi que des articles multilingues dans le jeu de données utilisé. Normalement, vous consacreriez plus de temps au prétraitement et à la réduction du bruit. Mais comme ce tutoriel vise à proposer une preuve de concept rapide, voyons si le modèle peut surmonter ce bruit et bien classer malgré ces écueils.
Intermezzo : caractéristiques Count vs TF-IDF
Je voulais savoir si mes vectoriseurs Count et TF-IDF extrayaient des jetons différents. Pour comparer facilement, vous pouvez retransformer les vecteurs en DataFrame et faire des comparaisons simples en Python.
En exécutant les cellules ci-dessous, vous verrez que les deux vectoriseurs extraient les mêmes jetons, mais avec des pondérations différentes. En jouant sur les paramètres
max_dfetmin_dfdu vectoriseur TF-IDF, on pourrait sans doute obtenir des caractéristiques différentes.5 rows × 56922 columns
5 rows × 56922 columns
Comparer les modèles
Il est temps d’entraîner et de tester vos modèles.
Nous allons commencer avec un classique du NLP,
MultinomialNB. Vous pouvez l’utiliser pour comparer TF-IDF au sac de mots. Mon intuition : le sac de mots (CountVectorizer) fonctionnerait mieux avec ce modèle. (Pour en savoir plus sur la distribution multinomiale et l’intérêt d’utiliser des entiers, voyez cette explication synthétique d’un cours de statistiques de l’UPenn.)Je trouve les matrices de confusion plus faciles à lire et à comparer ; je me suis donc appuyé sur la documentation scikit-learn pour construire des matrices lisibles (merci l’open source !). Une matrice de confusion affiche les étiquettes correctes sur la diagonale principale (du haut gauche vers le bas droit). Les autres cellules correspondent aux étiquettes incorrectes, souvent appelées faux positifs ou faux négatifs. Selon le problème, l’un des deux peut compter davantage. Par exemple, pour les fake news, est-il plus important d’éviter de classer des articles vrais comme faux ? Si oui, il faudra peut-être pondérer notre score d’exactitude en conséquence.
Au-delà des matrices de confusion, scikit-learn propose de multiples façons de visualiser et comparer vos modèles. Une méthode populaire consiste à utiliser une courbe ROC. D’autres métriques d’évaluation sont disponibles dans le module metrics.
Et en effet, sans aucun réglage d’hyperparamètres, votre jeu d’entraînement vectorisé par comptage
count_trainsurpasse visiblement vos vecteurs TF-IDF !Tester des modèles linéaires
De nombreux articles expliquent que les modèles linéaires fonctionnent très bien avec des vectoriseurs TF-IDF (voir par exemple word2vec pour la classification, la référence SVM dans l’analyse de texte scikit-learn, etc.).
Faut-il donc utiliser un SVM ?
J’ai récemment regardé le cours de Victor Lavrenko sur la classification de textes, où il compare les classifieurs Passive Aggressive aux SVM linéaires. Testons cette approche (rapide mais avec des limites d’apprentissage permanentes) sur notre jeu de données de fake news.
Waouh !
Impressionnant. La matrice de confusion est différente et le modèle classe un peu mieux nos fake news. Testons si l’ajustement de la valeur
alphad’unMultinomialNBpermet d’obtenir des résultats comparables. Vous pouvez aussi utiliser une recherche sur grille pour un réglage plus exhaustif.Pas tout à fait… À ce stade, il serait pertinent d’affiner les hyperparamètres de l’ensemble des classifieurs, ou d’examiner d’autres classifieurs bayésiens scikit-learn. Vous pourriez aussi tester un SVM pour voir s’il dépasse le classifieur Passive Aggressive.
Mais je suis surtout curieux de savoir ce que le modèle Passive Aggressive a réellement appris. Passons donc à l’introspection.
Observer l’intérieur des modèles
Alors, le problème des fake news est réglé, n’est-ce pas ? Nous avons obtenu 93 % d’exactitude, on remballe et on rentre.
Évidemment, non. Je reste très prudent face à ces résultats, vu le bruit observé dans les caractéristiques. Il existe une excellente réponse sur StackOverflow présentant une fonction très utile pour trouver les vecteurs influençant le plus les étiquettes. Elle ne fonctionne que pour la classification binaire (2 classes), mais c’est parfait ici puisque nos étiquettes sont FAKE ou REAL.
En utilisant votre meilleur couple classifieur–vecteurs TF-IDF (
tfidf_vectorizer) et classifieur Passive Aggressive (linear_clf), inspectez les 30 principaux vecteurs pour les articles faux et vrais :Vous pouvez aussi le faire très simplement en Python : associez coefficients et caractéristiques avec zip, puis regardez le début et la fin de la liste.
On voit clairement certains mots révélant une intention ou une source politique parmi les caractéristiques associées aux faux (par exemple corporate ou establishment).
On observe aussi que les données d’articles « vrais » emploient plus souvent des formes du verbe « to say », probablement parce que la presse cite fréquemment des sources (« La chancelière allemande Angela Merkel a déclaré… »).
Pour extraire la liste complète depuis votre classifieur actuel et examiner chaque jeton (ou comparer facilement d’un classifieur à l’autre), exportez-la ainsi.
Intermezzo : HashingVectorizer
Un autre vectoriseur parfois utilisé pour la classification de texte est le
HashingVectorizer. LesHashingVectorizerdemandent moins de mémoire et sont plus rapides (car ils produisent des matrices creuses et s’appuient sur des hachages plutôt que sur des jetons), mais ils sont plus difficiles à introspecter. Vous pouvez en lire davantage sur les avantages et limites deHashingVectorizerdans la documentation scikit-learn.Essayez-le et comparez ses résultats à ceux des autres vectoriseurs. Les performances sont honorables, meilleures que le TF-IDF avec
MultinomialNB(ce qui est attendu pour des raisons similaires à celles qui font queCountVectorizerperforme mieux), mais inférieures au TF-IDF avec l’algorithme linéaire Passive Aggressive.Conclusion
Alors, l’expérience de classifieur de fake news est-elle un succès ? Clairement non.
Mais avez-vous pu manipuler un nouveau jeu de données, tester des modèles de classification NLP et examiner leur comportement ? Oui.
Comme prévu dès le départ, définir les fake news avec un simple sac de mots ou des vecteurs TF-IDF est une approche trop simpliste, d’autant plus avec un jeu de données multilingue plein de bruit. Sans introspection de ce que votre modèle a réellement appris, vous auriez pu croire qu’il captait quelque chose de pertinent. Moralité : essayez toujours d’introspecter vos modèles (autant que possible) !
Je serais curieux de connaître d’autres tendances que j’aurais pu manquer. Je publierai un billet comparant différents classifieurs sous l’angle des caractéristiques les plus importantes sur mon blog. Si vous trouvez des éléments intéressants, partagez-les en commentaire ou contactez-moi sur Twitter (je suis @kjam).
J’espère que cette exploration d’un nouveau jeu de données NLP vous a plu !
Découvrez aussi le tutoriel DataCamp Python Machine Learning : Scikit-Learn Tutorial.