朴素贝叶斯(Naive Bayes)

 

目录

1 相关统计学概念

1.1 贝叶斯定理

1.2 条件独立

1.2.1 证明

1.2.2 示例

1.2.3 应用

1.3 先验概率与后验概率

1.4 先验概率(Prior probability)

1.5 条件概率(Conditional probability)

1.6 全概率公式

1.7 后验概率(Posterior probability)

2 朴素贝叶斯法的学习与分类

2.1 基本方法

2.2 后验概率最大化的含义

3 朴素贝叶斯的参数估计

3.1 极大似然估计

3.2 学习与分类算法

3.3 贝叶斯估计

3.4 当属性为连续型时

4 朴素贝叶斯算法分析

5 python实现


本文基于以下的例子:

        在夏季,某公园男性穿凉鞋的概率为 1/2 ,女性穿凉鞋的概率为 2/3 ,并且该公园中男女比例通常为 2:1 ,问题:若你在公园中随机遇到一个穿凉鞋的人,请问他的性别为男性或女性的概率分别为多少?

1 相关统计学概念

1.1 贝叶斯定理

        贝叶斯定理就是概率论中的条件概率,即P(B|A)=P(AB)/P(A) 变形可得

           

        这就是著名的“贝叶斯定理”。

1.2 条件独立

        如果P(X,Y|Z)=P(X|Z)P(Y|Z),或等价地 P(X|Y,Z)=P(X|Z),则称事件X,Y对于给定事件Z是条件独立的,也就是说,当Z发生时,X发生与否与Y发生与否是无关的。

      给定第三个事件 X, Y, Z,如果  ,则称X和Y是条件独立事件,符号表示为  。

      若X,Y关于事件Z条件独立,则有以下一些理解:

(1)事件 Z 的发生,使本来可能不独立的事件A和事件B变得独立起来;

(2)事件Z 的出现或发生,解开了X 和 Y 的依赖关系。

若 X,Y关于事件Z条件独立,则P(X|Y,Z)=P(X|Z)

1.2.1 证明

若 X,Y关于事件Z条件独立,则P(X|Y,Z)=P(X|Z)

    

      

      

      

      

      

1.2.2 示例

给定三个事件X,Y,Z:

  • X:明天下雨;
  • Y:今天的地面是湿的;
  • Z:今天是否下雨;

        Z事件的成立,对X和Y均有影响,然而,在Z事件成立的前提下,今天的地面情况对明天是否下雨没有影响。即,在已知Z的前提下,X和Y是相互独立的,即X和Y是条件独立的。

1.2.3 应用

        图模型可视化地表示变量间地相互影响,并且它有一个优点:利用条件独立性可以将大量变量上的推断分解成一组涉及少量变量的局部计算。

在图模型中,条件独立有以下三种典型情况: 

(1)头到尾连接

        三个事件可以顺序连接,如  。若给定Y,则X与Z是独立的:知道Y就知道Z的一切;知道X的状态并不能为Z增加附加知识,记作  。一般说,Y阻塞(block) 了从X到Z的路径,换句话说,Y分开了X和Z,意指如果删掉Y,则就不存在X和Z之间的路径。在这种情况下,联合概率写作:

        

典型地,X是Y的原因,Y是Z的原因。 

(2)尾到尾连接

        X可能是两个节点Y和Z的父节点,联合密度可以写作:

            

        通常,Y和Z是通过X依赖的,给定X,则它们变成独立的

            

        当X的值已知时,它阻塞了Y和Z之间的路径,换言之,X分开了Y和Z。 

(3)头到头连接

       在头到头连接中,有两个父节点X和Y连接到单个节点Z,则联合密度记作:

           

       X和Y是独立的:

              

       当知道Z时,X和Y变成依赖的。这种情况与阻塞或分开的概念不同。当观察不到Z时,X和Y之间的路径被阻塞;当Z(或者它的任意后代)被观测到时,X和Y便不再是阻塞的、独立的。

1.3 先验概率与后验概率

https://www.cnblogs.com/yemanxiaozu/p/7680761.html

https://www.jianshu.com/p/f9d56aeab75e

