1 朴素贝叶斯介绍
我们假设有一个二分类问题,现有一个新的样本点x,我们用贝叶斯决策理论来判断新的样本点应该属于二分类(A,B)的哪一类:如果x属于A类的概率大于属于B类的概率,那么x就属于A类;反之则属于B类。对于多分类ci,那么只需要计算x属于各个分类的概率p,然后找到,其对于的最大概率标签,就是x的分类。那么如何计算每个分类p(ci| x)。
没错,就是贝叶斯公式:
这里就用到了朴素贝叶斯的假设:假设所有xj(各特征属性)相互条件独立,则进一步拆分上面的公式,并且分母对于所有类别都是常数,所有将分母最大化,那么就可以得到:
那么朴素贝叶斯分类的流程如下:
1、设为一个待分类项,而每个a为x的一个特征属性。
2、有类别集合。
3、计算。
4、如果 = ,则 。
2 运行实例
实际应用场景可以有:文本分类;垃圾邮件过滤;病人分类;拼写检查等。
朴素贝叶斯常用的模型:高斯模型(特征是连续型变量);多项式模型(特征是离散的);伯努利模型(特征是离散的且为布尔类型(1/0))。
本文使用他来过滤恶意评论(恶意的为1,非恶意的为0):
# coding=utf-8
from numpy import *
# 创建一个实验样本
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)
# p0Num = zeros(numWords); p1Num = zeros(numWords)
# p0Denom = 0.0; p1Denom = 0.0
p0Num = ones(numWords); # 避免一个概率值为0,最后的乘积也为0
p1Num = 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 = p1Num / p1Denom
# p0Vect = p0Num / p0Denom
p1Vect = log(p1Num / p1Denom) # 在类1中,每个次的发生概率
p0Vect = log(p0Num / p0Denom) # 避免下溢出或者浮点数舍入导致的错误 下溢出是由太多很小的数相乘得到的
return p0Vect, p1Vect, pAbusive
# 朴素贝叶斯分类器
def classifyNB(vec2Classify, p0Vec, p1Vec, pClass1):
p1 = sum(vec2Classify*p1Vec) + log(pClass1)
p0 = sum(vec2Classify*p0Vec) + log(1.0-pClass1)
if p1 > p0:
return 1
else:
return 0
def testingNB():
listOPosts, listClasses = loadDataSet()
myVocabList = createVocabList(listOPosts)
trainMat = []
for postinDoc in listOPosts:
trainMat.append(setOfWords2Vec(myVocabList, postinDoc))
p0V, p1V, pAb = trainNB0(array(trainMat), array(listClasses))
testEntry = ['love','my','dalmation']
thisDoc = array(setOfWords2Vec(myVocabList, testEntry))
print testEntry, 'classified as: ', classifyNB(thisDoc, p0V, p1V, pAb)
testEntry = ['stupid','garbage']
thisDoc = array(setOfWords2Vec(myVocabList, testEntry))
print testEntry, 'classified as: ', classifyNB(thisDoc, p0V, p1V, pAb)
# 调用测试方法----------------------------------------------------------------------
testingNB()