Python手撸机器学习系列(四):朴素贝叶斯(华强买瓜版)

一、原理

1.1 买瓜

在这里插入图片描述

大家好,我叫刘华强。我现在手里有一堆西瓜,我希望通过观察我这一堆西瓜中好瓜的特征来总结出判断好瓜的标准,这样以后再看到别的西瓜我也能判断出这是好瓜还是坏瓜。这样瓜棚老板给我挑的瓜我一下就知道保不保熟(好瓜还是坏瓜)。
请添加图片描述

现在,我手里共有17个西瓜,它们大概长这样:

请添加图片描述

这堆西瓜里,我主要通过色泽、根蒂、敲声、纹理、脐部、触感六个特征来判断它们是好瓜还是坏瓜,其中好瓜用1表示坏瓜用0表示。也就是说,我们用六个特征作为前提计算它是好瓜或是坏瓜的概率,用公式表示为:
P ( 好 瓜 或 坏 瓜 ∣ 色 泽 、 根 蒂 、 敲 声 、 纹 理 、 脐 部 、 触 感 ) P(好瓜或坏瓜|色泽、根蒂、敲声、纹理、脐部、触感) P()
既然我们的标题叫做朴素贝叶斯,那么总得跟贝叶斯扯上点关系吧,先看贝叶斯公式:
P ( B ∣ A ) = P ( A ∣ B ) P ( B ) P ( A ) P(B|A) = \frac{P(A|B)P(B)}{P(A)} P(BA)=P(A)P(AB)P(B)
换到我们这堆西瓜就是:
P ( 类 别 ∣ 特 征 ) = P ( 特 征 ∣ 类 别 ) P ( 类 别 ) P ( 特 征 ) P(类别|特征)=\frac{P(特征|类别)P(类别)}{P(特征)} P()=P()P()P()
理解起来就是:

P ( 类 别 ∣ 特 征 ) P(类别|特征) P() :根据六大特征判断这个西瓜的好坏,也是我们的目标

P ( 特 征 ∣ 类 别 ) P(特征|类别) P():在一个西瓜是好瓜或者坏瓜的前提下,特征的概率分布情况

P ( 类 别 ) P(类别) P():我们这17个西瓜中好瓜和坏瓜分别的比重

P ( 特 征 ) P(特征) P():六个特征中每个特征自己的分布情况

1.2 算瓜

了解基本的想法后,我提着这17个西瓜去找瓜棚老板要瓜了,他给我挑了一个不错的西瓜,这个西瓜色泽青绿,根蒂蜷缩,敲声沉闷,纹理稍糊,脐部凹陷,触感硬滑。下面我将根据我那17个西瓜的情况来判断这个瓜是不是好瓜,同时决定老板该不该被捅。

请添加图片描述

按照上面的思想,我将计算
p ( 好 瓜 ∣ 青 绿 , 蜷 缩 , 沉 闷 , 稍 糊 , 凹 陷 , 硬 滑 ) p ( 坏 瓜 ∣ 青 绿 , 蜷 缩 , 沉 闷 , 稍 糊 , 凹 陷 , 硬 滑 ) p(好瓜|青绿,蜷缩,沉闷,稍糊,凹陷,硬滑)\\ p(坏瓜|青绿,蜷缩,沉闷,稍糊,凹陷,硬滑) p(绿)p(绿)
这两组概率来判断是不是好瓜

