继续浏览精彩内容
慕课网APP
程序员的梦工厂
打开
继续
感谢您的支持,我会继续努力的
赞赏金额会直接到老师账户
将二维码发送给自己后长按识别
微信支付
支付宝支付

【机器学习】贝叶斯——朴素贝叶斯算法以及案例代码(Python版)

Peak_One
关注TA
已关注
手记 25
粉丝 7094
获赞 169

【朴素贝叶斯算法概述】

朴素贝叶斯算法是在贝叶斯公式的基础之上演化而来的分类算法,在机器学习中有着广泛的应用。朴素贝叶斯算法是条件化的贝叶斯算法,即在特征条件独立假说下的贝叶斯算法

【关于先验概率、后验概率的理解】

   在进行理论推导之前,很有必要先普及一下什么是“先验概率”和“后验概率”,至少我在学习的过程中为区分此概念费了一番功夫。
举例说明如下:
前验概率: 一所学校里面有 60% 的男生,40% 的女生。男生总是穿长裤,女生则一半穿长裤一半穿裙子。有了这些信息之后我们可以容易地计算“随机选取一个学生,他(她)穿长裤的概率和穿裙子的概率是多大”,这个就是前面说的“先验概率”的计算。
后验概率: 然而,假设你走在校园中,迎面走来一个穿长裤的学生(很不幸的是你高度近似,你只看得见他(她)穿的是否长裤,而无法确定他(她)的性别),你能够推断出他(她)是女生的概率是多大吗?这就是所谓的“后验概率”。
分析:
将上例转化为分类问题,则类别c={,}c=\{\text{男},\text{女}\},学生个体为样本xx,其中xXx\in X,其中随机变量XX是一维向量,只有唯一的属性:性别{长裤,裙子}\text{性别} \in \{\text{长裤},\text{裙子}\}
先验概率的计算:
P(pants)=60100%+40%50%=80%P(pants) = 60*100\% + 40\%*50\% = 80\%表示随机选取一个学生,他(她)穿长裤的概率的概率。
后验概率的计算:
P(girlpants)=穿长裤的女生/穿长裤的人=P(girl,pants)/P(pants)=P(girl)P(pantsgirl)/P(pants)=40%50%÷80%=25%\begin{aligned}P(girl | pants) &= \text{穿长裤的女生/穿长裤的人}\\ &= P(girl, pants)/P(pants) \\ &= P(girl)*P(pants | girl) / P(pants) \\ &= 40\% * 50\%\div80 \% \\ &= 25\% \end{aligned}
表示一个穿长裤的学生,是女生的概率。其中在求解后验概率的公式中,我们用到了以下两个公式:
P(cx)=P(x,c)P(x)P(c|x)=\frac{P(x,c)}{P(x)}
P(cx)=P(c)P(xc)P(x)(后验公式)P(c|x)=\frac{P(c)P(x|c)}{P(x)} \rightarrow(\text{后验公式})

【贝叶斯决策论】

