Deep Learning Tutorial

chainer and python

6章  クラス分類 II:感情分析

まずはツイートデータを取得します。
しかし、ここでつまずきました...

いろいろ調べてツイートをダウンロードするコードを書きました。
tweepyというモジュールをダウンロードします。
以下のサイトが参考になりました
statsbeginner.hatenablog.com




しかし、API制限という最悪なものがあるため、どうやら180回/15分しかツイートをダウンロードできないようです。
API制限まとめ

解除する方法もちらほらあるようですが、自分にはよくわからないので仕方なく仕様どうりに行きたいと思います。

http://www.sananalytics.com/lab/twitter-sentiment/

このサイトから"sanders-twitter-0.2.zip"をダウンロードして解凍します。
その中にある、"corpus.csv"と同じディレクトリ内で以下のコードを実行します。

import tweepy
import csv
import time
import numpy as np
import pandas as pd
from time import sleep

# csvファイル読み込み
d = pd.read_csv('corpus.csv', names=['topic', 'pos/neg', 'id'])
f = open("tweet_text.csv", "a")
writer = csv.writer(f)
data = np.array(d['id'])

# 各種キーをセット
CONSUMER_KEY = 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'
CONSUMER_SECRET = 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'
auth = tweepy.OAuthHandler(CONSUMER_KEY, CONSUMER_SECRET)
ACCESS_TOKEN = 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'
ACCESS_SECRET = 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'
auth.set_access_token(ACCESS_TOKEN, ACCESS_SECRET)

#APIインスタンスを作成
api = tweepy.API(auth)


text = []
error = []
data_size = len(data)
for i in range(data_size):
    if i % 180 or i == 0:
        try:
            text.append([api.get_status(data[i]).text])
        except:
            text.append(["Error"])
            error.append(i)
            print(i," : Error")
    else:
        print("stop downloading(API) time [{} : {}] ".format(time.gmtime().tm_hour, time.gmtime().tm_min))
        print("Error tottal : ", len(error))
        sleep(900)
        continue

print("finished")
print("error index", error)
writer.writerows(text)
f.close()


7時間ぐらいかかります笑

終わると、"tweet_text.csv"というファイルが生成されていると思います。

最初はpositiveとnegativeの分類です。
"tweet_text.csvでは、1〜191までが"positive"、192〜568までが"negative"となっています。
なので、"Error"以外を取り除いて読み取っていきます。

f = open("tweet_text.csv", "r")
text = []
index = []

for i in range(568):
    t = f.readline()
    if t != 'Error\n':
        text.append(t)
        if i<=190:
            index.append(0)
        elif 191<= i <= 567:
            index.append(1)

その後、前回つかった"StemmedTfidfVectorizer"を使います。

english_stemmer = nltk.stem.SnowballStemmer('english')

class StemmedTfidfVectorizer(TfidfVectorizer):
    def build_analyzer(self):
        analyzer = super(TfidfVectorizer, self).build_analyzer()
        return lambda doc: (english_stemmer.stem(w) for w in analyzer(doc))

vec = StemmedTfidfVectorizer(ngram_range=(1, 3), stop_words='english', decode_error='ignore')
X = vec.fit_transform(text)
y = np.array(index)

X_train, X_test, y_train, y_test = train_test_split(X, y, train_size=0.7, random_state=0)

clf = MultinomialNB(alpha=0.8)
clf.fit(X_train, y_train)


正解率とAUCを見て行きましょう。

正解率 :  0.69105691056
AUC   :  0.82078313253

本とは違うやり方をしたせいか、正解率が約70%ととても低いです...
とりあえず、bias-variansグラフを見てみましょう。


f:id:tsuruchan_0827:20160225153246p:plain

!?!? 超ハイバリアンスですね...

ちょっとやる気をなくしたので、感情ありor感情なしの分類の方へ逃げようと思います。

感情なしのツイートは568〜5483になっています。
感情ありと感情なしのデータ比がちょっと....
細かいことは気にせずやっていきましょう。

for i in range(5483):
    t = f.readline()
    if t != 'Error\n':
        text.append(t)
        if i<=567:
            index.append(0)
        else:
            index.append(1)


正解率とAUCを見て行きましょう。

正解率 :  0.90955882352
AUC   :  0.882790780212

正解率90%はなかなかいい数字だと思います。
これも、bias-variansグラフを見てみましょう。

f:id:tsuruchan_0827:20160225153942p:plain


なかなかいい感じじゃなかいか!!
これで満足です。
positiveとnegativeの分類は忘れたとこにしましょう。


一応、全体のコードです。

import numpy as np
import nltk.stem
import matplotlib.pyplot as plt
from sklearn.metrics import roc_auc_score
from sklearn.naive_bayes import MultinomialNB
from sklearn.cross_validation import train_test_split
from sklearn.feature_extraction.text import TfidfVectorizer

f = open("tweet_text.csv", "r")
text = []
index = []

for i in range(568):
    t = f.readline()
    if t != 'Error\n':
        text.append(t)
        if i<=190:
            index.append(0)
        elif 191<= i <= 567:
            index.append(1)

english_stemmer = nltk.stem.SnowballStemmer('english')

class StemmedTfidfVectorizer(TfidfVectorizer):
    def build_analyzer(self):
        analyzer = super(TfidfVectorizer, self).build_analyzer()
        return lambda doc: (english_stemmer.stem(w) for w in analyzer(doc))

vec = StemmedTfidfVectorizer(ngram_range=(1, 3), stop_words='english', decode_error='ignore')
X = vec.fit_transform(text)
y = np.array(index)

X_train, X_test, y_train, y_test = train_test_split(X, y, train_size=0.7, random_state=0)
clf = MultinomialNB(alpha=0.8)
clf.fit(X_train, y_train)
   

y_pred = clf.predict_proba(X_test)[:, 1]

print("正解率 : ", clf.score(X_test, y_test))
print("AUC : ", roc_auc_score(y_test, y_pred))