https://www.cnblogs.com/eniac1946/p/8532753.html

       事情还没有发生,要求这件事情发生的可能性的大小,是先验概率。事情已经发生,要求这件事情发生的原因是由某个因素引起的可能性的大小,是后验概率先验概率与后验概率有不可分割的联系,后验概率的计算要以先验概率为基础。

       先验概率的计算比较简单,没有使用贝叶斯公式;而后验概率的计算,要使用贝叶斯公式,而且在利用样本资料计算逻辑概率时,还要使用理论概率分布,需要更多的数理统计知识。

1.4 先验概率(Prior probability)

       先验概率(prior probability)是指根据以往经验和分析得到的概率,如全概率公式(后面会讲)。
  我们使用以上例子来解释一下什么是先验概率。根据以上例子我们设定:假设某公园中一个人是男性为事件 Y=ymen,是女性则是 Y=ywomen ;一个人穿凉鞋为事件 X=x1 ,未穿凉鞋为事件 X=x0。而一个人的性别与是否穿凉鞋这两个事件之间是相互独立的。
  于是我们可以看到该例子中存在四个先验概率:

  • P(X=x1)
  • P(X=x0)
  • P(Y=ymen)
  • P(Y=ywomen)

  其中 P(Y=ymen)P(Y=ywomen)可以根据例子中“该公园中男女比例通常为 2:1 ” 这一以往经验求得:P(Y=ymen)=2/3, 以及 P(Y=ywomen)=1/3 。而先验概率 P(X=x1)P(X=x0) 并不能直接得出,需要根据全概率公式来求解。在学习全概率公式之前,我们先了解一下条件概率

1.5 条件概率(Conditional probability)

  条件概率是指在事件 Y=y 已经发生的条件下,事件 X=x 发生的概率。条件概率可表示为: P(X=x|Y=y) 。而条件概率计算公式为:

        P(X=x|Y=y) = P(X=x,Y=y) P(Y=y)

  其中 P(X=x,Y=y)联合概率,也就是两个事件共同发生的概率。而  P(Y=y) 以及 P(X=x) 先验概率

  我们用例子来说明一下就是: “某公园男性穿凉鞋的概率为 1/2 ”,也就是说“是男性的前提下,穿凉鞋的概率是 1/2 ”,此概率为条件概率,即 P(X=x1|Y=ymen) = 1/2  。同理 “女性穿凉鞋的概率为 2/3” 为条件概率 P(X=x1|Y=ywomen) = 2/3

1.6 全概率公式

  全概率公式是指:如果事件 Y=y1,Y=y2,...,Y=yn 可构成一个完备事件组,即它们两两互不相容,其和为全集。则对于事件 X=x 有:

  

  因此对于上面的例子,我们可以根据全概率公式求得:

    

    

  也就是说不考虑性别的情况下,公园中穿脱鞋的概率为 5/9 ,不穿拖鞋的概率为 4/9

1.7 后验概率(Posterior probability)

  后验概率是指,某事件 X=x 已经发生,那么该事件是因为事件 Y=y 的而发生的概率。也就是上例中所需要求解的“在知道一个人穿拖鞋的前提下,这个人是男性的概率或者是女性的概率是多少”。后验概率形式化便是:

       P(Y=ymen|X=x1)

  后验概率的计算要以先验概率为基础。后验概率可以根据通过贝叶斯公式,用先验概率似然函数计算出来。

  贝叶斯公式如下:

     

  其中  为所求后验概率 条件概率 为先验概率, 全概率公式

        而朴素贝叶斯算法正是利用以上信息求解后验概率,并依据后验概率的值来进行分类

        使用上面的例子来进行理解,后验概率为:

        

        

        也就是说,在知道一个人穿拖鞋的前提下,这个人是男性的概率是 3/5 ,是女性的概率是 2/5 。如果问题是“判断该人是男性还是女性”,此问题就是一个分类问题。由于依据贝叶斯公式计算的后验概率是男性的概率大于是女性的概率,即由于  ,那么我们就可以将其分类为男性(实际在使用朴素贝叶斯进行分类时,不需要求解分母 P(X=x1))。
  到此,我们已经使用例子来讲解了使用朴素贝叶斯进行分类的基本步骤以及简单的原理了。接下来我们将对朴素贝叶斯的原理进行详细地探讨。

