朴素贝叶斯的三个常用模型:高斯、多项式、伯努利

2014-10-12

朴素贝叶斯是一个很不错的分类器,在使用朴素贝叶斯分类器划分邮件有关于朴素贝叶斯的简单介绍。

一个样本有n个特征,分别用[latex]x_{1},x_{2},…,x_{n}[/latex]表示,将其划分到类[latex]y_{k}[/latex]的可能性[latex]P(y_{k}|x_{1},x_{2},…,x_{n})[/latex]为:

[latex]
P(y_{k}|x_{1},x_{2},…,x_{n}) = P(y_{k})\prod_{i=1}^{n}P(x_{i}|y_{k})
[/latex]

上式中等号右侧的各个值可以通过训练得到。根据上面的公式可以求的某个数据属于各个分类的可能性(这些可能性之和不一定是1),该数据应该属于具有最大可能性的分类中。

一般来说,如果一个样本没有特征[latex]x_{i}[/latex],那么[latex]P(x_{i}|y_{k})[/latex]将不参与计算。不过下面的伯努利模型除外。

以上是朴素贝叶斯的最基本的内容。

高斯模型


有些特征可能是连续型变量,比如说人的身高,物体的长度,这些特征可以转换成离散型的值,比如如果身高在160cm以下,特征值为1;在160cm和170cm之间,特征值为2;在170cm之上,特征值为3。也可以这样转换,将身高转换为3个特征,分别是f1、f2、f3,如果身高是160cm以下,这三个特征的值分别是1、0、0,若身高在170cm之上,这三个特征的值分别是0、0、1。不过这些方式都不够细腻,高斯模型可以解决这个问题。高斯模型假设这些一个特征的所有属于某个类别的观测值符合高斯分布,也就是:

[latex]
P(x_{i}|y_{k}) = \frac{1}{\sqrt{2\pi\sigma_{y_{k}}^{2}}}exp( -\frac{(x_{i}-\mu_{y_{k}})^2} {2\sigma_{y_{k}}^{2}} )
[/latex]

下面看一个sklearn中的示例:

>>> from sklearn import datasets
>>> iris = datasets.load_iris()
>>> iris.feature_names  # 四个特征的名字
['sepal length (cm)', 'sepal width (cm)', 'petal length (cm)', 'petal width (cm)']
>>> iris.data
array([[ 5.1,  3.5,  1.4,  0.2],
       [ 4.9,  3. ,  1.4,  0.2],
       [ 4.7,  3.2,  1.3,  0.2],
       [ 4.6,  3.1,  1.5,  0.2],
       [ 5. ,  3.6,  1.4,  0.2],
       [ 5.4,  3.9,  1.7,  0.4],
       [ 4.6,  3.4,  1.4,  0.3],
       [ 5. ,  3.4,  1.5,  0.2],
       ......
       [ 6.5,  3. ,  5.2,  2. ],
       [ 6.2,  3.4,  5.4,  2.3],
       [ 5.9,  3. ,  5.1,  1.8]]) #类型是numpy.array
>>> iris.data.size  
600  #共600/4=150个样本
>>> iris.target_names
array(['setosa', 'versicolor', 'virginica'], 
      dtype='|S10')
>>> iris.target
array([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,....., 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, ......, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2])
>>> iris.target.size
150
>>> from sklearn.naive_bayes import GaussianNB
>>> clf = GaussianNB()
>>> clf.fit(iris.data, iris.target)
>>> clf.predict(iris.data[0])
array([0])   # 预测正确
>>> clf.predict(iris.data[149])
array([2])   # 预测正确
>>> data = numpy.array([6,4,6,2])
>>> clf.predict(data)
array([2])  # 预测结果很合理

多项式模型


该模型常用于文本分类,特征是单词,值是单词的出现次数。

[latex]
P(x_{i}|y_{k}) = \frac{N_{y_{k}x_{i}}+\alpha}{N_{y_{k}}+\alpha n}
[/latex]

其中,[latex]N_{y_{k}x_{i}}[/latex]是类别[latex]y_{k}[/latex]下特征[latex]x_{i}[/latex]出现的总次数;[latex]N_{y_{k}}[/latex]是类别[latex]y_{k}[/latex]下所有特征出现的总次数。对应到文本分类里,如果单词word在一篇分类为label1的文档中出现了5次,那么[latex]N_{label1,word}[/latex]的值会增加5。如果是去除了重复单词的,那么[latex]N_{label1,word}[/latex]的值会增加1。[latex]n[/latex]是特征的数量,在文本分类中就是去重后的所有单词的数量。[latex]\alpha[/latex]的取值范围是[0,1],比较常见的是取值为1。