显然,我现在还没有办法根据这些个特征看看这瓜是不是好瓜,但是呢,通过贝叶斯,我能通过我那17个瓜的情况来推测这个新瓜的情况,即:
p ( 好 瓜 ∣ 青 绿 , 蜷 缩 , 沉 闷 , 稍 糊 , 凹 陷 , 硬 滑 ) = p ( 青 绿 , 蜷 缩 , 沉 闷 , 稍 糊 , 凹 陷 , 硬 滑 ∣ 好 瓜 ) P ( 好 瓜 ) p ( 青 绿 , 蜷 缩 , 沉 闷 , 稍 糊 , 凹 陷 , 硬 滑 ) p ( 坏 瓜 ∣ 青 绿 , 蜷 缩 , 沉 闷 , 稍 糊 , 凹 陷 , 硬 滑 ) = p ( 青 绿 , 蜷 缩 , 沉 闷 , 稍 糊 , 凹 陷 , 硬 滑 ∣ 坏 瓜 ) P ( 坏 瓜 ) p ( 青 绿 , 蜷 缩 , 沉 闷 , 稍 糊 , 凹 陷 , 硬 滑 ) p(好瓜|青绿,蜷缩,沉闷,稍糊,凹陷,硬滑) =\frac{p(青绿,蜷缩,沉闷,稍糊,凹陷,硬滑|好瓜)P(好瓜)}{p(青绿,蜷缩,沉闷,稍糊,凹陷,硬滑)}\\ p(坏瓜|青绿,蜷缩,沉闷,稍糊,凹陷,硬滑) =\frac{p(青绿,蜷缩,沉闷,稍糊,凹陷,硬滑|坏瓜)P(坏瓜)}{p(青绿,蜷缩,沉闷,稍糊,凹陷,硬滑)} p(绿)=p(绿)p(绿)P()p(绿)=p(绿)p(绿)P()
同时,我注意到,要区分好瓜和坏瓜,分母的计算好像都是一样的,我赶时间捅老板,所以能省就省了吧,于是,概率计算就变成了:
p ( 好 瓜 ∣ 青 绿 , 蜷 缩 , 沉 闷 , 稍 糊 , 凹 陷 , 硬 滑 ) = p ( 青 绿 , 蜷 缩 , 沉 闷 , 稍 糊 , 凹 陷 , 硬 滑 ∣ 好 瓜 ) P ( 好 瓜 ) p ( 坏 瓜 ∣ 青 绿 , 蜷 缩 , 沉 闷 , 稍 糊 , 凹 陷 , 硬 滑 ) = p ( 青 绿 , 蜷 缩 , 沉 闷 , 稍 糊 , 凹 陷 , 硬 滑 ∣ 坏 瓜 ) P ( 坏 瓜 ) p(好瓜|青绿,蜷缩,沉闷,稍糊,凹陷,硬滑) ={p(青绿,蜷缩,沉闷,稍糊,凹陷,硬滑|好瓜)P(好瓜)}\\ p(坏瓜|青绿,蜷缩,沉闷,稍糊,凹陷,硬滑) =p(青绿,蜷缩,沉闷,稍糊,凹陷,硬滑|坏瓜)P(坏瓜) p(绿)=p(绿)P()p(绿)=p(绿)P()
这可太好了,只需要计算这么两个公式,就知道该不该捅老板了

但是,同时满足青绿、蜷缩、沉闷、稍糊、凹陷、硬滑的瓜可不好找啊,我这区区17个西瓜极有可能没有一个符合这样的,那概率为就是0啊,按我刘华强的性格,我必不可能再去买一个这样的西瓜,那只能叫贝叶斯老实点把公式给改了,于是朴素贝叶斯就出现了:假设我们的特征之间是相互独立的,于是便有:
p ( 青 绿 , 蜷 缩 , 沉 闷 , 稍 糊 , 凹 陷 , 硬 滑 ∣ 好 瓜 ) = p ( 青 绿 ∣ 好 瓜 ) ∗ p ( 蜷 缩 ∣ 好 瓜 ) ∗ p ( 沉 闷 ∣ 好 瓜 ) ∗ p ( 稍 糊 ∣ 好 瓜 ) ∗ p ( 凹 陷 ∣ 好 瓜 ) ∗ p ( 硬 滑 ∣ 好 瓜 ) p ( 青 绿 , 蜷 缩 , 沉 闷 , 稍 糊 , 凹 陷 , 硬 滑 ∣ 坏 瓜 ) = p ( 青 绿 ∣ 坏 瓜 ) ∗ p ( 蜷 缩 ∣ 坏 瓜 ) ∗ p ( 沉 闷 ∣ 坏 瓜 ) ∗ p ( 稍 糊 ∣ 坏 瓜 ) ∗ p ( 凹 陷 ∣ 坏 瓜 ) ∗ p ( 硬 滑 ∣ 坏 瓜 ) p(青绿,蜷缩,沉闷,稍糊,凹陷,硬滑|好瓜) = p(青绿|好瓜)*p(蜷缩|好瓜)*p(沉闷|好瓜)*p(稍糊|好瓜)*p(凹陷|好瓜)*p(硬滑|好瓜)\\ p(青绿,蜷缩,沉闷,稍糊,凹陷,硬滑|坏瓜) = p(青绿|坏瓜)*p(蜷缩|坏瓜)*p(沉闷|坏瓜)*p(稍糊|坏瓜)*p(凹陷|坏瓜)*p(硬滑|坏瓜) p(绿)=p(绿)p()p()p()p()p()p(绿)=p(绿)p()p()p()p()p()
ps:朴素贝叶斯的朴素之处:即假设了特征之间的独立性。要做这样的假设的原因在于:

  1. 如果没有这个假设,现实生活中上述的这个式子概率极有可能是不能做的,因为可能一个对象有许多特征,每一个特征也有许多种可能,上面西瓜的特征总共是3×3×3×3×3×2=486种可能,计算机计算还好,但人来算就太吃力了。
  2. 同时满足上述所有个特征的物体(也就是瓜)可能真的没有,概率很容易为0