2 朴素贝叶斯法的学习与分类

2.1 基本方法

       朴素贝叶斯法(Naive Bayes)是基于贝叶斯定理与特征条件独立假设的分类方法。对于给定的训练数据集,首先基于特征条件独立假设学习输入/输出的联合概率分布;然后基于此模型,对给定的输入 x ,利用贝叶斯定理求出后验概率最大的输出 朴素贝叶斯是基于概率论的分类算法

(1)对于样本集

其中 m 表示有 m 个样本 n 表示有 n 个特征。  表示样本类别,取值为  。

(2)先验概率

(3)条件概率:

朴素贝叶斯法对条件概率分布作了条件独立性假设,因此:

        

(4)后验概率为:

(5)条件概率公式带入得:

上式为朴素贝叶斯分类的基本公式。

(6)于是,朴素贝叶斯分类器可表示为:

           

(7)由于分母对所有的 Ck 都是相同的,所以:

         

2.2 后验概率最大化的含义

3 朴素贝叶斯的参数估计

3.1 极大似然估计

似然与极大似然估计:https://blog.csdn.net/weixin_39910711/article/details/89647799

3.2 学习与分类算法

(摘自李航《统计学习方法》)

3.3 贝叶斯估计

3.4 当属性为连续型时

4 朴素贝叶斯算法分析

优点
  (1)朴素贝叶斯模型发源于古典数学理论,有稳定的分类效率。
  (2)对小规模的数据表现很好,能个处理多分类任务,适合增量式训练,尤其是数据量超出内存时,我们可以一批批的去增量训练。
  (3)对缺失数据不太敏感,算法也比较简单,常用于文本分类。
缺点
    (1)理论上,朴素贝叶斯模型与其他分类方法相比具有最小的误差率。但是实际上并非总是如此,这是因为朴素贝叶斯模型给定输出类别的情况下,假设属性之间相互独立,这个假设在实际应用中往往是不成立的,在属性个数比较多或者属性之间相关性较大时,分类效果不好。而在属性相关性较小时,朴素贝叶斯性能最为良好。对于这一点,有半朴素贝叶斯之类的算法通过考虑部分关联性适度改进。
   (2)需要知道先验概率,且先验概率很多时候取决于假设,假设的模型可以有很多种,因此在某些时候会由于假设的先验模型的原因导致预测效果不佳。
   (3)由于我们是通过先验和数据来决定后验的概率从而决定分类,所以分类决策存在一定的错误率。
   (4)对输入数据的表达形式很敏感。

5 python实现

# -*- coding: utf-8 -*-

import numpy as np
from sklearn.model_selection import train_test_split
from collections import Counter


