朴素的我,决定朴素地徒手实现贝叶斯算法!
摒弃sklearn 这个体贴善解人意把一切都打包封装好的妈妈
再见了sklearn 妈妈
我要自己手动实现
哪怕前方困难重重
哪怕我此刻还在发牢骚
但我还是要说,撒哟娜拉sklearn妈
看了知乎阿婆主的分析,我想,我对朴素贝叶斯的理解应该已经有了质的飞跃!!!
首先,我混淆了很久的先验概率和后验概率之分!!!
先验概率,就是基于统计、经验等得到的概率,为后续计算所用。
 一个概率是先验还是后验,是不一定。
1. 朴素贝叶斯的朴素理解
朴素贝叶斯的分类本质,就像是光看我的身体特征,分析我是男的概率有多大,是女的概率有多大。
朴素贝叶斯其实是我们潜意识里常用的分类方法,很不科学,但大概率会是正确的。
例如走在大马路上,迎面走来一个人,平胸、有喉结、短头发、眉毛粗、肢体粗犷
根据这个人的特征,如果是阅人无数的我,应该会下意识认为这是个男生【朴素贝叶斯在作祟】
因为在我认识的那一堆人中,有这样特征的虽然男男女女都有,但是在这样的特征中,男性的占比其实是比女性要大很多。
以上就是朴素贝叶斯的分类思想,主要应用的是归纳法。
目标:有个对象,它的特征为 
     
      
       
        
        
          X 
         
        
          ^ 
         
        
       
         = 
        
       
         { 
        
        
         
         
           x 
          
         
           0 
          
         
        
          , 
         
         
         
           x 
          
         
           1 
          
         
        
          , 
         
        
          . 
         
        
          . 
         
        
          . 
         
        
          . 
         
         
         
           x 
          
         
           m 
          
         
        
       
         } 
        
       
      
        \hat{X}=\{{x_0,x_1,....x_m}\} 
       
      
    X^={x0,x1,....xm},现需要判断这个对象究竟是属于哪个类别
 判断方式:在历史数据中找到符合这个特征的所有对象,计算在这些对象中,各类别的占比。
- 哪个类别的占比大,就判定这个对象是哪个类别
 
当然,朴素贝叶斯是有可能分类错误的!!!刻板印象不可有,但如果没有办法,刻板印象在一定程度上,就是经验
一个人的经验丰富,可能指的就是,这个人的朴素贝叶斯分类正确率较大,能够在面对某些情况时,根据他个人的经验(朴素贝叶斯),来做出正确概率较大的判断!!!
2. 举例理解朴素贝叶斯公式
首先,朴素贝叶斯能够通过计算,分类正确率较大的前提是,各特征之间没有相关性。
举个🌰:现有关于人体特征与性别的历史数据,其中特征为3种(即特征)
  
     
      
       
        
        
          x 
         
        
          1 
         
        
       
         (平胸与否:平胸、不平胸)、 
        
        
        
          x 
         
        
          1 
         
        
       
         (是否有喉结:有喉结、无喉结)、 
        
        
        
          x 
         
        
          2 
         
        
       
         (头发长度:短、中、长) 
        
       
      
        x_1(平胸与否:平胸、不平胸)、x_1(是否有喉结:有喉结、无喉结)、x_2(头发长度:短、中、长) 
       
      
    x1(平胸与否:平胸、不平胸)、x1(是否有喉结:有喉结、无喉结)、x2(头发长度:短、中、长),
 性别  
     
      
       
       
         y 
        
       
      
        y 
       
      
    y 为 2 种:男、女
目标:现在有个人的身体特征为 x 0 = 不平胸、 x 1 = 有喉结、 x 2 = 中头发 x_0=不平胸、x_1=有喉结、x_2=中头发 x0=不平胸、x1=有喉结、x2=中头发,请判断这人是男or女 ?
目前有两种根据概率来进行判断的思维:非常容易混淆!!!!!
判断思维1:计算出这个人的身体特征,在历史数据中符合这个身体特征的所有对象里,性别为男的概率有多大,性别为女的概率又有多大。
 即:
- 符合身体特征的所有对象中,男性的占比是多少 P (男 ∣ X ^ ) P(男|\hat{X}) P(男∣X^)
 - 符合身体特征的所有对象中,女性的占比是多少 P (女 ∣ X ^ ) P(女|\hat{X}) P(女∣X^)
 
方式1:联合筛选,计算概率【正常人的思维漏洞】
如果是用Excel操作,那就很简单了,直接挨个挨个筛选:先筛选不平胸、再筛选有喉结的、再筛选中头发的。
这三个条件同时满足的共有10个人,其中,男性占60%,女性占40%
可以看出,男生比例60%比较大,所以可以判断为这个 
     
      
       
        
        
          x 
         
        
          0 
         
        
       
         = 
        
       
         不平胸、 
        
        
        
          x 
         
        
          1 
         
        
       
         = 
        
       
         有喉结、 
        
        
        
          x 
         
        
          2 
         
        
       
         = 
        
       
         中头发 
        
       
      
        x_0=不平胸、x_1=有喉结、x_2=中头发 
       
      
    x0=不平胸、x1=有喉结、x2=中头发的人为男生。
 
