精华内容
下载资源
问答
  • 目录 朴素贝叶斯模型 离散估计 ...多项朴素贝叶斯分类器 MAP估计(Maximum APosteriori) 朴素贝叶斯模型 假设有个数据,每一个数据由个特征构成,如下: feature_1 feature_2 ......

    目录

     

    朴素贝叶斯模型

    离散估计

    极大似然估计

    概念和理论推导

    高斯贝叶斯分类器

    原理

    应用

    源码分析

    伯努利贝叶斯分类器

    原理

    源码分析

    多项朴素贝叶斯分类器

    MAP估计(Maximum A Posteriori)


    朴素贝叶斯模型

            假设有m个数据,每一个数据由n个特征构成,如下:

      feature_1 feature_2 ... feature_n class
    1 x_{11} x_{12} ... x_{1n} y_1
    2 x_{21} x_{22} ... x_{2n} y_2

         .

         .

         .

               .

               .

               .

               .

               .

               .

     

               .

               .

               .

               .

               .

               .

    m x_{m1} x_{m2} ... x_{mn} y_m

    \mathbf{x}_i=(x_{i1},x_{i2},...,x_{in})表示第i个数据,y_i\in\{c_1,c_2,...,c_p\}表示数据\mathbf{x}_i的类别。

            现在的任务是给定由n个特征构成的新数据\mathbf{x}=(x_1,x_2,...x_n),如何使用朴素贝叶斯来分类?

            用朴素贝叶斯分类器(Naive Bayes classifier)对数据\mathbf{x}分类的前提是假设数据特征之间相互独立。那么对于每个类别c_k,在已知\mathbf{x}的情况下,计算\mathbf{x}属于类别c_k的概率,即条件概率P(c_k|\mathbf{x})。p个条件概率P(c_k|\mathbf{x})的最大值对应的类别就作为数据\mathbf{x}所属分类。这是合情合理的,因为概率P(c_k|\mathbf{x})表示数据\mathbf{x}属于类别c_k的可能性,P(c_k|\mathbf{x})值越大,说明数据\mathbf{x}属于类别c_k的可能性就越大。

    下面详细推导贝叶斯公式,根据如下条件概率公式:

    P(c_k|\mathbf{x})=\frac{P(c_k,\mathbf{x})}{P(\mathbf{x})}, 

    其中P(c_k,\mathbf{x})表示数据为\mathbf{x}且类别为c_k的概率,P(\mathbf{x})表示数据\mathbf{x}发生的概率。由全概率公式和条件概率公式可知:

    P(c_k,\mathbf{x})=P(\mathbf{x},c_k)=P(x_1,x_2,...,x_n,c_k)

    =P(x_1|x_2,...,x_n,c_k)P(x_2,...,x_n,c_k)

    =P(x_1|x_2,...,x_n,c_k)P(x_2|x_3,...,x_n,c_k)P(x_3,...,x_n,c_k)

    =...

    =P(x_1|x_2,...,x_n,c_k)P(x_2|x_3,...,x_n,c_k)...P(x_{n-1}|x_n,c_k)P(x_{n}|c_k)P(c_k)

    因为数据\mathbf{x}的各特征之间相互独立,即

    P(x_i|x_{i+1},...x_n,c_k)=P(x_i|c_k)

    所以

    P(c_k,\mathbf{x})=P(c_k)\prod_{i=1}^{n}P(x_i|c_k)

    所以,我们就得到如下朴素贝叶斯公式:

                                                                                P(c_k|\mathbf{x})=\frac{P(c_k)\prod_{i=1}^{n}P(x_i|c_k)}{P(\mathbf{x})}                                  (1)

     从公式中来看,条件概率P(c_k|\mathbf{x})依赖P(c_k)P(x_i|c_k)P(\mathbf{x})。事实上对于每个c_k,概率P(\mathbf{x})是个常量,不影响P(c_k|\mathbf{x})的比较,实际计算可以忽略。下面我们分离散和连续两种情况,对依赖的这些概率进行估计。


    离散估计

            假设数据的每个特征取值范围都是有限的几个值,那么可以如下估计P(c_k)P(\mathbf{x})P(x_i|c_k)

    (1)估计P(c_k)

            P(c_k)表示的是类别c_k发生的概率,可以使用类c_k的频率来近似。假设表中类为c_k的数据个数为r_k,则如下估计P(c_k)

                                                                                          P(c_k)=\frac{r_k}{m}.

    (2)估计P(\mathbf{x})

            P(\mathbf{x})表示的是数据\mathbf{x}发生的概率,由于数据的每个特征之间是相互独立的,所以

    P(\mathbf{x})=\prod_{i=1}^{n}P(x_i),

    其中P(x_i)表示数据\mathbf{x}的第i个特征取值为x_i的概率,它可以使用x_i的频率来代替,假设第i个特征值为x_i的数据个数为m_i,则

    P(x_i)=\frac{m_i}{m}

    P(\mathbf{x})可以如下估计:

                                                                               P(\mathbf{x})=\frac{1}{m^n}\prod_{i=1}^{n}m_i

    (3)估计P(x_i|c_k)

            P(x_i|c_k)表示当类别为c_k的情况下,数据\mathbf{x}的第i个特征值为x_i的概率,假设在类别为c_k的数据中,第i个特征值为x_i的数据个数为q_i,则P(x_i|c_k)可以如下估计:

    P(x_i|c_k)=\frac{q_i}{r_k}

    由贝叶斯公式,就可以得到P(c_k|\mathbf{x})的估计,如下:

                                                         P(c_k|\mathbf{x})=\frac{P(c_k)\prod_{i=1}^{n}P(x_i|c_k)}{P(\mathbf{x})}=\frac{m^{n-1}\prod_{i=1}^{n}q_i}{r_k^{n-1}\prod_{i=1}^{n}m_i}


            前面假设了每个特征的取值范围都是有限的几个值,但在绝大多数情况下,数据的特征取值是连续的,我们获得的每个特征数据只是连续值中的一个值,那么这时候又如何估计贝叶斯公式中的各个概率呢?

    极大似然估计

    概念和理论推导

            所谓极大似然估计(Maximum Likelihood Estimation,简称MLE),不严谨地说,就是已经知道了随机变量x服从的密度函数形式f(x,\theta),但参数\theta是未知的。然后通过实验或者其他方式获得了关于随机变量xm个数据,比如x_1,x_2,...,x_m。如何使用这些数据估计出参数\theta的值呢?首先需要回答的是为什么可以使用这些数据估计参数\theta?这点应该不难理解,因为\theta的取值不同,会影响获得的数据,也就是说\theta在一定程度上决定了获得的数据形式,所以当然可以使用这些数据估计参数\theta。那么,什么样的\theta才会获得像x_1,x_2,...,x_m这样形式的数据呢?从概率的角度来说,也就是\theta为何值时,会使获得像x_1,x_2,...,x_m这样的数据可能性更大?这就是极大似然估计的思想。使x_1,x_2,...,x_m出现的可能性最大的\hat{\theta},就是\theta的一个极大似然估计。

            下面举个例子来理解下,比如最常见的“抛硬币”。对于一枚不均为的硬币,假设抛掷后只会出现正面和反面,出现正面记作1,反面记作0,正面出现的概率为p(未知),并假设每次抛硬币相互独立。虽然不知道概率p的具体值,但是我们知道抛硬币出现的结果是一个随机变量,假设为x,它服从如下的二项分布

                                                                       f(x,p)=p^x(1-p)^{1-x}

    通过抛掷10次硬币,获得如下10个数据:

                                                              1,   0,   0,   1,   1,   1,   1,   0,   1,   1

    下面使用这10个数据估计概率p。用A表示这组数据,P(A|p)表示在概率为p的情况下,出现数据组A的概率。根据极大似然估计思想,需要求解的就是使P(A|p)最大的p值。但是首先需要给出P(A|p)的具体表达式,因为每次抛掷硬币是相互独立的,所以P(A|p)可以如下表示:

    P(A|p)=\prod_{i=1}^{10}P(x_i|p)=\prod_{i=1}^{10}f(x_i,p)=\prod_{i=1}^{10}p^{x_i}(1-p)^{1-x_i}

    因为P(A|p)的最大值和对数lnP(A|p)的最大值是等价的,所以上式两边取对数,得到:

    lnP(A|p)=\sum_{i=1}^{10}ln[p^{x_i}(1-p)^{1-x_i}]=\sum_{i=1}^{10}[x_ilnp+(1-x_i)ln(1-p)]

    两边对p求导,得到

    \frac{\partial lnP(A|p)}{\partial p}=\sum_{i=1}^{10}(\frac{x_i}{p}-\frac{1-x_i}{1-p})

    令导数为0,得到:

    p=\frac{1}{10}\sum_{i=1}^{10}x_i=0.7.

    从结果能看到,其实概率p的极大似然估计就是获得的10个数据的平均值,这也验证了硬币确实是不均为的。


             贝叶斯分类器根据特征服从的分布不同有不同的分类器实现,常见有高斯贝叶斯分类器,伯努利贝叶斯分类器和多项贝叶斯分类器,类继承关系如图:

    下面逐个介绍它们的原理和python源码实现。


    高斯贝叶斯分类器

    原理

          现在我们回到贝叶斯公式的估计上来,假设已经知道了在分类为c_k的情况下,第i个特征x_i服从如下的正态分布:

                                                                                 p(x_i|c_k)=\frac{1}{\sqrt{2\pi}\sigma_{k}}e^{-\frac{(x_i-u_k)^2}{2\sigma_{k}^2}}

    这里u_k,\sigma_k^2就是我们前面极大似然估计里面说的未知参数\theta,不过这里需要估计两个参数,但是道理是一样的。事实上,对于每个分类c_k,都有一个u_k,\sigma_k^2与之对应。从表中找到类为c_k的所有数据,然后将它们的第i列特征数据提取出来组成一个集合,记为A_k=\{t_1,t_2,...,t_q\}。事实上A_k就是在分类为c_k的情况下,第i个特征x_i服从的正态分布决定产生的数据,使P(A_k|c_k)达到最大的\hat{u_k},\hat{\sigma_k^2}就是u_k,\sigma_k^2的极大似然估计。下面具体推导,因为各数据之间相互独立,所以

    P(A_k|c_k)=\prod_{i=1}^{q}P(t_i|c_k)

    两边取对数,得到

    lnP(A_k|c_k)=\sum_{i=1}^{q}lnP(t_i|c_k)\\ =\sum_{i=1}^{q}ln\frac{1}{\sqrt{2\pi}\sigma_k}e^{-\frac{(t_i-u_k)^2}{2\sigma_k^2}} =-\sum_{i=1}^{q}[\frac{1}{2}ln\sigma_k^2+\frac{1}{2}ln2\pi+\frac{(t_i-u_k)^2}{2\sigma_k^2}]

    两边对u_k,\sigma_k^2求偏导数,得到:

    \frac{\partial lnP(A_k|c_k)}{\partial u_k}=\sum_{i=1}^{q}\frac{t_i-u_k}{\sigma_k^2}

    \frac{\partial lnP(A_k|c_k)}{\partial \sigma_k^2}=-\sum_{i=1}^{q}[\frac{1}{2\sigma_k^2}-\frac{(t_i-u_k)^2}{2(\sigma_k^2)^2}]

    令偏导数为0,得到u_k,\sigma_k^2的极大似然估计:

    u_k=\frac{1}{q}\sum_{i=1}^{q}t_i

    \sigma_k^2=\frac{1}{q}\sum_{i=1}^{q}(t_i-u_k)^2

    从结果来看,u_k,\sigma_k^2分别是集合A_k中所有数据的平均值和方差。


    应用

            下面使用python中实现的高斯贝叶斯分类器来训练数据,并对数据进行分类,具体代码如下: 

    from sklearn import datasets
    from sklearn.naive_bayes import GaussianNB
    
    iris = datasets.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()))

    代码非常简单,主要分为以下几个步骤:

    (1)加载scikit-learn中自带了标准数据集iris,对应代码如下:

    iris = datasets.load_iris()

     scikit-learn中自带了一些标准数据集(datasets), 例如在分类中有irisdigits,在回归中有boston house prices dataset。我们这里使用的就是iris数据集,关于iris数据集,Wikipedia中介绍如下:

    但是截至目前,iris数据集中已经变成150个样本,每个样本有4个特征,如下:

    from sklearn import datasets
    
    iris = datasets.load_iris()
    print(iris.data.shape)

    程序输出结果:

    (150, 4)

     我们可以查看iris数据集的data和target。如下:

    print('前5条data:',iris.data[0:5])
    print('target:',iris.target)
    前5条data: [[5.1 3.5 1.4 0.2]
     [4.9 3.  1.4 0.2]
     [4.7 3.2 1.3 0.2]
     [4.6 3.1 1.5 0.2]
     [5.  3.6 1.4 0.2]]
    target: [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
     0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
     1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 2
     2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2
     2 2]

    (2)初始化高斯贝叶斯分类器GaussianNB,这里使用的是默认初始化,对应代码如下:

    gnb = GaussianNB()

    (3)使用标准数据集iris训练出一个高斯贝叶斯分类器,其实这一步使用极大似然估计完成了正态分布中的未知参数估计,对应代码如下:

    gnb.fit(iris.data, iris.target)

    (4) 使用训练出来的高斯贝叶斯分类器对数据进行预测,这里是预测的是标准数据集iris,对应代码如下:

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

    程序运行结果:

    Number of mislabeled points out of a total 150 points : 6

     结果表明:使用iris数据集训练得到的高斯贝叶斯分类器,只对6个样本分类错误,准确度可以接受。


    源码分析

            首先来看三个贝叶斯分类器的基类BaseNB,具体代码如下:

    class BaseNB(six.with_metaclass(ABCMeta, BaseEstimator, ClassifierMixin)):
        """贝叶斯估计(naive Bayes estimators)的抽象类"""
    
        @abstractmethod
        def _joint_log_likelihood(self, X):
    
        def predict(self, X):
            jll = self._joint_log_likelihood(X)
            return self.classes_[np.argmax(jll, axis=1)]
    
        def predict_log_proba(self, X):
            jll = self._joint_log_likelihood(X)
            # normalize by P(x) = P(f_1, ..., f_n)
            log_prob_x = logsumexp(jll, axis=1)
            return jll - np.atleast_2d(log_prob_x).T
    
        def predict_proba(self, X):
            return np.exp(self.predict_log_proba(X))

    该类包含了一个抽象方法和三个已经实现的方法:

    (1)_joint_log_likelihood(self, X)

            该方法是是一个抽象方法,具体实现由子类完成。它用于计算联合概率P(c_k,\mathbf{x})的对数,也就是lnP(c_k,\mathbf{x})=lnP(c_k)+lnP(\mathbf{x}|c_k)。返回如下m\times p阶联合概率对数矩阵:

                                                   jll=\begin{bmatrix} lnP(c_1,\mathbf{x_1}) & lnP(c_2,\mathbf{x_1}) & ... &lnP(c_p,\mathbf{x_1}) \\ lnP(c_1,\mathbf{x_2}) & lnP(c_2,\mathbf{x_2}) & ... &lnP(c_p,\mathbf{x_2}) \\ \vdots&\vdots & &\vdots \\ lnP(c_1,\mathbf{x_m}) & lnP(c_2,\mathbf{x_m}) & ... &lnP(c_p,\mathbf{x_m}) \\ \end{bmatrix}

    (2)predict(self, X)

            该方法通过调用_joint_log_likelihood(self, X)获得联合概率对数矩阵jll,并选择矩阵每行中最大值对应的下标,该下标也是类的下标。

    (3)predict_log_proba(self, X)

            该方法就是标准化联合概率对数矩阵jll。具体先计算第i行:

    total=ln\sum_{j=1}^{p}exp(lnP(c_j,\mathbf{x}_i))

    然后第i行的每个元素除以total,这样就得到一个标准化后的联合概率对数矩阵。

    (4)predict_proba(self, X)

            该方法是通过消除标准化后的联合概率对数矩阵中的对数,计算真正的概率。

    下面来看它的一个实现类GaussianNB的源码,使用GaussianNB分类器分类,主要分为5个阶段:

    (1)数据加载

    查看上面的应用。

    (2)分类器初始化

    当数据加载之后,接下来是初始化GaussianNB分类器,实际上调用的是__init__()方法,源码如下:

        def __init__(self, priors=None):
            self.priors = priors

    该方法中初始化了priors,其实是P(c_k)的先验概率,可以由程序员事先给定,如果选择默认实现,就使用离散估计中的P(c_k)

    (3)训练或拟合

    当GaussianNB分类器初始化结束后,调用了fit()方法,具体代码如下:

        def fit(self, X, y, sample_weight=None):
            X, y = check_X_y(X, y)
            return self._partial_fit(X, y, np.unique(y), _refit=True,
                                     sample_weight=sample_weight)

    该方法很简单,首先检查数据X和分类y是否有效,然后调用_partial_fit()训练数据,注意参数_refit=True,表示如果之前已经拟合过,全部抛弃,重新开始拟合。事实上,_partial_fit()方法才是GaussianNB分类器真正核心,具体代码如下:

        def _partial_fit(self, X, y, classes=None, _refit=False,
                         sample_weight=None):
            #检查数据有效性
            X, y = check_X_y(X, y)
            
            if sample_weight is not None:
                sample_weight = check_array(sample_weight, ensure_2d=False)
                check_consistent_length(y, sample_weight)
    
            epsilon = 1e-9 * np.var(X, axis=0).max()
            #如果重新拟合,将类别设置为None
            if _refit:
                self.classes_ = None
            #检查是否第一次拟合
            if _check_partial_fit_first_call(self, classes):
                #初始化特征数,类别数,u_k和sigma_k
                n_features = X.shape[1]
                n_classes = len(self.classes_)
                self.theta_ = np.zeros((n_classes, n_features))
                self.sigma_ = np.zeros((n_classes, n_features))
    
                self.class_count_ = np.zeros(n_classes, dtype=np.float64)
    
                # Initialise the class prior
                n_classes = len(self.classes_)
                # 当P(c_k)不为空时,对其进行有效性检验
                if self.priors is not None:
                    priors = np.asarray(self.priors)
                    # Check that the provide prior match the number of classes
                    if len(priors) != n_classes:
                        raise ValueError('Number of priors must match number of'
                                         ' classes.')
                    # Check that the sum is 1
                    if priors.sum() != 1.0:
                        raise ValueError('The sum of the priors should be 1.')
                    # Check that the prior are non-negative
                    if (priors < 0).any():
                        raise ValueError('Priors must be non-negative.')
                    self.class_prior_ = priors
                #第一次拟合时,如果P(C_K)为None,全部初始化为0
                else:
                    # Initialize the priors to zeros for each class
                    self.class_prior_ = np.zeros(len(self.classes_),
                                                 dtype=np.float64)
            else:
                if X.shape[1] != self.theta_.shape[1]:
                    msg = "Number of features %d does not match previous data %d."
                    raise ValueError(msg % (X.shape[1], self.theta_.shape[1]))
                # Put epsilon back in each time
                self.sigma_[:, :] -= epsilon
    
            classes = self.classes_
    
            unique_y = np.unique(y)
            unique_y_in_classes = np.in1d(unique_y, classes)
    
            if not np.all(unique_y_in_classes):
                raise ValueError("The target label(s) %s in y do not exist in the "
                                 "initial classes %s" %
                                 (unique_y[~unique_y_in_classes], classes))
            #对于每个类c_k,估计u_k和sigma_k
            for y_i in unique_y:
                i = classes.searchsorted(y_i)
                X_i = X[y == y_i, :]
    
                if sample_weight is not None:
                    sw_i = sample_weight[y == y_i]
                    N_i = sw_i.sum()
                else:
                    sw_i = None
                    N_i = X_i.shape[0]
    
                new_theta, new_sigma = self._update_mean_variance(
                    self.class_count_[i], self.theta_[i, :], self.sigma_[i, :],
                    X_i, sw_i)
    
                self.theta_[i, :] = new_theta
                self.sigma_[i, :] = new_sigma
                self.class_count_[i] += N_i
    
            self.sigma_[:, :] += epsilon
    
            # p(c_k)的计算,它可通过实例化GaussianNB分类器时参数传入
            # 如果p(c_k)为None,使用频率代替
            if self.priors is None:
                # Empirical prior, with sample_weight taken into account
                self.class_prior_ = self.class_count_ / self.class_count_.sum()
    
            return self

     已通过注释方式对代码的核心部分进行了解释。对照高斯贝叶斯分类器的极大似然估计推导,不难理解。

    (4)预测

    当拟合(训练)好高斯贝叶斯分类器后,就可以调用predict()方法使用它对数据进行预测分类了,实际上,GaussianNB类并未对predict()方法进行重写,而是直接调用基类BaseNB中已经实现的predict()方法,接着predict()调用GaussianNB实现的_joint_log_likelihood()方法,具体代码如下:

        def _joint_log_likelihood(self, X):
            check_is_fitted(self, "classes_")
    
            X = check_array(X)
            joint_log_likelihood = []
            for i in range(np.size(self.classes_)):
                jointi = np.log(self.class_prior_[i])
                n_ij = - 0.5 * np.sum(np.log(2. * np.pi * self.sigma_[i, :]))
                n_ij -= 0.5 * np.sum(((X - self.theta_[i, :]) ** 2) /
                                     (self.sigma_[i, :]), 1)
                joint_log_likelihood.append(jointi + n_ij)
    
            joint_log_likelihood = np.array(joint_log_likelihood).T
            return joint_log_likelihood

    该方法具体完成jll矩阵计算。当predict()方法拿到jll矩阵后就可以完成预测分类了。

    (5)评估
    查看上面应用。


    伯努利贝叶斯分类器

    原理

            首先看一个经典分类问题:文本分类。我们将一切可能的词组成一个字典。当然实际中“一切可能”的词都放入字典中是不可能的,但是我们先这么假设。我们如下来构造文本的一个特征向量:

            首先按照字典中词的个数n构造一个n维向量,通常字典是比较大的,所以对应的n也非常大。当字典的第i个词在文本中出现过,n维向量的第i个分量就取值为1,否则取值为0。这样就得到一个取值为0或1的n维向量,它就是文本对应的特征向量。

            我们的任务是使用文本的特征向量对文本进行分类。每一个文本特征向量就是一个数据,只是每个数据的特征只能取值为0或1。这就是伯努利贝叶斯分类器(Bernoulli Naive Bayes)的模型。它是一种实现服从多元伯努利分布数据的朴素贝叶斯训练和分类算法。下面使用贝叶斯公式,对伯努利贝叶斯分类器模型进行推导。推导过程与上面的高斯朴素分类器一样,只不过这里的数据服从的不再是正态分布,而是伯努利分布。对于n元随机向量(x_1,x_2,...,x_n),分量x_i是一个随机向量,在分类为y的情况下,服从如下伯努利分布:

                                                   P(x_i|y)=P(x_i=1|y)x_i+P(x_i=0|y)(1-x_i)

    注意到P(x_i=1|y)+P(x_i=0|y)=1,所以

                                               P(x_i|y)=P(x_i=1|y)x_i+(1-P(x_i=1|y))}(1-x_i)

    P(x_i=1|y)就是需要估计的参数,不失一般性,我们估计在分类为c_kx_i下的参数P(x_i=1|y),简记为P_{ik}。简化上式得到

    P(x_i|y)=P_{ik}[x_i-(1-x_i)]+(1-x_i)

    后面代码实现也是采用的这种形式。

            从表中找到类为c_k的所有数据,然后将它们的第i列特征数据提取出来组成一个集合,记为A_k=\{t_1,t_2,...,t_q\},并设A_k中等于1的数有n_k个。同样使用极大似然估计,构造似然函数

    P(A_k|c_k)=\prod_{i=1}^{q}P(t_i|c_k)

    两边取对数,得到

    lnP(A_k|c_k)=\sum_{j=1}^{q}lnP(t_j|c_k)=\sum_{j=1}^{q}ln[P_{ik}t_j+(1-P_{ik})(1-t_j)]

    两边对P_{ik}求导数,得到:

    \frac{\partial lnP(A_k|c_k)}{\partial P_{ik}}=\sum_{j=1}^{q}\frac{t_j-(1-t_j)}{P_{ik}t_j+(1-P_{ik})(1-t_j)}=\frac{n_k}{P_{ik}}-\frac{q-n_k}{1-P_{ik}}

    令导数为0,得到P_{ik}的极大似然估计:

    P_{ik}=\frac{n_k}{q}

    从结果来看,P_{ik}是类别为c_k的数据中第i个分量为1的数据的占比。

            从结果来看,P_{ik}的极大似然估计似乎很完美,但是如果获取的数据中的第i个分量全部为0,则使用这些数据估计出的概率P_{ik}=0。这是不符合实际情况的,虽然获得的数据中没有出现第i个分量为1的数据,但不代表第i个分量为1的数据不会在以后预测中出现。为了规避这个问题,引入一个平滑系数\alpha,如下:

                                                                                      P_{ik}=\frac{n_k+\alpha }{q+2\alpha }

    其中0<\alpha \leq 1


    源码分析

            从类继承关系图来看,伯努利贝叶斯分类器BernoulliNB,并没有直接继承BaseNB,而是继承BaseNB的继承类BaseDiscreteNB。该类是离散贝叶斯分类器的具体抽象,包含BernoulliNB和MultinomialNB两个子类。其中MultinomialNB就是后面要详细介绍的多项式贝叶斯分类器。依然按照数据加载、分类器初始化、训练(拟合)、预测和评估五个阶段来分析BernoulliNB的源码:

    (1)数据加载

    略。

    (2)分类器初始化

        def __init__(self, alpha=1.0, binarize=.0, fit_prior=True,
                     class_prior=None):
            self.alpha = alpha
            self.binarize = binarize
            self.fit_prior = fit_prior
            self.class_prior = class_prior

    self.alpha:初始化平滑系数;

    self.binarize:二值化的阈值,BernoulliNB分类器处理的只有0和1值的情况,如果输入是连续值,可以使用二值化阈值将连续值转换成0和1的值;

    self.fit_prior:是否学习类的先验概率,默认为true,这样会在训练数据不断增加的同时来优化类的先验概率。

    self.class_prior:类的先验概率,可以事先指定类的先验概率。如果未指定,使用类的频率代替。

    (3)训练(拟合)

    BernoulliNB中并没有fit()方法,而是调用的基类BaseDiscreteNB中的fit()方法,源码如下:

        def fit(self, X, y, sample_weight=None):
            #数据检查
            X, y = check_X_y(X, y, 'csr')
            #获取数据的特征数
            _, n_features = X.shape
    
            #标签处理,获取矩阵Y,Y的行表示数据,列表示类别,取值只有0和1
            labelbin = LabelBinarizer()
            Y = labelbin.fit_transform(y)
            self.classes_ = labelbin.classes_
            if Y.shape[1] == 1:
                Y = np.concatenate((1 - Y, Y), axis=1)
    
            Y = Y.astype(np.float64)
            if sample_weight is not None:
                sample_weight = np.atleast_2d(sample_weight)
                Y *= check_array(sample_weight).T
    
            class_prior = self.class_prior
    
            n_effective_classes = Y.shape[1]
            #初始化类别和特征频率
            self.class_count_ = np.zeros(n_effective_classes, dtype=np.float64)
            self.feature_count_ = np.zeros((n_effective_classes, n_features),
                                           dtype=np.float64)
            #调用实现类的_count/_update_feature_log_prob/_update_class_log_prior方法
            self._count(X, Y)
            alpha = self._check_alpha()
            self._update_feature_log_prob(alpha)
            self._update_class_log_prior(class_prior=class_prior)
            return self

    该方法比较容易理解,已通过注释方式将核心部分进行了解析。fit()方法核心是调用了子类BernoulliNB的三个方法:_count()、_update_feature_log_prob()和_update_class_log_prior(),具体来看:

        def _count(self, X, Y):
            """Count and smooth feature occurrences."""
            if self.binarize is not None:
                X = binarize(X, threshold=self.binarize)
            self.feature_count_ += safe_sparse_dot(Y.T, X)
            self.class_count_ += Y.sum(axis=0)

    _count()方法计算特征和类的频率。

       def _update_feature_log_prob(self, alpha):
            """Apply smoothing to raw counts and recompute log probabilities"""
            smoothed_fc = self.feature_count_ + alpha
            smoothed_cc = self.class_count_ + alpha * 2
    
            self.feature_log_prob_ = (np.log(smoothed_fc) -
                                      np.log(smoothed_cc.reshape(-1, 1)))

    _update_feature_log_prob()方法计算加入平滑系数后的lnP_{ik}

        def _joint_log_likelihood(self, X):
            """Calculate the posterior log probability of the samples X"""
            check_is_fitted(self, "classes_")
    
            X = check_array(X, accept_sparse='csr')
    
            if self.binarize is not None:
                X = binarize(X, threshold=self.binarize)
    
            n_classes, n_features = self.feature_log_prob_.shape
            n_samples, n_features_X = X.shape
    
            if n_features_X != n_features:
                raise ValueError("Expected input with %d features, got %d instead"
                                 % (n_features, n_features_X))
    
            neg_prob = np.log(1 - np.exp(self.feature_log_prob_))
            # Compute  neg_prob · (1 - X).T  as  ∑neg_prob - X · neg_prob
            jll = safe_sparse_dot(X, (self.feature_log_prob_ - neg_prob).T)
            jll += self.class_log_prior_ + neg_prob.sum(axis=1)
    
            return jll

    _joint_log_likelihood方法计算联合概率对数矩阵jll

    (4)预测

    略。

    (5)评估

    略。

    整个计算流程如图:


    多项朴素贝叶斯分类器

            多项朴素贝叶斯分类器(Multinomial Naive Bayes)是一种实现服从多项分布数据的分类算法。多项分布其实是伯努利分布的直接推广。在多项分布中,出现的结果不再是两个(0或1),而是kk\geq 2)个。所以,伯努利分布是多项分布中k=2的情况。假设在分类为c_k的情况下,第i个特征x_i服从多项分布,多项分布出现的可能结果为\{a_1,a_2,...,a_k\}a_i取值0或1,\sum_{i=1}^{k}a_i=1,且P(a_i=1)=p_i\sum_{i=1}^{k}p_i=1,则条件概率P(x_i|c_k),如下:

                                                                       P(x_i|c_k)=\sum_{i=1}^{k}p_ia_i

    不失一般性,使用极大似然来估计p_j,上式可以简化后为:

                                                  P(x_i|c_k)=p_ja_j+(1-p_j)(1-a_j)

    从表中找到类为c_k且第i个特征取值为a_j的所有数据,然后将它们的第i列特征数据提取出来组成一个集合,记为A_k=\{t_1,t_2,...,t_q\},并设A_k中等于1的数有n_k个。同样使用极大似然估计,构造似然函数

    P(A_k|c_k)=\prod_{i=1}^{q}P(t_i|c_k)

    两边取对数,得到

    lnP(A_k|c_k)=\sum_{i=1}^{q}lnP(t_j|c_k)=\sum_{i=1}^{q}ln[p_ja_j+(1-p_j)(1-a_j)]

    两边对p_j求导数,得到:

    \frac{\partial lnP(A_k|c_k)}{\partial p_j}=\sum_{i=1}^{q}\frac{a_j-(1-a_j)}{p_ja_j+(1-p_j)(1-a_j)}=\frac{n_k}{p_j}-\frac{q-n_k}{1-p_j}

    令导数为0,得到p_j的极大似然估计:

    p_j=\frac{n_k}{q}

    这个结果和离散估计是一致的。

            与伯努利分布类似,引入一个平滑系数\alpha,如下:

                                                                                      p_j=\frac{n_k+\alpha }{q+n\alpha }

    源码与伯努利朴素贝叶斯分类器类似,不再累述。我们回到文本分类的问题上来,在伯努利朴素分类器中,提取了文本特征向量,每个向量取值为0或1。但是在文本分类和主题分析时,这种方法不是很好。它只度量了字典中的词是否在文本中出现,对于出现的频率并没有度量。现在换一种方法提取文本特征。

            构建一个n维向量,向量的第i个分量表示字典中第i个位置的词在文本中出现的频率。

     此时,每个分量的取值是非负整数。这个就是文本的多项分布模型。文字对主题文本的影响分为两部分:

    (1)某个文字在文本中出现的比例越高,它与文本主题也就越相关;

    (2)一个文字出现的文本数占总文本数的比例越小,它与文本主题也就越相关;

    第一条就是熟悉的TF,第二条是IDF,假设文本的特征向量为\mathbf{x}_i=(x_{i1},x_{i2},...,x_{in}),则

                                                                                       TF_{ij}=\frac{x_{ij}}{\sum_{j=1}^nx_{ij}}

                                                                                  IDF_j=ln\frac{m}{\sum_{i=1}^m1_{x_{ij}>0}}

                                                                                  TFIDF_{ij}=TF_{ij}*IDF_{j}


    MAP估计(Maximum A Posteriori)

            前面在比较条件概率P(c_k|\mathbf{x})时,先是在已经P(x_i|c_k)的概率密度函数形式下,使用极大似然对参数进行估计,估计出了P(x_i|c_k)的概率密度函数,而P(c_k)直接使用的是频率。在有些情况下,P(c_k)服从的概率密度函数的形式也是知道的。假设

    p(x_i|c_k)=\frac{1}{\sqrt{2\pi}\sigma_{k}}e^{-\frac{(x_i-u_k)^2}{2\sigma_{k}^2}}

    P(c_k)P(x_i|c_k)服从同样的分布。

                                                                              \max_{u_k,\sigma_k}P(c_k)\prod_{i=1}^{n}P(x_k|c_k)

    展开全文
  • 大数据分析笔记 - 朴素贝叶斯定义贝叶斯定理 (Bayes' Theorem)朴素贝叶斯分类器 定义 朴素贝叶斯是一种基于贝叶斯定理(Bayes’ theorem)的概率分类方法(probabilistic classification method)。朴素贝叶斯分类器假设...

    定义

    朴素贝叶斯是一种基于贝叶斯定理(Bayes’ theorem)的概率分类方法(probabilistic classification method)。朴素贝叶斯分类器假设一个类的特定特征的存在和其他特征的存在与否是无关的。(条件独立假设 conditional independence assumption)
    一个合理的分类会认为一个
    球形、黄色且重量小于 60 克的对象可能是网球。即使这些特征相互依赖或者依赖于其他特征的存在,朴素贝叶斯分类器也认为所有这些属性独立地贡献了“该对象是一个网球”的概率。
    输出包括了类别标签(class label)及其相应的概率分数(probability score)。

    应用

    • 贝叶斯垃圾邮件过滤
    • 欺诈检测 (如汽车保险领域对司机的评级)

    连续变量离散化 (Discretization of continuous variable)

    连续变量(比如重量)能够按照间隔来分组,从而被转换成一个分类变量。比如对于"收入(income)"这样的属性,可以转换为以下分类变量:

    • 低收入:income < $10,000
    • 工薪阶级:$10,000 ≤ income < $50,000
    • 中产阶级:$50,000 ≤ income < $1000,000
    • 高产阶级:income ≥ $1,000,000

    贝叶斯定理 (Bayes’ Theorem)

    在事件A已经发生的情况下,事件C发生的条件概率用P(C|A)表示,如下图
    在这里插入图片描述
    C是类标签 𝐶 ∈ {𝑐1, 𝑐2, … , 𝑐}
    A是观察到的属性 𝐴 ∈ {𝑎1, 𝑎2, … , 𝑎𝑚}

    贝叶斯定理的一种更通用的形式(more practical form)是给一个具有多个属性A = {a1, a2, …, am}的对象分配分类标签,使得标签对应P(ci | A)的最大值,如下图。
    在这里插入图片描述

    朴素贝叶斯分类器 (Naive Bayes Classifier)

    经过两种简化(simplifications),贝叶斯定理能被扩展为朴素贝叶斯分类器。

    1. 第一种简化就是使用条件独立性假设(Conditional independence assumption)。给定一个类标签ci, 每个属性是条件独立于其他属性的。
      在这里插入图片描述
      这个朴素假设简化了P(a1, a2, …, am | ci) 的计算。
    2. 第二种假设就是忽略分母 (denominator) P(a1, a2, …, am)。因为P(a1, a2, …, am)出现在所有i的P(ci | A)的分母里,移除分母对于相对概率值(relative probability score)没有影响。

    使用这两种简化手法之后,分类器变成了:
    在这里插入图片描述
    数学符号表示了LHS,P(ci | A) 和 RHS 直接成比例。

    为了建立一个朴素贝叶斯分类器,需要知道从训练集中计算出来的统计数字。

    • 对于所有类别的 P(ci)
    • 给定每个类标 ci 的情况下,每个属性aj的条件概率,即P(aj | ci)

    比如,对于示例训练集来说,P(ci):
    在这里插入图片描述
    对于每个属性和其可能值,计算给定ci下的条件概率,P(aj | ci):

    在这里插入图片描述
    在训练完分类器并且计算出所有需要的统计数字之后,朴素贝叶斯分类器对测试集做测试。对于测试集中的每条记录,朴素贝叶斯分类器分配了最大化以下公式的标签ci。
    在这里插入图片描述
    例子:
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    因为 P(subscribed= yes|A) > P(subscribed=no|A),所以表中的客户被赋予标签 subscribed = yes。也就是说,客户被认为很可能签约凭证式存款。

    可能问题

    数据下溢 (numerical underflow)

    当被分析的问题包含大量属性或者属性由很多层级构成的时候,这些值可能都非常小(接近于0),从而导致结果的差异更小。这是由几个接近于0的概率值相乘而引起的。

    解决方案:
    计算积的对数,这相当于这些概率的对数总和。
    在这里插入图片描述

    罕见事件 (rare events)

    如果一个属性值没有在训练集中的类标签出现过,那么相应的P{aj | ci}将等于0。当这种情况出现,无论一些条件概率的值有多大,所有的P(aj | ci)相乘之后,P(ci | A) 将会立即变成0。

    解决方案:

    平滑技术: 为没有包含在数据集中的小概率事件赋一个很小的非0概率值。同时,平滑技术也解决了可能发生的对0取对数的问题。

    拉普拉斯平滑 (Laplace smoothing): 该技术假装看到每个结果的次数都比实际多一次。
    在这里插入图片描述
    拉普拉斯平滑方式的一个问题是它可能会给不可见事件太高的概率,为了解决这个问题, 拉普拉斯平滑可以使用ε而不是1, ε ∈[0,1]。
    在这里插入图片描述

    分类器优点

    • 容易实现。
    • 高效地处理多维数据(high-dimensional data)。
    • 朴素贝叶斯对过度拟合更有抵抗力,特别是在有平滑技术时。
    • 能够处理缺失值(missing values)。

    分类器缺点

    • 朴素贝叶斯需要假定数据变量之间是条件独立的。因此,它对关联变量(correlated variables)是敏感的。(因为算法可能会重复计算其影响)
    • 朴素贝叶斯分类器在概率估计(probability estimation)上通常并不可靠,应该仅用作分配类的标签。

    分类器诊断

    混淆矩阵 (confusion matrix)

    混淆矩阵是一个特定的表格布局,可以可视化分类器的性能。
    在这里插入图片描述
    在这里插入图片描述
    真阳性(TP)是阳性实例被分类器正确识别为阳性的数量。伪阳性(FP)是实例被分类器识别为阳性但是实际上为阴性的数量。真阴性 (TN)是阴性实例被分类器正确认定为阴性的数量。伪阴性(FN)是实例被分类器识别为阴性但是实际上是阳性的数量。在二类分类器中,预设的阈值可用于区分阳性阴性。TP 和 TN 是正确的猜测。

    精确度(Accuracy)

    定义了模型能够正确地对记录进行分类的比例。
    在这里插入图片描述

    TPR, TNR, FPR, FNR

    在这里插入图片描述
    FPR也被称为误报率(false alarm rate)或者Ⅰ型错误率 (type Ⅰ error rate)。
    FNR也被称为缺失率(miss rate)或者Ⅱ型错误率(type Ⅱ error rate)。

    准确率 (Precision)

    在这里插入图片描述

    召回率 (Recall)

    在这里插入图片描述

    ROC和AUC

    之前整理过:
    点击:大数据分析笔记 - 逻辑回归分析

    选择合适的分类器

    在这里插入图片描述

    展开全文
  • 1.分析 1.1 背景意义:  KNN分类决策树都是要求分类器能够给出实例明确... 首先概述整个朴素贝叶斯分类算法:对于给定的训练数据集,首先基于“特征条件独立假设”学习输入输出的联合概率分布;然后基于此模型...

    1.分析

    1.1 背景意义:

            KNN和分类决策树都是要求分类器能够给出实例明确属于哪一类?但很多时候我们没法判断准确是哪一类时候,这时候起码能够给出最优可能的那一类和有多大概率属于该类。朴素贝叶斯分类算法就可以干这事。

    1.2 原理

             首先概述整个朴素贝叶斯分类算法:对于给定的训练数据集,首先基于“特征条件独立假设”学习输入输出的联合概率分布;然后基于此模型,对于给定的输入x(实例),利用贝叶斯定理求出后验概率最大的输出y(类别)。

            所以,我们的目标是,根据样本x,算出该样本属于每个类别y的后验概率,比较得出最大值对应的那个y就是最有可能的类别,由贝叶斯定理有公式如下:

             P(y|x)=\frac{P(x|y)P(y)}{P(x)}
            由于条件概率P(x|y)难算:x是一个d维向量,那么x就有d次方的指数级别种可能的组合,远大于样本的数量,说明一些组合是没有的,因此用样本出现的频数来估计条件概率P(x|y)既难算又不合理。所以用到了“特征条件独立假设”,该假设是说,用来分类的特征,在类确定的条件下是条件独立的,就是说每个特征对分类的影响独立。这是一个较强的假设(因为特征之间可能有关联性),使得该分类方法变得简单,损失一定准确性,所以称之为"朴素"。
             由“特征条件独立假设”有公式如下:
              P(x|y)=\prod_{i=1}^{d}P(x_i|y)
            并且由于P(x)对于每一个类别y都是一样的,所以朴素贝叶斯分类器的表达式为:

             \widehat{y}=argmaxP(y)\prod_{i=1}^{d}P(x_i|y)

            参数估计用极大似然估计,其实也就是用频数来代表概率。
            算法流程如下:

    图来源于https://zhuanlan.zhihu.com/p/36545000

           直接使用极大似然估计法时,需要注意,若某个属性值在训练集中没有与某个类同时出现,则直接基于之前的公式进行概率估计,再进行判别将出现问题。不能因为没有出现该样本,而直接把该样本的出现概率设为0。为了避免其他属性携带的信息被训练集中未出现的属性值 “抹去”,在估计概率值时通常需要进行 “平滑” (smoothing),我们常用 “拉普拉斯修正”。公式具体看李航书P51。

     

    2.实践(《机器学习实战》第四章代码解析)

    使用python来文本分类

    1.准备数据:从文中构建词向量

    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']]
        #0-非侮辱性,1-侮辱性
        classVec = [0,1,0,1,0,1]    
        return postingList,classVec
    
    def createVocabList(dataset):#获取词汇表:把文本集装换成一个不含重复词的列表
        vocabSet = set([])#创建一个空集,可以进行集合操作
        for document in dataset:
            vocabSet = vocabSet |set(document)#每次把文件中的不重复元素放入
        return list(vocabSet)
    
    def setOfWords2Vec(vocabList, inputSet):#转化成向量:参数是词汇表和某个文档
        returnVec = [0]*len(vocabList)#构建vocabList长度的0向量
        for word in inputSet:  #把该文档中在词汇表中有该单词的位置标位1(one-hot向量)
            if word in vocabList:
                returnVec[vocabList.index(word)]=1 
            else:
                 print("the word: %s is not in my Vocabulary!" % word)
        return returnVec

    2.训练算法:从词向量计算概率

    def trainNB0(trainMatrix, trainGategory):
        numTrainDocs = len(trainMatrix)   #返回训练的文档数目
        numWords = len(trainMatrix[0])   #返回每一篇文档的词条数
        pAbusive = sum(trainGategory)/float(numTrainDocs)  #文档属于侮辱类的概率
        #用拉普拉斯修正”来平滑数据
        p0Num = np.ones(numWords); p1Num = np.ones(numWords)  #创建numpy.zeros数组,词条出现数初始化为0
        p0Denom = 2.0; p1Denom = 2.0   #分母初始化为2
        for i in range(numTrainDocs):
            if trainGategory[i] == 1:  #统计属于侮辱类的条件概率所需的数据,即P(w0|1),P(w1|1),P(w2|1)···
                p1Num += trainMatrix[i]
                p1Denom += sum(trainMatrix[i])
            else:  #统计属于非侮辱类的条件概率所需的数据,即P(w0|0),P(w1|0),P(w2|0)···
                p0Num += trainMatrix[i]
                p0Denom += sum(trainMatrix[i])
        p1Vect = np.log(p1Num/p1Denom)#log防止下溢出
        p0Vect = np.log(p0Num/p0Denom)
        return p0Vect,p1Vect,pAbusive  #返回属于非侮辱类的条件概率数组,属于侮辱类的条件概率数组,文档属于侮辱类的概率

    3.测试算法:根据现实情况修改分类器

    def classifyNB(vec2Classify, p0Vec, p1Vec, pClass1):
        p1 = sum(vec2Classify*p1Vec)+np.log(pClass1)# #对应元素相乘。logA * B = logA + logB,所以这里加上log(pClass1)
        p0 = sum(vec2Classify*p0Vec)+np.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(np.array(trainMat),np.array(listClasses))
        testEntry = ['love','my','dalmation']
        thisDoc = np.array(setOfWords2Vec(myVocabList,testEntry))
        print(testEntry,'classified as:',classifyNB(thisDoc,p0V,p1V,pAb))
        testEntry = ['stupid','garbage']
        thisDoc = np.array(setOfWords2Vec(myVocabList,testEntry))
        print(testEntry,'classified as:',classifyNB(thisDoc,p0V,p1V,pAb))

    4.准备数据:文档词袋模型:和setOfWords2Vec区别是每个单词可以重复多次

    #词袋模型
    def bagOfWords2VecMN(vocabList, inputSet):
        returnVec = [0]*len(vocabList)
        for word in inputSet:
            if word in vocabList:
                returnVec[vocabList.index(word)] += 1
        return returnVec

    示例:使用朴素贝叶斯过滤垃圾邮件

    def textParse(bigString):
        """
        输入很长的字符串,转换为向量
        参数:
            bigString -- 长字符串
        返回:
            去掉少于两个字符,转换为小写的字符串
        """
        import re
        listOfTokens = re.split(r'\W*', bigString)#正则表达式来去掉空格和标点符号
        return [tok.lower() for tok in listOfTokens if len(tok) > 2] #全变成小写,去掉少于两个字符的字符串
    
    def spamTest():
        #新建三个列表
        docList=[]; classList = []; fullText =[]
        #遍历垃圾邮件和正常邮件,各25个
        for i in range(1,26):
            #读取垃圾邮件
            wordList = textParse(open("email/spam/{}.txt".format(i), errors = 'ignore').read())
            #添加到列表
            docList.append(wordList)
            fullText.extend(wordList)
            #添加到类
            classList.append(1)
            #读取正常邮件
            #ham中的23.txt总是报错有不能解读的字节,选择忽略该错误
            wordList = textParse(open("email/ham/{}.txt".format(i), errors = 'ignore').read())
            docList.append(wordList)
            fullText.extend(wordList)
            classList.append(0)
        #创建词汇表
        vocabList = createVocabList(docList)
        #训练集和测试集序号集
        trainingSet = list(range(50)); testSet=[]
        #随机抽取训练集中的10个序号,放入测试集
        for i in range(10):
            #生成随机序号
            randIndex = np.int(np.random.uniform(0,len(trainingSet)))
            #序号对应的元素由训练集移动到测试集中
            testSet.append(trainingSet[randIndex])
            del(trainingSet[randIndex]) 
        #新建训练矩阵和训练标签
        trainMat=[]; trainClasses = []
        #对于训练集中的元素
        for docIndex in trainingSet:
            #对应词袋添加到训练矩阵中
            trainMat.append(bagOfWords2VecMN(vocabList, docList[docIndex]))
            #类别添加到标签中
            trainClasses.append(classList[docIndex])
        #训练朴素贝叶斯分类器
        p0V,p1V,pSpam = trainNB0(np.array(trainMat),np.array(trainClasses))
        #错误计数器初始化为0
        errorCount = 0
        #对于测试集
        for docIndex in testSet:
            #得到词袋向量
            wordVector = bagOfWords2VecMN(vocabList, docList[docIndex])
            #判断结果
            if classifyNB(np.array(wordVector),p0V,p1V,pSpam) != classList[docIndex]:
                #统计错误
                errorCount += 1
                #打印错误信息
                print("错误序号为:{}".format(docList[docIndex]))
        print("总准确率为:{}".format(1 - np.float(errorCount)/len(testSet)))

     

    参考

    【1】https://zhuanlan.zhihu.com/p/36545000
    【2】《统计学习方法》李航
    【3】《机器学习实战》

     

     

     

     

     

     

     

    展开全文
  • 朴素贝叶斯对wine数据分类

    万次阅读 2015-11-10 09:51:53
    该实验的数据集是MostPopular Data ...经过几天对数据集以及分类算法的研究,详细研究了朴素贝叶斯分类器和其他学习算法,包括决策树和神经网络等等。同时由于这个数据集有13个属性,用决策树实现起来会很复杂。我最终

    该实验的数据集是MostPopular Data Sets(hits since 2007)中的wine数据集,这是是对在意大利同一地区生产的三种不同品种的酒,做大量分析所得出的数据。这些数据包括了三种酒中13种不同成分的数量。

    经过几天对数据集以及分类算法的研究,详细研究了朴素贝叶斯分类器和其他学习算法,包括决策树和神经网络等等。同时由于这个数据集有13个属性,用决策树实现起来会很复杂。我最终选择了用贝叶斯分类算法来实现。编程的时候采用c++语言实现分类的功能。我将178个样本分成118个训练样本和60个测试样本,采用朴素贝叶斯分类算法,计算出先验概率和后验概率,通过比较概率的最大值,判别出测试样本所属于的酒的类型,同时输出测试样本计算的正确率和错误率。

    1.实验数据集介绍

    1.1Wine数据集

    该实验的数据源是Wine data,这是对在意大利同一地区生产的三种不同品种的酒,做大量分析所得出的数据。如下图1-1所示:


    这些数据包括了三种酒中13种不同成分的数量。13种成分分别为:Alcohol,Malicacid,Ash,Alcalinity of ash,Magnesium,Total phenols,Flavanoids,Nonflavanoid phenols,Proanthocyanins,Color intensity,Hue,OD280/OD315 of diluted wines,Proline。在 “wine.data”文件中,每行代表一种酒的样本,共有178个样本;一共有14列,其中,第一列为类标志属性,共有三类,分别记为“1”,“2”,“3”;后面的13列为每个样本的对应属性的样本值。其中第1类有59个样本,第2类有71个样本,第3类有48个样本。

         由于数据源文件中的每个样本的数据都是完整的,没有空缺值等,所以我没有对该数据源文件进行数据的清理工作。

    2.实验方案

    2.1朴素贝叶斯分类算法

    每个数据样本用一个n维特征向量X={x1,x2,…,xn}表示,分别描述对n个属性A1,A2,..,An样本的n个度量。假定有m个类C1,…,Cm,对于数据样本X,分类法将预测X属于类Ci,当且仅当:P(Ci|X)> P(Cj|X),1<=j<=m而且j不等于i。

    根据贝叶斯定理, :P(Ci|X)=P(X|Ci)P(Ci)/P(X)

    由于P(X)对于所有类都是常数,只需最大化P(X|Ci)P(Ci),计算P(X|Ci),朴素贝叶斯分类假设类条件独立.即给定样本属性值相互条件独立,即:

    ,在使用中,p常用频度代替。

    2.2朴素贝叶斯分类的原理与流程

    朴素贝叶斯的思想基础是这样的:对于给出的待分类项,求解在此项出现的条件下各个类别出现的概率,哪个最大,就认为此待分类项属于哪个类别。通俗来说,就好比这么个道理,你在街上看到一个黑人,我问你猜这哥们哪里来的,你十有八九猜非洲。为什么呢?因为黑人中非洲人的比率最高,当然人家也可能是美洲人或亚洲人,但在没有其它可用信息下,我们会选择条件概率最大的类别,这就是朴素贝叶斯的思想基础。朴素贝叶斯分类的正式定义如下:

          1、设为一个待分类项,而每个a为x的一个特征属性。

          2、有类别集合

          3、计算

          4、如果

    那么现在的关键就是如何计算第3步中的各个条件概率。我们可以这么做:

          1、找到一个已知分类的待分类项集合,这个集合叫做训练样本集。

          2、统计得到在各类别下各个特征属性的条件概率估计。即。

          3、如果各个特征属性是条件独立的,则根据贝叶斯定理有如下推导:


          

    因为分母对于所有类别为常数,因为我们只要将分子最大化皆可。又因为各特征属性是条件独立的,所以有:


          

    根据上述分析,朴素贝叶斯分类的流程可以由下图2-1表示(暂时不考虑验证):


                

    3实验步骤

    3.1数据集的下载

        在http://archive.ics.uci.edu/ml/网页上下载实验所用的Wine数据集。点击Wine数据集,在页面上,点击Data Folder,下载wine.data数据,即为实验所需的数据集。

    3.2朴素贝叶斯算法实现

    首先,将Wine数据集分成118个训练样本和60个测试样本,分别保存在“Ttrainingwine.data”和 “testwine.data”中。用DataRead从文件中读取数值。

    然后用朴素贝叶斯算法的思想:

    1.统计三类红酒数据的数量,各自求和,拿各自类的数量除以总数,求出它们的先验概率p(Q1),p(Q2),p(Q3),保存在数组R中的R[0], R[1], R[2]。

    2.分别求P(Xk|Q1)中 ,P(Xk|Q2)中和 P(Xk|Q3) 中Xk的个数。

    3.计算概率p(X|Q1),计算p(Q1)*p(X|Q1),同样的方法去计算概率p(X|Q2), p(Q2)*p(X|Q2), p(X|Q3), p(Q3)*p(X|Q3),把这三个计算出来的概率值p(Q1)*p(X|Q1),p(Q2)*p(X|Q2),p(Q3)*p(X|Q3)保存在数组gailv中的gailv[0],gailv[1],gailv[2]。

    4.比较gailv[0],gailv[1],gailv[2],找出最大值,最大值所对应的那个类即为我们要找的wine的分类。

    3.3朴素贝叶斯算法实现的源代码

        关于具体的实现代码见下面,此处不做详细的说明。

    3.4实验结果

    实验结果如下面的截图所示。

    源代码:

    MachineLearning.h:

    #include <string>
    #include <set>                       //set是C++标准库中的一种关联容器。所谓关联容器就是通过键(key)来读取和修改元素。
                                       //set容器的每一个键只能对应一个元素,即不存在键相同的不同元素。


    #include <map>                      //map 一种容器 也叫关联数组 
                                                  //你先把它理解成数组  一个个的元素知道吧
                                                //然后你再这样理解,每个元素都有两个值,一个叫“键”,一个叫“值”
                                              //你可以通过“键”找到相关的“值”
                                             //通常map容器 只能存入单一实例,就是说不能有相同的“键/值”
                                            //map 就是 在key和value之间建立映射,是的可以通过key访问/获取value。


    #include <vector>                 //标准库Vector类型,使用需要的头文件
                                              //vector是一种顺序容器,事实上和数组差不多,但它比数组更优越。
                                            //一般来说数组不能动态拓展,因此在程序运行的时候不是浪费内存,就是造成越界。
                                         //而vector正好弥补了这个缺陷,它的特征是相当于可分配拓展的数组,它的随机访问快,
    using namespace std;
    /*
      1) Alcohol
      2) Malic acid
      3) Ash
    4) Alcalinity of ash  
      5) Magnesium
    6) Total phenols
      7) Flavanoids
      8) Nonflavanoid phenols
      9) Proanthocyanins
    10)Color intensity
      11)Hue
      12)OD280/OD315 of diluted wines
      13)Proline            


    */
    int xunlianshuliang = 118; //所有训练数据的范围
    int ceshishuliang= 60;
    struct yuanshishuju
    {
    double M1;
    double M2;
    double M3;
    double M4;
        double M5;
        double M6;
    double M7;
    double M8;
    double M9;
    double M10;
    double M11;
    double M12;
    double M13;
    double M14;
    };

    MachineLearning.cpp:

    #include <iostream>                              //包含输入输出流
    #include <sstream>                               //sstream是字符串流,C++引入了ostringstream、istringstream、stringstream这三个类
                                                     //要使用他们创建对象就必须包含sstream.h头文件 
    #include <fstream>                               //包含文件流,这样就可以使用与文件相关的一些函数,像open(),close()等                                                                                 
    #include "MachineLearning.h"                     //自己所建的一个头文件,名字为MachineLearning
    using namespace std;                             //命名空间,c++中的所有标识符都被定义于std命名空间中
    double R[3];                                     //在这里定义一个数组,用来存放先验概率
    int m;             
    vector<yuanshishuju> ceshishuju;                 //存放测试数据
    vector<yuanshishuju> xunlianshuju;               //存放训练数据,vector是一个能够存放任意类型的动态数组,能够增加和压缩数据。
    const int shuxingzongshu=13;                     //这里定义属性总数为一个常量,而且以后不能对其修改
    map<double, double> Q1_map[13];                  //存放每一类型,每种属性中某数值的概率
    map<double, double> Q2_map[13];                  //自动建立Key - value的对应。key 和 value可以是任意你需要的类型
    map<double, double> Q3_map[13];
    ifstream   file1;                             //ifstream表示是以输入的方式打开文件


    void DataRead(vector<yuanshishuju> &shuju, const char* fileName)   //用DataRead从文件中读取数值 
    {
    file1.open(fileName);                                         //创建或打开一个用于访问文件的对象
    int s;
    if (fileName[0] == 'T')
    s = xunlianshuliang;
    else 
    s = ceshishuliang;
    string line;                                                  //定义一个line变量,string类型
    yuanshishuju Ttrainingwine;
    for (int a = 0;  a < s; a++)
    {
    file1 >> line;
    while (line.find(',') > 0 && line.find(',') < line.length())     //find查找一个元素
    {
    line[line.find(',')] = ' '; 
    }
    istringstream stream(line);                                     //从字符串读,istringstream对象可以绑定一行字符串,然后以空格为分隔符把该行分隔开来
    stream >> Ttrainingwine.M1 >> Ttrainingwine.M2 >> Ttrainingwine.M3 >> Ttrainingwine.M4 >> Ttrainingwine.M5 >> Ttrainingwine.M6 >> Ttrainingwine.M7 >> Ttrainingwine.M8 >> 
    Ttrainingwine.M9 >> Ttrainingwine.M10 >>Ttrainingwine.M11 >>Ttrainingwine.M12 >> Ttrainingwine.M13 >> Ttrainingwine.M14;
    shuju.push_back(Ttrainingwine);                                 //在vector尾部加入一个值为Ttrainingwine的数据
    }
    file1.close();                                                      //关闭文件
    }


    void pusubeiyesi()
    {
    int number1 = 0; 
    int number2 = 0;
    int number3 = 0;
    int a;


        //统计三类红酒数据的数量,各自求和


    for(a = 0; a < xunlianshuliang  ; a++)
    {
    if(xunlianshuju[a].M1 == 1)
    {
    number1 ++;
    }
    if(xunlianshuju[a].M1 == 2)
    {
    number2 ++;
    }
    if(xunlianshuju[a].M1 == 3)
    {
    number3 ++;
    }                                                   
    }


        //求它们的先验概率,拿各自类的数量除以总数


    R[0] = (double)number1/(double)xunlianshuliang;         
    R[1] = (double)number2/(double)xunlianshuliang;
    R[2] = (double)number3/(double)xunlianshuliang;

    map<double, double>::iterator match;                     //interator迭代器,可以把它当做指向所属容器的指针
        for( a= 0 ; a < xunlianshuliang; a++)       
    {
            //分别求P(Xk|Q1)中 ,P(Xk|Q2)中和 P(Xk|Q3) 中Xk的个数


    if(xunlianshuju[a].M1 == 1)                          
    {
    int b=0;
    for(;b< 13 ;b++)
    {
    double n = *(&xunlianshuju[b].M2+b);        //n为指向依次指向13个属性的属性内容

    match = Q1_map[b].find(n);                  //遍历第一类红酒的数组,用find()函数返回一个迭代器指向键值为n的元素
    if(match == Q1_map[b].end())
    {    

                        Q1_map[b].insert(pair<double, double>(n, 1));    //在第一类红酒的表Q1_map中用insert插入pair数据
    }
    else
    {
    double b = match->second;                       //否则的话就指向第2个迭代器
    match->second = b + 1;
    }
    }
    }
            
    if(xunlianshuju[a].M1 == 2)                             
    {
    int b = 0;
    for(;b< 13 ;b++)
    {
    double n = *(&xunlianshuju[a].M2+b);

    match = Q2_map[b].find(n);         //遍历第二类红酒的数组,用find()函数返回一个迭代器指向键值为n的元素                 
    if(match == Q2_map[b].end())
    {

                          Q2_map[b].insert(pair<double, double>(n, 1)); //在第二类红酒的表Q2_map中用insert插入pair数据
    }
    else
    {
    double b = match->second;                       //否则的话就指向第2个迭代器
    match->second = b + 1;
    }
    }
    }


    if(xunlianshuju[a].M1 == 3)                                 
    {
    int b = 0;
    for(;b< 13 ;b++)
    {
    double n = *(&xunlianshuju[a].M2+b);

    match = Q3_map[b].find(n);                             //遍历第三类红酒的各属性值,用find()函数返回一个迭代器指向键值为n的元素  
    if(match == Q3_map[b].end())
    {

                          Q3_map[b].insert(pair<double, double>(n, 1));     //在第三类红酒的表Q3_map中用insert插入pair数据
    }
    else
    {
    double b = match->second;
    match->second = b + 1;
    }
    }
    }
    }


    //计算各自的概率


    for(a = 0; a < shuxingzongshu; a++)
    {
    for(match=Q1_map[a].begin(); match!=Q1_map[a].end(); ++match) 
    {
    double number = match->second;                            
    match->second = (double)number/(double)number1;
    }

    for(match=Q2_map[a].begin(); match!=Q2_map[a].end(); ++match) 
    {
    double number = match->second; 
    match->second = (double)number/(double)number2;
    }


    for(match=Q3_map[a].begin(); match!=Q3_map[a].end(); ++match) 
    {
    double number = match->second; 
    match->second = (double)number/(double)number3;
            }

    }
    }


         //计算后验概率,找出最大值,最大值所对应的那个类即为我们要找的分类



    void houyangailv()                    

    {
    int a,b,c;
    double gailv[3];
       for(a = 0; a<ceshishuliang; a++)
    {
    double pXQ[3]={0,0,0};
    for(b = 0; b < 3; b++)
    {
    map<double, double>::iterator match;

       //计算概率p(X|Q1)


    for(c = 0; c < shuxingzongshu; c++)
    {
    match = Q1_map[c].find(*(&ceshishuju[a].M2+c));
    if(match != Q1_map[c].end())
    {
    pXQ[0] =pXQ[0]+match->second;
    }
    }


    //计算p(Q1)*p(X|Q1)


    gailv[0] = R[0] * pXQ[0];
       
    //计算概率p(X|Q2)
    for(c = 0; c < shuxingzongshu; c++)
    {
    match = Q2_map[c].find(*(&ceshishuju[a].M2+c));
    if(match != Q2_map[c].end())
    {
    pXQ[1] =pXQ[1]+match->second;
    }
    }
                    
    //计算p(Q2)*p(X|Q2)


    gailv[1] = R[1]*pXQ[1];


       //计算概率p(X|Q3)


    for(c = 0; c < shuxingzongshu; c++)
    {
    match = Q3_map[c].find(*(&ceshishuju[a].M2+c));
    if(match != Q3_map[c].end())
    {
    pXQ[2] =pXQ[2]+match->second;
    }
    }


                    //计算p(Q3)*p(X|Q3)


    gailv[2] = R[2]*pXQ[2];

    }
               
      
     //找出计算出的概率最大值
               
     if(gailv[0] > gailv[1] && gailv[0] >gailv[2])
    {   
    cout<<"    "<<1<<"        "<<gailv[0]<<"   "<<gailv[1]<<"         "<<gailv[3]<<"                  "<<gailv[0]<<endl;
    cout<<endl;
    if(ceshishuju[a].M1==1)
       m++;
    }
    else
    {
    if(gailv[1] > gailv[2])
    {
     
     cout<<"    "<<2<<"        "<<gailv[0]<<"          "<<gailv[1]<<"         "<<gailv[3]<<"                  "<<gailv[1]<<endl; 
     cout<<endl;
    if(ceshishuju[a].M1==2)
           m++;
    }
    else
    {  
      
                      cout<<"    "<<3<<"        "<<gailv[0]<<"          "<<gailv[1]<<"        "<<gailv[3]<<"                  "<<gailv[2]<<endl;
                      cout<<endl;
           m++;
    }
    }
    }
    }

    void  main()
    {
    double zhengquelv,cuowulv;
    cout<<endl;


    //输出计算出来的各种分类的信息


            cout<<"分类结果"<<"    "<<"概率1"<<"          "<<"概率2"<<"          "<<"概率3"<<"           "<<"计算出来的概率的最大值"<<endl;
       DataRead(xunlianshuju,"Ttrainingwine.data");
    pusubeiyesi();
    DataRead(ceshishuju,"testwine.data");
    houyangailv();
            zhengquelv=(double)m/60;
    cuowulv=1-zhengquelv;
    cout<<endl<<endl<<endl;


    //输出正确率和错误率


    cout<<"测试样本计算的正确率(百分比):"<<zhengquelv*100<<"%"<<" ,"<<"测试样本计算的错误率(百分比):"<<cuowulv*100<<"%"<<endl;
          
    }


    训练数据集:Ttrainingwine.data

    1,13.71,1.86,2.36,16.6,101,2.61,2.88,.27,1.69,3.8,1.11,4,1035
    1,12.85,1.6,2.52,17.8,95,2.48,2.37,.26,1.46,3.93,1.09,3.63,1015
    1,13.5,1.81,2.61,20,96,2.53,2.61,.28,1.66,3.52,1.12,3.82,845
    1,13.05,2.05,3.22,25,124,2.63,2.68,.47,1.92,3.58,1.13,3.2,830
    1,13.39,1.77,2.62,16.1,93,2.85,2.94,.34,1.45,4.8,.92,3.22,1195
    1,13.3,1.72,2.14,17,94,2.4,2.19,.27,1.35,3.95,1.02,2.77,1285
    1,13.87,1.9,2.8,19.4,107,2.95,2.97,.37,1.76,4.5,1.25,3.4,915
    1,14.02,1.68,2.21,16,96,2.65,2.33,.26,1.98,4.7,1.04,3.59,1035
    1,13.73,1.5,2.7,22.5,101,3,3.25,.29,2.38,5.7,1.19,2.71,1285
    1,13.58,1.66,2.36,19.1,106,2.86,3.19,.22,1.95,6.9,1.09,2.88,1515
    1,13.68,1.83,2.36,17.2,104,2.42,2.69,.42,1.97,3.84,1.23,2.87,990
    1,13.76,1.53,2.7,19.5,132,2.95,2.74,.5,1.35,5.4,1.25,3,1235
    1,13.51,1.8,2.65,19,110,2.35,2.53,.29,1.54,4.2,1.1,2.87,1095
    1,13.48,1.81,2.41,20.5,100,2.7,2.98,.26,1.86,5.1,1.04,3.47,920
    1,13.28,1.64,2.84,15.5,110,2.6,2.68,.34,1.36,4.6,1.09,2.78,880
    1,13.05,1.65,2.55,18,98,2.45,2.43,.29,1.44,4.25,1.12,2.51,1105
    1,13.07,1.5,2.1,15.5,98,2.4,2.64,.28,1.37,3.7,1.18,2.69,1020
    1,14.22,3.99,2.51,13.2,128,3,3.04,.2,2.08,5.1,.89,3.53,760
    1,13.56,1.71,2.31,16.2,117,3.15,3.29,.34,2.34,6.13,.95,3.38,795
    1,13.41,3.84,2.12,18.8,90,2.45,2.68,.27,1.48,4.28,.91,3,1035
    1,13.88,1.89,2.59,15,101,3.25,3.56,.17,1.7,5.43,.88,3.56,1095
    1,13.24,3.98,2.29,17.5,103,2.64,2.63,.32,1.66,4.36,.82,3,680
    1,13.05,1.77,2.1,17,107,3,3,.28,2.03,5.04,.88,3.35,885
    1,14.21,4.04,2.44,18.9,111,2.85,2.65,.3,1.25,5.24,.87,3.33,1080
    1,14.38,3.59,2.28,16,102,3.25,3.17,.27,2.19,4.9,1.04,3.44,1065
    1,13.9,1.68,2.12,16,101,3.1,3.39,.21,2.14,6.1,.91,3.33,985
    1,14.1,2.02,2.4,18.8,103,2.75,2.92,.32,2.38,6.2,1.07,2.75,1060
    1,13.94,1.73,2.27,17.4,108,2.88,3.54,.32,2.08,8.90,1.12,3.1,1260
    1,13.05,1.73,2.04,12.4,92,2.72,3.27,.17,2.91,7.2,1.12,2.91,1150
    1,13.83,1.65,2.6,17.2,94,2.45,2.99,.22,2.29,5.6,1.24,3.37,1265
    1,13.82,1.75,2.42,14,111,3.88,3.74,.32,1.87,7.05,1.01,3.26,1190
    1,13.77,1.9,2.68,17.1,115,3,2.79,.39,1.68,6.3,1.13,2.93,1375
    1,13.74,1.67,2.25,16.4,118,2.6,2.9,.21,1.62,5.85,.92,3.2,1060
    1,13.56,1.73,2.46,20.5,116,2.96,2.78,.2,2.45,6.25,.98,3.03,1120
    1,14.22,1.7,2.3,16.3,118,3.2,3,.26,2.03,6.38,.94,3.31,970
    1,13.29,1.97,2.68,16.8,102,3,3.23,.31,1.66,6,1.07,2.84,1270
    1,13.72,1.43,2.5,16.7,108,3.4,3.67,.19,2.04,6.8,.89,2.87,1285
    2,12.37,1.13,2.16,19,87,3.5,3.1,.19,1.87,4.45,1.22,2.87,420
    2,12.17,1.45,2.53,19,104,1.89,1.75,.45,1.03,2.95,1.45,2.23,355
    2,12.37,1.21,2.56,18.1,98,2.42,2.65,.37,2.08,4.6,1.19,2.3,678
    2,13.11,1.01,1.7,15,78,2.98,3.18,.26,2.28,5.3,1.12,3.18,502
    2,12.37,1.17,1.92,19.6,78,2.11,2,.27,1.04,4.68,1.12,3.48,510
    2,13.34,.94,2.36,17,110,2.53,1.3,.55,.42,3.17,1.02,1.93,750
    2,12.21,1.19,1.75,16.8,151,1.85,1.28,.14,2.5,2.85,1.28,3.07,718
    2,12.29,1.61,2.21,20.4,103,1.1,1.02,.37,1.46,3.05,.906,1.82,870
    2,11.96,1.09,2.3,21,101,3.38,2.14,.13,1.65,3.21,.99,3.13,886
    2,11.84,2.89,2.23,18,112,1.72,1.32,.43,.95,2.65,.96,2.52,500
    2,12.33,.99,1.95,14.8,136,1.9,1.85,.35,2.76,3.4,1.06,2.31,750
    2,12.7,3.87,2.4,23,101,2.83,2.55,.43,1.95,2.57,1.19,3.13,463
    2,12,.92,2,19,86,2.42,2.26,.3,1.43,2.5,1.38,3.12,278
    2,12.72,1.81,2.2,18.8,86,2.2,2.53,.26,1.77,3.9,1.16,3.14,714
    2,12.08,1.13,2.51,24,78,2,1.58,.4,1.4,2.2,1.31,2.72,630
    2,13.05,3.86,2.32,22.5,85,1.65,1.59,.61,1.62,4.8,.84,2.01,515
    2,11.84,.89,2.58,18,94,2.2,2.21,.22,2.35,3.05,.79,3.08,520
    2,12.67,.98,2.24,18,99,2.2,1.94,.3,1.46,2.62,1.23,3.16,450
    2,12.16,1.61,2.31,22.8,90,1.78,1.69,.43,1.56,2.45,1.33,2.26,495
    2,11.65,1.67,2.62,26,88,1.92,1.61,.4,1.34,2.6,1.36,3.21,562
    2,11.64,2.06,2.46,21.6,84,1.95,1.69,.48,1.35,2.8,1,2.75,680
    2,12.08,1.33,2.3,23.6,70,2.2,1.59,.42,1.38,1.74,1.07,3.21,625
    2,12.08,1.83,2.32,18.5,81,1.6,1.5,.52,1.64,2.4,1.08,2.27,480
    2,12,1.51,2.42,22,86,1.45,1.25,.5,1.63,3.6,1.05,2.65,450
    2,12.69,1.53,2.26,20.7,80,1.38,1.46,.58,1.62,3.05,.96,2.06,495
    2,12.29,2.83,2.22,18,88,2.45,2.25,.25,1.99,2.15,1.15,3.3,290
    2,11.62,1.99,2.28,18,98,3.02,2.26,.17,1.35,3.25,1.16,2.96,345
    2,12.47,1.52,2.2,19,162,2.5,2.27,.32,3.28,2.6,1.16,2.63,937
    2,11.81,2.12,2.74,21.5,134,1.6,.99,.14,1.56,2.5,.95,2.26,625
    2,12.29,1.41,1.98,16,85,2.55,2.5,.29,1.77,2.9,1.23,2.74,428
    2,12.37,1.07,2.1,18.5,88,3.52,3.75,.24,1.95,4.5,1.04,2.77,660
    2,12.29,3.17,2.21,18,88,2.85,2.99,.45,2.81,2.3,1.42,2.83,406
    2,12.52,2.43,2.17,21,88,2.55,2.27,.26,1.22,2,.9,2.78,325
    2,11.76,2.68,2.92,20,103,1.75,2.03,.6,1.05,3.8,1.23,2.5,607
    2,11.41,.74,2.5,21,88,2.48,2.01,.42,1.44,3.08,1.1,2.31,434
    2,12.08,1.39,2.5,22.5,84,2.56,2.29,.43,1.04,2.9,.93,3.19,385
    2,11.03,1.51,2.2,21.5,85,2.46,2.17,.52,2.01,1.9,1.71,2.87,407
    2,11.82,1.47,1.99,20.8,86,1.98,1.6,.3,1.53,1.95,.95,3.33,495
    2,12.42,1.61,2.19,22.5,108,2,2.09,.34,1.61,2.06,1.06,2.96,345
    2,12.77,3.43,1.98,16,80,1.63,1.25,.43,.83,3.4,.7,2.12,372
    2,12,3.43,2,19,87,2,1.64,.37,1.87,1.28,.93,3.05,564
    2,11.45,2.4,2.42,20,96,2.9,2.79,.32,1.83,3.25,.8,3.39,625
    2,12.04,4.3,2.38,22,80,2.1,1.75,.42,1.35,2.6,.79,2.57,580
    3,12.81,2.31,2.4,24,98,1.15,1.09,.27,.83,5.7,.66,1.36,560
    3,12.7,3.55,2.36,21.5,106,1.7,1.2,.17,.84,5,.78,1.29,600
    3,12.51,1.24,2.25,17.5,85,2,.58,.6,1.25,5.45,.75,1.51,650
    3,12.6,2.46,2.2,18.5,94,1.62,.66,.63,.94,7.1,.73,1.58,695
    3,12.25,4.72,2.54,21,89,1.38,.47,.53,.8,3.85,.75,1.27,720
    3,12.53,5.51,2.64,25,96,1.79,.6,.63,1.1,5,.82,1.69,515
    3,13.49,3.59,2.19,19.5,88,1.62,.48,.58,.88,5.7,.81,1.82,580
    3,12.84,2.96,2.61,24,101,2.32,.6,.53,.81,4.92,.89,2.15,590
    3,12.93,2.81,2.7,21,96,1.54,.5,.53,.75,4.6,.77,2.31,600
    3,13.36,2.56,2.35,20,89,1.4,.5,.37,.64,5.6,.7,2.47,780
    3,13.52,3.17,2.72,23.5,97,1.55,.52,.5,.55,4.35,.89,2.06,520
    3,13.62,4.95,2.35,20,92,2,.8,.47,1.02,4.4,.91,2.05,550
    3,12.25,3.88,2.2,18.5,112,1.38,.78,.29,1.14,8.21,.65,2,855
    3,13.16,3.57,2.15,21,102,1.5,.55,.43,1.3,4,.6,1.68,830
    3,13.88,5.04,2.23,20,80,.98,.34,.4,.68,4.9,.58,1.33,415
    3,12.87,4.61,2.48,21.5,86,1.7,.65,.47,.86,7.65,.54,1.86,625
    3,13.32,3.24,2.38,21.5,92,1.93,.76,.45,1.25,8.42,.55,1.62,650
    3,13.08,3.9,2.36,21.5,113,1.41,1.39,.34,1.14,9.40,.57,1.33,550
    3,13.5,3.12,2.62,24,123,1.4,1.57,.22,1.25,8.60,.59,1.3,500
    3,12.79,2.67,2.48,22,112,1.48,1.36,.24,1.26,10.8,.48,1.47,480
    3,13.11,1.9,2.75,25.5,116,2.2,1.28,.26,1.56,7.1,.61,1.33,425
    3,13.23,3.3,2.28,18.5,98,1.8,.83,.61,1.87,10.52,.56,1.51,675
    3,12.58,1.29,2.1,20,103,1.48,.58,.53,1.4,7.6,.58,1.55,640
    3,13.17,5.19,2.32,22,93,1.74,.63,.61,1.55,7.9,.6,1.48,725
    3,13.84,4.12,2.38,19.5,89,1.8,.83,.48,1.56,9.01,.57,1.64,480
    3,12.45,3.03,2.64,27,97,1.9,.58,.63,1.14,7.5,.67,1.73,880
    3,14.34,1.68,2.7,25,98,2.8,1.31,.53,2.7,13,.57,1.96,660
    3,14.16,2.51,2.48,20,91,1.68,.7,.44,1.24,9.7,.62,1.71,660
    3,13.71,5.65,2.45,20.5,95,1.68,.61,.52,1.06,7.7,.64,1.74,740
    3,13.4,3.91,2.48,23,102,1.8,.75,.43,1.41,7.3,.7,1.56,750
    3,13.27,4.28,2.26,20,120,1.59,.69,.43,1.35,10.2,.59,1.56,835
    3,13.17,2.59,2.37,20,120,1.65,.68,.53,1.46,9.3,.6,1.62,840
    3,14.13,4.1,2.74,24.5,96,2.05,.76,.56,1.35,9.2,.61,1.6,560
    3,13.45,3.7,2.6,23,111,1.7,.92,.43,1.46,10.68,.85,1.56,695
    3,12.82,3.37,2.3,19.5,88,1.48,.66,.4,.97,10.26,.72,1.75,685
    3,13.58,2.58,2.69,24.5,105,1.55,.84,.39,1.54,8.66,.74,1.8,750
    3,13.4,4.6,2.86,25,112,1.98,.96,.27,1.11,8.5,.67,1.92,630
    3,12.2,3.03,2.32,19,96,1.25,.49,.4,.73,5.5,.66,1.83,510


    测试数据集:testwine.data

    1,13.16,2.36,2.67,18.6,101,2.8,3.24,.3,2.81,5.68,1.03,3.17,1185
    1,12.93,3.8,2.65,18.6,102,2.41,2.41,.25,1.98,4.5,1.03,3.52,770
    1,14.23,1.71,2.43,15.6,127,2.8,3.06,.28,2.29,5.64,1.04,3.92,1065
    1,13.2,1.78,2.14,11.2,100,2.65,2.76,.26,1.28,4.38,1.05,3.4,1050
    1,13.16,2.36,2.67,18.6,101,2.8,3.24,.3,2.81,5.68,1.03,3.17,1185
    1,12.93,3.8,2.65,18.6,102,2.41,2.41,.25,1.98,4.5,1.03,3.52,770
    1,13.71,1.86,2.36,16.6,101,2.61,2.88,.27,1.69,3.8,1.11,4,1035
    1,12.85,1.6,2.52,17.8,95,2.48,2.37,.26,1.46,3.93,1.09,3.63,1015
    1,13.5,1.81,2.61,20,96,2.53,2.61,.28,1.66,3.52,1.12,3.82,845
    1,13.05,2.05,3.22,25,124,2.63,2.68,.47,1.92,3.58,1.13,3.2,830
    1,13.39,1.77,2.62,16.1,93,2.85,2.94,.34,1.45,4.8,.92,3.22,1195
    1,13.3,1.72,2.14,17,94,2.4,2.19,.27,1.35,3.95,1.02,2.77,1285
    1,13.87,1.9,2.8,19.4,107,2.95,2.97,.37,1.76,4.5,1.25,3.4,915
    1,14.02,1.68,2.21,16,96,2.65,2.33,.26,1.98,4.7,1.04,3.59,1035
    1,13.73,1.5,2.7,22.5,101,3,3.25,.29,2.38,5.7,1.19,2.71,1285
    1,13.58,1.66,2.36,19.1,106,2.86,3.19,.22,1.95,6.9,1.09,2.88,1515
    1,13.68,1.83,2.36,17.2,104,2.42,2.69,.42,1.97,3.84,1.23,2.87,990
    1,13.76,1.53,2.7,19.5,132,2.95,2.74,.5,1.35,5.4,1.25,3,1235
    1,13.51,1.8,2.65,19,110,2.35,2.53,.29,1.54,4.2,1.1,2.87,1095
    1,13.48,1.81,2.41,20.5,100,2.7,2.98,.26,1.86,5.1,1.04,3.47,920
    2,12.64,1.36,2.02,16.8,100,2.02,1.41,.53,.62,5.75,.98,1.59,450
    2,13.67,1.25,1.92,18,94,2.1,1.79,.32,.73,3.8,1.23,2.46,630
    2,12.37,.94,1.36,10.6,88,1.98,.57,.28,.42,1.95,1.05,1.82,520
    2,12.33,1.1,2.28,16,101,2.05,1.09,.63,.41,3.27,1.25,1.67,680
    2,12.64,1.36,2.02,16.8,100,2.02,1.41,.53,.62,5.75,.98,1.59,450
    2,13.67,1.25,1.92,18,94,2.1,1.79,.32,.73,3.8,1.23,2.46,630
    2,12.37,1.13,2.16,19,87,3.5,3.1,.19,1.87,4.45,1.22,2.87,420
    2,12.17,1.45,2.53,19,104,1.89,1.75,.45,1.03,2.95,1.45,2.23,355
    2,12.37,1.21,2.56,18.1,98,2.42,2.65,.37,2.08,4.6,1.19,2.3,678
    2,13.11,1.01,1.7,15,78,2.98,3.18,.26,2.28,5.3,1.12,3.18,502
    2,12.37,1.17,1.92,19.6,78,2.11,2,.27,1.04,4.68,1.12,3.48,510
    2,13.34,.94,2.36,17,110,2.53,1.3,.55,.42,3.17,1.02,1.93,750
    2,12.21,1.19,1.75,16.8,151,1.85,1.28,.14,2.5,2.85,1.28,3.07,718
    2,12.29,1.61,2.21,20.4,103,1.1,1.02,.37,1.46,3.05,.906,1.82,870
    2,11.96,1.09,2.3,21,101,3.38,2.14,.13,1.65,3.21,.99,3.13,886
    2,11.84,2.89,2.23,18,112,1.72,1.32,.43,.95,2.65,.96,2.52,500
    2,12.33,.99,1.95,14.8,136,1.9,1.85,.35,2.76,3.4,1.06,2.31,750
    2,12.7,3.87,2.4,23,101,2.83,2.55,.43,1.95,2.57,1.19,3.13,463
    2,12,.92,2,19,86,2.42,2.26,.3,1.43,2.5,1.38,3.12,278
    2,12.72,1.81,2.2,18.8,86,2.2,2.53,.26,1.77,3.9,1.16,3.14,714
    3,12.86,1.35,2.32,18,122,1.51,1.25,.21,.94,4.1,.76,1.29,630
    3,12.88,2.99,2.4,20,104,1.3,1.22,.24,.83,5.4,.74,1.42,530
    3,12.86,1.35,2.32,18,122,1.51,1.25,.21,.94,4.1,.76,1.29,630
    3,12.88,2.99,2.4,20,104,1.3,1.22,.24,.83,5.4,.74,1.42,530
    3,12.81,2.31,2.4,24,98,1.15,1.09,.27,.83,5.7,.66,1.36,560
    3,12.7,3.55,2.36,21.5,106,1.7,1.2,.17,.84,5,.78,1.29,600
    3,12.51,1.24,2.25,17.5,85,2,.58,.6,1.25,5.45,.75,1.51,650
    3,12.6,2.46,2.2,18.5,94,1.62,.66,.63,.94,7.1,.73,1.58,695
    3,12.25,4.72,2.54,21,89,1.38,.47,.53,.8,3.85,.75,1.27,720
    3,12.53,5.51,2.64,25,96,1.79,.6,.63,1.1,5,.82,1.69,515
    3,13.49,3.59,2.19,19.5,88,1.62,.48,.58,.88,5.7,.81,1.82,580
    3,12.84,2.96,2.61,24,101,2.32,.6,.53,.81,4.92,.89,2.15,590
    3,12.93,2.81,2.7,21,96,1.54,.5,.53,.75,4.6,.77,2.31,600
    3,13.36,2.56,2.35,20,89,1.4,.5,.37,.64,5.6,.7,2.47,780
    3,13.52,3.17,2.72,23.5,97,1.55,.52,.5,.55,4.35,.89,2.06,520
    3,13.62,4.95,2.35,20,92,2,.8,.47,1.02,4.4,.91,2.05,550
    3,12.25,3.88,2.2,18.5,112,1.38,.78,.29,1.14,8.21,.65,2,855
    3,13.16,3.57,2.15,21,102,1.5,.55,.43,1.3,4,.6,1.68,830
    3,13.88,5.04,2.23,20,80,.98,.34,.4,.68,4.9,.58,1.33,415
    3,12.87,4.61,2.48,21.5,86,1.7,.65,.47,.86,7.65,.54,1.86,625


    实验贴图:














    展开全文
  • 朴素贝叶斯(Naïve Bayes) 属性独立性是Naïve Bayes的前提也是关键 思想:通俗地说,就是根据已有的数据集,得到先验概率各种属性对于各种决策的条件概率(可以理解为每种属性对每种决策的影响的大小);面
  • 针对数据缺失问题,基于期望最大值算法(EM),将朴素贝叶斯分类器利用已有的不完整数据进行参数学习;针对样本数值型连续属性非正态分布的情况,基于核密度估计,利用其分布密度(Distribution Density)和新的分析...
  • 贝叶斯分类器分成两个部分,第一部分对基础知识、贝叶斯决策论、极似然估计、朴素贝叶斯分类器和半朴素贝叶斯分类器进行介绍,第二部分对贝叶斯网进行详细介绍。本文是对周志华老师的《机器学习》第七章贝叶斯分类...
  • 贝叶斯分类器分成两个部分,第一部分对基础知识、贝叶斯决策论、极似然估计、朴素贝叶斯分类器和半朴素贝叶斯分类器进行介绍,第二部分对贝叶斯网进行详细介绍。本文是对周志华老师的《机器学习》第七章贝叶斯分类...
  • 朴素贝叶斯分类器是一种众所周知的机器学习分类器,应用于自然语言处理(NLP)其他领域。尽管它很简单,但它能够在不同的任务中实现高于平均水平的表现,例如情绪分析。今天我们将详细阐述该模型的核心原理,然后在...
  • 高斯判别分析朴素贝叶斯等传统贝叶斯分类方法在构建...将基于D-vine Copula理论的贝叶斯分类器应用到生物电信号的分类问题上,并对分类效果进行分析和验证.结果表明,所提出的方法在各项分类指标上均具备良好的性能.
  • 本文是从机器学习的角度分析朴素贝叶斯(Naive Bayes),主要分析的内容有贝叶斯定理、朴素贝叶斯分类器和似然估计法等。此外,针对贝叶斯定理,举了两个容易理解的例子,并且在朴素贝叶斯的实现方面,也提供了...
  • 朴素贝叶斯算法用于分类任务,基于贝叶斯理论。对于类别c属性x,贝叶斯公式如下: 其中P(c|x)是后验概率,P©是先验概率。所谓贝叶斯分析,就是利用先验概率去估计后验概率的过程。 对于所有类别来说P(x)相同,...
  •   文本分类(Document Classification / Document Categorization) ▶ 分类方法1——基于规则(Hand-coded) 精度高 开销 ▶ 分类方法2——机器学习(Machine learning) ...分类器(classifie
  • 算法利用朴素贝叶斯估计出EM算法初值,然后将EM贝叶斯网络结合进行迭代确定最终更新,同时得到填充后的完整数据集。实验结果表明,与经典填充算法相比,新算法具有更高的分类准确率,且节省了大量开销。
  • 贝叶斯和EM算法简介

    2020-07-27 23:59:37
    文章目录一、贝叶斯决策论1.1 ...2.6 总结三、半朴素贝叶斯分类器3.1 概述3.2 核心思想3.3 基本构造四、贝叶斯网4.1 概述4.2 实例4.3 分析4.4 特殊贝叶斯五、EM算法5.1 EM简介5.2 极似然估计5.3 jensen不等式5.3.1
  • 利用朴素贝叶斯分类文法的分类器分析已经手动分类的文本,根据文本内容计算分类条件概率,再利用训练好的分类器分析未分类的文本,根据分类器算出的所属领域概率最大的进行分类(毕业设计,课程设计,请联系,Q Q...
  • 贝叶斯分类因果学习 贝叶斯决策论 贝叶斯决策论(Bayesian decision theory)是在概率框架下实施 ...朴素贝叶斯分类器 贝叶斯网络 贝叶斯网 (Bayesian network)亦称“信念网”(brief network),它借 助有向无...
  • 介于两者之间的则是一系列半朴素贝叶斯分类器,它们基于各种假设约束来对属性间的部分依赖性进行建模。 贝叶斯分类器与一般意义上的“贝叶斯学习”有显著区别,前者是根据最大后验概率进行单点估计,后者则是进行...
  • 该技术框架以支持向量机为主分类器,融合了朴素贝叶斯分类器模型其他统计特征。实验数据表明,该技术框架在离线训练时长、对未知DGA恶意域名家族的检测能力方面表现优秀,可以较好地满足运营商网环境下对恶意...
  • 八种机器学习算法(决策树分类器,随机森林分类器,K最近邻,K均值算法,支持向量机,梯度提升,朴素贝叶斯和逻辑回归)和两个深度学习神经网络模型(单层感知器和多层)在联合国Covid数据集(kaggle)上对...
  • 试建立决策树、SVM神经网络3种分类器模型,比较各种分类器在此数据集上的效果。 在这里插入代码片 2 ( 50分 ) 基于Keras建立深度神经网络模型,在bankpep数据集上训练神经网络分类模型,将训练模型的耗时以及模型...
  • 18大数据挖掘的经典算法以及代码实现,涉及到了决策分类,聚类,链接挖掘,关联挖掘,模式挖掘等等方面,后面都是相应算法的博文链接,希望能够帮助大家学。 目前追加了其他的一些经典的DM算法,在others的包中涉及...
  • 文本分析 项目3:基于自然语言处理的... 对nltk自带的朴素贝叶斯分类器模型进行训练; \3. 最后模拟业务场景检测训练效果 项目3:2018.08 – 2018.12 智能考试分析系统 **项目描述:**由于公务员、事业单位、国企等面
  • 我们利用诸如Logistic回归,朴素贝叶斯分类器,神经网络随机森林分类器之类的分类算法来识别音乐曲目的流派。 我们还应用了K-means聚类算法来创建歌曲簇,并推荐用户最可能喜欢的歌曲。 储存库内容: 音乐分析...
  • 特征选择分类是脑功能磁...分类器选择高斯朴素贝叶斯(GNB)支持向量机(SVM),评估该特征选择方法。实验结果表明,该方法有效提高了分类速度,分类准确度也得到很提高。对分类方法进行比较,SVM总体上优于GNB。
  • 5.3.1朴素贝叶斯分类器 110 5.3.2BBN 112 5.4贝叶斯算法源程序分析 114 5.5贝叶斯算法特点及应用 119 5.5.1朴素贝叶斯分类算法 119 5.5.2贝叶斯信念网 120 思考题 121 第6章人工神经网络算法 122 6.1基本概念 122 ...
  • 5.3.3 朴素贝叶斯分类器 141 5.3.4 贝叶斯误差率 145 5.3.5 贝叶斯信念网络 147 5.4 人工神经网络 150 5.4.1 感知器 151 5.4.2 多层人工神经网络 153 5.4.3 人工神经网络的特点 155 5.5 支持向量机 156 ...

空空如也

空空如也

1 2 3
收藏数 48
精华内容 19
关键字:

朴素贝叶斯分类器和大数据分析