我目前正试图通过分析我收集的一个语料库来生成一个垃圾邮件过滤器。
我使用维基百科条目http://en.wikipedia.org/wiki/Bayesian_spam_filtering来开发我的分类代码。
我实现了代码,通过实现wiki中的以下公式来计算消息是垃圾邮件的概率,因为它包含特定的单词:

我的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;
}根据组合个体概率部分,我实现了代码,将测试消息中所有唯一单词的概率组合起来,以确定垃圾信息。
从wiki公式:

我的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);
}在测试字符串“这一点都不坏”上,将产生以下输出:
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实现--但是当我检查维基百科的组合函数时,公式的红利是分数的乘积。我不认为多个概率的组合最终会比.1%概率更高。
如果是这样,那么消息越长,概率分数就越低,我如何补偿垃圾邮件配额,以正确预测小型和大型测试用例的垃圾邮件/火腿?
附加信息
我的语料库实际上是一个大约40k的编辑评论的集合。实际上,我正在对这些评论应用我的“垃圾邮件过滤器”。我将个人评论评为垃圾邮件/火腿,其依据是向下投票的票数:如果向上的票数少于向下的票数,则被认为是垃圾邮件,否则就是垃圾邮件。
现在,由于语料库的类型,事实证明在垃圾邮件中使用的单词实际上很少,在火腿中使用得更多。这是最常见于垃圾邮件的十大单词列表。
+-----------+------------+-----------+
| word | spam_count | ham_count |
+-----------+------------+-----------+
| krugman | 30 | 27 |
| fetus | 12.5 | 7.5 |
| boehner | 12 | 10 |
| hatred | 11.5 | 5.5 |
| scum | 11 | 10 |
| reserve | 11 | 10 |
| incapable | 8.5 | 6.5 |
| socalled | 8.5 | 5.5 |
| jones | 8.5 | 7.5 |
| orgasms | 8.5 | 7.5 |
+-----------+------------+-----------+相反,大多数词在火腿中使用得比火腿更多。例如,我列出的垃圾邮件数量最多的10个单词。
+------+------------+-----------+
| word | spam_count | ham_count |
+------+------------+-----------+
| the | 4884 | 17982 |
| to | 4006.5 | 14658.5 |
| a | 3770.5 | 14057.5 |
| of | 3250.5 | 12102.5 |
| and | 3130 | 11709 |
| is | 3102.5 | 11032.5 |
| i | 2987.5 | 10565.5 |
| that | 2953.5 | 10725.5 |
| it | 2633 | 9639 |
| in | 2593.5 | 9780.5 |
+------+------------+-----------+正如您所看到的,垃圾邮件的使用频率明显低于火腿使用。在我的40k评论语料库中,2100条评论被认为是垃圾邮件。
如下文所建议的,帖子上的测试短语认为垃圾邮件率如下:
短语
Cops are losers in general. That's why they're cops.分析:
C:\projects\bayes>php test.php
cops: 0.15833333333333
are: 0.2218958611482
losers: 0.44444444444444
in: 0.20959269435914
general: 0.19565217391304
that's: 0.22080730418068
why: 0.24539170506912
they're: 0.19264544456641
float(6.0865969793861E-5)根据这一点,这是垃圾邮件的可能性极低。然而,如果我现在分析一个火腿评论:
短语
Bill and TED's excellent venture?分析
C:\projects\bayes>php test.php
bill: 0.19534050179211
and: 0.21093065570456
ted's: 1
excellent: 0.16091954022989
venture: 0.30434782608696
float(1)好吧,这很有趣。在编写这个更新时,我正在做这些示例,所以这是我第一次看到这个特定测试用例的结果。我想我的预测是颠倒的。它实际上是找出火腿的概率,而不是垃圾邮件。这是值得证实的。
对已知火腿的新测试。
短语
Complain about $174,000 salary being too little for self. Complain about $50,000 a year too much for teachers.
Scumbag congressman.分析
C:\projects\bayes>php test.php
complain: 0.19736842105263
about: 0.21896031561847
174: 0.044117647058824
000: 0.19665809768638
salary: 0.20786516853933
being: 0.22011494252874
too: 0.21003236245955
little: 0.21134020618557
for: 0.20980452359022
self: 0.21052631578947
50: 0.19245283018868
a: 0.21149315683195
year: 0.21035386631717
much: 0.20139771283355
teachers: 0.21969696969697
scumbag: 0.22727272727273
congressman: 0.27678571428571
float(3.9604152477223E-11)不幸的是没有。结果是巧合。我开始怀疑,也许评论不那么容易量化。也许一个坏评论的本质与垃圾邮件的本质有很大的不同。
也许只有当你有一个特定的单词类垃圾邮件时,垃圾邮件过滤才能有效呢?
最终更新
如答复中所指出,奇怪的结果是由于语料库的性质造成的。在没有明确定义垃圾邮件的评论语料库时,贝叶斯分类不能执行。由于任何一个评论都有可能(而且很可能)得到不同用户的垃圾邮件和火腿评级,所以不可能生成垃圾评论的严格分类。
最终,我想要生成一个注释分类器,该分类器可以根据调整到评论内容的贝叶斯分类来确定评论帖子是否会装饰业力。我可能还会调查如何将分类器调到电子邮件垃圾邮件中,看看这样的分类器是否可以猜测评论系统的业力响应。但就目前而言,这个问题已经得到了回答。谢谢大家的意见。
发布于 2011-06-24 15:25:10
只有计算器的变化,它似乎可以为非垃圾邮件短语,你张贴。在这种情况下,$pProducts比$pSums小几个数量级。
试着从你的垃圾邮件文件夹中运行一些真正的垃圾邮件,在那里你会遇到0.8这样的概率。猜猜为什么垃圾邮件发送者有时会试图在一个隐藏的框架内发送一份报纸,并附上以下信息:)
发布于 2011-10-10 09:26:14
如果您的过滤器没有偏倚(Pr(S)=Pr(H) = 0.5),那么:“所学习的消息集也应该符合关于垃圾邮件和火腿之间重新划分的50%假设,即垃圾邮件和火腿的数据集大小相同。”
这意味着你应该教你的贝叶斯过滤器类似数量的垃圾邮件和火腿消息。比如1000条垃圾邮件和1000条火腿消息。
我假设(而不是检查)如果你的过滤器是有偏见的,学习集应该符合关于任何信息都是垃圾邮件的假设。
发布于 2014-11-15 15:10:37
根据补偿消息长度的思想,您可以为每个集合估计消息词作为特定单词的概率,然后使用泊松分布估计包含该特定单词的N个单词的消息概率。
https://stackoverflow.com/questions/6463983
复制相似问题