乍一听,很合理,我都懵了,这样的判断方式,没毛病呀!!!
但这样的思维,有个非常大的缺陷问题!!!!!!有漏洞!!!
漏洞就是,万一其中某个特征的对象,本来就很少呢?
例如,假设在头发特征100个人里,中头发的人如果只有10个,并且如果中头发与性别关系不大:这种情况下,对中头发的筛选,会同时筛除掉包含另外两个特征(胸和喉结)的(短、长头发)人群。
简单来说,就是如果某个特征与分类结果关系不大,且该特征占比差异悬殊,那么对该特征的筛选,有可能会影响到其他特征的数据,最终又可能导致分类结果出错。
再打个比方:身高与智商无关,但在历史数据中包含有身高、基因、记忆力等特征数据X,以及对应的智商Y(高中低)。
当有个人,身高2.2米,基因xx,记忆力xx,现在要判断他智商Y的类别。
当我们筛选身高2.2米时,可能直接把99.999%的人全部筛出去了,最终可能只剩下2个人,那这2个人的智商为高、中、低的概率,还能够作为判断那个人智商的依据吗?
显然不能,因此:当特征与类别的关系不大时,筛选特征,有可能会错误地影响分类结果
方式2:条件独立,计算概率【改进方式1】
那么,第一种思维的计算方式有漏洞,我们要对第1种思维的计算方式,进行改进。
改进的方向:避免特征筛选对其他特征的影响
当各个特征之间,是相互独立,即不相关的情况下才能应用此改进的计算方式。
 这句话本身是有问题的,且先暂时这么想
也就是各特征是直接与类别有关,例如假设一个人的类别是胖、瘦,那么身高特征、外貌特征可以直接影响到类别,但身高与外貌的取值无关。一个人既高又美的概率 P = P高*P美——身高与外貌相互独立
第2种改进思维:计算出各类别中,这种身体特征出现的概率有多大,即
- 男性中出现不平胸、有喉结、中长发的概率 P ( X ^ ∣ 男) P(\hat{X}|男) P(X^∣男)
 - 女性中出现不平胸、有喉结、中长发的概率 P ( X ^ ∣ 女) P(\hat{X}|女) P(X^∣女)
 
完全跟第一种思维反过来了!!!!
但千万不能再用刚才的表格筛选:筛选出男性,再计算既不平胸、又有喉结、且还是中长发的人数占比;筛选出女性,再计算既不平胸、又有喉结、且还是中长发的人数占比!!不!不能这样,这样用联立的条件(同时成立的条件),还是会让中长发的影响到其他特征的数据
这些特征都相互独立的情况下,应分别计算出男性的各个特征占比:
- 男性中,不平胸的人数占比为 P (不平胸 ∣ 男) P(不平胸|男) P(不平胸∣男)
 - 男性中,有喉结的人数占比为 P (有喉结 ∣ 男) P(有喉结|男) P(有喉结∣男)
 - 男性中,中头发的人数占比为 P (中头发 ∣ 男) P(中头发|男) P(中头发∣男)
 
这些特征是相互独立的,也就意味着,在男性中同时出现不平胸、有喉结、中长发的概率为
  
     
      
       
       
         P 
        
       
         ( 
        
        
        
          X 
         
        
          ^ 
         
        
       
         ∣ 
        
       
         男) 
        
       
         = 
        
       
         P 
        
       
         (不平胸 
        
       
         ∣ 
        
       
         男) 
        
       
         ∗ 
        
       
         P 
        
       
         (有喉结 
        
       
         ∣ 
        
       
         男) 
        
       
         ∗ 
        
       
         P 
        
       
         (中头发 
        
       
         ∣ 
        
       
         男) 
        
       
      
        P(\hat{X}|男)=P(不平胸|男)*P(有喉结|男)*P(中头发|男) 
       
      
    P(X^∣男)=P(不平胸∣男)∗P(有喉结∣男)∗P(中头发∣男)
- 女性中,不平胸的人数占比为 P (不平胸 ∣ 女) P(不平胸|女) P(不平胸∣女)
 - 女性中,有喉结的人数占比为 P (有喉结 ∣ 女) P(有喉结|女) P(有喉结∣女)
 - 女性中,中头发的人数占比为 P (中头发 ∣ 女) P(中头发|女) P(中头发∣女)
 
这些特征是相互独立的,也就意味着,在女性中同时出现不平胸、有喉结、中长发的概率为
  
     
      
       
       
         P 
        
       
         ( 
        
        
        
          X 
         
        
          ^ 
         
        
       
         ∣ 
        
       
         女) 
        
       
         = 
        
       
         P 
        
       
         (不平胸 
        
       
         ∣ 
        
       
         女) 
        
       
         ∗ 
        
       
         P 
        
       
         (有喉结 
        
       
         ∣ 
        
       
         女) 
        
       
         ∗ 
        
       
         P 
        
       
         (中头发 
        
       
         ∣ 
        
       
         女) 
        
       
      
        P(\hat{X}|女)=P(不平胸|女)*P(有喉结|女)*P(中头发|女) 
       
      
    P(X^∣女)=P(不平胸∣女)∗P(有喉结∣女)∗P(中头发∣女)

 这样的计算,虽然避免了一个特征的筛选,影响其他特征数据的情况,但还是对分类概率本身有很大影响。
因为,如果某些特征本来占比就少,例如假设中头发的人数本来就很少很少,那么无论男性、还是女性中, P (中头发 ∣ 男) P(中头发|男) P(中头发∣男)和 P (中头发 ∣ 男) P(中头发|男) P(中头发∣男)都会非常小
这就像是,全中国身高超过2.2米的人数占比为0.1%,非常小。。。。而男性中,身高超过2.2米的占比也非常小,可能为0.11%
 那么如果用男性中的身高占比,去计算分类概率时,会非常拉低分类概率的。
即,计算出来的 P ( X ^ ∣ 男) P(\hat{X}|男) P(X^∣男)和 P ( X ^ ∣ 女) P(\hat{X}|女) P(X^∣女)也会很小。
所以,为了避免各个特征自身占比的影响,就让各类别中的每个特征占比,都分别去除以各特征自身的占比。
这就好像是,全中国身高超过2.2米的占比为0.1%,本身就很小,那我用0.11%除以0.1%,不久可以去除特征自身占比偏小的影响了嘛!
但相除的实际数学意义是什么呢?拿 P (中头发 ∣ 男) P (中头发) \frac{ P(中头发|男)}{P(中头发)} P(中头发)P(中头发∣男)作为例子,

