Extraire les mots-clefs d'un texte

Dans le cadre d'un projet personnel (dont je vous parlerai peut-être une prochaine fois, qui sait ? teasing...), j'éprouvais le besoin d'extraire les mots clefs d'un texte. Je vous présente ici la solution que j'ai élaborée.

Ce que j'appelle les mots clefs d'un texte, c'est une liste de mots représentative du sujet de ce texte.

Ce domaine mélangant informatique et linguistique est appellé natural language processing, ou traitement automatique du langage naturel. C'est la première fois que je suis ammené à cotoyer ce domaine, j'espère que les plus puristes d'entre-vous ne m'en voudront pas...

Première approche...

Une première approche, plutôt naïve avouons le, serait de compter les occurences de chaque mot dans le texte. Ainsi, on peut facilement trouver les mots les plus utilisés dans le texte.

Cependant, cette approche ne fonctionne pas vraiment. Par exemple, les deux mots "maison" et "maisons" seraient comptés séparement alors qu'il s'agit du même mot, l'un est au singulier, l'autre au pluriel. On peut bien-sûr choisir d'enlever les lettres s à la fin des mots, mais dans ce cas là comment gérer les pluriels non réguliers (cheval / chevaux), les différentes conjugaisons, les différents formes des mots, etc...

Bref vous l'aurez compris, c'est plutôt complexe et j'avais l'impression de devoir réinventer la roue. Cela a forcémment déjà été fait ailleurs ! (Moteurs de recherche, recommandation de contenus, etc.)

Une histoire de racines...

Ce processus a en faite un nom, c'est le processus de racinisation (stemming en anglais). En discutant avec un collègue du sujet, il m'indique que Apache Lucene permet de faire de la racinisation. En creusant un peu plus, il s'avère qu'en interne, Lucene utilise Snowball. Snowball est en faite un domain specific language permettant la description d'un ensemble de règles pour effectuer la racinisation des mots dans un language donné.

Il existe des outils pour traduire un script Snowball dans différents languages de programmation, y compris Java (mon préféré !).

Vous trouverez plus d'informations sur http://snowball.tartarus.org/.

Alphabet et mots vides

Avant d'appeler notre Stemmer (programme en charge de la racinisation) pour chaque mot du texte, il faudrait savoir ce qu'est exactement un mot, et si il est vraiment pertinant de le compter.

Alphabet

Je pensais d'abord définir la liste des caractères qui peuvent séparer des mots (espace, apostrophe, saut de ligne, etc.), mais je pense qu'il est plus judicieux de définir la liste des caractères qui peuvent composer un mot. Il s'agit tout simplement des 26 lettres de notre alphabet, des différents caractères accentués et autres signes diacritiques. J'en ai dressé la liste ici : https://github.com/jchampemont/keywords-extractor/blob/blog/src/main/resources/lang/fr/alphabet.txt

Ainsi, un mot est défini comme étant une suite de ces caractères. Les caractères non listés constituent des séparateurs de mots.

Mots vides

Un mot vide (ou stopword en anglais), est un mot qui n'apporte pas de sens au texte, qui a juste une utilité grammaticale. Le projet Snowball en a dressé la liste pour le français ici : http://snowball.tartarus.org/algorithms/french/stop.txt.

J'ai ajouté à ceux ci les deux conjugaisons suivantes du verbe avoir : a et as, qui m'apportaient pas mal de faux positifs par la suite.

Vous l'aurez compris, par la suite on ignorera complètement les mots vides.

Un peu de statistiques...

Après avoir compté les occurences de chaque racine de mot dans le texte, j'ai défini la pertinence de chaque mot-clef comme étant le pourcentage d'apparition de cette racine parmis toutes les autres.

Enfin, j'ai décidé de ne garder qu'une partie de tous les mots clefs d'un texte. En faisant quelques tests, j'ai trouvé que garder les mots-clefs du dernier 25 percentile de la pertinence était une bonne valeur. Ce chiffre nécessite sûrement un réglage suivant la longueur du texte. (Un texte risque d'entraîner une répartition plus importante de la pertinence, donc un nombre plus important de mots clefs séléctionnés.)

Le code et des exemples

Le code est disponible sur mon GitHub : https://github.com/jchampemont/keywords-extractor.

Pour tester mon programme, j'ai choisi 2 articles récents piochés sur le site du Monde.

Exemple 1

L'article utilisé est le suivant : Chômage : quasi-stabilité au mois de juin.

Voici les résultats :

[W='emploi', R=0.0340]

[W='nombr', R=0.0303]

[W='plus', R=0.0303]

[W='an', R=0.0265]

[W='mois', R=0.0227]

[W='catégor', R=0.0227]

[W='demandeur', R=0.0227]

[W='hauss', R=0.01893]

[W='pôl', R=0.01893]

[W='juin', R=0.01893]

Wow ! Pour être honnête, je ne m'attendais pas à de si bon résultats ! Même sans avoir lu l'article, on retrouve pas mal de mots auxquels on pourrait s'attendre dans un article traitant du chomage en France au mois de Juin.

Exemple 2

L'article utilisé est le suivant : Plusieurs centaines de tentatives d’intrusion sur le site du tunnel sous la Manche.

Voici les résultats :

[W='migr', R=0.0407]

[W='eurotunnel', R=0.0259]

[W='tunnel', R=0.0222]

[W='million', R=0.0185]

[W='précis', R=0.0185]

[W='cal', R=0.0185]

[W='sit', R=0.0185]

[W='intrus', R=0.0148]

[W='tentat', R=0.0148]

[W='terminal', R=0.0148]

[W='manch', R=0.0111]

[W='annonc', R=0.0111]

[W='plusieur', R=0.0111]

Encore une fois, je suis plutôt content du résultat. On retrouve la racine "migr" en tête, qui doit correspondre aux mots "migrants", "migrer", "migration", "immigration", etc. La racine cal que l'on retrouve au 6ème rang est sans doute la racinisation de Calais.

La suite ?

On vient de voir qu'en quelques lignes de code, un peu de recherches sur internet, et une petite dose de statistiques, on peut facilement extraire une liste de mots clefs d'un texte. Notre algorithme est bien sûr perfectible, il pourrait notamment prendre en compte les noms propres, les mots composés ou fréquemment associés entre eux, etc.

Les mots clefs "racine" trouvés par notre programme sont bien adapté à l'utilisation par des programmes informatiques, mais ne peuvent pas être communiqués à des utilisateurs. Pour reformer des mots de français correct, on pourra rechercher de nouveau dans le texte un ou plusieurs mots correspondant à chaque racine.

Si ça vous a plu, n'hésitez pas à partager l'article sur vos réseaux !

Commentaires