【ソースコード付き】Twitterのつぶやきを感情分析してみる その1

投稿日: カテゴリー: IT

 

Advertisements

はじめに

日本語のテキストマイニングを、Facebook FastTextで実際にやってみる。
Facebook FastTextのsouce codeはすべてここから取得できます。
build方法なども書いてある。

今回は、Twitterのつぶやきの感情分析を行い、
そのつぶやきが ポジティブ なのか ネガティブ なのか、それを判定してみようと思う。

 

前提

すでに前の記事で以下について投稿済みなので、そちらを事前に見ておくと、スムーズかと思います。

  1. 環境構築
    • Mecabやfasttextなどの導入手順
  2. 日本語の前処理
    • 形態素解析
    • テキストマイニングの精度向上させるコツ
    • それを実現するためのライブラリとその使い方
  3. 本記事で使用するコードは、全てここから取得可能

 

手順

以下のような順で実施する。

  1. twitterからデータを入手する
  2. 入手したデータの前処理
  3. 教師データの学習と学習モデル作成
  4. 評価対象データの分類
  5. 結果の可視化
  6. 結果の解釈

長くなるので、今回は 入手したデータの前処理 までを述べる。

 

1. twitterからデータを入手する

基本的に、以下のようにgetTweet.pyに引数を与えて実行すれば取得できる。

python getTweet.py 対象アカウント

対象アカウントとして、引数に複数指定できる。
1.1節で、一気に複数アカウントを取得するshell scriptを紹介する。

 

ただし、Twitter APIの制限で、最大およそ3,000件 しか取得できない。
そのため、たくさんつぶやくアカウントのデータ期間は短くなることに注意。
そしてその逆に、あまり呟かないアカウントデータ期間は、長くなる。

 

1.1 教師データの入手

教師データの準備として、twitterでポジティブ名言とネガティブ名言を取得する。
ポジティブ名言として取得したアカウント、ネガティブ明言として取得したアカウントの一覧は以下の通り。

分類アカウントアカウント数
ポジティブpositive_bot3 posi_tive_sp_ kami_positive positivekk_bot maemukikotoba1 Plus_bot heart_meign bot105863218
ネガティブn_siko nega_bot Mostnegative cynicalbot UnluckyBot Antinatalismbot6

 
教師データとする、ネガティブ発言を集めるのが悩ましかった。そりゃそうか。
みんな、ネガティブなことなんて、聞きたいくないし。

以下のように、shellからpython codeを呼び出して、twitterデータを収集する。

#!/bin/bash
#
# ポジティブ名言アカウントとネガティブ名言アカウントを配列にしておいて、一気に取得する
P_ARRAY=(positive_bot3 posi_tive_sp_ kami_positive positivekk_bot maemukikotoba1 Plus_bot heart_meign bot10586321)
N_ARRAY=(n_siko nega_bot Mostnegative cynicalbot UnluckyBot Antinatalismbot)
echo get tweet data
for item in ${P_ARRAY[@]} ${N_ARRAY[@]}; do
echo "get tweet data: "$item
python getTweet.py $item
sleep 3
done

 
この後も使うため、ポジティブなアカウントとネガィテブなアカウントを、
それぞれ P_ARRAYN_ARRAY という配列に入れておく。

どんな処理をしているのか気になる場合は、getTweet.pyの中身を見て欲しい。
positive_bot3.n_siko.txt、。。。といった、アカウント名.txt というテキストファイルが作成される。

ファイルの中身は、こんな感じになっているはず。
これは、「positive_bot3.txt」 の中身の一部です。