P (中头发 ∣ 男) = 男性中的中头发人数 男性总人数 P(中头发|男)=\frac{男性中的中头发人数}{男性总人数} P(中头发∣男)=男性总人数男性中的中头发人数
P (中头发) = ( 总人数中的中头发数 ) 总人数 {P(中头发)}=\frac{(总人数中的中头发数)}{总人数} P(中头发)=总人数(总人数中的中头发数)
则 P (中头发 ∣ 男) P (中头发) = 男性中的中头发人数 男性总人数 ➗ 总人数中的中头发数 总人数 = 男性中的中头发数 总人数中的中头发数 ✖ 总人数 男性总人数 \frac{ P(中头发|男)}{P(中头发)}=\frac{男性中的中头发人数}{男性总人数}➗\frac{总人数中的中头发数}{总人数}=\frac{男性中的中头发数}{总人数中的中头发数}✖\frac{总人数}{男性总人数} P(中头发)P(中头发∣男)=男性总人数男性中的中头发人数➗总人数总人数中的中头发数=总人数中的中头发数男性中的中头发数✖男性总人数总人数
亮点来了!!!!!!
这里,其实就等于中头发中,性别为男的概率 P (男 ∣ 中头发) P(男|中头发) P(男∣中头发)
譬如,50个男里有10个中头发,总共100个人里有30个中头发——那不就相当于100个人里,总共有30个中头发,其中男的占了10个
所以, P (男 ∣ 中头发) = P (中头发 ∣ 男) P (中头发) ∗ P (男) P(男|中头发)=\frac{ P(中头发|男)}{P(中头发)}*P(男) P(男∣中头发)=P(中头发)P(中头发∣男)∗P(男)
= 男性中的中头发数 总人数中的中头发数 ✖ 总人数 男性总人数 ∗ 男性总人数 总人数 = 男性中的中头发数 总人数中的中头发数 = \frac{男性中的中头发数}{总人数中的中头发数}✖\frac{总人数}{男性总人数}*\frac{男性总人数}{总人数}=\frac{男性中的中头发数}{总人数中的中头发数} =总人数中的中头发数男性中的中头发数✖男性总人数总人数∗总人数男性总人数=总人数中的中头发数男性中的中头发数
那么 P (男 ∣ 中头发) = P (中头发 ∣ 男) P (中头发) ∗ P (男) P(男|中头发)=\frac{ P(中头发|男)}{P(中头发)}*P(男) P(男∣中头发)=P(中头发)P(中头发∣男)∗P(男) ,这就是贝叶斯公式的计算过程呀!!!!
我觉得我悟了呜呜呜呜,虽然感觉任何正常人看了,都会不知所云。。。但我真的悟了。。。。还是要写下来,才能梳理清自己的思维
 手动实现算法的代码,其实是一件比理解更容易的事,能理解一件事,对我而言,真的不容易
 因为脑子,有时候是骗人的,你以为的你以为,有时真的只是你以为
但即便是我理解了,我也无法真的能用逻辑清晰,简洁易懂的话,让别人理解。。。
更完整的概率计算如下,
  
     
      
       
       
         P 
        
       
         (男 
        
       
         ∣ 
        
       
         不平胸) 
        
       
         = 
        
        
         
         
           P 
          
         
           (不平胸 
          
         
           ∣ 
          
         
           男) 
          
         
         
         
           P 
          
         
           (不平胸) 
          
         
        
       
         ∗ 
        
       
         P 
        
       
         (男) 
        
       
      
        P(男|不平胸)=\frac{ P(不平胸|男)}{P(不平胸)}*P(男) 
       
      
    P(男∣不平胸)=P(不平胸)P(不平胸∣男)∗P(男)
P (男 ∣ 有喉结) = P (有喉结 ∣ 男) P (有喉结) ∗ P (男) P(男|有喉结)=\frac{ P(有喉结|男)}{P(有喉结)}*P(男) P(男∣有喉结)=P(有喉结)P(有喉结∣男)∗P(男)
P (男 ∣ 中头发) = P (中头发 ∣ 男) P (中头发) ∗ P (男) P(男|中头发)=\frac{ P(中头发|男)}{P(中头发)}*P(男) P(男∣中头发)=P(中头发)P(中头发∣男)∗P(男)
P (男 ∣ 不平胸 & 有喉结 & 中头发) = P (不平胸 & 有喉结 & 中头发 ∣ 男) P (不平胸 & 有喉结 & 中头发) ∗ P ( 男 ) P(男|不平胸\&有喉结\&中头发)=\frac{P(不平胸\&有喉结\&中头发|男)}{P(不平胸\&有喉结\&中头发)}*P(男) P(男∣不平胸&有喉结&中头发)=P(不平胸&有喉结&中头发)P(不平胸&有喉结&中头发∣男)∗P(男)
= P (不平胸 ∣ 男) ∗ P (中头发 ∣ 男) ∗ P (有喉结 ∣ 男) P (不平胸) P (有喉结) P (中头发) ∗ P (男) \frac{ P(不平胸|男)* P(中头发|男)*P(有喉结|男)}{P(不平胸)P(有喉结)P(中头发)}*P(男) P(不平胸)P(有喉结)P(中头发)P(不平胸∣男)∗P(中头发∣男)∗P(有喉结∣男)∗P(男)
无知的困惑1
之前有个困惑,既然各个特征之间是相互独立的,那为什么不用下边这种方式来计算?
  
     
      
       
       
         P 
        
       
         (男 
        
       
         ∣ 
        
       
         不平胸 
        
       
         & 
        
       
         有喉结 
        
       
         & 
        
       
         中头发) 
        
       
         = 
        
       
         P 
        
       
         (男 
        
       
         ∣ 
        
       
         不平胸) 
        
       
         P 
        
       
         (男 
        
       
         ∣ 
        
       
         有喉结) 
        
       
         P 
        
       
         (男 
        
       
         ∣ 
        
       
         中头发) 
        
       
      
        P(男|不平胸\&有喉结\&中头发)=P(男|不平胸)P(男|有喉结)P(男|中头发) 
       
      
    P(男∣不平胸&有喉结&中头发)=P(男∣不平胸)P(男∣有喉结)P(男∣中头发)
