のんびり読書日記

日々の記録をつらつらと

Algorithm::BayesianSetsモジュールをアップした

前回のエントリでBayesian Setsを試してみたのですが、その時に書いたコードをAlgorithm::BayesianSetsというモジュールにまとめて、CPANにアップしました。生まれて初めてのCPANアップです。

すごいちっちゃいモジュールですが、これで僕もCPAN Authorの仲間入りかと思うとうれしいですね^^ 実用で使うのはちょっと厳しいかもしれませんが、なんとなくBayesian Setsを試してみるにはいいかと思います。

前回と同じように、タブ区切りのフォーマットのデータを入力として与える場合は、以下のようなコードで動きます。

#!/usr/bin/perl

use strict;
use warnings;
use Algorithm::BayesianSets;

use constant {
    MAX_OUTPUT => 20,
};

my $path = shift @ARGV;
my @queries = @ARGV;
if (!$path || !@queries) {
    warn "Usage $0 file query1 query2 ..\n";
    exit 1;
}

my $bs = Algorithm::BayesianSets->new();

# read input documents
# format: document_id \t key1 \t val1 \t key2 \t val2 \t ...\n
open my $fh, $path or die "cannot open file: $path";
while (my $line = <$fh>) {
    chomp $line;
    my @arr = split /\t/, $line;
    my $doc_id = shift @arr;
    my %vector = @arr;
    $bs->add_document($doc_id, \%vector);
}

$bs->calc_parameters();
my $scores = $bs->calc_similarities(\@queries);
my $count = 0;
foreach my $doc_id (sort { $scores->{$b} <=> $scores->{$a} }
    keys %{ $scores }) {
    last if ++$count > MAX_OUTPUT;
    printf "%s\t%.3f\n", $doc_id, $scores->{$doc_id};
}

ちなみにSYNOPSYSの例では入力ベクトル集合の値がすべて1になっていますが、ここは別に正の値であればなんでも大丈夫です。コンストラクタで与えた閾値(デフォルトでは0)以上のキーのみが使用されます。よく考えたら、閾値は絶対値で比較するようにして、正負両方の値を受けられるようにした方がよかったかな…?まあ負の値を使うケースはそんなに多くはなさそうですし、その場合でもユーザ側で正に揃えておいてもらえば十分ですかね。

あとBayesian SetsのC++実装版をいま作り中です。ライブラリ部分と、実際のサービスで使用できるようにサーバ部分も作っているのですが、サーバ実装まわりの知識がまったく足りてないので勉強しながらごにょごにょと開発中です。結構先になっちゃいそうですが、ある程度動く状態になったらまたブログに書きたいと思います。