机器学习基础--贝叶斯分类器

机器学习 专栏收录该内容
6 篇文章 0 订阅

单纯的贝叶斯分类器很简单,基本上就是一个贝叶斯公式,要理解透彻贝叶斯分类器需要搞清楚两个概念

似然函数

基本上维基百科讲的很清楚,我这里在重复一下,可以直接去维基百科看
在数理统计学中,似然函数是一种关于统计模型中的参数的函数,表示模型参数中的似然性。似然函数在统计推断中有重大作用,如在最大似然估计和费雪信息之中的应用等等。“似然性”与“或然性”或“概率”意思相近,都是指某种事件发生的可能性,但是在统计学中,“似然性”和“或然性”或“概率”又有明确的区分。概率用于在已知一些参数的情况下,预测接下来的观测所得到的结果,而似然性则是用于在已知某些观测所得到的结果时,对有关事物的性质的参数进行估计。

在这种意义上,似然函数可以理解为条件概率的逆反。在已知某个参数B时,事件A会发生的概率写作:

P(AB)=P(A,B)P(B)

利用贝叶斯定理,

P(BA)=P(AB)P(B)P(A)

因此,我们可以反过来构造表示似然性的方法:已知有事件A发生,运用似然函数 L(BA) ,我们估计参数B的可能性。形式上,似然函数也是一种条件概率函数,但我们关注的变量改变了:

bP(AB=b)

注意到这里并不要求似然函数满足归一性: bBP(AB=b)=1 。一个似然函数乘以一个正的常数之后仍然是似然函数。对所有 α>0 ,都可以有似然函数:

L(bA)=αP(AB=b)

例子

考虑投掷一枚硬币的实验。通常来说,已知投出的硬币正面朝上和反面朝上的概率各自是 pH=0.5 ,便可以知道投掷若干次后出现各种结果的可能性。比如说,投两次都是正面朝上的概率是0.25。用条件概率表示,就是:

P(HHpH=0.5)=0.52=0.25

其中H表示正面朝上。

在统计学中,我们关心的是在已知一系列投掷的结果时,关于硬币投掷时正面朝上的可能性的信息。
我们可以建立一个统计模型:假设硬币投出时会有 pH 的概率正面朝上,而有 1pH 的概率反面朝上。
这时,条件概率可以改写成似然函数:

L(pHHH)=P(HHpH=0.5)=0.25

也就是说,对于取定的似然函数,在观测到两次投掷都是正面朝上时, pH=0.5 的似然性是0.25(这并不表示当观测到两次正面朝上时 pH=0.5 的概率是0.25)。

如果考虑 pH=0.6 ,那么似然函数的值也会改变。

L(pHHH)=P(HHpH=0.6)=0.36

三次投掷中头两次正面朝上,第三次反面朝上时的似然函数

注意到似然函数的值变大了。

这说明,如果参数 pH 的取值变成0.6的话,结果观测到连续两次正面朝上的概率要比假设 pH=0.5 时更大。也就是说,参数 pH 取成0.6要比取成0.5更有说服力,更为“合理”。总之,似然函数的重要性不是它的具体取值,而是当参数变化时函数到底变小还是变大。对同一个似然函数,如果存在一个参数值,使得它的函数值达到最大的话,那么这个值就是最为“合理”的参数值。

在这个例子中,似然函数实际上等于:

L(θHH)=P(HHpH=θ)=θ2 ,其中 0pH1

如果取 pH=1 ,那么似然函数达到最大值1。也就是说,当连续观测到两次正面朝上时,假设硬币投掷时正面朝上的概率为1是最合理的。

类似地,如果观测到的是三次投掷硬币,头两次正面朝上,第三次反面朝上,那么似然函数将会是:

L(θHHT)=P(HHTpH=θ)=θ2(1θ) ,其中T表示反面朝上, 0pH1

这时候,似然函数的最大值将会在 pH=23 的时候取到。也就是说,当观测到三次投掷中前两次正面朝上而后一次反面朝上时,估计硬币投掷时正面朝上的概率 pH=23 是最合理的。

最大似然估计

我们首先要定义似然函数:

lik(θ)=fD(x1,,xnθ)

并且在 θ 的所有取值上通过令一阶导数等于零,使这个函数取到最大值。这个使可能性最大的 θˆ 值即称为 θ 的最大似然估计

例子

现在假设例子1中的盒子中有无数个硬币,对于 0p1 中的任何一个 p , 都有一个抛出正面概率为 p 的硬币对应,我们来求其似然函数的最大值:

lik(θ)=fD(H=49,T=80-49p)=(8049)p49(1p)31

其中 0p1 . 我们可以使用微分法来求最值。方程两边同时对 p 取微分,并使其为零。

0==ddp((8049)p49(1p)31)49p48(1p)3131p49(1p)30p48(1p)30[49(1p)31p]

在不同比例参数值下一个二项式过程的可能性曲线t = 3, n = 10;其最大似然估计值发生在其众数并在曲线的最大值处。

其解为 p=0 , p=1 ,以及 p=49/80 .使可能性最大的解显然是 p=49/80 (因为 p=0 p=1 这两个解会使可能性为零)。因此我们说最大似然估计值为 pˆ=49/80pˆ .

这个结果很容易一般化。只需要用一个字母 t 代替49用以表达伯努利试验中的被观察数据(即样本)的“成功”次数,用另一个字母 n 代表伯努利试验的次数即可。使用完全同样的方法即可以得到最大似然估计值:

pˆ=tn

对于任何成功次数为 t ,试验总数为 n 的伯努利试验。

基本上就是似然函数就是一件事发生的概率公式,而最大似然估计是在当前似然函数下函数能取到的最大值,就是一件事最可能发生的概率,这在计算中很重要。

在一个垃圾邮件检测代码中贝叶斯公式的解释

P(BA)=P(AB)P(B)P(A)

P(B) 表示邮件是垃圾邮件的概率 垃圾邮件数/总邮件数
P(A) 表示某个词在所有邮件中的出现概率 /
P(AB) 是垃圾邮件的情况下某个词出现的概率 是垃圾邮件某词出现次数/是垃圾邮件所有词数目
P(BA) 在一个词出现概率为A的情况下是垃圾邮件的概率 所有出现词的概率求和 对比垃圾邮件和非垃圾邮件那个值更大 判断是否是垃圾邮件

这里有个优化就是对词的初始出现次数默认置1,防止分子为0导致整个值为0,还有所有词数如果为0的话默认置2,防止除0错误
另一个是为了优化多个0.1左右的值乘积会变得很小,所以用 ln(ab)=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()
  • 1
    点赞
  • 2
    评论
  • 1
    收藏
  • 一键三连
    一键三连
  • 扫一扫,分享海报

©️2021 CSDN 皮肤主题: 编程工作室 设计师:CSDN官方博客 返回首页
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值