在朴素贝叶斯垃圾邮件过滤中,将个别概率进行组合。

7 浏览
0 Comments

在朴素贝叶斯垃圾邮件过滤中,将个别概率进行组合。

我目前正在尝试通过分析我收集的语料库来生成一个垃圾邮件过滤器。

我正在使用维基百科上的条目http://en.wikipedia.org/wiki/Bayesian_spam_filtering来开发我的分类代码。

我已经实现了计算消息包含特定单词时它是垃圾邮件的概率的代码,实现了维基上的以下公式:

pr(S|W) = (pr(W|S)*pr(S))/(pr(W|S)*pr(S) + pr(W|H)*pr(H))

我的PHP代码:

public function pSpaminess($word)
{
    $ps = $this->pContentIsSpam();
    $ph = $this->pContentIsHam();
    $pws = $this->pWordInSpam($word);
    $pwh = $this->pWordInHam($word);
    $psw = ($pws * $ps) / ($pws * $ps + $pwh * $ph);
    return $psw;
}

根据“组合各个概率”的部分,我已经实现了代码来组合测试消息中所有唯一单词的概率以确定垃圾邮件的可能性。

根据维基百科的公式:

p=(p1*pn)/((p1*pn)+(1-p)(1-pn))

我的PHP代码:

public function predict($content)
{
    $words = $this->tokenize($content);
    $pProducts = 1;
    $pSums = 1;
    foreach($words as $word)
    {
        $p = $this->pSpaminess($word);
        echo "$word: $p\n";
        $pProducts *= $p;
        $pSums *= (1 - $p);
    }
    return $pProducts / ($pProducts + $pSums);
}

对于测试字符串"This isn't very bad at all.",产生以下输出:

C:\projects\bayes>php test.php
this: 0.19907407407407
isn't: 0.23
very: 0.2
bad: 0.2906976744186
at: 0.17427385892116
all: 0.16098484848485
probability message is spam: float(0.00030795502523944)

我的问题是:我是否正确实现了组合各个概率的方法?假设我生成了有效的单词概率,组合方法是否正确?

我担心计算结果的概率非常小。我在一个更大的测试消息上进行了测试,最终的概率结果是科学计数法表示的,有超过10个零的位数。我本来期望得到10或100的概率值。

我希望问题在于我的PHP实现上,但是当我检查维基百科中的组合函数时,公式的被除数是分数的乘积。我不明白多个概率的组合怎么会超过0.1%的概率。

如果情况是这样的,即消息越长,概率得分越低,那么我如何调整垃圾邮件的配额以正确预测小型和大型测试案例的垃圾邮件/非垃圾邮件?

0