P (男 ∣ 不平胸 & 有喉结 & 中头发) P(男|不平胸\&有喉结\&中头发) P(男∣不平胸&有喉结&中头发)表示:在既不平胸、又有喉结、同时还留中头发的对象里,男性的占比为多少= 不平胸、有喉结、中头发的男性人数 不平胸、有喉结、中头发总人数 \frac{不平胸、有喉结、中头发的男性人数}{不平胸、有喉结、中头发总人数} 不平胸、有喉结、中头发总人数不平胸、有喉结、中头发的男性人数
P(男|不平胸)表示:不平胸的对象里,男性占比为多少 =  
     
      
       
        
        
          不平胸的男性人数 
         
        
          不平胸总人数 
         
        
       
      
        \frac{不平胸的男性人数}{不平胸总人数} 
       
      
    不平胸总人数不平胸的男性人数
 P(男|有喉结)表示:有喉结的对象里,男性占比为多少 =  
     
      
       
        
        
          有喉结的男性人数 
         
        
          不平胸总人数 
         
        
       
      
        \frac{有喉结的男性人数}{不平胸总人数} 
       
      
    不平胸总人数有喉结的男性人数
 P(男|中头发)表示:中头发的对象里,男性占比为多少 =  
     
      
       
        
        
          中头发的男性人数 
         
        
          中头发总人数 
         
        
       
      
        \frac{中头发的男性人数}{中头发总人数} 
       
      
    中头发总人数中头发的男性人数
不平胸的男性人数 不平胸总人数 ∗ 不平胸的男性人数 不平胸总人数 ∗ 中头发的男性人数 不平胸总人数 ≠ 不平胸、有喉结、中头发的男性人数 不平胸、有喉结、中头发总人数 \frac{不平胸的男性人数}{不平胸总人数}*\frac{不平胸的男性人数}{不平胸总人数}*\frac{中头发的男性人数}{不平胸总人数}≠ \frac{不平胸、有喉结、中头发的男性人数}{不平胸、有喉结、中头发总人数} 不平胸总人数不平胸的男性人数∗不平胸总人数不平胸的男性人数∗不平胸总人数中头发的男性人数=不平胸、有喉结、中头发总人数不平胸、有喉结、中头发的男性人数
因此, P (男 ∣ 不平胸 & 有喉结 & 中头发) ≠ P (男 ∣ 不平胸) P (男 ∣ 有喉结) P (男 ∣ 中头发) P(男|不平胸\&有喉结\&中头发)≠P(男|不平胸)P(男|有喉结)P(男|中头发) P(男∣不平胸&有喉结&中头发)=P(男∣不平胸)P(男∣有喉结)P(男∣中头发)
P (男 ∣ 不平胸 & 有喉结 & 中头发) P(男|不平胸\&有喉结\&中头发) P(男∣不平胸&有喉结&中头发)中,【不平胸&有喉结&中头发】是一个既定统计事实,不能是通过特征独立后的概率相乘计算得到
无知的困惑2
另外,还有个地方是我困惑的:在课本里的朴素贝叶斯分母部分,是用的全概率公式
  
     
      
       
       
         P 
        
       
         (男 
        
       
         ∣ 
        
       
         不平胸 
        
       
         & 
        
       
         有喉结 
        
       
         & 
        
       
         中头发) 
        
       
         = 
        
        
         
         
           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(有喉结)P(中头发) 
       
      
    P(不平胸&有喉结&中头发)=P(不平胸)P(有喉结)P(中头发)
独立的新知识:条件独立和独立,是不一样的!!!我之前的说法又错了!!!
条件独立:在结果是既定发生的条件下,特征对结果的影响是独立的,即 
     
      
       
       
         P 
        
       
         ( 
        
       
         A 
        
       
         、 
        
       
         B 
        
       
         ∣ 
        
       
         条件 
        
       
         1 
        
       
         ) 
        
       
         = 
        
       
         P 
        
       
         ( 
        
       
         A 
        
       
         ∣ 
        
       
         条件 
        
       
         1 
        
       
         ) 
        
       
         ∗ 
        
       
         P 
        
       
         ( 
        
       
         B 
        
       
         ∣ 
        
       
         条件 
        
       
         1 
        
       
         ) 
        
       
      
        P(A、B|条件1)=P(A|条件1)*P(B|条件1) 
       
      
    P(A、B∣条件1)=P(A∣条件1)∗P(B∣条件1)
 但是: 
     
      
       
       
         P 
        
       
         ( 
        
       
         A 
        
       
         、 
        
       
         B 
        
       
         )不一定等于 
        
       
         P 
        
       
         ( 
        
       
         A 
        
       
         ) 
        
       
         ∗ 
        
       
         P 
        
       
         ( 
        
       
         B 
        
       
         ) 
        
       
      
        P(A、B)不一定等于P(A)*P(B) 
       
      
    P(A、B)不一定等于P(A)∗P(B)
