原文
中国反垃圾邮件联盟论坛一. 贝叶斯过滤算法的基本步骤
1) 收集大量的垃圾邮件和非垃圾邮件,建立垃圾邮件集和非垃圾邮件集。
2) 提取邮件主题和邮件体中的独立字串例如 ABC32,¥234等作为TOKEN串并统计提取出的TOKEN串出现的次数即字频。按照上述的方法分别处理垃圾邮件集和非垃圾邮件集中的所有邮件。
3) 每一个邮件集对应一个哈希表,hashtable_good对应非垃圾邮件集而hashtable_bad对应垃圾邮件集。表中存储TOKEN串到字频的映射关系。
4) 计算每个哈希表中TOKEN串出现的概率P=(某TOKEN串的字频)/(对应哈希表的长度)
5) 综合考虑hashtable_good和hashtable_bad,推断出当新来的邮件中出现某个TOKEN串时,该新邮件为垃圾邮件的概率。数学表达式为:
A事件----邮件为垃圾邮件;
t1,t2 …….tn代表TOKEN串
则P(A|ti)表示在邮件中出现TOKEN串ti时,该邮件为垃圾邮件的概率。
设
P1(ti)=(ti在hashtable_good中的值)
P2(ti)=(ti在hashtable_ bad中的值)
则 P(A|ti)= P1(ti)/[(P1(ti)+ P2(ti)];
6) 建立新的哈希表 hashtable_probability存储TOKEN串ti到P(A|ti)的映射
7) 至此,垃圾邮件集和非垃圾邮件集的学习过程结束。根据建立的哈希表 hashtable_probability可以估计一封新到的邮件为垃圾邮件的可能性。
当新到一封邮件时,按照步骤2)生成TOKEN串。查询hashtable_probability得到该TOKEN 串的键值。
假设由该邮件共得到N个TOKEN串,t1,t2…….tn, hashtable_probability中对应的值为P1,P2,。。。。。。PN,
P(A|t1 ,t2, t3……tn)表示在邮件中同时出现多个TOKEN串t1,t2…….tn时,该邮件为垃圾邮件的概率。
由复合概率公式可得
P(A|t1 ,t2, t3……tn)=(P1*P2*。。。。PN)/[P1*P2*。。。。。PN+(1-P1)*(1-P2)*。。。(1-PN)]
当P(A|t1 ,t2, t3……tn)超过预定阈值时,就可以判断邮件为垃圾邮件。
二. 贝叶斯过滤算法举例
例如:一封含有“法轮功”字样的垃圾邮件 A
和 一封含有“法律”字样的非垃圾邮件B
根据邮件A生成hashtable_ bad,该哈希表中的记录为
法:1次
轮:1次
功:1次
计算得在本表中:
法出现的概率为0。3
轮出现的概率为0。3
功出现的概率为0。3
根据邮件B生成hashtable_good,该哈希表中的记录为:
法:1
律:1
计算得在本表中:
法出现的概率为0。5
律出现的概率为0。5
综合考虑两个哈希表,共有四个TOKEN串: 法 轮 功 律
当邮件中出现“法”时,该邮件为垃圾邮件的概率为:
P=0。3/(0。3+0。5)=0。375
出现“轮”时:
P=0。3/(0。3+0)=1
出现“功“时:
P=0。3/(0。3+0)=1
出现“律”时
P=0/(0+0。5)=0;
由此可得第三个哈希表:hashtable_probability 其数据为:
法:0。375
轮:1
功:1
律:0
当新到一封含有“功律”的邮件时,我们可得到两个TOKEN串,功 律
查询哈希表hashtable_probability可得
P(垃圾邮件| 功)=1
P (垃圾邮件|律)=0
此时该邮件为垃圾邮件的可能性为:
P=(0*1)/[0*1+(1-0)*(1-1)]=0
由此可推出该邮件为非垃圾邮件
更好的贝叶斯过滤法译者:李寄
2003年1月
(本文是在2003年垃圾邮件大会上的一个讲话。它描述了我为提高在《一个计划》中提到算法所做的工作,以及我对未来的打算。)
我想在此给出的第一个发现,是一个用于评估科研论文的懒人算法。你只需写下你想写的,不去引用任何前人的工作,然后热心读者会把你应该引用的论文章节都寄给你。我在《一个计划》【1】发表于Slashdot之后发现的这个算法。
垃圾邮件过滤,是文件分类的一个子集,它是一个相当健全的领域。不过关于贝叶斯过滤法最早的两个文献都是在1988年大会上给出的,一个提供者是Pantel和Lin【2】,另一个是微软研究所的一个小组【3】。
当我听说这项工作时我有点吃惊。如果人们早在四年前就开始贝叶斯过滤法的话,那为什么如今没人在用它呢?读了文章后我明白为什么了。Pantel和Lin的过滤法时那两个中比较有效的一个,可它也只抓住了92%的垃圾邮件,并且是1.16%的错纠率。
当我试着编写一个贝叶斯过滤法时,它抓住了99.5%的垃圾邮件,且错纠率低于0.03%【4】。两个人做同一个实验却得到差别很大的结果,这是很应该引起注意的。在这件事中尤其如此,因为不同的结果可以导致完全相反的结论。诚然,不同用户有不同的需求,不过我想了,对很多人来说,过滤效率仅92%错纠率却高达1.16%,意味着这个过滤法是在不好接受。而99.5%对应小于0.03%的错纠率,则意味着相反。
那么,为什么我们得到如此不同的数字呢?我没有尝试去复制Pantel和Lin的结果,但只是读了他们的论文,我发现有五件事大概可以解释这个差异的。
第一个很简单,他们的过滤法建立在一个很小的数据库上:160个垃圾邮件和466个非垃圾邮件。即便数据库如此之小,过滤效率还是应该高得多的。所以这些数字大概不恩那个确切说明他们算法的有效程度,更不用说广义上的贝叶斯过滤法的有效程度了。
不过我认为,最重要的区别大概在于,他们忽略了邮件台头。这在任何致力于垃圾邮件过滤器的人看来,都是一个不合常理的做法。可实际上在我尝试编写第一个过滤器时,我也忽视了台头。为什么呢?因为我想让问题简单化。那会儿我对邮件台头知道得还不多,对我来说,它们就是一堆随机的玩意儿。这里,对过滤器编写者是一个教训:不要忽略数据。你会觉得这个教训太明显了,不值一提,可我实际上不得不把它吸取了好几遍。
第三,Pantel和Lin对token进行了剪切,好比说,他们把“mailing”和“mailed”都压缩成根词“mail”来处理。他们大概觉得必须得这样做,因为他们采用邮件集的容量之小。可若如此,这不过是一个不成熟的乐观想法。
第四,他们用了不同的方法来算概率。他们把所有的token都用上了,而我只用了15个最具代表性的。当你使用所有的token时,你就倾向错过较长的垃圾邮件,那些某人跟你讲他们一生的故事,讲直到某天他们通过某种分层营销手段而致富的邮件。并且这样的算法容易北垃圾散发者所愚弄:只需加上一大堆随机文档来中和掉那些垃圾术语就可以了。
最后一点是,他们没有对错纠提起注意。我认为,不管什么垃圾邮件过滤法,都需要包含一个方便旋钮,你一拧,就能在降低过滤率的代价之上降低错纠率。我用的法子,是把token在非垃圾邮件集里出现的次数加倍。
我认为,把过滤垃圾邮件当作单纯是一个文件分类问题来处理不是个好主意。你可以使用文件分类技术,可你的法子应当体现出这些文件是邮件的事实,并且特别是垃圾邮件。邮件不仅仅是文本,它具有自己的结构,过滤垃圾邮件不仅仅是分类,因为错纠比错放要恶劣得多多,你必须把它们看成是不同性质的差错,并且这些差错的来源并非什么随机偏差,而是活生生的致力于攻克你过滤器的垃圾邮件制作人。
Tokens
在Slashdot文章(译者注:《一个计划》)之后,我听说的另一个项目是Bill Yerazunis的CRM114【5】。这是我刚提到过设计原理的一个反例。它是一个单纯的文本分类器,但却有着惊人的效率,可以在不知道自己在做什么的情况下,把垃圾邮件近乎完美地给过滤掉。
当我理解了CRM114是怎么工作的之后,看似不可避免地,我迟早德从基于单个单词的过滤法走向类似这个的方法。不过我先是想着,我得看看依靠单个单词能走多远。然后那答案是,令人吃惊之远。
总体上我致力于更精良的token化处理工作。对现有的垃圾邮件,我已能达到近似crm114的过滤效率。这些技术跟Bill的(译者注:CRM114用到的技术)基本上是正交的。一个理想化方案大概是合并这二者。
《一个计划》中用的是一个对token的简单定义方法:字母,数字,破折号,撇号,美元符号,这些是组成成分,其他的都是token分离符。我还忽略了词格(译者注:例如,主谓宾格)。
现在我有一个更复杂的token定义法则:
1. 词格保留。
2. 惊叹号是组成成分。
3. 当句号和逗号出现在两个数字之间时,它们也是组成成分。这样我可以使IP地址和价钱保持不碰。
4. 价格范围如$20-25,是两个token,$20和$25。
5. 在发往To,来自From,主题Subject,和回归路径Return-Path这些栏,或是url中的出现的token,作以相应的标记。例如,主题Subject中的“foo”就变成“Subject*foo”。(这里的星号可以是任何你没定义成token组成成分的符号。)
以上措施提高了过滤器的词汇量,于是使分辨率更高。举例说,在现有的过滤器中,主题栏出现的“free”一词具有98%的垃圾概率,而在正文出现的同一token概率仅为65%。
以下是现有的一些概率【6】:
Subject*FREE 0.9999
free!! 0.9999
To*free 0.9998
Subject*free 0.9782
free! 0.9199
Free 0.9198
Url*free 0.9091
FREE 0.8747
From*free 0.7636
free 0.6546
在上次的计划中,所有这些token的概率是一样的,都是0.7602。那个过滤器识别的token大约有23,000个,现有的约为187,000个。
更大的token世界带来的坏处是,错放的机会会增加。对一个邮件集来说,提高其token数目的效果类似于减小其容量。例如,你要是把惊叹号当成组成成分,结果你就找不到free连着7个惊叹号的概率,虽然你明知道free带两惊叹号的概率是99.99%。
一个解决方法是我所谓“退化法”。如果你找不到某个token的确切数值,你就把它处理成一个不那么明确的版本。像末尾的惊叹号,大写字母,以及在那五个标记位置里出现,这些我都看成是使token更明确化的标志。例如,假如我找不到“Subject*free!”的概率,我就去找“Subject*free”,“free!”和“free”,然后取其中离0.5最远的那个概率。
以下列举的是过滤器在主题栏看见“FREE!!!”并且找不到其概率是所拥有的其他选择【7】:
Subject*Free!!!
Subject*free!!!
Subject*FREE!
Subject*Free!
Subject*free!
Subject*FREE
Subject*Free
Subject*free
FREE!!!
Free!!!
free!!!
FREE!
Free!
free!
FREE
Free
free
当你这么做时,注意一定要把开头字母大写和所有字母大写以及所有字母小写这些情况一起考虑进去。垃圾邮件倾向含有更多祈使句式的句子,同时那些句子的第一个字是动词。所以开头字母大写的动词比所有小写字母的有更高的垃圾概率。我的过滤器里,“Act”的垃圾概率是98%,而“act”仅有62%。
当你提高过滤器的词汇量,你结果会把相同的单词算上多遍,――就你过去定义的“相同”而言。逻辑上讲,它们不再是同一个token了。不过如果你还是觉得不爽的话,那么从我的经验看来,这些你看着是被重复计算的词,倾向于刚好就是你想要重复计算的那些。
加大了的词库带来的另一个后果,是当你观察一个收到的邮件时,你会发现更多有趣的token,即概率远离0.5的那些。我用15个最关键词来决定一封邮件是否垃圾,不过,若是用这样一个固定的数字你会遇上困难。如果你发现很多极度有趣的token,那结果会是,你的结论被一些莫名其妙的随机事件所左右,是它们决定了这些同等关键的token的排列次序。对付这情况的方法是,把其中一些token看成比其他的更为关键。
举例来说,“dalco”这个token在我的垃圾邮件集中出现过3次,从未在合法邮件集中出现过。“Url*optmails”这个token(意思是“optmails”包含在某url中)出现了1223次。可当我计算token的概率时,这两个有相同的垃圾概率,0.99那个槛。
这感觉不大对。关于给予这两个token本质上不同概率(Pantel和Lin是这么干的)的问题,存在有理论依据,不过我还没试过。看上去至少得这样:如果我们发现有多于15个token只出现在这个或那个邮件集,我们就得优先考虑出现次数很多的那些。所以现在有两个槛值。对于只出现在垃圾邮件集的token,当它们出现超过10次时其概率时0.999,否则0.998。对相反方向那些只出现在合法邮件集的token,我们作同样处理。以后我大概会对概率进行实质上的权衡。不过以上这些微小份量的差别,至少确保了token整理的方向正确性。
另一个可能应该是不只考虑15个token,而是把所有token放在一个特定的有趣程度槛上进行衡量。Steven Houser在他的统计法邮件过滤器中是这么做的【8】。如果你用一个槛,就得把它弄得非常高,不然垃圾散发者会拿更多合法词汇充斥其邮件来瞒过你。
最后一点是,我们可以拿html怎么办?我试过所有可能的选择,从忽略它到对它作语法分析。忽略html不号,因为它充满了有用的垃圾邮件信号。但你若是对它作语法分析,你的过滤器会退化成光是一个html识别器。看来最有效的是中间方法,即注意一部分token而放过其他部分。我是查看img和font标签,而忽略别的。链接和图片自然是你应该看的,因为它们包含了url。
对付html,我大概能做的更聪明些,不过我不认为它值得花很多时间在上面。那些满是html的垃圾邮件很容易过滤,精明些的垃圾散发者早已避开了这个。所以未来的工作情况,不应决定于你是怎么对付html的。
工作情况
自2002年12月10日,至2003年1月10日之间,我收到约1750个垃圾邮件,其中有4个被放过了。这个过滤率大概有99.75%。这四个溜掉的垃圾邮件中,有两个是因为它们刚好用了我合法邮件中常出现的词。
第三个是利用一个不安全的cgi脚本把邮件发给第三方的那种垃圾邮件。只基于内容它们很难过滤,因为台头清白并且用词谨慎。即便如此,我一般还是能抓住它们。这一个是以0.88的概率给溜了,刚好低过0.9的槛。
自然,若是用查看多重token序列方法应该能轻易抓住它。“Below is the result of your feedback form”立马就把它给卖了。
第四个则是我所谓“未来型”垃圾邮件,因为它正是我指望垃圾邮件会进化成的样子:一些全然是中性的文本,接着来一个url。在这里,它来自某个声称刚做完主页让我去看一眼的家伙(那个主页自然是一个黄色网站的广告)。
如果垃圾散发者小心台头,并且使用新鲜的url,那这种“未来型”垃圾邮件将没什么好引起过滤器注意的地方。我们当然可以放一个爬虫去其网站,进行反击,不过那未必是必须的。这种未来型垃圾邮件,它们的回应率一定很低,不然的话所有人都在用它了。若是低得足够的话,垃圾散发者干这个就会划不来,那么我们也就不需要花大力气来进行过滤了。
现在让我们来看真正令人震惊的消息。在这同样的一个月之内,我弄出了三个错纠邮件。
在某种程度上,错纠的存在是一种解脱。当我写《一个计划》时,我一个错纠都没碰上,于是就没法知道它们该长什么样儿。现在我有了几个。解脱的是,它们不像我担心的那么糟。统计方法过滤器所产生的错纠邮件,其实就是那些听上去特象垃圾邮件的家伙,并且倾向是你最不介意错过的那些。
错纠邮件中,有两个是我买过东西商家发来的新闻信。我从没要求过接受它们,所以有理由说它们也是垃圾邮件。不过我当它们是错纠,因为我从未把它们当垃圾邮件一样删掉过。过滤器捕获它们的原因是,这两公司都于1月份从发送自他们自己的服务器转成商业邮件发送了,并且它们的台头和主体都变得更垃圾化了。
第三个错纠却是一个坏例子。它来自埃及的某人,从头到尾都大写。这是把token设置得更敏感的直接后果。《一个计划》中用到的过滤器不过错抓住它。
难说总体的错纠率会有多高,因为统计上讲,我们身处噪音之中。任何致力于过滤器的人(至少是有效的过滤器),都会警觉于这个问题。有些邮件你压根说不好它们是不是垃圾,而当你把过滤器做得严格了,这些刚好就是你到头来得面对的邮件。举例说,迄今为止过滤器抓住了两个因拼写错误误发到我地址来的邮件,其中一个是把我当成另外什么人了。它们究竟是我的垃圾邮件还是非垃圾邮件,这可说不好。
另一个错纠邮件是来自Virtumundo的某个副总经理。我装成是他们的顾客写信过去,然后他们回信过来。因为回信是通过Virtumundo的服务器,其台头是你想象得出最可疑的那种。同样这算不算错纠也很难说,不过带点Heisenberg不确定性效应(译者注:Heisenberg Uncertainty Effect---“The more precisely the position is determined, the less precisely the momentum is known.”你的位置越明确,状态就越难料。):我收到它,只因我在写关于垃圾邮件过滤器的东西。
不算这些的话,我总计碰到过五个错纠邮件,在约7740个合法邮件中计0.06%。另外两个是我买的东西被back-order的同志,和一个来自Evite的聚会提醒。
我不认为这些数字是可信的,部分因为样本太小,部分因为我相信我可以修改过滤器,使它不再抓其中一些。
错纠对我来说,同错放使不同种类的差错。过滤率是用来测量工作情况的,错纠我则认为更象是bug。我把提高过滤率当作优化工作来做,而减少错纠就象是debug。
所以这五个错纠邮件就是我的bug清单。举例说,那个垃圾邮件的被抓,是因为大写字母使过滤器看它象一个Nigerian垃圾邮件。这确实是一种bug。跟html相似,一封邮件所有字母都大写,从概念上讲的确只是一个特征,而非每个单词都分别有一个特征。我得用更高明的手段处理这事。
那么,我们拿这0.06%怎么办呢?我没想太多。呢可以当它是一个上限,同时别忘了样本空间之小。不过就现阶段而言,这更多是一个对在我使用下贝叶斯过滤器所产生bug的测度,而不能算成是贝叶斯过滤器本质上的错纠率。
未来
随后是什么?过滤是一个优化问题,而优化的关键是概括。别试着去猜你的代码在哪变慢,因为你会猜错。你得去观察,你的代码在哪走慢了,然后改进它。在过滤中,以上过程即是:观察你所错过的垃圾邮件,然后搞明白你的怎么做才能抓住它们。
例如,现在垃圾散发者们正主动运作,要避开过滤器,他们在做的一件事是,把单词分割或者拼错,这样来防止被过滤器识别。不过这方面的努力不是我的重点,因为我能不费力地抓住这种垃圾邮件【10】。
有两种垃圾邮件,是我现在感到麻烦的。一个是那种假装来自某个女人,邀你去跟她聊天,或者看她在什么黄色网站上的资料。这些能溜过过滤器是因为,它们是那种不需使用推销词汇的推销手段,并且它们用的全是我真实邮件里那些词。
另一种我不大好过滤掉的,是那些来自(例如Bulgaria)的某公司发来的提供编程服务合约的垃圾邮件。它们能通过,是因为我也是个编程员,并且那些垃圾邮件的用词跟我真实邮件的一个样儿。
我大概会先致力于个人广告类。我想要是再看仔细点儿,我应该能发现它们跟我真实邮件之间的统计学差异。文笔自然是不同的,哪怕得用到多重单词过滤法。而且,我注意到它们都倾向重复提及其url,而在合法邮件中提到url的人不大会这么干【11】。
境外合约那种垃圾邮件将不好对付。即便你往那网站发个爬虫,你也不会发现一杆冒烟儿的统计枪。也许唯一的解答是,弄一个现有垃圾邮件包含域名的主要列表【12】。不过这种邮件的数量多不至此。如果垃圾邮件就只剩下这些不请自来的Bulgaria来的编程服务合约的话,我们也许不妨都去忙点什么别的。
统计过滤法真能令我们走这么远么?我不知道。现在对我个人来说,垃圾邮件不是个问题。不过至今为止,垃圾散发者还未曾认真努力过来瞒过统计过滤器。要是他们这么做了,那会怎么样?
对网络层的过滤器,我不感觉乐观【13】。当有一个值得通过的静止不动的障碍物在那呆着,垃圾散发者可以相当有效地通过去。现在已经有一个名叫Assurance Systems的公司,专门把你的邮件放在Spamassassin下运行,然后告诉你它是否会被过滤掉。
网络层的过滤器也不是全没用。他们大概足以用来干掉所有“opt-in”的垃圾邮件,意即来自诸如Virtumundo或Equalamail等公司的,声称他们确实在使用opt-in清单的垃圾邮件。你可以光是基于台头就过滤掉那些家伙,不管他们在邮件主题说些什么。不过,任何人只有乐意伪造台头,或是使用开放型中继站,(可以想象大多数黄色垃圾散发者都会如此)那他们就应该能让一些邮件(值得一提的是,那不会是他们最想传递的邮件)通过网络层过滤器,只要他们想。
我持乐观态度的的,是那些基于每个用户个人邮件来计算概率的过滤器。它们可以更有效得多,不光是避免错纠,而且在过滤上也是如此。例如,在任何地方发现64位编码的接受者地址,就是一个很好的垃圾警报器。
不过,个人化过滤器的真正优点在于,它们个个都不一样。如果每个人的过滤器都有不同的概率数字,那会使垃圾散发者的优化系统――程序员称之为“编辑-编译-测试”循环――以惊人缓慢的方式打转。他们不能光是修改一个垃圾邮件使之能通过他们桌面上的某个过滤器,而是得就每次修改都做一下测试。这就像是在缺乏互动层面的基础上,用某个语言进行编程,我不指望任何人会喜欢干这个。
注释
【1】 Paul Graham. 《一个关于垃圾邮件的计划》。2002年8月。http://paulgrahan.com/spam.html。
这个算法用的是一种简化贝叶斯法则来计算概率。有两个简化的假设:一是单个物体(单词)的概率是独立的,一是我们对一封邮件是垃圾的概率一无所知。
第一个假设在文本分类中很常见。这么做的算法叫做“幼稚的贝叶斯”。
第二个假设,我是基于我的日常垃圾邮件进项每天(事实上,每小时)都不一样的事实而提出的,因为这样一来,整体比例就压根不能用来当作预设。如果你假设垃圾的概率和非垃圾的概率都是0.5,那它们就相互抵消了,你就可以把它们从计算公式里整个扔掉。
如果是在垃圾与非垃圾比例持续性很高或者,尤其是很低的情况下做贝叶斯过滤器,那你大概能用加进预设概率的方法来提高工作情况。要想这么做,你得在一天的不同时候对比例进行跟踪,因为垃圾邮件和合法邮件有各自不同的日常作息。
【2】 Patrick Pantel和Dekang Lin。《SpamCop-A Spam Classification & Organization Program》。AAAI-98工作间在学会文本归类方法之后。
【3】 Mehran Sahami,Susan Dumais,David Heckerman和Eric Horvitz。《A Bayesian Approach to Filtering Junk E-mail》。AAAI-98工作间在学会文本归类方法之后。
【4】 那时我在4000封合法邮件中没有一个错纠。如果下一个合法邮件被错纠,那结果会是0.03%。正如我后来指出的,这些错纠率不可信。我在这里引用这个数据,只是位了说明不管错纠率会是多少,它是小于1.16%的。
【5】 Bill Yerazunis。《Sparse Binary Polynomial Hash Message Filtering and the CRM114 Discriminator》。2003垃圾邮件大会之后。
【6】 在《一个计划》中,我用了0.99和0.1的槛。把槛设得跟邮件集的大小成比例应该是有道理的。因为我现在两种邮件都用10,000个做邮件集,现在的槛是0.9999和0.0001了。
【7】 这里有一个毛病是我大概应该修改的。现在情况是,当“Subject*foo”退化成“foo”时,这意味着你获取的是“foo”出现在我标记的那5个部分之外的主题或台头中的统计数字。我应该把“foo”这个词的总体出现情况以及特殊情况都记录下来,然后把“Subject*foo”退化成“Anywhere*foo”而不是“foo”。同样的,我应该把字母大写退化成所有形式,而不是字母小写。
用这个方法来对付价钱应该也是好的,好比,“$129.99”退化成“$--9.99”,“-$--.99”,和“$--”。
你还可以把单词退化成它们的一般形式,不过这当你使用小型邮件集时大概只能提高一开头的过滤率。
【8】 Steven Hauser。《Statistical Spam Filter Works for Me》。
http://www.sofbot.com.
【9】 错纠并不都等价,我们在比较各种针对垃圾邮件的技术时,应当记住这点。不光有那些近乎垃圾邮件的你不在乎丢失的错纠邮件,还有一些别的,好比因黑名单而造成的错纠,那只是些别人发给你的正常邮件,因为他们使用了错误的ISP而被丢失了。这两种情况下你都时抓住了“约等于”垃圾的邮件,不过对黑名单来说,这个“约等于”是物理意义上的,而对过滤器来说这是文本意义上的。
不过公平地说,象SBL这种值得信赖的新生代黑名单,它所造成的错纠,要比早期像MAPS RBL这种黑名单要少得多多,因为早期黑名单造成一大堆错纠,不过是它想要引起公众对ISP的注意的一种故意手段。
【10】 如果垃圾散发者改进到能用这种混淆token的方法制造出大麻烦,我们可以简单删除空格,句号,逗号等,来进行反击,并且可以用一个词典来把单词从得到的序列中给找出来。当然了,把这种隐藏在文本中的单词找出来,这事本身就是垃圾邮件的一个证据。
这种找词不会是简单的。它需要比重组单词边界更多的东西;垃圾散发者添加(“xHot nPorn cSite”)并且省略(“P#rn”)这些词。视觉研究在这里大概会有用处,因为人类视觉正是这些诡计所能尝试的极限。
【11】 一般来说,垃圾邮件的重复率要比普通邮件为高。他们想使他们的信息一步到位。现在我并不准许15个头号token中有重复,因为要是发送者刚好把什么坏词用上多遍,那就会导致错纠。(在我现有的过滤器中,“dick”的垃圾概率有0.9999,可它同时也是个人名。)不过看来我们至少得对重复提起注意,所以我大概会尝试,对每个token允许至多两遍的重复,正如Brian Burton在SpamProbe里做的那样。
【12】 这是一旦垃圾散发者被迫使用mad-lib技术来生成文件中的所有其他文本,像Brightmail那样的方法将退化成的样子。
【13】 争议是,我们是否应该致力于网络层的过滤器,因为它更有效。当人们这么说的时候,他们的意思一般是:我们已经在网络层有过滤器了,就不想再从底层开始。不过问题是,你不能为了支持你的解决方案而窜改题目。
历史上说,在软件设计上总是小规模那方失败。人们倾向于做的,是为使其他理由下作出的选择(特别是不动的选择)名正言顺而使用它们。
感谢Sarah Harlin, Trevor Blackwell, Dan Giffin阅读此文手稿,并且再次感谢Dan打造这个过滤器赖以工作的大部分基础。