テックレポート - TechReport

一覧はこちら

  • now_btn.png
  • ameblo_btn.png

ツイートから好みのタイプの女の子を見つけるセンチメント分析とDeep Learning 2014年6月

執筆者

執筆者:
斉藤広和
所属部署:
株式会社WAVEST メイクme
業務経歴:
2012年株式会社サイバーエージェント入社。現在、子会社WAVESTにてJCJK向けメイクと自撮りの研究サービス「メイクme」のシステム責任者を担当。主にサーバサイドを担当しています。

 

概要

膨大なツイートから好みの女の子を見つけたいです。

好きな女の子のタイプのキーワードを入力すると、該当するアカウントを出力するステキなシステムを作ります。

作成したコードやデータはこちら

https://github.com/inkenkun/tech_twitter

目次

 

1. 女の子だけのアカウントを取得したい

Twitterには性別という属性がないため、まずは女の子のアカウントを何とかして大量に取得してこなければなりません。

おっさんとマッチングされても困りますからね。

1-2. 女性単語辞書を作る。

確実にこれは女性だってわかるアカウントを30個ほど目視で取得します。

そして抽出した女性アカウントのツイートを最新200件ずつ取ってきます。
RTツイートとbotは含めません。

Twitterで女性がよく使う言葉を取得するために、抽出したツイートから単語辞書を作成します。

女性アカウントのツイートを取得する際に、mecabで分かち書きし、女性単語辞書テーブルに、単語と使用頻度を突っ込みます。
この時、ノイズを減らすために名詞と動詞と副詞だけを引っ張ってきます。

(get_girls.js)

 

今回は女性単語辞書テーブルに入れた単語6526単語のうち90パーセンタイルを使用することにしました。
作成したデータは以下の通りです。

girls
女性マスタ

id

username

create_at

1

06031111

2014-06-11 00:00:00

2

lopipa_yu

2014-06-11 00:00:00

3 rinamoiin 2014-06-11 00:00:00

girls_timeline
女性アカウントのタイムライン

id

tweet_id

username

body
wakachi

create_at

  ツイートID アカウント名 本文 スペース区切りの分かち書き ツイート日

1

477237122873581600

06031111

ATSUSHI のライブまでもう少し♪ 超楽しみ *´∀`  次の日仕事っていうの忘れて楽しむぞぉ♪ ATSUSHI の ライブ まで もう少し ♪ 超 楽しみ *´∀` 次 の 日 仕事 っていう の 忘れ て 楽し むぞぉ ♪

2014-05-22 04:08:32

2

474849506740011000

0607OOO

call Me! 行きたいなあ~ call Me ! 行き たい なあ ~

2014-06-14 04:02:50

3 477652593670250500 yuinosuke_m ディズニーランド入園制限かかっておる T ^ T ディズニーランド 入園 制限 かかっ て おる T ^ T 2014-06-14 21:23:47

girls_word
女性単語辞書

id

word

hindo

  単語 出力頻度

1

iLoveMusic

1

2

人気

6

3 最新 1
4 聴き 1
5 放題 2

girls_timeline_word
girls_timelineとgirls_wordをひもづけるテーブル

id

t_id

w_id

  girls_timeline.id girls_word.id

1

1

7

2

1

8

3 1 9

 

1-3. 女性ツイートの特徴を抽出する

girls_timeline_wordテーブルを元に、女性ツイートの教師コーパス「女性教師コーパス」というのを作成します。
この女性教師コーパスとは、簡単に言うとツイートとそのツイートに出てくる単語と頻度を紐付けたものです。

 

ただこのままだと、単語データが多すぎるので、pythonで特徴の次元削減(LSI)します。
今回は20トピックに指定しました。

 

次元削減とは、すごいおおざっぱに言うと、女性ツイートから抽出した6千個の単語を、出現頻度を元に20個にまとめたって感じです。
1ツイートに対して、その20個の特徴がどれだけあるかを数値化したのがコーパスです。

例えばこんな感じ

id

tweet_id

is_female

v0
v1
v2
v3
v4
v5
v6
v7
v8
v9
v10
v11
v12
v13
v14
v15
v16
v17
v18
v19

1

468420336761860100

1

-0.995848 0.000914188 0.0897001 0.0127015 -0.00662591 -0.00121336 0.00425892 -0.00216391 0.00110394 0.000506512 0.00221946 -0.000934771 0.000263865 -0.00118693 0.000410661 0.000194178 -0.000548632 -0.000109973 -0.000112813 -0.000932135

