前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >python朴素贝叶斯实现-2

python朴素贝叶斯实现-2

作者头像
bear_fish
发布2018-09-14 10:01:18
9620
发布2018-09-14 10:01:18
举报

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://cloud.tencent.com/developer/article/1338373

本文主要内容:

1. 朴素贝叶斯为何需要特征条件独立
2. 朴素贝叶斯三种模型:
  • 特征是离散的时候,使用多项式模型
  • 特征是连续变量的时候,应该采用高斯模型
  • 特征的取值只能是1和0伯努利模型)
3. 多项式模型的python实现

朴素贝叶斯 (naive Bayes) 法是基于贝叶斯定理特征条件独立假设的分类方法。对于给定的训练数据集,首先基于特征条件独立假设学习输入/输出的联合概率分布;然后基于此模型,对给定的输入x,利用贝叶斯定理求出后验概率最大的输出Y。 贝叶斯分类是一类分类算法的总称,这类算法均以贝叶斯定理为基础,故统称为贝叶斯分类。而朴素朴素贝叶斯分类是贝叶斯分类中最简单,也是常见的一种分类方法。

理解朴素贝叶斯 (naive Bayes)主要分为两个部分:

1. 贝叶斯定理
2. 特征条件独立

贝叶斯定理上篇blog已经做了回顾,本文首先,说明特征条件独立的意义


1. 朴素贝叶斯为何需要特征条件独立

朴素贝叶斯法对条件概率分布作了条件独立性的假设。由于这是一个较强的假设,朴素贝叶斯法也由此得名。具体地,条件独立性假设是:

光看定义,还是不能很好的理解为何需要条件独立,现在给出知乎上面别人的解释:

假设根据一个男生四个特征(帅, 性格好,身高,上进)来判断女生是否嫁还是不嫁。首先给出下表(以及省略很多数据)

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

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

没有假设特征之间相互独立,那么我们统计的时候,就需要在整个特征空间中去找,比如统计p(不帅、性格不好、身高矮、不上进|嫁),我们就需要在嫁的条件下,去找四种特征全满足分别是不帅,性格不好,身高矮,不上进的人的个数,这样的话,由于数据的稀疏性,很容易统计到0的情况 我们这个例子有4个特征,其中帅包括{帅,不帅},性格包括{不好,好,爆好},身高包括{高,矮,中},上进包括{不上进,上进},那么四个特征的联合概率分布总共是4维空间,总个数为2*3*3*2=36个

假设特征之间相互独立,根据朴素贝叶斯公式:

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

2. 朴素贝叶斯三种模型:

特征是离散的时候,使用多项式模型

下面给出实际示例:

特征是连续变量的时候,应该采用高斯模型
特征的取值只能是1和0伯努利模型)

3. 多项式模型的python实现

数据来自于李航书上的示例, S, M, L改为了 4, 5, 6

代码语言:javascript
复制
def get_multi_data():
    x = np.array([
        [1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3],
        [4, 5, 5, 4, 4, 4, 5, 5, 6, 6, 6, 5, 5, 6, 6]
    ])

    x = x.T

    y = np.array([-1, -1, 1, 1, -1, -1, -1, 1, 1, 1, 1, 1, 1, 1, -1])
    return x, y

代码实现