A,B在条件1发生下相互独立等价于A在条件1下是否发生和B是否发生无关。【盗取别人的说法】
条件独立就好像是,唐僧取经成功的情况下(既定条件),孙悟空的打怪个数和猪八戒的摆烂次数,是相互独立的。
好像不贴切哈,再换一个:考试满分的情况下(既定条件),妈妈送饭和熬夜学习这两个特征,是相互独立的。
算了。。。好像都不怎么贴切,但就是这么个意思,要有个条件前提下,特征相互独立的情况。
独立:特征之间是相互独立的。【条件影响无作用】
 也就是 
     
      
       
       
         P 
        
       
         ( 
        
       
         A 
        
       
         、 
        
       
         B 
        
       
         ) 
        
       
         = 
        
       
         P 
        
       
         ( 
        
       
         A 
        
       
         ) 
        
       
         ∗ 
        
       
         P 
        
       
         ( 
        
       
         B 
        
       
         ) 
        
       
      
        P(A、B)= P(A)*P(B) 
       
      
    P(A、B)=P(A)∗P(B)
 由于条件影响无作用,因此,
 👉 P(A|条件1) = P(A)、P(B|条件1)=P(B)
 👉 P(AB|条件1) = P(AB)=P(A)*P(B)
条件独立和独立之间,并没有包含关系。
即,两个特征的条件独立,并不能说明这两个特征独立。
- 例如,当处在一个总体学习成绩特别好的班级里,家境和教育环境对成绩的影响,是相互独立的。
 - 即,在一个总体学习成绩特别好的班级,家境虽然有些不同,但教育环境其实是相近的,因此家境与教育环境之间,相对而言是独立的。
 - 但如果没有这个班级的前提,也就是如果单纯考量家境和教育环境的关系,通常会发现家境其实是会对教育环境有较大的影响,有较强的相关性:家境好的家庭,通产会将孩子送到教育环境好的地方学习
 
另外,两个特征独立,并不能说明这两个特征基于某个条件也独立。
- 例如,在无特定的场景条件下,尿布和啤酒的销量,是相互独立的。即尿布卖多卖少,与啤酒无关
 - 但如果是在已婚妇女的超市购物场景条件下,统计可发现尿布和啤酒的销量之间是有相关性的,尿布销量高,啤酒销量也高
 - 原因:已婚妇女有孩子,有丈夫,一次性购物通常会同时买。
 
我也不知道举例是否正确
朴素贝叶斯是基于条件独立的前提下进行的,而不是独立
那么 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(女)
感动…朴素贝叶斯的理论部分,差不多完结了,好像还有拉普拉斯平滑。。。这个就很简单了,先不搞
2.1 朴素的朴素贝叶斯公式
👉 总公式:
  
     
      
       
       
         P 
        
       
         (男 
        
       
         ∣ 
        
       
         不平胸 
        
       
         & 
        
       
         有喉结 
        
       
         & 
        
       
         中头发) 
        
       
         = 
        
        
         
         
           P 
          
         
           (不平胸 
          
         
           & 
          
         
           有喉结 
          
         
           & 
          
         
           中头发 
          
         
           ∣ 
          
         
           男) 
          
         
         
         
           P 
          
         
           (不平胸 
          
         
           & 
          
         
           有喉结 
          
         
           & 
          
         
           中头发) 
          
         
        
       
         ∗ 
        
       
         P 
        
       
         ( 
        
       
         男 
        
       
         ) 
        
       
      
        P(男|不平胸\&有喉结\&中头发)=\frac{P(不平胸\&有喉结\&中头发|男)}{P(不平胸\&有喉结\&中头发)}*P(男) 
       
      
    P(男∣不平胸&有喉结&中头发)=P(不平胸&有喉结&中头发)P(不平胸&有喉结&中头发∣男)∗P(男)
P (女 ∣ 不平胸 & 有喉结 & 中头发) = 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(中头发|女)*P(女)
👉 更细节公式-单个概率部分:
 分子和分母的计算,都是单个特征的条件概率计算,例如P(有喉结|女)
 具化到统计时,如下
P ( 有喉结 ∣ 女 ) = 女性中有喉结的人数 女性人数 P(有喉结|女) = \frac{女性中有喉结的人数}{女性人数} P(有喉结∣女)=女性人数女性中有喉结的人数
P ( 男 ) = 男性人数 总人数 P(男) =\frac{男性人数}{总人数} P(男)=总人数男性人数
不行!!没有拉普拉斯平滑,我的第一个朴素贝叶斯代码就遇到大问题了
2.1.2 拉普拉斯平滑
如果:出现数据里没有的某个特征值,那么条件概率计算就会为0,则无法进行分类。
例如,如果我们要预测对象,ta的特征是,不平胸、无头发、有喉结,注意,无头发这个特征在原来的数据里是没有的,那么 P(无头发|女),或 P(无头发|男),都为0
那么根据朴素贝叶斯公式,分母部分就会为 0 ,导致无法进行计算和分类 :
 P(不平胸&有喉结&中头发)= P(不平胸|男)*P(有喉结|男)*P(无头发|男)*P(男)+P(不平胸|女)*P(有喉结|女)*P(无头发|女)*P(女)
无法计算出概率,这就无法进行分类了呀!!!我们希望的情况是:即使出现新的特征,也能根据其他原有的特征进行分类
也就是,即使无头发这个特征值没有,但我们还可以根据不平胸、有喉结这两个特征进行分类啊
这就好像,如果你人生中第一次看到光头,你也可以根据喉结来判断这个光头是男是女。
因此,要解决这个问题,需要引入平滑算法,让它在某个问题上能够圆滑地糊弄过去,而且糊弄的不会太糟糕。
可见圆滑的糊弄,并不是人情世故里独有的招数,在数学的世界里,那也是非常好用的!
拉普拉斯平滑呢,就是给每个特征的条件概率计算,引入拉普拉斯算子。
这个算子呢,其实就是给每个特征的条件概率计算,分子部分+λ,分母部分+S*λ
- λ,一般是1
 - S,表示该特征的值个数,例如头发特征有3种,短头发、中头发、长头发,那么S就是3
 
