テキストデータを使ってお手軽にNgram統計を取る方法
テキストデータの言語的な特徴を知りたい場合、そのデータを使ってNgram統計を取ることがよくある。Ngram統計というのはテキスト中の連続したN文字それぞれが何回出現したかの統計をとること。
といわれてもピンとこない人もいるかも知れない。実例を見るのが早いので当ブログの昨年12月の記事タイトルを使ってNgram統計を取ってみる。
まず記事タイトルを一行一列でテキストファイルに書き出す。
$$ cat blog-title.txt 「PIANO OPERA FINAL FANTASY I/II/III」がとても気になる そっくりヒロインなラノベ「おおコウスケよ、えらべないとはなさけない!」を読みました PSP「探偵オペラ ミルキィホームズ1.5」第5話(最終話)だよ? 簡潔ビットベクトル性能評価実験のソースコード(rx-trie編) 簡潔ビットベクトル性能評価実験のソースコード(ux-trie編) 簡潔ビットベクトル性能評価実験のソースコード(marisa-trie編) 30分でわかるレコメンデーションエンジンの作り方 ねんがんの TAoMP本を てにいれたぞ! 魔装機神IIのPV第二弾が公開されたので興奮して眠れません! DSIRNLP#2で発表しました「作ろう!簡潔ビットベクトル」 話題の新技術、簡潔データ構造の入門用資料をまとめてみた 「ミルキィホームズSS」のBDをげっとした CRFがよくわからなくてお腹が痛くなってしまう人のための30分でわかるCRFのはなし 自然言語処理なサービスをつくりたい人は「入門ソーシャルデータ」も読むといいのでは ALSIP2011に参加して簡潔データ構造の話を聴いて来ました
次にテキストデータからNgramを取り出すスクリプトを書く。
$$ cat text2ngram.pl #!/usr/local/bin/perl use strict; use warnings; binmode STDIN, ":utf8"; binmode STDOUT, ":utf8"; my $n = shift @ARGV; while (<>) { chomp; my @a = split(//); my $length = @a - $n + 1; for (my $i = 0; $i < $length; $i++) { for (my $j = 0; $j < $n; $j++) { print $a[$i + $j]; } print "\n"; } }
これを実行するとテキストデータからすべての連続したN文字が得られる。ここではN=3の場合、つまり3gramを取り出してみる。
$$ ./text2ngram.pl 3 < blog-title.txt > blog-title.3gram $$ tail blog-title.3gram 構造の 造の話 の話を 話を聴 を聴い 聴いて いて来 て来ま 来まし ました
この「構造の」とか「造の話」というのが3gram(=連続した3文字)。この3gramがそれぞれ何回出現したかの統計を取りたい。これは以下のようにsortコマンドとuniqコマンドを組み合わせると簡単に実行できる。
$$ LC_ALL=C sort blog-title.3gram | uniq -c | sort -nr > blog-title.3gram.ct $$ head blog-title.3gram.ct 4 簡潔ビ 4 潔ビッ 4 ベクト 4 ビット 4 トベク 4 ットベ 4 クトル 3 験のソ 3 評価実 3 能評価
これが3gramの統計情報。当ブログの12月記事には簡潔ビットベクトルの記事が多かったんだなあ、ということが読み取れる。
おまけ(という名のerika-trieの宣伝)
拙作のerika-trie(http://code.google.com/p/erika-trie/)を使うとNgram統計に対する前方一致検索などができる。
まずはerika-trieをインスト。
$$ svn checkout http://erika-trie.googlecode.com/svn/trunk/ erika-trie $$ cd erika-trie/src $$ make $$ sudo make install
インストしたら先ほどの3gram統計情報を「3gram\t回数」という形式にする。
$$ perl -pe 's/^\s+(\d+)\s(.+)$/$2\t$1/' blog-title.3gram.ct > blog-title.3gram.key
そしてerika-trieに付属のerika_make_vt.shを使ってトライを構築する。
$$ erika_make_vt.sh blog-title.3gram.key blog-title.3gram.trie
あとはerika_predictive_searchを使う。
$$ erika_predictive_search blog-title.3gram.trie 簡潔 # 簡潔 簡潔デ 2 簡潔ビ 4
このように「簡潔」で始まる3gramは「簡潔デ」と「簡潔ビ」の2つだよ、ということがわかる。と同時にこの結果から「簡潔」という2gramの出現回数が(2+4=)6回だということもわかる。