🌝
Table of Contents

朴素贝叶斯分类器

Posted at — Nov 10, 2019

这篇文章将对朴素贝叶斯分类器进行简单描述和公式推导,并以性别预测为例来理解其「朴素」的原因,最后你应该能根据文章的描述编写一个简单的由人的姓名预测其性别的小程序。阅读前你可能需要懂一些概率论的知识,比如条件概率、贝叶斯公式等等。

基本原理

我们在小学二年级学过贝叶斯公式:

$$ P(B|A)=\frac{P(B)P(A|B)}{P(A)} \tag{1} $$

通过该式子,我们可以算出在已知事件A发生的条件下,事件B发生的概率。比如1当我们看到室友抽屉里藏女士内衣,则室友是个变态的概率就是遇到变态室友的概率乘室友是个变态还喜欢把内衣放抽屉里的概率再除以室友抽屉里有内衣的概率。是不是非常的啊妹zing呀?这里面其实蕴含着「贝叶斯学派」独有的思想,即「后验概率」的思想。感兴趣的同学可以深入了解一下

现在我们假设上式中的事件A由很多事件构成,即:

$$ A=A_1 \cap A_2 \cap … \cap A_n $$

则我们的贝叶斯公式变成:

$$ P(B|A_1 A_2 … A_n)=\frac{P(B)P(A_1 A_2 … A_n|B)}{P(A_1 A_2 … A_n)} \tag{2} $$

这其实已经是一个分类器的模型了。我们不妨将事件B看成一推数据的分类结果,将 $A_1,A_2,…,A_n$ 看成是导致该结果的因素或者叫特征(以下统称特征),则等号左边表示的就是我们的数据属于分类 $B$ 的概率,当其达到某个阈值,我们可以认为该推数据就属于某个分类。

要得到等号左边是多少,我们得从已有的数据中找到等号右边的三项的值。其中 $P(B)$ 可以通过统计数据集中 $B$ 类样本出现的频次得到,即:

$$ P(B)=\frac{B类样本个数}{样本总个数} $$

但剩下的两项很难从有限的数据中直接得出。对于 $P(A_1 A_2 … A_n|B)$,我们假设所有的特征相互独立,则我们就有: 2

$$ P(A_1 A_2 … A_n|B)=\prod_{i=1}^{n}{P(A_i|B)} \tag{3} $$

其中 $P(A_i|B)$ 是容易从数据集中直接得到的,分为离散和连续两种情况:

$$ P(A_i|B)=\frac{B类中有特征A_i的数据个数}{B类数据个数} $$

假设 $A_i|B$ 符合期望为 $\mu_{ki}$,方差为 $\sigma^2_{ki}$ 的正态分布,则有:

$$ P(A_i|B)=\frac{1}{\sqrt{2\pi}\sigma_{ki}}e^{{-\frac{(A_i-\mu_{ki})^2}{2\sigma^2_{ki}}}} $$

而对于2式等号右边分母部分,我们通过一个技巧来绕开对它的依赖。思考一下,我们的分类模型给我们的结果 $P(B|A_1 A_2 … A_n)$ 是一个有特征 $A_1 A_2 … A_n$ 的对象属于某一类的可能性大小,并不是一个确定的分类结果,我们可以算出该对象属于第 $k$ 类的概率:$P(B_k|A_1 A_2 … A_n)$,并对所有的 $P(B_k|A_1 A_2 … A_n)$ 进行比较,将最大的那个,即可能性最大的分类结果作为最终的分类结果。而对每个 $P(B_k|A_i)$ 的计算,其分母 $P(A_1 A_2 … A_n)$ 都是相同的,故可以不将该分母代入计算,那么我们最终的分类器模型就变成了:

$$ \max{P(B_k|A_1 A_2 … A_n)}=\max{P(B_k)\prod_{i=1}^{n}{P(A_i|B_k)}} $$

应用示例

现在假设我们有1万人的姓名-性别数据,其中4500人为女生,5500人为男生,且名字里有「徐」字的男女生人数分别为10、20人,名字里有「坤」字的男女生人数为80、10人。将「名字」看成是不同的特征,「性别」看成是分类结果,于是就可以利用上式算出名字是「徐坤」的人是男生的概率为:

同理得到名字是「徐坤」的人是男生的概率为:

我们发现算出来的两个结果都非常的小,因为我们提供的数据的特征分布比较稀疏,计算出的结果很可能小到让计算机发生位溢出,为避免这种情况,对于二分问题,我们可以在计算前先做商,即:

$$ r=\frac{P(B_1|A_1 A_2 … A_n)}{P(B_2|A_1 A_2 … A_n)} $$

这样就都转换到整型数据的计算上了,对此我们可以合理地认为当 $r>1$ 时,分类到第一类,当 $r<1$ 时分类到第二类。对于上述例子:

$$ r=\biggl(\frac{5500}{10000}\times\frac{10}{5500}\times\frac{80}{5500}\biggr)\div\biggl(\frac{4500}{10000}\times\frac{20}{4500}\times\frac{10}{4500}\biggr) \approx 3.27 > 1 $$

故名字为「徐坤」的人被分类到男生中。

当然我们不一定要用 1 作为分类的界限,选择多少作为该界限可以通过跑测试数据集查看拟合程度,若发现大量男生被分类到女生,就降低界限,反之亦然。

拉普拉斯修正

细心的你一定发现了一个问题,如果我们的数据中没有名字里有坤字的男生的话,会导致 $r$ 分子为零,又或者没有名字里有坤字的女生,导致 $r$ 的分母为零,我们的模型就失效了。为避免这种极端的情况发生,我们可以在统计名字里有坤字的人个数时人为地加一来避免零的出现,对于我们的分类模型,就是:

$$ P(A_i|B_k)=\frac{第k类中有特征A_i的样本个数+1}{第k类样本个数+不同的特征个数} $$

其中「不同的特征个数」,在我们的例子中,就是指数据中不同的字的个数。这种对统计数据的处理就叫做拉普拉斯修正。

需要注意的是,若在计算中使用了拉普拉斯修正,则同时需要对先验概率进行修正,即

$$ P(B_k)=\frac{第k类样本个数+1}{样本总数+类别数} $$

对于二分类问题,「类别数」就为 2。

最后,关于对该性别预测例子的实现,其实有人早在几年前做了(见GitHub),并且公开了数据集(2000w条),可以拿来试试。该作者对最后一步概率的处理和博主描述的有所不同,从源码中可以看出,是将男女生的计算结果分别取了在其和的占比,间接地算出了是男、女生的概率,也是个不错的方法。


  1. 该例子取自毕导 - 我是如何判断室友是不是变态的?这要从贝叶斯概率说起 ↩︎

  2. 该特征相互独立的假设就是朴素贝叶斯分类器「朴素」的地方。 ↩︎

评论插件加载中 OvO