かわみのメモ帳

趣味に関するメモを書いていきます。

天海春香会話bot開発チャレンジ2

おはようございます。かわみです。
先日は、番外編的に夏目漱石先生に無理やり名台詞を書いていただいたり、三四郎の中で「インフルエンザ」ということばが既に使われていたのを紹介したりしました。
その記事の影響や呪いかは分かりかねますが、3月にもなってインフルエンザに罹り、久々にタミフルにお世話になりました。
さて、天海春香さんと会話しようと目論んでスタートしたこの企画ですが、私がこの世界の神として、私の主観をもとに徐々に改良していました。
果たして試行錯誤の結果、どこまで会話できるようになったのでしょうか。

前回の天海春香会話bot

前回。 kawami.hatenablog.jp

  • 手法を考えて作った
  • 動かしてみた
  • 思ったほど天海春香っぽさがなかった
  • 変な発話がされた

成長した?天海春香と会話してみよう

入力文1つに対して応答文を10文出力するようにしてあります。前回は出力結果の一部でしたが、今回は包み隠さずすべての出力結果を掲載いたします。
ちなみに入力文は前回のもの+αです。是非前回のものと比較してみてください。

f:id:kawamix:20180423003718p:plain

f:id:kawamix:20180423003728p:plain

f:id:kawamix:20180423003730p:plain

f:id:kawamix:20180423003731p:plain

f:id:kawamix:20180423003733p:plain

f:id:kawamix:20180423003734p:plain

f:id:kawamix:20180423003736p:plain

ここから+α

f:id:kawamix:20180423003737p:plain

f:id:kawamix:20180423003738p:plain

f:id:kawamix:20180423003740p:plain

f:id:kawamix:20180423003743p:plainなんでお鍋限定やねんと言いたいところだが、元データの収集時期が秋冬なので仕方ない

あれ?前回より悪化している??気のせい?
今回は特徴づけされたもののみを出力対象としましたが、おそらく入力文に対して得られた特徴づけ前の出力ノードに対して適切に特徴づけできないものも存在する気がします。 ただし個人的には、「千早ちゃん」という単語が多く含まれるようになり、天海春香らしさは増したと捉えています。
このあたり、トレードオフなのでしょうか。真面目に考え始めると大変な沼かもしれません。

さて、何をどう変えたのか、ここから中身の話をしていきます。

主な変更点

  • 形態素解析器を変えました ←たぶんこれが一番大きいのでは?
  • 特徴づけされた文だけを出力(前回までは特徴づけの有無にかかわらず出力していました)
  • 普通の文を作る過程で、言語モデル内に1度しか登場しないような特殊な単語は使用しないようにしました
  • 文頭のノードも特徴づけの対象にしました(前回までは文頭の次のノードから対象としていました)

そして変なものを出さないような設計(いうなれば適合率よりも再現率を重視する感覚)を念頭に改変しました。
"null"の発話はこの設計思想に起因しています。この際は特徴づけされなくても出力すればいいんでしょうけど。

仕組みについて少し解説

ノード?どういうことなの??という方がいるかもしれませんので、特徴づけの手法について少しだけ解説いたします。

言語モデルはざっくり言ってしまうと形態素単位のN-gram言語モデルです。
ただし、よく使われるような形態素の表層情報のみではなく、品詞情報すべてを保持しています。
そのため、表層だけでなく品詞も考慮したうえで正しい文が生成されると期待しています。差が出るかは知りませんが。したがってノードとはそういうことです。ええ。 あ、N個の形態素のまとまりをそう勝手に呼んでます。実質N-1個の形態素情報から次の形態素候補が取得されますが、それをグラフっぽくノードとして呼ぶことにします。勝手にすみません。

そしてノードから次のノード候補の集合を取得し、その中から最適なノードを選択することで文を組み立てていくわけなんですが、 この時、普通のほうと特徴づけをさせたいほうの2種類の言語モデルを併用しています。

そして特徴づけと私が呼んでいますが、具体的にはノードの「置換」「追加」「削除」処理です。
と、ここまで説明すればあなたも実装できるはずですよね!あとは自分自身の天海春香会話botを作りましょう!!





















などということを言うと全Pから怒られそうなので、軽く触れます。軽くですよ。

ノードの「置換」「追加」「削除」処理

