前回試してみて、とりあえず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 スパム/ハムの判定
我ながら、使いにくいものを作ってしまったものです。