朴素贝叶斯(naive bayes)法是基于贝叶斯定理与特征条件独立假设的分类方法。
优点:在数据较少的情况下仍然有效,可以处理多分类问题。
缺点:对入输入数据的准备方式较为敏感。
使用数据类型:标称型数据。
下面从一个简单问题出发,介绍怎么使用朴素贝叶斯解决分类问题。
一天,老师问了个问题,只根据头发和声音怎么判断一位同学的性别。
为了解决这个问题,同学们马上简单的统计了7位同学的相关特征,数据如下:
头发
声音
性别
长
粗
男
短
粗
男
短
粗
男
长
细
女
短
细
女
短
粗
女
长
粗
女
长
粗
女
这个问题之前用决策树做过了,这里我们换一种思路。
要是知道男生和女生头发长短的概率以及声音粗细的概率,我们就可以计算出各种情况的概率,然后比较概率大小,来判断性别。
假设抽样样本足够大,我们可以近似认为可以代表所有数据,假设上位7位同学能代表所有数据,这里方便计算~
由这7位同学,我们马上得出下面表格概率分布。
性别
头发长
声音粗
男
1/3
1
女
3/5
3/5
假设头发和声音都是独立特征,于是
男生头发长声音粗的概率=3/8*1/3*1=1/8
女生头发长声音粗的概率=5/8*3/5*3/5=9/40
因为1/8<9/40所以如果一个人,头发长,声音粗,那么这个人更可能是女生,于是出现这些特征就是女生。其他特征依次类推。
这就是朴素贝叶斯分类方法。是的,就是这么简单。
下面来解释原理,先看贝叶斯公式:
公式中,事件Bi的概率为P(Bi),事件Bi已发生条件下事件A的概率为P(A│Bi),事件A发生条件下事件Bi的概率为P(Bi│A)。
带入我们的例子中,判断头发长的人性别:
P(男|头发长)=P(头发长|男)*P(男)/P(头发长)
P(女|头发长)=P(头发长|女)*P(女)/P(头发长)
判断头发长、声音粗的人性别:
P(男|头发长声音粗)=P(头发长|男)P(声音粗|男)*P(男)/P(头发长声音粗)
P(女|头发长声音粗)=P(头发长|女)P(声音粗|女)*P(女)/P(头发长声音粗)
可以看到,比较最后比较概率,只用比较分子即可。也就是前面计算头发长声音粗的人是男生女生的概率。
下面应用于文本分类,文本分类不想上面例子有具体的特征,需先建立文本特征。以下为文本分类的一个简单例子。
1 #_*_ coding:utf-8 _*_
2 from numpy import *
3 importre4 importrandom5
6 def loadDataSet(): #创建样例数据
7 postingList = [['my', 'dog', 'has', 'flea', 'problems', 'help', 'please'],8 ['maybe', 'not', 'take', 'him', 'to', 'dog', 'park', 'stupid'],9 ['my', 'dalmation', 'is', 'so', 'cute', 'I', 'love', 'him'],10 ['stop', 'posting', 'stupid', 'worthless', 'garbage'],11 ['mr', 'licks', 'ate', 'my', 'steak', 'how', 'to', 'stop', 'him'],12 ['quit', 'buying', 'worthless', 'dog', 'food', 'stupid']]13 classVec = [0, 1, 0, 1, 0, 1] #1代表脏话
14 returnpostingList, classVec15
16 def createVocabList(dataSet): #创建词库 这里就是直接把所有词去重后,当作词库
17 vocabSet =set([])18 for document indataSet:19 vocabSet = vocabSet |set(document)20 returnlist(vocabSet)21
22 def setOfWords2Vec(vocabList, inputSet): #文本词向量。词库中每个词当作一个特征,文本中就该词,该词特征就是1,没有就是0
23 returnVec = [0] *len(vocabList)24 for word ininputSet:25 if word invocabList:26 returnVec[vocabList.index(word)] = 1
27 else:28 print("the word: %s is not in my Vocabulary!" %word)29 returnreturnVec30
31
32 deftrainNB0(trainMatrix, trainCategory):33 numTrainDocs =len(trainMatrix)34 numWords =len(trainMatrix[0])35 pAbusive = sum(trainCategory) /float(numTrainDocs)36 p0Num = ones(numWords) #防止某个类别计算出的概率为0,导致最后相乘都为0,所以初始词都赋值1,分母赋值为2.
37 p1Num =ones(numWords)38 p0Denom = 2
39 p1Denom = 2
40 for i inrange(numTrainDocs):41 if trainCategory[i] == 1:42 p1Num +=trainMatrix[i]43 p1Denom +=sum(trainMatrix[i])44 else:45 p0Num +=trainMatrix[i]46 p0Denom +=sum(trainMatrix[i])47 p1Vect = log(p1Num / p1Denom) #这里使用了Log函数,方便计算,因为最后是比较大小,所有对结果没有影响。
48 p0Vect = log(p0Num /p0Denom)49 returnp0Vect, p1Vect, pAbusive50
51 def classifyNB(vec2Classify,p0Vec,p1Vec,pClass1): #比较概率大小进行判断,
52 p1 = sum(vec2Classify*p1Vec)+log(pClass1)53 p0 = sum(vec2Classify*p0Vec)+log(1-pClass1)54 if p1>p0:55 return 1
56 else:57 return058
59 deftestingNB():60 listOPosts,listClasses =loadDataSet()61 myVocabList =createVocabList(listOPosts)62 trainMat=[]63 for postinDoc inlistOPosts:64 trainMat.append(setOfWords2Vec(myVocabList, postinDoc))65 p0V,p1V,pAb =trainNB0(array(trainMat),array(listClasses))66 testEntry = ['love', 'my', 'dalmation'] #测试数据
67 thisDoc =array(setOfWords2Vec(myVocabList, testEntry))68 print(testEntry,'classified as:',classifyNB(thisDoc,p0V,p1V,pAb))69 testEntry = ['stupid', 'garbage'] #测试数据
70 thisDoc =array(setOfWords2Vec(myVocabList, testEntry))71 print(testEntry,'classified as:',classifyNB(thisDoc,p0V,p1V,pAb))72
73 if __name__=='__main__':74 testingNB()
1 #输出结果
2 ['love', 'my', 'dalmation'] classified as: 03 ['stupid', 'garbage'] classified as: 1
参考:
- Machine Learning in Action
- 统计学习方法
转载:http://blog.csdn.net/csqazwsxedc/article/details/69488938