本文主要讲朴素贝叶斯算法(naiveBayes)
1.基本方法
朴素贝叶斯发是基于贝叶斯定理与特征条件独立假设的分类方法。所谓朴素即是特征条件独立。
对于给定的输入x,利用贝叶斯定理求出后验概率最大的输出y。
2.后验概率最大化
3.算法
下面简单举个栗子:
4.朴素贝叶斯应用:文档分类及其实现
在文本中获取特征,需要先拆分文本。将每个文本变成词向量,其中1表示词条出现在文档中,0表示词条未出现在文档中。
计算每个词条在侮辱性和非侮辱性条件下的概率,最后相乘再乘以先验概率即可。
思路:
对每个类别:
如果词条出现在文档中,就增加该词条的计数值
增加所有词条的计数值
对每个类别:
对每个词条:
将该词条的数目除以总词条数目得到条件概率
代码如下:
import numpy as np
# 过滤网站的恶意留言 侮辱性:1 非侮辱性:0
# 创建一个实验样本
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] #分类标签
return postingList, classVec
# 创建一个包含在所有文档中出现的不重复词的列表
def createVocabList(dataSet):
vocabSet = set([]) # 创建一个空集
for document in dataSet:
vocabSet = vocabSet | set(document) # 创建两个集合的并集
return list(vocabSet)
# 将文档词条转换成词向量
def setOfWords2Vec(vocabList, inputSet):
returnVec = [0]*len(vocabList) # 创建一个其中所含元素都为0的向量
for word in inputSet:
if word in vocabList:
# returnVec[vocabList.index(word)] = 1 # index函数在字符串里找到字符第一次出现的位置 词集模型
returnVec[vocabList.index(word)] += 1 # 文档的词袋模型 每个单词可以出现多次
else: print("the word: %s is not in my Vocabulary!" % word)
#其实现在所有的词条都在集合里面,因为前面已经将所有不重复的词构造了一个列表
return returnVec
# 朴素贝叶斯分类器训练函数 从词向量计算概率
def trainNB0(trainMatrix, trainCategory):
numTrainDocs = len(trainMatrix) #样本数目
numWords = len(trainMatrix[0]) #每个词向量的长度
pAbusive = sum(trainCategory)/float(numTrainDocs) #侮辱性词汇的先验概率
#sum()就是将列表中的元素的值相加所得的和,因为类别是0和1,所以相加的也就是侮辱性词的数量
# p0Num = zeros(numWords); p1Num = zeros(numWords)
# p0Denom = 0.0; p1Denom = 0.0
#用拉普拉斯平滑改进
p0Num = np.ones(numWords); # 避免一个概率值为0,最后的乘积也为0
p1Num = np.ones(numWords); # 用来统计两类数据中,各词的词频
p0Denom = 2.0; # 用于统计0类中的总数
p1Denom = 2.0 # 用于统计1类中的总数
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) # 避免下溢出或者浮点数舍入导致的错误 下溢出是由太多很小的数相乘得到的
return p0Vect, p1Vect, pAbusive
# 朴素贝叶斯分类器
def classifyNB(vec2Classify, p0Vec, p1Vec, pClass1):
#连乘再乘以先验概率,因为取了对数,所以变成加法
p1 = sum(vec2Classify*p1Vec) + np.log(pClass1)
p0 = sum(vec2Classify*p0Vec) + np.log(1.0-pClass1)
if p1 > p0:
return '侮辱性'
else:
return '非侮辱性'
def testingNB():
listOPosts, listClasses = loadDataSet()
myVocabList = createVocabList(listOPosts)
trainMat = []
for postinDoc in listOPosts:
trainMat.append(setOfWords2Vec(myVocabList, postinDoc))
p0V, p1V, pAb = trainNB0(np.array(trainMat), np.array(listClasses))
testEntry = ['love','my','dalmation']
thisDoc = np.array(setOfWords2Vec(myVocabList, testEntry))
print (testEntry, 'classified as: ', classifyNB(thisDoc, p0V, p1V, pAb))
testEntry = ['stupid','garbage']
thisDoc = np.array(setOfWords2Vec(myVocabList, testEntry))
print (testEntry, 'classified as: ', classifyNB(thisDoc, p0V, p1V, pAb))
# 调用测试
testingNB()
这里好好体会下怎么算条件概率的。因为转换成了词向量,需要用出现的次数除以这个类别的词条总数。还有这里的条件概率都用矩阵存储起来了,方便多了。