对于分类问题,其实谁都不会陌生,日常生活中我们每天都进行着分类过程。例如,当你看到一个人,你的脑子下意识判断他是学生还是社会上的人;你可能经常会走在路上对身旁的朋友说“这个人一看就很有钱。”之类的话,其实这就是一种分类操作。
朴素贝叶斯算法概述
贝叶斯分类是一类分类算法的总称,这类算法均以贝叶斯定理为基础,故统称为贝叶斯分类。而朴素朴素贝叶斯分类是贝叶斯分类中最简单,也是常见的一种分类方法。
朴素贝叶斯算法仍然是流行的十大挖掘算法之一,该算法是有监督的学习算法,解决的是分类问题,如客户是否流失、是否值得投资、信用等级评定等多分类问题。该算法的优点在于简单易懂、学习效率高、在某些领域的分类问题中能够与决策树、神经网络相媲美。
基本概念
概率(Probability)
- 概率定义:一件事情发生的可能性。
- P(X):取值在[0, 1]
条件概率
- 定义:就是事件A在另外一个事件B已经发生条件下的发生概率。
- 记作:P(A|B)
联合概率
- 定义:包含多个条件,且所有条件同时成立的概率。
- 记作: P(A, B)
相互独立
- 定义:如果P(A, B)= P(A)P(B),则称事件A与事件B相互独立。
- P(A, B)= P(A)P(B) <=>事件A与事件B相互独立。
贝叶斯公式

朴素贝叶斯公式
贝叶斯和朴素贝叶斯的概念是不同的,区别就在于“朴素”二字。
朴素贝叶斯假设:假设有n个特征,且特征与特征之间是相互独立的。
根据这个假设,可以得到:
P(b1,b2,..,bn) = P(b1) * P(b2) * … * P(bn)
P(b1,b2,..,bn|A) = P(b1|A) * P(b2|A) * … * (bn|A)
最后我们可以把

改写成

由于该算法基于朴素贝叶斯理论,所以自变量之间的独立(条件特征独立)性和连续变量的正态性假设为前提,就会导致算法精度在某种程度上受影响。
算法特点
优点
- 朴素贝叶斯模型发源于古典数学理论,有稳定的分类效率。
- 对小规模的数据表现很好,能个处理多分类任务,适合增量式训练,尤其是数据量超出内存时,我们可以一批批的去增量训练。
- 对缺失数据不太敏感,算法也比较简单,常用于文本分类。
缺点
- 理论上,朴素贝叶斯模型与其他分类方法相比具有最小的误差率。但是实际上并非总是如此,这是因为朴素贝叶斯模型给定输出类别的情况下,假设属性之间相互独立,这个假设在实际应用中往往是不成立的,在属性个数比较多或者属性之间相关性较大时,分类效果不好。而在属性相关性较小时,朴素贝叶斯性能最为良好。对于这一点,有半朴素贝叶斯之类的算法通过考虑部分关联性适度改进。
- 需要知道先验概率,且先验概率很多时候取决于假设,假设的模型可以有很多种,因此在某些时候会由于假设的先验模型的原因导致预测效果不佳。
- 由于我们是通过先验和数据来决定后验的概率从而决定分类,所以分类决策存在一定的错误率。
- 对输入数据的表达形式很敏感。
适用数据类型
- 标称型数据。
朴素贝叶斯的一般过程
- 收集数据:可以使用任何方法。
- 准备数据:需要数值型或者布尔型数据。
- 分析数据:有大量特征时,绘制特征作用不大,此时使用直方图效果更好。
- 训练算法:计算不同的独立特征的条件概率。
- 测试算法:计算错误率。
- 使用算法:一个常见的朴素贝叶斯应用是文档分类。可以在任意的分类场景中使用朴素贝叶斯分类器,不一定非要是文本。
实施朴素贝叶斯算法
Python核心代码如下:
def trainNB0(trainMat, classVec):
numTrainDocs = len(trainMat)
numWords = len(trainMat[0])
pAbusive = sum(classVec)/float(numTrainDocs)
p0Num = np.ones(numWords)
p1Num = np.ones(numWords)
p0Denom = 2.0
p1Denom = 2.0
for i in range(numTrainDocs):
if classVec[i] == 1:
p1Num += trainMat[i]
p1Denom += sum(trainMat[i])
else:
p0Num += trainMat[i]
p0Denom += sum(trainMat[i])
p1Vect = np.log(p1Num/p1Denom)
p0Vect = np.log(p0Num/p0Denom)
return p0Vect, p1Vect, pAbusive
def classifyNB(testEntry, p0Vect, p1Vect, pAbusive, vocabList):
testMat = setOfWords2Vec(vocabList, testEntry)
p1 = np.sum(testMat * p1Vect, axis=1) + np.log(pAbusive)
p0 = np.sum(testMat * p0Vect, axis=1) + np.log(1.0-pAbusive)
result = [0]*len(testEntry)
for i in range(len(testMat)):
print("p1=%.2f,p0=%.2f" % (p1[i], p0[i]))
if p1[i] > p0[i]:
result[i] = 1
return result
函数说明:朴素贝叶斯分类器训练函数
Parameters:
trainMat – 训练文档矩阵
classVec – 训练类别标签向量
Returns:
p0Vect – 非C类的条件概率数组
p1Vect – C类的条件概率数组
pAbusive – 文档属于C类的概率
函数说明:朴素贝叶斯分类器分类函数
Parameters:
testEntry – 待分类的词条数组
p0Vec – C类的条件概率数组
p1Vec – 非C类的条件概率数组
Returns:
0 – 属于非C类
1 – 属于C类