type
status
date
slug
summary
tags
category
icon
password
Property
原理
在所有的机器学习分类算法中,朴素贝叶斯和其他绝大多数的分类算法都不同。对于大多数的分类算法,比如决策树,KNN,逻辑回归,支持向量机等,都是判别方法,也就是直接学习出特征输出和特征之间的关系,要么是决策函数,要么是条件分布 。但是朴素贝叶斯却是生成方法,也就是直接找出特征输出和特征的联合分布,然后用得出。
朴素贝叶斯很直观,计算量也不大,在很多领域有广泛的应用。
朴素贝叶斯相关的统计学知识
贝叶斯学派很古老,但是从诞生到一百年前一直不是主流。主流是频率学派。频率学派的权威皮尔逊和费歇尔都对贝叶斯学派不屑一顾,但是贝叶斯学派硬是凭借在现代特定领域的出色应用表现为自己赢得了半壁江山。
贝叶斯学派的思想可以概括为先验概率+数据=后验概率。也就是说在实际问题中需要得到的后验概率,可以通过先验概率和数据一起综合得到。数据好理解,被频率学派攻击的是先验概率,一般来说先验概率就是我们对于数据所在领域的历史经验,但是这个经验常常难以量化或者模型化,于是贝叶斯学派大胆的假设先验分布的模型,比如正态分布,beta分布等。这个假设一般没有特定的依据,因此一直被频率学派认为很荒谬。虽然难以从严密的数学逻辑里推出贝叶斯学派的逻辑,但是在很多实际应用中,贝叶斯理论很好用,比如垃圾邮件分类,文本分类。
条件独立公式,如果和相互独立,则有:
条件概率公式:
全概率公式
其中
贝叶斯公式:
朴素贝叶斯的模型
假如分类模型样本是:
个样本,每个样本有个特征;特征输出有个类别,定义为
从样本可以学习得到朴素贝叶斯的先验分布:
接着学习到条件概率分布:
然后就可以用贝叶斯公式得到X和Y的联合分布了,联合分布定义为:
从上面的式子可以看出 比较容易通过最大似然法求出,得到的 就是类别 在训练集里面出现的频数。但是 很难求出,这是一个超级复杂的有个维度的条件分布。
朴素贝叶斯模型在这里做了一个大胆的假设,即的个维度之间相互独立,这样就可以得出:
从上式可以看出,这个很难的条件分布大大的简化了,但是这也可能带来预测的不准确性。如果特征之间非常不独立怎么办?如果真是非常不独立的话,那就尽量不要使用朴素贝叶斯模型了,考虑使用其他的分类方法比较好。但是一般情况下,样本的特征之间独立这个条件的确是弱成立的,尤其是数据量非常大的时候。虽然牺牲了准确性,但是得到的好处是模型的条件分布的计算大大简化了,这就是贝叶斯模型的选择。
回到要解决的问题,给定测试集的一个新样本特征 ,如何判断它属于哪个类型?
既然是贝叶斯模型,当然是后验概率最大化来判断分类了。只要计算出所有的个条件概率 ,然后找出最大的条件概率对应的类别,这就是朴素贝叶斯的预测了。
朴素贝叶斯的推断过程
预测的类别 是使最大化的类别,数学表达式为:
由于对于所有的类别计算 时,上式的分母是一样的,都是 ,因此预测公式可以简化为:
接着利用朴素贝叶斯的独立性假设,就可以得到通常意义上的朴素贝叶斯推断公式:
朴素贝叶斯的参数估计
只要求出,通过比较就可以得到朴素贝叶斯的推断结果。
对于 ,比较简单,通过极大似然估计我们很容易得到 为样本类别出现的频率,即样本类别出现的次数除以样本总数。
对于 ,这个取决于先验条件:
- 如果是离散的值,那么可以假设符合多项式分布,这样得到 是在样本类别中,特征 出现的频率,即:
为样本类别总的特征计数, 为类别为的样本中,第维特征出现的计数。
某些时候,可能某些类别在样本中没有出现,这样可能导致 为0,这样会影响后验的估计,为了解决这种情况,引入了拉普拉斯平滑,即此时有:
其中为一个大于0的常数,常常取为1。 为第个特征的取值个数
- 如果是非常稀疏的离散值,即各个特征出现概率很低,这时可以假设符合伯努利分布,即特征出现记为1,不出现记为0。即只要出现即可,不关注的次数。
这样得到 是在样本类别中, 出现的频率。
此时有:
其中, 取值为0和1
- 如果是连续值,通常取的先验概率为正态分布,即在样本类别中,的值符合正态分布。这样 的概率分布是:
和 是正态分布的期望和方差,可以通过极大似然估计求得。 为在样本类别中,所有的平均值。为在样本类别 中,所有的方差。对于一个连续的样本值,带入正态分布的公式,就可以求出概率分布了。
朴素贝叶斯算法过程
假设训练集为个样本个维度,如下:
共有个特征输出类别,分别为 ,每个特征输出类别的样本个数为 ,在第个类别中,如果是离散特征,则特征各个类别取值为。其中取值为, 为特征不同的取值数。
输出为实例的分类。
算法流程如下:
- 若没有的先验概率,计算的个先验概率:,否则为输入的先验概率。
- 分别计算第个类别的第维特征的第个取值条件概率:
- 如果是离散值:
- 如果是稀疏二项离散值:
- 如果是连续值不需要计算各个l的取值概率,直接求正态分布的参数:
可以取值为1,或者其他大于0的数字。
此时只有两种取值
需要求出 和 。 为在样本类别中,所有的平均值。 为在样本类别中,所有的方差。
- 对于实例 ,分别计算:
- 确定实例 的分类
没有复杂的求导和矩阵运算,因此效率很高。
朴素贝叶斯算法小结
朴素贝叶斯的主要优点有:
- 朴素贝叶斯模型发源于古典数学理论,有稳定的分类效率
- 对小规模的数据表现很好,能个处理多分类任务,适合增量式训练,尤其是数据量超出内存时,我们可以一批批的去增量训练
- 对缺失数据不太敏感,算法也比较简单,常用于文本分类
朴素贝叶斯的主要缺点有:
- 理论上,朴素贝叶斯模型与其他分类方法相比具有最小的误差率。但是实际上并非总是如此,这是因为朴素贝叶斯模型给定输出类别的情况下,假设属性之间相互独立,这个假设在实际应用中往往是不成立的,在属性个数比较多或者属性之间相关性较大时,分类效果不好。而在属性相关性较小时,朴素贝叶斯性能最为良好。对于这一点,有半朴素贝叶斯之类的算法通过考虑部分关联性适度改进
- 需要知道先验概率,且先验概率很多时候取决于假设,假设的模型可以有很多种,因此在某些时候会由于假设的先验模型的原因导致预测效果不佳
- 由于我们是通过先验和数据来决定后验的概率从而决定分类,所以分类决策存在一定的错误率
- 对输入数据的表达形式很敏感
补充
朴素贝叶斯擅长处理文本分类,这是根据朴素贝叶斯的什么性质得到的呢?
朴素贝叶斯模型给定输出类别的情况下,假设属性之间相互独立,所以如果属性之间的独立性越强,朴素贝叶斯的算法效果也就越好。对于文本来说,一般分词后 词和词之间的关联性较低,因此效果会更好。这个是相比用于一些基于非文本的数值特征来说的, 一般数值特征之间的关联性会较强,不适合朴素贝叶斯
既然朴素贝叶斯对输入数据的独立性有要求,那么是不是可以先PCA一下然后再试试呢?
对已经拿到的训练数据来进行PCA,这样得到了主成分仅仅针对你这些训练数据。并不能很好的代表真实情况下的特征相关性。如果训练数据覆盖不全或者较少时, PCA的结果甚至可能和真实情况完全不同。所以PCA不能帮你完全解决特征独立性的问题。
做了PCA后的特征已经不可解释,朴素贝叶斯的解释性也丧失了
朴素贝叶斯对数据的表现形式很敏感
朴素贝叶斯是一个简单的基于特征进行统计的模型,因此数据的表现形式是连续特征,离散特征还是二元特征都会对模型的概率计算结果产生很大的影响,进而对基于特征的预测结果产生影响。
代码
从零实现高斯模型
scikit-learn实现
在scikit-learn中,一共有3个朴素贝叶斯的分类算法类,分别是
GaussianNB
,MultinomialNB
和BernoulliNB
。其中GaussianNB
就是先验为高斯分布的朴素贝叶斯,MultinomialNB
就是先验为多项式分布的朴素贝叶斯,而BernoulliNB
就是先验为伯努利分布的朴素贝叶斯这三个类适用的分类场景各不相同,一般来说,如果样本特征的分布大部分是连续值,使用GaussianNB会比较好。如果如果样本特征的分大部分是多元离散值,使用MultinomialNB比较合适。而如果样本特征是二元离散值或者很稀疏的多元离散值,应该使用BernoulliNB
GaussianNB
GaussianNB假设特征的先验概率为正态分布,即如下式:
其中 为Y的第k类类别, 和为需要从训练集估计的值。
GaussianNB会根据训练集求出和 。 为在样本类别中,所有的平均值。 为在样本类别中,所有的方差。
GaussianNB类的主要参数仅有一个,即先验概率priors ,对应Y的各个类别的先验概率。这个值默认不给出,如果不给出此时 。其中 为训练集样本总数量, 为输出为第类别的训练集样本数。如果给出的话就以priors 为准。
在使用GaussianNB的fit方法拟合数据后可以进行预测,预测有三种方法,包括predict,predict_log_proba和predict_proba:
predict
方法就是最常用的预测方法,直接给出测试集的预测类别输出predict_proba
则不同,它会给出测试集样本在各个类别上预测的概率。容易理解,predict_proba预测出的各个类别概率里的最大值对应的类别,也就是predict方法得到类别。predict_log_proba
和predict_proba类似,它会给出测试集样本在各个类别上预测的概率的一个对数转化。转化后predict_log_proba预测出的各个类别对数概率里的最大值对应的类别,也就是predict方法得到类别。结果如下:
从上面的结果可以看出,测试样本[-0.8,-1]的类别预测为类别1。具体的测试样本[-0.8,-1]被预测为1的概率为9.99999949e-01 ,远远大于预测为2的概率5.05653254e-08。
此外,GaussianNB一个重要的功能是有
partial_fit
方法,这个方法的一般用在如果训练集数据量非常大,一次不能全部载入内存的时候。这时我们可以把训练集分成若干等分,重复调用partial_fit来一步步的学习训练集,非常方便。MultinomialNB和BernoulliNB也有类似的功能。MultinomialNB
MultinomialNB假设特征的先验概率为多项式分布,即如下式:
其中, 是第k个类别的第j维特征的第个个取值条件概率。 是训练集中输出为第k类的样本个数。 为一个大于0的常数,常常取为1,即拉普拉斯平滑。也可以取其他值。
MultinomialNB参数比GaussianNB多,但是一共也只有仅仅3个。其中,参数alpha即为上面的常数 ,如果你没有特别的需要,用默认的1即可。如果发现拟合的不好,需要调优时,可以选择稍大于1或者稍小于1的数。布尔参数fit_prior表示是否要考虑先验概率,如果是false,则所有的样本类别输出都有相同的类别先验概率。否则可以自己用第三个参数class_prior输入先验概率,或者不输入第三个参数class_prior让MultinomialNB自己从训练集样本来计算先验概率,此时的先验概率为。其中m为训练集样本总数量, 为输出为第k类别的训练集样本数。总结如下:
fit_prior | class_prior | 最终先验概率 |
false | 填或者不填没有意义 | |
true | 不填 | |
true | 填 | =class_prior |
在使用MultinomialNB的fit方法或者partial_fit方法拟合数据后可以进行预测。此时预测有三种方法,包括predict,predict_log_proba和predict_proba,和GaussianNB完全一样。
BernoulliNB
BernoulliNB假设特征的先验概率为二元伯努利分布,即如下式:
此时只有两种取值, 只能取值0或者1。
BernoulliNB一共有4个参数,其中3个参数的名字和意义和MultinomialNB完全相同。唯一增加的一个参数是binarize。这个参数主要是用来帮BernoulliNB处理二项分布的,可以是数值或者不输入。如果不输入,则BernoulliNB认为每个数据特征都已经是二元的。否则的话,小于binarize的会归为一类,大于binarize的会归为另外一类。
在使用BernoulliNB的fit或者partial_fit方法拟合数据后,我们可以进行预测。此时预测有三种方法,包括predict,predict_log_proba和predict_proba。