单纯的贝叶斯分类器很简单,基本上就是一个贝叶斯公式,要理解透彻贝叶斯分类器需要搞清楚两个概念
基本上维基百科讲的很清楚,我这里在重复一下,可以直接去维基百科看
在数理统计学中,似然函数是一种关于统计模型中的参数的函数,表示模型参数中的似然性。似然函数在统计推断中有重大作用,如在最大似然估计和费雪信息之中的应用等等。“似然性”与“或然性”或“概率”意思相近,都是指某种事件发生的可能性,但是在统计学中,“似然性”和“或然性”或“概率”又有明确的区分。概率用于在已知一些参数的情况下,预测接下来的观测所得到的结果,而似然性则是用于在已知某些观测所得到的结果时,对有关事物的性质的参数进行估计。
在这种意义上,似然函数可以理解为条件概率的逆反。在已知某个参数B时,事件A会发生的概率写作:
利用贝叶斯定理,
因此,我们可以反过来构造表示似然性的方法:已知有事件A发生,运用似然函数 L(B∣A) ,我们估计参数B的可能性。形式上,似然函数也是一种条件概率函数,但我们关注的变量改变了:
注意到这里并不要求似然函数满足归一性: ∑b∈BP(A∣B=b)=1 。一个似然函数乘以一个正的常数之后仍然是似然函数。对所有 α>0 ,都可以有似然函数:
考虑投掷一枚硬币的实验。通常来说,已知投出的硬币正面朝上和反面朝上的概率各自是 pH=0.5 ,便可以知道投掷若干次后出现各种结果的可能性。比如说,投两次都是正面朝上的概率是0.25。用条件概率表示,就是:
P(HH∣pH=0.5)=0.52=0.25
其中H表示正面朝上。
在统计学中,我们关心的是在已知一系列投掷的结果时,关于硬币投掷时正面朝上的可能性的信息。
我们可以建立一个统计模型:假设硬币投出时会有 pH 的概率正面朝上,而有 1−pH 的概率反面朝上。
这时,条件概率可以改写成似然函数:
也就是说,对于取定的似然函数,在观测到两次投掷都是正面朝上时, pH=0.5 的似然性是0.25(这并不表示当观测到两次正面朝上时 pH=0.5 的概率是0.25)。
如果考虑 pH=0.6 ,那么似然函数的值也会改变。
注意到似然函数的值变大了。
这说明,如果参数 pH 的取值变成0.6的话,结果观测到连续两次正面朝上的概率要比假设 pH=0.5 时更大。也就是说,参数 pH 取成0.6要比取成0.5更有说服力,更为“合理”。总之,似然函数的重要性不是它的具体取值,而是当参数变化时函数到底变小还是变大。对同一个似然函数,如果存在一个参数值,使得它的函数值达到最大的话,那么这个值就是最为“合理”的参数值。
在这个例子中,似然函数实际上等于:
L(θ∣HH)=P(HH∣pH=θ)=θ2 ,其中 0≤pH≤1 。
如果取 pH=1 ,那么似然函数达到最大值1。也就是说,当连续观测到两次正面朝上时,假设硬币投掷时正面朝上的概率为1是最合理的。
类似地,如果观测到的是三次投掷硬币,头两次正面朝上,第三次反面朝上,那么似然函数将会是:
L(θ∣HHT)=P(HHT∣pH=θ)=θ2(1−θ) ,其中T表示反面朝上, 0≤pH≤1 。
这时候,似然函数的最大值将会在 pH=23 的时候取到。也就是说,当观测到三次投掷中前两次正面朝上而后一次反面朝上时,估计硬币投掷时正面朝上的概率 pH=23 是最合理的。
我们首先要定义似然函数:
并且在 θ 的所有取值上通过令一阶导数等于零,使这个函数取到最大值。这个使可能性最大的 θˆ 值即称为 θ 的最大似然估计
现在假设例子1中的盒子中有无数个硬币,对于 0≤p≤1 中的任何一个 p , 都有一个抛出正面概率为 p 的硬币对应,我们来求其似然函数的最大值:
其中 0≤p≤1 . 我们可以使用微分法来求最值。方程两边同时对 p 取微分,并使其为零。
在不同比例参数值下一个二项式过程的可能性曲线t = 3, n = 10;其最大似然估计值发生在其众数并在曲线的最大值处。
其解为 p=0 , p=1 ,以及 p=49/80 .使可能性最大的解显然是 p=49/80 (因为 p=0 和 p=1 这两个解会使可能性为零)。因此我们说最大似然估计值为 pˆ=49/80pˆ .
这个结果很容易一般化。只需要用一个字母 t 代替49用以表达伯努利试验中的被观察数据(即样本)的“成功”次数,用另一个字母 n 代表伯努利试验的次数即可。使用完全同样的方法即可以得到最大似然估计值:
对于任何成功次数为 t ,试验总数为 n 的伯努利试验。
基本上就是似然函数就是一件事发生的概率公式,而最大似然估计是在当前似然函数下函数能取到的最大值,就是一件事最可能发生的概率,这在计算中很重要。
在一个垃圾邮件检测代码中贝叶斯公式的解释
P(B) 表示邮件是垃圾邮件的概率 垃圾邮件数/总邮件数
P(A) 表示某个词在所有邮件中的出现概率 当前次出现次数/总次数
P(A∣B) 是垃圾邮件的情况下某个词出现的概率 是垃圾邮件某词出现次数/是垃圾邮件所有词数目
P(B∣A) 在一个词出现概率为A的情况下是垃圾邮件的概率 所有出现词的概率求和 对比垃圾邮件和非垃圾邮件那个值更大 判断是否是垃圾邮件
这里有个优化就是对词的初始出现次数默认置1,防止分子为0导致整个值为0,还有所有词数如果为0的话默认置2,防止除0错误
另一个是为了优化多个0.1左右的值乘积会变得很小,所以用 ln(a∗b)=ln(a)+ln(b) 这个公式可以把乘积变成先ln然后求和
看一个机器学习实战中贝叶斯检测垃圾词的代码
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] #1 is abusive, 0 not
return postingList,classVec
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
def trainNB0(trainMatrix,trainCategory):
numTrainDocs = len(trainMatrix)
numWords = len(trainMatrix[0])
pAbusive = sum(trainCategory)/float(numTrainDocs)
p0Num = ones(numWords); p1Num = ones(numWords) #change to ones()
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 = log(p1Num/p1Denom) #change to log()
p0Vect = log(p0Num/p0Denom) #change to log()
return p0Vect,p1Vect,pAbusive
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
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 "p0v: ", p0V, " p1V : ", p1V, " pAb: ", pAb
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)
if __name__ == '__main__':
listOposts, listClasses = loadDataSet()
myVocabList = createVocabList(listOposts)
print setOfWords2Vec(myVocabList, listOposts[0])
print testingNB()