class NavieBayes:

    def fit(self, feature, datatarget):
        data_num = np.shape(feature)[0]  # 样本数量
        datatarget = list(datatarget)  # 将标签列表化
        feature_num = np.shape(feature[0])[0]  # 特征数量
        target_label = list(set(datatarget))  # 类别种类
        target_dic = {}  # 标签种类及其概率
        total_dic = {}
        feature_label_type = []
        for i in range(feature_num):
            feature_label = np.unique(feature[:, i])
            feature_label_type.append(feature_label)  # 各个特征的可能的取值
        # print(feature_label_type)
        for each_target in target_label:
            feature_dic = []  # 各个特征的条件概率
            target_count = datatarget.count(each_target)
            tarfet_prob = (target_count + 1) / (data_num + len(target_label))
            # 返回每个标签对应的个数和概率,例如{'否': [4, 0.36363636363636365], '是': [7,
            # 0.6363636363636364]}
            target_dic[each_target] = [target_count, tarfet_prob]
            target_index = [i for i, x in enumerate(
                datatarget) if x == each_target]  # 计算target取值为“是”或者“否”时的索引
            feature_data = feature[target_index]
            # print(each_target)
            # print(feature_data)
            for i in range(feature_num):
                feature_each_label = feature_data[:, i]
                feature_each_count = Counter(feature_each_label)
                feature_each_keys = np.array(list(feature_each_count.keys()))
                for key in feature_each_count.keys():
                    feature_each_count[key] = (
                        feature_each_count[key] + 1) / (target_count + len(feature_label_type[i]))
                # 存在于feature_label_type[i]中,但不存在于feature_each_keys中的特征取值
                feature_diff = np.setdiff1d(
                    feature_label_type[i], feature_each_keys)
                # 计算不存在于feature_each_keys中的特征所取值的对应概率
                if len(feature_diff) != 0:
                    for diff in feature_diff:
                        feature_each_count[diff] = 1 / (target_count + len(
                            feature_label_type[i]))
                feature_dic.append(feature_each_count)
            total_dic[each_target] = feature_dic
        return total_dic, target_dic, feature_label_type

    def predict(self, feature_test, total_dic, target_d, feature_type):
        max_prob = 0
        feature_test = list(feature_test)
        feature_num = len(feature_test)  # 特征数量
        target_result = ""
        for each_target in total_dic.keys():
            prob = target_d[each_target][1]  # y = target 所对应的概率
            for i in range(feature_num):
                # 将测试集中的数据依次匹配total_dic对应的概率
                if feature_test[i] in total_dic[each_target][i].keys():
                    prob = total_dic[each_target][i][feature_test[i]] * prob
                else:
                    print(
                        "{0} is not exist in total_dic".format(
                            feature_test[i]))
                    total_dic[each_target][i][feature_test[i]] = 1 / \
                        (target_d[each_target][0] + len(feature_type[i]))
                    prob = total_dic[each_target][i][feature_test[i]] * prob
            # print(each_target, prob)
            if prob > max_prob:
                max_prob = prob
                target_result = each_target
        # print('max_prob', max_prob, target_result)
        return target_result


def evalution(predict, test):
    tp = 0
    tn = 0
    fp = 0
    fn = 0
    for i in range(len(test)):
        if predict[i] == '是' and test[i] == '是':
            tp += 1
        elif predict[i] == '否' and test[i] == '否':
            tn += 1
        elif predict[i] == '是' and test[i] == '否':
            fp += 1
        elif predict[i] == '否' and test[i] == '是':
            fn += 1
    if tp + tn + fp + fn:
        accuracy = (tp + tn) / (tp + tn + fp + fn)
    else:
        accuracy = 0
    if tp + fn:
        recall = tp / (tp + fn)
    else:
        recall = 0
    if tp + fp:
        precision = tp / (tp + fp)
    else:
        precision = 0
    return accuracy, recall, precision


if __name__ == "__main__":
    # 读取文件中的数据
    with open('watermelon', 'r', encoding='utf-8') as f:
        data_all = []
        for line in f.readlines():
            each_line = line.strip().split(',')
            data_all.append(each_line)
    data_all = np.array(data_all)
    label = data_all[0, : -1]
    dataset = data_all[1:, :]
    data = dataset[:, :-1]
    target = dataset[:, -1]
    # print(label)
    # print(data)
    train_feature, test_feature, train_target, test_target = train_test_split(
        data, target, test_size=0.3)
    nb = NavieBayes()
    prob_dict, target_dic, feature_label_type = nb.fit(
        train_feature, train_target)
    predict_result = []
    print('prob_dict', prob_dict)
    print('total_dic', target_dic)
    for test_line in test_feature:
        class_label = nb.predict(
            test_line,
            prob_dict,
            target_dic,
            feature_label_type)
        predict_result.append(class_label)
    print("predict_result: ", predict_result)
    print("test_target:    ", list(test_target))
    accuracy, recall, precision = evalution(predict_result, test_target)
    print(
        "accuracy:{:.4f};recall:{:.4f};precision:{:.4f}".format(
            accuracy,
            recall,
            precision))

 

 

https://www.zhihu.com/question/43481146

https://blog.csdn.net/lanchunhui/article/details/53696550

https://blog.csdn.net/u010435005/article/details/80323936

https://blog.csdn.net/zhang20072844/article/details/51794278

https://www.cnblogs.com/lliuye/p/9178090.html

  • 1
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值