date    user    tweet
Fri Aug 04 07:19:03 +0000 2017  positive_bot3   剣は折れた。だが私は折れた剣の端を握ってあくまで戦うつもりだ。~ド・ゴール~
Fri Aug 04 05:19:05 +0000 2017  positive_bot3   あきらめたらそこで試合終了だよ ~安西監督~
Fri Aug 04 01:19:05 +0000 2017  positive_bot3   人生の目的は悟ることではありません。生きるんです。人間は動物ですから。~岡本太郎~
Thu Aug 03 23:19:07 +0000 2017  positive_bot3   他人の後ろから行くものは、けっして前進しているのではない。 ~ロマン・ロラン~
Thu Aug 03 13:19:04 +0000 2017  positive_bot3   過ぎたことを悔やんでも、しょうがないじゃないか。目はどうして前についていると思う?前向きに進んでいくためだよ。  ~ ドラえもん~
Thu Aug 03 11:19:05 +0000 2017  positive_bot3   知ってた?スタバで出来る無料のカスタマイズおすすめ5選!
Thu Aug 03 09:19:03 +0000 2017  positive_bot3   やる前に負ける事考えるバカいるかよ! ~アントニオ猪木~
Thu Aug 03 07:19:03 +0000 2017  positive_bot3   人生3万日しかない~中川翔子~
Thu Aug 03 05:19:07 +0000 2017  positive_bot3   10年後にはきっと、せめて10年でいいからもどってやり直したいと思っているのだろう。 今やり直せよ。未来を。10年後か、20年後か、50年後からもどってきたんだよ今。~2ちゃんねる就職板~
Thu Aug 03 03:19:04 +0000 2017  positive_bot3   発明は恋愛と同じです。苦しいと思えば苦しい。楽しいと思えばこれほど楽しいことはありません。~本田宗一郎~

 

1.2 評価対象データの入手

分析対象データもtwitterのつぶやきなので、合わせて取得しておく。
方法は、教師データとまったく同様。

分類アカウントアカウント数
個人的フォロワーboomin614 shimasho yutokiku karen529mm iwasaki_p toosee_spidy6
アニメのキャラセリフ他matsuoka_shuzo shinji0606_bot ayano05153
日経関連アカウントnikkei nikkeilive nikkeivdata nikkeistyle nikkeiDUAL nikkei_WOL nikkei_ent Nikkei_TRENDY9

 
以下のようにすることで、boomin614.txt、shimasho.txt、。。。といった、アカウント名.txt というテキストファイルが作成される。

# 対象アカウントを配列にしておいて、一気に取得する
#!/bin/bash
#
T_ARRAY=(boomin614 shimasho yutokiku karen529mm iwasaki_p toosee_spidy)
A_ARRAY=(matsuoka_shuzo shinji0606_bot ayano0515)
NIKKEI=(nikkei nikkeilive nikkeivdata nikkeistyle nikkeiDUAL nikkei_WOL nikkei_ent Nikkei_TRENDY)
echo get tweet data
for item in ${T_ARRAY[@]} ${NIKKEI[@]}; do
echo "get tweet data: "$item
python getTweet.py $item
sleep 3
done

ファイルの中身は、こんな感じになっているはず。
これは、「nikkei.txt」 の中身の一部。

date    user    tweet
Fri Aug 04 07:52:02 +0000 2017  nikkei  伊藤忠商事CFO、中国経済「思っている以上に順調」
Fri Aug 04 07:13:00 +0000 2017  nikkei  バルセロナからパリ・サンジェルマンに移籍するサッカーの #ネイマール。巨額移籍を動かしたカタールマネーの底力に迫りました。
Fri Aug 04 07:10:03 +0000 2017  nikkei  ネイマール獲得 カタールマネーの底力
Fri Aug 04 07:10:02 +0000 2017  nikkei  海外旅行「はしか」にご注意 欧州で流行、厚労省呼び掛け
Fri Aug 04 06:58:02 +0000 2017  nikkei  民進・細野氏、離党の意向表明 「新党つくる決意」
Fri Aug 04 06:55:02 +0000 2017  nikkei  日経平均続落、終値は76円安の1万9952円

 

Advertisements

2. 入手したデータの前処理

ここでは、twitterとして得られた教師データと評価対象データの前処理について述べる。

 

2.1 教師データの前処理

前処理としてやらないといけないことは、だいたい以下の通り。

  1. 不要データの削除
  2. 規格化、分かち書き、品詞フィルタ
    • 教師データとして、ノイズ低減のために、規格化と品詞やストップワードによるフィルタリングが必要
    • さらに、日本語の場合、単語で分かち書きする必要あり
  3. 学習対象データの抽出と連結
  4. 学習対象データのラベル付け
  5. 重複データの削除

不要データの削除は、形態素解析する前のほうが都合がいいこともあるし、
あとのほうが都合がよいこともあるでしょう。
処理順や処理内容は、ここで述べる内容をもとに、各自でデータごとに、そこは適当に処理をしてください。

 

2.1.1 不要データの削除(お好み)

