人工無脳を作ってみようとするよ5

なんかいいかげん日記につづる形式が適当とも思えないような気もしなくはないので、Wikiとか設置してそっちで書くかも。

なんかフラフラと自然言語処理の知識を遠くから眺めて思ったんだが、この分野ってすげえエキサイティングなんじゃなかろうか。適当に自然言語処理の本を少しだけ読んだりしたが、俺が理解できそうなレベルの事柄が普通に実用に意味のありそうなことだったりする。
NamazuMigemogonzuiだと、geekな人達には有名な高林哲さんが自然言語処理について述べているページ、自然言語処理 悪魔の辞典はすばらしく洒落が効いている。こうにもこのページがおもしろいのは、自然言語処理というのがまだまだ成熟していないからじゃなかろうか。

自然言語処理のことなんざ何もわかってないのに、自然言語処理を紹介しようとする無茶な試みをしてみましょう。
自然言語をプログラムに処理させるためには、どうにかして言語というものを理解(してるふり)をさせなければなりません。
プログラムに持たせる「言語」というものに対する認識を「言語モデル」と呼びます。どのような言語モデルを使わせるかで、そのプログラムの言語処理の精度を決まります。もちろん実用のためには実装もおおいに頭をねじる必要がありますが。
人工無脳(対話プログラム)を例に書きます。例えば「こんにちは」という入力があると「おはよう」という文章を返すプログラムがあるとします。Perlなどで以下のようにあっさり書けますね。

while(<>){print"おはよう" if(/こんにちは/);

こんなプログラムで言語モデルなんてもんを意識する必要性は無いです。が、それでも敢えて言うのならば「Aという文章は知っていて、それにはBという文章を返すのが適切」という知っている言語モデルを持っているとも考えられないでしょうか。この言語モデルでも、登録してある「A->B」のデータによっては人工無脳としてそれなりにおもしろいものもできるかもしれません。登録するデータだって人手でやるか、その登録もプログラムにやらせてみるとか、色々楽しめそうです。

でもどうだろう、もうちょっとハッタリが効いた言語モデルも持たせてみたい。そこで、自然言語処理の本を開くと(たぶん)最初に出てくる言語モデルN-gramモデルを使ってみよう。

N-gramモデルは、機械に言語を理解させることを諦め、統計的情報だけで言語モデルの近似を取ろうとするモデルの中でも、かなり基本的なモデル。
このモデルはN個の文字(または単語)の並びから、N-1個の文字(または単語)の並びがあった場合、次に来る文字(または単語)はわかると近似した言語モデルである。巷でマルコフ連鎖マルコフモデルだ言われてるのは、たぶんこの言語モデルを使っているのだと思う。実用上は2-gram、3-gram程度が使われることが多いらしい。

以下にちょっとPerlで2-gramモデルに基づいて適当な文章を出力するプログラムを書いてみる。

#!/usr/bin/perl

$dic = {
  "&bos;" => ["やあ、", "今日は", "やあ、"],
  "やあ、" => ["今日は"],
  "今日は" => ["良い", "悪い", "もう寝る"],
  "良い" => ["天気"],
  "悪い" => ["天気"],
  "天気" => ["だ"],
  "もう寝る" => ["&eos;"],
  "だ" => ["&eos;"]
};

$word = "&bos;";
while(1){ # 1を評価した結果が真の間ループし続けるよ = ずっとループするよ
  @nextwords = @{$dic->{$word}}; # ハッシュから次に来る単語の配列を受けとる
  $word = @nextwords[rand(@nextwords)]; # 候補単語配列からランダムに決定
  last if($word eq "&eos;"); # 得た単語が &eos; だったらループから抜けるよ
  print $word; # 得た単語を出力
}
print "\n";

$dicが文章生成のための辞書のハッシュ(のリファレンス)である。$dicの意味は、「文頭の次には"やあ、"が来る確率2/3、"今日は"が来る確率1/3。"やあ、"の後は"今日は"が来る確率1、……」といったものになる。このスクリプトを実行すると「やあ、今日は良い天気だ」や「今日はもう寝る」などといった文章が出力される。結構簡単なモデルだと思うが、意外と使える(らしい)。今回は辞書データ部分を適当に人手で書きましたが、この部分を機械に丸投げしたりすると、なんか楽しそうですよね。
しかしながら。前1つの単語だけを元に次の単語の確率を求める2-gram、前2つの単語から求める3-gramなどは、それ以上前の単語から来る関連性はまったく気付きません。例えば括弧「」の関連性など。この場合には、トリガーモデルなども組み込んでいくと、うまくいくかもしれません。
トリガーモデルというのは、ある単語と別のある単語の強い結び付きをトリガー対として組み入れたモデル。単体で使うことはなく、他の言語モデルと組み合わせて使うモデル。例えば1個前の単語しか憶えてない2-gramモデルと合わせることで、2-gramモデルだけでは表現できない離れた単語間での関係を示すことができる。たぶんトリガーモデルってそんなの。

統計的じゃない文法規則がどうこうとかいった言語モデルはまったくもってわからないのでパス。


提灯記事じゃなあないですが、長岡技術科学大学自然言語研究室のWEBページに対するポリシーがかっこいい。
http://nlp.nagaokaut.ac.jp/wiki/wiki.cgi?page=Web%A5%DA%A1%BC%A5%B8%A4%CE%BA%EE%C0%AE%BB%D8%BF%CB
少なくとも最近人工無脳にはまって、微妙に自然言語処理に興味がわいてきた某電気通信大学の学生こと俺には役にたってるので超ありがたい。

人工無脳楽しいから勢いあまって自然言語処理の本を眺めたりして思った。WEBの人工無脳界隈ではやたらマルコフ連鎖言われてるけど、それって配列のことをポインタって言ってるようなもんじゃねえのかな、と。TCP/IPとhttpの関係というか、そんなような。まあ、よくわからんので自信はまったく無いのだが。
WEB上にある「マルコフ連鎖ほげほげ」っていうのは、なんかやたらと便利に色々省略して表現している気がする。省略しないで書くと、文章モデルとして、適当な文章からN-1重離散マルコフモデルで近似した単語Nグラムモデルを使い、その離散マルコフモデルを構成する離散マルコフ過程ことマルコフ連鎖から、適時単語の出現確率を読みとって、適当な単語つながりを持つ文章をつくるということなのでは。
修学中途の、半端な知識でもどんどん垂れ流しますよますよ。
はてなキーワード > マルコフ連鎖のページとかだって、今は「ん? ちょっと違わね?」と思ったりもするけど、最初にマルコフ連鎖を理解するのには役にたったりはするし。でも、「〜する方法」ではないような、気がする。はてなダイアリー市民権を得て編集できるようになった頃にまた考えよう。


んで人工無脳めざしさんの開発をやっているのかというと、上の文章書くのにかまけたりでそんなにやってない。なんか適当だなあと思う箇所がたくさんありますが、
http://konbu.s13.xrea.com/talk/2-gram/Mezassi.pm
http://konbu.s13.xrea.com/talk/3-gram/Mezassi.pm
http://konbu.s13.xrea.com/talk/4-gram/Mezassi.pm
(2|3|4)-gram版による文章生成をするモジュール。共通するコードが多いなら継承とかでゴニョゴニョとか、まあ普通に粗しか無いようなモジュールですが。

test