查询包e1071中的朴素贝叶斯算法R

时间:2016-03-09 12:39:09

标签: r statistics bayesian naivebayes

下面是我在R中使用Naive Bayes实现的训练数据集(使用e1071包),其中:X,Y,Z是不同的类,V1,V2,V3,V4,V5是属性: - < / p>

Class   V1  V2  V3  V4  V5
X       Yes Yes No  Yes Yes
X       Yes Yes No  No  Yes
X       Yes Yes No  No  Yes
X       Yes Yes No  No  Yes
X        No Yes No  No  Yes
X        No Yes No  No  Yes
X        No Yes No  No  Yes
X        No No  No  No  No
X        No No  No  No  No
X        No No  No  No  No
X        No No  No  No  No
X        No No  No  No  No
X        No No  No  No  No
X        No No  No  No  No
X        No No  No  No  No
X        No No  No  No  No
Y       Yes Yes Yes No  Yes
Y        No No  No  No  Yes
Y        No No  No  No  Yes
Y        No No  No  No  No
Y        No No  No  No  No
Y        No No  No  No  No
Y        No No  No  No  No
Z        No Yes Yes No  Yes
Z        No No  No  No  Yes
Z        No No  No  No  Yes
Z        No No  No  No  No
Z        No No  No  No  No
Z        No No  No  No  No
Z        No No  No  No  No

上述数据集的先验概率为X-> 0.5333333 Y-> 0.2333333 Z-> 0.2333333

并且条件概率是: -

V1
Y          No       Yes
   X 0.7500000 0.2500000
   Y 0.8571429 0.1428571
   Z 1.0000000 0.0000000

V2
Y          No       Yes
   X 0.5625000 0.4375000
   Y 0.8571429 0.1428571
   Z 0.8571429 0.1428571

V3
 Y          No       Yes
   X 1.0000000 0.0000000
   Y 0.8571429 0.1428571
   Z 0.8571429 0.1428571

V4
 Y       No    Yes
   X 0.9375 0.0625
   Y 1.0000 0.0000
   Z 1.0000 0.0000

V5
 Y          No       Yes
   X 0.5625000 0.4375000
   Y 0.5714286 0.4285714
   Z 0.5714286 0.4285714

案例1: - 未使用拉普拉斯平滑

我想知道V3属于哪个类,给定值是。所以我的测试数据为: -

V3
Yes

所以,我必须找出每个类的概率,即概率(X | V3 =是),概率(Y | V3 =是),概率(Z | V3 =是)并取出三个中的最大值。现在,

概率(X | V3 =是)=概率(X)*概率(V3 =是| X)/ P(V3)

根据上述条件概率,我们知道概率(V3 = Yes | X)= 0 因此,概率(X | V3 =是)应为0且概率(Y | V3 =是),概率(Z | V3 =是)应为0.5。

但在R输出中是不同的。从包e1071我使用了naiveBayes功能。下面是代码及其相应的输出: -

#model_nb<-naiveBayes(Class~.,data = train,laplace=0)
#results<-predict(model_nb,test,type = "raw")
#print(results)

#         X         Y         Z
#[1,] 0.5714286 0.2142857 0.2142857

有人可以解释一下为什么这是R中的输出?

案例2: - 使用拉普拉斯平滑

