プログラマでありたい

おっさんになっても、プログラマでありつづけたい

Algorithm::NaiveBayes ベイズ理論を使ってコメントスパムフィルター

 Livedoorのブログに対して、余りにコメントスパムが多いので何か対策はないかなと考えてみました。現状、コメントを承認制にして、定期的に目でチェックして救い上げているのですが、余りに面倒くさいです。そこで、スパムメール/迷惑メールのフィルターのエンジン部分の実装として人気のベイジアンフィルターを使って簡単に、コメントスパムフィルターを作れないか考えてみました。

構想
 1. 既存の一般なコメントとスパムコメントを使って初期コーパスとする
 2. Mecabを使って、分ちがちしたものを学習用のデータとする
 3. Algorithm::NaiveBayesを使って、学習させる
 4. コメント通知が来たら、判断させる
 5. 4を元に管理者画面でリリースさせる
 →5の実装が面倒くさそう。。。

#!/usr/bin/perl -w

use strict;
use Algorithm::NaiveBayes;
#use Digest::MD5 qw(md5_hex);
use Data::Dumper;

my $bayes = Algorithm::NaiveBayes->new;
my %list;

%list = &getHash("s.txt");
$bayes->add_instance(
    attributes => {%list},
    label => 'spam',
);

%list = &getHash("h.txt");
$bayes->add_instance(
    attributes => {%list},
    label => 'ham',
);

$bayes->train;

%list = &getHash("t.txt");
my $result = $bayes->predict(
    attributes => {%list}
);

print Dumper($result);

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;
}

スパムから抽出したs.txt。ハムから抽出したh.txt。これらは、それぞれ10個くらいのメッセージを元にデータを作っています。また判定対象となるスパムコメントを元に作ったt.txtを用意します。で、実行。

$VAR1 = {
          'spam' => '0.999999999997147',
          'ham' => '2.38859809356052e-06'
        };
In practice, scores using Naive Bayes tend to be very close to 0 or 1 because of the way normalization is performed. I might try to alleviate this in future versions of the code.

結果は、0〜1の間で出るよと。一瞬おかしいのではと思いましたが、hamの方は2.38859809356052*(0.000001) ということで、極めて0に近い値ですね。よってちゃんと判定できています。

 検討すべき点は多いですが、とりあえず使えるかもという感触は得られました。これを元にちゃっちゃと実装しています。
※実際は、送信元IPや文中のURLなど特別な対処をした方が精度は上がりますが、とりあえずは後で考えます(笑)