naïve Bayes

标签: 机器学习  贝叶斯  朴素贝叶斯

总体把握

关键词:类条件概率密度/似然(likelihood),贝叶斯决策论,极大似然估计,属性条件独立性假设

判别概率/后验概率  =>>  先验概率+类条件概率密度  =>> 概率密度估计(最大似然准则) =>> 属性条件独立

判别式模型:给定x,通过直接建模P(c|x)来预测c,如决策树,神经网络,SVM

生成式模型:给定x,先对联合概率分布P(x,c)=P(x|c)P(c)建模,然后由此获得P(c|x),如朴素贝叶斯,隐马尔科夫模型(HMMs)

没有什么事情是举例子解决不了的

我们利用鱼的光泽度指标数据x分为两种鱼(\omega_{1},\omega_{2} ). 假定x是连续变量,其分布取决于类别状态,表示成p(x|\omega)的形式,这就是类条件概率密度函数,即类别状态为\omega时的x的概率密度函数。于是p(x|\omega_{1})p(x|\omega_{2})间的区别就表示了鲈鱼与鲑鱼间光泽度的区别。贝叶斯公式:

                                                                    P(c|x) = \frac{P(c)P(x|c)}{P(x)},

P(x)是用于归一化的“证据”因子,类先验概率:p(\omega_{j})=P(c), 类条件概率密度或者称为似然(likelihood)p(x|\omega_{j}),对给定样本x,证据因子P(x) 与类标记无关,因此估计P(c|x)的问题就转化为如何基于训练数据D来估计先验P(c) 和似然P(x|c).

  • 根据大数定律,当训练集包含充足的独立同分布样本时,P(c) 可通过各类样本出现的频率来进行估计.
  • 而直接根据样本出现的频率来估计P(x|c)将会遇到严重的困难,此处引入极大似然估计

左图假定的类条件概率密度函数图,显示了模式处于类别\omega_{i}时,观测某个特定特征值x的概率密度。概率函数已经归一化,因此每条曲线下的面积为1.右图是在先验概率p(\omega_{1})=2/3,p(\omega_{2})=1/3,以及上图给出的类条件概率密度的条件下的后验概率。若x=14,那么属于\omega_{1}的概率约0.92,属于\omega_{2}的概率约为0.08,在每个x处的后验概率之和为1.0。

   

贝叶斯决策论

贝叶斯判定准则:为了最小化总体风险,只需在每个样本上选择那个能使条件风险R(c|x)最小的类别标记.

假设有N种类别标记,即Y = \left \{ c_{1},...,c_{N} \right \}\lambda _{ij}是将一个真实标记为c_{j}的样本误分类为c_{i}所产生的损失。\lambda _{ij} = \left \{ \begin{aligned} 0 & , & i=j \\ 1 & , & i\not= j\\ \end{aligned} \right.

基于后验概率P(c_{i}|x)可获得样本x分类为c_{i}所产生的期望损失,即在样本x上的“条件风险”,一次预期的损失被称为一次风险。

                                                                  R(c_{i}|x) = \sum_{j=1}^{N}\lambda _{ij}P(c_{j}|x)

我们的任务就是寻找一个判定准则h:X\rightarrow Y ,以最小化总体风险

                                       R(h)=E_{x}\left [ R(h(x)|x) \right ] = \int R(h(x)|x) p(x)dx

对每个样本x,若判定准则h(x)能最小化条件风险R(h(x)|x),总体风险R(h)也将被最小化。

                                                               h^{*}(x) = arg\min \limits_{c \in Y}R(c|x)

此时,h^{*}称为贝叶斯最优分类器。最小化后的总风险值R(h^{*})称为贝叶斯风险,1-R(h^{*})反映了分类器所能达到的最好性能。换句话说,基于最小化误差概率

                                            对任给j \not= i,如果P(c_{i}|x) > P(c_{j}|x),则判决为c_{i}

极大似然估计

在典型的监督分类中,估计先验概率没有太大困难,最大的困难在于估计类条件概率密度。估计类条件概率一种常用策略是1.假定其具有某种确定的概率分布形式,2.基于训练样本对概率分布的参数进行估计

例如,假设P(x|c_{i})是一个多元正态分布,均值为\mu _{i},协方差矩阵\Sigma _{i},这样就把问题从估计完全未知的概率密度P(x|c_{i})转化为估计参数\mu _{i}\Sigma _{i}。假设P(x|c)具有确定的形式并且被参数向量\theta _{c}唯一确定,则我们任务是利用训练集D估计参数\theta _{c},我们将P(x|c)记为P(x|\theta _{c}).

D_{c}表示训练集D中第c类的样本合集,假设样本是独立同分布的,则参数\theta_{c}对数据集D_{c}似然

P(D_{c}|\theta_{c}) = \prod _{x \in D_{c}}P(x|\theta_{c})

\theta _{c}进行极大似然估计就是去寻找能最大化似然P(D_{c}|\theta_{c})的参数值\widehat{\theta_{c}}。直观上看,极大似然估计是试图在\theta _{c}所有可能取值中,找到一个能使数据出现的“可能性”最大的值。上式的连乘操作会造成下溢,通常使用对数似然(log-likelihood)

L(\theta _{c})=log P(D_{c}|\theta_{c}) = \sum _{x \in D_{c}} logP(x|\theta_{c})

此时\theta _{c}的最大似然估计\widehat{\theta_{c}}为:

\widehat{\theta _{c}} = arg \max _{\theta _{c}}L(\theta ){c})

