机器学习期末复习 贝叶斯分类器

先验概率与后验概率

先验概率:对于某一个概率事件,我们都会有基于自己已有的知识,对于这个概率事件会分别以什么概率出现各种结果会有一个预先的估计,而这个估计并未考虑到任何相关因素。

对于分类数据来说,先验概率就是取某一类的概率。

(基于自己已有的知识->已有的数据)

(预先的估计->统计概率)

假如你考试没及格,老师要求大家拿卷子回家给爸妈签字,假如你考试没及格过10次,你每次都用小本记下来后果:

  • 被胖揍一顿:7次
  • 被简单地数落一下:2次
  • 被温情地鼓励:1次

那么先验概率:

  • 被胖揍一顿:70%
  • 被简单地数落一下:20%
  • 被温情地鼓励:10%

后验概率:在先验概率的基础上加了一层“考虑”:结合我们已有的知识,将与待检验事件(即我们正在估计概率的随机事件)相关的因素也考虑进去后,我们对随机事件的概率的预估。

我的理解是,通过结果估计条件。就西瓜数据集来说,结果是好瓜还是坏瓜,条件是色泽,敲声等等的属性,所以后验概率就是,我们已经知道这个西瓜是好瓜了,在他是好瓜的前提下估计他的色泽时青绿的概率,即P(青绿|好瓜),用字符表示就是P(x | c)。

那么,落实到实际的问题当中,我们想获得的核心结果其实也就是P(c|x),即在x数据集上,是好瓜的概率P(c=好瓜|x)和是坏瓜P(c=坏瓜|x)的概率,通过贝叶斯公式:

即可通过P(x | c)求得P(c | x),但是,求P(x | c)并不容易,所以引出下面的朴素贝叶斯。

详细分析后验概率看这篇博文吧:

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

重点:朴素贝叶斯

朴素贝叶斯方法是基于贝叶斯定理的一组有监督学习算法

朴素->所有属性相互独立,就西瓜数据集来说,颜色与敲声没有任何关系。(实际情况下是有联系的,但是为了简化,假设他们没关系)

公式:

 公式中的P(x)可以忽略。

因为这个公式最后求出来的是一个数,比如西瓜数据集,我们最后求出的是P(c=好瓜 | X)=0.4

P(c=坏瓜 | X)=0.8,然后通过比较这两个数的大小来判断测试集是好瓜还是坏瓜。

P(x)在计算P(c=好瓜 | X)和P(c=坏瓜 | X)都有,而且相同。所以去掉P(x)并不影响

P(c=好瓜 | X)和P(c=坏瓜 | X)之间的大小关系。

分类准则:

思路:

具体分析还请看:朴素贝叶斯分类器(Naive Bayesian Classifier)

假设我们有了一个数据集D,那么p( c )的获得其实也较为简单:计算D中c的各个情况出现的频率即可。(这里用到了大数定律:当训练集包含充足的独立同分布样本时,P( c )可通过各类样本出现的频率来进行估计。)

朴素贝叶斯+拉普拉斯修正实现代码:

"""
    利用打网球数据集PlayTenis构建决策树,该数据集的特性如下:
    属性包括天气(outlook)、温度(temperature)、湿度(humidity)、是否有风(windy),样本个数为14。
    标签为今天是否去打网球(play)。
    具体数据如下:
    NO. Outlook temperature humidity   windy  play
    1   sunny      hot       high      FALSE  no
    2   sunny      hot       high      TRUE   no
    3   overcast   hot       high      FALSE  yes
    4   rainy      mild      high      FALSE  yes
    5   rainy      cool      normal    FALSE  yes
    6   rainy      cool      normal    TRUE   no
    7   overcast   cool      normal    TRUE   yes
    8   sunny      mild      high      FALSE  no
    9   sunny      cool      normal    FALSE  yes
    10  rainy      mild      normal    FALSE  yes
"""

