[PYTHON] Versuchen Sie eine rudimentäre Stimmungsanalyse für Twitter Stream API-Daten.

Ich denke, dass die Emotionsanalyse eines der Dinge ist, die ich gerne tun würde, wenn ich eine Twitter-Analyse durchführe. (Ist es nicht so?) Ich denke, es gibt verschiedene Methoden, aber ich möchte mit dem einfachsten Beispiel beginnen und sehen, dass es allmählich fortgeschrittener wird (vorzugsweise).

Die zu analysierenden Daten sind wieder Twitter. Bisher wurde es jedoch unter Twitter REST APIs erworben, diesmal jedoch unter Twitter Stream API. (/ Streaming / Übersicht) Ich möchte die Twitter-Daten importieren, dann die Ergebnisse der Emotionsanalyse digitalisieren und in der Datenbank speichern.

Weitere Informationen zum Abrufen von Twitter-Daten für Mongodb finden Sie unter Vorheriger Artikel.

1. Holen Sie sich Daten von der Twitter Stream API und speichern Sie sie in mongoDB.

1-1 Vorbereitung

Zuallererst ist es eine Vorbereitung. Importiert verschiedene Bibliotheken, deklariert Dienstprogrammfunktionen und stellt eine Verbindung zur Datenbank her.

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):  #Da es sich um einen Tweet handelt, dürfen maximal 140 Zeichen verwendet werden
        if node.surface != "":  #Kopf- und Fußzeilen ausschließen
            word_type = node.feature.split(",")[0]
            if word_type in ["Adjektiv", "Verb","Substantiv", "Adverb"]:
                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 = { #Listen Sie unten die Schlüssel auf, die Sie mit Ihrem Konto erhalten haben
        'consumer_key':'**********',
        'consumer_secret':'**********',
        'access_token':'**********',
        'access_secret''**********',
       }

Dieses Mal verwendet das Protokoll Logger, um die Datei auszugeben. Die Protokollausgabe-Einstellungsdatei lautet wie folgt.

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=

1-2. Herunterladen und Fortbestehen des japanischen Evaluierungs-Polarwörterbuchs

Erstellt von der [Labor von Professor Inui und Professor Okazaki] der Tohoku-Universität (http://www.cl.ecei.tohoku.ac.jp/index.php?Open%20Resources%2FJapanese%20Sentiment%20Polarity%20Dictionary) Da Emotionen zunächst mit dem verfügbaren japanischen Bewertungspolaritätswörterbuch quantifiziert werden

Von hier Herunterladen und im selben Ordner wie .py speichern Machen.

In Bezug auf das japanische Bewertungspolaritätswörterbuch (Wörter) wird der positive Term als 1 und der negative Term als -1 quantifiziert und in Mongodb importiert. Für das japanische Bewertungspolaritätswörterbuch (Nomen Edition) wird der Term p als 1 quantifiziert, der Term e wird als 0 quantifiziert und der Term n wird -1 und in Mongodb importiert. Unten ist der Code.

#Positive und negative Wörter in mongoDB importieren

#Japanisches Bewertungspolaritätswörterbuch (Wörter) ver.1.Importieren Sie 0 (Version Dezember 2008) in mongodb
#Positiver Term ist 1,Negativer Begriff ist-Quantifizieren Sie als 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]=="Positiv" else -1
        posi_nega_dict.insert({"word":l[1].decode('utf-8'),"value":value})
        

#Japanisches Bewertungspolaritätswörterbuch (Nomenausgabe) ver.1.Importieren Sie 0 (Version Dezember 2008) in mongodb
#Der Term p ist 1 Der Term e ist 0,Der Term n ist-Quantifizieren Sie als 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})  

1-3. Verarbeitung zur Quantifizierung der emotionalen Ebene

Da wir in 1-2 eine Datenbank mit emotionalen Werten für jedes Wort erstellen konnten, werden wir eine Verarbeitung hinzufügen, mit der Sätze in emotionale Werte umgewandelt werden können. Diesmal ist es jedoch "elementar", so dass nichts getan wird und

  1. Überprüfen Sie einfach, ob jedes im Satz enthaltene Wort im japanischen Bewertungspolaritätswörterbuch vorhanden ist
  2. Wenn es existiert, verwenden Sie diese Nummer
  3. Berechnen Sie den emotionalen Wert des Satzes nach der folgenden Formel. ($ X_i $ ist der emotionale Wert des Wortes im japanischen Bewertungspolaritätswörterbuch, $ n $ ist die Anzahl der Wörter im japanischen Bewertungspolaritätswörterbuch.)
{\rm sentiment\, value\, of\, the\, sentence} \, = \, \frac{1}{n}\sum_{i=1}^{n} x_i 

Daher kann der emotionale Wert unabhängig von der Anzahl der Wörter im Satz zwischen -1 und 1 abgeleitet werden, und ein Vergleich zwischen Sätzen wird möglich.


#Einstellung der Emotionsstufe(In das Wörterbuchobjekt für die Hash-Suche aufnehmen, um die Suche zu beschleunigen)
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

# -Gibt den emotionalen Wert für einen bestimmten Satz (Wortliste) im Bereich von 1 bis 1 zurück.(1:Am positivsten,-1:Am negativsten)
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: #Wenn gefunden, addieren Sie die Punktzahlen und zählen Sie die Wörter
            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.

1-4. Herunterladen von Daten von der Twitter Stream API

Code zum Herunterladen von Tweet-Daten von der Twitter Stream API. Während des Herunterladens von Tweets wird mit MeCab eine morphologische Analyse durchgeführt, und jedes Wort wird durch Nomenklatur, Verb, Adjektiv und Zusatz getrennt und aufgelistet. Sogenannte Bag of Words.

Dann wird der Emotionswert durch die zuvor für diese Wörter definierte Funktion get_setntiment () abgeleitet und zusammen mit dieser in mongodb gespeichert.

# -----Stream-Daten importieren---------#
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'Substantiv')
                verb_list      = get_list_from_dict(result, u'Verb')
                adjective_list = get_list_from_dict(result, u'Adjektiv')
                adverb_list    = get_list_from_dict(result, u'Adverb')

                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
                
                #Ergebnisse der Emotionsanalyse hinzugefügt####################
                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( '===Fehlerinhalt===')
    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( '===Fehlerinhalt===')
    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.")