例如,在连续属性情形下,假设类条件概率密度函数是正态分布p(x|c) \sim N(\mu _{c},\sigma _{c}^{2}),则参数\mu _{i}\sigma _{c}^{2}的极大似然估计为

\widehat{\mu _{c}} = \frac{1}{|D_{c}|}\sum_{x \in D_{c}}x\\ \widehat{\sigma _{c}^{2}} = \frac {1}{|D_{c}|}\sum_{x \in D_{c}}(x-\widehat{\mu _{c}} )(x-\widehat{\mu _{c}} )^{T}

没有什么事情是举例子解决不了的

上:一维情况下的训练样本,服从方差已知,均值未知的一维高斯分布

中:似然函数 关于均值的函数图像。如果有非常多的训练样本,波形将更窄

下:对数似然函数

作为一个关于\theta的函数,似然函数p(D|\theta),并不表示概率密度,其曲线下的面积也没实际意义。

朴素贝叶斯法

基于贝叶斯公式来估计后验概率P(c|x)的主要困难在于:类条件概率P(x|c)是所有属性上的联合概率,难以从有限的训练样本直接估计而得。为了避开这个障碍,朴素贝叶斯分类器采用“属性条件独立性假设”:对已知类别,假设所有属性相互独立。换言之假设每个属性独立地对分类结果发生影响。根据属性条件独立性假设

P(c|x) = \frac{P(c)P(x|c)}{P(x)}=\frac{P(c)}{P(x)}\prod _{i=1}^{d}P(x_{i}|c)

其中d为属性数目, x_{i}x在第i个属性上的取值。由于对于所有类别来说P(x)相同,因此根据贝叶斯判定准则有

h_{nb}^{*}(x) = arg\max \limits_{c \in Y}P(c)\prod _{i=1}^{d}P(x_{i}|c)

这就是朴素贝叶斯分类器的表达式。其训练过程就是基于训练集D来估计类先验概率P(c),并为每个属性估计条件概率P(x_{i}|c)

P(c) = \frac{|D_{c}|}{|D|}, P(x_{i}|c)=\frac {|D_{c,x_{i}}|}{|D|}

|D_{c,x_{i}}|,表示D_{c}中在第i个属性上取值为x_{i}的样本组成的集合,对于连续属性可考虑概率密度函数,假定p(x_{i}|c) \sim N(\mu _{c,i},\sigma _{c,i}^{2}),其中\mu _{c,i},\sigma _{c,i}^{2}分别是第c类样本在第i个属性上取值的均值和方差,则有

p(x_{i}|c) = \frac{1}{\sqrt{2\pi}\sigma _{c,i}^{2} }exp(- \frac{(x_{i}-\mu_{c,i})^2}{2\sigma _{c,i}^2})

总结

优点:数据较少情况下仍然有效,

缺点:对输入数据较为敏感

代码

"""判断侮辱恶意词汇"""

import numpy as np


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 侮辱性文字, 0 is 正常文字
    return postingList,classVec

def creatVocabList(dataset):
    """
    创建一个包含在所有文档中出现的不重复词的列表
    :param dataset:
    :return:
    """
    vocabSet = set([])
    for document in dataset:
        vocabSet = vocabSet | set(document)
    return list(vocabSet)

def setWord2vec(vocabList, inputset):
    """
    根据vocabList的索引位置,表示单词是否出现,1出现,0未出现
    :param vocabList: 词汇表
    :param inputset: 输入文本
    :return:
    """
    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 bagOfWords2VecMN(vocabList, inputSet):
    """
    由于一个词在文档中出现次数不止一次,所以此函数每遇见一个单词,就会增加词向量中的对应值,而不是一直设为1
    :param vocabList:
    :param inputSet:
    :return:
    """
    returnVec = [0]*len(vocabList)
    for word in inputSet:
        if word in vocabList:
            returnVec[vocabList.index(word)] += 1
    return returnVec


def trainNB_0(trainMatrix, trainCategory):
    """
    根据训练样本,求出先验类概率密度函数,每个单词为侮辱性词语的概率p1Vect,每个单词不是侮辱词语的概率p0Vect,文档属于侮辱类的概率pAbusive
    :param trainMatrix: 文档矩阵
    :param trainCategory: 文档矩阵对应的标签向量
    :return: p(x|0),p(x|1),p(1)
    """
    numTrainLines, numWords = len(trainMatrix),len(trainMatrix[0])
    pAbusive = sum(trainCategory)/float(numTrainLines)

    # 计算联合概率密度时,乘积元素不能为0,否则结果恒为0,将所有词出现次数初始化为1,分母初始化为2
    p0Num,p1Num = np.ones(numWords), np.ones(numWords)
    p0Denom = 2.0; p1Denom = 2.0

    # 统计训练样本中每个单词在侮辱和非侮辱标签中出现的次数
    for i in range(numTrainLines):
        if trainCategory[i] == 1:
            p1Num += trainMatrix[i]
            p1Denom += sum(trainMatrix[i])
        else:
            p0Num += trainMatrix[i]
            p0Denom += sum(trainMatrix[i])
    # 防止下溢
    p1Vect = np.log(p1Num/p1Denom)          #change to log()
    p0Vect = np.log(p0Num/p0Denom)          #change to log()
    return p0Vect,p1Vect,pAbusive

