Sentiment Analysis with Hive

 

Le flow de données généré par les médias sociaux ne cesse d’augmenter à tel point qu’il en devient difficile de les analyser. Pourtant, ces textes sont pour la plupart porteur d’opinion et les analyser permettrait à des entreprises de connaitre automatiquement l’image que les consommateurs ont de leur marque, de leurs produits, de leurs services, de leurs concurrents. Les personnalités politiques pourraient détecter des rumeurs ou anticiper des crises…

L’analyse des sentiments vise à déterminer l’opinion de l’auteur par rapport à un thème.

sentiment-analysis

 Social media may be the world’s largest source of Open Data. Between blog posts, online reviews, and a couple of billion tweets every week, social media produces an unending stream of opinion and information about products, services, and events. Sentiment analysis is a new method for turning social media into computable data that can be used to analyze trends, gauge consumer opinion, or guide political campaigns. It’s a way to analyze social media for the “sentiments” it reflects – the virtual crowd’s opinions, emotions, and feedback about companies, politicians, entertainers, and anything else that’s a subject of social media discussion.

Seth Grimes (Opendatanow - 24/10/2013)

L’étude automatisée des sentiments n’est pas une nouvelle discipline, elle a été introduite par Sanjiv Das et Mike Che en 2001 afin d’analyser des sentiments dans le cadre de l’économie de marché. Plusieurs disciplines sont en jeux :

  • Natural Language Processing (NLP) : discipline à la frontière de la linguistique, de l’informatique et de l’intelligence artificielle.
  • Text mining et l’Opinion Mining : ensemble de traitements informatiques consistant à extraire des connaissances selon des critères de similarité dans des textes produits par des humains.

Déceler le sentiment d’une phrase n’est pas aisé, en effet il existe une infinité de variations et d’altérations linguistiques. Le sentiment dépend du contexte, de la personne, de sa langue, de son âge,… Les sous entendus sont difficiles à appréhender…

Il existe plusieurs techniques et algorithmes, comme la méthode de Classification naïve bayésienne qu’utilise NLTK un ensemble de bibliothèques Python permettant d’effectuer du machine learning pour classifier les sentiments.

Une autre approche consiste à utiliser une liste de mots où chaque mot a été catégorisé (positif / négatif). Il existe plusieurs dictionnaires comme AFINN et LabMT et sont pour la plupart en Anglais.

En 2012, pour une présentation aux Journées SQL Server 2012 j’avais utilisé Sentiment140, une API permettant d’obtenir le sentiment de Tweets : https://pulsweb.azurewebsites.net/jss2012-big-data-hadoop-bi/

 

Dans cet article je vais classifier des Tweets à l’aide d’un dictionnaire et utiliser la puissance de Hadoop pour traiter une grande volumétrie de données. Je me suis inspiré de plusieurs techniques et ai conçu cette approche qui n’est surement pas la plus précise, mais qui a le mérite d’être évolutive et qui dans un premier temps répond à mes besoins de catégorisations.

 

Le Principe

Le principe est simple, je vais :

  • Fabriquer un dictionnaire de données et attribuer une note de 0 à 10 pour chacun des mots.
  • Récupérer des Tweets au format JSON
  • Creer un cluster HDInsight de 4 Noeuds.
  • Sérialiser les Tweets avec des UDF Hive.
  • Corréler et agréger les données via des requêtes HQL.
  • Mettre en forme les résultats 🙂

Pour déterminer le sentimensentiment_analysis_social_mediat général d’un Tweet, il suffit d’ajouter les scores des mots trouvés dans le dictionnaire et d’en obtenir une moyenne.

Si la moyenne d’un Tweet est inférieure a 5 cela veut dire que le sentiment est négatif, s’il est égal a 5 le sentiment est neutre. Enfin si la moyenne est supérieure à 5 le sentiment sera positif.

Mon modèle est « basique » et donc limité, en effet j’affecte une tonalité positive, neutre ou négative à un mot sans tenir compte du contexte et je n’ai pas la capacité à analyser des figures rhétoriques comme le sarcasme ou l’ironie. Disons que c’est un premier jet et que la méthode a le mérite d’être rapide 😉

 

Les Données

Voici le format d’un Tweet : https://dev.twitter.com/docs/platform-objects/tweets.