Bis zu diesem Punkt war die Analysemethode eine einfache Methode, um jedem Wort einfach emotionale Werte zuzuweisen und diese zu mitteln. In Bezug auf die zukünftige Entwicklung denken wir, dass die Spam-Klassifizierung ein Problem für die weitere Vorverarbeitung sein wird, und in der aktuellen Situation wird die Verarbeitung, die die Beziehungen zwischen Wörtern berücksichtigt, ein Problem sein. Insbesondere werden Wörter wie "nicht süß" in "süß" und "nicht" unterteilt, und da "nicht" verweigert wird, sollte der positive Ausdruck von "süß" +1,0 mit "nicht" gestrichen werden, um -1,0 zu erhalten. Ist natürlich, aber derzeit wird nur "süß" verarbeitet und es wird +1.0, was das gegenteilige Ergebnis ist.

Um dies richtig zu handhaben, ist es notwendig, durch eine Methode namens "Abhängigkeitsanalyse" zu verknüpfen und zu interpretieren, von welchem Wort "nicht" abhängt. Im nächsten Abschnitt möchte ich zunächst erläutern, wie die Abhängigkeitsanalysebibliothek CaboCha installiert wird.

2. Abhängigkeitsanalyse

2-1. Installation der Abhängigkeitsanalysebibliothek CaboCha

Daher möchte ich die Installation der Abhängigkeitsanalysebibliothek CaboCha http://taku910.github.io/cabocha/ auf einem Mac durchführen. Die Installation hat viel Zeit in Anspruch genommen, daher hoffe ich, dass es hilfreich sein wird.

** CaboCha herunterladen ** https://drive.google.com/folderview?id=0B4y35FiV1wh7cGRCUUJHVTNJRnM&usp=sharing#list

Für die Installation von CaboCha ist eine Bibliothek namens CRF + erforderlich. ** CRF + Seite ** http://taku910.github.io/crfpp/#install

** CRF + Download ** https://drive.google.com/folderview?id=0B4y35FiV1wh7fngteFhHQUN2Y1B5eUJBNHZUemJYQV9VWlBUb3JlX0xBdWVZTWtSbVBneU0&usp=drive_web#list

Nach dem Herunterladen entpacken und erstellen und installieren. Da es einige notwendige Umgebungsvariablen und Bibliotheken gibt, wird ihre Anwendung auch unten beschrieben.

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

Die obige Installationsmethode wurde unter Bezugnahme auf die folgende Site erstellt.

Site, die als Referenz für die CaboCha-Installation verwendet wurde

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

2-2. CaboCha-Test

Versuchen Sie die Abhängigkeitsanalyse mit dem Testtext.

import CaboCha

c = CaboCha.Parser()

sentence = "Soseki gab dieses Buch der Frau, die Ryunosuke sah."

tree =  c.parse(sentence)