所以,P(无头发|女) = 女性中无头发的人数 + λ 女性人数 + S ∗ λ = 女性中无头发的人数 + 1 女性人数 + 3 ∗ 1 \frac{女性中无头发的人数+λ}{女性人数+S*λ}=\frac{女性中无头发的人数+1}{女性人数+3*1} 女性人数+S∗λ女性中无头发的人数+λ=女性人数+3∗1女性中无头发的人数+1
即使女性中无头发的人数=0,P(无头发|女)也不再是0,而是 
     
      
       
        
         
         
           0 
          
         
           + 
          
         
           1 
          
         
         
         
           女性人数 
          
         
           + 
          
         
           3 
          
         
           ∗ 
          
         
           1 
          
         
        
       
      
        \frac{0+1}{女性人数+3*1} 
       
      
    女性人数+3∗10+1
P(无头发|男)也是如此
至此,朴素贝叶斯,暂时告一段落
但这就结束了吗!!!!!啊!!!!并没有!!!!!!
要知道,前边所讲的朴素贝叶斯分类,都是基于特征是有界的离散值来进行的分类。
例如,有喉结、无喉结,就两种特种值。
但有些特征值,是连续的:例如,金钱、年龄、点击率、销售额等等
这种连续的特征值,该怎么计算出条件概率呢?——以后再说!先把最简单的用代码实现一下
2.1.3 朴素贝叶斯 — 手动代码
收回我当初无知的言论...写代码也很难...哭了
 难就难在如何设计数据结构,思路很简单
-  
  
- 先统计各类型下各个特征值的对象数——存入字典【小复杂】
 
 -  
  
- 计算并预测每个对象的类型
 
- ① 针对单个对象的特征数据,索引获取字典中的对象数
 - ② 根据朴素贝叶斯公式,计算各类型的概率【增加拉普拉斯算子】
 - ③ 以概率最大的类型为预测结果,返回该类型
 
 
字典设计如下,叶子节点全是统计的对象数:
 如果要获取字典中,低推荐类型中,专业度为5的对象数,
 则字典索引为:字典结构[ 低推荐 ][ 专业度 ][ 5 ]
 
import numpy as np
import pandas as pd
# 获取所需数据:'推荐分值', '专业度','回复速度','服务态度','推荐类型'
datas = pd.read_excel('./datas4.xlsx')
important_features = ['推荐分值', '专业度','回复速度','服务态度','推荐类型']
datas_1 = datas[important_features]
Y = datas_1['推荐类型']
X = datas_1.drop('推荐类型',axis=1)
X_features = X.columns
Y_features = important_features[4]
rows,columns = datas_1.shape
# 1. 计算各个统计概率:P(推荐分值|各推荐类型)P(专业度|各推荐类型)P(回复速度|各推荐类型)P(回复速度|各推荐类型)P(各推荐类型)
# 如何获取具体有哪些特征、有哪些类别?——集合set函数
# 如何计算各个统计概率?——python自带的count函数
# 如何保存各个统计概率?——字典,将set里的值作为键,将count
# 集合获取特征、类别里的值
datas_dict = {}
for i in important_features:
    words = set(datas_1[i])
    datas_dict[i] = set(datas_1[i])
# 统计各特征、类别的数据,存入字典:字典结构是需要好好设计的!!!
groups = datas_1.groupby(Y_features) # 按类型分组,每组分别是一个类型的数据
datas_count = {}
for i in datas_dict[Y_features]:  # 依次获取各类型的值
    dict_temp = {}
    group = groups.get_group(i) 
    num1 = group.shape[0] # 获取当前类型组的对象数(即有几行数据)
    dict_temp[i] = num1
    """依次统计当前类型下,各个特征中-每种特征值的对象数"""
    for a in X_features: # 依次获取各个特征
        dict_Xtemp = {}
        group1 = group.groupby(a) # 按当前特征分组,每组分别是当前类型-当前特征下的数据
        for b in datas_dict[a]: # 依次获取当前特征的特征值
            try:
            	"""获取当前类型-当前特征-当前特征值组的对象数(即有几行数据)
            	(如果没有该特征值,程序会报错,因此捕获错误后让程序继续统计)"""
                num2 = group1.get_group(b).shape[0]
                dict_Xtemp[b] = num2
            except:
                pass
        dict_temp[a] = dict_Xtemp
    datas_count[i] = dict_temp
    print(datas_count)
# 基于朴素贝叶斯公式,计算单个对象的各类别概率,以概率最大的类别为预测类别,输出预测的类别
def predict(X):  # 只对每一行的X值进行计算,即预测每个对象的类别
    P_Y = []
    labels = list(datas_count.keys())
    for i in labels:  # 推荐类型
        P = 1
        P_i = datas_count[i][i]/len(Y) # P(当前类型)
        for j in X.index: # 所有特征
            """ 如果原数据中某个类型下没有某个特征值,则该类型下就没有X[j]这个键,
            那么获取datas_count[i][j][X[j]]键值时程序会报错:
            因此,需要捕获报错,在except中,将datas_count[i][j][X[j]]设置为0,再另行计算
            (也就是当找不到某个特征值,就赋值为0,而不是让程序报错)
            """
            try:
                P_up = datas_count[i][j][X[j]]+1  # +1是拉普拉斯平滑算子
                # len(datas_count[i][j])是拉普拉斯平滑算子,表示该特征的特征值个数
                P_down = datas_count[i][i]+len(datas_count[i][j]) 
                P *= (P_up/P_down)
                print(f"【{j}】值为{X[j]},{i}人数为{datas_count[i][j][X[j]]}:",P_up,P_down,f"占比{round(P_up/P_down*100,2)}%")
            except:
                P_up = 0 + 1
                P_down = datas_count[i][i]+len(datas_count[i][j])
                P *= (P_up/P_down)
                print(f"【{j}】值为{X[j]},{i}人数为0:", P_up,P_down,f"占比{round(P_up/P_down*100,2)}%")
       	"""记得要 P(特征|当前类型)*P(当前类型),
        只计算了分子部分,不计算分母部分,因为分母部分值相同"""
        P_Y.append(round(P*P_i,8)) 
    # 获取概率最大的类别名称
    Y_hat = labels[P_Y.index(max(P_Y))]
    return Y_hat