J’ai récupéré des Tweets et les ai sauvegardés dans un Blob Storage Azure (wasb://DATA@apvxdcube.blob.core.windows.net/tweets).

J’ai créé et uploadé le dictionnaire suivant au format TSV :

Sentiment

Afin d’être plus précis, il serait intéressant de créer plusieurs dictionnaires, et de les utiliser en fonction des besoins, la polarité d’un mot dépend du contexte étudié.

 

Hive

J’ai créé un cluster HDInsight de 4 noeuds en utilisant des commandes PowerShell : https://pulsweb.azurewebsites.net/hdinsight-powershell/

J’ai sérialisé les Tweets à l’aide de Hive Json Serde :

ADD jar C:\apps\json-serde-1.1.6-SNAPSHOT-jar-with-dependencies.jar;
CREATE EXTERNAL TABLE tweets (
   id BIGINT,
   created_at STRING,
   source STRING,
   favorited BOOLEAN,
   retweet_count INT,
   retweeted_status STRUCT<
      text:STRING,
      user:STRUCT<screen_name:string,name:string>>,
   entities STRUCT<
      urls:ARRAY<struct<expanded_url:string>>,
      user_mentions:ARRAY<struct<screen_name:string,name:string>>,
      hashtags:ARRAY>,
   text STRING,
   user STRUCT< screen_name:STRING, name:STRING, friends_count:INT, followers_count:INT, statuses_count:INT, verified:BOOLEAN, utc_offset:STRING, time_zone:STRING>,
   in_reply_to_screen_name STRING
) ROW FORMAT SERDE 'org.openx.data.jsonserde.JsonSerDe'
LOCATION 'wasb://DATA@apvxdcube.blob.core.windows.net/tweets';

J’ai créé une table externe pour le dictionnaire

CREATE EXTERNAL TABLE dictionnaire (
    word string,
    polarity int
) ROW FORMAT DELIMITED FIELDS TERMINATED BY '\t' 
STORED AS TEXTFILE
LOCATION 'wasb://DATA@apvxdcube.blob.core.windows.net/dictionnaire';

J’ai créé trois vues :

CREATE VIEW view1 AS SELECT id, words FROM tweets LATERAL VIEW EXPLODE(SENTENCES(LOWER(text))) tmp AS words;
CREATE VIEW view2 AS SELECT id, word FROM view1 LATERAL VIEW explode(words) tmp AS word ;
CREATE VIEW view3 AS SELECT id, view2.word, d.polarity FROM view2 LEFT OUTER JOIN dictionnaire d ON LOWER(view2.word) = LOWER(d.word);
  • view1 possède l’identifiant des tweets et un tableau contenant la liste de chacun des mots composant le tweet.
  • view2 possède l’identifiant des tweets et ses mots qui le composent sur plusieurs lignes.
  • view3 possède l’identifiant des tweets, ses mots et leurs polarités (de 0 à 10).

L’UDF sentences() découpe une phrase en un tableau de mot :
SELECT sentences(« Je m’appelle Romain Casteres ») FROM somedata LIMIT 1;
Résultat : [[« Je », »m’appelle », »Romain », »Casteres »]]

L’UDF explode() prend en entrée un tableau et renvoie les éléments du tableau sur plusieurs lignes.
J’ai créé une table interne :

CREATE TABLE sentiment 
STORED AS ORC AS 
   SELECT 
      id, 
      CASE
         WHEN AVG(polarity) > 5 then 'positive' 
         when AVG( polarity ) < 5 then 'negative'  
         ELSE 'neutral' 
      END AS sentiment 
FROM view3 
GROUP BY id;

J’ai créé une dernière table interne :

CREATE TABLE myResult
STORED AS ORC AS 
   SELECT 
   t.*, 
   s.sentiment 
FROM tweets t 
LEFT OUTER JOIN sentiment s ON t.id = s.id;

Les tables Hive internes créent sont stockées en ORC (Optimized Row Columnar), cela améliore les performances de Hive.

 

Résultat

ReportSentiment

 

Ressources

 

Comments are closed.

En savoir plus sur Pulsweb - Romain Casteres

Abonnez-vous pour poursuivre la lecture et avoir accès à l’ensemble des archives.

Continue reading