2

473730479607148540

1

-0.683974 0.726128 0.0452496 0.0457684 -0.015661 -0.00130161 0.0185422 -0.00396264 0.00343795 -0.00985174 0.00552777 -0.00364097 -0.00112312 -0.00156012 -0.00186006 -0.000224107 -0.00226358 -0.00152444 0.00109055 -0.000144751

 

上のコーパスの作成はPythonのGenshimで行います。
GenshimはLSIやLDAなどを用いた次元圧縮を簡単に行えるので便利です。(girls.py)

1-4. 女性以外のツイートの特徴を抽出する

女性特定するために、女性以外のデータも必要になるので、抽出していきます。やり方は1-3と同じ。(get_other.js)

男性や広告など、女性以外のツイートの特徴を抽出するために、1-2 , 1-3同様、女性以外だってわかるアカウントを目視で30個ほど抽出し、女性以外単語辞書を作り、「女性以外教師コーパス」を作ります。(others.py) 

1-5. 女性かどうかを検証したいツイートを引っ張ってくる

twitterからlang:ja のツイートを30万件ほど引っ張ってきます。(get_all_timeline.js)

取得したツイートと女性単語辞書を組み合わせた「男女不明コーパス」を作ります。
これが検証したいコーパスとなります。(unknowns.py)

1-6. 性別判定する

Weka Toolkitで女性予測をします。
前処理として、「女性教師コーパス」と「女性以外コーパス」を読み込ませます。

preprocess.png?version=1&modificationDate=1416535774000&api=v2

予測するための決定木のアルゴリズムの精度を調べるために、J48、Naive Bayes、RandomForestの3つを試してみます。

それぞれ交差検証での精度は以下の通りです。


    J48: 99.735% 

j48.png?version=1&modificationDate=1416535774000&api=v2


    Naive Bayes: 69.28%

naive_bayse.png?version=1&modificationDate=1416535774000&api=v2
    RandomForest: 99.8896% 

random_forest.png?version=1&modificationDate=1416535774000&api=v2
   
J48も99.735といい数字を出してますが、RandomForestの99.8896% はかなり驚異的な精度です。
この結果、RandomForestで女性判定を行うことにしました。

「男女不明コーパス」をWekaに入れて、女性のツイートかそうじゃないかを予測します。
取得したツイートの「60%以上が女性ツイートと判断されたアカウント」を女性としました。

女の子と判断されたアカウントリストをforecastテーブルに格納し、forecastテーブルとuser_timelineテーブルからSQLでladyテーブルを作成します。(forecast.py)

forecast
女の子予測テンポラリテーブル

id

is_female

is_female_text

tweet_id

  女の子か 女の子の文章か ツイートID
1

1

True

477677782244147200

2

1

True

477677786736242688

3 1 True 477677800942346240

lady
多分女の子だよアカウント

username

tweet_num

feminin_point

アカウント名 ツイート回数 女の子ポイント

yuya9cirno

5

3

rinriiiine

5

3

cocotanz32hnnn 5 3

 

これで機械的に女の子と判断されたアカウントリストを生成することが出来ました。

 

2. マイナス思考な女の子はタイプから外したい

女の子に限らず男でもマイナス思考な人は嫌ですよね。

できればそういう子は除外したいわけです。

そこで感情を判断できるセンチメント分析です。
センチメント分析を用いると、ある文章がポジティブなのか、ネガティブなのか、中立なのかを判断することができます。

 

2-1. ポジネガを判定するセンチメント分析

女の子のツイート内容からどういった感情(ポジティブなのかネガティブなのか)を判断します。

解析器にはzunda https://code.google.com/p/zunda/ を使います。

zundaは

時制 未来、非未来
仮想 条件、帰結、0
態度 叙述、意志、欲求、働きかけ-直接、働きかけ-間接、働きかけ-勧誘、欲求、問いかけ
真偽判断 成立、不成立、不成立から成立、成立から不成立、高確率、低確率、低確率から高確率、高確率から低確率、0
価値判断 ポジティブ、ネガティブ、0

を判断してくれます。

 

例えば、「今日はラーメン食べた。明日はハンバーグ食べたい」というのをzundaにかけると以下のようになります。

