2.7 朴素贝叶斯
1.先从贝叶斯定理复习起
说起来,前面1.4 节讲概率的时候,我们已经见过贝叶斯定理了。这一章的主角朴素贝叶斯,本质上就是在这条定理上做了一道漂亮的近似。所以我们先把这条老定理请出来,再往前走一步。
贝叶斯定理的公式是这样的:
这里每个符号都得说清楚。 是我们想预测的类别(比如一封邮件到底是不是垃圾邮件), 是我们手上能观察到的特征(比如这封邮件里出现了哪些词)。 叫先验概率,是在没看到任何特征之前,我们对这个类别的把握。 叫似然,意思是假如类别已经确定了,看到这些特征的可能性有多大。 叫证据,是这些特征总体出现的概率,起一个归一化的作用。 才是我们要的那个数,叫后验概率,意思是在看到特征之后,这个类别的概率变成了多少。整个公式干的事,就是把先验 拿似然 往上抬一下,再除以证据 归个一,得到后验。
我打个比方。小张的妈妈前阵子去医院体检,某项肿瘤标志物化验结果是阳性,一家人吓得不轻。我陪她去复查的时候,大夫说这项化验的灵敏度(真正有病的人里被查出来的比例)和特异度(真正没病的人里被正确判定的比例)都不算低,可这种病在普通人群里的发病率其实很低,先验概率非常小,所以即便化验阳性,最终真的患病的后验概率也没有想象中那么高。大夫这番话,说穿了就是贝叶斯定理,先验太低,似然再往上抬,后验也抬不到天上去。这条思路放到机器学习里,就是用历史数据估出先验和似然,再拿新样本的特征去算后验,最后挑后验最大的那个类别当作预测。
2.朴素假设:给定类别,特征之间条件独立
贝叶斯定理看起来很美,可一旦真的想算 ,就会撞上一堵墙。原因是 往往是一堆特征凑起来的,记作 ,这里 表示第 个特征(比如第 个词出现还是没出现), 是特征总数。要把这么多特征一起考虑,联合概率 算起来特别费劲,需要穷举各种特征组合的共现次数,数据量根本不够用。
朴素贝叶斯在这里加了一条关键假设:给定类别 之后,各个特征之间条件独立。写成式子就是:
这里 是连乘符号,意思是从第 个特征到第 个特征,每个特征的条件概率全部乘在一起。 这个符号我们在3.10 节讲梯度连乘的时候也见过,意思是一样的,就是把一串数全部乘起来。
这么一假设,那个难算的联合概率,就被拆成了一连串好算的单变量条件概率。每个 只关心一个特征和一个类别,数起来轻松得多。代回贝叶斯定理,由于分母 对所有类别都一样,比较的时候可以省掉,于是有:
这里 表示正比于,意思是左右两边只差一个对所有类别都相同的常数因子。预测的时候,我们对每个类别都算一遍右边的乘积,哪个最大,就把样本归到哪一类。这种挑法有个名字,叫最大后验估计。
3.为什么叫朴素
说到这儿大概你也感觉到了,条件独立这条假设其实相当强。现实里的特征常常是纠缠在一起的,一封邮件里出现免费和中奖这两个词,多半是一块儿冒出来的,谁也不真的独立于谁。可朴素贝叶斯偏偏假装,只要类别给定,这些词就互不影响了。这就是朴素这三个字的由来,朴素得近乎天真。
可就是这么一条近乎天真的假设,效果却出奇地好,尤其是文本分类这一摊事。个中缘由说起来也简单。我们最终要的只是哪个类别的后验最大,并不需要每个概率都估得特别准。即便假设不完全成立,那串连乘给出的排序通常仍然是对的,垃圾邮件还是会被判成垃圾邮件。我之前看过一本讲统计学习的书,里面有一句话印象很深,说朴素贝叶斯之所以效果好,关键在于它把有限的样本用到了极致,每个特征只单独计数,参数再省也够估。这话我一直记得。小明开了一家做酸菜鱼的小馆子,他凭经验判断回头客,看的就是几个互不相干的信号(客人来店里是周中还是周末、是不是带朋友来、点没点招牌酸菜鱼),这些信号之间其实也谈不上严格独立,可搭在一起就是相当准。朴素贝叶斯干的也是这件事。
4.拉普拉斯平滑:别让一个零清零一整项
朴素贝叶斯还有一个绕不开的坑,叫零概率问题。式子里那一串连乘,只要有一个 等于零,整个乘积就全清零了,别的特征再怎么指向这一类都没用。这显然不合理。比方说训练集里所有的正常邮件都没有出现过中奖这个词,那 ,于是来一封新邮件,只要它带着中奖这个词,不管它还带着多少明显正常的内容,正常这一类的得分都是零,这封邮件只能被判成垃圾。
解决办法叫拉普拉斯平滑,做法很温和,给每个特征的计数都加一个小常数。设类别 下第 个特征取某个值的计数是 ( 就是训练集里属于类别 、且第 个特征取该值的样本数),该特征可能取值的种数记作 ( 是第 个特征能取多少种不同的值),平滑后的概率是:
这里 是平滑常数,通常取 , 是训练集里属于类别 的样本总数。直观上理解,就是假装每个特征的每个取值都额外多见了 次,再正常不过的零计数也就被抬成了一个很小但不是零的数。这一招和1.4 节信息论里讲到的那种给极端情况留点余地的思路是相通的,遇到没见过的情况,总要留一点点余地,别把话说死。
5.经典应用:从垃圾邮件到情感分类
朴素贝叶斯最经典的应用大概就是垃圾邮件分类了。做法是把一封邮件先切成一个个词,再统计哪些词出现、哪些不出现,或者直接用词频当特征。常见的有两个套路,一个叫多项式模型,把每个词的出现次数当作特征。另一个叫伯努利模型,只看一个词出现没出现,出现记 ,没出现记 。无论哪种,最后都套进上面那套连乘公式里,比较垃圾邮件和正常邮件两类后验哪个大。
情感分类的路数也差不多,把一条评论切成词之后,统计正面情感词(喜欢、好看、惊喜)和负面情感词(失望、踩雷、难看)的分布,再用带类别标注的训练集估出每个词的条件概率。新来一条评论,套朴素贝叶斯,就能大致判断它是好评还是差评。我记得某部讲互联网创业的连续剧里有个桥段,主人公团队靠一个朴素贝叶斯模型,从海量用户评论里筛出了对产品的真实不满,模型虽朴素,胜在好实现、好解释,上线也快。这种轻量级方案在做初版分类、做基线对比的时候特别讨喜。后面我们会讲到的深度文本模型,效果当然更好,可朴素贝叶斯这个基线,至今仍然值得先跑一版看看。
6.手算一个小例子:免费中奖的邮件
光讲公式不练手总是虚的,我们来算一个小例子。假设训练集里有10封邮件,其中4封是垃圾邮件,6封是正常邮件。先验就有了:
我们挑免费和中奖这两个关键词做特征,只看它们出现还是没出现。统计下来是这样的:在4封垃圾邮件里,3封含免费,3封含中奖。在6封正常邮件里,1封含免费,0封含中奖。
现在来了一封新邮件,里面既有免费又有中奖,我们想判断它是不是垃圾。先用朴素贝叶斯那套连乘算垃圾这一类(这里 表示乘法):
把数代进去:
再算正常这一类,问题就来了:
中奖这个词在正常邮件里一次都没出现过,条件概率直接为零,整项连乘清零,正常这一类的得分成了零。这显然不合理,正是拉普拉斯平滑出场的时候。这里的特征是出现和没出现两种取值,所以 ,取 ,重新估一遍:
现在再算两类的得分:
垃圾这一类的得分大约是正常这一类的9倍多,于是模型把这封邮件判成垃圾邮件。要是再除以两类得分之和做一下归一化,垃圾这一类的后验大约是 ,也就是九成把握。这个结果和我们的直觉吻合,免费加中奖,听着就不太正经。
7.收个尾
朴素贝叶斯讲到这里就差不多了。说起来它和前面几篇都有点缘分,根上的贝叶斯定理接的是1.4 节的概率,连乘符号在3.10 节的梯度链里见过,平滑常数那种给极端情况留余地的思路,也和信息论里的一些做法相通。后面我们聊线性回归(2.1 节)、聊降维里的PCA(1.3 节讲过特征值),多少都会回头呼应这些老朋友。朴素贝叶斯虽朴素,却一直是个值得先跑一版的好基线。
今天就先到这儿,下一章见。
练习
Q1. 朴素贝叶斯"朴素"在哪?现实中特征明显不独立(比如"免费"和"中奖"常一起出现),为啥这套近乎天真的假设效果反而不错?
"朴素"在它假设给定类别之后各个特征条件独立,把难算的联合概率 拆成连乘 。现实中特征常常纠缠在一起,这条假设近乎天真。可效果出奇地好,尤其是文本分类——因为我们最终要的只是哪个类别的后验最大,并不需要每个概率都估得特别准,即便假设不完全成立,那串连乘给出的排序通常仍然是对的,垃圾邮件照样被认出来。说白了它把有限的样本用到了极致,每个特征只单独计数,参数再省也够估。
Q2. 训练集 4 封垃圾、6 封正常;垃圾里 3 封含"免费"、3 封含"中奖",正常里 1 封含"免费"、0 封含"中奖"。来一封既含"免费"又含"中奖"的邮件,不做平滑会出什么问题?取 拉普拉斯平滑后(特征取值种数 ),垃圾类得分大约是正常类的几倍?
不做平滑的话,,正常类那串连乘直接清零,邮件不管还带多少正常内容都只能被判成垃圾,显然不合理。平滑后 ,,垃圾得分 ;,,正常得分 。垃圾得分大约是正常类的 9 倍多,判成垃圾。
Q3. 拉普拉斯平滑公式 里每个符号什么意思?为什么朴素贝叶斯非加这一步不可?
是训练集里属于类别 且第 个特征取该值的样本数, 是类别 的样本总数, 是第 个特征能取多少种不同的值, 是平滑常数(通常取 1)。直观上就是假装每个特征的每个取值都额外多见了 次。非加不可,是因为朴素贝叶斯靠连乘算后验,只要有一个 ,整项乘积就清零,别的特征再怎么指向这一类都没用——拉普拉斯平滑把零抬成一个很小但不是零的数,避免一个没见过的取值清零整项,遇到没见过的情况总要留点余地。