分析において、その他削除したい単語などがある場合は、その処理を行う。

例えば、今回の場合、twitterのデータを分析対象としている。
そのため、内容によっては、以下のような文字列(とその正規表現)は、削除したくなるかもしれない。

  • Hashtagの削除
    • hashtagそのものは、文章の流れとは関係ないと判断して削除
  • 引用元を削除
    • (人名)となっているような部分は、文章の流れではないと仮定して削除
    • アカウントによって表現は異なるが、例えば以下のようなケースがある。
    • (\w*)や、 \(\w*\)
    • ~\w*~とか
  • リプライを削除
    • botのアカウントを使って、管理者が呟いているようなものは、名言じゃないと判断して削除する
    • @\.* とか

こうした上記のような文字列は、教師データとしてふさわしくないとして、削除する。
実際には、アカウントというか、対象データの中身を見て、しかるべき文字列を削除する。

ここでは、いちいちアカウントごとに一つずつやるのも面倒なので、正規表現で一括処理することにする。

$ regexp.sh ${P_ARRAY[@]} ${N_ARRAY[@]} ${T_ARRAY[@]} ${A_ARRAY[@]} ${NIKKEI[@]}

 
どんな処理をしているのかは、regexp.shの中身を見てほしい。
sed使って正規表現で一気に該当部分を削除しているだけ。
これを実行すると、元ファイルが書き換えられる。
それが嫌なら、元のtweetデータはバックアップを取っておくこと。

 

2.1.2 教師データの規格化、分かち書き、品詞フィルタ

こんな感じで、createLearningData.pyに引数を指定して実行する。

echo convert tweet data to wakati
for item in ${P_ARRAY[@]} ${N_ARRAY[@]}; do
echo "converting data: "$item
python createLearningData.py ${item}.txt -n 2
done

 
-nオプションで、対象のカラム番号を指定する。
最初のカラム番号が、0から始まることに注意する。
すなわち、ここで2をしているということは、3番目のカラムとなる。

以下のような2つのファイルが出力される。

  • w_positive_bot3.tsv
  • w_positive_bot3.pkl

教師データの前処理としては、以降、拡張子が「tsv」のものを使用する。

このコマンドの結果、以下のような内容のファイルが得られる。
これは、w_positive_bot3.tsv の内容となる。

Fri Aug 04 23:19:06 +0000 2017  positive_bot3   自分 立つ いる  深い 掘る そこ キット 泉 湧く でる
Fri Aug 04 13:19:08 +0000 2017  positive_bot3   自分 考える た  生きる ない なる ない そう だ ない 自分 生きる た  考える しまう
Fri Aug 04 11:19:05 +0000 2017  positive_bot3   お前 いつか 出会う 災い おまえ おろそか する た 時間 報い だ
Fri Aug 04 09:19:04 +0000 2017  positive_bot3   やる 前 負ける  考える バカ いる かよ
Fri Aug 04 07:19:03 +0000 2017  positive_bot3   剣 折れる た だ 私 折れる た 剣 端 握る あくまで 戦う  だ
Fri Aug 04 05:19:05 +0000 2017  positive_bot3   あきらめる た 試合終了 だ
Fri Aug 04 01:19:05 +0000 2017  positive_bot3   人生の目的 悟る  だ ある ます ん 生きる  です 人間 動物 です
Thu Aug 03 23:19:07 +0000 2017  positive_bot3   他人 後ろ 行く  けっして 前進 する いる  だ ない
Thu Aug 03 13:19:04 +0000 2017  positive_bot3   過ぎる た  悔やむ しょうが ない ない 目 どうして 前 つく いる 思う 前向き 進む いく  だ
Thu Aug 03 09:19:03 +0000 2017  positive_bot3   やる 前 負ける  考える バカ いる かよ
Thu Aug 03 07:19:03 +0000 2017  positive_bot3   人生 3 万 日 ない

 
ちゃんと、形態素解析され、基本形に変換され、そしてストップワード(記号などの除外)や
品詞フィルタ(ここでは名詞、形容詞、副詞、動詞、助動詞のみ)が効いている。
ここの処理の詳しい中身は、日本語の前処理を読んでください。

 
一般的には、助動詞は除外することが多い。
しかし、今回はネガポジの感情判定することが目的。
否定を検知するために、意図的に助動詞を分析対象として選択している。
ただ、これが良かったのか悪かったのかはわからない

 