好了,中场休息后我们继续买瓜,在朴素贝叶斯之后,我们的公式最后变为:
p ( 好 瓜 ∣ 青 绿 , 蜷 缩 , 沉 闷 , 稍 糊 , 凹 陷 , 硬 滑 ) = p ( 青 绿 ∣ 好 瓜 ) ∗ p ( 蜷 缩 ∣ 好 瓜 ) ∗ p ( 沉 闷 ∣ 好 瓜 ) ∗ p ( 稍 糊 ∣ 好 瓜 ) ∗ p ( 凹 陷 ∣ 好 瓜 ) ∗ p ( 硬 滑 ∣ 好 瓜 ) p ( 好 瓜 ) p ( 坏 瓜 ∣ 青 绿 , 蜷 缩 , 沉 闷 , 稍 糊 , 凹 陷 , 硬 滑 ) = p ( 青 绿 ∣ 坏 瓜 ) ∗ p ( 蜷 缩 ∣ 坏 瓜 ) ∗ p ( 沉 闷 ∣ 坏 瓜 ) ∗ p ( 稍 糊 ∣ 坏 瓜 ) ∗ p ( 凹 陷 ∣ 坏 瓜 ) ∗ p ( 硬 滑 ∣ 坏 瓜 ) p ( 坏 瓜 ) p(好瓜|青绿,蜷缩,沉闷,稍糊,凹陷,硬滑) ={ p(青绿|好瓜)*p(蜷缩|好瓜)*p(沉闷|好瓜)*p(稍糊|好瓜)*p(凹陷|好瓜)*p(硬滑|好瓜)p(好瓜)}\\ p(坏瓜|青绿,蜷缩,沉闷,稍糊,凹陷,硬滑) =p(青绿|坏瓜)*p(蜷缩|坏瓜)*p(沉闷|坏瓜)*p(稍糊|坏瓜)*p(凹陷|坏瓜)*p(硬滑|坏瓜)p(坏瓜) p(绿)=p(绿)p()p()p()p()p()p()p(绿)=p(绿)p()p()p()p()p()p()
按照我们之前的数据集,我们逐步计算:

  1. 计算 p ( 好 瓜 ) p(好瓜) p() p ( 坏 瓜 ) p(坏瓜) p()

    总共17个瓜,好瓜8个坏瓜9个,即:

    p ( 好 瓜 ) = 8 17 , p ( 坏 瓜 ) = 9 17 p(好瓜) = \frac{8}{17},p(坏瓜)=\frac{9}{17} p()=178p()=179

  2. 计算 p ( 特 征 好 瓜 ) p(特征好瓜) p() p ( 特 征 ∣ 坏 瓜 ) p(特征|坏瓜) p()

    好瓜共8个,里面色泽青绿的瓜3个,根蒂蜷缩的瓜5个,敲声沉闷的瓜2个,纹理稍糊的瓜1个,脐部凹陷的瓜5个,触感硬滑的瓜6个,所以:

    p ( 青 绿 ∣ 好 瓜 ) = 3 8 , p ( 蜷 缩 ∣ 好 瓜 ) = 5 8 , p ( 沉 闷 ∣ 好 瓜 ) = 2 8 , p ( 稍 糊 ∣ 好 瓜 ) = 1 8 , p ( 凹 陷 ∣ 好 瓜 ) = 5 8 , p ( 硬 滑 ∣ 好 瓜 ) = 6 8 p(青绿|好瓜) = \frac{3}{8},p(蜷缩|好瓜) = \frac{5}{8},p(沉闷|好瓜) = \frac{2}{8},p(稍糊|好瓜)=\frac{1}{8},p(凹陷|好瓜) = \frac{5}{8},p(硬滑|好瓜) = \frac{6}{8} p(绿)=83p()=85p()=82p()=81p()=85p()=86

    坏瓜共9个,里面色泽青绿的瓜3个,根蒂蜷缩的瓜3个,敲声沉闷的瓜3个,纹理稍糊的瓜4个,脐部凹陷的瓜2个,触感硬滑的瓜6个,所以

    p ( 青 绿 ∣ 坏 瓜 ) = 3 9 , p ( 蜷 缩 ∣ 坏 瓜 ) = 3 9 , p ( 沉 闷 ∣ 坏 瓜 ) = 3 9 , p ( 稍 糊 ∣ 坏 瓜 ) = 4 9 , p ( 凹 陷 ∣ 坏 瓜 ) = 2 9 , p ( 硬 滑 ∣ 坏 瓜 ) = 6 9 p(青绿|坏瓜)=\frac{3}{9},p(蜷缩|坏瓜)=\frac{3}{9},p(沉闷|坏瓜)=\frac{3}{9},p(稍糊|坏瓜)=\frac{4}{9},p(凹陷|坏瓜)=\frac{2}{9},p(硬滑|坏瓜)=\frac{6}{9} p(绿)=93p()=93p()=93p()=94p()=92p()=96

  3. 计算 p ( 好 瓜 ∣ 青 绿 , 蜷 缩 , 沉 闷 , 稍 糊 , 凹 陷 , 硬 滑 ) p(好瓜|青绿,蜷缩,沉闷,稍糊,凹陷,硬滑) p(绿) p ( 坏 瓜 ∣ 青 绿 , 蜷 缩 , 沉 闷 , 稍 糊 , 凹 陷 , 硬 滑 ) p(坏瓜|青绿,蜷缩,沉闷,稍糊,凹陷,硬滑) p(绿):
    p ( 好 瓜 ∣ 青 绿 , 蜷 缩 , 沉 闷 , 稍 糊 , 凹 陷 , 硬 滑 ) = p ( 青 绿 ∣ 好 瓜 ) ∗ p ( 蜷 缩 ∣ 好 瓜 ) ∗ p ( 沉 闷 ∣ 好 瓜 ) ∗ p ( 稍 糊 ∣ 好 瓜 ) ∗ p ( 凹 陷 ∣ 好 瓜 ) ∗ p ( 硬 滑 ∣ 好 瓜 ) p ( 好 瓜 ) = 3 8 ∗ 5 8 ∗ 2 8 ∗ 1 8 ∗ 5 8 ∗ 6 8 ∗ 8 17 = 0.001615 p(好瓜|青绿,蜷缩,沉闷,稍糊,凹陷,硬滑)={p(青绿|好瓜)*p(蜷缩|好瓜)*p(沉闷|好瓜)*p(稍糊|好瓜)*p(凹陷|好瓜)*p(硬滑|好瓜)p(好瓜)}\\=\frac{3}{8}*\frac{5}{8}*\frac{2}{8}*\frac{1}{8}*\frac{5}{8}*\frac{6}{8}*\frac{8}{17}\\= 0.001615\\ p(绿)=p(绿)p()p()p()p()p()p()=838582818586178=0.001615