贝叶斯局策论,基于概率和误判损失来选择最优的类别标记。本部分内容将从以下问题出发:
问题描述:对于样本xx,有NN种可能的类别标记,即类别空间y={c1,c2,,cN}y=\{c_1,c_2,\cdots ,c_N\}
λij\lambda_{ij}表示将一个真实标记为cjc_j的样本误分类为cic_i所产生的损失。基于后验概率P(cix)P(c_i|x)(即对于给定样本,判断样本属于哪个分类,概率最大的那个类别是最可能正确的类别)可获得将样本xx分类为cic_i所产生的期望损失,即在样本xx上的“条件风险”:
R(cix)=j=1NλijP(cjx)R(c_i|x)=\sum_{j=1}^{N}\lambda_{ij}P(c_j|x)
我们训练模型的目的就是为了寻找一个映射函数h:xyh:x\rightarrow y以最小化总体风险:
R(h)=Ex[R(h(x)x)]R(h)=E_x[R(h(x)|x)]
那么对于每个样本xx,若h(x)h(x)能最小化条件风险R(h(x)x)R(h(x)|x),则总体风险R(h)R(h)也将被最小化。所以为了得到最小的总体风险,只需在每个样本上选择哪个能使条件风险R(cx)R(c|x)最小的类别标记,即
h(x)=arg mincyR(cx)h^*(x)=\underset{c \in y}{arg\ min}R(c|x)
其中hh^*称为贝叶斯最优分类器,与之对应的总体风险R(h)R(h^*)称为贝叶斯风险。1R(h)1-R(h^*)反映了分类器所能达到的最好性能,即通过机器学习所产生的模型精度的理论上限。
R(cx)R(c|x)是最小化分类错误率,则误判损失λij\lambda_{ij}可表示为:
λij={0,i=j1,otherwise\lambda_{ij}=\begin{cases} 0, & i =j \\ 1 , & otherwise \end{cases}
此时条件风险表示为:R(cx)=1P(cx)R(c|x)=1-P(c|x)
于是,最小化分类错误率的贝叶斯最优分类器为:
h(x)=arg maxcyP(cx)h^*(x)=\underset{c\in y}{arg \ max}P(c|x)
即对每个样本xx,选择能使后验概率P(cx)P(c|x)最大的类别标记。

【贝叶斯模型的解释】

以上内容已经对问题解释的很清楚了,如果想要对样本进行分类,我们需要得到最大的P(cx)P(c|x),但是对于一般的情况下,直接求解,很难求出,所以一般借助贝叶斯定理,从侧面进行求解:
P(cx)=P(c)P(xc)P(x)P(c|x)=\frac{P(c)P(x|c)}{P(x)}
P(cx)P(c|x)叫后验概率,也就是我们要计算的后验概率,知道样本,计算这个样本属于某个类别的概率,概率最大的那个类别是最可能正确的类别。
P(c)P(c)是类“先验”概率。
P(xc)P(x|c)是条件概率,也就是在类别c的条件下,出现样本x的可能性。
对于每个样本xx,其P(x)=x的样本数总样本数P(x)=\frac{x\text{的样本数}}{\text{总样本数}}为很定的数值(在不考虑特征属性的情况下,如此表示),所以计算P(cx)P(c|x)的难点在于求解P(xc)P(x|c)或称之为“似然函数”。
求解类别cc的类条件概率P(xc)P(x|c)(似然函数)有两种方式实现:

  • 极大似然估计
  • 朴素贝叶斯分类器

【极大似然估计】

对于上式的计算,我们需要计算的内容主要为:P(c)P(xc)P(c)\text{和}P(x|c),其中类先验概率P(c)P(c)表达了样本空间中各类样本所占的比例,很容易计算。难点在于似然函数P(xc)P(x|c)的计算。为了方便,我们将P(xc)P(x|c)记为P(xθc)P(x| \theta_c)
DcD_c表示训练集DD中第cc类样本组成的集合,假设这些样本是独立同分布的,则参数θc\theta_c对于数据集DcD_c的似然为:
P(Dcθc)=xDcP(xθc)P(D_c|\theta_c)=\prod_{x\in D_c}P(x|\theta_c)
θc\theta_c进行极大似然估计,就是去寻找能最大化似然P(xθc)P(x| \theta_c)的参数值θc^\hat{\theta_c},对上式进行对数操作:
LL(θc)=logP(Dcθc)=xDclogP(xθc)LL(\theta_c)=\log P(D_c|\theta_c)=\sum_{x\in D_c}\log P(x|\theta_c)
此时参数θc\theta_c的极大似然估计θc^\hat{\theta_c}为:
θc^=arg maxθcLL(θc)\hat{\theta_c}=\underset{\theta_c}{arg\ max}LL(\theta_c)
例如:通常在连续属性情况下,假设P(xc)N(μc,σc2)P(x|c)\backsim N(\mu_c,\sigma_c^2)则参数μc\mu_cσc2\sigma_c^2的极大似然估计为:
μc^=1DcxDcx\hat{\mu_c}=\frac{1}{|D_c|}\sum_{x \in D_c}x
σc^2=1DcxDc(xμc^)(xμc^)T\hat{\sigma_c}^2=\frac{1}{|D_c|}\sum_{x \in D_c}(x-\hat{\mu_c})(x-\hat{\mu_c})^T
上面的两个公式中,均值向量的计算就是把所有属于类别c的训练的特征向量相加,处于c类样本总数,得到均值向量。对于方差也按照公式计算。
其实这里的思路是(引用自:贝叶斯分类器学习笔记):
1)首先认为数据都是采样得到的,我们只能观测到一部分。是啊,我们的训练数据都是有限的,只能部分反应问题。
2)然后,还假设数据产生于某个分布,比如正态分布。这个假设有点勉强,为什么一定是某个分布产生的呢?万一真实问题很复杂,根本无法用一个分布描述呢?不过这样的假设还是可以接受。
3)要特别注意,分布选的好不好,能不能反映问题空间,将直接影响最终效果。比如我假设身高服从正态分布,然后利用训练数据估计出正态分布的两个参数,最后算出类条件概率,最后用类条件概率乘上类先验概率,就得到了后验概率,预测的效果也很好。但是如果身高不服从正态分布,出来的预测效果可能就很不好。

