どくでんぱのつくりかた

id:wiz-stargazer:20061210:1165720324を見て。


今のどくでんぱ。は、ゴーストのディレクトリにあるテキストを
汎用テキスト整形ルーチンに叩き込んで日本語を抽出しているので、
\hの喋りも\uの喋りも区別がありません。


例えば、AYAやSATORIやKAWARIといった辞書形式に応じたエンジンを積んで、
辞書を読む際に、\hと\uを区別してモードを変え、それぞれで文章を出力すれば、
(\hの発話に含まれるキーワードで\u側の文章を生成する)
\hと\u両方で掛け合いをするどくでんぱ。なんてのも作れるかもしれません。


良い機会ですので、日本語文章の生成について少し知っていることを纏めてみます。


発話と反応

日本語の文章を自動生成する方法は色々あります。
ここではおおざっぱに、「発話型」と「反応型」にわけて考えてみます。


「発話型」とは要するに、いきなりワケの分からない事を喋りだすもので、
会話の時系列等はあまり意識せずに文章を生成するタイプ。


「反応型」とは、文章を入力として、その文章に対する返答として
文章を生成するタイプ。会話型と言ってもいいかもしれません。


もちろんこの2つは綺麗に分かれるわけではなく、両方備えたエンジンや
反応寄りだけど発話もするなんていうエンジンもあります。


発話型であれば、ランダムにキーワードや単語を選んで組み合わせれば
それでいいのですが、反応型となると、「会話」としてなりたたせないと
いけません。次の章でそれを簡単に考えてみます。

言われたことに反応するには

反応型の文章生成でポイントとなるのは、「与えられた文章」を真似るのではなく、
「与えられた文章に対する返答」を真似て文章を作らなければならないということ。


例えば、「ありがとう」と言われたら、「ありがとう」を真似るのではなく、
「どういたしまして」を真似なければいけない。
ぬるぽ」と言われたら、「ぬるぽ」を含む文章を生成するのではなく、
「がっ」から文章を生成しなればならない。


そこで、例えばIRCBOTなんかは、ログから「元の発言に似た発言」を探して、
さらに「その発言に対する過去の(人間の)返答」を探して、それを真似る、
といったロジックのものが多いです。


いくつか例を挙げると、例えばロイディ。

  • 相手の発言から単語を抽出して記憶する。
  • 過去の発言から「相手の発言に類似する発言」を探し、その次の発言をベース発言とする。
  • ベース発言中の単語を「相手の発言に出現した単語」に置換して、発言する。


他には、人工無能れたすなんてのもこのタイプにちかいです。

  • 1.直前数行に含まれるキーワードをランダムに抽出。
  • 2.そのキーワードを含む行をログから選択。
  • 3.その行に続く数行からランダムに行を選択し,マルコフ連鎖で文章を生成。
  • 4.生成した文章に含まれるキーワードと直前数行に含まれるキーワードの関連度を計算して全て足しあわせ空気読み度とする。
  • 5.2-4を何度も繰り返し,空気読み度の高い文章を優先的に返答とする。


どっちも、過去のログを記録しておいて、「人間が入力した応答」をお手本に
文章を生成するのがポイントですね。

文章生成の方法


さて、「発話型」にしろ、「反応型」にしろ、1つ以上のキーワードが決まりました。
「発話型」であればランダムに、「反応型」であれば過去のログ等からそれを決めたわけです。


そうしたら、そのキーワードに沿って文章を作ります。
文章の作り方にも色々あります。


一番簡単なのは、「どこいつ」なんて呼ばれている方法で、
予め用意された文章や単語などを組み合わせたりして文章を作る方法です。


この方式の最右翼が実は一般的な「ゴースト」になるのではないでしょうか。
予め決められた辞書を用いて喋る方式ですね。


この方式は、破綻無くかつ統一性の取れた文章を生成するには有効ですが、
予め喋る言葉を大量に用意しておかなければならないというのが大変です。


そのため、ロイディでは、過去ログから文章を拾い出し、その文章中の単語を
置き換える、という戦略を取っているようです。
これは「学習型どこいつ」と言ってもいいかもしれません。


人工無能れたすでは、マルコフ連鎖というものを使っています。
マルコフ連鎖とは元々数学の確率の用語なのですが、文章生成の世界でマルコフ連鎖
言う場合、「ある単語」「その次の単語」と単語が続いた場合、さらに次にはどんな
単語が来る可能性が高いか、というものを元に、文章を生成する方式を言います。
マルコフ連鎖についてはこのページがわかりやすいので見てみてください。


マルコフ連鎖では、思ってもみないような文章を生成する可能性は高いですが、
その反面、日本語として破綻した文章を生成してしまう可能性も高いです。
その弱点を補う方法として、マルコフ連鎖で文章をいくつも生成し、それを
何らかのロジックで評価して、一番高い点数のものを出力する、といった
方法をとっているのが、人工無能れたすや、ししゃものような例になります。

日本語の文章学習の難しさ


さて、予め決められた文章だけ喋るのではなく、何らかの学習をしたい場合、
難しいのは、日本語は単語が区切られていないということです。


そのため、ロイディのように単語学習をするにも、マルコフ連鎖をするにも、
文書を適切な単語や文節で区切る、といった作業を避けて通ることができません。


この「区切る」ことを形態素解析*1と呼んだりします。
簡単にやってしまうなら、漢字や句読点などで分割してしまう方式があります。


例えば、「我輩は猫である。名前はまだ無い。」であれば、
「我輩|は|猫|である|。|名前|はまだ|無|い|。|」と区切る、など。


この方式は、頭から文章を一通り見れば良いので高速ですし、他に辞書などを
必要としないためコンパクトなのですが、見てわかるとおり、あまり単純な仕組みでは
「はまだ」など、意味のない部分で区切られてしまい、学習の精度が上がりません。


ロイディや拙作のどくでんぱ。の非Mecabモードではこの方式を使っていますが、
色々工夫(助詞などを手がかりにして)して単語を抜き出しています。


もう一つの方式は、日本語の辞書を用意しておいて、それを頼りに区切る方法です。
日本語の辞書を使う為、精度は上がりますが、大量の辞書との比較が必要になるため
速度は落ちますし、日本語辞書も一緒に配布するとサイズが大きくなるといった問題があります。


この辞書利用方式で形態素解析をやってくれるエンジンはいくつかあります。
どくでんぱ。ではMecabというエンジンを使っています。
Mecabは高速で精度もそこそこ良いのが特徴です。


先ほどの文章をMecab(とその付属の日本語辞書)で区切ると次のようになります。
「吾輩|は|猫|で|ある|名前|は|まだ|無い」
どうでしょうか。さっきの「漢字-ひらがな」方式より自然に区切られていますね。
しかし、Mecabはその為に50MB以上の辞書を持っています。

まとめ

以上、ざっと日本語文章の生成について、ごく簡単な説明をしてみました。
私も日本語文章生成について調べ始めたばかりなので間違いなど多いかもしれませんが、
ざっとした概観にはなるのではないかと思います。


拙作のどくでんぱ。では、Mecabマルコフ連鎖で文章を作っています。
他のIRC用のBOTエンジンなどでは、会話を成り立たすように色々と工夫をしていますが、
どくでんぱ。は特に何も工夫していません。素のマルコフ連鎖だとこんな感じです。
どくでんぱ。をベースに色々と工夫すれば、会話用BOTとしてはマシになるかもしれませんが…

*1:実際には形態素解析とは、分割するだけでなく品詞の確定まで含みます。