赞
踩
朴素贝叶斯算法是基于统计学概率的分类方法,通过计算样本发生的概率来实现分类。这里必须知道贝叶斯公式
p
(
X
Y
)
=
p
(
X
∣
Y
)
∗
p
(
Y
)
=
p
(
Y
∣
X
)
∗
p
(
X
)
(
1
)
p(XY)=p(X|Y)*p(Y)=p(Y|X)*p(X)\quad\quad\quad(1)
p(XY)=p(X∣Y)∗p(Y)=p(Y∣X)∗p(X)(1)
有些时候在直接计算P(Y|X)的条件概率时显得很困难,但是使用朴素贝叶斯公式就可以间接求解。当然使用贝叶斯公式求解问题的前提是,各个事件相互独立。举个例子吧
在这份数据集中,事件年龄和有工作是互不影响的,两者没有任何关系,他们之间就是相互独立的,当然在现实生活中肯定会有一些影响。记事件年龄为0的情况下同意贷款的概率为P(Y|x1),直接求这个概率就显得很棘手,但是使用贝叶斯公式后,就很简单了
p
(
Y
∣
x
1
)
=
p
(
X
1
∣
Y
)
∗
p
(
Y
)
p
(
x
1
)
=
2
9
∗
9
15
5
15
(
2
)
p(Y|x_1)=\frac{p(X_1|Y)*p(Y)}{p(x_1)}=\frac{\frac{2}{9}*\frac{9}{15}}{\frac{5}{15}}\quad\quad\quad(2)
p(Y∣x1)=p(x1)p(X1∣Y)∗p(Y)=15592∗159(2)
朴素贝叶斯分类器就是分别计算在该数据样本中的情况下是类别A的概率
p
(
A
∣
X
)
=
p
(
X
∣
A
)
∗
p
(
A
)
p
(
X
)
(
3
)
p(A|X)=\frac{p(X|A)*p(A)}{p(X)}\quad\quad\quad(3)
p(A∣X)=p(X)p(X∣A)∗p(A)(3)
是该数据样本中的情况下是类别B的概率
p
(
B
∣
X
)
=
p
(
X
∣
B
)
∗
p
(
B
)
p
(
X
)
(
4
)
p(B|X)=\frac{p(X|B)*p(B)}{p(X)}\quad\quad\quad(4)
p(B∣X)=p(X)p(X∣B)∗p(B)(4)
然后比较两种大小,取概率大的作为该数据样本的类别。当然这是一个二分类问题,多分类问题也是类似比较各个分类的条件概率,然后取概率大作为数据样本的分类。
对于多个特征维度X的情况下,P(X|A)计算时需要拆分成P(x1|A)*P(x1|A)*P(x1|A),但是如果其中一项概率为零,会影响整个概率计算结果,为了解决这个问题,初始化过程中设为1,不要设为0.同时还存在另外一个问题就是如果各个概率过小,计算时可能会出现下溢出(很多小数相乘会四舍五入为0),为了解决这个问题,计算过程中取对数
l
n
(
p
(
X
∣
A
)
)
=
l
n
(
p
(
x
1
∣
A
)
)
+
l
n
(
p
(
x
2
∣
A
)
)
+
l
n
(
p
(
x
3
∣
A
)
)
+
.
.
.
(
5
)
ln(p(X|A))=ln(p(x_1|A))+ln(p(x_2|A))+ln(p(x_3|A))+...\quad(5)
ln(p(X∣A))=ln(p(x1∣A))+ln(p(x2∣A))+ln(p(x3∣A))+...(5)
在观察公式3,4我们发现分母都是一样的,所以这里可以简化计算,只比较分子的大小
#导入第三方科学计算包 import random from numpy import * #导入正则表达式模块 import re #统计文档中所有单词 def createVocabList(dataSet): #定义并初始化词汇列表 vocabSet=set([]) #对于数据集中每一句话迭代 for document in dataSet: #将每一句话中的单词与词汇集合并并去重 vocabSet=vocabSet|set(document) #返回词汇列表 return list(vocabSet) #将词汇表转换为文档向量 def setOfWordsVec(vocabList,inputSet): #定义并初始化返回的词汇向量 returnVec=[0]*len(vocabList) #对于传入的话的每一个单词迭代 for word in inputSet: #如果该单词在词汇列表中 if word in vocabList: #对相应的词汇向量加一 returnVec[vocabList.index(word)]+=1 #返回词汇向量 return returnVec #贝叶斯分类器 def trainNB(trainMatrix,trainCategory): #获得数据集中有个样本数据(多少句话) numTrainDocs=len(trainMatrix) #获取词汇表的数据 numWords=len(trainMatrix[0]) #计算侮辱性样本的概率 pAbusive=sum(trainCategory)/float(numTrainDocs) #定义并初始化非侮辱性样本数目 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(vecClassify,p0Vec,p1Vec,pClass1): #计算条件概率:在该邮件的情况下,是垃圾邮件的概率(计算时由于两者分母相同,故省去了分母) p1=sum(vecClassify*p1Vec)+log(pClass1) #计算条件概率:在该邮件的情况下,是正常邮件的概率(计算时由于两者分母相同,故省去了分母) p0=sum(vecClassify*p0Vec)+log(1.0-pClass1) #比较两者概率,返回概率大的哪个类别 if p1>p0: return 1 else: return 0 #邮件文件解析 def textParse(bigString): #使用正则表达式处理数据文件 regEx=re.compile(r'\W') listOfTokens=regEx.split(bigString) #筛选出字符长度大于2单词,并且改为小写 return [tok.lower() for tok in listOfTokens if len(tok)>2] #垃圾邮件测试 def spamTest(): #定义邮件内容数据集 docList=[] #定义邮件种类 classList=[] # fullText=[] #对26封邮件迭代处理 for i in range(1,26): #对邮件内容处理 wordList=textParse(open("D:/学习资料/机器学习实战/《机器学习实战》源代码/machinelearninginaction/Ch04/email/spam/%d.txt" % i).read()) #将每一封邮件作为一个数据样本存入邮件数据集 docList.append(wordList) # fullText.extend(wordList) #定义邮件种类为垃圾邮件 classList.append(1) #对邮件内容处理 wordList=textParse(open("D:/学习资料/机器学习实战/《机器学习实战》源代码/machinelearninginaction/Ch04/email/ham/%d.txt" %i).read()) # 将每一封邮件作为一个数据样本存入邮件数据集 docList.append(wordList) fullText.extend(wordList) # 定义邮件种类为垃圾邮件 classList.append(0) #获取所有邮件的词汇表 vocabList=createVocabList(docList) #定义并初始化训练集 trainingSet=list(range(50)) #定义并初始测试集 testSet=[] #从0-9迭代 for i in range(10): #在1-50间生成分布均匀的随机数 randIndex =int(random.uniform(0,len(trainingSet))) # 在测试数据集中添加随机生成下标所对应的训练数据集 testSet.append(trainingSet[randIndex]) #在训练数据集中删除添加的测试数据集 del (trainingSet[randIndex]) # 初始化训练集词汇向量表 trainMat=[] # 定义并初始化训练集标签 trainClasses=[] #对训练集中的每一份邮件样本迭代 for docIndex in trainingSet: #将样本邮件中的词汇向量添加到存储词汇向量表 trainMat.append(setOfWordsVec(vocabList,docList[docIndex])) #将样本邮件类别添加到存储邮件类别的列表中 trainClasses.append(classList[docIndex]) #在非垃圾邮件概率的情况下,各个单词出现的概率,在垃圾邮件的情况下,各个单词出现的概率,获取垃圾邮件概率 p0v,p1v,pSpm=trainNB(array(trainMat),array(trainClasses)) #定义并初始话错误数目 errorCount=0.0 #对测试集中每一份邮件样本迭代 for docIndex in testSet: #获取测试邮件样本的词汇向量表 wordVector=setOfWordsVec(vocabList,docList[docIndex]) #如果预测结果与实际不符 if classifyNB(array(wordVector),p0v,p1v,pSpm)!=classList[docIndex]: errorCount+=1 print(f"错误率是{float(errorCount)/len(testSet)}") #测试 if __name__=='__main__': spamTest()
朴素贝叶斯分类常用于垃圾邮件检测,污秽语言检测,它要求各个时间之间相互独立,互不影响.
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。