精华内容
下载资源
问答
  • 10_分类算法-朴素贝叶斯算法应用场景、联合概率和条件概率、朴素贝叶斯介绍、朴素贝叶斯公式、朴素贝叶斯模型流程、半朴素贝叶斯分类器、sklearn朴素贝叶斯实现API、拉普拉斯平滑、优缺点、面试题.pdf
  • 朴素贝叶斯半朴素贝叶斯(AODE)分类器Python实现

    千次阅读 多人点赞 2019-12-28 21:30:41
    机器学习最后一次实验,要求实现朴素贝叶斯和AODE的半朴素贝叶斯分类器。由于老师说可以调用现成的相关机器学习的库,所以我一开始在做朴素贝叶斯分类器的时候,直接调用了sklearn库,很方便,可是问题来了,在做...

    一、概述

    机器学习最后一次实验,要求实现朴素贝叶斯和AODE的半朴素贝叶斯分类器。由于老师说可以调用现成的相关机器学习的库,所以我一开始在做朴素贝叶斯分类器的时候,直接调用了sklearn库,很方便,可是问题来了,在做AODE半朴素贝叶斯分类器的时候,并没有找到集成好的方法。所以就想着自己把半朴素贝叶斯分类器实现了,朴素贝叶斯分类就直接调用库算了。可是让人头大的是,上来就直接实现AODE分类器还是不太科学,还得从基本的贝叶斯原理到朴素贝叶斯开始,所以我又从头看,主要看的这篇博客 西瓜书读书笔记——第七章:贝叶斯分类器,写的非常好,看完之后就基本弄懂了。我感觉实现起来,朴素贝叶斯和半朴素贝叶斯有很多相似之处,索性就先把朴素贝叶斯实现了,正好也能加深一下理解,然后再实现AODE半朴素贝叶斯分类器就会容易些了。

    二、贝叶斯分类器

    2.1 朴素贝叶斯分类器

    (1)贝叶斯分类基本思想简单解释

    首先,贝叶斯分类的思想很简单,假设数据一共有 n n n种类别,即 L a b e l = { L 1 , L 2 , ⋯   , L n } Label=\{L_1,L_2,\cdots,L_n\} Label={L1,L2,,Ln},给定一个样本数据 x = { x 1 , x 2 , ⋯   , x m } x=\{x_1,x_2,\cdots,x_m\} x={x1,x2,,xm},注意,这里的 x x x是一个样本数据, x 1 , x 2 , ⋯   , x m x_1,x_2,\cdots,x_m x1,x2,,xm表示这个数据有 m m m维特征,当知道了样本数据 x x x,根据 x x x计算出来这个数据属于每一种类别的概率 P = { P L 1 , P L 2 , ⋯   , P L n } P=\{P_{L_1},P_{L_2},\cdots,P_{L_n}\} P={PL1,PL2,,PLn},最后将这个数据 x x x划分为最大概率对应的类别。比如,如果 a r g m a x { P L 1 , P L 2 , ⋯   , P L n } = L 2 argmax\{P_{L_1},P_{L_2},\cdots,P_{L_n}\}=L_2 argmax{PL1,PL2,,PLn}=L2,那么 x x x就被划分为 L 2 L_2 L2

    (2)贝叶斯分类基本原理

    其次,贝叶斯分类的实现也很简单。现在已经知道了基本原理,设 x x x所属的类别为 c c c x i x_i xi代表样本 x x x的第 i i i个属性值(第 i i i个维度的值),那么上面所说的要求样本 x x x属于每种类别的概率就记为 P ( c ∣ x ) P(c|x) P(cx),根据贝叶斯模型和极大似然估计原理,那么就有:
    P ( c ∣ x ) = P ( x ∣ c ) P ( c ) P ( x ) = P ( c ) P ( x ) ∏ i = 1 m P ( x i ∣ c ) P(c|x)=\frac{P(x|c)P(c)}{P(x)}=\frac{P(c)}{P(x)}\prod_{i=1}^mP(x_i|c) P(cx)=P(x)P(xc)P(c)=P(x)P(c)i=1mP(xic)
    其中 P ( x ) = ∏ i = 1 m P ( x i ) P(x)=\prod_{i=1}^mP(x_i) P(x)=i=1mP(xi),对于数据 x x x来说,计算对应的每一种类别的概率时, P ( x ) P(x) P(x)是相同的,所以为了计算方便,可以省略掉,记为:
    P ( c ∣ x ) ∝ P ( c ) ∏ i = 1 m P ( x i ∣ c ) P(c|x)\propto P(c)\prod_{i=1}^mP(x_i|c) P(cx)P(c)i=1mP(xic)注:在实现时,为了防止概率连乘导致趋近于0,将 ∏ i = 1 m P ( x i ∣ c ) \prod_{i=1}^mP(x_i|c) i=1mP(xic)取对数变成连加)所以最终计算 x x x所对应的类别就有:
    L ( x ) = a r g m a x P ( c ) ∏ i = 1 m P ( x i ∣ c ) L(x)=argmax P(c)\prod_{i=1}^mP(x_i|c) L(x)=argmaxP(c)i=1mP(xic)这里c是所要求的值。根据这个公式就知道,要求 x x x所属的类别,只要求出 P ( c ) P(c) P(c) P ( x i ∣ c ) P(x_i|c) P(xic)就行了。
    设整个样本数据集为 D D D,当 ∣ D ∣ |D| D足够大时(即样本数量足够多),就可以利用频率估计概率(大数定律)来计算出先验概率 P ( c ) P(c) P(c)
    P ( c ) = ∣ D c ∣ ∣ D ∣ P(c)=\frac{|D_c|}{|D|} P(c)=DDc ∣ D ∣ |D| D代表所有数据的数量, ∣ D c ∣ |D_c| Dc表示类别为 c c c的样本的数量。现在 P ( c ) P(c) P(c)很容易的求出来了,然后就是 P ( x i ∣ c ) P(x_i|c) P(xic)了。

    然而,对于样本属性 x i x_i xi来说,其可分为连续性样本属性离散型样本属性。先理解一下什么是“离散型样本属性”,那么“连续型”就比较容易理解了。

    离散型样本属性”:比如,对于西瓜 A A A来说, A A A就是整个西瓜家族里面的一个样本,那么 A A A的属性就会有 { 外 皮 颜 色 , 敲 击 声 音 , 触 摸 手 感 , ⋯   } \{外皮颜色,敲击声音,触摸手感,\cdots\} {},而对于“外皮颜色”这个属性来说,它的取值可能有 { 黄 色 , 绿 色 , 青 绿 色 , ⋯   } \{黄色,绿色,青绿色,\cdots\} {绿绿},这个属性的取值是离散的,有限的,那么这个属性就是“离散型”属性了,另外两个属性也是一样。对于离散型样本属性的条件概率计算公式也是根据频率估计概率得到:
    P ( x i ∣ c ) = ∣ D c , x i ∣ ∣ D c ∣ P(x_i|c)=\frac{|D_{c,x_i}|}{|D_c|} P(xic)=DcDc,xi ∣ D c , x i ∣ |D_{c,x_i}| Dc,xi为类别 c c c中的所有数据的第 i i i个属性值为 x i x_i xi的样本的数量。

    连续型样本属性”:还是对西瓜 A A A来说, A A A除了上面提到的那些属性之外,还有 { 含 糖 量 , 水 分 } \{含糖量,水分\} {}这些属性,这两个属性如果以定量方法(精确地测量数值)来表示,比如含糖量为 45.678 % 45.678\% 45.678%,这样就叫做“连续型”属性了,但是如果以定性方法来表示,比如将含糖量划分为 { 低 , 中 , 高 } \{低,中,高\} {}三个等级,那么就是“离散型”属性了。对于连续型样本属性的条件概率计算公式使用高斯核密度估计(应该是这么叫吧,希望数理统计没白学)得到:
    P ( x i ∣ c ) = 1 2 π σ c , i e x p ( − ( x i − μ c , i ) 2 2 σ c , i 2 ) P(x_i|c)=\frac{1}{\sqrt{2\pi}\sigma_{c,i}}exp\left(-\frac{(x_i-\mu_{c,i})^2}{2\sigma^2_{c,i}}\right) P(xic)=2π σc,i1exp(2σc,i2(xiμc,i)2)其中 μ c , i \mu_{c,i} μc,i σ c , i \sigma_{c,i} σc,i分别为第 c c c类样本在第 i i i个属性取值的均值和标准差。

    为了避免数据集不充分而导致估计概率为0的情况,需要在实现过程中引入拉普拉斯修正(具体拉普拉斯修正方法也很简单),但我为了图方便,直接在先验概率和条件概率(针对离散型属性)的分子和分母都 +1 了(实际测试中,并没有发现有太大的差别)。

    2.2 AODE半朴素贝叶斯分类器

    首先,要知道什么是AODE(Averaged One-Dependent Estimator),就要先了解什么是SPODE(Super-Parent One-Dependent Estimator)。在上面所讲的朴素贝叶斯分类都是基于样本的所有属性是相互独立的,那么如果某些属性存在依赖关系怎么办呢。SPODE就是假设样本的每个属性都依赖于某一个属性,这个属性就叫做“超父”。比如,将 x 1 x_1 x1属性设置为“超父”,那么计算 x x x属于第 c c c类数据的概率公式为:
    P ( c ∣ x ) ∝ P ( c ) ∏ i = 1 m P ( x i ∣ c , x 1 ) P(c|x)\propto P(c)\prod_{i=1}^mP(x_i|c,x_1) P(cx)P(c)i=1mP(xic,x1)而AODE就是在此基础上,将样本的属性依次作为超父来计算概率,最后求和,同时,假设类别 c c c也依赖于样本的属性,那么计算 x x x属于类别 c c c的概率公式为:
    P ( c ∣ x ) ∝ ∑ i = 1 m P ( c , x i ) ∏ j = 1 m P ( x j ∣ c , x i ) P(c|x)\propto \sum_{i=1}^m P(c,x_i)\prod_{j=1}^mP(x_j|c,x_i) P(cx)i=1mP(c,xi)j=1mP(xjc,xi)同样的,利用频率估计概率的方法可以得到:
    P ( x j ∣ c , x i ) = ∣ D c , x i , x j ∣ ∣ D c , x i ∣ P(x_j|c,x_i)=\frac{|D_{c,x_i,x_j}|}{|D_{c,x_i}|} P(xjc,xi)=Dc,xiDc,xi,xj与朴素贝叶斯分类相同,实现时也要引入拉普拉斯修正,我还是分子分母都 +1 了。

    通过观察 x x x属于类别 c c c的概率公式就能看出,这个方法的时间复杂度很高,实际上,对于每一个样本,计算出分别属于哪一个类的概率一共有三层循环(不知是否有优化方法,但是时间复杂度几乎不可能降低了)。实现之后,这个方法并没有进行实验结果的验证,因为时间代价太大,所以我猜测,这也是为什么sklearn中有朴素贝叶斯却没有AODE半朴素贝叶斯方法的原因了。

    三、实验结果与代码

    3.1 实验结果

    对于朴素贝叶斯分类器的实现,我只实现了离散型样本属性的分类(连续性属性也比较容易,只要把条件概率函数换成高斯核即可),使用了MNIST、Yale和COIL20这三个数据对其进行了实验,使用ACC评价标准对其进行评价。(注:由于AODE时间成本过高,不太适合属性维度较多数据,我没有进行数据实验,所以我也不知道对不对,不过按照朴素贝叶斯的思路来应该也不会错吧。。。)

    方法\数据MNISTYaleCOIL20
    McQueen_NBC0.9511
    GaussianNB0.550.81

    这里我就没有将数据集划分成测试集和训练集了,这三组数据测试集是在训练集中每个类别数据分别抽取前0.5%,10%,1%得到的。McQueen_NBC方法是我自己实现的朴素贝叶斯分类器(实际上是多项式贝叶斯),适用于离散属性样本,而GaussianNB是调用的sklearn库的方法,这个方法是基于连续型属性的,由结果可以看出,在MNIST和Yale这两个数据上,连续型准确率不如离散型(因为这两个数据是离散型样本数据)。

    3.2 完整代码

    datadvi.py

    from scipy.io import loadmat
    import numpy as np
    
    def divdata():
        filename = 'C:/Users/ALIENWARE/Documents/作业/机器学习/datasets/' + input("input name of data file: ")
        data = loadmat(filename)
    #    print(data['X'])
    
    
        if filename == 'C:/Users/ALIENWARE/Documents/作业/机器学习/datasets/COIL20.mat':
            dataX = data['fea']
            dataY = data['gnd'][0]
    
        else:
            dataX = data['X']
            dataY = data['Y'].T[0]
    
        print(len(dataX[0]))
    
        divideornot = input("divide data or not?(Yes/No): ")
        if divideornot == 'Yes':
            dataX_train = []
            dataX_predict = []
            dataY_train = []
            dataY_predict = []
            num_Y = np.unique(dataY).astype(int)
            for i in range(len(num_Y)):
                temp = dataY == num_Y[i]
                temp.astype(float)
                num_Y[i] = np.sum(temp)
                flag = 0
                for j in range(len(dataY)):
                    if temp[j] == 1:
                        if flag < int(round(0.9 * num_Y[i])):
                            dataX_train.append(dataX[j])
                            dataY_train.append(dataY[j])
                            flag += 1
                        else:
                            dataX_predict.append(dataX[j])
                            dataY_predict.append(dataY[j])
    
            dataX_train = np.array(dataX_train)
            dataX_predict = np.array(dataX_predict)
            dataY_train = np.array(dataY_train)
            dataY_predict = np.array(dataY_predict)
            return dataX_train,dataX_predict,dataY_train,dataY_predict
        else:
            return dataX,dataX,dataY,dataY
    
    def decreaseData(dataX,dataY):
        dataX_train = []
        dataY_train = []
        num_Y = np.unique(dataY).astype(int)
        print("this data has {} samples".format(len(dataX)))
        ratio = float(input("input the ratio you want to decrease: "))
        for i in range(len(num_Y)):
            temp = dataY == num_Y[i]
            temp.astype(float)
            num_Y[i] = np.sum(temp)
            flag = 0
            for j in range(len(dataY)):
                if temp[j] == 1:
                    if flag < round(ratio * num_Y[i]):
                        dataX_train.append(dataX[j])
                        dataY_train.append(dataY[j])
                        flag += 1
    
        dataX_train = np.array(dataX_train)
        dataY_train = np.array(dataY_train)
        print(dataX_train)
    
        return dataX_train,dataY_train
    

    Acc.py

    import numpy as np
    
    def acc(L1, L2):
        sum = np.sum(L1[:]==L2[:])
        return sum/len(L2)
    

    NBC.py

    import math
    import numpy as np
    import datadvi
    import Acc
    
    #加载数据
    def loadData(filename):
        return datadvi.divdata()
    
    #按标签类别生成不同标签样本组成的集合,返回值为每种类别样本的索引
    def divSamples(dataY):
        label = np.unique(dataY)
        D = []
        for i in label:
            D.append(np.argwhere(dataY==i).T[0])
        return np.array(D)
    
    # 计算第c类样本在第i个属性上取值的均值和标准差,smaple_cIndx是第c类样本的索引(用于连续型属性,此次未用到)
    def calcMuSig(sample_cIndx,i,D):
        mu =  np.average(D[sample_cIndx][:,i])
        sigma = np.std(D[sample_cIndx][:,i])
        return mu,sigma
    
    #计算类先验概率P(c),
    def beforeProb(sample_cIndx,D):
        return float(len(sample_cIndx)+1)/(D.shape[0]+1)
    
    #计算离散型条件概率P(xi|c)
    def condProb_disp(i,xi,sample_cIndx,D):
        numerator = np.sum(D[sample_cIndx][:,i]==xi)+1
        denominator = len(sample_cIndx)+1
        return float(numerator)/denominator
    
    #计算连续型条件概率P(xi|c)
    def condProb_cont(i,xi,sample_cIndx,D):
        mu,sigma = calcMuSig(sample_cIndx,i,D)
        prob = 1/(math.sqrt(2*3.14)*sigma)*math.exp(-float((xi-mu)*(xi-mu))/(2*sigma*sigma))
        return prob
    
    #计算类后验概率P(c|x)
    def afterProb(sample_x,c,dataX,dataY):
        sample_c = divSamples(dataY)
        p = beforeProb(sample_c[c],dataX)
        #p = beforeProb(sample_c[c],dataX)
        p1 = 0
        for i in range(len(sample_x)):
            p1 += math.log10(condProb_disp(i,sample_x[i],sample_c[c],dataX))
            #p1 *= condProb_cont(i,sample_x[i],sample_c[c],dataX) #会下溢
        return p*p1
    
    #计算最大概率对应的类
    def argMaxProb_c(sample_x,dataX,dataY):
        label = np.unique(dataY)
        argProb1 = []
        for c in label:
            temp_prob = afterProb(sample_x,c-1,dataX,dataY)
            argProb1.append(temp_prob)
        argProb = np.array(argProb1)
        return label[np.argmax(argProb)]
    
    
    #将所有数据分类
    def bayesClassifier(dataPredict,dataX,dataY):
        pred = []
        for sample_x in dataPredict:
            pred.append(argMaxProb_c(sample_x,dataX,dataY))
            print(len(pred))
        return pred
    
    dataX_train, dataX_predict, dataY_train, dataY_predict = datadvi.divdata()
    dataX_predict,dataY_predict = datadvi.decreaseData(dataX_predict,dataY_predict)
    print(len(dataX_predict))
    sample_c = divSamples(dataY_train)
    pred = bayesClassifier(dataX_predict,dataX_train,dataY_train)
    print(pred)
    print(Acc.acc(pred,dataY_predict))
    

    AODE.py

    import math
    import numpy as np
    import datadvi
    import Acc
    import RBFNN
    
    #加载数据
    def loadData(filename):
        return datadvi.divdata()
    
    #按标签类别生成不同标签样本组成的集合,返回值为每种类别样本的索引
    def divSamples(dataY):
        label = np.unique(dataY)
        D = []
        for i in label:
            D.append(np.argwhere(dataY==i).T[0])
        return np.array(D)
    
    
    #计算先验概率P(c,xi)
    def beforeProb(sample_cIndx,i,xi,D):
        numerator = len(np.argwhere(D[sample_cIndx][:,i]==xi).T[0])+1 #索引改变了,但是数量没变
        denominator = D.shape[0]+1 #此处1需被替换为N*Ni
        return float(numerator)/denominator
    
    
    #计算条件概率P(xj|c,xi)
    def condProb(i,xi,j,xj,sample_cIndx,D):
        D_c = D[sample_cIndx]
        D_c_xi = D_c[np.argwhere(D_c[:,i]==xi).T[0]]
        D_c_xi_xj = D_c_xi[np.argwhere(D_c_xi[:,j]==xj).T[0]]
        numerator = len(D_c_xi_xj)+1
        denominator = len(D_c_xi)+1
        return float(numerator)/denominator
    
    #计算后验概率P(c|x)
    def afterProb(sample_x,c,dataX,dataY):
        sample_c = divSamples(dataY)
        prob = 0
        for i in range(len(sample_x)):
            p1 = 0
            p = beforeProb(sample_c[c],i,sample_x[i],dataX)
            for j in range(len(sample_x)):
                p1 += math.log10(condProb(i,sample_x[i],j, sample_x[j],sample_c[c], dataX))  #防止下溢
            prob += p*p1
        return prob
    
    
    #计算最大概率对应的类
    def argMaxProb_c(sample_x,dataX,dataY):
        label = np.unique(dataY)
        argProb1 = []
    
        for c in label:
            temp_prob = afterProb(sample_x, c - 1, dataX, dataY)
            argProb1.append(temp_prob)
    
        argProb = np.array(argProb1)
        return label[np.argmax(argProb)]
    
    
    #将所有数据分类
    def bayesClassifier(dataPredict,dataX,dataY):
        pred = []
        for sample_x in dataPredict:
            label_pred = argMaxProb_c(sample_x,dataX,dataY)
            pred.append(label_pred)
            print(len(pred))
        return pred
    
    
    dataX_train, dataX_predict, dataY_train, dataY_predict = datadvi.divdata()
    dataX_predict,dataY_predict = datadvi.decreaseData(dataX_predict,dataY_predict)
    
    
    print(len(dataX_predict))
    
    pred = bayesClassifier(dataX_predict,dataX_train,dataY_train)
    print(Acc.acc(pred,dataY_predict))
    

    四、总结

    机器学习四次实验全部结束了,学到了很多知识,感觉很充实,体会到了Python的强大,还好之前自学了Python,不然真可能现在被逼的去用MATLAB(不是针对MATLAB,我只想说C++天下第一,手动狗头)了。虽然机器学习课时短,加上理论课没有好好听,浪费了很多时间,不过实验好好做了感觉把知识又全都补回来了。接下来又得去做计算机视觉的实验了,我哭了。。。

    展开全文
  • 贝叶斯分类器理论知识。包括贝叶斯决策论,朴素贝叶斯分类器,半朴素贝叶斯分类器。
    学习贝叶斯分类器,理论。


    展开全文
  • 半朴素贝叶斯算法

    2019-09-21 18:33:50
    前置知识: ... 朴素贝叶斯算法:https://blog.csdn.net/qq_32172681/article/details/101112211 ...1.、半朴素贝叶斯的“” 前面说到,朴素贝叶斯(NB)的‘朴素’就体现在它假设各属性之间没有相互依赖,可以...

    前置知识:

    贝叶斯公式:https://blog.csdn.net/qq_32172681/article/details/98032205

    朴素贝叶斯算法:https://blog.csdn.net/qq_32172681/article/details/101112211

     

    1.、半朴素贝叶斯的“半”

    前面说到,朴素贝叶斯(NB)的‘朴素’就体现在它假设各属性之间没有相互依赖,可以简化贝叶斯公式中P(x|c)的计算。但事实上,属性直接完全没有依赖的情况是非常少的。如果简单粗暴用朴素贝叶斯建模,泛化能力和鲁棒性都难以达到令人满意。

    这就可以引出主角半朴素贝叶斯了,它假定每个属性最多只依赖一个(或k个)其他属性。它考虑属性间的相互依赖,但假定依赖只有一个(ODE)或k个(kDE)其他属性。这就是半朴素贝叶斯的’半’所体现之处。半朴素贝叶斯分类器适当考虑一部分属性之间的相互依赖信息,从而既不需要进行联合概率计算,又不至于彻底忽略比较强的属性依赖关系。

    "独依赖估计" (One-Dependent Estimator,简称ODE)是半朴素贝叶斯分类器最常用的一种策略。所谓"独依赖"就是假设每个属性在类别之外最多仅依赖于一个其他属性。

    于是半朴素贝叶斯分类器的公式为:

    其中为属性所依赖的属性,称为的父属性。

    问题的关键就转化为如何确定每个属性的父属性,不同的做法产生不同的独依赖分类器。

     

    2、 常见的半朴素贝叶斯算法SPODE和TAN

    SPODE算法:假设所有属性都依赖同一个属性,这个属性称为“超父”属性。

    TAN算法:通过最大带权生成树算法确定属性之间的依赖关系,简单点说,就是每个属性找到跟自己最相关的属性,然后形成一个有向边(只能往一个方向)。

    下面的图借自周志华老师西瓜书:

    è¿éåå¾çæè¿°

     

    3、详解TAN算法

    步骤如下:

    (1)计算任意两个属性之间的条件互信息(CMI,即相互依赖程度)

    è¿éåå¾çæè¿°

    (2)以每个属性为节点(nodenode),CMI为边(edgeedge)形成一张图。找到这张图的最大带权生成树。即找到一个节点之间的连接规则,这个规则满足三个条件:

    • 能够连接所有节点;
    • 使用最少数目的边;
    • 边长(CMI)总和最大

    (3)再把节点连接关系设置为有向,即从父节点指向子节点。在这里把最先出现的属性设置为根节点,再由根节点出发来确定边的方向。在代码中把第2步和第3步一起执行。

    (4)求  

     

     

    参考:http://www.luyixian.cn/news_show_3477.aspx

     

    展开全文
  • 而朴素朴素贝叶斯分类是贝叶斯分类中最简单,也是常见的一种分类方法。这篇文章我尽可能用直白的话语总结一下我们学习会上讲到的朴素贝叶斯分类算法,希望有利于他人理解。 1 分类问题综述 ...

    贝叶斯分类

    贝叶斯分类是一类分类算法的总称,这类算法均以贝叶斯定理为基础,故统称为贝叶斯分类。而朴素朴素贝叶斯分类是贝叶斯分类中最简单,也是常见的一种分类方法。这篇文章我尽可能用直白的话语总结一下我们学习会上讲到的朴素贝叶斯分类算法,希望有利于他人理解。


    1   分类问题综述


     对于分类问题,其实谁都不会陌生,日常生活中我们每天都进行着分类过程。例如,当你看到一个人,你的脑子下意识判断他是学生还是社会上的人;你可能经常会走在路上对身旁的朋友说“这个人一看就很有钱”之类的话,其实这就是一种分类操作。


    既然是贝叶斯分类算法,那么分类的数学描述又是什么呢?


    从数学角度来说,分类问题可做如下定义:已知集合,确定映射规则y = f(x),使得任意有且仅有一个,使得成立


    其中C叫做类别集合,其中每一个元素是一个类别,而I叫做项集合(特征集合),其中每一个元素是一个待分类项,f叫做分类器。分类算法的任务就是构造分类器f。


    分类算法的内容是要求给定特征,让我们得出类别,这也是所有分类问题的关键。那么如何由指定特征,得到我们最终的类别,也是我们下面要讲的,每一个不同的分类算法,对应着不同的核心思想。


    本篇文章,我会用一个具体实例,对朴素贝叶斯算法几乎所有的重要知识点进行讲解。


    2   朴素贝叶斯分类


    那么既然是朴素贝叶斯分类算法,它的核心算法又是什么呢?

    是下面这个贝叶斯公式:




    换个表达形式就会明朗很多,如下:




    我们最终求的p(类别|特征)即可!就相当于完成了我们的任务。


    3   例题分析


    下面我先给出例子问题。


    给定数据如下:




    现在给我们的问题是,如果一对男女朋友,男生想女生求婚,男生的四个特点分别是不帅,性格不好,身高矮,不上进,请你判断一下女生是还是不嫁


    这是一个典型的分类问题,转为数学问题就是比较p(嫁|(不帅、性格不好、身高矮、不上进))与p(不嫁|(不帅、性格不好、身高矮、不上进))的概率谁的概率大,我就能给出嫁或者不嫁的答案!

    这里我们联系到朴素贝叶斯公式:




    我们需要求p(嫁|(不帅、性格不好、身高矮、不上进),这是我们不知道的,但是通过朴素贝叶斯公式可以转化为好求的三个量.


    p(不帅、性格不好、身高矮、不上进|嫁)、p(不帅、性格不好、身高矮、不上进)、p(嫁)(至于为什么能求,后面会讲,那么就太好了,将待求的量转化为其它可求的值,这就相当于解决了我们的问题!


    4   朴素贝叶斯算法的朴素一词解释


    那么这三个量是如何求得?


    是根据已知训练数据统计得来,下面详细给出该例子的求解过程。

    回忆一下我们要求的公式如下:




    那么我只要求得p(不帅、性格不好、身高矮、不上进|嫁)、p(不帅、性格不好、身高矮、不上进)、p(嫁)即可,好的,下面我分别求出这几个概率,最后一比,就得到最终结果。


    p(不帅、性格不好、身高矮、不上进|嫁) = p(不帅|嫁)*p(性格不好|嫁)*p(身高矮|嫁)*p(不上进|嫁),那么我就要分别统计后面几个概率,也就得到了左边的概率!


    等等,为什么这个成立呢?学过概率论的同学可能有感觉了,这个等式成立的条件需要特征之间相互独立吧!


    对的!这也就是为什么朴素贝叶斯分类有朴素一词的来源,朴素贝叶斯算法是假设各个特征之间相互独立,那么这个等式就成立了!


    但是为什么需要假设特征之间相互独立呢?



    1、我们这么想,假如没有这个假设,那么我们对右边这些概率的估计其实是不可做的,这么说,我们这个例子有4个特征,其中帅包括{帅,不帅},性格包括{不好,好,爆好},身高包括{高,矮,中},上进包括{不上进,上进},那么四个特征的联合概率分布总共是4维空间,总个数为2*3*3*2=36个。


    36个,计算机扫描统计还可以,但是现实生活中,往往有非常多的特征,每一个特征的取值也是非常之多,那么通过统计来估计后面概率的值,变得几乎不可做,这也是为什么需要假设特征之间独立的原因。


    2、假如我们没有假设特征之间相互独立,那么我们统计的时候,就需要在整个特征空间中去找,比如统计p(不帅、性格不好、身高矮、不上进|嫁),


    我们就需要在嫁的条件下,去找四种特征全满足分别是不帅,性格不好,身高矮,不上进的人的个数,这样的话,由于数据的稀疏性,很容易统计到0的情况。 这样是不合适的。


    根据上面俩个原因,朴素贝叶斯法对条件概率分布做了条件独立性的假设,由于这是一个较强的假设,朴素贝叶斯也由此得名!这一假设使得朴素贝叶斯法变得简单,但有时会牺牲一定的分类准确率。


    好的,上面我解释了为什么可以拆成分开连乘形式。那么下面我们就开始求解!


    我们将上面公式整理一下如下:




    下面我将一个一个的进行统计计算(在数据量很大的时候,根据中心极限定理,频率是等于概率的,这里只是一个例子,所以我就进行统计即可)。


    p(嫁)=?

    首先我们整理训练数据中,嫁的样本数如下:



    则 p(嫁) = 6/12(总样本数) = 1/2


    p(不帅|嫁)=?统计满足样本数如下:



    则p(不帅|嫁) = 3/6 = 1/2 在嫁的条件下,看不帅有多少


    p(性格不好|嫁)= ?统计满足样本数如下:



    则p(性格不好|嫁)= 1/6


    p(矮|嫁) = ?统计满足样本数如下:



    则p(矮|嫁) = 1/6


    p(不上进|嫁) = ?统计满足样本数如下:



    则p(不上进|嫁) = 1/6


    下面开始求分母,p(不帅),p(性格不好),p(矮),p(不上进)

    统计样本如下:




    不帅统计如上红色所示,占4个,那么p(不帅) = 4/12 = 1/3




    性格不好统计如上红色所示,占4个,那么p(性格不好) = 4/12 = 1/3




    身高矮统计如上红色所示,占7个,那么p(身高矮) = 7/12




    不上进统计如上红色所示,占4个,那么p(不上进) = 4/12 = 1/3


    到这里,要求p(不帅、性格不好、身高矮、不上进|嫁)的所需项全部求出来了,下面我带入进去即可,



    = (1/2*1/6*1/6*1/6*1/2)/(1/3*1/3*7/12*1/3)


    下面我们根据同样的方法来求p(不嫁|不帅,性格不好,身高矮,不上进),完全一样的做法,为了方便理解,我这里也走一遍帮助理解。首先公式如下:




    下面我也一个一个来进行统计计算,这里与上面公式中,分母是一样的,于是我们分母不需要重新统计计算!


    p(不嫁)=?根据统计计算如下(红色为满足条件):




    则p(不嫁)=6/12 = 1/2


    p(不帅|不嫁) = ?统计满足条件的样本如下(红色为满足条件):




    则p(不帅|不嫁) = 1/6


    p(性格不好|不嫁) = ?据统计计算如下(红色为满足条件):



    则p(性格不好|不嫁) =3/6 = 1/2


    p(矮|不嫁) = ?据统计计算如下(红色为满足条件):



    则p(矮|不嫁) = 6/6 = 1


    p(不上进|不嫁) = ?据统计计算如下(红色为满足条件):


    则p(不上进|不嫁) = 3/6 = 1/2


    那么根据公式:


    p (不嫁|不帅、性格不好、身高矮、不上进) = ((1/6*1/2*1*1/2)*1/2)/(1/3*1/3*7/12*1/3)

    很显然(1/6*1/2*1*1/2) > (1/2*1/6*1/6*1/6*1/2)


    于是有p (不嫁|不帅、性格不好、身高矮、不上进)>p (嫁|不帅、性格不好、身高矮、不上进)


    所以我们根据朴素贝叶斯算法可以给这个女生答案,是不嫁!!!!


    5   朴素贝叶斯分类的优缺点


    优点:

    (1) 算法逻辑简单,易于实现(算法思路很简单,只要使用贝叶斯公式转化医学即可!

    (2)分类过程中时空开销小(假设特征相互独立,只会涉及到二维存储


    缺点:


    理论上,朴素贝叶斯模型与其他分类方法相比具有最小的误差率。但是实际上并非总是如此,这是因为朴素贝叶斯模型假设属性之间相互独立,这个假设在实际应用中往往是不成立的,在属性个数比较多或者属性之间相关性较大时,分类效果不好。


    而在属性相关性较小时,朴素贝叶斯性能最为良好。对于这一点,有半朴素贝叶斯之类的算法通过考虑部分关联性适度改进。


    整个例子详细的讲解了朴素贝叶斯算法的分类过程,希望对大家的理解有帮助~


    朴素贝叶斯分类器的一个重要假定:分类对应的各个属性间是相互独立的,然而在现实应用中,这个往往难以做到,那怎么办呢?

    半朴素贝叶斯分类

    很简单,适当考虑一部分属性间的相互依赖关系,这种放松后的分类称为半朴素贝叶斯分类,其中最常用的策略:假定每个属性仅依赖于其他最多一个属性,称其依赖的这个属性为其超父属性,这种关系称为:独依赖估计(ODE)。


    因此,对某个样本x 的预测朴素贝叶斯公式就由如下:

    0?wx_fmt=png

    修正为如下的半朴素贝叶斯分类器公式:

    0?wx_fmt=png

    从上式中,可以看到类条件概率 P(xi | c) 修改为了 xi 依赖于分类c 和 一个依赖属性pai 。

    半朴素贝叶斯例子解释

    在阐述朴素贝叶斯分类器用到的数据集还是用到此处,数据集如下:



    #大小颜色 形状 标签
    1
    青色 非规则
    2红色 非规则
    3红色 圆形
    4青色 圆形
    5青色 非规则
    6红色 圆形
    7青色 非规则
    8红色 非规则
    9青色 圆形
    10红色 圆形



    测试集上要预测的某个样本如下:

    #大小颜色 形状 标签
    11
    青色 圆形 ?


    采用拉普拉斯修正后的先验概率P(c)的计算公式:

    0?wx_fmt=png

    基于类c和类外的依赖属性pai的条件概率计算公式如下:

    0?wx_fmt=png

    属性的依赖关系定义如下:

    • 大小的依赖属性为:形状,且属性取值为大时依赖形状为圆形

    • 颜色不存在依赖属性;

    • 形状的依赖属性为大小,且属性取值为圆形时依赖大小为大


    先验概率 P(c) ,

    P(c = 好果)=  (4+1) / (10+2) = 5/12

    P(c = 一般) = (6+1) / (10+2) = 7/12


    带有依赖属性的类条件概率:

    P(大小=大 | c=好果,形状=圆形) =   (2+1)/(3+2) = 3/5

    P(颜色=青色 | c=好果) = (0+1)/(4+2) = 1/6

    P(形状=圆形 | c=好果,大小=大) = (2+1) / (3+2) = 3/5


    P(大小=大 | c=一般,形状=圆形) =  (1+1) /( 2+2) = 2/4

    P(颜色=青色 | c=一般) = (5+1)/(6+2) = 6/8

    P(形状=圆形 | c=一般,大小=大) =  (1+1)/(3+2) = 2/5


    因此:  

    P(c=好果) * P(大小=大 | c=好果,形状=圆形) * P(颜色=青色 | c=好果) * P(形状=圆形 | c=好果,大小=大)  

    = 5/12 * 3/5 * 1/6 * 3/5 

    = 0.025


    P(c=一般) * P(大小=大 | c=一般,形状=圆形) * P(颜色=红色 | c=一般) * P(形状=圆形 | c=一般,大小=大)  

    = 7/12 * 2/4 * 6/8 * 2/5

    = 0.0875


    因此,测试集上要预测的这个样本和朴素贝叶斯分类器要预测的结果是相同的,都为一般的果子。


    这种依赖属性选取算法称为超父ODE算法:SPODE。显然,这个算法是每个属性值只与其他唯一 一个有依赖关系。基于它之上,又提出另一种基于集成学习机制,更为强大的独依赖分类器,AODE,它的算法思想是怎么样的呢?

    AODE算法

    这个算法思路很简单,就是在SPODE算法的基础上在外面包一个循环吧,说的好听点就是尝试将每个属性作为超父属性来构建SPODE吧,请看下面的公式,是不是在SPODE外面包了一个循环,然后求它们的和作为当前预测样本的得分值啊:

    0?wx_fmt=png

    上面的求和符号实质兑换为代码不就是一个for循环吗。

    总结和展望

    以上介绍了考虑属性间有依赖关系时的半朴素贝叶斯分类器。结合近几天的阐述,这些(半)朴素贝叶斯分类器,都有一个共同特点:假设训练样本所有属性变量的值都已被观测到,训练样本是完整的。

    然后,现实生活中,有时候拿到的数据集缺少某个属性的观测值(这种变量称为隐变量),在这种存在“未观测”变量的情形下,是否仍能对模型参数进行估计呢?

     比如,两箱苹果,其中从A箱中取到一个好苹果的概率大于从B箱中取得,如果有一堆苹果来自于A箱和B箱,但是不知道某个苹果来自于A箱还是B箱,进行了5组实验,每组抽取10个苹果,每组抽到的好苹果和一般苹果都记录到纸上,通过这些观测数据,能得出从A或B箱中取到一个好苹果的概率吗?

    这个预测,无形中增加了一个隐变量:苹果出处这属性吧(取值:A箱或B箱)。在这种情况下,介绍一种常用的估计类似参数隐变量的利器:Expectation-Maximization 算法(期望最大算法)。EM算法正如它的名字那样每轮迭代经过两步:E步和M步,迭代,直至收敛。

    谢谢您的阅读!

    原文地址:
    http://blog.csdn.net/xo3ylAF9kGs/article/details/78643424?locationNum=5&fps=1

    展开全文
  • 而朴素朴素贝叶斯分类是贝叶斯分类中最简单,也是常见的一种分类方法。这篇文章我尽可能用直白的话语总结一下我们学习会上讲到的朴素贝叶斯分类算法,希望有利于他人理解。 1   分类问题综述  ...
  • 半朴素贝叶斯分类器

    千次阅读 2018-10-20 09:13:18
    由此有了半朴素贝叶斯分类器,适当考虑一部分属性之间的相互依赖关系。"独依赖估计" (One-Dependent Estimator ,简称 ODE)是半朴素贝叶斯分类器最常用的一种策略。"独依赖"就是假设每个属性在...
  • 由于作为朴素贝叶斯分类器的主要特征的条件独立性假设条件过强且在不同数据集上表现出的...从降低后验概率的估计误差入手提出一种条件熵匹配的半朴素贝叶斯分类器。实验证明,该方法能有效提高朴素贝叶斯分类器的性能。
  • 所以有人就尝试对属性条件独立性假设做出一定的放松,于是就产生了“半朴素贝叶斯分类器”。 假设每个属性最多仅依赖一个其他属性:问题转变为确定每个属性的依赖的属性(父属性)。 SPODE方法:假设所有的属性...
  • 半朴素贝叶斯分类器半朴素贝叶斯分类器的基本思想: 适当考虑一部分属性间的相互依赖信息。 独依赖估计(One-Dependent Estimator,简称ODE) 是半朴素贝叶斯分类器最常用的一种策略。P(c|x)∝P(c)∏i=1dP(xi|c,pai)...
  • 基于周志华《机器学习》,通俗讲解半朴素贝叶斯分类器
  • 现实情况是属性全部独立基本上是不可能的,而如果完全考虑各属性之间的相关性会大大增加计算复杂度,所以才引入半朴素贝叶斯网络:进一步放松条件独立性假设,即假设部分属性之间存在依赖关系。 独依赖估计:每个...
  • 为什么需要半朴素贝叶斯分类器 1:后验概率P(c∣x)P(c\mid\mathbf{x})计算起来比较困难。 2:属性条件独立性假设在现实任务中往往很难成立。 半朴素贝叶斯分类器的基本思想 适当考虑一部分属性之间的相互依赖...
  • 朴素贝叶斯存在两个问题需要考虑:1、特征独立性假设;2、在训练样本不足的前提下先验概率的估计方法。半朴素贝叶斯改进了这两个问题。
  • 概率机器学习的系列博文已经写到第四篇了,依然关注者乏。虽说来只是自己的学习记录,不过这样下去显得自己贡献值比较低下。...1. 半朴素贝叶斯的“” 前面说到,朴素贝叶斯(NB)的‘朴素’就体现在它假设...
  • 朴素贝叶斯设定了一个假设前提:输入实例的各个属性之间是相互独立的,其结构图如下图所示 但是在现实中很多时候这种假设是不成立的,本文要介绍的SuperParent是对朴素贝叶斯的一种扩展,打破了这种属性之间相互...
  • 朴素贝叶斯朴素贝叶斯定义、朴素贝叶斯公式分解、朴素贝叶斯分类流程、高斯型朴素贝叶斯、多项式朴素贝叶斯、伯努利型朴素贝叶斯朴素贝叶斯预测概率校准、朴素贝叶斯优缺点 目录 朴素贝叶斯朴素贝叶斯定义、...
  • 在sklearn中,提供了若干种朴素贝叶斯的实现算法,不同的朴素贝叶斯算法,主要是对P(xi|y)的分布假设不同,进而采用不同的参数估计方式。我们能够发现,朴素贝叶斯算法,主要就是计算P(xi|y),一旦P(xi|y)确定,最终...
  • 朴素贝叶斯(Naive Bayes)原理+编程实现拉普拉斯修正的朴素贝叶斯分类器,以西瓜数据集3.0为训练集,对“测1”样本进行判别。

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 45,973
精华内容 18,389
关键字:

半朴素贝叶斯