ベイジアンフィルタに手を出してみた
perlで。
CPANに「Bayes」でお伺いを立ててみると、
Algorithm::NaiveBayes
なんて言うのがヒットした。説明を見ると、ベイジアンフィルタのいくつかの実装がされているらしい。
そんなんで、適当に書いてみる。
あらかじめ、Cのソースコードとperlスクリプトを、GoogleのCodeSearchあたりで拾い集め、 cは1.c..5.c、perlは1.pl..5.plというファイル名で保存しておいた。
判定に使うものはtest.txt。
use Algorithm::NaiveBayes; use YAML; my $nb = Algorithm::NaiveBayes->new; # Cのソースコードを読み込み for(1..5) { $nb->add_instance( attributes => get_hash($_.".c"), label => 'c' ); } # perlスクリプトを読み込み for(1..5) { $nb->add_instance( attributes => get_hash($_.".pl"), label => 'perl' ); } # 計算! $nb->train; # どっち!? my $result = $nb->predict( attributes => get_hash("test.txt") ); print YAML::Dump $result; sub get_hash { my $file = shift; my $hash = {}; open(INFILE, "<", $file) or die "Cannot open file: $file"; while (<INFILE>) { chomp(); ++$hash->{$_} if($_ ne ''); } return $hash; }
普通は、単語単位でやるんだろうけど、行単位でやってみた。
判定には以下のソースコードをかませてみた。
#include <stdio.h> int main() { printf("Hello World"); return 0; }
結果。
--- c: 0.99943269700008 perl: 0.0336791354869307
確かにcとして判定されちょる。
試しに、get_hashを以下のように単語単位に区切るようにしてみたら、
さらに精度があがった。当然か。
sub get_hash { my $file = shift; my $hash = {}; open(INFILE, "<", $file) or die "Cannot open file: $file"; while (<INFILE>) { chomp(); for( split(/ /) ) { ++$hash->{$_} if($_ ne ''); } } return $hash; }
結果
--- c: 0.999998691261783 perl: 0.00161786115610611
今度はperlを判定。
短いかなぁ? とは思ったけど、以下のを食わせてみた。
use strict; print "Hello World";
結果
-
- -
正しく判定されるもんだねぇ。