900字范文,内容丰富有趣,生活中的好帮手!
900字范文 > 机器学习实战读书笔记-朴素贝叶斯

机器学习实战读书笔记-朴素贝叶斯

时间:2021-07-03 00:46:10

相关推荐

机器学习实战读书笔记-朴素贝叶斯

朴素贝叶斯

朴素贝叶斯是一种基于概率论的分类方法

条件概率公式

P(Y|X)=P(X|Y)P(Y)P(X)

P(Y|X)表示,X条件下Y的概率。

举例说明:假设夫妻双方血型,丈夫为O型,妻子为AB型血。两人结合生下的孩子是什么血型?

P(A型血|(aa,AB))表示孩子是A型血的概率,其中(丈夫为O型,妻子为AB型血即为条件)

其中P(X|Y)在各特征独立且权重一样的的情况下可以拆分成:

P(X|Y)=P((x1,x2...xn)|Y)=P((x1)|Y)∗P((x2)|Y)∗...P((xn)|Y)

注意X为特征向量,可以有多个特征。如下

X表示每一行的(x1,x2,x3,x4), Y表示每一行的y

这就很清楚了,

P((x1,x2...xn)|Y)=P((x1)|Y)∗P((x2)|Y)∗...P((xn)|Y)

左边表示x1,x2…xn同时满足,右边则是拆分满足x1的情况,再满足x2等等。所以上述等式成立是显而易见的了。

根据以上的概率知识,只要获得给定X的情况下,P(Y|X)概率最大的,那个Y就是我们需要的分类了。

算法实现步骤

收集数据(初始化数据)获取训练集中,所有不同的词列表(多少个不同的词)转化为训练集矩阵形式训练算法,计算不同的独立词中各种分类情况下的概率给定某一串文字,进行分类得出结果

下面以文本分类作为例子进行说明(以在线社区的留言板为例):

具体实现

def testingNB():listOPosts, listClasses = loadDataSet() #初始化数据集及分类集myVocabList = createVocabList(listOPosts) # 获得训练集中,所有不同的词列表即词汇表# 转化训练集为矩阵trainMat = []for postinDoc in listOPosts:trainMat.append(setOfWords2Vec(myVocabList, postinDoc))p0V, p1V, pAb = AlgorithmUtil.trainNBO(array(trainMat), array(listClasses))# testEntry = ['love', 'my', 'dalmation']testEntry = ['dog', 'stupid', 'him']thisDoc = array(setOfWords2Vec(myVocabList, testEntry))print testEntry,'classified as: ',AlgorithmUtil.classifyNB(thisDoc,p0V,p1V,pAb)

==========以下为一些子函数

#初始化训练数据def loadDataSet():postingLis = [['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 代表侮辱性文字,0代表正常言论return postingLis, classVec

上面为初始训练集。当然实际情况不可能这么简单,这么少的。当然这不影响算法的实现步骤。

#获得包含在所有文档中出现的不重复词的列表(也就是获取词汇表)def createVocabList(dataSet):#参数说明,dataSet可以看作上一函数中的postingLis,就是初始训练集vocabSet = set([])for document in dataSet:vocabSet = vocabSet | set(document) #并集return list(vocabSet)

#转化为词向量,向量的每一元素为1或0,分别表示词汇表中的单词在输人文档中是否出现def setOfWords2Vec(vocabList, inputSet):returnVec = [0] * len(vocabList)for word in inputSet:if word in vocabList:returnVec[vocabList.index(word)] =1else: print "the word:%s is not in my Vocabulary!" % wordreturn returnVec

#朴素贝叶斯分类器训练函数(只有俩类的情况)def trainNBO(trainMatrix,trainCategory):#参数说明,trainMatrixnumTrainDocs = len(trainMatrix) #行numWords = len(trainMatrix[0]) #列pAbusive = sum(trainCategory) / float(numTrainDocs) #整个训练集中,侮辱性言论的比例,或者概率。P(Y),即P(侮辱性言论)p0Num = ones(numWords); p1Num = ones(numWords)# 1 代表侮辱性文字,0代表正常言论#p0Num表示训练集中,正常言论里面包含每一个词的个数。是一个向量(包括词汇表中每一个词)#p1Num表示训练集中,侮辱性言论里面包含每一个词的个数是一个向量(包括词汇表中每一个词)p0Denom = 2.0; p1Denom = 2.0#p0Denom表示训练集中,正常言论里面总的词汇数(有可能重复)#p1Denom表示训练集中,侮辱性言论里面总的词汇数(有可能重复)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 = np.log(p1Num/p1Denom) #概率 分类1时,各词出现的概率p0Vect = np.log(p0Num/p0Denom) #概率 分类0时,各词出现的概率#加log,是为一些数学到考虑,下面会提到return p0Vect, p1Vect, pAbusive

为什么p0Num,p1Num初始化为[1,1,….,1],不为[0,0,…,0]呢?

为什么p0Denom,p1Denom初始化为2呢?

是因为:利用贝叶斯分类器对文档进行分类时,要计算多个概率的乘积以获得文档属于某个类别的概率。从上面的函数我们可以看到,其实求到的是每一个词汇对应类别的概率。如果其中一个概率值为0,那么最后的乘积也为0。所以为降低 这种影响,可以将所有词的出现数初始化为1,并将分母初始化为2(分母不能为0吧)。这不影响结果,因为我们是要比较哪种分类的概率大

为什么要加得到的概率要log?

是因为:同样到要计算多个概率的乘积以获得文档属于某个类别的概率。由于大部分因子都非常小,所以程序会下溢出或者 得到不正确的答案。(很多很小到数相乘,四舍五入后会=0)。log不影响结果,因为我们是要比较哪种分类的概率大,log大的,还是大,趋势一致。(这应该好理解吧。。。)其实后面分解也会有用到。

#具体分类def classifyNB(vec2Classify, pOVec, plVec, pClassl):#参数说明 #vec2Classify 测试文本(转换为向量后的)#pOVec 训练集中,类别为0即正常言论里,各词的概率#plVec 训练集中,类别为1即侮辱言论里,各词的概率#pClassl 训练集中,侮辱言论的概率pl = sum(vec2Classify * plVec) + log(pClassl)p0 = sum(vec2Classify * pOVec) + log(1.0 - pClassl)if pl > p0:return 1else: return 0

上面pl = sum(vec2Classify * plVec) + log(pClassl)的含义:

P(Y|X)=P(X|Y)P(Y)P(X)

根据P(X|Y)=P((x1,x2...xn)|Y)=P((x1)|Y)∗P((x2)|Y)∗...P((xn)|Y)

因为X是相同的,分母相同,取log,只要比较分子的大小即可。

log一下,就得到了(简单,自己推导一下)

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。