与Case1 w.r.t相同的情况。测试数据,只有laplace使用的区别是1.所以,我必须再次找出每个类的概率,即概率(X | V3 =是),概率(Y | V3 =是),概率(Z | V3 =是并从三个中取出最大值。

以下是拉普拉斯平滑后的条件概率(k = 1)

V1
Y          No       Yes
   X 0.7222222 0.2777778
   Y 0.7777778 0.2222222
   Z 0.8888889 0.1111111

V2
Y          No       Yes
   X 0.5555556 0.4444444
   Y 0.7777778 0.2222222
   Z 0.7777778 0.2222222

V3
Y          No        Yes
   X 0.94444444 0.05555556
   Y 0.77777778 0.22222222
   Z 0.77777778 0.22222222

V4
Y          No       Yes
   X 0.8888889 0.1111111
   Y 0.8888889 0.1111111
   Z 0.8888889 0.1111111

V5
Y          No       Yes
   X 0.5555556 0.4444444
   Y 0.5555556 0.4444444
   Z 0.5555556 0.4444444

从幼稚的贝叶斯定义,

概率(X | V3 =是)=概率(X)*概率(V3 =是| X)/ P(V3)

概率(Y | V3 =是)=概率(Y)*概率(V3 =是| X)/ P(V3)

概率(Z | V3 =是)=概率(Z)*概率(V3 =是| X)/ P(V3)

我有计算后,

概率(X | V3 =是)= 0.53 * 0.05555556 / P(V3)= 0.029 / P(V3)

概率(Y | V3 =是)= 0.23 * 0.22222222 / P(V3)= 0.051 / P(V3)

概率(Z | V3 =是)= 0.23 * 0.22222222 / P(V3)= 0.051 / P(V3)

从上面的计算中,Y和Z之间应该有一个联系。但是在R输出中是不同的。类X显示为输出类。下面是代码及其相应的输出: -

#model_nb<-naiveBayes(Class~.,data = train,laplace=1)
#results<-predict(model_nb,test,type = "raw")
#print(results)


#        X         Y         Z
#[1,] 0.5811966 0.2094017 0.2094017

再次,有人可以解释为什么这样的输出在R?我的计算在任何地方都会出错吗?

另外,需要一些关于如何在完成拉普拉斯平滑时计算P(V3)的解释。

提前致谢!

2 个答案:

答案 0 :(得分:1)

问题是您只使用一个样本作为测试数据集,只有一个值V3。如果您提供更多测试数据,您将获得合理/预期的结果(仅关注案例1 ):

test <- data.frame(V3=c("Yes", "No"))
predict(model_nb, test, type="raw")
               X         Y         Z
[1,] 0.007936508 0.4960317 0.4960317
[2,] 0.571428571 0.2142857 0.2142857

请注意,对于V3 =&#34;是&#34;,您不能得到0,0.5,0.5,因为该功能正在使用您可以调整的阈值,请执行?predict.naiveBayes以获取更多信息资讯

问题实际上是由于predict.naiveBayes的内部实现(源代码位于CRAN存储库)。我不打算详细介绍所有细节,但基本上我已经调试了这个功能,并且在某个步骤中有这条线,

newdata <- data.matrix(newdata)

稍后将决定使用哪个条件概率列。使用原始数据,data.matrix看起来像这样:

data.matrix(data.frame(V3="Yes"))
     V3
[1,]  1

因此它后来假定条件概率取自第1列,即V3 =&#34; No&#34;的值为1.0000000,0.8571429和0.8571429,这就是为什么你得到的结果为如果V3实际上是&#34;否&#34;。

然而,

data.matrix(data.frame(V3=c("Yes", "No")))
     V3
[1,]  2
[2,]  1
当p是&#34;是&#34;时,

给出条件概率的第2列,从而得到正确的结果。

我很确定您的案例2 只是类似的。

希望它有所帮助。

评论后编辑:我想解决问题的更简单方法是将所有数据放在一个data.frame中,然后选择用于培训/测试模型的索引。许多函数接受subset来选择用于训练的数据,naiveBayes也不例外。但是,对于predict.naiveBayes,您必须选择索引。这样的事情。

all_data <- rbind(train, c(NA, NA, NA, "Yes", NA, NA))
trainIndex <- 1:30
model_nb <- naiveBayes(Class~., data=all_data, laplace=0, subset=trainIndex)
predict(model_nb, all_data[-trainIndex,], type="raw")

给出了预期的结果。

               X         Y         Z
[1,] 0.007936508 0.4960317 0.4960317

请注意,这是有效的,因为在这种情况下,当您执行data.matrix操作时,您会得到正确的结果。

data.matrix(all_data[-trainIndex,])
   Class V1 V2 V3 V4 V5
31    NA NA NA  2 NA NA

评论后的EDIT2:有关原因的详细信息。

当您定义的test数据框只包含一个等于&#34;否&#34;的值时,data.matrix执行的转换实际上无法知道您的变量{{1}有2个可能的值,&#34;是&#34;和&#34;不&#34;。 V3实际上是一个因素:

test$V3

并且据说它只有一个级别(data.frame无法知道实际上有2个级别)

test <- data.frame(V3="Yes")
class(test$V3)
[1] "factor"

levels(test$V3) [1] "Yes" 的实施,正如您在docs中看到的那样,使用了因素的级别:

  

因子和有序因素被其内部代码所取代。

因此,当将测试转换为data.matrix时,它会解释因子只有一个可能的值并对其进行解码,

data.matrix

但是,当您将训练和测试放入同一数据帧时,可以正确定义因子级别。

data.matrix(test)
     V3
[1,]  1

如果您这样做,结果将是相同的:

levels(all_data$V3)
[1] "No"  "Yes"

答案 1 :(得分:1)

我遇到了同样的问题,它确实所有关于因素!您必须在训练数据和为预测提供的新数据之间同步因子水平。 (正如Rinzcig在上面的“编辑2”中所述。)

e1071中的朴素贝叶斯函数将所有字符数据转换为因子。您必须控制此转换,否则您将获得意外结果。

这只是您需要的这一行代码:

test <- data.frame(V3=factor("Yes", levels=levels(all_data$V3)))

你可以看到我有same issue and solution here.