朴素贝叶斯算法

Posted 数据挖掘与R语言

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了朴素贝叶斯算法相关的知识,希望对你有一定的参考价值。

朴素贝叶斯(Naive Bayes,以下简称NB)算法是基于概率学习的一种分类方法,朴素贝叶斯利用先验信息来预测将来事件发生的概率。举个例子,就好比古时大夫给病人看病,他需要“望闻问切”,才能对病人的病情做出诊断。这里“望闻问切”是为了获取病人的病情即特征,然后他会对比该病情特征和以往他所见过的病情特征做比较,推断具体病症然后对症下药,这里的推断从某种程度上就用到了贝叶斯算法。好了,下面进入主题,介绍什么是NB算法。

NB算法的基础是贝叶斯定理,我们首先来理解一下贝叶斯定理的定义。

贝叶斯定理

我们直接抛出贝叶斯定理公式:


这里对其中的一些记号做一些说明,朴素贝叶斯算法表示条件概率,即事件B发生的前提下A发生的概率。

接下来说说这个公式的妙用了,我们在实际问题中经常遇到朴素贝叶斯算法很难直接得到,而朴素贝叶斯算法很容易求得的情形,这时便可采用贝叶斯定理了。

为了便于理解上面的贝叶斯定理,我们引用一个典型的垃圾邮件分类问题。

把问题做简化,假设只有一个分类特征,获得如下频数表信息,行spam表示垃圾邮件,ham表示正常邮件,yes表示邮件中出现free单词,no表示邮件中未出现free单词。接下来,我们看如何用朴素贝叶斯算法来判断新来邮件是否为垃圾邮件。

freq yes no Total
spam 15 5 20
ham 10 70 80
Total 25 75 100

假如新来一封邮件,我们在未获取任何特征信息的时,认为这封邮件是垃圾邮件的概率朴素贝叶斯算法为20%(历史样本中垃圾邮件的比例)。这里的朴素贝叶斯算法被称之为先验概率。

如果我们获取了特征信息,知道这封邮件中是否含有free单词,那么我们可以计算出朴素贝叶斯算法或者朴素贝叶斯算法,这个条件概率称之为似然,与之对应的 朴素贝叶斯算法或者朴素贝叶斯算法则称之为边缘似然。

有了以上这些概率值,我们便可很容易的求得后验概率朴素贝叶斯算法,公式如下,

朴素贝叶斯算法

同理,我们可以计算出朴素贝叶斯算法,然后比较其与朴素贝叶斯算法的大小,哪一项概率值更大,那么邮件则更可能属于哪一类。

这时,新来一封邮件,经统计发现,该邮件内容中出现了free单词,我们首先按步骤计算似然、边缘似然以及先验概率:

朴素贝叶斯算法

朴素贝叶斯算法

朴素贝叶斯算法

朴素贝叶斯算法

然后计算后验概率:

朴素贝叶斯算法

朴素贝叶斯算法

于是,我们判定这封邮件为垃圾邮件。下面对NB算法的一般步骤做个总结。

NB算法

NB分类计算步骤
  • 1 获取特征属性值 朴素贝叶斯算法,设朴素贝叶斯算法表示类别

  • 2 计算条件概率 朴素贝叶斯算法,先验概率 朴素贝叶斯算法 ,以及边缘似然朴素贝叶斯算法

  • 3 由贝叶斯公式计算 朴素贝叶斯算法

  • 4 计算 朴素贝叶斯算法,则 朴素贝叶斯算法

这里计算的关键是计算条件概率朴素贝叶斯算法

  • 当特征属性为离散情形时, 朴素贝叶斯算法非常容易计算,只要统计各个离散的特征属性值在每种分类中出现的频率即可;

  • 当特征为连续特征时,可以把连续特征离散化,离散化后计算规则同上;更一般地,我们假定其值服从正态分布。即

朴素贝叶斯算法

这里的朴素贝叶斯算法朴素贝叶斯算法为特征朴素贝叶斯算法朴素贝叶斯算法类别下的样本均值和标准差。


正态分布的好处是分布参数容易估计,大多数特征属性在大样本情形下用正态分布不会有太大的问题。实际上,这里的分布形式并不局限于正态分布,确切地说,为提高分类的准确度,我们应当采用更适合的特征属性的分布形式。

Laplace校准

当特征属性为离散情形时,当其中一个类别下某个特征划分没有出现即朴素贝叶斯算法

这时假定特征之间相互独立,那有

朴素贝叶斯算法

这可能会导致严重的预测错误。我们来看个例子:

朴素贝叶斯算法

朴素贝叶斯算法

这时,判定属于C1类的概率为

朴素贝叶斯算法

判定属于C2类的概率为

