在循环中使用kernlab包中的rbfdot表现不佳

use*_*616 2 performance r

我需要加速的缓慢工作代码(函数rbf来自kernlab包)的简化示例:

install.packages('kernlab')       
library('kernlab')

rbf <- rbfdot(sigma=1)

test <- matrix(NaN,nrow=5,ncol=10)
for (i in 1:5) {
               for (j in 1:10) { test[i,j] <- rbf(i,j)}
               }
Run Code Online (Sandbox Code Playgroud)

我试过outer()但它不起作用,因为该rbf函数没有返回所需的长度(50).我需要加快这个代码的速度,因为我有大量的数据.我已经读过,矢量化将是加速这一过程的圣杯,但我不知道如何.

你能指点我正确的方向吗?

Ric*_*ton 8

如果rbf确实是来自调用的返回值rbfdot,那么body(rbf)看起来像

{
    if (!is(x, "vector")) 
        stop("x must be a vector")
    if (!is(y, "vector") && !is.null(y)) 
        stop("y must a vector")
    if (is(x, "vector") && is.null(y)) {
        return(1)
    }
    if (is(x, "vector") && is(y, "vector")) {
        if (!length(x) == length(y)) 
            stop("number of dimension must be the same on both data points")
        return(exp(sigma * (2 * crossprod(x, y) - crossprod(x) - 
            crossprod(y))))
    }
}
Run Code Online (Sandbox Code Playgroud)

由于大部分内容都是由检查函数组成,并crossprod简化了当你只传入标量时,我认为你的函数简化为

rbf <- function(x, y, sigma = 1)
{
  exp(- sigma * (x - y) ^ 2)
}
Run Code Online (Sandbox Code Playgroud)

要进一步加速,请使用compiler包(需要R-2.14.0或更高版本).

rbf_loop <- function(m, n)
{
  out <- matrix(NaN, nrow = m, ncol = n)
  for (i in seq_len(m)) 
  {
    for (j in seq_len(n)) 
    { 
      out[i,j] <- rbf(i,j)
    }
  }
  out
)

library(compiler)
rbf_loop_cmp <- cmpfun(rbf_loop)
Run Code Online (Sandbox Code Playgroud)

然后比较rbf_loop_cmp(m, n)你之前的时间.


简化步骤更容易反过来看.如果你扩展 (x - y) ^ 2你得到x ^ 2 - 2 * x * y + y ^ 2,这是减去rbf函数中的东西.