1.朴素贝叶斯简介
在上期判别分析的介绍中,说明了判别分析算法如何使用Baye’s rule
,即根据判别函数值预测属于每个类的概率。朴素贝叶斯算法的工作原理与之完全相同,只是它不像判别分析那样进行降维,而且它可以处理分类预测和连续预测。
1.1 使用朴素贝叶斯进行分类
假设有一个来自社交媒体平台 Twitter 的 tweet 数据库,接下来构建一个模型,将每个 tweet 自动分类到一个主题。这些主题包括:politics, sports, movies, other
,并简单创建四个分类预测变量:
- 是否有
opinion
这个词; - 是否有
score
这个词; - 是否有
game
这个词; - 是否有
cinema
这个词。
朴素贝叶斯的"朴素"之处在于,通过单独估计每个预测变量的似然,然后将它们相乘,做出了一个非常强的假设,即预测变量是独立的。尽管这种假设经常是错误的,但即使在非独立的预测变量下,朴素贝叶斯往往表现得相当好。
在实践中,evidence
的计算常常比较困难,因为它实际上只是一个使所有后验概率和为 1 的正常化常数,故可以省略它,简单地将似然和先验概率相乘:
1.2 如何计算分类预测变量和连续预测变量的似然?
当我们有一个分类预测变量(比如上述中一个单词是否存在)时,朴素贝叶斯只是使用特定类中训练实例的比例,以及该预测变量的值。
当我们有一个连续变量时,朴素贝叶斯通常假设每组中的数据是正态分布。每个实例基于该拟合正态分布的概率密度被用来估计在特定类下预测变量观察到该值的似然。
当数据混合了分类变量和连续预测变量时,由于朴素贝叶斯假设它们之间是独立的,它会使用适当的方法来估计似然,这取决于每个预测变量是分类的还是连续的。
2.建立朴素贝叶斯模型
假设你是一名政治科学家,接下来我们将通过建立和评估朴素贝叶斯模型的性能来预测政党的隶属关系,使用 20 世纪 80 年代中期的常见的投票模式来预测美国国会议员是民主党人还是共和党人。你有国会议院每个成员的投票记录并可以找出你认为最能分出两党的 16 张关键选票。你的工作是根据国会议员全年的投票情况训练一个朴素贝叶斯模型来预测一个国会议员是民主党人还是共和党人。
首先,加载 R
包。
library(mlr) library(tidyverse)
2.1 加载和探索 HouseVotes84 数据集
该数据集位于 mlbench
包中,加载数据并将其转换为 tibble
格式。
data(HouseVotes84, package = "mlbench") votesTib <- as_tibble(HouseVotes84) votesTib # A tibble: 435 × 17 # Class V1 V2 V3 V4 V5 V6 V7 V8 # <fct> <fct> <fct> <fct> <fct> <fct> <fct> <fct> <fct> # 1 republic… n y n y y y n n # 2 republic… n y n y y y n n # 3 democrat NA y y NA y y n n # 4 democrat n y y n NA y n n # 5 democrat y y y n y y n n # 6 democrat n y y n y y n n # 7 democrat n y n y y y n n # 8 republic… n y n y y y n n # 9 republic… n y n y y y n n #10 democrat y y y n n n y y # … with 425 more rows, and 8 more variables: V9 <fct>, # V10 <fct>, V11 <fct>, V12 <fct>, V13 <fct>, V14 <fct>, # V15 <fct>, V16 <fct>
该数据集中有 435 个实例和 17 个变量,Class
变量是一个表明政党成员的因子,其他 16 个变量是表明个人如何投票的 16 张选票的因子。y
表示投了赞成票,n
表示投了反对票,NA
表示弃权或没有投票。我们的目标是训练一个模型,它可以利用这些变量中的信息,根据国会议员的投票结果,来预测他们是民主党人(democrat
)还是共和党人(republican
)。
注意到数据中包含 NA
,使用函数 map_dbl()
来查看每列有多少个 NA
:
map_dbl(votesTib, ~sum(is.na(.))) #Class V1 V2 V3 V4 V5 V6 V7 V8 V9 # 0 12 48 11 11 15 11 14 15 22 # V10 V11 V12 V13 V14 V15 V16 # 7 21 31 25 17 28 104
可以看到, Class
列没有缺失值。朴素贝叶斯算法处理缺失值有以下两种方式:
- 省略特定实例下有缺失值的变量,但仍然使用该实例来训练模型;
- 省略训练集中有缺失值的实例。
默认情况下,mlr
中使用的朴素贝叶斯算法是保留实例并删除变量。在大多数情况下,如果缺失值与完整值的比例非常小,那么这种方法通常是可行的。但是,如果有少量的变量和大量的缺失值,则省略实例。
2.2 绘制数据
接下来绘制数据,以更好地理解政党和投票之间的关系。同样,我们将数据转换为 untidy
格式,这样就可以绘制不同预测变量的 facet
图。
votesUntidy <- gather(votesTib, "Variable", "Value", -Class)#转换格式 ggplot(votesUntidy, aes(Class, fill = Value)) + #绘图 facet_wrap(~ Variable, scales = "free_y") + geom_bar(position = "fill") + theme_bw()
Fig 1. HouseVotes84 数据变量 facet 图
可以看到,民主党人和共和党人的投票意见有非常明显的分歧。
2.3 训练模型
首先,定义任务和学习者,并训练模型。
votesTask <- makeClassifTask(data = votesTib, target = "Class")#定义任务 bayes <- makeLearner("classif.naiveBayes")#定义学习者 bayesModel <- train(bayes, votesTask)#训练模型
模型训练完成没有错误,因为朴素贝叶斯可以处理缺失的数据。
接下来,使用 10-fold 交叉验证,重复 50 次来评估模型构建过程的性能。因为这是两分类问题,我们可以得到 fpr
和 fnr
(逻辑回归算法介绍过的二分类性能指标)。
kFold <- makeResampleDesc(method = "RepCV", folds = 10, reps = 50, stratify = TRUE) bayesCV <- resample(learner = bayes, task = votesTask, resampling = kFold, measures = list(mmce, acc, fpr, fnr)) bayesCV$aggr #mmce.test.mean acc.test.mean fpr.test.mean fnr.test.mean # 0.09808663 0.90191337 0.08125735 0.10862678
在交叉验证中,模型正确预测了 90% 的测试集实例,效果还不错。接下来可以使用该模型预测新实例所属政党:
politician <- tibble(V1 = "n", V2 = "n", V3 = "y", V4 = "n", V5 = "n", V6 = "y", V7 = "y", V8 = "y", V9 = "y", V10 = "y", V11 = "n", V12 = "y", V13 = "n", V14 = "n", V15 = "y", V16 = "n")#新实例数据 politicianPred <- predict(bayesModel, newdata = politician)#预测 getPredictionResponse(politicianPred) #[1] democrat #Levels: democrat republican
模型预测新的实例是民主党人。
小编有话说
本期主要介绍了朴素贝叶斯的基本内容和模型,该算法的优点之一是可以处理分类变量和连续变量的数据,而且不需要调参,使用过程较为简捷。下期内容小编将和大家一起学习支持向量机的内容,敬请期待!