【朴素贝叶斯】

在此处引入全概率公式:
P(A)=i=1nP(Bi)P(ABi)P\left(A\right)=\sum_{i=1}^n{P\left(B_i\right)P\left(A|B_i\right)}
基于属性条件独立性假设,即所有属性相互独立。可进一步将贝叶斯公式转化为:
P(cx)=P(c)P(xc)P(x)=P(c)P(x)i=1dP(xic)P(c|x)=\frac{P(c)P(x|c)}{P(x)}=\frac{P(c)}{P(x)}\prod_{i=1}^{d}P(x_i|c)
其中dd为属性数目,xix_ixx在第ii个属性上的取值。
由于分母P(x)P(x)对于所有类别来说相同,因此公式可以进一步化简为:
hnb(x)=arg maxcyP(c)i=1dP(xic)h_{nb}(x)=\underset{c \in y}{arg \ max}P(c)\prod_{i=1}^{d}P(x_i|c)
即朴素贝叶斯分类器的表达式。即在运算过程中,通过比较各个分类的概率大小,来选择概率最大的分类。
DcD_c表示训练集DD中第cc类样本组成的集合,若有充足的独立同分布样本,则可容易地估计出类先验概率P(c)P(c):
P(c)=DcDP(c)=\frac{|D_c|}{|D|}
对于离散型属性而言,令Dc,xiD_{c,x_i}表示DcD_c中在第ii个属性上取值为xix_i的样本组成的集合,则条件概率P(xic)P(x_i|c)可估计为:
P(xic)=Dc,xiDcP(x_i|c)=\frac{|D_{c,x_i}|}{|D_c|}
对于连续属性可考虑概率密度函数,假定p(xic)N(μc,i,σc,i2)p(x_i|c)\backsim N(\mu_{c,i},\sigma_{c,i}^2),其中μc,i\mu_{c,i}σc,i2\sigma_{c,i}^2分别是第cc类样本在第ii个属性上取值的均值和方差,则有
p(xic)=12πσc,iexp((xiμc,i)22σc,i2)p(x_i|c)=\frac{1}{\sqrt{2\pi}\sigma_{c,i}}\exp\left(-\frac{(x_i-\mu_{c,i})^2}{2\sigma_{c,i}^2}\right)
举例:
采用西瓜数据集3.0进行举例如下:
图片描述

