一、概述
1. 原理:
- 工作机制:
2. 优缺点
- 优点:在数据少的情况下有效,可以处理多类别问题
- 缺点:对于输入数据的准备方式较为敏感
- 适用数据范围:标称型数据
3.条件概论:
- 在B的条件下A出现的概率。
p(A|B)=p(AB)/p(B)
- 交换条件中的条件与结果:
p(B|A)=p(A|B)*p(B)/p(A)
4.贝叶斯决策理论的核心思想:
- 选择具有最高概论的决策
5.朴素贝叶斯算法的两个假设:
- (1)每个特征之间都是独立的,这就使得公式:
p((f1,f2,...fn)|c)=p(f1|c)p(f2|c)...p(fn|c)
- (2)每个特征同等重要,我们拿文本分类做例子,把文档中的单词作为特征。这种假设使得我们在进行分类的过程中无需考虑单词出现的次数,只考虑单词出现与否。这也就贝叶斯算法的贝努利模型实现方式。
- 注:贝叶斯的另一种实现方式为多项式模型,在这种模型中则需要考虑单词的出现次数。
二、算法流程
- 收集数据:可用任何方法
- 准备数据:需要数值型或者布尔型数据
- 分析数据:有大量特征时,绘制特征作用不大,此时使用直方图效果更好
- 训练算法:计算不同的独立特征的条件概率
- 测试算法:计算错误率
- 使用算法:一个常见的朴素贝叶斯应用是文档分类。可以在任意的分类场景中使用朴素贝叶斯分类器,不一定非要是文本。
三、算法实践
1.问题
- 对是否属于侮辱性文章进行分类
2.准备数据:从文本中构建词向量
- 准备数据
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# 产生训练数据
def loadDataSet():
# 该数据取自某狗狗论坛的留言版
postingList=[['my', 'dog', 'has', 'flea', 'problems', 'help', 'please'],
['maybe', 'not', 'take', 'him', 'to', 'dog', 'park', 'stupid'],
['my', 'dalmation', 'is', 'so', 'cute', 'I', 'love', 'him'],
['stop', 'posting', 'stupid', 'worthless', 'garbage'],
['mr', 'licks', 'ate', 'my', 'steak', 'how', 'to', 'stop', 'him'],
['quit', 'buying', 'worthless', 'dog', 'food', 'stupid']]
# 标注每条数据的分类,这里0表示正常言论,1表示侮辱性留言
classVec = [0, 1, 0, 1, 0, 1]
return postingList, classVec
# 建立词汇表
def createVocabList(dataSet):
# 首先建立一个空集
vocabSet = set([])
# 遍历数据集中的每条数据
for document in dataSet:
# 这条语句中首先统计了每条数据的词汇集,然后与总的词汇表求并集
vocabSet = vocabSet | set(document)
return list(vocabSet)
# 按照词汇表解析输入
def setOfWords2Vec(vocabList, inputSet):
# 创建一个跟词汇表(vocabList)等长的向量,并将其元素都设为0
returnVec = [0]*len(vocabList)
# 遍历输入,将含有词汇表单词的文档向量设为1
for word in inputSet:
if word in vocabList:
returnVec[vocabList.index(word)] = 1
else:
print("the word:%s is not in my vocabulary!" % word)
return returnVec
1 | 命令行 |
3.训练算法:从词向量计算概率
1 | # 朴素贝叶斯分类器训练函数 |
1 | >> import bayes |
4.测试算法: 朴素贝叶斯分类函数
1 | # 朴素贝叶斯分类函数 |
- 该函数是用来测试(封装了一些操作)
1
2
3
4
5
6
7
8
9
10
11
12
13
14#内嵌测试函数
def testingNB():
listOPosts, listClasses=loadDataSet()
myVocabList = createVocabList(listOPosts)
trainMat = []
for postinDoc in listOPosts:
trainMat.append(setOfWords2Vec(myVocabList, postinDoc))
p0V, p1V, p1 = trainNB0(trainMat, listClasses)
testEntry = ['love', 'my', 'dalmation']
thisDoc = setOfWords2Vec(myVocabList, testEntry)
print(testEntry, "classified as:", classifyNB(thisDoc, p0V, p1V, p1))
testEntry = ['garbage', 'stupid']
thisDoc = setOfWords2Vec(myVocabList, testEntry)
print(testEntry, "classified as:", classifyNB(thisDoc, p0V, p1V, p1))
1 | 命令行 |
5.词袋模型的转换函数(准备数据中优化)
- 之前的算法我们只考虑了单词出现与否,使用的是一种词集模型。
- 贝叶斯有两种实现方式,另一种多项式模型,需要考虑每个单词出现的次数,就是所谓的词袋模型。
- 为了适应这种词袋模型,我们需要对函数setOfWords2Vec作一下修改
1
2
3
4
5
6
7
8
9
10
11#词袋模型的转换函数
def bagOfWords2VecMN(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 not in my vocabulary!" %word
return returnVec
四、示例:使用朴素贝叶斯进行垃圾邮件过滤
1.准备数据,切分文本
1 | # 该函数将每个句子都解析成单词,并忽略空格,标点符号以及长度小于3的单词 |
2.分类器
错误信息合集(参考) 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# 检测垃圾邮件
def spamTest():
# 存放输入数据
docList = []
#存放类别标签
classList = []
# 所有的文本
fullText = []
# 分别读取邮件内容
for i in range(1, 26):
wordList = textParse(open('email/spam/%d.txt' % i, "rb").read().decode('GBK','ignore') )
docList.append(wordList)
fullText.extend(wordList)
classList.append(1)
wordList = textParse(open('email/ham/%d.txt' % i, "rb").read().decode('GBK','ignore') )
docList.append(wordList)
fullText.extend(wordList)
classList.append(0)
vocabList = createVocabList(docList)
# range(50)表示从0到50,不包括50
trainingSet = list(range(50))
# 测试集
testSet = []
# 随机抽取是个作为测试集
for i in range(10):
# 从50个数据集中随机选取十个作为测试集,并把其从训练集中删除
randIndex = int(random.uniform(0,len(trainingSet)))
testSet.append(trainingSet[randIndex])
del(trainingSet[randIndex])
trainMat = []
trainClasses = []
for docIndex in trainingSet:
trainMat.append(setOfWords2Vec(vocabList, docList[docIndex]))
trainClasses.append(classList[docIndex])
# 使用训练集得到概率向量
p0V, p1V, pSpam = trainNB0(array(trainMat), array(trainClasses))
# 测试分类器的错误率
errorCount = 0
for docIndex in testSet:
wordVector = setOfWords2Vec(vocabList, docList[docIndex])
if classifyNB(array(wordVector), p0V, p1V, pSpam) != classList[docIndex]:
errorCount += 1
print("Classification error:")
print(docList[docIndex])
print(errorCount)
print("the error rate is:", float(errorCount)/len(testSet))