今日のIIR輪講[2008-09-07-2]の内容のフォローも兼ねて、
ちょっとしたハックを紹介。
bigram language model に基づく、
ランダム文生成を行います。
って、まあ、単純にある単語の次に現れる単語の分布を用いて、
文章を生成していくだけですが。
以下、サンプルプログラムと実行例です。
サンプルコード
rss-lm.pl
#!/usr/bin/perl
use strict;
use warnings;
use XML::RSS;
use LWP::Simple;
use XML::Simple;
use URI::Escape;
use utf8;
binmode STDOUT, ":utf8";
my $appid = "YahooDemo";
my $rss_url = shift;
my $rss_cont = get($rss_url) || "";
my $rss = XML::RSS->new;
$rss->parse($rss_cont);
my %next_words;
my $pre = "";
foreach my $i (@{$rss->items}) {
my $ma_ref = webma($i->{title}."\n".$i->{description});
foreach my $mo (@{$ma_ref->{ma_result}->{word_list}->{word}}) {
my $w = $mo->{surface};
$w = "" if ref($w) eq "HASH";
next if ($pre eq "" and $w eq "");
push @{$next_words{$pre}}, $w;
$pre = $w;
}
}
my @words;
my $cur = "";
for (my $i = 0; $i < 200; $i++) {
my $tmp = $next_words{$cur};
$cur = $tmp->[rand(@$tmp)];
last if $cur eq "" and $i > 100;
push @words, $cur;
}
print join("", @words), "\n";
sub webma {
my ($key) = @_;
return {} unless $key;
my $url = "http://api.jlp.yahoo.co.jp/MAService/V1/parse"
."?appid=$appid&results=ma&response=surface"
."&sentence=".URI::Escape::uri_escape_utf8($key);
my $response = get($url);
my $xmlsimple = XML::Simple->new(ForceArray => [ 'word' ]);
return $xmlsimple->XMLin($response);
}
日本語形態素解析に Yahoo!API を使っています。
$appid は自分で取得したものを使ってくださいね。
(http://e.developer.yahoo.co.jp/webservices/register_application)
実行例
RSS の URL を引数に与えて実行します。
実行結果はカオスです!
http://chalow.net/
./rss-lm.pl http://chalow.net/cl.rdf
【初めての持ちが、ハーゲンダッツの会)ブログで焼いて、その他 のひみつ][2008北海道へ行かなくて。場所は、彼のエコアート。 ローマ人のスーパーでは一個29,400円は、-04-03-08-基本的な味で 売っていた!描画がFX35-KChromeLUMIXでも、デニムの大和路[2008特に http://wassr...blog.com/2008受賞作品展」というかとか西麻布で オフィシャルにスイカを置いておいしいです。
「北海道へ行かなくて。場所は、彼のエコアート。」ってのは、
ポエムな感じで素敵です。
あと、確かにオフィシャルなスイカ(たぶん国産西瓜のことかと)
はおいしいです。
http://d.hatena.ne.jp/naoya/
./rss-lm.pl http://d.hatena.ne.jp/naoya/rss
SKK分だけ、はてなハイクの発表を受けはてなハイクのインターンも byteArray::Gapでした。金曜日はアルゴリズムの頃、 はてなハイクのたつをさんから、あの変換スタイルにやろうと言えば ThriftcodesKansai.net/~naoya1977/about-thrift/naoya/naoya1977/ インフラを終えて発表資料を試みました。という課題が終わり、 計算機科学にアップロードしましたことから何か適当に関する手法第2回募集
ついに「はてなハイクのたつをさん」になってしまいました!
あまり使ってないんだけどな、最近は。
あと、「何か適当に関する手法」を募集しているようです。
しかも第2回。一発ネタでは終わらないのですね。
簡単な解説
RSS(日本語)を読み込んで、テキストを形態素解析し、
単語2連続(bigram)をカウントしています
(ハッシュ %next_words に格納)。
単語 x の後に y が現れる確率は P(y|x) です。
生成時は、確率 P(y|x) に準じてランダムに y を選びます。
その方法は、
(1) x の次に現れる単語(
重複をゆるすリストに格納する。
例:「今日」→「は」「も」「の」「の」「は」「から」「は」「の」
(x = 「今日」)
(2) そのリストから一つランダムで選ぶ。
という単純なものです。
説明するまでもないと思いますが、
こうすることで「は」「も」「の」「から」は、
それぞれ P(は|今日)、P(も|今日)、P(の|今日)、P(から|今日)、
に準じた確率でランダムに選ばれます。
単語が多い対象では実行性能が悪くなりますが、
RSS のテキストくらいの量なら問題ないでしょう。
ランダムで選ばれた単語を出力し、
その単語の次に現れる単語をまたランダムで選ぶ、
ということをループさせることにより文章を生成していきます。
なお、空文字の単語は「文頭または文末」を意味しています。
ループの最初は空文字からスタートさせます。
関連リンク
JavaScript 版と PHP 版。生成のロジックは同じです。
- マルコフ連鎖で文章生成(JavaScript) - エブログ
http://ablog.seesaa.net/article/20987336.html
- Yahoo!のAPIを利用してマルコフ連鎖で文章生成(php)
http://shohoji.net/blog/archives/001723.html
trigram (3gram) によるモデル。
- mizzy.org : perlで人工無脳 #1
http://blog.mizzy.org/articles/2005/06/19/bot01
確率文章生成を含む、いろんな人工無脳について。
- 人工無脳レビュー
http://www.ycf.nanet.co.jp/~skato/muno/material/review.html
いくつかの RSS でやってみたサンプル集。
- いろんなブログのRSSで文章生成してみた (ヲハニュース)
http://d.hatena.ne.jp/yto/20080906/p5



