らこらこブログ

唐揚げとアニメとプログラミングが大好きです

メカらこ開発日誌 v3.0.1

先日からメカらこを再実装し始めた。C#でUserStream監視と形態素解析、文章生成まで全部やってたv1はなかなか便利ではあったけどC#ってのが実行環境を選ぶので、サーバー側とbot側を分離しようと思ってv2はサーバーをGo言語で書いてた。でもある程度書いたところでGolangに飽きたのでメカらこ停止してた。

昨日Dartで書けばいいじゃんと思ってサーバー側をDartで書いてherokuで動かしたらあっさりbbop出来るところまで実装できた。なので今日は語彙獲得と文章生成を実装した。

語彙獲得

TwitterのUserStreamを監視する役目はAndroidアプリを書いた。twitter4jの扱いに慣れているのもあるし、使ってない端末を家で充電しておけば簡易常駐サーバーとして使えるからだ。念のためActivityではなくサービスとして実装したのでエラーで落ちても自動で再起動するようになってる。

現在の語彙獲得プロセスは以下の流れ

  1. タイムライン上でURLやハッシュタグ非公式RTなどを含まないまともそうなツイートを拾う
  2. AndroidアプリからDartサーバーにREST APIで投げる
  3. Dartサーバーで受け取った文をYahoo!形態素解析に投げる
  4. 分かち書きした結果をTri-gramに整形してDBに追加

いろいろ考えたけど結局文脈を無視すれば一番自然に文章が作れるのはN-gramモデルだと思った。今回は品詞情報は捨てた。

文章生成

獲得した語彙から文章を作るのはTri-gramに線形補間法のスムージングを当ててみた。線形補間法の定数λ1, λ2, λ3は最初0.66, 0.33, 0.01にしてたのだけど、λ2が大きすぎて前方一語一致の重みが強すぎた。けっこう不自然な連結をしたり、時々無限ループみたいなことを引き起こしたりしてたので、これを参考にとりあえず0.85, 0.10, 0.05に設定しなおす。

最尤推定とスムージングはこれでできるのだけど、スムージング後の最尤候補を採用するだけだと、ランダム性がなくて同じ文章を生成しまくってしまうので、スムージング後の{単語, 確率}のペアのリストを確率の降順にソートして、上から全体の3割の要素を切り出した。切り出した3割は等価にシャッフルして一件を取り出して採用するようにしたら多少の乱れは生じるが、時々予想外に面白い文章も吐き出すようになった。適当に3割としたので、いい感じの割合は今後探る。

ワンカウント法は断念した

はじめはTri-gramのスムージングにワンカウント法を使うつもりだったのだけど、コードの記述自体は大したことはないけどもDBやリストへの検索回数が尋常じゃない感じになってきてこれはクッソ遅くなると予感して早々に断念した。使用例の記事が全然ないのも残念だった。