R中两个大矩阵之间的行间差异

时间:2014-11-10 17:18:22

标签: r performance matrix

我想就如何加快以下操作提出意见。

我有两个矩阵说A和B有n行3列;对于A的任何行向量,我想比较它与B的任何行向量的差异。因此,它是两个矩阵的所有行向量之间的成对差异。然后,得到的矩阵是n * n矩阵。然后我想将一个函数应用于我在该示例中编写的biharm()函数的任何元素。问题在于,对于小矩阵我没有问题,我有必要将这个操作应用于非常大的矩阵,如1000 * 3。在我写的sigm()函数中,我首先初始化S然后我写了两个为循环编写的。但是,对于大型矩阵来说这很慢。有没有人知道如何加快这个?我认为使用apply()但我无法弄清楚正确的方法。下面是一个完全可重复的例子。提前感谢任何建议。最好的,保罗。

biharm<-function(vec1,vec2){
  reso<-norm(as.matrix(vec1)-as.matrix(vec2),type="F")^2*log(norm((as.matrix(vec1)-as.matrix(vec2)),type="F"))
  reso
}
sigm<-function(mat1,mat2=NULL){
  tt<-mat1
  if(is.null(mat2)){yy<-mat1}else{yy<-mat2}
  k<-nrow(yy)
  m<-ncol(yy)
  SGMr<-matrix(rep(0,k^2),ncol=k)
  for(i in 1:k){
    for(j in 1: k){
      SGMr[i,j]<-biharm(yy[i,],tt[j,])
    }}
  SGMr<-replace(SGMr,which(SGMr=="NaN",arr.ind=T),0)
  return(SGMr)}


### small matrices example:
A<-matrix(rnorm(30),ncol=3)
B<-matrix(rnorm(30),ncol=3)
sigm(A,B)

### large matrices example:
A<-matrix(rnorm(900),ncol=3)
B<-matrix(rnorm(900),ncol=3)
sigm(A,B)

2 个答案:

答案 0 :(得分:1)

这比我的系统快8倍。

biharm.new <- function(vec1,vec2){
  n <- sqrt(sum((vec1-vec2)^2))
  n^2*log(n)
}

sigm.new<-function(mat1,mat2=NULL){
  tt<-mat1
  if(is.null(mat2)){yy<-mat1}else{yy<-mat2}
  SGMr <- apply(tt,1,function(t)apply(yy,1,biharm.new,t))
  replace(SGMr,which(SGMr=="NaN",arr.ind=T),0)
}
### large matrices example:
set.seed(1)
A<-matrix(rnorm(900),ncol=3)
B<-matrix(rnorm(900),ncol=3)
system.time(result.1<-sigm(A,B))
#    user  system elapsed 
#    6.13    0.00    6.13 
system.time(result.2<-sigm.new(A,B))
#    user  system elapsed 
#    0.81    0.00    0.81 
all.equal(result.1,result.2)
# [1] TRUE

apply(...)的使用效果提高了约3倍。剩下的工作来自优化biharm(...) - 因为你要拨打810,000次,所以要尽可能高效。

请注意,Frobenius规范只是欧几里德范数,所以如果您真正想要使用sqrt(sum(x^2))而不是转换为矩阵并使用norm(...)。前者很多更快。

答案 1 :(得分:0)

这个怎么样:

set.seed(1)
foo<-matrix(runif(30),nc=3)
bar<-matrix(runif(30),nc=3)

sapply(1:10,function(j) sapply(1:10,function(k) biharm(bar[k,],foo[j,])) )

编辑 - 与jhoward的“sigm.new”基本相同,没有错误检查。显然biharm.new是胜利者。

microbenchmark(carl(foo,bar),jhoward(foo,bar),times=3)
Unit: milliseconds
              expr       min       lq    median       uq      max neval
    carl(foo, bar) 5846.8273 6071.364 6295.8999 6322.425 6348.951     3
 jhoward(foo, bar)  891.5734  934.550  977.5267 1008.388 1039.248     3