数据嗨客 | 第3期:朴素贝叶斯和垃圾邮件过滤
摘要:概率论只不过是把常识用数学公式表达了出来。
概率论只不过是把常识用数学公式表达了出来。
————拉普拉斯
由于使用邮箱注册各种网站,我们每天都会收到各种广告、推销、甚至是诈骗邮件,但幸运地是,我们的邮箱并没有隔几分钟就会有新邮件提醒,因为它会自动识别垃圾邮件,并扔到垃圾箱,就像什么都没有发生。
说到垃圾邮件过滤,不得不提朴素贝叶斯算法,它是一种常见而且效果不错的文本分类算法,今天就让我们来聊聊它。
说文解字,朴素贝叶斯顾名思义基于贝叶斯公式并俱“朴素”之美。
1贝叶斯公式
贝叶斯方法源于托马斯·贝叶斯生前为解决一个“逆概”问题写的一篇文章,而这篇文章是在他死后才由他的一位朋友发表出来的。
在贝叶斯写这篇文章之前,人们已经能够计算“正向概率”,如“假设袋子里面有N个白球,M个黑球,你伸手进去摸一把,摸出黑球的概率是多大”。
而一个自然而然的问题是反过来:“如果我们事先并不知道袋子里面黑白球的比例,而是闭着眼睛摸出一个(或好几个)球,观察这些取出来的球的颜色之后,那么我们可以就此对袋子里面的黑白球的比例作出什么样的推测”。
这个问题,就是所谓的逆概问题。(摘自wikipedia)
设A和B是两个事件(比如A表示今天下雨,B表示草地湿了),那么贝叶斯公式为:
其中:
- P(A)PA和P(B)PB表示A和B各自发生的概率
- P(A | B)PA B表示已知B发生时,A发生的条件概率
- P(B | A)PB A表示已知A发生时,B发生的条件概率
设想,某一天起床,你发现家里草坪上是湿的,你想确认一下昨晚是否下雨了(或者你想知道昨晚下雨的概率),这时候你便可以利用贝叶斯公式:
根据以往的经验,你很快确定了式子右边的一些概率值,然后便可以计算左边的结果了。
2垃圾邮件过滤
我不久前注册了Packt Publishing,并买了几本机器学习的书,最近每天都会在垃圾邮箱里发现来自Packt Publishing的图书推荐和打折的消息。
让我们来看看都有什么内容:
- “... help you and those you know benefit from the skills and techniques inside. Remember, for just 24 hours you can get any eBook or Video for just $10, so don't wait!...”
- “...Our week long celebration of Linux is nearly at an end – there’s just 24 hours left to pick up our selection of handpicked eBooks at 50% off or our 5 for $50 bundles. ...”
- ...
如你所见,里面是一些打折的信息,类似“$10”和“50% off”这样的单词已经透露了这一点。
为了说明问题,让我们简化一下,假设我的邮箱里有500封正常邮件(ham),200封垃圾邮件(spam),现在来了一封新邮件,我发现里面出现了单词“discount”(折扣),我想知道这封邮件是垃圾邮件的概率有多大呢?
很明显,这是一个条件概率问题,让我们试试贝叶斯公式:
我检查了一下所有邮件(请放心,我不是傻傻地靠肉眼检查,一个脚本就可以搞定它),发现垃圾邮件中包含单词discount的有50封,非垃圾邮件中包含单词discount的有20封。那么:
计算P(discount)Pdiscount需要用到全概公式,这也是贝叶斯公式的推论:
好了,现在让我们看看最终的结果:
如果只考虑单词discount,我们有71%的把握认为这是一封垃圾邮件(spam)。
然而,实际情况是,一封邮件通常包含了大量的单词,假设为w1, w2, w3,⋯,wn,那么我们需要计算的是给定单词向量,这封邮件是垃圾邮件的概率是多少。贝叶斯公式稍作改动:
问题似乎没什么变化,我们只要将单词discount换成单词向量{w1, w2, w3,⋯},重新计算一遍就行了。
然而,读者很容易发现,计算P(w1,w2,⋯ | spam)是困难的,因为你几乎很难找到同时包含这些单词的邮件,这时候就需要借助朴素贝叶斯的“朴素”之力了。
3“朴素”之美
数学以简洁为美,简洁不仅使得知识易于理解,而且让计算变得容易。
言归正传,“朴素”之意实际上是独立性假设,对于垃圾邮件过滤即认为每个单词的出现与否是条件独立的,这是一个很强的假设,然而带来的好处是上述的概率计算异常简单:
你看问题又回到了分别计算每个单词相对应的条件概率值了!
朴素贝叶斯因其独立性假设而得名,它不论模型训练或者预测分类,计算都是线性的,因此计算的开销很小,然而效果却很不错!
因此它也是公认的数据挖掘十大算法之一。
很多人好奇,朴素贝叶斯方法的条件独立假设看上去很傻很天真,为什么结果却很好很强大呢?
就拿一个句子来说,我们怎么能鲁莽地声称其中任意一个单词出现的概率只受到它前面的 3 个或 4 个单词的影响呢?
别说 3 个,有时候一个单词的概率受到上一句话的影响都是绝对可能的。那么为什么这个假设在实际中的表现却不比决策树差呢?
有人对此提出了一个理论解释,并且建立了什么时候朴素贝叶斯的效果能够等价于非朴素贝叶斯的充要条件,这个解释的核心就是:
有些独立假设在各个分类之间的分布都是均匀的所以对于似然(即P(w1,w2,⋯, wn | spam))的相对大小不产生影响;即便不是如此,也有很大的可能性各个独立假设所产生的消极影响或积极影响互相抵消,最终导致结果受到的影响不大。
4补充
细心的读者可能会发现,假如某个单词(例如w1w1)在垃圾邮件中不出现,那么P(w1 | spam)=0,进而P(w1,w2,⋯ | spam)=0,显然这是不合理的。
毕竟由于我的邮件数量有限,邮件中未出现的单词不能认为其概率为0。
合理的做法是给那些未出现的单词赋一个很小的概率值,这叫做平滑。
另一方面,实际应用中,单词向量是很稀疏的,每个单词的概率也是很小的,为了防止计算中出现浮点溢出的情况,可以对P(w1,w2,⋯, wn | spam)求对数:
垃圾邮件过滤是文本二分类问题,对于文本多分类问题,思路是一样的。
看完了上面的简单介绍,如果你已经跃跃欲试,想要趁热打铁,我可以给你推荐一些常用的软件和包:
- Python 你可以使用jieba(这是中文分词工具,英文文本通常不存在分词问题)来分词,然后利用sklearn或者gensim来做一些简单的建模,比如上述的朴素贝叶斯分类,或者计算一下文本相似度等等。
- R语言 你可以使用Rwordseg或者jiebaR来分词,它们都支持中文分词,效果也不错。然后用tm做一些前处理,用wordcloud进行可视化,最后用rpart或者e1071做建模分析。
这一期的科普就到这里。下一期我们讲逻辑回归。