2.1.3 対象データの抽出と連結、そしてラベル付け

まず、tweetデータ以外は不要なので、それだけを取り出す。
そしてポジティブなアカウントのつぶやきだけ、ネガティブなアカウントのつぶやきだけでまとめる。
ついでに、正解ラベルも付けておく。

以下のスクリプトで処理している内容:

  1. 対象ファイルの3列目が空じゃないものだけを対象とする
  2. 3列目だけを抽出
  3. 抽出された文章の先頭に、ラベルを付ける。

ここでは、

  • positiveな文章の先頭に __label__1,
  • negativeな文章の先頭に __label__2,

を付ける。
これは、FastTextの仕様というかルール。
デフォルトでは、ラベルには__label__を付けておく必要がある。

これを、 awksed で処理する。
shell scriptなら、パイプでつなげれば1行で書ける。超便利。

各ファイルの先頭行には、「date user tweet」というヘッダがついている。
そこで、awkで1行読み飛ばすオプションを付けて、ヘッダをスキップさせる必要があることに注意。

for item in ${P_ARRAY[@]}; do
echo $item
awk -F"\t" 'NR>1 {if ( $3!~/^$/ ) print $3}' w_${item}.tsv | sed -e "s/^/__label__1, /g" > label_negaposi.tsv
done

上記のawkを使ったscriptで以下のような中身の 「label_negaposi.tsv」 が得られるはず。

__label__1, 自分 考える た  生きる ない なる ない そう だ ない 自分 生きる た  考える しまう
__label__1, お前 いつか 出会う 災い おまえ おろそか する た 時間 報い だ
__label__1, やる 前 負ける  考える バカ いる かよ
__label__1, 剣 折れる た だ 私 折れる た 剣 端 握る あくまで 戦う  だ
__label__1, あきらめる た 試合終了 だ
__label__1, 人生の目的 悟る  だ ある ます ん 生きる  です 人間 動物 です
__label__1, 他人 後ろ 行く  けっして 前進 する いる  だ ない
__label__1, 過ぎる た  悔やむ しょうが ない ない 目 どうして 前 つく いる 思う 前向き 進む いく  だ

ネガティブ発言も同様。
ただし、ネガティブ名言の場合は、ラベルを **__label__2** としていることに留意。
また、教師データとして1つのファイルにまとめたいので、ポジティブ発言で出力したファイル
label_negaposi.tsv に、追記していることに留意。

for item in ${N_ARRAY[@]}; do
echo $item
awk -F"\t" 'NR>1 {if ( $3!~/^$/ ) print $3}' w_${item}.tsv | sed -e "s/^/__label__2, /g" >> label_negaposi.tsv
done
2.1.4 重複データの削除

元ネタがbotなので、同じセリフを繰り返しつぶやいている。そのため、この重複を排除しないと、
** 特定の繰り返し回数が多い** 発言が、よりポジティブ(ネガティブ)なもの、として学習されてしまう。
そこで、重複したセリフを排除する。

sort -f label_negaposi.tsv -b | uniq > traindata.tsv

ただ、これも物は考えようで、繰り返しが多いものは、
よりポジティブだったりネガィテブだったりと考えることもできる。
ここをどう考えて教師データを作るか、データのクレンジングはいつも悩ましい。

2.2 評価対象データの前処理

教師データと同様、評価対象データも同様に、前処理を行う。
具体的な内容は、基本的に一緒だが、ラベル付は不要。
教師データより、することは少ない。

  1. 規格化、分かち書き、品詞フィルタ
  2. 不要データの削除
echo convert tweet data to wakati
for item in ${T_ARRAY[@]} ${A_ARRAY[@]} ${NIKKEI[@]}; do
echo "converting data: "$item
python createLearningData.py ${item}.txt -n 2
done

-nの引数で、対象カラム番号を指定する。複数指定可。
アカウント数だけファイルがあるはずなので、とにかく処理する。

上記のようなコマンドを打鍵した場合、以下のような2つの結果ファイルが作られる。

  • w_boomin614.tsv
  • w_boomin614.pkl

拡張子が「pkl」のものを、後続の処理で使用する。

2.3 これまでの処理結果の確認

