机器学习实战(Peter Harrington)-----朴素贝叶斯

贝叶斯理论:选择具有最高概率的决策

方法:计算数据点属于每个类别的概率,并进行比较

贝叶斯理论的核心,实质上就是概率的计算与比较,在这里涉及到条件概率

借用书上的例子来解释这个问题

首先明确我们的问题,即,现在有一个样本x,有一些类别C_{i}(i = 1,2,...,n|n\geqslant 2),我们要做的是求取p(C_{i}|x),即在确定样本是x的情况下,该样本是来自于类别C_{i}的概率。

明确了我们要求解的问题,下面我们介绍贝叶斯准则,贝叶斯准则告诉了我们如何交换条件概率的条件和结果,即如果想求解p(C_{i}|x)可以通过p(x|C_{i})来求解,求解公式如下:

p(C_{i}|x) = \frac{p(x|C_{i})p(C_{i})}{p(x)}

因此,我们现在需要求解的问题变成了求解p(x|C_{i})p(C_{i})(实际上,由于我们最后的应用是对各个结果进行概率比较,所以我们并不需要求解p(x),因为p(x)的值是一定的,它并不会因为C_{i}的变化而变化),下面我们着重来了解p(x|C_{i})

借用书中的例子,如图所示:

总工有7块石头,3块白色和4块黑色,分别放到A、B两个桶里面,分布情况如图所示,现在我们要求从B桶中取到白色石头的概率

P(白色石头|B桶),即已知石头来自B桶的情况下,取出白色石头的概率,很显然,这个概率P=1/3。由此我们引出条件概率计算公式:

p(x|C_{i}) = p(x,C_{i}) / p(C_{i})

在上面这个例子中,易得到p(x,C_{i}) = \frac{1}{7} ,p(C_{i}) = \frac{3}{7},二者相除,结果为\frac{1}{3},也就是上面说的条件概率结果。

至此,我们已经说完了条件概率以及利用贝叶斯理论进行条件和结果的交换,下面,我们介绍实战部分。

 

模型训练:

我们首先需要了解的是其使用的数据格式,如下:

    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

可以看到,对于数据集来说仅有两种类别,分别用0和1表示,下面我们来按照上面石头和桶的例子来分析一下这里应该怎么做。

首先,对于数据集的两种类别,我们可以看作是A、B两个桶,但是现在的情况是A、B两个桶各有3个,而不是像上面例子中的一个桶,这是其一;其次,在上面的例子中,只有黑白两色的石头,而这两种颜色实质上就可以看作特征,但是在现在这个数据集中,其有很多词汇,这些也可以看作是特征(在别的例子中,也会有各种特征,不局限于词汇这一个例子),在这里,我们可以理解为这些词汇就是各种各样颜色的石头,在每个桶中出现的次数都不一样,而根据每个桶中出现的石头不同以及每个桶的类别不同,我们就可以建立概率联系。

首先,我们需要知道总共有多少类的“石头”,实现代码如下图:

def createVocabList(dataSet):
    '''
    find all the words that have appearend from the dataSet
    '''
    vocaSet = set([]);
    for document in dataSet:
        vocaSet = vocaSet | set(document)
    return list(vocaSet)

(需要注意的是set这个函数用法)至此,我们得到了一个包含在数据集中出现过的所有词汇的集合vocabList,下面进行模型的训练(其实就是求取各个单词在每种类别中出现的机率,这样就相当于得到一个关于各个单词的权重向量):

def trainNB0(trainMatrix, trainCategory):
    '''
    Navie Bayes classification training function
    input:  trainMatrix(mat)    document matrix
            trainCategory(vec)  labels of every document
    output: pAbusive(float)     document is an insulting probability
            p0Vect(vec)         the probability of each vocabulary appearing in a insulting article
            p1Vect(vec)         the probability of each vocabulary appearing in a non-insulting article
    '''
    numTrainDocs = len(trainMatrix)     # number of doccuments
    numWords = len(trainMatrix[0])
    pAbusive = sum(trainCategory) / float(numTrainDocs)  #   document is an insulting probability
    # change the initialize value to prevent the denominator is zero
    p0Num = ones(numWords)
    p1Num = ones(numWords)
    p0Denom = 2.0
    p1Denom = 2.0
    # Separate statistically insulting and non-humiliating articles
    for i in range(numTrainDocs):
        if trainCategory[i] == 1:
            # Statistics Insult articles, which words have appeared in the vocabulary and how many times have appeared in total
            p1Num += trainMatrix[i]
            p1Denom += sum(trainMatrix[i])
        else:
            # In statistical non-insulting articles, which words have appeared in the vocabulary and how many times have they appeared in total
            p0Num += trainMatrix[i]
            p0Denom += sum(trainMatrix[i])
    # equivalent to normalization
    # p(w|Ci)
    # use log function to prevent oversize
    p1Vect = log(p1Num / p1Denom)
    p0Vect = log(p0Num / p0Denom)
    return p0Vect, p1Vect, pAbusive

可以看到,在这里实际上就是求取了两个条件概率以及一个P(C_{i}),其中,条件概率部分如果按照上面的“桶和石头”例子来理解,就是分别计算两种桶子中一共有多少块石头,同时分别统计每种石头共出现了多少次,从而得到在两种桶子中每种石头出现的概率p1Vect和p0Vect,需要注意的是,这里条件概率最后的结果是以向量的形式返回的,对应于前面创建的vacabList,需要注意的是我们在这里给每个单词出现次数初始化为1是因为我们这里使用的是朴素贝叶斯模型,也就是说,我们假设各个单词出现的概率是独立的,互不干扰,那么对于一个词向量w,计算p(w|C)就可以表示成p(w1|C)*p(w2|C)*...*p(wn|C),然而这样会出现的结果就是若其中一项为0,那么整体结果都是0,为了避免这种情况故而采取这种方法,由于我们将出现总次数初始化为2,最后求出来的概率是0.5,也就是该单词出现或不出现的概率是不变的,而对于最后的结果采用Log处理的原因是可能某些概率的结果非常的小,这样他们相乘的结果最后会更小,受限于位数表示最后可能直接简化为0,为了避免这种情况,我们采用对数处理。

随后,我们要根据上面得到的权重向量来进行分类处理,如下:

def classifyNB(vec2Classify, p0Vec, p1Vec, pAbusive):
    '''
    Classify vector
    input:  vec2Classify(vec)   Vector to be classified
            p0Vec(vec)
            p1Vec(vec)   
    output: 1/0            Vector category
    '''
    p1 = sum(vec2Classify * p1Vec) + log(pAbusive)
    p0 = sum(vec2Classify * p0Vec) + log(1 - pAbusive)
    if p1 > p0:
        return 1        # insulting
    else:
        return 0        # non-insulting

需要注意的是,由于前面我们用对数处理了p0Vect和p1Vect,因此对整个公式实际上都是采用了对数处理的,也就是原来的p(x|C_{i})p(C_{i})变成了

log(p(x|C_{i})) + log(p(C_{i}))

计算了样本属于两个类别的概率之后,二者相比较,取概率较大的一种作为最终的类别。

 

另:放个链接,讲线性模型和非线性模型的区别,如果有兴趣可以看看线性模型和非线性模型的区别

 

 

 

 

 

 

 

 

 

 

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值