print tree.toString(CaboCha.FORMAT_TREE)
print tree.toString(CaboCha.FORMAT_LATTICE)

Das Ergebnis der Ausführung dieses Codes ist wie folgt.

output


Soseki-----------D
Dies-D       |
Buch---D   |
Ryunosuke-D   |
sah-D |
Für Frauen-D
Ich habe es übergeben.
EOS

* 0 6D 0/1 -2.475106
Soseki Substantiv,Eigenname,Name der Person,Name,*,*,Soseki,Souseki,Soseki
Ist ein Assistent,Hilfe,*,*,*,*,Ist,C.,Beeindruckend
* 1 2D 0/0 1.488413
Dieser Zusatz,*,*,*,*,*,Dies,Dies,Dies
* 2 4D 0/1 0.091699
Diese Nomenklatur,Allgemeines,*,*,*,*,Buch,Hong,Hong
Hilfs,Fallassistent,Allgemeines,*,*,*,Zu,Wo,Wo
* 3 4D 0/1 2.266675
Ryunosuke Substantiv,Eigenname,Name der Person,Name,*,*,Ryunosuke,Ryunosuke,Ryunosuke
Hilfs,Fallassistent,Allgemeines,*,*,*,Zu,Wo,Wo
* 4 5D 0/1 1.416783
Schau Verb,Unabhängigkeit,*,*,Ein Schritt,Kontinuierlicher Typ,sehen,Mi.,Mi.
Hilfsverb,*,*,*,Besondere,Grundform,Ta,Ta,Ta
* 5 6D 0/1 -2.475106
Weibliche Nomenklatur,Allgemeines,*,*,*,*,Weiblich,Josei,Josei
Hilfs,Fallassistent,Allgemeines,*,*,*,Zu,D.,D.
* 6 -1D 0/1 0.000000
Verb übergeben,Unabhängigkeit,*,*,Godan / Sa Linie,Kontinuierlicher Typ,aushändigen,ich,ich
Hilfsverb,*,*,*,Besondere,Grundform,Ta,Ta,Ta
.. Symbol,Phrase,*,*,*,*,。,。,。
EOS

Die Zeile mit "*" ist das Analyseergebnis, und einige darauf folgende Wörter sind die Klauseln.

Neben * steht die "Phrasennummer". Als nächstes folgt die Klauselnummer des Kontakts, die -1 ist, wenn kein Kontakt vorhanden ist. Es scheint, dass Sie sich keine Sorgen um "D" machen müssen.

Die nächsten beiden Zahlen sind die Positionen der Hauptwörter / Funktionswörter

Die letzte Zahl gibt den Grad der Verlobungsbewertung an. Je größer der Wert, desto einfacher ist es im Allgemeinen, sich zu engagieren.

Die erste Phrase ist also 0 "Soseki ist", und die verantwortliche Person ist 6D, also ist sie "bestanden".

In diesem Artikel haben wir sogar CaboCha installiert, eine Bibliothek zur Abhängigkeitsanalyse. Ich möchte dies im nächsten Artikel auf Tweet-Daten anwenden.

Referenzen usw.

Japanisches Bewertungspolaritätswörterbuch - Inui Okazaki Laboratory --Tohoku University Nozomi Kobayashi, Kentaro Inui, Yuji Matsumoto, Kenji Tateishi, Shunichi Fukushima. Sammlung von Bewertungsausdrücken zum Extrahieren von Meinungen. Verarbeitung natürlicher Sprache, Band 12, Nr. 3, S. 203-222, 2005. Masahiko Higashiyama, Kentaro Inui, Yuji Matsumoto, Erwerb der Polarität der Nasenbewertung mit Schwerpunkt auf der Präferenz für die Prädikatauswahl, Bericht der 14. Jahrestagung der Language Processing Society, S. 584-587, 2008.

Recommended Posts

Versuchen Sie eine rudimentäre Stimmungsanalyse für Twitter Stream API-Daten.
Versuchen Sie es mit der Twitter-API
[Python] Hinweise zur Datenanalyse
Versuchen Sie "100 Schläge auf Data Science" ①
Versuchen Sie es mit der Twitter-API
Twitter-Daten analysieren | Trendanalyse
Visualisierung und Analyse von Stava Twitter-Datenstandortinformationen
Datenanalyseumgebung mit Schwerpunkt auf Datalab (+ GCP)
Emotionale Analyse umfangreicher Tweet-Daten durch NLTK
Versuchen Sie, MLB-Daten auf Mac und Python zu importieren
Holen Sie sich mit Python eine große Menge von Starbas Twitter-Daten und probieren Sie die Datenanalyse Teil 1 aus