Twitterのロリコン人工無能Bot @jsfavo について

@jsfavoとは

JSこれくたー,Twitterを監視する淫らなbot君です.

・@sosoruと@jsfavoのHomeTLを見て,指定されたキーワードが入ってるとふぁぼる
・30分おき(朝7時~9時は10分おき)に何かをツイート.深夜帯はお休み
・リプライを送ると何か返してくる

ふぁぼ機能

  • @sosoruと@jsfavoのHomeタイムラインを常に監視しています.指定されたキーワード,もしくは,キーワードの類似語が含まれていたらふぁぼります.
  • UserStreamを使って監視していて,見つけたらすぐにふぁぼる仕様でしたが,何処からか圧力が掛かったので,いくらかの遅延を持たせてふぁぼらせています.

f:id:sosoru_m:20160201024001p:plain
🔺こんな感じ.(TriggeredFilterが反応した単語)

f:id:sosoru_m:20160201024442p:plain
🔺類似語の場合はこんな感じ

ツイート機能

  • 予め登録されたキーワードを元に何か文章を作成します.文章の素は@sosoruの過去のHomeTLを使っています.


  • 4語のマルコフ連鎖で幾つか文章を作成していますが,そのままだと「パクツイ」になりやすいので,名詞などを類似語にランダムで置き換えています.
  • リプライを送ると,そのツイートを基に何か文章を作成して返してきます.


🔺テンプレに反応して返してくれる

  • 深夜帯の1時30分~6時前まではツイートしません.裏でデータベースのメンテナンスをしています.リプライ機能は生きているので,何かしら返してくれるかもしれませんが,メンテナンスの都合で返せない場合があります.


🔺返してくれないときもある,「わかんないよぉ」って言うときもある

リプライについて

  • 空リプを送ると何のツイートに反応したか返してくれます.


  • 何か文章を送ると,反応する単語が含まれているか教えてくれます.同時に何か喋りかけてきます.


  • 文章に「詳細」が含まれていると,さらに詳しい情報を教えてくれます.triggered filterは内部で使っている正規表現です.


  • この他にも,リプライに対して定型文を返すような設定が幾つか入っています.探してみてください.

しくみ

  • bot自体はC#で書かれていて,辞書学習等々のファイル操作でRubyをちょっと使っています.
  • C#のCoreTweetでTwiterAPIを弄りつつ,SQLServerに得たツイートを垂れ流しています.文章の形態素解析にはMeCabを使っていて,辞書には「はてなキーワード」を主に使っています.(C#側のライブラリはLibNMeCab)
  • 類似語の列挙にはword2vecを使っています.@sosoruのHomeTLをMeCabでわかち書きしたものを学習させています.(C#側のライブラリはWord2Vec.Net)

類似語について

  • word2vecを使えば単語の意味ベクトルが得られるので,2つの単語ベクトルの内積を取れば,どれだけ類似しているかが数値化できます.(これをコサイン類似度と呼ぶ?)
  • 類似語とは文脈で使われやすい単語を指しているようで,同義語と反義語の区別はないようです.

f:id:sosoru_m:20160201032919p:plain
🔺類似度の高い単語を列挙した場合,それっぽい単語がサジェストされる

f:id:sosoru_m:20160201033003p:plain
🔺類似語に同義語と反義語の区別はない?

f:id:sosoru_m:20160201033807p:plain
🔺ペアだと高い類似度を持つ?

  • 類似語の計算はとても重いです.200次元のベクトル同士を10~20万回内積計算させる処理です.キャッシュを入れましょう.
  • 最適化込みのビルドをCore i5-4670K @ 3.40GHzのマシンで並列処理させて,約100msec~200msec程度かかるようです.
  • float精度の計算なのでGPUに肩代わりさせた方が利口かもしれません.

文章生成について

  • @sosoruのHomeTLを基に4語のマルコフ連鎖で文章を作っています.2016年1月の時点で,過去1年程度のTL,300~400万ツイートがデータベースに溜まっています.
  • リプライ等々で文章生成のリクエストを受け取ると30文程度の文章を生成します.生成された文章の中から,比較的短文で,基となった単語や文章と類似したものをランダムで選び出します.基の単語と文章の類似度を測るときにも,word2vecで出した単語の意味のベクトルを利用しています.
  • 単語の意味ベクトルはword2vecが吐きだした数値を用いれば良いですが,文章の場合には,使われている名詞・形容詞などを抜き出し,その単語の意味ベクトルを足し合わせて正規化したものを,文章の意味ベクトルとして扱っています.
  • 意味ベクトルとして考慮する単語が多くなるほど,基の単語・文章との類似度が低下するので,単語数を考慮してランダムで選び出します.
  • 生成された文章と基になった文章の類似度が高い場合,幾つかの単語を類似語で置き換えています.botにたまによくある奇想天外な文章の類似度は,感覚的にあまり高くないようなので,わざと落とすことにしています.

f:id:sosoru_m:20160201040422p:plain
🔺考慮する品詞,代名詞や接尾語は見ない

f:id:sosoru_m:20160201035316p:plain
🔺「ゆのっち」を与えたときに生成された文.表示されているのは名詞や形容詞の数が2~10程度の文章.名詞・形容詞などの単語数,基の単語との類似度,生成された文章の順に表示.

辞書の更新について

  • 深夜帯にSQLデータベースのインデックス再構成と形態素解析辞書の更新,word2vecに再学習をさせています.マルコフ連鎖で使う辞書はツイートを受信した段階で,データベースに突っ込んでいます.
  • インデックスの更新が割と重要で,定期的に再構成してやらないと,参照時にタイムアウトすることがありました.