前回試してみて、とりあえずAlgorithm::NaiveBayesでいけそうと言うことが解りました。もう少しだけ、使いやすい形にプログラムを修正。具体的には、以下の3点です。
・トレーニングした成果をファイルに残す
・2回目以降のトレーニングは、前回分の結果に差分の学習結果を追加する
・引数によって、挙動を変える。
#!/usr/bin/perl -w
use strict;
use Algorithm::NaiveBayes;
use Algorithm::NaiveBayes::Model::Frequency;
use Storable;
use Getopt::Std;
#use Digest::MD5 qw(md5_hex);
use Data::Dumper;
getopt('cfl'); #Command, File, Label
use vars qw / $opt_c $opt_f $opt_l /;
my $bayes;
my $DB = 'bayes.db';
my $command = $opt_c;
my $file = $opt_f;
my $label = $opt_l;
if (!defined($file)) {
die "usage: need -f filename?n";
}
$bayes = &loadInstance;
if ($command eq 'predict') {
&calcPredict($file);
} elsif ($command eq 'train') {
if (!defined($label)) {die "need -l labelname?n"};
&trainInstance($file,$label);
}
sub calcPredict {
my $file = $_[0];
my %list = &getHash($file);
my $result = $bayes->predict(
attributes => {%list}
);
print Dumper($result);
}
sub trainInstance {
my $file = $_[0];
my $label = $_[1];
my %list = &getHash($file);
$bayes->add_instance(
attributes => {%list},
label => $label,
);
$bayes->train;
Storable::store($bayes => $DB );
}
sub loadInstance {
eval {$bayes = Storable::retrieve($DB)} if -e $DB;
$bayes ||= Algorithm::NaiveBayes->new(purge => 0);
return $bayes;
}
sub getHash {
my $file = $_[0];
my %hash;
open INFILE, "< $file" or die "Cannot open file: $file";
while (<INFILE>) {
chomp();
# $_ = md5_hex($_);
if (!$hash{$_}) {$hash{$_} = 0};
$hash{$_} = $hash{$_}+1;
}
return %hash;
} eval {$bayes = Storable::retrieve($DB)} if -e $DB;
$bayes ||= Algorithm::NaiveBayes->new(purge => 0);オブジェクトの生成の部分で、purge=0で生成すると、$bayes->predictの部分で、
Can't locate object method "predict" via package "Algorithm::NaiveBayes::Model::Frequency"
と出てくる。マニュアルを見てみると、どうもpurge=0でも再びインスタンスを追加してtrain()しろと書いているみたいです。ソース見て、単にオブジェクトをロード出来ていないようなので、足りないと言われているAlgorithm::NaiveBayes::Model::Frequencyを呼び出してみました。すると、あっさり通りました。
出来上がったものは、
./bayes_test.pl -c train -f spam.txt -l spam スパムの学習 ./bayes_test.pl -c train -f spam.txt -l spam ハムの学習 ./bayes_test.pl -c predict -f target.txt スパム/ハムの判定
我ながら、使いにくいものを作ってしまったものです。