朴素贝叶斯算法

这种判定合理吗,很可能不是的。

这便是Laplace估计量设计的初衷,引入它就是用来防止这类问题的发生。Laplace校准的思想非常简单,就是对每个类别下所有划分的统计频数加一个小的常数,这个常数通常设为1,就是为了保证在每一种分类情况下,其特征的统计频数不为0。回过头来,在上述例子中加入Laplace=1,重新计算分类概率:

朴素贝叶斯算法

朴素贝叶斯算法

我们看到,经Laplace校正,判定属于C1类的概率为

朴素贝叶斯算法

判定属于C2类的概率为

可以看到,判定结论来了个大翻转,而这个判定才极有可能是最终正确的。

编写一个NB算法程序

# 设随机数种子   
set.seed(123)
# 拆分训练和测试集      
as.ind <- which(asdat$player %in% allStarnames[-c(3,6,9,12,15,18,21,24)])
no.ind <- which(!asdat$player %in% allStarnames)
train.index <- c(as.ind,sample(no.ind, length(no.ind)%/%4*3))
asdat.train <- asdat[train.index, ]asdat.test <- asdat[-train.index, ]

# 计算概率密度函数的参数
density.M <- ddply(.data = asdat.train,
.variables = "as",                  
.fun = function(dat) data.frame(feature=c("pts","per","wr"),
m=c(mean(dat$pts),mean(dat$per),mean(dat$wr)),
sd=c(sd(dat$pts),sd(dat$per),sd(dat$wr)))  )

# 先验概率
prior.p <- sum(asdat.train$as==1)/nrow(asdat.train)
# 朴素贝叶斯分类预测
predict.nb <- function(newdata,density.M,prior.p){  # 提取不同类别概率密度函数的参数  density.pts0 <- filter(density.M,feature=="pts" & as==0)  density.per0 <- filter(density.M,feature=="per" & as==0)  density.wr0 <- filter(density.M,feature=="wr" & as==0)  density.pts1 <- filter(density.M,feature=="pts" & as==1)  density.per1 <- filter(density.M,feature=="per" & as==1)  density.wr1 <- filter(density.M,feature=="wr" & as==1)  n <- nrow(newdata)  pred <- rep(NA,n)  for(i in 1:n){    temp <- newdata[i,]    # 计算负类概率    f1_C0 <- dnorm(temp$pts,mean = density.pts0$m,sd = density.pts0$sd)    f2_C0 <- dnorm(temp$per,mean = density.per0$m,sd = density.per0$sd)    f3_C0 <- dnorm(temp$wr,mean = density.wr0$m,sd = density.wr0$sd)    p0 <- f1_C0*f2_C0*f3_C0*(1-prior.p)        # 计算正类概率    f1_C0 <- dnorm(temp$pts,mean = density.pts1$m,sd = density.pts1$sd)    f2_C0 <- dnorm(temp$per,mean = density.per1$m,sd = density.per1$sd)    f3_C0 <- dnorm(temp$wr,mean = density.wr1$m,sd = density.wr1$sd)    p1 <- f1_C0*f2_C0*f3_C0*prior.p        # 判定    pred[i] <- ifelse(p1>p0,1,0)  }  return(pred)
}

# 检验预测结果
pred <- predict.nb(asdat.test,density.M,prior.p)
table(pred,asdat.test$as)
 
## pred  0  1
##    0 23  3
##    1  1  5
# 预测错误项
asdat.test$pred <- pred
select(asdat.test,player,as,pred) %>% filter(as!=pred)
##          player as pred
## 1 达米安-利拉德  0    1
## 2   德维恩-韦德  1    0
## 3 科比-布莱恩特  1    0
## 4   艾尔-霍福德  1    0

可以看到,预测的准确率还可以。有意思的是,NB算法预测结果与(←点此链接可跳转)的预测结果那完全一样,预测效果可接受,分析参见前篇。

上述案例可以帮你深入理解贝叶斯分类算法的计算流程,但是程序代码写得比较粗糙,仅适用于这个特定案例。其实,当你十分熟悉NB算法后,也可以直接调用e1071包中的naiveBayes函数,其调用形式相当简单,留给大家自行尝试,有任何问题欢迎交流,谢谢!


长按识别图中二维码 


以上是关于朴素贝叶斯算法的主要内容,如果未能解决你的问题,请参考以下文章

朴素贝叶斯并不朴素

朴素贝叶斯算法简介及python代码实现分析

利用朴素贝叶斯算法进行分类-Java代码实现

机器学习——朴素贝叶斯算法

机器学习--朴素贝叶斯算法原理方法及代码实现

译文:朴素贝叶斯算法简介(Python和R中的代码)