e1071 包:naiveBayes 预测很慢
e1071 Package: naiveBayes prediction is slow
我正在尝试 运行 来自 R
包 e1071
的 naiveBayes
分类器。我 运行 遇到一个问题,即预测时间比训练时间长,大约是 300 倍。
我想知道是否还有其他人观察到这种行为,如果是,您是否有任何改进建议。
此问题仅在某些情况下出现。下面,我有代码在 Iris 数据集上训练和预测 NB 分类器。这里的训练和预测时间非常接近(预测时间长 10 倍而不是 300 倍)。我能在网上找到的关于此问题的唯一其他线索是 here。在这种情况下,答案是确保分类变量被格式化为因子。我已经这样做了,但仍然没有看到任何改进。
我试过样本大小 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()
我运行陷入同样的问题。我需要 运行 朴素贝叶斯并在一些大矩阵(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 在预测函数中如此缓慢的原因是因为它们本质上使用了双 for 循环。从 2017 年初左右开始,已经有一个 pull request 开放,至少矢量化了其中一个,但尚未被接受。
我正在尝试 运行 来自 R
包 e1071
的 naiveBayes
分类器。我 运行 遇到一个问题,即预测时间比训练时间长,大约是 300 倍。
我想知道是否还有其他人观察到这种行为,如果是,您是否有任何改进建议。
此问题仅在某些情况下出现。下面,我有代码在 Iris 数据集上训练和预测 NB 分类器。这里的训练和预测时间非常接近(预测时间长 10 倍而不是 300 倍)。我能在网上找到的关于此问题的唯一其他线索是 here。在这种情况下,答案是确保分类变量被格式化为因子。我已经这样做了,但仍然没有看到任何改进。
我试过样本大小 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()
我运行陷入同样的问题。我需要 运行 朴素贝叶斯并在一些大矩阵(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 在预测函数中如此缓慢的原因是因为它们本质上使用了双 for 循环。从 2017 年初左右开始,已经有一个 pull request 开放,至少矢量化了其中一个,但尚未被接受。