【问题标题】:Is the Epanechnikov kernel really computationally more efficient that the Gaussian kernel?Epanechnikov 核在计算上真的比高斯核更有效吗?
【发布时间】:2021-08-03 22:45:13
【问题描述】:

我正在实现一个函数来估计单变量和多变量情况下的核密度估计。就此而言,我使用的是高斯内核,即使处理大量数据集,它也能很好地工作。然而,许多人声称我应该使用 Epanechnikov 内核,因为它的计算效率更高,因为它支持紧凑。但我不同意,或者,至少,我还没有找到一种方法来实现它,以便它击败高斯。 这是我的代码,用于对实数中点 x_o 处的密度进行高斯估计,相对于值 x 的向量:

dens_point <- function(x_0, x, width){
  weights <- (1/sqrt(2*pi))*exp(-(1/2)*(((x_0-x)/width)^2))
  return((1/(length(x)*width))*sum(weights))
}

甚至更高效,

dens_point <- function(x_0, x, width){
  constant <- (1/sqrt(2*pi)
  weights <- constant*exp(-0.5*(((x_0-x)/width)^2)))
  return((1/(length(x)*width))*sum(weights))
}

或者更进一步,以牺牲可读性为代价:

dens_point <- function(x_0, x, width){
  constant <- (1/sqrt(2*pi)
  return(
     (1/(length(x)*width))*sum(constant*exp(-0.5*(((x_0-x)/width)^2))))
  )
}

为了获得区间上的线,我只需对参数x_0 上的函数进行矢量化,并给它一个值序列。这是我能带来的效率。相比之下,Epanechnikov 内核要慢得多。我试过以下代码:

epanechnikov <- function(u){
  if (u <= 1){
    return(0)
  } else {
    return( (1-u^2)*0.75 )
  }
}
epanechnikov <- Vectorize(epanechnikov)

dens_point <- function(x0, x, width){
  weights <- epanechnikov( (x0-x)/width )
  return( (1/(length(x)*width)*sum(weights) )
}

但是这个解比高斯解差到极点,却是我能想到的最精炼的表达方式。 For 循环和 sapplies 甚至更慢。我想说高斯函数非常快,因为它使用了基本的 R 向量运算,这是 Vectorize() 无法与之竞争的。你能想出一个更快的代码吗?

【问题讨论】:

  • 要利用 Epanechnikov 内核的有界支持,需要能够有效地确定哪些点属于支持(因此您排除任何其他点)。这样做可能意味着用于存储数据点的专用结构(可能是一种树),因此在有限区域中查找数据点不需要扫描所有点(否则您将返回与成比例的操作数量数据的数量)。遇到这么多麻烦可能意味着相当大的数据集(数百万到数十亿)。
  • @RobertDodier 我非常同意。我最好的选择可能是首先对值进行排序,然后开始计算权重,当达到最后一个值严格为正且当前值为零的点时,然后停止并将以下所有点设为零价值。

标签: r statistics kernel-density


【解决方案1】:

确实,Vectorize 无法与矢量化函数竞争。因此,只需使用基本功能:

epanechnikov2 <- function(u) {
  k <- (1-u^2) * 0.75
  k[u <= 1] <- 0
  k
}

或者稍微快一点[编辑:并且使用更少的内存]:

epanechnikov3 <- function(u) {
  k <- (1-u^2) * 0.75
  (abs(k) + k) / 2
}

【讨论】:

  • 这很巧妙,但高斯内核仍然至少与您定义的函数一样有效。我想说的是,Epanechnikov 的紧凑支持的优点是您不需要为那些u&gt;=1 计算(1-u^2) * 0.75。无论如何,使用您的答案,您仍然必须为所有元素计算(1-u^2) * 0.75,因此在计算能力方面没有胜利。但我想这是朝着这个方向迈出的一步。
  • @morphicphicus 是的,这是一个公平的观点。一种选择是迁移到 C++(即Rcpp);我现在没有时间写它,但如果没有人尽快回复,我可以稍后尝试。
  • 计算指数的计算成本是否进入这个比较? microbenchmark::microbenchmark(exp(-x^2), 1-x^2) 表示多项式需要大约 75% 的时间...
猜你喜欢
  • 1970-01-01
  • 2015-08-28
  • 2013-09-15
  • 1970-01-01
  • 1970-01-01
  • 2012-03-07
  • 2015-11-13
  • 1970-01-01
相关资源
最近更新 更多