zunda
#EVENT0 4 wr:筆者 非未来 0 叙述 成立 0 0
#EVENT1 11 wr:筆者 未来 0 欲求 0 ポジティブ 0
* 0 2D 0/1 1.517062
今日 名詞,副詞可能,*,*,*,*,今日,キョウ,キョー
は 助詞,係助詞,*,*,*,*,は,ハ,ワ
* 1 2D 0/1 3.754632
ラーメン 名詞,一般,*,*,*,*,ラーメン,ラーメン,ラーメン
を 助詞,格助詞,一般,*,*,*,を,ヲ,ヲ
* 2 5D 0/1 -1.168598
食べ 動詞,自立,*,*,一段,連用形,食べる,タベ,タベ
た 助動詞,*,*,*,特殊・タ,基本形,た,タ,タ
。 記号,句点,*,*,*,*,。,。,。
* 3 5D 0/1 -1.168598
あした 名詞,副詞可能,*,*,*,*,あした,アシタ,アシタ
は 助詞,係助詞,*,*,*,*,は,ハ,ワ
* 4 5D 0/1 -1.168598
ハンバーグ 名詞,一般,*,*,*,*,ハンバーグ,ハンバーグ,ハンバーグ
を 助詞,格助詞,一般,*,*,*,を,ヲ,ヲ
* 5 -1D 0/1 0.000000
食べ 動詞,自立,*,*,一段,連用形,食べる,タベ,タベ
たい 助動詞,*,*,*,特殊・タイ,基本形,たい,タイ,タイ
EOS

 

「#EVENT」が対象の情報です。
ただこのままだと、どこの文章にどの#EVENTがかかってるかわかりづらいのと、Nodejsで使いたかったので、npm作りました。

ZundaJS
https://www.npmjs.org/package/zunda

これにさっきの文章をかけるとこうなります。

zundajs
[ { event: [ '#EVENT0', '4', 'wr:筆者', '非未来', '0', '叙述', '成立', '0', '0' ],
   words: '今日はラーメンを食べた。',
   wakachi: '今日 は ラーメン を 食べ た 。' },
 { event: [ '#EVENT1', '11', 'wr:筆者', '未来', '0', '欲求', '0', 'ポジティブ', '0' ],
   words: 'あしたはハンバーグを食べたい',
   wakachi: 'あした は ハンバーグ を 食べ たい' } ]

wordsはeventがかかっている文章、wakachiはそれを分かち書きにしたものです。

zundaがtwitterのつぶやきという崩れた日本語に対して、どれだけ的確に解析できるかが分かれ目な気がします。

ladyテーブルを元に、多分女の子であろうアカウントがツイートした内容を引っ張ってきて、それをzundaにかけて、ツイートの文章とzundaのイベントを紐付けます。
1アカウントに対し100件づつタイムラインを取得します。(get_lady.js)

zundaの解析が遅いのとTwitterのAPIのリクエスト制限があるのでかなり遅いです。(10日くらいスクリプトを回して22万ツイートくらい)

 

lady_timelineテーブル

多分女の子であろう子たちがツイートした内容
構造はgirls_timelineと同じ。

 

lady_timeline_zunda
lady_timelineとzundaのイベントをひもづけるテーブル

id

tweet_id

jise

kaso
taido

shingi

kachi
body
wakachi
  ツイートID 時制 仮想 態度 真偽判断 価値判断 ツイート本文 スペース区切りの分かち書き

1

478887176524951550

未来

0 欲求

0

ポジティブ 一度でいいからパイを投げ合いたいね。 一 度 で いい から パイ を 投げ 合い たい ね 。

2

478881779336478700

未来

0 欲求

0

ポジティブ 乗りたい 乗り たい
3 478881098705821700 未来 0 欲求 0 ポジティブ てかちょー乗りてぇ てか ちょ ー 乗り てぇ 

これで、あるツイートに対してのポジネガを出すことが出来ました。

lady_timeline_zundaからデータを取得し、ステム処理してファイル(zunda.txt)に出力します(zunda2txt.py)

 

3. タイプの女の子を探す

あるキーワードに対して、関連性が高い項目を引っ張ってくるために、word2vecを使います。

キーワードに対して関連性の高い単語や文章以外にも、アカウントも引っ張ってこることができます。
と言うか、アカウントの文字列も他の単語同様に扱われます。

word2vecは文章をDeep learningで学習させることができて類語を取得することができるツールです。
文章に対象のキーワードが入っていなくても関連性が高かったら取得できるわけです。

 

3-1. word2vecに女の子のツイートデータを突っ込む

女性教師コーパスを作ったgensimにはword2vecも扱える機能が備わっています。
word2vecに入れるには分かち書きされたデータが必要です。