def classifyNB(vec2Classify, p0Vec, p1Vec, pClass1):
    """

    :param vec2Classify: 待分类的词汇索引向量
    :param p0Vec: p(x|1)概率密度
    :param p1Vec:  p(x|0)概率密度
    :param pClass1:  p(1)
    :return:
    """
    p1 = sum(vec2Classify * p1Vec) + np.log(pClass1)  # element-wise mult
    p0 = sum(vec2Classify * p0Vec) + np.log(1.0 - pClass1)
    if p1 > p0:
        return 1
    else:
        return 0


if __name__ == "__main__":
    listPosts, listLabel = loadDataSet()
    myVocabList = creatVocabList(listPosts)
    trainMat = []
    for postinDoc in listPosts:
        trainMat.append(setWord2vec(myVocabList, postinDoc))
    p0V, p1V, pAb = trainNB_0(trainMat,listLabel)
    testEntry = ['love', 'my', 'dalmation']
    thisDoc = np.array(setWord2vec(myVocabList, testEntry))
    print(testEntry, 'classified as: ', classifyNB(thisDoc, p0V, p1V, pAb))
    testEntry = ['stupid', 'garbage']
    thisDoc = np.array(setWord2vec(myVocabList, testEntry))
    print(testEntry, 'classified as: ', classifyNB(thisDoc, p0V, p1V, pAb))

scikit-learn

  • 高斯朴素贝叶斯

GaussianNB 实现了运用于分类的高斯朴素贝叶斯算法。特征的可能性(即概率)假设为高斯分布:

参数 \sigma_y 和 \mu_y 使用最大似然法估计。

p(x_{i}|y) = \frac{1}{\sqrt{2\pi}\sigma _{y}^{2} }exp(- \frac{(x_{i}-\mu_{y})^2}{2\sigma _{y}^2})

  • 多项分布朴素贝叶斯

MultinomialNB 实现了服从多项分布数据的朴素贝叶斯算法,也是用于文本分类的两大经典朴素贝叶斯算法之一。 分布参数由每类 y 的 \theta_y = (\theta_{y1},\ldots,\theta_{yn}) 向量决定, 式中 n 是特征的数量(对于文本分类,是词汇量的大小) \theta_{yi} 是样本中属于类 y 中特征 i 概率 P(x_i \mid y) 。

参数 \theta_y 使用平滑过的最大似然估计法来估计,即相对频率计数:

\hat{\theta}_{yi} = \frac{ N_{yi} + \alpha}{N_y + \alpha n}

式中 N_{yi} = \sum_{x \in T} x_i 是 训练集 T 中 特征 i 在类 y 中出现的次数,

N_{y} = \sum_{i=1}^{|T|} N_{yi} 是类 y 中出现所有特征的计数总和。

先验平滑因子 \alpha \ge 0 应用于在学习样本中没有出现的特征,以防在将来的计算中出现0概率输出。 把 \alpha = 1 被称为拉普拉斯平滑(Lapalce smoothing),而 \alpha < 1 被称为利德斯通(Lidstone smoothing)。

  • 伯努利朴素贝叶斯

BernoulliNB 实现了用于多重伯努利分布数据的朴素贝叶斯训练和分类算法,即有多个特征,但每个特征 都假设是一个二元 (Bernoulli, boolean) 变量。 因此,这类算法要求样本以二元值特征向量表示;如果样本含有其他类型的数据, 一个 BernoulliNB 实例会将其二值化(取决于 binarize 参数)。

伯努利朴素贝叶斯的决策规则基于

P(x_i \mid y) = P(i \mid y) x_i + (1 - P(i \mid y)) (1 - x_i)

与多项分布朴素贝叶斯的规则不同 伯努利朴素贝叶斯明确地惩罚类 y 中没有出现作为预测因子的特征 i ,而多项分布分布朴素贝叶斯只是简单地忽略没出现的特征。

在文本分类的例子中,词频向量(word occurrence vectors)(而非词数向量(word count vectors))可能用于训练和用于这个分类器。 BernoulliNB 可能在一些数据集上可能表现得更好,特别是那些更短的文档。 如果时间允许,建议对两个模型都进行评估。

from sklearn.datasets import load_iris
from sklearn.naive_bayes import GaussianNB,MultinomialNB, BernoulliNB   # 可替换分类器


iris= load_iris()
gnb = GaussianNB()
y_pred = gnb.fit(iris.data, iris.target).predict(iris.data)

print("Number of mislabeled points out of a total %d points : %d" %(iris.data.shape[0],(iris.target != y_pred).sum()))

 

原文链接:加载失败,请重新获取