読者です 読者をやめる 読者になる 読者になる

プログラマでありたい

おっさんになっても、プログラマでありつづけたい

特徴語抽出のあれこれ

プログラム 自然言語処理

 最近の特徴語抽出の手法ってどんなんかなと思って、はてなの注目のエントリーを見てみました。
タグ「特徴語抽出」を含む注目エントリー


 面白いものが目白押しです。
特にGigazinizeというのは、秀逸です。面白いなぁ〜。
http://blog.fulltext-search.biz/articles/2007/09/03/gigazinize
Gigazinize のなかみ


 私も何か作ってみたくなりました。書籍データやらWikipediaやらのデータは色々あるので、そのあたりを組み合わせてみようかと思います。その前に特徴語を抽出する為のツールです。(だいぶ昔に作ったものですが。)ロジックは、たつをさんが紹介している下記の方法です。


形態素解析と検索APIとTF-IDFでキーワード抽出
 形態素解析とYahoo APIを使って特徴語を抽出する方法です。さっくりと作れて、それなりに使えます。ただ、つどWeb検索に行っているのでそれなりに遅いです。要は文章の母集団があればよいので、Yahoo APIの部分をWikiPediaから作ったコーパス等に置き換えたらかなり早くなると思います。
下はYahoo APIを使った場合のサンプルです。

use LWP::Simple;
use MeCab;

my $file = shift @ARGV;
my $population = 19200000000;
my $hit;
my $content;
my @feature;
my %result;

$content = readFile($file);
@feature = &parseText($content);
%result = countFeature(@feature);

foreach $key (keys %result) {
  $hit = &get_num($key);
  $tfidf = calcTFIDF($result{$key},$hit,$population);
  print "key=$key,hit=$hit,tfidf=$tfidf\n";
}

sub parseText {
    my $content = shift @_;
    my $m = new MeCab::Tagger ("-Ochasen");
    my @feature = ();
    for (my $n = $m->parseToNode ($content); $n; $n = $n->{next}) {
        if ($n->{feature} =~ /名詞/) {
            push @feature,$n->{surface};
        }
    }
    return @feature;
}

sub countFeature {
    my @feature = sort(@_);
    my $str="";
    my $prev="";
    my $cnt=0;
    my %feature;
    foreach $str (@feature) {
      if ( defined  $feature{$str} ) {
        $feature{$str}++;
      } else {
        $feature{$str}=1;
      }
    }
    return %feature;
}

sub readFile {
    my $file = shift @_;
    open FH, "<$file";
    my $content = join '', <FH>;
    close FH;
    return $content;
}

sub get_num { # 検索ヒット数獲得 by Yahoo! API
    my ($key) = @_; # UTF-8
    $key =~ s/([^0-9A-Za-z_ ])/'%'.unpack('H2',$1)/ge;
    my $url = "http://api.search.yahoo.com/WebSearchService/V1/".
        "webSearch?appid=YahooDemo&query=$key&results=1";
    my $c;
    ($c = get($url)) or die "Can't get $url\n";
    my ($num) = ($c =~ /totalResultsAvailable="(\d+)"/);
    return $num;
}

sub calcTFIDF {
  my $tf = shift @_;
  my $df = shift @_;
  my $n = shift @_;
  
  my $tfidf;

  eval {
      $tfidf = $tf*log($n/$df);
  };
  return $tfidf;
}

次は、コーパス部分を変更したいと思います。
Yahoo APIからWikipedia