# 应用了pandas中的apply函数,将每行数据都进行predict运算预测
Y_hat = X.apply(predict,axis = 1)
print(f"分类准确率:{sum(Y==Y_hat)/len(Y)*100}%")
 
最终分类结果如下
但其实,朴素贝叶斯分类没那么准确的,之所以这次分类准确的原因,是因为原数据中的推荐类型是严格按照推荐分值进行划分的
高推荐:推荐分值≥9
中推荐:8≥推荐分值≥7
低推荐:6≥推荐分值≥0
假设这次,不用推荐分值参与分类计算了,来看看朴素贝叶斯分类的情况
 
惨不忍睹,不忍直视…这是朴素贝叶斯的普遍情况,分类速度很快,但是准确率是堪忧的!
无所谓辣,人各有所长,有所短,哪能都这么完美
3. 朴素-高斯贝叶斯
3.1 基础理解
上述的朴素贝叶斯,都是基于特征值是有限的离散值,
- 如头发这个特征,有三个特征值:短头发、中头发、长头发
 - 如喉结这个特征,有两个特征值:有喉结、无喉结
 
可是有些特征是连续的,比如说销售额、利润、身高、年龄、存款
 身高:165cm、166cm、188cm等等连续
【不知道为什么,最近思考数据,第一时间涌现上来的,都是钱。。。。】
当这些连续的特征值,也会影响分类时,我们同样需要纳入考量。
可是,连续的特征值,很难进行对象数的统计呀…
 总不能每个身高,都分别统计对应的人数吧,比如男性中,身高为166cm的有多少人
那就要很多很多很多很多的统计了,从1cm到250cm,依次进行统计
虽然这种苦力活是交给电脑,但是我自己等它干那苦力活,等得也是很烦躁的
因此,有人说,可以给这种连续的特征值,进行阶段性的划分,比如
- 低于155cm:矮
 - 低于170cm:略矮
 - 低于180cm:高
 - 高于180cm:非常高
 
这样的划分呢,很麻烦…而且万一人为划分的有问题,那就不好辣
那么就可以引进【朴素-高斯贝叶斯】
朴素-高斯贝叶斯的前提是,特征值是服从正态分布的,然后通过正态分布的概率密度函数,计算出对应的P值。
哇,忽然发觉,之前学假设检验时的统计学基础,还是派上用场了…
果然,数学知识是相通的,数学,真的是…太神奇了
哎…
但是要注意,这里的P值,并非假设检验中的P值。
👉假设检验中的P值,其实求的是概率密度函数的积分(面积)
  
     
      
       
       
         P 
        
       
         = 
        
        
        
          ∫ 
         
        
          下限 
         
        
          上限 
         
        
        
        
          1 
         
         
          
           
           
             2 
            
           
             π 
            
           
          
         
           σ 
          
         
        
        
        
          e 
         
         
         
           − 
          
          
           
           
             ( 
            
           
             x 
            
           
             − 
            
           
             μ 
            
            
            
              ) 
             
            
              2 
             
            
           
           
           
             2 
            
            
            
              σ 
             
            
              2 
             
            
           
          
         
        
       
         d 
        
       
         x 
        
       
      
        P = ∫^{上限}_{下限} \frac{1}{\sqrt{2π}σ}e^{-\frac{(x-μ)²}{2σ²}}dx 
       
      
    P=∫下限上限2πσ1e−2σ2(x−μ)2dx
 👉但是,朴素-高斯贝叶斯里的P值,求得是概率密度函数的值(高度)
  
     
      
       
       
         P 
        
       
         = 
        
        
        
          1 
         
         
          
           
           
             2 
            
           
             π 
            
           
          
         
           σ 
          
         
        
        
        
          e 
         
         
         
           − 
          
          
           
           
             ( 
            
           
             x 
            
           
             − 
            
           
             μ 
            
            
            
              ) 
             
            
              2 
             
            
           
           
           
             2 
            
            
            
              σ 
             
            
              2 
             
            
           
          
         
        
       
      
        P = \frac{1}{\sqrt{2π}σ}e^{-\frac{(x-μ)²}{2σ²}} 
       
      
    P=2πσ1e−2σ2(x−μ)2

 其中,朴素高斯贝叶斯公式里的具体参数解释
  
     
      
       
       
         P 
        
       
         ( 
        
       
         特征值 
        
       
         ∣ 
        
       
         类别 
        
       
         ) 
        
       
         = 
        
        
        
          1 
         
         
          
           
           
             2 
            
           
             π 
            
           
          
         
           σ 
          
         
        
        
        
          e 
         
         
         
           − 
          
          
           
           
             ( 
            
           
             x 
            
           
             − 
            
           
             μ 
            
            
            
              ) 
             
            
              2 
             
            
           
           
           
             2 
            
            
            
              σ 
             
            
              2 
             
            
           
          
         
        
       
      
        P(特征值|类别) = \frac{1}{\sqrt{2π}σ}e^{-\frac{(x-μ)²}{2σ²}} 
       
      
    P(特征值∣类别)=2πσ1e−2σ2(x−μ)2
