朴素贝叶斯

0、概述

朴素贝叶斯是贝叶斯理论的一部分,所以讲述这部分内容之前首先需要了解一下贝叶斯定理。
贝叶斯定理是关于随机事件A和B的条件概率(或边缘概率)的一则定理。其中P(A|B)是在B发
生的情况下A发生的可能性。
描述两个条件概率之间的关系,比如 P(A|B) 和 P(B|A)。
按照乘法法则,可以立刻导出:
P(A∩B) = P(A)*P(B|A) = P(B)*P(A|B)
如上公式也可变形为:
P(B|A) = P(A|B)*P(B)/P(A)

朴素贝叶斯分类器基于一个简单的假定:给定目标值时属性之间相互条件独立。

贝叶斯公式

1、介绍

1.1、工作原理

假设每个特征对于决定样本属于哪一类都同等重要。给定一个测试样本w,计算它属于c的概
率,只需要计算出训练样本中类别c的每个特征类型的概率p(w|c),所有训练样本中类别c的
概率p(c),测试样本w的概率(实际使用中比较样本w属于哪个类别的可能性更大,等号两边相等)
p(c|w) = p(w|c)p(c)/p(w)

1.2、优点,缺点,适用范围

优点:在数据较少的情况下仍然有效,可以处理多类别问题。
缺点:对于输入数据的准备方式较为敏感。
适用范围:标称型数据。

1.3、一般流程

收集数据:可以使用任何方法。
准备数据:需要数值型或者布尔型数据。
分析数据:有大量特征时,绘制特征作用不大,此时使用直方图效果更好。
训练算法:计算不同的独立特征的条件概率。
测试算法:计算错误率。
使用算法:常用于文档分类。可以在任意的分类场景中使用朴素贝叶斯分类器,不一定非要是文本。

2、实现

2.1、伪代码

1
2
3
4
5
6
7
8
9
计算每个类别中的文档数目
对每篇训练文档:
对每个类别:
如果词条出现文档中 -> 增加该词条的计数值
增加所有词条的计数值
对每个类别:
对每个词条:
将该词条的数目数除以总词条数目得到条件概率
返回每个类别的条件概率

2.2、python实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
def createVocabList(dataSet):
vocabSet = set([])
for document in dataSet:
vocabSet = vocabSet | set(document)
return list(vocabSet)

def setOfWords2Vec(vocabList,inputSet):
returnVec = [0]*len(vocabList)
for word in inputSet:
if word in vocabList:
returnVec[vocabList.index(word)] = 1
else: print("the word: %s is no in my Vocabulary!"%word)
return returnVec

def bagOfWords2VecMN(vocabList,inputSet):
'''
单个单词出现多次的场景
:param vocabList:单词集合
:param inputSet:输入的句子
:return:
'''
returnVec = [0]*len(vocabList)
for word in inputSet:
if word in vocabList:
returnVec[vocabList.index(word)] += 1
else: print("the word: %s is no in my Vocabulary!" % word)
return returnVec

def trainNB0(trainMatrix,trainCategory):
'''

:param trainMatrix:文档矩阵
:param trainCategory:文档标签向量
:return:
'''
# 计算样本数
numTrainDocs = len(trainMatrix)
# 计算单词数
numWords = len(trainMatrix[0])
# 计算所有样本中侮辱言论的概率
pAbusive = sum(trainCategory)/float(numTrainDocs)
# 避免个别单词不出现,导致计算概率为0,默认都出现一次。
p0Num = ones(numWords);p1Num = ones(numWords)
p0Denom = 2.0; p1Denom = 2.0
for i in range(numTrainDocs):
# 轮询所有样本
if trainCategory[i] == 1:
# 所有侮辱性言论
# 侮辱性言论中,每个单词使用的次数
p1Num += trainMatrix[i]
# 侮辱性言论中,所有单词的出现次数
p1Denom += sum(trainMatrix[i])
else:
# 所有正常言论
# 正常言论中,每个单词使用的次数
p0Num += trainMatrix[i]
# 正常言论中,所有单词的出现次数
p0Denom += sum(trainMatrix[i])
p1Vect = log(p1Num / p1Denom)
p0Vect = log(p0Num / p0Denom)
return p0Vect,p1Vect,pAbusive

def classifyNB(vec2Classify,p0Vec,p1Vec,pClass1):
# p(c1|w) = p(w|c1)p(c1)/p(w)
# p(c0|w) = p(w|c0)p(c0)/p(w)
# p0Vec,p1Vec已经log过的。此处缺少除以单词本身出现的概率p(w)。p0,p1都需要除以p(w)可约去
p1 = sum(vec2Classify * p1Vec)+log(pClass1)
p0 = sum(vec2Classify * p0Vec)+log(1 - pClass1)
if p1 > p0:
return 1
else:
return 0

3、总结

巧妙的运用概率的方法解决分类问题,朴素贝叶斯降低了条件概率计算的复杂度,并且正确率很好。
坚持原创技术分享,您的支持将鼓励我继续创作!