p ( 坏 瓜 ∣ 青 绿 , 蜷 缩 , 沉 闷 , 稍 糊 , 凹 陷 , 硬 滑 ) = p ( 青 绿 ∣ 坏 瓜 ) ∗ p ( 蜷 缩 ∣ 坏 瓜 ) ∗ p ( 沉 闷 ∣ 坏 瓜 ) ∗ p ( 稍 糊 ∣ 坏 瓜 ) ∗ p ( 凹 陷 ∣ 坏 瓜 ) ∗ p ( 硬 滑 ∣ 坏 瓜 ) p ( 坏 瓜 ) = 3 9 ∗ 3 9 ∗ 3 9 ∗ 4 9 ∗ 2 9 ∗ 6 9 ∗ 9 17 = 0.001291 p(坏瓜|青绿,蜷缩,沉闷,稍糊,凹陷,硬滑) =p(青绿|坏瓜)*p(蜷缩|坏瓜)*p(沉闷|坏瓜)*p(稍糊|坏瓜)*p(凹陷|坏瓜)*p(硬滑|坏瓜)p(坏瓜)\\=\frac{3}{9}*\frac{3}{9}*\frac{3}{9}*\frac{4}{9}*\frac{2}{9}*\frac{6}{9}*\frac{9}{17}\\= 0.001291 p(绿)=p(绿)p()p()p()p()p()p()=939393949296179=0.001291