- x:表示当前对象的具体特征值
 - μ:表示当前类型下的当前特征均值
 - σ:表示当前类型下的当前特征的标准差
 
其实很简单,就是在原来的代码里,对指定的特征的概率计算,换成正态分布的概率密度公式计算就好。
但是。。。我实在是懒得了
3.2 高斯贝叶斯 - sklearn代码
sklearn中的高斯贝叶斯,不知道是不是将所有离散值,也用概率密度函数来计算概率值
from sklearn import naive_bayes
import pandas as pd
import matplotlib.pyplot as plt
from sklearn.metrics import classification_report
# 获取所需数据:'推荐分值', '专业度','回复速度','用户群活跃天数'
datas = pd.read_excel('./datas1.xlsx')
important_features = ['推荐类型','推荐分值', '专业度','回复速度','用户群活跃天数']
datas_1 = datas[important_features]
# 明确实值Y为'推荐分值',X分别为'专业度','回复速度','用户群活跃天数'
Y = datas_1['推荐类型']
X = datas_1.drop('推荐类型',axis=1)
# 1. 建立模型
classifier = naive_bayes.GaussianNB()
classifier.fit(X,Y)
# 2. 学习模型
classifier.fit(X,Y)
Y_predict = classifier.predict(X)
result_P = classifier.predict_proba(X)
# 3. 衡量模型
accurency = classifier.score(X,Y)
PRF = classification_report(Y,Y_predict)
# 输出模型最优状态下的参数及衡量模型的指标
print("模型分类【准确率】为:",accurency)
print("模型的精确率、召回率、F1分数为:")
print(PRF)
print('【模型分类,实际分类】的对比如下:')
for index,value in enumerate(zip(Y_predict,Y)):
    print(value)
    print(result_P[index])
# print(result_P)
 

 手动演算一下sklearn的高斯贝叶斯计算过程
3.3 高斯贝叶斯 - 手动代码
import math
import numpy as np
import pandas as pd
# 获取所需数据:'推荐分值', '专业度','回复速度','服务态度','推荐类型'
datas = pd.read_excel('./datas1.xlsx')
important_features = ['推荐类型','推荐分值', '专业度','回复速度','用户群活跃天数']
datas_1 = datas[important_features]
Y = datas_1['推荐类型']
X = datas_1.drop('推荐类型',axis=1)
X_features = X.columns
Y_features = '推荐类型'
rows,columns = datas_1.shape
# 1. 计算各个统计概率:P(推荐分值|各推荐类型)P(专业度|各推荐类型)P(回复速度|各推荐类型)P(回复速度|各推荐类型)P(各推荐类型)
# 如何获取具体有哪些特征、有哪些类别?——集合set函数
# 如何计算各个统计概率?——python自带的count函数
# 如何保存各个统计概率?——字典,将set里的值作为键,将count
# 集合获取特征、类别里的值
datas_dict = {}
for i in important_features:
    words = set(datas_1[i])
    datas_dict[i] = set(datas_1[i])
# 统计各特征、类别的数据,存入字典:字典结构是需要好好设计的!!!
groups = datas_1.groupby(Y_features)
datas_count = {}
for i in datas_dict[Y_features]:
    dict_temp = {}
    group = groups.get_group(i)
    num1 = group.shape[0]
    dict_temp[i] = num1/len(Y)
    for a in X_features:
        dict_Xtemp = {}
        mean = group[a].mean()
        σ = group[a].std()
        dict_Xtemp = (mean,σ)
        dict_temp[a] = dict_Xtemp
    datas_count[i] = dict_temp
print(datas_count)
# 基于朴素贝叶斯公式,计算单个对象的各类别概率,以概率最大的类别为预测类别,输出预测的类别
def predict(X):  # 只对每一行的X值进行计算,即预测每个对象的类别
    P_Y = []
    labels = list(datas_count.keys())
    for i in labels:  # 推荐类型
        P = 1
        P_i = datas_count[i][i]
        for j in X.index: # 所有特征
            """ 如果原数据中某个类型下没有某个特征值,则该类型下就没有X[j]这个键,
            那么获取datas_count[i][j][X[j]]键值时程序会报错:
            因此,需要捕获报错,在except中,将datas_count[i][j][X[j]]设置为0,再另行计算
            (也就是当找不到某个特征值,就赋值为0,而不是让程序报错)
            """
            try:
                μ = datas_count[i][j][0]
                σ = datas_count[i][j][1]
                x = X[j]
                if σ == 0:
                    P_x = 1
                P_x = 1/(math.sqrt(2*math.pi)*μ)*math.exp(-math.pow(x-μ,2)/(2*σ*σ))
                P *= P_x
                print(f"【{j}】值为{X[j]},{i}人数为占比{round(P_x*100,6)}%")
            except:
                P_x = 1
                P *= P_x
                print(f"【{j}】值为{X[j]},{i}人数为占比{round(P_x*100,6)}%")
        P_Y.append(round(P*P_i,8))
    # 获取概率最大的类别名称
    Y_hat = labels[P_Y.index(max(P_Y))]
    return Y_hat
# 应用了pandas中的apply函数,将每行数据都进行predict运算预测
Y_hat = X.apply(predict,axis = 1)
# print(f"分类准确率:{sum(Y==Y_hat)/len(Y)*100}%")
 
奇了怪了…怎么sklearn的高斯朴素贝叶斯分类准确率比我的还低呢。。。。
我这是将所有特征值,都用正态分布来计算概率的。。。。
不过也能看得出,朴素高斯贝叶斯,相对于朴素贝叶斯,好像分类结果比较差呢























