zoukankan      html  css  js  c++  java
  • 贝叶斯分类小结

    《贝叶斯之朴素理解》比较详细地总结了一个朴素贝叶斯。这里再对非朴素贝叶斯做一个小结,以了结贝叶斯分类。

    1、非朴素贝叶斯公式

    1.1 高维高斯分布

    在此之前,我们同样先需准备一些数学知识,高维高斯概率分布,或者也叫做联合高斯概率分布,它有如下公式

    [p(mathbf{x})=frac{1}{sqrt{(2pi)^n|Sigma|}}expleft(-frac{1}{2}(mathbf{x}-oldsymbol{mu})Sigma^{-1}(mathbf{x}-oldsymbol{mu})^T ight) ag{1-1} ]

    注:如果特征属性是以列向量的形式表示的,那么上式(1-1)应表示为

    [p(mathbf{x})=frac{1}{sqrt{(2pi)^n|Sigma|}}expleft(-frac{1}{2}(mathbf{x}-oldsymbol{mu})^TSigma^{-1}(mathbf{x}-oldsymbol{mu}) ight) ]

    上式中,(oldsymbol{mu}=(mu_1,mu_2,cdots,mu_n))表示特征(mathbf{x}=(x_1,x_2,cdots,x_n))的均值向量,即有

    [mu_i = frac{1}{m}sum_{j=1}^{m}x_{ij}, i = 1,2,cdots,n; j=1,2,cdots,m ag{1-2} ]

    注:其中(n)表示特征的个数,(m)表示样本数

    (Sigma)表示协方差矩阵,(|Sigma|)表示协方差矩阵的行列式,协方差阵可以表示为

    [Sigma=frac{1}{m}sum_{i=1}^{m}(mathbf{x}_j-oldsymbol{mu})^T(mathbf{x}_j-oldsymbol{mu}) ag{1-3} ]

    其中(mathbf{x}_j)表示第(j)个样本的特征行向量。

    1.2 联合贝叶斯公式

    《贝叶斯之朴素理解》第2小节中的贝叶斯公式类似,可以表达为如下公式

    [p(c_k|mathbf{x})=frac{p(mathbf{x}|c_k)p(c_k)}{p(mathbf{x})} ag{1-4} ]

    同样我们可以假设其中的似然概率(p(mathbf{x}|c_k))服从高斯分布,那么由式(1-1)可得似然概率的表达式为

    [p(mathbf{x}|c_k)=frac{1}{sqrt{(2pi)^n|Sigma|}}expleft(-frac{1}{2}(mathbf{x}-oldsymbol{mu})Sigma^{-1}(mathbf{x}-oldsymbol{mu})^T ight) ag{1-5} ]

    由于对所有的(p(c_k|mathbf{x}))(p(mathbf{x}))都是一样的,所以我们只需要对式(1-4)的分母比较大小,因此我们可以推出如下判别式

    [log(p(mathbf{x}|c_k)p(c_k))=-frac{1}{2}log|Sigma|-frac{1}{2}(mathbf{x}-oldsymbol{mu})Sigma^{-1}(mathbf{x}-oldsymbol{mu})^T-frac{n}{2}log(2pi)+log{p(c_k)} ]

    注:取对数,可以简化我们的计算,并不影响我们对大小的判断。更进一步地,我们可以将上式的表达式中的常数项去掉。

    [g_k(mathbf{x})=-frac{1}{2}log|Sigma|-frac{1}{2}(mathbf{x}-oldsymbol{mu})Sigma^{-1}(mathbf{x}-oldsymbol{mu})^T+log{p(c_k)} ag{1-6} ]

    最终,我们只需要对式(1-6)进行计算,即可分出类别。

    2、非朴素贝叶斯实现

    2.1 准备数据

    《贝叶斯之朴素理解》第4小节类似,我们先准备好我们的工作环境:jupyter+python3.6,这是我目前用的环境,如果大家没有用过jupyter,我建议大家用一下,相信你会爱上它的。关于jupyter的安装和下载以及使用,我在这里就不说了,聪明的你自会百度或google。其次,我们再准备一下数据集:CIFAR-10图像数据,我将其放入了我的百度网盘,链接: https://pan.baidu.com/s/1yIkiL7xXHsqlXS53gxMkEg 提取码: wcc4。原始的CIFAR-10图像是一个用于普世物体识别的数据集,分为airplane、automobile、bird、cat、deer、dog、frog、horse、ship、truck共10类,但是这里为了简单起见,我用了其中3类。

    注:由于在《贝叶斯之朴素理解》一文中详细地说明了关于数据的读取,这里就不多说了,直接贴出代码,相信机智的你也能看懂。

    下面代码为读取数据(请保证数据集在当前文件路径下的data文件夹下)

    import numpy as np
    import pandas as pd
    from scipy.io import loadmat
    
    train_data_mat = loadmat("./data/train_data.mat")
    test_data_mat = loadmat("./data/test_data.mat")
    labels_name_mat = loadmat("./data/labels_name.mat")
    
    # 训练数据和标签
    train_data = train_data_mat["Data"]
    train_data_label = train_data_mat["Label"]
    # 测试数据和标签
    test_data = test_data_mat["Data"]
    test_data_label = test_data_mat["Label"]
    # 标签的实际名字
    label_names = labels_name_mat["label_names"]
    # 因为标签名字有误,我这里把它手动改一下
    label_names[:, 0] = ['automobile', 'bird', 'cat', 'deer', 'dog']
    
    col_name_lst = [0]*3072
    
    for i in range(1, 3073):
        col_name_lst[i-1] = "x" + str(i)
    
    # 结构化训练集数据
    train_data = pd.DataFrame(train_data, columns=col_name_lst)
    train_data_label = pd.DataFrame(train_data_label, columns=['class_no'])
    train_dataFrm = train_data.join(train_data_label)
    # 结构化测试集数据
    test_data = pd.DataFrame(test_data, columns=col_name_lst)
    test_data_label = pd.DataFrame(test_data_label, columns=['class_no'])
    test_dataFrm = test_data.join(test_data_label)
    
    # 上面所得到的数据是全部5类的数据,下面只取出前3类数据
    train_dataFrm = train_dataFrm[train_dataFrm["class_no"] <= 3]
    train_data = train_dataFrm.drop(columns=["class_no"], axis=1)
    train_data_label = train_dataFrm["class_no"].copy()
    
    test_dataFrm = test_dataFrm[test_dataFrm["class_no"] <= 3]
    test_data = test_dataFrm.drop(columns=["class_no"], axis=1)
    test_data_label = test_dataFrm["class_no"].copy()
    
    # 查看取出3类后的基本的数据结构信息
    # print(train_data_label.shape)
    # print(train_data.shape)
    # print(test_data_label.shape)
    # print(test_data.shape)
    

    2.2 实现贝叶斯

    据式(1-6)实现如下贝叶斯分类器。

    计算均值向量和协方差矩阵

    from sklearn.decomposition import PCA
    # 利用PCA对原始数据进行降维
    pca = PCA(n_components=21)
    pca.fit(train_data)
    train_data_pca = pca.transform(train_data)
    test_data_pca = pca.transform(test_data)
    
    train_data_pca = pd.DataFrame(train_data_pca, index=train_dataFrm.index)
    test_data_pca = pd.DataFrame(test_data_pca, index=test_dataFrm.index)
    
    # 求出每个类的均值向量和协方差矩阵
    train_cls_cov = []# 协方差矩阵
    train_cls_cov_inv = []#协方差矩阵的逆
    train_cls_cov_det = []#协方差矩阵的行列式
    train_cls_mean = []#均值向量
    
    for i in range(0,3):
        train_cls_cov.append(np.cov(train_data_pca[train_dataFrm["class_no"]==1+i].T))
        train_cls_cov_inv.append(np.linalg.inv(train_cls_cov[i]))
        train_cls_cov_det.append(np.linalg.det(train_cls_cov[i]))
    
        train_cls_mean.append(train_data_pca[train_dataFrm["class_no"]==1+i].mean())
    

    注:上面的代码中利了PCA对数据进行降维,关于PCA的知识,后面有时间再讨论。这里之所以要进行降维,有两原因,一是因为原始数据维度过高,求出它的协方差矩阵后,对其求行列式,行列式会变成0(其实此时不是0,是一个非常非常小的数,计算机无法存放,所以为0),二是因为原始数据的数据内容并不纯净,PCA可以起到一个去除噪声的作用。

    对测试集数据进行预测

    for img_index in range(0, test_data.shape[0]):
        determine_clf = [0]*3
        ftr_data = test_data_pca.iloc[img_index]
    
        for i in range(0, 3):
            class_mean = train_cls_mean[i]
            class_cov = train_cls_cov[i]
            class_inv = train_cls_cov_inv[i]
            class_det = train_cls_cov_det[i]
    
            prob_temp = -(np.log(class_det)*0.5+0.5 * 
                np.dot(np.dot((ftr_data-class_mean), class_inv), (ftr_data-class_mean).T))
    
            prob_temp = prob_temp + np.log(prior_series[i+1])
            determine_clf[i] = prob_temp
        # 取出其中最大值的索引,即为我们的预测值
        pred_label[img_index] = np.argmax(determine_clf) + 1
    
    accu = sum(pred_label == test_data_label)/len(pred_label)
    print("dimn:{0:3}-->accu:{1:.3f}".format(test_data_pca.shape[1], accu))
    

    输出

    dimn: 21-->accu:0.722
    

    可以看到,降到21维后,准确率为72.2%。

  • 相关阅读:
    verilog 基础知识
    excel函数提取身份证出生日期,分离日期时间的日期和时间
    excel函数提取内容中的汉字
    excel匹配函数vlookup和lookup
    excel计数函数COUNTIF、COUNTIFS
    excel函数sum、sumif和sumifs
    excel替换函数substitute
    excel判断数据是否存在另一列中
    python用random模块模拟抽奖逻辑(print修改end参数使打印结果不分行)
    excel用函数去掉单元格内容中的括号,并只保留单元格里面的内容
  • 原文地址:https://www.cnblogs.com/endlesscoding/p/9987439.html
Copyright © 2011-2022 走看看