简介
贝叶斯定理是关于随机事件A和B的条件概率的一则定理。通常,事件A在事件B(发生)的条件下的概率,与事件B在事件A(发生)的条件下的概率是不一样的;然而,这两者之间有确实的关系,贝叶斯法则就是这种关系的陈述。
基于贝叶斯决策理论的分类方法之朴素贝叶斯
- 优点:在数据较少的情况下仍然有效,可以处理多类别问题
- 缺点:对于输入数据的准备方式较为敏感
- 适用数据类型:标称型数据。
朴素贝叶斯的一般过程
- 收集数据:可以使用任何方式
- 准备数据:需要数据型或是布尔型数据
- 分类数据:有大量特征时,绘制特征作用不大,此时使用直方图效果更好
- 训练算法:计算不同的独立特征的条件概率
- 测试算法:计算错误率
- 使用算法:文档分类
原理
主要是运用贝叶斯定理
算法实现
下面做一个简单的留言板分类,自动判别留言类别:侮辱类和非侮辱类,分别使用1和0表示。下面来做一下这个实验。以下函数全部写在一个叫bayes.py文件中,后面的实验室通过导入bayes.py,调用里面的函数来做的。
导入numpy包
from numpy import *
1.加载数据集
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']] classVec = [0,1,0,1,0,1] #1 is abusive, 0 not return postingList,classVec
该函数返回的是词条切分集合和类标签。
2.根据样本创建一个词库
下面的函数是根据上面给出来的样本数据所创建出来的一个词库。
def createVocabList(dataSet): vocabSet = set([]) #create empty set for document in dataSet: vocabSet = vocabSet | set(document) #union of the two sets return list(vocabSet)
3.统计每个样本在词库中的出现情况
下面的函数功能是把单个样本映射到词库中去,统计单个样本在词库中的出现情况,1表示出现过,0表示没有出现,函数如下:
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 not in my Vocabulary!" % word return returnVec
4.计算条件概率和类标签概率
def trainNB0(trainMatrix,trainCategory): numTrainDocs = len(trainMatrix) numWords = len(trainMatrix[0]) pAbusive = sum(trainCategory)/float(numTrainDocs) #计算某个类发生的概率 p0Num = ones(numWords); p1Num = ones(numWords) #初始样本个数为1,防止条件概率为0,影响结果 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) #计算类标签为1时的其它属性发生的条件概率 p0Vect = log(p0Num/p0Denom) #计算标签为0时的其它属性发生的条件概率 return p0Vect,p1Vect,pAbusive #返回条件概率和类标签为1的概率
说明:
5.训练贝叶斯分类算法
该算法包含四个输入,vec2Classify表示待分类的样本在词库中的映射集合,p0Vec表示条件概率P(wi|c=0)P(wi|c=0),p1Vec表示条件概率P(wi|c=1)P(wi|c=1),pClass1表示类标签为1时的概率P(c=1)P(c=1)。
def classifyNB(vec2Classify, p0Vec, p1Vec, pClass1): p1 = sum(vec2Classify * p1Vec) + log(pClass1) #element-wise mult p0 = sum(vec2Classify * p0Vec) + log(1.0 - pClass1) if p1 > p0: return 1 else: return 0
其中p1和p0表示的是lnp(w1|c=1)p(w2|c=1)...p(wn|c=1)∗p(c=1)lnp(w1|c=1)p(w2|c=1)...p(wn|c=1)∗p(c=1)和lnp(w1|c=0)p(w2|c=0)...p(wn|c=0)∗p(c=0)lnp(w1|c=0)p(w2|c=0)...p(wn|c=0)∗p(c=0),取对数是因为防止p(w_1|c=1)p(w_2|c=1)p(w_3|c=1)…p(w_n|c=1)多个小于1的数相乘结果值下溢。
6.文档词袋模型,修改函数setOfWords2Vec
词袋模型主要修改上面的第三个步骤,因为有的词可能出现多次,所以在单个样本映射到词库的时候需要多次统计。
def bagOfWords2VecMN(vocabList, inputSet): returnVec = [0]*len(vocabList) for word in inputSet: if word in vocabList: returnVec[vocabList.index(word)] += 1 return returnVec
7.测试函数
下面给出一个测试函数,直接调用该测试函数就可以实现简单的分类,测试结果看下个部分。
def testingNB(): #step1:加载数据集和类标号 listOPosts,listClasses = loadDataSet() #step2:创建词库 myVocabList = createVocabList(listOPosts) # step3:计算每个样本在词库中的出现情况 trainMat=[] for postinDoc in listOPosts: trainMat.append(setOfWords2Vec(myVocabList, postinDoc)) #step4:调用第四步函数,计算条件概率 p0V,p1V,pAb = trainNB0(array(trainMat),array(listClasses)) # step5 # 测试1 testEntry = ['love', 'my', 'dalmation'] thisDoc = array(setOfWords2Vec(myVocabList, testEntry)) print testEntry,'classified as: ',classifyNB(thisDoc,p0V,p1V,pAb) # 测试2 testEntry = ['stupid', 'garbage'] thisDoc = array(setOfWords2Vec(myVocabList, testEntry)) print testEntry,'classified as: ',classifyNB(thisDoc,p0V,p1V,pAb)
8.实验
首先导入库,然后导入bayes.py文件
import os os.chdir(r"K:\编程资源\《机器学习实战》源代码\Ch04") import bayes
可以看出,贝叶斯算法将[‘love’, ‘my’, ‘dalmation’]分为“无侮辱”一类,将[‘stupid’, ‘garbage’]分为“侮辱”性质的一类。