【sklearn朴素贝叶斯算法】高斯分布/多项式/伯努利贝叶斯算法以及代码实例

朴素贝叶斯

朴素贝叶斯方法是一组基于贝叶斯定理的监督学习算法,其“朴素”假设是:给定类别变量的每一对特征之间条件独立。贝叶斯定理描述了如下关系:
给定类别变量(y)以及属性值向量(x_1)(x_n)

(P(y mid x_1, dots, x_n) = frac{P(y) P(x_1, dots x_n mid y)} {P(x_1, dots, x_n)})

依据朴素条件独立假设可得:

(P(x_i mid y, x_1, dots, x_{i-1}, x_{i+1}, dots, x_n) = P(x_i mid y))

(i) 进行遍历,上式可化为:

(P(y mid x_1, dots, x_n) = frac{P(y) prod_{i=1}^{n} P(x_i mid y)} {P(x_1, dots, x_n)})

由于输入的(P(x_1, dots, x_n))是给定的常数值,我们可以得到以下式子:

(P(y mid x_1, dots, x_n) propto P(y) prod_{i=1}^{n} P(x_i mid y))

(hat{y} = argmax_y P(y) prod_{i=1}^{n} P(x_i mid y))

然后我们可以极大化后验估计(MAP),来估计(P(y))(P(x_i mid y)),前者就是训练集中类别(y)的相对频率。

不同的朴素贝叶斯分类器的区别主要在于它们对(P(x_i mid y))分布的假设不同。

尽管它们的假设显然过于简化,但naive Bayes分类器在许多实际情况下都能很好地工作,比如常见的文档分类和垃圾邮件过滤。
它们需要一些训练数据来估计必要的参数。

与其他更复杂的方法相比,朴素贝叶斯学习器和分类器执行速度非常快。类别条件特征分布的分解意味着每个分布都可以独立地作为一维分布进行估计。这反过来又有助于缓解组合爆炸的问题。

另一方面,尽管朴素贝叶斯被认为是一个不错的分类器,但它是一个糟糕的估计器,所以(predict\_proba)输出的概率并太靠谱。

1. 高斯朴素贝叶斯算法

(GaussianNB) 实现了高斯朴素贝叶斯分类算法。假设特征的似然为高斯分布:

(P(x_i mid y) = frac{1}{sqrt{2pisigma^2_y}} expleft(-frac{(x_i - mu_y)^2}{2sigma^2_y} ight))

参数(sigma_y)(mu_y)采用极大似然估计。

以鸢尾花分类为例:

from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
from sklearn.naive_bayes import GaussianNB
X, y = load_iris(return_X_y=True)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.5, random_state=0)
gnb = GaussianNB()
y_pred = gnb.fit(X_train, y_train).predict(X_test)
print("Number of mislabeled points out of a total %d points : %d" % (X_test.shape[0], (y_test != y_pred).sum()))
Number of mislabeled points out of a total 75 points : 4

2. 多项式贝叶斯算法

(MultinomialNB)实现了对多项式分布数据的朴素贝叶斯算法,是文本分类中使用的两种经典的朴素贝叶斯变体之一(其中数据通常表示为词向量计数,虽然(tf-idf)向量在实践中也很有效)。

这个分布的每个类别(y)的参数向量为( heta_y = ( heta_{y1},ldots, heta_{yn})),其中(n)是特征数量(在文本分类中是词典大小),( heta_{yi})是特征(i)在类别(y)的一个样本中出现的概率(P(x_i mid y))

参数( heta_y)由最大似然的平滑版本来估计,即相对频率计数:

(hat{ heta}_{yi} = frac{ N_{yi} + alpha}{N_y + alpha n})

其中(N_{yi} = sum_{x in T} x_i)是训练集(T)上特征(i)在类别(y)的一个样本中出现的次数。(N_{y} = sum_{i=1}^{n} N_{yi})是类(y)的所有特征的总数。

平滑先验(alpha ge 0)让学习样本中不存在的特征占一定的比例,并防止在进一步的计算中出现零概率。

(alpha = 1)时为拉普拉斯(Laplace)平滑,(alpha < 1)时为李德斯通(Lidstone)平滑。

以鸢尾花分类为例:

from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
from sklearn.naive_bayes import ComplementNB
X, y = load_iris(return_X_y=True)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.5, random_state=0)
cnb = ComplementNB()
y_pred = cnb.fit(X_train, y_train).predict(X_test)
print("Number of mislabeled points out of a total %d points : %d" % (X_test.shape[0], (y_test != y_pred).sum()))
Number of mislabeled points out of a total 75 points : 30

3. 伯努利贝叶斯算法

(BernoulliNB)是对按多元伯努利分布的数据,实现朴素贝叶斯训练和分类的算法,即,可能有多个特征,但每个特征都被假定为一个二元(伯努利,布尔)变量。因此,该类别要求样本用二值特征向量表示;如果传递任何其他类型的数据,(BernoulliNB)的实例可以对该输入进行二值化(取决于二值参数)。

基于贝叶斯的决策规则:

(P(x_i mid y) = P(i mid y) x_i + (1 - P(i mid y)) (1 - x_i))

它与多项式NB规则的不同之处在于,它显式地惩罚了类别(y)的指标特征(i)的不出现,而多项式贝叶斯变体将简单地忽略一个不出现的特征。

在文本分类的应用中,可以使用单词出现向量(而不是单词计数向量)来训练和使用这个分类器。BernoulliNB可能在某些数据集上表现得更好,特别是那些文档更短的数据集。如果时间允许,最好对两个模型都进行评估。

以鸢尾花分类为例:

from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
from sklearn.naive_bayes import BernoulliNB
X, y = load_iris(return_X_y=True)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.5, random_state=0)
bnb = BernoulliNB()
y_pred = bnb.fit(X_train, y_train).predict(X_test)
print("Number of mislabeled points out of a total %d points : %d" % (X_test.shape[0], (y_test != y_pred).sum()))
Number of mislabeled points out of a total 75 points : 54

参考文档

scikit-learn 1.9.1, 1.9.2, 1.9.4 Gaussian/Multinomial/Complement Naive Bayes