1.1、贝叶斯定理
贝叶斯定理是关于随机事件A和B的条件概率的一则定理。
其中P(A|B)是在B发生的情况下A发生的可能性。
在贝叶斯定理中,每个名词都有约定俗成的名称:
- P(A|B)是已知B发生后A的条件概率,也由于得自B的取值而被称作A的后验概率。
- P(B|A)是已知A发生后B的条件概率,也由于得自A的取值而被称作B的后验概率。
- P(A)是A的先验概率或(或边缘概率)。之所以称为"先验"是因为它不考虑任何B方面的因素。
- P(B)是B的先验概率或边缘概率。
按这些术语,贝叶斯定理可表述为:后验概率 = (相似度*先验概率)/标准化常量。也就是说,后验概率与先验概率和相似度的
乘积成正比。另外,比例P(B|A)/P(B)也有时被称作标准相似度(standardised likelihood),贝叶斯定理可表述为:
- 后验概率 = 标准相似度*先验概率
1.2、分类问题
分类是指识别出样本所属的类别。识别前是否需要进行训练,可分为有监督分类和无监督分类。有监督分类(supervised classification):
根据已知训练区提供的样本,通过计算选择特征参数,建立判别函数以对样本进行的分类。无监督分类(unsupervised classification):指人们
事先对分类过程不施加任何的先验知识,而仅凭数据,即自然聚类的特性,进行“盲目”的分类;其分类的结果只是对不同类别达到了区分,但
并不能确定类别的属性。
1.3、朴素贝叶斯分类器
分类是把一个事物分到某个类别中。一个事物具有很多属性,把它的众多属性看作一个向量,即x=(x1,x2,x3,…,xn),用x这个向量
来代表这个事物,x的集合记为X,称为属性集。类别也有很多种,用集合C={c1,c2,…cm}表示。一般X和C的关系是不确定的,可以将
X和C看作是随机变量,P(C|X)称为C的后验概率,与之相对的,P(C)称为C的先验概率。
根据贝叶斯公式,后验概率P(C|X)=P(X|C)P(C)/P(X),但在比较不同C值的后验概率时,分母P(X)总是常数,忽略掉,后验概率
P(C|X)=P(X|C)P(C),先验概率P(C)可以通过计算训练集中属于每一个类的训练样本所占的比例,容易估计,对类条件概率P(X|C)的估
计,这里我只说朴素贝叶斯分类器方法,因为朴素贝叶斯假设事物属性之间相互条件独立,P(X|C)=∏P(xi|ci)。
2.1、使用朴素贝叶斯进行文档分类
机器学习的一个重要过程就是文档的自动分类。在文档分类中,整个文档(如一封电子邮件)是实例,而电子邮件中的某些元
素构成特征。虽然电子邮件是一种不会增加的文本,但同样也可以对新闻报导、用户留言等其他任意文本进行分类。观察文档中出
现的词,并把每个词的出现作为一个特征,这样得到的特征数目就会跟词汇表中的词一样多。
朴素贝叶斯的一般过程:
- 收集数据:可以用任何方法
- 准备数据
- 分析数据:有大量特征时,绘制特征作用不大,此时用直方图效果更好。
- 训练算法:计算不同的独立特征的条件概率。
- 测试算法:计算错误率。
- 使用算法:一个常见的朴素贝叶斯应用是文档分类。可以在任意的分类场景中使用朴素贝叶斯分类器,不一定是文本。
def createVocabList(dataSet):
vocabSet = set([]) #create empty set
for document in dataSet:
vocabSet = vocabSet | set(document) #union of the two sets
return list(vocabSet)
def setOfWords2Vec(vocabList, inputSet):
returnVec = [0]*len(vocabList)
for word in inputSet:
if word in vocabList:
returnVec[vocabList.index(word)] = 1
else: print "the word: %s is not in my Vocabulary!" % word
return returnVec
2.2.2、训练算法
def trainNB0(trainMatrix,trainCategory):
numTrainDocs = len(trainMatrix)
numWords = len(trainMatrix[0])
pAbusive = sum(trainCategory)/float(numTrainDocs)
p0Num = zeros(numWords); p1Num = zeros(numWords)
#p0Num = ones(numWords); p1Num = ones(numWords) #change to ones()
p0Denom = 0.0; p1Denom = 0.0
#p0Denom = 2.0; p1Denom = 2.0 #change to 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 = p1Num/p1Denom
p0Vect = p0Num/p0Denom
'''
p1Vect = log(p1Num/p1Denom) #change to log()
p0Vect = log(p0Num/p0Denom) #change to log()
'''
return p0Vect,p1Vect,pAbusive
#根据p1与p0概率的大小关系将文本分类
def classifyNB(vec2Classify, p0Vec, p1Vec, pClass1):
p1 = sum(vec2Classify * p1Vec) + log(pClass1) #element-wise mult
p0 = sum(vec2Classify * p0Vec) + log(1.0 - pClass1)
if p1 > p0:
return 1
else:
return 0
# 将分类器改为词袋模型,即单词表中出现该词,则将对应向量元素数值+1。
def bagOfWords2VecMN(vocabList, inputSet):
returnVec = [0]*len(vocabList)
for word in inputSet:
if word in vocabList:
returnVec[vocabList.index(word)] += 1
return returnVec
#一个测试函数,可以修改测试词组
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)
#切分邮件文本,使用正则表达式,去掉符合、数字,替换大写字母为小写,将文本处理为一个单词表。
def textParse(bigString): #input is big string, #output is word list
import re
listOfTokens = re.split(r'\W*', bigString)
return [tok.lower() for tok in listOfTokens if len(tok) > 2]
#交叉验证,将两个文件夹中的50条文本全部读入并处理为单词表,随机选择10条文本,剩下40条作为测试集
def spamTest():
docList=[]; classList = []; fullText =[]
for i in range(1,26):
wordList = textParse(open('email/spam/%d.txt' % i).read())
docList.append(wordList)
fullText.extend(wordList)
classList.append(1)
wordList = textParse(open('email/ham/%d.txt' % i).read())
docList.append(wordList)
fullText.extend(wordList)
classList.append(0)
vocabList = createVocabList(docList)#create vocabulary
trainingSet = range(50); testSet=[] #create test set
for i in range(10):
randIndex = int(random.uniform(0,len(trainingSet)))
testSet.append(trainingSet[randIndex])
del(trainingSet[randIndex])
trainMat=[]; trainClasses = []
for docIndex in trainingSet:#train the classifier (get probs) trainNB0
trainMat.append(bagOfWords2VecMN(vocabList, docList[docIndex]))
trainClasses.append(classList[docIndex])
p0V,p1V,pSpam = trainNB0(array(trainMat),array(trainClasses))
errorCount = 0
for docIndex in testSet: #classify the remaining items
wordVector = bagOfWords2VecMN(vocabList, docList[docIndex])
if classifyNB(array(wordVector),p0V,p1V,pSpam) != classList[docIndex]:
errorCount += 1
print "classification error",docList[docIndex]
print 'the error rate is: ',float(errorCount)/len(testSet)
#return vocabList,fullText