ここまで、教示データと評価対象データに対して、前処理を行ってきた。
その結果、以下のような内容のファイルが得られているか、確認しておきましょう。

  • 教師データ [traindata.tsv]
__label__1, する てる まに もっと 未来へ 目 むける ない ふりかえる いる ない 前 見る 進む ない
__label__1, だ ポジティブ だ 意味 づける する そこ ポジティブ だ 影響 受け取る  できる
__label__1, ちゃんと 生きること 人生  一 度 訪れる ない
__label__1, 起こる 人 優しい する なさる それ 後々 あなた 財産 なる
__label__1, 死ぬ 出端 ない  生きる 問題 だ  だ
__label__1, 試す た 道 外れる た  近道 遠回り する た 全て 今 自分 繋がる いる 思う
__label__1, 重ねる  とんでも ない  行く ただ ひとつ 道
__label__1, 寝る 忘れる さ
__label__1, 人生 これ だ いい 考える いける ない そう 思う た 瞬間 進歩 止まる 置く いく れる だ う
__label__1, 友人 僕 当り前 やる いる  俺 到底 できる ない 誉める られる 自信 つく た 好き だ 何気ない やる いる  人 才能 だ  だ 思う
  • 評価対象データ [w_nikkei.tsv]
Fri Aug 04 16:31:02 +0000 2017  nikkei  キヤノン電子 4 社 小型衛星 打ち上げる 参入
Fri Aug 04 15:13:02 +0000 2017  nikkei  ポスト安倍 石破 氏 首位 岸田氏 4位
Fri Aug 04 14:12:45 +0000 2017  nikkei  規模 領域 幅広い さ 違う 私たち 多く 共通点 ある マツダ 社長 トヨタ 資本 業務提携 発表 する た 記者会見 一問一答 です
Fri Aug 04 14:07:02 +0000 2017  nikkei  NY 株 上昇 始まる 米 雇用統計 受ける 金融株 買う
Fri Aug 04 13:37:02 +0000 2017  nikkei  内閣支持率 42% 3 ポイント 上昇 本社 世論調査
Fri Aug 04 13:15:49 +0000 2017  nikkei  SingPost chief IS Confide NT of putting company back ON track after months without top management
Fri Aug 04 13:04:02 +0000 2017  nikkei  台風5号 列島 接近 6日 夜 九州 上陸
Fri Aug 04 12:46:02 +0000 2017  nikkei  米 雇用 20 9万人 増 7月 市場 予測 上回る
  • 評価対象データ [w_boomin614.tsv]
Sun Jul 23 18:14:21 +0000 2017  boomin614   つぶやき ポジティブ だ  ネガィテブ だ  機械学習 する せる それ 可視 化 する た 結果 です いろいろ 突込み ある 思う 歓迎 する ます なんで 結果 なる た 僕 わかる ます ん それ 機械学習 だ
Sun Jul 23 17:59:27 +0000 2017  boomin614   結局 可視化 こだわる 時間 なる しまう た 明日 どうせ 昼前 出社 予定 だ いい
Sun Jul 23 16:06:59 +0000 2017  boomin614   やっぱり 今日 一 日 使い込む みる た 機械学習 文章 ちょろっと 触る fasttext それ だ いい 途中 ベクトル 演算 ガチ やる たい Neural Network ガチ 機械学習 がっつり tuning しよう 思う た 全然 物足りない
Sun Jul 23 15:56:43 +0000 2017  boomin614   それ 都市伝説 です
Sun Jul 23 15:55:28 +0000 2017  boomin614   気持ち わかる やる みる た 内容 面白い 考える ネタ 的 こっち なる
Sun Jul 23 15:36:21 +0000 2017  boomin614   ちょっと 使い込む みる た Facebook fasttext 使う づらい かゆい  手 届く ない
Sun Jul 23 11:22:25 +0000 2017  boomin614   昨日 お祭り お神輿 担ぐ だ 筋肉痛 だ
Sun Jul 23 09:20:08 +0000 2017  boomin614   原因 分かる た 禁則 文字 入り込む いる た 可視化 こだわる たい それ 結果 見る みる う

 

まとめ

今回の作業で、教師データ評価対象データの準備ができた。
次回は、教師データを使って機械学習を行い、学習モデルを作る。
さらに、その学習モデルを使って、評価対象データのネガポジ判定を行うことにする。

Advertisements

コメントを残す