Je pense que l'analyse des émotions est l'une des choses que j'aimerais faire lors de l'analyse de Twitter. (N'est-ce pas?) Je pense qu'il existe différentes méthodes, mais j'aimerais commencer par l'exemple le plus simple et voir qu'il devient progressivement plus avancé (de préférence).
Les données à analyser seront à nouveau Twitter. Cependant, jusqu'à présent, il a été acquis sur API REST Twitter, mais cette fois, il a été acquis sur API Twitter Stream. (/ streaming / overview) Je souhaite importer les données Twitter, puis numériser les résultats de l'analyse des émotions et les stocker dans la base de données.
Veuillez vous référer à Article précédent pour obtenir des explications sur la façon d'obtenir des données Twitter vers mongodb.
Tout d'abord, c'est une préparation. Importe diverses bibliothèques, déclare des fonctions utilitaires et se connecte à la base de données.
from requests_oauthlib import OAuth1Session
from requests.exceptions import ConnectionError, ReadTimeout, SSLError
import json, time, exceptions, sys, datetime, pytz, re, unicodedata, pymongo
import oauth2 as oauth
import urllib2 as urllib
import MeCab as mc
from collections import defaultdict
from pymongo import MongoClient
from httplib import IncompleteRead
import numpy as np
import logging
from logging import FileHandler, Formatter
import logging.config
connect = MongoClient('localhost', 27017)
db = connect.word_info
posi_nega_dict = db.posi_nega_dict
db2 = connect.twitter
streamdata = db2.streamdata
def str_to_date_jp(str_date):
dts = datetime.datetime.strptime(str_date,'%a %b %d %H:%M:%S +0000 %Y')
return pytz.utc.localize(dts).astimezone(pytz.timezone('Asia/Tokyo'))
def mecab_analysis(sentence):
t = mc.Tagger('-Ochasen -d /usr/local/Cellar/mecab/0.996/lib/mecab/dic/mecab-ipadic-neologd/')
sentence = sentence.replace('\n', ' ')
text = sentence.encode('utf-8')
node = t.parseToNode(text)
result_dict = defaultdict(list)
for i in range(140): #Puisqu'il s'agit d'un tweet, MAX 140 caractères
if node.surface != "": #Exclure les en-têtes et les pieds de page
word_type = node.feature.split(",")[0]
if word_type in ["adjectif", "verbe","nom", "adverbe"]:
plain_word = node.feature.split(",")[6]
if plain_word !="*":
result_dict[word_type.decode('utf-8')].append(plain_word.decode('utf-8'))
node = node.next
if node is None:
break
return result_dict
def logger_setting():
import logging
from logging import FileHandler, Formatter
import logging.config
logging.config.fileConfig('logging_tw.conf')
logger = logging.getLogger('filelogger')
return logger
logger = logger_setting()
KEYS = { #Répertoriez ci-dessous les clés que vous avez obtenues avec votre compte
'consumer_key':'**********',
'consumer_secret':'**********',
'access_token':'**********',
'access_secret''**********',
}
logging_tw.conf
# logging_tw.conf
[loggers]
keys=root, filelogger
[handlers]
keys= fileHandler
[formatters]
keys=logFormatter
[logger_root]
level=DEBUG
handlers=fileHandler
[logger_filelogger]
level=DEBUG
handlers=fileHandler
qualname=filelogger
propagate=0
[handler_fileHandler]
class=handlers.RotatingFileHandler
level=DEBUG
formatter=logFormatter
args=('logging_tw.log',)
[formatter_logFormatter]
format=%(asctime)s - %(name)s - %(levelname)s - %(message)s
datefmt=
Créé par le [Laboratoire du professeur Inui et du professeur Okazaki] de l'Université Tohoku (http://www.cl.ecei.tohoku.ac.jp/index.php?Open%20Resources%2FJapanese%20Sentiment%20Polarity%20Dictionary) Puisque les émotions sont quantifiées à l'aide du dictionnaire japonais de polarité d'évaluation disponible, tout d'abord
D'ici Téléchargez et stockez dans le même dossier que .py Faire.
En ce qui concerne le dictionnaire japonais de polarité d'évaluation (mots), le terme positif est quantifié comme 1 et le terme négatif est -1 et importé dans mongodb. Pour le dictionnaire japonais de polarité d'évaluation (édition nomen), le terme p est quantifié comme 1, le terme e est quantifié comme 0 et le terme n est -1 et importé dans mongodb. Ci-dessous le code.
#Importer des mots positifs et négatifs dans mongoDB
#Dictionnaire japonais de polarité d'évaluation (mots) ver.1.Importer 0 (version de décembre 2008) dans mongodb
#Le terme positif est 1,Le terme négatif est-Quantifier comme 1
with open("wago.121808.pn.txt", 'r') as f:
for l in f.readlines():
l = l.split('\t')
l[1] = l[1].replace(" ","").replace('\n','')
value = 1 if l[0].split('(')[0]=="Positif" else -1
posi_nega_dict.insert({"word":l[1].decode('utf-8'),"value":value})
#Dictionnaire japonais de polarité d'évaluation (édition du nom) ver.1.Importer 0 (version de décembre 2008) dans mongodb
#Le terme p est 1 Le terme e est 0,Le terme n est-Quantifier comme 1
with open("pn.csv.m3.120408.trim", 'r') as f:
for l in f.readlines():
l = l.split('\t')
if l[1]=="p":
value = 1
elif l[1]=="e":
value = 0
elif l[1]=="n":
value = -1
posi_nega_dict.insert({"word":l[0].decode('utf-8'),"value":value})
Puisque nous avons pu créer une base de données de valeurs émotionnelles pour chaque mot en 1-2, nous ajouterons un traitement qui peut convertir des phrases en valeurs émotionnelles. Cependant, cette fois c'est "élémentaire" donc rien n'est fait et
{\rm sentiment\, value\, of\, the\, sentence} \, = \, \frac{1}{n}\sum_{i=1}^{n} x_i
Par conséquent, la valeur émotionnelle peut être dérivée entre -1 et 1 quel que soit le nombre de mots dans la phrase, et la comparaison entre les phrases devient possible.
#Réglage du niveau d'émotion(Inclure dans l'objet dictionnaire pour la recherche par hachage pour accélérer la recherche)
pn_dict = {data['word']: data['value'] for data in posi_nega_dict.find({},{'word':1,'value':1})}
def isexist_and_get_data(data, key):
return data[key] if key in data else None
# -Renvoie la valeur émotionnelle d'une phrase donnée (liste de mots) comprise entre 1 et 1.(1:Le plus positif,-1:Le plus négatif)
def get_setntiment(word_list):
val = 0
score = 0
word_count = 0
val_list = []
for word in word_list:
val = isexist_and_get_data(pn_dict, word)
val_list.append(val)
if val is not None and val != 0: #Si trouvé, ajoutez les scores et comptez les mots
score += val
word_count += 1
logger.debug(','.join(word_list).encode('utf-8'))
logger.debug(val_list)
return score/float(word_count) if word_count != 0. else 0.
Code pour télécharger les données de tweet depuis l'API Twitter Stream. Lors du téléchargement des tweets, l'analyse morphologique est effectuée avec MeCab, et chaque mot est séparé et répertorié par nomenclature, verbe, adjectif et complément. Soi-disant sac de mots.
Ensuite, la valeur d'émotion est dérivée par la fonction get_setntiment () définie précédemment pour ces mots, et elle est stockée dans mongodb avec ceci.
# -----Importer des données de flux---------#
consumer = oauth.Consumer(key=KEYS['consumer_key'], secret=KEYS['consumer_secret'])
token = oauth.Token(key=KEYS['access_token'], secret=KEYS['access_secret'])
url = 'https://stream.twitter.com/1.1/statuses/sample.json'
params = {}
request = oauth.Request.from_consumer_and_token(consumer, token, http_url=url, parameters=params)
request.sign_request(oauth.SignatureMethod_HMAC_SHA1(), consumer, token)
res = urllib.urlopen(request.to_url())
def get_list_from_dict(result, key):
if key in result.keys():
result_list = result[key]
else:
result_list = []
return result_list
cnt = 1
try:
for r in res:
data = json.loads(r)
if 'delete' in data.keys():
pass
else:
if data['lang'] in ['ja']: #['ja','en','und']:
result = mecab_analysis(data['text'].replace('\n',''))
noun_list = get_list_from_dict(result, u'nom')
verb_list = get_list_from_dict(result, u'verbe')
adjective_list = get_list_from_dict(result, u'adjectif')
adverb_list = get_list_from_dict(result, u'adverbe')
item = {'id':data['id'], 'screen_name': data['user']['screen_name'],
'text':data['text'].replace('\n',''), 'created_datetime':str_to_date_jp(data['created_at']),\
'verb':verb_list, 'adjective':adjective_list, 'noun': noun_list, 'adverb':adverb_list}
if 'lang' in data.keys():
item['lang'] = data['lang']
else:
item['lang'] = None
#Ajout des résultats de l'analyse des émotions####################
word_list = [word for k in result.keys() for word in result[k] ]
item['sentiment'] = get_setntiment(word_list)
streamdata.insert(item)
if cnt%1000==0:
logger.info("%d, "%cnt)
cnt += 1
except IncompleteRead as e:
logger.error( '===contenu de l'erreur===')
logger.error( 'type:' + str(type(e)))
logger.error( 'args:' + str(e.args))
logger.error( 'message:' + str(e.message))
logger.error( 'e self:' + str(e))
try:
if type(e) == exceptions.KeyError:
logger.error( data.keys())
except:
pass
except Exception as e:
logger.error( '===contenu de l'erreur===')
logger.error( 'type:' + str(type(e)))
logger.error( 'args:' + str(e.args))
logger.error( 'message:' + str(e.message))
logger.error( 'e self:' + str(e))
try:
if type(e) == exceptions.KeyError:
logger.error( data.keys())
except:
pass
except:
logger.error( "error.")
logger.info( "finished.")
Jusqu'à présent, la méthode d'analyse était une méthode simple pour attribuer simplement des valeurs émotionnelles à chaque mot et en faire la moyenne. En ce qui concerne le développement futur, nous pensons que la classification du spam sera un problème en tant que prétraitement ultérieur, et dans la situation actuelle, le traitement qui prend en compte les relations entre les mots sera problématique. En particulier, les mots tels que "pas mignon" sont divisés en "mignon" et "pas", et puisque "pas" est refusé, l'expression positive de "mignon" +1.0 doit être annulée avec "pas" pour en faire -1.0. C'est naturel, mais à l'heure actuelle, seul «mignon» est traité et il devient +1,0, ce qui est le résultat inverse.
Afin de gérer cela correctement, il est nécessaire de relier et d'interpréter de quel mot "non" dépend une méthode appelée "analyse de dépendance". Dans la section suivante, j'aimerais expliquer comment installer d'abord la bibliothèque d'analyse de dépendances CaboCha.
Je souhaite donc gérer l'installation de la bibliothèque d'analyse des dépendances CaboCha http://taku910.github.io/cabocha/ sur Mac. Il a fallu beaucoup de temps pour l'installer, j'espère donc que ce sera utile.
** Télécharger CaboCha ** https://drive.google.com/folderview?id=0B4y35FiV1wh7cGRCUUJHVTNJRnM&usp=sharing#list
Une bibliothèque appelée CRF + est nécessaire pour installer CaboCha. ** Page CRF + ** http://taku910.github.io/crfpp/#install
** CRF + Télécharger ** https://drive.google.com/folderview?id=0B4y35FiV1wh7fngteFhHQUN2Y1B5eUJBNHZUemJYQV9VWlBUb3JlX0xBdWVZTWtSbVBneU0&usp=drive_web#list
Après le téléchargement, décompressez et créez et installez. Puisqu'il existe certaines variables d'environnement et bibliothèques nécessaires, leur application est également décrite ci-dessous.
tar zxfv CRF++-0.58.tar
cd CRF++-0.58
./configure
make
sudo make install
export LIBRARY_PATH="/usr/local/include:/usr/local/lib:"
export CPLUS_INCLUDE_PATH="/usr/local/include:/opt/local/include"
export OBJC_INCLUDE_PATH="/usr/local/include:/opt/local/lib"
brew tap homebrew/dupes
brew install libxml2 libxslt libiconv
brew link --force libxml2
brew link --force libxslt
brew link libiconv —force
tar zxf cabocha-0.69.tar.bz2
cd cabocha-0.69
./configure --with-mecab-config=`which mecab-config` --with-charset=UTF8
make
make check
sudo make install
#[output: install information]
#.././install-sh -c -d '/usr/local/share/man/man1'
#/usr/bin/install -c -m 644 cabocha.1 '/usr/local/share/man/man1'
#./install-sh -c -d '/usr/local/bin'
#/usr/bin/install -c cabocha-config '/usr/local/bin'
#./install-sh -c -d '/usr/local/etc'
#/usr/bin/install -c -m 644 cabocharc '/usr/local/etc'
cd cabocha-0.69/python
python setup.py install
cp build/lib.macosx-10.10-intel-2.7/_CaboCha.so /Library/Python/2.7/site-packages
cp build/lib.macosx-10.10-intel-2.7/CaboCha.py /Library/Python/2.7/site-packages
La méthode d'installation ci-dessus a été créée en se référant au site suivant.
http://qiita.com/nezuq/items/f481f07fc0576b38e81d#1-10 http://hotolab.net/blog/mac_mecab_cabocha/ http://qiita.com/t_732_twit/items/a7956a170b1694f7ffc2 http://blog.goo.ne.jp/inubuyo-tools/e/db7b43bbcfdc23a9ff2ad2f37a2c72df http://qiita.com/t_732_twit/items/a7956a170b1694f7ffc2
Essayez l'analyse des dépendances avec le texte d'essai.
import CaboCha
c = CaboCha.Parser()
sentence = "Soseki a remis ce livre à la femme qui a vu Ryunosuke."
tree = c.parse(sentence)
print tree.toString(CaboCha.FORMAT_TREE)
print tree.toString(CaboCha.FORMAT_LATTICE)
Le résultat de l'exécution de ce code est le suivant.
output
Soseki-----------D
cette-D |
Livre---D |
Ryunosuke-D |
vu-D |
Aux femmes-D
Je l'ai remis.
EOS
* 0 6D 0/1 -2.475106
Soseki substantif,Nomenclature propriétaire,Nom d'une personne,Nom,*,*,Soseki,Souseki,Soseki
Est un assistant,Assistance,*,*,*,*,Est,C,sensationnel
* 1 2D 0/0 1.488413
Cet accessoire,*,*,*,*,*,cette,cette,cette
* 2 4D 0/1 0.091699
Cette nomenclature,Général,*,*,*,*,Livre,Hong,Hong
Auxiliaire,Assistant de cas,Général,*,*,*,À,Wo,Wo
* 3 4D 0/1 2.266675
Ryunosuke substantif,Nomenclature propriétaire,Nom d'une personne,Nom,*,*,Ryunosuke,Ryunosuke,Ryunosuke
Auxiliaire,Assistant de cas,Général,*,*,*,À,Wo,Wo
* 4 5D 0/1 1.416783
Look verbe,Indépendance,*,*,Un pas,Type continu,à voir,Mi,Mi
Verbe auxiliaire,*,*,*,Spécial,Forme basique,Ta,Ta,Ta
* 5 6D 0/1 -2.475106
Nomenclature féminine,Général,*,*,*,*,Femme,Josei,Josei
Auxiliaire,Assistant de cas,Général,*,*,*,À,ré,ré
* 6 -1D 0/1 0.000000
Verbe passant,Indépendance,*,*,Ligne Godan / Sa,Type continu,remettre,je,je
Verbe auxiliaire,*,*,*,Spécial,Forme basique,Ta,Ta,Ta
.. symbole,Phrase,*,*,*,*,。,。,。
EOS
La ligne avec "*" est le résultat de l'analyse, et quelques mots qui suivent sont les clauses.
À côté de * se trouve le "numéro de phrase". Vient ensuite le numéro de clause du contact, qui est -1 s'il n'y a pas de contact. Il semble que vous n'ayez pas à vous soucier de "D".
Les deux nombres suivants sont les positions des mots principaux / mots fonctionnels
Le dernier chiffre indique le degré de score d'engagement. Généralement, plus la valeur est élevée, plus il est facile de s'engager.
Donc, la première phrase est 0 "Soseki est", et le responsable est 6D, donc il est "passé".
Dans cet article, nous avons même installé CaboCha, une bibliothèque d'analyse des dépendances. Je voudrais appliquer cela aux données de tweet dans le prochain article.
Dictionnaire japonais de la polarité d'évaluation - Laboratoire Inui Okazaki - Université de Tohoku Nozomi Kobayashi, Kentaro Inui, Yuji Matsumoto, Kenji Tateishi, Shunichi Fukushima. Collection d'expressions d'évaluation pour extraire des opinions. Traitement du langage naturel, Vol.12, No.3, pp.203-222, 2005. Masahiko Higashiyama, Kentaro Inui, Yuji Matsumoto, Acquisition of Nomenclature Evaluation Polarity Focusing on Predicate Selection Preference, Proceedings of the 14th Annual Meeting of the Language Processing Society, pp.584-587, 2008.
Recommended Posts