ニコ動のごちうさ1話のコメントでword2vecで遊んでみた
ふと、ごちうさ1話のコメントから、いわゆる"ごちうさ難民"の人工知能を作れないかと思い行動。
今回は、趣旨が違って、拾ったコーパスをword2vecに通したらどうなるかのお遊びだけ。
コーパス
ニコニコ動画のコメントはドワンゴより以下のようなデータが提供されています。
が、ごちうさ1話のコメントを取るには古すぎたので、自分でスクレイピングしました。
その際に普通にスクレイピングしても取れなさそうなので、Seleniumを使いました。
スクレイピングの方法としては
- ログインが必要になるので、自分のアカウントでログイン
- ごちうさ1話の動画へ移動
- コメントが読み込まれるまで待機
- コメントが読み込まれたらスクロールしながらコメントのDOM情報をMongoDBに保存
という手順をSeleniumで組みました。このクローラーを1日に1回のペースで回し、約35000件のコメントを保存しました。
なおコメントに加えて、コメントの投稿時間や、コメントの投稿した再生時間も保存してあります。
ソースコードは以下に用意しました。READMEとかまだできていないですが参考にしていただければと。
githubの src/gochi_usa_scrape.py が実行スクリプトとなっています。(環境変数にユーザー名のパスワードの設定必要あり)
スクレイピングに関して
今回行った成果は、以下を参考にしたうえで行いました。
robots.txtの内容も確認いたしました。
当成果に対して何か問題があればご連絡お願いします。
Webスクレイピングの注意事項一覧 - Qiita
Webスクレイピングの法律周りの話をしよう! - Qiita
niconico利用規約 - niconico
分かち書き
こういうデータを使う際には決まって文を単語に分ける分かち書きという作業が必要があります。
その際には、形態素解析器mecabと、すげえmecabの辞書mecab-ipadic-neologdを用いました。
この辞書、アニメの単語とか本当に理解してすごいです。
mecabのインストール
brew install mecab brew install mecab-ipadic
また、python3で処理をしたので以下のようにライブラリをインストール
pip install mecab-python3
mecab-ipadic-neologd
以下の記事を参考にしてインストール
mecabはインストール済みなので
git clone --depth 1 https://github.com/neologd/mecab-ipadic-neologd.git cd mecab-ipadic-neologd ./bin/install-mecab-ipadic-neologd
python上でmecab-ipadic-neologdを使う場合は
mt = MeCab.Tagger('-Ochasen -d /usr/local/lib/mecab/dic/mecab-ipadic-neologd')
と、タガーを定義する際に引数に辞書を指定する必要があります。
また、今回のコーパスは複数行にわたるAAが顕著に見られました(しかも各行が分けられて撮ってきている)
よって、形態素解析及び分かち書きの際は、文中の"記号"が6割以上超えた場合にコーパスから排除するという処理を行いました。
コードしてはこんな感じ。sent_parser関数が文の分かち書きで、parser関数が複数の文をまとめて分かち書きできる。
#!/usr/bin/env python # coding: utf-8 import MeCab def surface_iter(node): #「文頭」を無視 node = node.next while node.next: yield (node.surface, node.feature) node = node.next def sent_parser(sentence): dic = '/usr/local/lib/mecab/dic/mecab-ipadic-neologd' config = '-Ochasen' config += " -d {}".format(dic) mt = MeCab.Tagger(config) mt.parse('') node = mt.parseToNode(sentence) parsed = surface_iter(node) try: parsed = list(parsed) surfaces, features = zip(*parsed) new_surfaces = [sur for sur, fea in parsed] n_kigou = len([x for x in features if '記号' in x]) score = n_kigou / len(features) return new_surfaces if score < 0.6 else [] except ValueError: # zipに失敗したものは排除。 return [] def parser(docs): parsed = map(sent_parser, docs) parsed = [x for x in parsed if x] return parsed
word2vec
gensimのword2vecを使って類似度計算を行いました。
word2vecによって、単語をベクトル表現することができ、コサイン類似度で単語の類似度を調べることができます。
"word2vec"についてわからない人は、ググると出てくるので是非ググってください。有名なモデルです。
類似度計算の際は、上記のコードの関数で分かち書きした単語列の頭に投稿した再生時間を示す記号を投入。
(例えば、再生時間01:00に投稿されたものはTM_01という記号を入れる)
具体的に、コードにするとこんな感じ(x['time'][:2]がコメントの投稿した再生時間(分単位)、x['parsed']は分かち書きしたコメント)
[['TM_' + x['time'][:2]] + x['parsed'] for x in result]
こういう細工をすることで、各再生時間で使われる単語を見ることができてニヤニヤできますw
ちなみに、各コメントを3つにコピーしてかさ増ししました。
word2vecにかけて、類似度計算をしてみた結果。
川の類似度。表示結果は川と類似する単語です。川に対して詳しい。
EUの類似度。類似する単語がめっちゃタイムリー。
濃度の類似度。空気と関係していたり薄くなったり不穏。
TM_16のデータをかさ増ししていないモデルの結果で。この時間は弾幕が濃い。
同じくかさ増しせずにTM_22。線路へほっぴんジャンプ♪
TM_○○の類似度はかさ増ししない方が面白い結果が出ました。