# 读入数据函数  返回正例,反例,总例,数据
def readFile():
    f = open('D:\\PythonProject_Class\\test_Data\\PlayTennis.txt', 'r')
    lk = 10
    preData = [[] for i in range(lk)]
    dict_PlusFeatures = {}  # 保存属性的名称,并为求信息增益做准备,也就是把初值赋值为0
    dict_NegativeFeatures = {}  # 上一个保存的是正例,这个保存的的是反例
    sum_Features = {}

    for i in range(0, 4):  # 把前几行的文字描述跳过
        s = f.readline()

    s = f.readline()  # 读入属性
    #    NO. Outlook temperature humidity   windy  play
    # strip函数是去除这行的开头和结尾的换行符和空格的
    s = s.strip('\n')
    s = s.strip(' ')
    x = s.split(' ')
    # 初始化字典
    for i in range(1, len(x)):  # 从1开始是要跳过NO.
        if x[i] == 'play':
            dict_PlusFeatures[x[i]] = 0
            dict_NegativeFeatures[x[i]] = 0
            sum_Features[x[i]] = 0
        elif x[i] != '':
            dict_PlusFeatures[x[i]] = {}
            dict_NegativeFeatures[x[i]] = {}
            sum_Features[x[i]] = {}

    ls = [i for i in dict_PlusFeatures.keys()]  # 提取字典中的特征名称
    ls.pop(len(ls) - 1)  # 去掉play
    # s=set()不能kidls=[s for i in range(len(ls))],这样列表中的一个集合改变,其他的也会改变
    # kidls = [set() for i in range(len(ls))]  # 保存每个特征的属性值,使用没有重复元素的集合set

    flag = 0  # 用于标记是正例还是反例
    index = 0  # 用于指向 保存所有读入数据的predata 的下标
    for i in range(lk):
        cnt = 0
        s = f.readline()  # 读入属性
        s = s.strip('\n')
        s = s.strip(' ')
        x = s.split(' ')
        if x[len(x) - 1] == 'no':  # 首先处理是正例还是反例,同时统计正反例个数
            flag = -1
            dict_NegativeFeatures['play'] += 1
        elif x[len(x) - 1] == 'yes':
            flag = 1
            dict_PlusFeatures['play'] += 1
        sum_Features['play'] += 1
        for j in range(2, len(x) - 1):  # 跳过编号以及最后的正反例
            if x[j] != '':
                if flag == 1:
                    if x[j] not in dict_PlusFeatures[ls[cnt]].keys():
                        dict_PlusFeatures[ls[cnt]][x[j]] = 1
                    else:
                        dict_PlusFeatures[ls[cnt]][x[j]] += 1
                elif flag == -1:
                    if x[j] not in dict_NegativeFeatures[ls[cnt]].keys():
                        dict_NegativeFeatures[ls[cnt]][x[j]] = 1
                    else:
                        dict_NegativeFeatures[ls[cnt]][x[j]] += 1

                if x[j] not in sum_Features[ls[cnt]].keys():
                    sum_Features[ls[cnt]][x[j]] = 1
                else:
                    sum_Features[ls[cnt]][x[j]] += 1

                # kidls[cnt].add(x[j])
                preData[index].append(x[j])
                cnt += 1
        preData[index].append(x[len(x) - 1])
        index += 1

    for i in dict_PlusFeatures.keys():
        if i != 'play':
            for j in dict_PlusFeatures[i].keys():
                if j not in dict_NegativeFeatures[i].keys():
                    dict_NegativeFeatures[i][j] = 0

    for i in dict_NegativeFeatures.keys():
        if i != 'play':
            for j in dict_NegativeFeatures[i].keys():
                if j not in dict_PlusFeatures[i].keys():
                    dict_PlusFeatures[i][j] = 0

    preData.insert(0, ls)  # 在split中发现需要表头
    preData[0].append('play')
    return dict_PlusFeatures, dict_NegativeFeatures, sum_Features, preData


def method(dict_PlusFeatures, dict_NegativeFeatures, sum_Features, preData):
    dict_PlusFeatures['play'] = dict_PlusFeatures['play'] / sum_Features['play']
    dict_NegativeFeatures['play'] = dict_NegativeFeatures['play'] / sum_Features['play']
    for i in dict_PlusFeatures:
        if i != 'play':
            for j in dict_PlusFeatures[i]:
                dict_PlusFeatures[i][j] = (dict_PlusFeatures[i][j] + 1) / (
                            dict_PlusFeatures['play'] + len(dict_PlusFeatures[i]))
    for i in dict_NegativeFeatures:
        if i != 'play':
            for j in dict_NegativeFeatures[i]:
                dict_NegativeFeatures[i][j] = (dict_NegativeFeatures[i][j] + 1) / (
                            dict_NegativeFeatures['play'] + len(dict_NegativeFeatures[i]))

    for i in range(1, len(preData)):
        ls = [dict_PlusFeatures['play'], dict_NegativeFeatures['play']]
        for j in range(len(preData[0]) - 1):
            ls[0] *= dict_PlusFeatures[preData[0][j]][preData[i][j]]
            ls[1] *= dict_NegativeFeatures[preData[0][j]][preData[i][j]]
        key = ls.index(max(ls))
        if key == 0 and preData[i][-1] == 'yes':
            print("数据{}预测正确".format(i))
        elif key == 1 and preData[i][-1] == 'no':
            print("数据{}预测正确".format(i))
        else:
            print("数据{}预测错误".format(i))


if __name__ == '__main__':
    dict_PlusFeatures, dict_NegativeFeatures, sum_Features, preData = readFile()
    method(dict_PlusFeatures, dict_NegativeFeatures, sum_Features, preData)


1.什么是朴素贝叶斯分类器?

1.不同于其它分类器,朴素贝叶斯是一种基于概率理论的分类算法;

2.特征之间的条件独立性假设,显然这种假设显得“粗鲁”而不符合实际,这也是名称中“朴素”的由来。然而事实证明,朴素贝叶斯在有些领域很有用,比如垃圾邮件过滤;

3.总体上来说,朴素贝叶斯原理和实现都比较简单,学习和预测的效率都很高,是一种经典而常用的分类算法。

2.朴素贝叶斯的分类准则?

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值