Machine learning : extraire la positivité/négativité d'une conversation en Français

J'expérimente pas mal en ce moment sur des sujets qui traitent de la memetique et du machine learning.

En particulier, en ce moment, je me pose la question de "comment reproduire l'expérience Facebook de 2012 sur la positivité negativité avec les moyens du bord"

Problématiques

La puissance machine

Je dispose d'une petite machine, et il faut donc laisser à la machine le maximum de puissance de calcul. Une première question est donc : comment avoir une empreinte CPU et mémoire minimale pour que les traitements tournent correctement.

Ma réponse est un environnement linux léger, et l'utilisation du langage python (qui a d'autres avantages dans le contexte), et d'Emacs + Elpy.

Vous trouverez ma configuration emacs/python mise à jour au fur et à mesure de son évolution sur GitHub 

Les jeux de données

Les "GAFA" comme on les appelle disposent de jeux de donnée étendus sur lesquels ils peuvent travailler et en contribuent même parfois certains.

Comment faire sans cela ?

D'abord, de quoi avons nous besoin ? En première approche, j'ai choisi de me concentrer sur le langage écrit, et j'ai besoin, a minima, pour reproduire l'expérience, du sentiment positif/négatif.

Alors bien sur, il y a une approche extrêmement simple en MachineLearning, qui est grosso modo de s'appuyer sur les critiques de films (ou de restaurants par exemple) qui sont scorées pour inférer un sentiment par apprentissage. Bon. Déjà fait et presque trop facile.

Par contre ça ne semble pas... Si bien que ça.  

Déjà parce que trouver des datasets plus explicites ou plus fins psychologiquement, ce n'est pas évident. L'ISEAR par exemple est intéressant mais critiquable. Pour commencer, vu le nombre de nationalités, que le champ en texte libre soit systématiquement en anglais est assez problématique. (cf Memes of translation, Chesterman 2000 )

Et donc il y a cette barrière de la langue. Sentiwordnet est en anglais (même si on peut saluer la jolie initiative d'Amita Davas et Sivaji Bandyopadyay avec "Dr Sentiment" pour étendre le dataset à d'autres langues par le jeu), Wordnet Affects également.

Ce qui est dommage d'ailleurs parce que Wordnet Affects dispose de la précision lexico-grammaticale dont ne dispose pas l'ISEAR. 

Heureusement, si certains datasets sont fermés comme l'EuroWordNet, d'autres sont plus libres comme le WOrdnet Libre Français (WOLF) qui fait partie du groupe Open Multilingual Wordnet (OWN). Ca mache déjà une grosse partie du boulot, on peut entrainer ensuite un etiquetteur lexico-grammatical (POS Tagger grosso modo) avec d'autres jeux (certains issus de wikipedia). 

Bon grosso modo, en première approche, je me suis amusé à partir de WOLF et SentiWordnet en faisant l'association sur les "jeux de synonymes" (Synsets). Cela passe certains écceuils, pas tous, de la langue (j'y reviens).

Acquérir de nouvelles données

Je partais d'une approche très proche de celle de Dr Sentiment, initialement, une "gamification" du concept. 

J'ai trouvé Telegram très adapté à mon expérience : 

  • Ouvert et libre dans son intéraction
  • Sécurisé, il offre la possibilité d'une plus grande ouverture émotionnelle
  • Bot friendly : un bot est ridiculement simple à créer, et peut même envoyer des questionnaires en guise de clavier

Dans le contexte de python, un mélange de Errbot et de Chatterbot s'avère assez facile à mettre en place et amusant

Le premier, Errbot, est un moteur facilement configurable et extensible tournant en daemon qui permet, entre autres, d'utiliser XMPP et Telegram. 

Le second est grosso modo un robot de discussion à chaine de Markov. La dite chaine est persistée, ce qui permettra des usages ultérieurs. 

Le résultat est une sorte de CleverBot simplifié sur lequel on peut rajouter des commandes et des hooks. 

Restera donc à définir le "Jeu" comme cela a été si bien fait pour Dr Sentiment. J'ai mes idées.

Machine Learning et Traitement Automatisé du Langage

Les deux disciplines vont de paire. Beaucoup de pans du TAL dépendent du ML. Pas mal d'exercices de ML utilisent le TAL. 