待预测样本中的特征[latex]x_{i}[/latex]在训练时可能没有出现,如果没有出现,则[latex]N_{y_{k}x_{i}}[/latex]值为0,如果直接拿来计算该样本属于某个分类的概率,结果都将是0。在分子中加入[latex]\alpha[/latex],在分母中加入[latex]\alpha n[/latex]可以解决这个问题。

下面的代码来自sklearn的示例:

>>> import numpy as np
>>> X = np.random.randint(5, size=(6, 100))
>>> y = np.array([1, 2, 3, 4, 5, 6])
>>> from sklearn.naive_bayes import MultinomialNB
>>> clf = MultinomialNB()
>>> clf.fit(X, y)
MultinomialNB(alpha=1.0, class_prior=None, fit_prior=True)
>>> print(clf.predict(X[2]))
[3]

值得注意的是,多项式模型在训练一个数据集结束后可以继续训练其他数据集而无需将两个数据集放在一起进行训练。在sklearn中,MultinomialNB()类的partial_fit()方法可以进行这种训练。这种方式特别适合于训练集大到内存无法一次性放入的情况。

在第一次调用partial_fit()时需要给出所有的分类标号。

>>> import numpy
>>> from sklearn.naive_bayes import MultinomialNB
>>> clf = MultinomialNB() 
>>> clf.partial_fit(numpy.array([1,1]), numpy.array(['aa']), ['aa','bb'])
GaussianNB()
>>> clf.partial_fit(numpy.array([6,1]), numpy.array(['bb']))
GaussianNB()
>>> clf.predict(numpy.array([9,1]))
array(['bb'], 
      dtype='|S2')

伯努利模型


伯努利模型中,对于一个样本来说,其特征用的是全局的特征。

在伯努利模型中,每个特征的取值是布尔型的,即true和false,或者1和0。在文本分类中,就是一个特征有没有在一个文档中出现。

如果特征值[latex]x_{i}[/latex]值为1,那么

[latex]
P(x_{i}|y_{k}) = P(x_{i}=1|y_{k})
[/latex]

如果特征值[latex]x_{i}[/latex]值为0,那么

[latex]
P(x_{i}|y_{k}) = 1-P(x_{i}=1|y_{k})
[/latex]

这意味着,“没有某个特征”也是一个特征。
下面的示例来自sklearn官方文档:

>>> import numpy as np
>>> X = np.random.randint(2, size=(6, 100))
>>> Y = np.array([1, 2, 3, 4, 4, 5])
>>> from sklearn.naive_bayes import BernoulliNB
>>> clf = BernoulliNB()
>>> clf.fit(X, Y)
BernoulliNB(alpha=1.0, binarize=0.0, class_prior=None, fit_prior=True)
>>> print(clf.predict(X[2]))
[3]

BernoulliNB()类也有partial_fit()函数。

多项式模型和伯努利模型在文本分类中的应用


基于naive bayes的文本分类算法给出了很好的解释。

在多项式模型中:

在多项式模型中, 设某文档d=(t1,t2,…,tk),tk是该文档中出现过的单词,允许重复,则

先验概率P(c)= 类c下单词总数/整个训练样本的单词总数

类条件概率P(tk|c)=(类c下单词tk在各个文档中出现过的次数之和+1)/(类c下单词总数+|V|)

V是训练样本的单词表(即抽取单词,单词出现多次,只算一个),|V|则表示训练样本包含多少种单词。 P(tk|c)可以看作是单词tk在证明d属于类c上提供了多大的证据,而P(c)则可以认为是类别c在整体上占多大比例(有多大可能性)。

在伯努利模型中:

P(c)= 类c下文件总数/整个训练样本的文件总数

P(tk|c)=(类c下包含单词tk的文件数+1)/(类c下单词总数+2)

参考


http://scikit-learn.org/stable/modules/naive_bayes.html

http://scikit-learn.org/stable/modules/generated/sklearn.naive_bayes.GaussianNB.html

http://scikit-learn.org/stable/modules/generated/sklearn.naive_bayes.MultinomialNB.html

http://scikit-learn.org/stable/modules/generated/sklearn.naive_bayes.BernoulliNB.html

http://cn.soulmachine.me/blog/20100528/