ノードの「置換」処理はWord2Vecの学習モデルより単語のコサイン類似度を算出し、設定した閾値以上のものについて上位N件を候補とし、置換します。
「追加」処理は、普通の言語モデルより次のノード候補を取得した際、特徴づけするための言語モデルより、そのノードを構成する形態素の1番目からN-1(N-gramのN)までを探索開始時のキーとして 最終のノードがN番目の形態素で終わるようなノード列を最大M個探索して取得し、そのノード列を追加します。文字にすると非常にややこしいです。余裕があればアニメーションにでもしたのですが。
「削除」処理は言ってしまえば「置換」処理の反対の処理です。削っても問題ない、つまり削った場合でも連鎖として成立するようなノードを削除します。

説明は以上です。ヘリウムのような軽さです。

類似文の取得方法

入力文に対して類似している文を取得し、その集合を言語モデル化するわけですが、その際の文の類似度方法についても少し説明することにします。
Word Mover's Distanceと呼ばれる手法を用いました。
単語の分散表現を用いる手法であり、少しの表記揺れであっても類似度にそこまで影響が出ないといった特徴があります。
手法自体に関しては詳しくは以下の記事をご覧ください。 hironsan.hatenablog.com

ちなみにはじめは、元となったEarth Mover's Distanceの手法を調べ、一から実装しようかとも考えていたわけですが、インターネットの世界にはいろいろな方がおられるわけで、 結局既存の実装を用いました。

github.com

このライブラリを紹介している時点で賢明な方はお分かりでしょうが、うちの天海春香はPure Java実装です。
この手法、さらっと書いたけど結構重要な部分かもしれません。

うちの天海春香さんの中身

ということで実装言語が暴露されたので、githubソースコードを上げました。お待たせいたしました。

github.com

他の複数のプロジェクトに依存している点より公開方法を悩んでいましたが、純粋なチャットボットの実装部分のみを上げることとしました。
当初、公開する気はさらさら無かったので、大変読みづらく、コーディング時の気分によってコメントの有無が左右されています。
なおコミットしてあるのは今回の最新版で、そのまま動かそうとしても動きません。あくまでもご参考まで。

ちなみにresourcesディレクトリにはキャラクター名辞書が置いてあります。ご自由にお使いください。

判明する問題

表層ノード列と探索用ノード列とのズレに起因する問題

ここで賢明な方であればある問題に気付いているはずです。
ノードの「置換」「追加」「削除」処理は表層上であり、ノードの探索中には元のノード列が参照されます。
よって、置換・追加・削除されたノードが反映されない連鎖ができることで、最終的に組みあがる表層もおかしくなることがあるのです。
置換・追加・削除したノードは特徴づけするためのノードであり、そうでない言語モデルにはそのノードが含まれていない場合を考えると、探索中に参照するノード列に入れるわけにもいかなさそうです。
今回、この未解決の難事件が発生してしまったため、開発がそこでストップしてしまい、記事の更新が遅れた次第でございます。申し訳ございません。
この事件には暇があれば適切に対処していく所存でございます。皆さんもぜひこの未解決事件およびチャレンジに取り組んでください。お願いします。

人間味のある発話速度問題

また入力1文に対して応答まで平均5分以上掛かります。Twitterで見かけるような既存のBotとは異なり、大変人間味のある仕様となっています。
その理由はWMDによる類似度算出を数十万文よりおこなっており、その部分に時間がかかるためです。脳筋的解決法では、並列化すれば解決できそうです。
そうではない解決法では、たとえばデータベースにおけるインデックスのようなものを用いれば良いのかななどと考えています。

次回予告?

前回の予告(ゆうパック)は今回の変更前の開発中に出力されたものであり、ミスリードになってしまいました。
さて、次回予告ですが未定の極みです。(現時点において)小学校で必修化されるプログラミングの授業の内容くらい未定です。
そもそもこの記事の執筆自体に3か月もかかっている時点で今後の展開はあるのでしょうか、いや(略)。
正直なところToDoリストは大量ですが、どれからどう消化していくかが課題です。

また"1入力1応答"でさえ怪しい段階ですが、既存のチャットボットと差別化するためには、会話の流れを意識した発話を実現させるしかないと考えており、それをどうにか形にできればと目論んでいます。
これこそ先行研究はあるでしょうが、いま流行りのRNN辺りのタスクとしてうまく設計できないかと密かに目論んでいます。目論んでいるだけです。

皆さんのCDHACへの参加を心よりお待ちしております。是非、天海春香会話学会でも開催しましょう。