phaの日記

パーティーは終わった

「圧縮新聞」を作った



僕は昔からロボットがロボットなりに変な文章を生成して喋ったりする人工無脳とかそういう仕組みが好きで、最近はそのへんの仕組みを勉強していました。それで大体仕組みの基本はわかったので簡単なスクリプトを書いてみたよ。

このスクリプトはウェブ上にある新聞社とかのニュースの文章を元にして、バラバラにして圧縮してまとめた文章を作るので、ざっと眺めるだけでその日起こった事件の全体が何となくわかるかもしれません。リロードするたび文章は変わります。

生成例

しょうゆ・みそ業界大手のNOVA(大阪市)が入った郵便小包は、北朝鮮の鉄道網を連結する計画だったらしいことが21日、わかった。タンクに灯油を補給した。検案の結果、財政難などをほとんど与えずに6者協議の外相会議の早期再開に期待を表明した国と製薬会社に賠償を求めた。その後、亡した。

しくみ

こういった人工無脳みたいな文章生成をするには形態素解析マルコフ連鎖という仕組みを使います。結構簡単にできます。

形態素解析

形態素解析というのは、簡単に言うと文章を単語に分けてバラバラにすることです。英語だと単語と単語はスペースで区切られているので楽なのですが、日本語は全部くっついているので、どこからどこまでが一つの単語なのかを区切ってやらないといけません。
上のサイトではYahooの形態素解析APIを使っています。

例えばこのAPI

上のサイトではYahooの形態素解析APIを使っています。

という文章を投げると、

上 | の | サイト | で | は | Yahoo | の | 形態素 | 解析 | API | を | 使っ | て | い | ます | 。

というようにばらばらになった文章が返ってきます。

マルコフ連鎖

このバラバラになった文章を繋げるのにマルコフ連鎖という仕組みを使います。簡単に言うと、いくつかの単語の繋がりを記録しておいて、それを繋げていって文章を作るという仕組みです。
文章を形態素解析でバラバラにしたら、その中の単語の繋がりのパターンを記録します。「Yahoo」=「 の」という繋がりとか、「API」=「は」とか。
そして文章を作るときには、例えば最初に「Yahoo」=「 の」という繋がりを持ってくるとして、そしたら次は「の」から始まる繋がりをそこから繋げます。「Yahoo」=「 の」の次を「の」 =「 記憶」という繋がりにしたら、その次は「記憶 」=「 は」という繋がりを繋げられる。
そういう風に「Yahoo」= 「の」「の」=「記憶」「記憶」=「は」「は」=「終わっ」「終わっ」=「て」「て」=「ない」「ない」=「。」と繋げていくと、

「Yahooの記憶は終わってない。」

という、意味はわからないけれど文法的には違和感のない文章ができあがるわけです。
ちなみに上の例では2単語ずつの連なりを記録していますが、圧縮新聞では最初に文章を解析する際に4単語の連なりを1セットとして記録しています。仕組みとして2単語よりも3単語、3単語よりも4単語のほうが文章の意味が保持されやすくなります。最初に3単語セットのバージョンも作ったんだけどこれだとあまりにも文章の繋がりがばらばらになりすぎるので、このスクリプトの場合はある程度意味を保持していたほうが面白いだろうと思った。あと新聞記事は定型文が多いので、4連鎖をセットにしても結構文章が繋がるというのもあった。

資料

詳しくはこの本で学びました。

恋するプログラム―Rubyでつくる人工無脳

恋するプログラム―Rubyでつくる人工無脳

これはRubyの本で、僕はRubyではなくPHPで書いたんだけど、ロジックだけ参考にした。
あとPHPで書かれてるこのページにあるコードも参考にした。

本を貸してくれた赤田くんありがとう。

追記

Twitter版も作ってみました。

Twitter / asshuku