e1071软件包:朴素贝叶斯的预测速度较慢

4

我正在尝试运行Re1071中的naiveBayes分类器。我遇到了一个问题,预测所需的时间比训练所需的时间长得多,大约是300倍。

我想知道是否还有其他人观察到了这种情况,如果有的话,您是否有任何改进建议。

这个问题只在某些实例中出现。下面是在鸢尾花数据集上对NB分类器进行训练和预测的代码。在这里,训练和预测时间非常接近(预测需要10倍的时间而不是300倍)。我在网上找到的关于此问题的唯一其他痕迹是这里。在那个例子中,答案是确保分类变量格式化为因子。我已经这样做了,但仍然没有看到任何改进。

我已经尝试过不同的样本大小N,发现当N减小时,问题似乎会减轻。也许这是算法的预期行为?将N减小10倍时,预测只需要150倍的时间,但将其增加10倍时,预测速度仍然减慢了300倍。对我来说,这些数字似乎很不可思议,特别是因为我过去曾在包含约300,000个示例的数据集上使用此算法,并发现它非常快。有些可疑,但我无法找到原因。

我正在Linux上使用R版本3.3.1。 e1071包是最新的(2015年发布)。

下面的代码应该在任何计算机上都可以重现。我的机器在分类鸢尾花时计时为0.003秒,在预测鸢尾花时为0.032秒,在模拟数据分类时为0.045秒,而结果预测需要15.205秒。如果您得到与这些数字不同的数字,请让我知道,因为这可能是我本地机器上的某些问题。

# Remove everything from the environment and clear out memory
rm(list = ls())
gc()

# Load required packages and datasets
require(e1071)
data(iris)

# Custom function: tic/toc function to time the execution
tic <- function(gcFirst = TRUE, type=c("elapsed", "user.self", "sys.self"))
{
  type <- match.arg(type)
  assign(".type", type, envir=baseenv())
  if(gcFirst) gc(FALSE)
  tic <- proc.time()[type]         
  assign(".tic", tic, envir=baseenv())
  invisible(tic)
}

toc <- function()
{
  type <- get(".type", envir=baseenv())
  toc <- proc.time()[type]
  tic <- get(".tic", envir=baseenv())
  print(toc - tic)
  invisible(toc)
}

# set seed for reproducibility
set.seed(12345)

#---------------------------------
# 1. Naive Bayes on Iris data
#---------------------------------
tic()
model.nb.iris <- naiveBayes(Species~Sepal.Length+Sepal.Width+Petal.Length+Petal.Width,data=iris)
toc()
tic()
pred.nb.iris <- predict(model.nb.iris, iris, type="raw")
toc()

#---------------------------------
# 2. Simulate data and reproduce NB error
#---------------------------------
# Hyperparameters
L <- 5   # no. of locations
N <- 1e4*L

# Data
married        <- 1*(runif(N,0.0,1.0)>.45)
kids           <- 1*(runif(N,0.0,1.0)<.22)
birthloc       <- sample(1:L,N,TRUE)
major          <- 1*(runif(N,0.0,1.0)>.4)
exper          <- 15+4*rnorm(N)
exper[exper<0] <- 0
migShifter     <- 2*runif(N,0.0,1.0)-1
occShifter     <- 2*runif(N,0.0,1.0)-1
X <- data.frame(rep.int(1,N),birthloc,migShifter,occShifter,major,married,kids,exper,exper^2,exper^3)
colnames(X)[1] <- "constant"
rm(married)
rm(kids)
rm(birthloc)
rm(major)
rm(exper)
rm(occShifter)

# Parameters and errors
Gamma <- 15*matrix(runif(7*L), nrow=7, ncol=L)
eps <- matrix(rnorm(N*L, 0, 1), nrow=N, ncol=L)

# Deterministic portion of probabilities
u <- matrix(rep.int(0,N*L), nrow=N, ncol=L)
for (l in 1:L) {
    u[ ,l] = (X$birthloc==l)*Gamma[1,l] +
    X$major*Gamma[2,l]         + X$married*Gamma[3,l]              
    X$kids*Gamma[4,l]          + X$exper*Gamma[5,l]              
    X$occShifter*Gamma[6,l]    + X$migShifter*X$married*Gamma[7,l]
    eps[ ,l]
}

choice <- apply(u, 1, which.max)

# Add choice to data frame
dat <- cbind(choice,X)

# factorize categorical variables for estimation
dat$major      <- as.factor(dat$major)
dat$married    <- as.factor(dat$married)
dat$kids       <- as.factor(dat$kids)
dat$birthloc   <- as.factor(dat$birthloc)
dat$choice     <- as.factor(dat$choice)

tic()
model.nb <- naiveBayes(choice~birthloc+major+married+kids+exper+occShifter+migShifter,data=dat,laplace=3)
toc()
tic()
pred.nb <- predict(model.nb, dat, type="raw")
toc()

如果您不需要每个类别的后验概率条件,那么它会稍微快一些(在我的机器上,大约需要11秒,而不是15秒)。 - Sandipan Dey
1
更新:根据软件包维护者的说法,这些计算时间并不令人惊讶。一切似乎都按预期运行。 - Tyler R.
1
好的,但作为一种生成模型,它不应该比预测更需要训练时间吗?这有点违反直觉。 - Sandipan Dey
@SandipanDey:你能解释一下我们如何将这个存储在字典中以便快速查找吗? - Hardik Gupta
1
你可以查看其他朴素贝叶斯实现 :) https://cran.r-project.org/web/packages/naivebayes/index.html - Michal Majka
显示剩余5条评论
1个回答

3

我遇到了同样的问题。我需要在一些大矩阵上(10000行,1000-2000列)运行朴素贝叶斯并进行大量预测(1000次以上)。因为我有时间,所以我决定实现自己的朴素贝叶斯算法来使其更快:

https://cran.r-project.org/web/packages/fastNaiveBayes/index.html

我对此进行了一些工作,并创建了一个软件包:https://cran.r-project.org/web/packages/fastNaiveBayes/index.html。它使用伯努利事件模型,速度提高了约330倍。此外,它还实现了多项式事件模型(速度更快一些)和高斯模型(略微更快)。最后,还有一个混合模型,可以为不同的列使用不同的事件模型并将它们组合起来!
e1071在预测函数中非常缓慢,因为他们基本上使用双重循环。从2017年初就已经有一个拉取请求打开,至少向量化了其中之一,但尚未被接受。

1
听起来你应该向原始软件包源提交一个拉取请求! - Tyler R.
1
我做得更好,我将它制作成了自己的软件包:https://cran.r-project.org/web/packages/fastNaiveBayes/index.html - Martin Skogholt
我希望我能为你的这个贡献给予+100的声望值!! - Tyler R.

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接