代码语言:javascript
复制
class MultinomialNB(object):
    def __init__(self, alpha=1.0):
        self.alpha = alpha

        self._dic_class_prior = {}
        self._cd_prob = {}

    def fit(self, x, y):
        # calculate class prior probabilities: P(y=ck)
        self._cal_y_prob(y)

        # calculate Conditional Probability: P( xj | y=ck )
        self._cal_x_prob(x, y)

    def _cal_y_prob(self, y):
        """
        calculate class prior probability
        like: {class_1: prob_1, class_2:prob_2, ...}
        for example two class 1, 2 with probability 0.4 and 0.6
        {1: 0.4, 2: 0.6}
        """
        sample_num = len(y) * 1.0
        if sample_num < 1:
            raise ValueError

        unique_class, class_count = np.unique(y, return_counts=True)

        # calculate class prior probability
        for c, num in zip(unique_class, class_count):
            self._dic_class_prior[c] = num / sample_num

    def _cal_x_prob(self, x, y):
        """
        calculate Conditional Probability: P( xj | y=ck )
        like { c0:{ x0:{ value0:0.2, value1:0.8 }, x1:{} }, c1:{...} }

        for example the below ,as to class 1 feature 0 has 3 values "1, 2 , 3"
        the corresponding probability 0.22, 0.33, 0.44 
        p( x1 = 1 | y = 1 ) = 0.22
        p( x1 = 2 | y = 1 ) = 0.33
        p( x1 = 3 | y = 1 ) = 0.44

        { 1: {0: {1: 0.22, 2: 0.33, 3: 0.44}, 1: {4: 0.11, 5: 0.44, 6: 0.44}},
         -1: {0: {1: 0.50, 2: 0.33, 3: 0.16}, 1: {4: 0.50, 5: 0.33, 6: 0.16}}
        }
        """

        unique_class = np.unique(y)

        for c in unique_class:
            self._cd_prob[c] = {}

            c_idxs = np.where(y==c)[0]

            for i, col_feature in enumerate(x.T):
                dic_f_prob = {}
                self._cd_prob[c][i] = dic_f_prob

                for idx in c_idxs:
                    if col_feature[idx] in dic_f_prob:
                        dic_f_prob[col_feature[idx]] += 1
                    else:
                        dic_f_prob[col_feature[idx]] = 1

                for k in dic_f_prob:
                    dic_f_prob[k] = dic_f_prob[k] * 1.0 / len(c_idxs)

    def _pred_once(self, x):
        dic_ret = {}

        for y in self._dic_class_prior:
            y_prob = self._dic_class_prior[y]
            for i, v in enumerate(x):
                y_prob = y_prob * self._cd_prob[y][i][v]

            dic_ret[y] = y_prob

        return dic_ret

    def predict(self, x):
        if x.ndim == 1:
            return self._pred_once(x)
        else:
            labels = []
            for i in xrange(x.shape[0]):
                labels.append(self._pred_once(x[i]))

        return labels

    def get_class_prior(self):
        return self._dic_class_prior

    def get_cd_prob(self):
        return self._cd_prob

运行的结果:

代码语言:javascript
复制
if __name__ == '__main__':

    x, y = get_multi_data()
    print x.ndim, y.ndim
    # 2 1

    mnb = MultinomialNB()
    mnb.fit(x, y)

    print "class prior probability: %s" % mnb.get_class_prior()
    # {1: 0.599, -1: 0.40}

    print "feature condition probability: %s" % mnb.get_cd_prob()
    # { 1: {0: {1: 0.22, 2: 0.33, 3: 0.44}, 1: {4: 0.11, 5: 0.44, 6: 0.44}},
    #  -1: {0: {1: 0.50, 2: 0.33, 3: 0.16}, 1: {4: 0.50, 5: 0.33, 6: 0.16}}
    # }

    item = np.array([2, 4])
    print mnb.predict(item)
    # {1: 0.02222, -1: 0.06666}

参考:

  1. 李航《统计学习方法》
  2. 朴素贝叶斯分类器和一般的贝叶斯分类器有什么区别?知乎
  3. http://blog.csdn.net/u012162613/article/details/48323777
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2017年12月04日,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1. 朴素贝叶斯为何需要特征条件独立
  • 2. 朴素贝叶斯三种模型:
  • 3. 多项式模型的python实现
  • 1. 贝叶斯定理
  • 2. 特征条件独立
  • 1. 朴素贝叶斯为何需要特征条件独立
    • 假设特征之间相互独立,根据朴素贝叶斯公式:
    • 2. 朴素贝叶斯三种模型:
      • 特征是离散的时候,使用多项式模型
        • 特征是连续变量的时候,应该采用高斯模型
          • 特征的取值只能是1和0伯努利模型)
          • 3. 多项式模型的python实现
          • 参考:
          领券
          问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档