2-1の最後で作成したzunda.txtを使って、モデルと言われるいわゆる辞書を作ります。(w2v2.py)

w2v2.py
python w2v2.py 0 --text zunda.txt -s

 

3-2. キーワード検索する

モデルができたらいよいよ好みのタイプの女の子を検索します。
今回は「アニメ好き」で「眼鏡っ子」を探したいと思います。

キーワードを「アニメ」「眼鏡」にして、ネガティブ以外で上位10件取得します。

w2v2.py
python w2v2.py 10 --model zunda.model --posi "アニメ" "眼鏡" --nega "ネガティブ"
 
1 @asmz_k 0.47620177269
2 @BlackWhitewww 0.442193210125
3 @eve127ast 0.431005120277
4 @bomusoca342838 0.418721705675
5 @cocotaaaaan58 0.418698459864
6 @ayunoko 0.41844946146
7 @candycofin 0.415168076754
8 @burattinata 0.414755672216
9 @d6y_ 0.4045573771
10 @azunagisa858 0.403305977583

腐女子っぽいアカウントが多めに出てきました。

 

「料理好きの人妻」は

キーワードを「ごはん」「掃除」「旦那」とかにしてみます。

w2v2.py
python w2v2.py 10 --model zunda.model --posi "ごはん" "掃除" "旦那" --nega "ネガティブ"
 
1 @BND1354 0.522793889046
2 @Cs_Another 0.515757977962
3 @chizufuchan 0.504830598831
4 @bump9848rad 0.4981957376
5 @ch1taru519 0.494182884693
6 @Cypher_AR_801 0.491773694754
7 @Ayami_SP 0.487014561892
8 @forest_green13 0.485887646675
9 @buin_buin_buin_ 0.482782870531
10 @cottonXcandy301 0.479955106974

と人妻らしき人が出てきましたね。

 

4. まとめ、こういう使い方のがいいかも

上記の検索だと、アニメ、メガネに関連するツイート → アニメに登場するあるメガネキャラが好きな女の子 → 「アニメ好きでメガネをかけてる男が好きな女の子」がヒットする可能性が大いにあります。

 

ツイートを元に検索をかけてるのでキーワード選定がちゃんとされてないとほとんど引っかかりません。
例えば、「女子高生」でヒットさせたい場合、「女子高生」というキーワードで検索をかけても、自分で「わたし女子高生なの」なんてつぶやく人はいないためほとんど引っかかりません。
たぶん「あー学校だりぃ」とか「学校終わった、これからバイト」みたいな文章がほとんどだと思うので、「学校」というキーワードで出てくる可能性のが高いです。(中学生も引っかかってきそうなので、「バイト」と入れたほうがいいかもしれないですね)

 

自分で自分の外見的特徴をなかなか言わないように、好みのタイプを探すにはキーワード選定が結構難しいと思います。

ツイートは基本的に本人が興味あること、好きなこと、嫌いなことをつぶやくため、「芸能人」や「アプリ」で検索して今女の子に人気の芸能人や、「最近のアプリのネガティブな意見を引っ張ってくる」みたいな使い方のが、実用性があるかなと思いました。

 

5. 参考文献

Differences in the Mechanics of Information Diffusion
Across Topics: Idioms, Political Hashtags, and Complex
Contagion on Twitter
http://dromero.org.s3-website-us-east-1.amazonaws.com/info_diffusion_topics_slides.pdf


Topic and Sentiment Analysis on OSNs:
a Case Study of Advertising Strategies on Twitter
http://arxiv.org/pdf/1312.6635v1.pdf


Introduction to Weka- A Toolkit for Machine Learning
http://iasri.res.in/ebook/win_school_aa/notes/WEKA.pdf

 

LSIやLDAを手軽に試せるGensimを使った自然言語処理入門
http://yuku-tech.hatenablog.com/entry/20110623/1308810518


潜在的意味インデキシング(LSI)徹底入門
http://d.hatena.ne.jp/a_bicky/20120324/1332591498

Python用のトピックモデルのライブラリgensim の使い方
http://sucrose.hatenablog.com/entry/2013/10/29/001041

モデルの精度を推定する
http://musashi.sourceforge.jp/tutorial/mining/xtclassify/accuracy.html

gensim
http://radimrehurek.com/gensim/index.html


zunda Japanese Extended Modality Analyzer
https://code.google.com/p/zunda/

word2vec
https://code.google.com/p/word2vec/