预测样本:
图片描述
其中类先验概率P(c)P(c)为:
P(好瓜=是)=8170.471P(\text{好瓜=是})=\frac{8}{17}\approx0.471
P(好瓜=否)=9170.529P(\text{好瓜=否})=\frac{9}{17}\approx0.529
然后,每个属性的条件概率P(xic)P(x_i|c):
P青绿|是=P(色泽=青绿|好瓜=是)=38=0.375P_\text{青绿|是}=P(\text{色泽=青绿|好瓜=是})=\frac{3}{8}=0.375
P青绿|否=P(色泽=青绿|好瓜=否)=39=0.333P_\text{青绿|否}=P(\text{色泽=青绿|好瓜=否})=\frac{3}{9}=0.333
P蜷缩|是=P(根蒂=蜷缩|好瓜=是)=58=0.625P_\text{蜷缩|是}=P(\text{根蒂=蜷缩|好瓜=是})=\frac{5}{8}=0.625
P蜷缩|否=P(根蒂=蜷缩|好瓜=否)=39=0.333P_\text{蜷缩|否}=P(\text{根蒂=蜷缩|好瓜=否})=\frac{3}{9}=0.333
P浊响|是=P(敲声=浊响|好瓜=是)=68=0.750P_\text{浊响|是}=P(\text{敲声=浊响|好瓜=是})=\frac{6}{8}=0.750
P浊响|否=P(敲声=浊响|好瓜=否)=49=0.444P_\text{浊响|否}=P(\text{敲声=浊响|好瓜=否})=\frac{4}{9}=0.444
P清晰|是=P(纹理=清晰|好瓜=是)=78=0.875P_\text{清晰|是}=P(\text{纹理=清晰|好瓜=是})=\frac{7}{8}=0.875
P清晰|否=P(纹理=清晰|好瓜=否)=29=0.222P_\text{清晰|否}=P(\text{纹理=清晰|好瓜=否})=\frac{2}{9}=0.222
P凹陷|是=P(脐部=凹陷|好瓜=是)=68=0.750P_\text{凹陷|是}=P(\text{脐部=凹陷|好瓜=是})=\frac{6}{8}=0.750
P凹陷|否=P(脐部=凹陷|好瓜=否)=29=0.222P_\text{凹陷|否}=P(\text{脐部=凹陷|好瓜=否})=\frac{2}{9}=0.222
P硬滑|是=P(触感=硬滑|好瓜=是)=68=0.750P_\text{硬滑|是}=P(\text{触感=硬滑|好瓜=是})=\frac{6}{8}=0.750
P硬滑|否=P(触感=硬滑|好瓜=否)=69=0.667P_\text{硬滑|否}=P(\text{触感=硬滑|好瓜=否})=\frac{6}{9}=0.667
p密度:0.697|是=p(密度=0.697|好瓜=是)=12π0.129exp((0.6970.574)220.1292)1.959p_{\text{密度:0.697|是}}=p(\text{密度=0.697|好瓜=是})=\frac{1}{\sqrt{2\pi}0.129}\exp\left(-\frac{(0.697-0.574)^2}{2\cdot 0.129^2}\right)\approx1.959
p密度:0.697|否=p(密度=0.697|好瓜=否)=12π0.195exp((0.6970.496)220.1952)1.203p_{\text{密度:0.697|否}}=p(\text{密度=0.697|好瓜=否})=\frac{1}{\sqrt{2\pi}0.195}\exp\left(-\frac{(0.697-0.496)^2}{2\cdot 0.195^2}\right)\approx1.203
p含糖:0.460|是=p(含糖率=0.460|好瓜=是)=12π0.101exp((0.4600.279)220.1012)0.788p_{\text{含糖:0.460|是}}=p(\text{含糖率=0.460|好瓜=是})=\frac{1}{\sqrt{2\pi}0.101}\exp\left(-\frac{(0.460-0.279)^2}{2\cdot 0.101^2}\right)\approx0.788
p含糖:0.460|否=p(含糖率=0.460|好瓜=否)=12π0.108exp((0.4600.154)220.1082)0.066p_{\text{含糖:0.460|否}}=p(\text{含糖率=0.460|好瓜=否})=\frac{1}{\sqrt{2\pi}0.108}\exp\left(-\frac{(0.460-0.154)^2}{2\cdot 0.108^2}\right)\approx0.066
于是,根据朴素贝叶斯公式可得:
P(好瓜=是)×P青绿|是×P蜷缩|是×P浊响|是×P清晰|是×P凹陷|是×P硬滑|是×p密度:0.697|是×p含糖:0.460|是0.063P(\text{好瓜=是})\times P_\text{青绿|是} \times P_\text{蜷缩|是}\times P_\text{浊响|是}\times P_\text{清晰|是}\times P_\text{凹陷|是}\times P_\text{硬滑|是}\times p_{\text{密度:0.697|是}}\times p_{\text{含糖:0.460|是}}\approx0.063
P(好瓜=否)×P青绿|否×P蜷缩|否×P浊响|否×P清晰|否×P凹陷|否×P硬滑|否×p密度:0.697|否×p含糖:0.460|否6.80×105P(\text{好瓜=否})\times P_\text{青绿|否} \times P_\text{蜷缩|否}\times P_\text{浊响|否}\times P_\text{清晰|否}\times P_\text{凹陷|否}\times P_\text{硬滑|否}\times p_{\text{密度:0.697|否}}\times p_{\text{含糖:0.460|否}}\approx 6.80\times10^{-5}
由于0.063>6.80×1050.063>6.80\times10^{-5},因此,预测结果为“好瓜”。
问题:
若某个属性值在训练集中没有与某个类同时出现过,则直接基于朴素贝叶斯进行估计,很有很能出现错误的估计:例如:对一个“敲声=清脆”的测试例,有
P(清脆|是)=P(敲声=清脆|好瓜=是)=08=0P(\text{清脆|是})=P(\text{敲声=清脆|好瓜=是})=\frac{0}{8}=0
得到的最终的概率值始终为0,而不管其他属性怎么样。为了解决此类问题便引出了以下概念