Sur le TAL, python dispose (encore une fois) d'une bibiolothèque très étendue et complexe qui s'appelle NLTK. Et NLTK est quand même une sacrée monstruosité, car en anglais on a d'entrée de jeu, entre autres le POS Tagging, Wordnet et Sentiwordnet.

NLTK est extensible à d'autres langages via différents corpus (dont OWN que l'on utilise à travers l'API Wordnet) qu'il faut télécharger, ou via une librairie d'entrainement par ML (nltk trainer).

Si pour l'instant je n'ai pas affronté le chantier de créer un POS tagger français via nltk-trainer, j'obtiens des premiers bons résultats qualitativement sur le POS tagging français via TreeTagger et treetaggerwrapper (en python). Par contre avec un appel à un binaire wrappé, on n'est pas au maximum des performances que l'on peut attendre : le tagging est un processus lent. Mais a minima on a le POS Tagging et la lemmisation, c'est à dire passer de "Je fus" à "je/Pronom Personnel être/Verbe au passé simple"

A partir du lemme et de l'étiquette, on peut récupérer les jeux de synonymes (synset) dans Wordnet Anglais (avec beaucoup trop de résultats malheureusement), puis les SentiSynset depuis SentiWordnet.

Point d'étape et évolutions

A l'heure où j'écris ces lignes, un robot tourne sur Telegram, capable d'accepter plusieurs joueurs et de stocker leurs N dernières entrées dans une queue FIFO, et même capable d'en déterminer la positivité/négativité sur commande... Mais pas de rétourner le résultat avant un timeout ;) 

Il y a beaucoup de choses à faire pour continuer cette expérience.

Déjà il y a la performance générale du POS Tagging à l'heure actuelle qui est insatisfaisante.

Il faudrait le désynchroniser du temps de la conversation, et donc avoir un moteur multithreadé en parallèle du moteur de discussion. Ce sera de toute façon généralement nécessaire.

Mais idéalement, il faut que j'entraine un POS Tagger, ce qui ne semble pas difficile, les corpus ne manquant a priori pas, je voulais juste avoir un prototype de la chaine au préalable.

J'ai aussi envie de voir comment ce prototype pourrait s'étendre à WordNet Affects. Qu'il faudrait porter pour python parce que je ne crois pas que cela aie été fait (SentiWordNet est apparemment beaucoup plus utilisé, il y a sans doute de bonnes raisons à ça à part l'age du DataSet)

Il faudra définir le ou les jeux. Précisément à partir de ce que rapportent les premières informations. Et vois si on ne peut pas inclure de l'entrainement renforcé (Q-Learning par exemple) à partir de ça (récompense positive sur certains gradiants d'émotion par exemple).

Et à un moment il faudra packager tout ça... 

Bref, j'ai encore de quoi m'occuper, même en bossant tout seul sur ce sujet.

Commentaires

1. Le lundi, mai 9 2016, 17:21 par benito

Le problème de performance en temps de calcul du POS Tagging que tu rencontres vient peut être de l'initialisation du processus de TreeTagger.

J'ai rencontré un problème similaire en faisant communiquer TreeTagger avec un processus Java. Il fallait une demi-seconde à chaque fois que le processus de TreeTagger était initialisé. En le faisant pour chaque message, c'est très coûteux.

L'astuce consiste à initialiser une seule fois le processus de TreeTagger et à le réutiliser lorsque tu en as besoin. La librairie TT4J (https://github.com/reckart/tt4j) m'a permis de faire cela en java.

En espérant que cela te sera utile ;)

Benoît

2. Le mercredi, mai 11 2016, 08:08 par Aggelos

Merci Benoît !

C'est ce que j'avais cru deviner aussi avec treetagger, ce n'est pas surprenant l'effet de "Cold start" sur un appel wrappe.

Treetaggerwrapper fait à peu près la même chose que tt4j en fait en regard, en fournissant une API mulithreadee

Le problème vient avec le packaging, la maintenance et le déploiement derrière : mettre TT en dépendance externe ça arrange pas mes plans.
API non "homogène" au reste du projet , langage différent, binaire indépendant, classpath à setter...

Merci beaucoup de ton conseil pertinent cela dit :)