我正在研究一些需要我反复计算大方阵的元素的东西。该过程涉及读取存储在另一个矩阵中的数据,然后计算矩阵元素。目前我正在使用双 for 循环来执行此操作。
library(matrixcalc)
data <- matrix(nrow=3,ncol=1000)
for(x in 1:ncol(data)){
for(y in 1:ncol(data)){
matrix[x,y]=exp(-entrywise.norm(data[,x]-data[,y],2))
}
}
问题在于,由于我的矩阵非常大,因此非常慢。这个程序最快的替代方法是什么?
答案 0 :(得分:3)
短而快:
mat <- exp(-as.matrix(dist(t(data))))
我还建议使用fields::rdist
函数作为计算欧氏距离矩阵的dist
的更快替代方法,因此如果加载包不是问题,请考虑:
library(fields)
mat <- exp(-rdist(t(data)))
为了让您了解提速:
data <- matrix(runif(3000), nrow=3, ncol=1000)
OP <- function(data) {
require(matrixcalc)
mat <- matrix(0, ncol(data), ncol(data))
for(x in 1:ncol(data)){
for(y in 1:ncol(data)){
mat[x,y]=exp(-entrywise.norm(data[,x]-data[,y],2))
}
}
mat
}
flodel1 <- function(data) exp(-as.matrix(dist(t(data))))
flodel2 <- function(data) {
require(fields)
exp(-rdist(t(data)))
}
system.time(res1 <- OP(data))
# user system elapsed
# 22.708 2.080 24.602
system.time(res2 <- flodel1(data))
# user system elapsed
# 0.112 0.025 0.136
system.time(res3 <- flodel2(data))
# user system elapsed
# 0.048 0.000 0.049
(请注意,在OP
和flodel2
的情况下,这些运行时不包括在测试之前加载的软件包的加载。)
答案 1 :(得分:2)
这应该快得多:
nc <- ncol(data)
mat <- diag(nc)
for(x in 2:nc){
for(y in 1:x){
mat[x, y] <- exp(-(sum((data[ , x] - data[ , y])^2) ^ .5))
}
}
mat[upper.tri(mat)] <- t(mat)[upper.tri(mat)]
答案 2 :(得分:1)
R语言使用 column-major-order 数组。更改for循环顺序可以提高性能。因为这样,您可以以更连续的形状访问内存,从而实现cpu-cache优势。
for(y in 1:dim) //outer is y now
{
for(x in 1:dim) //now x is count inside
{
matrix[x,y]=exp(-entrywise.norm(data[,x]-data[,y],2))
}
}
你的&#34;矩阵&#34;是2D阵列吗?
如果你需要更高的速度,你可以展开一些内部循环,以减少cpu的分支负载和更好的缓存/预取。
for(y in 1:dim)
{
for(x in 1:(dim/8)) //lets imagine dimension is a multiple of 8
{
matrix[x,y]=exp(-entrywise.norm(data[,x]-data[,y],2))
matrix[x+1,y]=exp(-entrywise.norm(data[,x+1]-data[,y],2))
matrix[x+2,y]=exp(-entrywise.norm(data[,x+2]-data[,y],2))
matrix[x+3,y]=exp(-entrywise.norm(data[,x+3]-data[,y],2))
matrix[x+4,y]=exp(-entrywise.norm(data[,x+4]-data[,y],2))
matrix[x+5,y]=exp(-entrywise.norm(data[,x+5]-data[,y],2))
matrix[x+6,y]=exp(-entrywise.norm(data[,x+6]-data[,y],2))
matrix[x+7,y]=exp(-entrywise.norm(data[,x+7]-data[,y],2))
}
}
答案 3 :(得分:1)
您可以使用colSums
代替内循环。根据@Sven Hohenstein的回答:
nc <- ncol(data)
mat <- diag(nc)
for(x in 2:nc){
mat[x, 1:x] <- exp(-(colSums((data[ , 1:x] - data[ ,x])^2) ^ .5))
}
mat[upper.tri(mat)] <- t(mat)[upper.tri(mat)]