【拉普拉斯修正】

为了避免其他属性携带的信息被训练集中未出现的属性值“抹去”,在估计概率值时通常要进行“平滑”,常用“拉普拉斯修正”,令NN表示训练集DD中可能的类别数,NiN_i表示第ii个属性可能的取值数,则修正后的P(c)P(c)P(xic)P(x_i|c)如下
P(c)^=Dc+1D+N\hat{P(c)}=\frac{|D_c|+1}{|D|+N}
P(xic)^=Dc,xi+1Dc+Ni\hat{P(x_i|c)}=\frac{|D_{c,x_i}|+1}{|D_c|+N_i}

【案例代码】

基于贝叶斯的单词拼写错误检测:词料库与源码(详细解释)

import re, collections
 
def words(text): return re.findall('[a-z]+', text.lower()) 
 
def train(features):
    model = collections.defaultdict(lambda: 1)
    for f in features:
        model[f] += 1
    return model
 
NWORDS = train(words(open('big.txt').read()))
 
alphabet = 'abcdefghijklmnopqrstuvwxyz'
 
def edits1(word):
    n = len(word)
    return set([word[0:i]+word[i+1:] for i in range(n)] +                     # deletion
               [word[0:i]+word[i+1]+word[i]+word[i+2:] for i in range(n-1)] + # transposition
               [word[0:i]+c+word[i+1:] for i in range(n) for c in alphabet] + # alteration
               [word[0:i]+c+word[i:] for i in range(n+1) for c in alphabet])  # insertion
 
def known_edits2(word):
    return set(e2 for e1 in edits1(word) for e2 in edits1(e1) if e2 in NWORDS)
 
def known(words): return set(w for w in words if w in NWORDS)
 
def correct(word):
    candidates = known([word]) or known(edits1(word)) or known_edits2(word) or [word]
    return max(candidates, key=lambda w: NWORDS[w])


#appl #appla #learw #tess #morw
correct('teal')

输出结果:
图片描述

【参考文献】

打开App,阅读手记
4人推荐
发表评论
随时随地看视频慕课网APP