显然,0.001615 > 0.001291,即瓜棚老板给我的瓜是好瓜。

请添加图片描述

那没事了,理亏跑路

请添加图片描述

二、代码实现

有了上述分析,我们能很容易的得出朴素贝叶斯的计算过程:

  1. 计算数据集中每个类别的概率
  2. 计算数据集中以每个类别为前提的情况下每一个特征的每一种情况的概率
  3. 根据测试集中的特征情况用上述概率计算出每一类的概率情况
  4. 将测试集归类为概率最大的那一类

具体代码实现如下:
西瓜数据集(csv格式):百度网盘 提取码:dy4c

import numpy as np
import pandas as pd

# def feature_num(x): #每个特征有几种可能
#     print(x.value_counts())
#     return len(x.value_counts())

def Y_prob(Y): #好瓜和坏瓜的各自的比重
    y = Y.values
    true_prob = sum(y)/len(y)
    return {0:1-true_prob,1:true_prob}

def x_y_prob(feature,y): #求p(特征|类别),用字典的形式存储返回
    x_y = {}
    n = len(y)
    for f in feature.columns:
        # for i in range(feature_num(feature[f])): #x_f = i
        for i in feature[f].value_counts().keys():
            index = (y==1)
            index_True = y[y==True].index
            index_False = y[y==False].index

            sample_True = data.loc[index_True, f] == i
            prob_true = len(sample_True.loc[sample_True == True])/len(index_True)
            strings_True = str(f)+'='+str(i)+'|'+'y=1'

            sample_False = data.loc[index_False, f] == i
            prob_False = len(sample_False.loc[sample_False == True]) / len(index_False)
            strings_False = str(f) + '=' + str(i) + '|' + 'y=0'

            x_y[strings_True] = prob_true
            x_y[strings_False] = prob_False
    return x_y

if __name__ == '__main__':
    data = pd.read_csv('./data_word.csv')
    feature = data.columns.values[:-1]
    x_y = x_y_prob(data[feature],data['好瓜'])  #用字典存储p(特征|类别)
    y_prob = Y_prob(data['好瓜'])
    test_data = ['青绿','蜷缩','沉闷','稍糊','凹陷','硬滑']
    #将测试数据转化为字典可以搜索的格式
    test_true = [str(feature[i]) + '=' + str(test_data[i]) + '|' + 'y=1' for i in range(len(feature))]
    test_false = [str(feature[i]) + '=' + str(test_data[i]) + '|' + 'y=0' for i in range(len(feature))]
    p_true = y_prob[1]
    p_false = y_prob[0]
    for i in range(len(feature)): #计算每一类的概率
        p_true *= x_y[test_true[i]]
        p_false *= x_y[test_false[i]]
    print('特征为:{}的瓜,是好瓜的概率为:{:.8f},不是好瓜的概率为:{:.8f}'.format(test_data,p_true,p_false))
    print('朴素贝叶斯最后预测:'+'是好瓜' if p_true>p_false else '不是好瓜')

运行结果:
请添加图片描述

三、参考文献

周志华 《机器学习》
李航《统计学习方法》
知乎专栏:https://zhuanlan.zhihu.com/p/26262151

玩梗归玩梗,希望这个版本能帮助大家理解书上复杂的公式

评论 11
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

锌a

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值