我是 R 新手,正在尝试用更有效的东西替换附加代码块中的循环。对于上下文,这是具有多元(3 维)目标的 k 最近邻回归的简单综合示例。
rm(list=ls())
set.seed(1)
# Fast nearest neighbor package
library(FNN)
k <- 3
# Synthetic 5d predictor and noisy 3d target data
x <- matrix(rnorm(50), ncol=5)
y <- 5*x[,1:3] + matrix(rnorm(30), ncol=3)
print(x)
print(y)
# New synthetic 5d predictor data (4 cases)
x.new <- matrix(rnorm(20), ncol=5)
print(x.new)
# Identify k-nearest neighbors
nn <- knnx.index(data=x, query=x.new, k=k)
print(nn)
目前,我通过以下循环获取 k 最近邻 (nn) 的未加权平均值:
# Unweighted k-nearest neighbor regression predictions based on y and nn
y.new <- matrix(0, ncol=ncol(y), nrow=nrow(x.new))
for(i in 1:nrow(nn))
y.new[i,] <- colMeans(y[nn[i,],,drop=FALSE])
print(y.new)
但是必须有一个简单的方法来避免这里循环。谢谢。
最佳答案
在这些情况下,一个选择是构建一个大矩阵并操纵索引:
y2<-array(colMeans(matrix(y[t(nn),],nrow=ncol(nn))),dim(y.new))
identical(y2,y.new)
## [1] TRUE
在这种情况下,我的代码运行速度大约是你的两倍:
microbenchmark(
loop = for(i in 1:nrow(nn))
y.new[i,] <- colMeans(y[nn[i,],,drop=FALSE]),
matrix=y2<-array(colMeans(matrix(y[t(nn),],nrow=ncol(nn))),dim(y.new)))
## Unit: microseconds
## expr min lq median uq max neval
## loop 43.680 47.8805 49.1675 49.975 128.698 100
## matrix 23.807 25.4330 25.9985 26.761 80.491 100
这种情况下的循环并没有那么糟糕。一般来说,只要您在循环中执行大量工作(在本例中对矩阵进行子集化并调用 colMeans),那么每次迭代的开销与循环的实际内容相比就会很小。在 R 中真正需要避免循环的时候是每次迭代只执行少量工作的情况,在这种情况下,R 中迭代的开销将真正成为瓶颈,而避免循环可以显着提高性能。
循环的优点是你在做什么非常清楚,而我的代码却相当难以理解。然而,像这样进行矩阵索引操作通常会更快,有时会快很多,因为您只对 y
矩阵进行子集化一次,而不是每次循环一次。
关于替换 R 中的循环 : multivariate k-nearest neighbor regression example,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19284939/