私は、書いている Web クローラーの感情分類を試しています (少なくともクローラーに関する限り、車輪の再発明について私に尋ねないでください!)。私は現在、Naive Bayes の使用を検討しています。これは主に、簡単にするための perl モジュールが存在するためです。ただし、映画のレビューの良し悪しを判断するためのテスト ケースの設定に少し問題があります。
私が理解しているように、まず、モジュールがトレーニングする一連のテスト データを用意する必要があります。私は映画をレビューするいくつかの Web サイトにアクセスし、12 の悪いレビューと 12 の良いレビューをダウンロードしました。各ファイルを読み込んで単語リストを生成し、それを単語頻度のハッシュに変換します。次に、一連の「不明な」レビューに対して同じ処理を行います (感情は多かれ少なかれ知っていますが) が、問題が発生しており、これについて間違った方法で行っているかどうかはわかりません!
テスト出力は次のとおりです。
*** Processing good reviews
Reading set/good/anniehall.txt
Reading set/good/biglebowski.txt
Reading set/good/contact.txt
Reading set/good/eternalsunshine.txt
Reading set/good/harakiri.txt
Reading set/good/killing.txt
Reading set/good/lincoln.txt
Reading set/good/mulhollanddr.txt
Reading set/good/narayama.txt
Reading set/good/scarface.txt
Reading set/good/seven.txt
Reading set/good/shoah.txt
Reading set/good/spiritedaway.txt
*** Processing bad reviews
Reading set/bad/battlefieldearth.txt
Reading set/bad/charliesangels.txt
Reading set/bad/deathsmootchy.txt
Reading set/bad/deucebigaloweuro.txt
Reading set/bad/freddyfingered.txt
Reading set/bad/humancentipede.txt
Reading set/bad/jasonx.txt
Reading set/bad/north.txt
Reading set/bad/pootietang.txt
Reading set/bad/residentevilapocalypse.txt
Reading set/bad/savingsilverman.txt
Reading set/bad/slackers.txt
Reading set/bad/texaschainsaw.txt
*** Predicting unknown reviews
set/unknown/benjaminbutton.txt: $VAR1 = {
'bad' => '1.06973342245912e-68',
'good' => '1'
};
set/unknown/epic.txt: $VAR1 = {
'good' => '1',
'bad' => '7.2271232924459e-35'
};
set/unknown/hangoverpart3.txt: $VAR1 = {
'good' => '1',
'bad' => '1.08569835047604e-17'
};
set/unknown/jacobsladder.txt: $VAR1 = {
'good' => '1',
'bad' => '9.31582505503138e-60'
};
set/unknown/marleyme.txt: $VAR1 = {
'good' => '1',
'bad' => '5.57603799052706e-26'
};
set/unknown/quantumofsolace.txt: $VAR1 = {
'bad' => '2.40424666202666e-27',
'good' => '1'
};
set/unknown/thespirit.txt: $VAR1 = {
'bad' => '2.47177895177767e-19',
'good' => '1'
};
set/unknown/twilight.txt: $VAR1 = {
'good' => '1',
'bad' => '9.77187340648713e-62'
};
常に未知のデータを「良い」とマークするようです!
これはプログラム自体です:
use 5.010;
use strict;
use warnings;
use utf8;
use Data::Dumper;
BEGIN { push @INC, "../lib"; }
use Algorithm::NaiveBayes;
my $nb = Algorithm::NaiveBayes->new;
# For each file in each directory, retrieve a hash with each key being a
# unique word, and each value the associated frequency of that word.
# Start with scanning good reviews directory
say "*** Processing good reviews";
my @files = <set/good/*>;
foreach (@files) {
next if ($_ =~ m/^\./); # ignore files beginning with .
say "Reading $_";
my %attr = hash_file($_);
$nb->add_instance ( attributes => \%attr, label => 'good');
}
# Then scan bad reviews
say "*** Processing bad reviews";
@files = <set/bad/*>;
foreach (@files) {
next if ($_ =~ m/^\./); # ignore files beginning with .
say "Reading $_";
my %attr = hash_file($_);
$nb->add_instance ( attributes => \%attr, label => 'bad');
}
# Train, and cross fingers
$nb->train;
# Test unknown reviews
say "*** Predicting unknown reviews";
@files = <set/unknown/*>;
foreach (@files) {
next if ($_ =~ m/^\./); # ignore files beginning with .
print "$_: ";
my %attr = hash_file($_);
my $result = $nb->predict(attributes => \%attr);
print Dumper($result);
}
# Subroutine that takes a file path and returns a hash of the word frequencies
sub hash_file {
my ($file) = @_;
my %words;
my @word_list;
open FILE, $file or die $!;
while(<FILE>){
chomp;
push @word_list, split;
}
close FILE;
foreach (@word_list){
$_ =~ s/[[:punct:]]//g; # Remove punctuation
next if ($_ eq '');
# Increment frequency if word is in hash, or add to hash
if (exists $words{$_} ){
$words{$_}++;
} else {
$words{$_} = 1;
}
}
return %words;
}
そのコードに明らかなエラーがあることを願っていますが、ハッシュ サブルーチンをチェックしたところ、正しいハッシュが出力されているようです。他に考えられる唯一のことは、トレーニングに十分なデータを使用していない可能性があるということです。私のアプローチ全体が間違っているのでしょうか?
洞察をありがとう