隠れマルコフモデルで自然言語を学習

隠れマルコフモデルで社内掲示板の1万個弱の書き込みを学習させてみた。

まず初期値について。遷移確率はおおよそ対角行列。それだけだと差別化できないし、確率が0だと遷移が置きなくて面白く無いので対角成分を11、対角線の一つ上を2、それ以外1として確率として正しくなるように正規化した。出力確率はランダム。ただし今回、文末の構造に注目したいので最後の状態だけ句点「。」の出力確率を2倍にした。

図の見方は、一番左が遷移確率の行列の値の大きさを黒四角の大きさで表現したもの。最大値と最小値で正規化しているので黒四角が見えないところは確率0ってわけではなく、小さな値だという意味。中央はその表示を2倍に拡大したもの。小さい確率値がどうしても見づらいのでね。赤く塗ってあるのは2倍にした結果1を超えたことを意味している。一番右はなんとなく黒→赤→緑→白のスケールになっている。まあ最初に作ったのがこれだったんだけどこれじゃ赤緑色盲の人に怒られるなーと思って。

下の文字の羅列は各状態が出力する文字を頻度の高い順に20件表示している。

1ステップ学習したのが下記。

おおよそすべての状態が平均的な文字の出現頻度で出力するようになった。(UNK)(RET)(SP)はそれぞれ「未知の文字」「改行」「半角空白」に対応している。あ、そうそういい忘れたけど出現頻度順で上位90%だけを各々の文字として認識して残りは全部「未知の文字」扱いにしている。遷移行列のつながり具合などによって各状態の出力する文字に微妙な差が出ていることがわかる。


このあたりで英字を中心とするクラスタと、ひらがなを中心とするクラスタが分化しだしているのが観察できる。

遷移確率が徐々にフラットになってきて、ここで一気に上昇する。

そして適当な収束パターンを模索している。


英字中心だったs2、s3、s4の中でs4だけ0が出現頻度2位に躍り出る。

1枚ずつ見て行っても大変なので一気に進めよう。次は20回の学習終了後。

s0がカタカナ、s1が大文字英字、s2が記号、s3が小文字英字、s4が数字、s5がひらがなと句点、という分化の仕方をしているのが観察される。重要なのはそれぞれの文字のコードポイントが連続しているとかそういう情報は全く与えず、ただ掲示板の書き込みのデータだけを流しこんでやって文字種の分類ができているという点だ。連続して出てくるものは似た種類のものなのかなーとまとめていくことでこうやって6つのクラスターを発見できている。

さて、今回僕は句点周りの観察をしたいので、ここでs5を複製してs6を作ることにしよう。アニメーションの方では一瞬赤い領域が広がるのだが、これは複製の時に遷移行列の複製対象以外の値に0.1を足して正規化しているせい。よくよく考えたらそこまでしなくていいので、新しく追加された一番右の列に 1.0 / K を入れるようにするんだけど、とりあえずここでは全部に0.1を足しているために確率の値が平均的にならされてしまっている。ま、次のステップですぐまた大小わかれるからいいよね。

その後さらに20回学習させたものがこちら。

s6が改行と句点をツートップとする状態になっている。しかもs0への遷移が割と強い。s0は掲示板の書き込みの最初の文字が常にs0であるようなバイアスがかかっているため「文頭」に近い文字を収集していると思われる。で、このこは句点がでると、掲示板の冒頭と似たパターンへ遷移しやすいってことを発見したわけだ。なるほどなるほど。さて、それじゃs6をまた複製してみようか。その後40回学習したものがこちら。


s6で句点がトップに踊りでている。それだけではなく、「…?!、.」といったいかにも区切りっぽいものが集まってきている。遷移確率を見ると、s6は自分自身にとどまらずにすぐにs7に遷移することがわかる。句点「。」はいくつも書いたりしないことが多い、という僕の書き方のパターンを学習しているのだな。

これを学習させていたときには気づいていなかったけど、s7にとある特徴的な文字が出現している。それはなんでしょう?

このあとs6を複製し、学習をして、句点の多いクラスタを複製して、を何回か繰り返したものがこちら:


s10が句点クラスタになっていて、そこから遷移する先はs7。改行や未知文字が多いのはまだわかるが、その次の全角空白と中黒はなんだろう?あ、そうかこれはアレだ!僕がHTMLタグの使えない平文の環境で箇条書きをするときには中黒と全角空白を使うんだ。それを学習したんだな!

s10への遷移が多いs9を見てみると「ですね」「かなぁ」「んだよ」みたいな文字が沢山。文末ですね。
s8はなんだろう。s5への遷移が多い。s5は…未知文字が一番多いけど残りは「が」「で」「てにおは」が多いから主部っぽい。s7で文章の前につく箇条書きの点などが入って、そこからの遷移も多い。s7は文章の前の飾りか?でも閉じ括弧が結構含まれているのが不可解だね。分割できるだけの状態数がなかったのかな。

このあと何をすると面白いかな。全部の状態からフラットにつながっていて、当確率に初期化された状態を1個追加して、それがどういう役割を担うようになるか観察とかかな。開き括弧と閉じ括弧を区別するように学習するか、それとも数字やアルファベットのあたりをもっと細分化するように進むか…興味深い。

なお例のごとくこの画像はCC-BY3.0ライセンスとするので作者の氏名を表示すれば自由に使えます。とはいえ前回の(混合ガウス分布モデルのクラスタをk平均法とEMアルゴリズムと変分ベイズでそれぞれ推定)に比べると使い勝手悪いでしょうけど。