2017-04-06 12 views
1

대칭 행렬을 만들기 위해 반복을 줄임으로써 시간과 메모리 사용을 줄이고 싶습니다. (이전에는이 ​​행을 사용했지만 메모리는 더 많이 소비했습니다) 즉 sol[i, j]은 다음과 같습니다. sol[j, i]. 지금까지대칭 행렬을 만드는 루프

내 코드 :

# Prepare input 
subss <- list(a = c(1, 2, 4), b = c(1, 2, 3), c = c(4, 5)) 
A <- matrix(runif(25), ncol = 5, nrow = 5) 
# Pre allocate memory 
sol <- matrix(nrow = length(subss), ncol = length(subss), 
      dimnames = list(names(subss), names(subss))) 
x <- 0 
for (i in seq_along(subss)) { 
    # Omit for the subsets I already calculated ? 
    for (j in seq_along(subss)) { 
     x <- x + 1 
     message(x) 

     # The function I use here might result in a NA 
     sol[i, j] <- mean(A[subss[[i]], subss[[j]]]) 
     sol[j, i] <- sol[i, j] # Will overwrite when it shouldn't 
    } 
} 

9 반복을 사용할 것인가, 어떻게 그들을 피하기 그냥 6 반복을 할 수 있습니까?

대칭 값을 계산해야하므로 this question이 적용되지 않습니다. 또한이 other one은 여러 가지 조합이있을 수 있으며 어느 시점에서 벡터를 메모리에 할당 할 수 없기 때문에 작동하지 않습니다.

+0

아니요, 처음에는 서브를 사용하지 않으므로 제안하는 차원은 3x3이 아니라 5x5입니다. 평균 대신 실제 함수가 더 복잡합니다 – Llopis

답변

0

for 루프는 일반적으로 outer보다 느립니다. 루프를 바이트 컴파일하거나 Rcpp에 구현하십시오.

subss <- list(a = c(1, 2, 4), b = c(1, 2, 3), c = c(4, 5)) 
set.seed(42) 
A <- matrix(runif(25), ncol = 5, nrow = 5) 

#all combinations of indices 
ij <- combn(seq_along(subss), 2) 

#add all i = j 
ij <- matrix(c(ij, rep(seq_along(subss), each = 2)), nrow = 2) 

#preallocate 
res <- numeric(ncol(ij)) 

#only one loop 
for (k in seq_len(ncol(ij))) { 

    message(k) 

    res[k] <- mean(A[subss[[ij[1, k]]], subss[[ij[2, k]]]]) 
} 
#1 
#2 
#3 
#4 
#5 
#6 

#create symmetric sparse matrix  
library(Matrix) 
sol <- sparseMatrix(i = ij[1,], j = ij[2,], 
        x = res, dims = rep(length(subss), 2), 
        symmetric = TRUE, index1 = TRUE) 
#3 x 3 sparse Matrix of class "dsCMatrix" 
#         
#[1,] 0.7764715 0.6696987 0.7304413 
#[2,] 0.6696987 0.6266553 0.6778936 
#[3,] 0.7304413 0.6778936 0.5161089 
+0

어떻게 작동하는지 테스트 해 보겠습니다. 그러나 subs는 20000 길다 그래서 모든 조합은 아주 크다. 또한 의존성을 피하려고 노력하고 행렬이 희소하지 않고 어떤 이점을 가져다 줍니까? 그것은 더 효율적으로 저장됩니까? – Llopis

+0

대칭 행렬이 희박합니다. 결국, 하나의 삼각형과 대각선 만 저장하면됩니다. 우리 시스템에서는'i'와'j'의 4 억 가지 조합을 계산하는 데 약 1 분이 걸립니다. 귀하의 성능 문제는 귀하의 기능에 대한 4 억 건의 전화가 될 가능성이 큽니다. 이 작업을 정말로 수행해야하는지 정말 고려해야하며 작업을 수행하는 경우 작업에 Rcpp를 사용해야합니다. – Roland

+0

시간은별로 제약이 없습니다 ('외부'는 데이터에 따라 ~ 5 시간 안에 완료됩니다). 그러나 메모리는 (외부에서 프로세스가 htop로 측정했을 때 91Gb에 도달합니다.) 이것이 내가 생각한 이유입니다. 루프를 사용하여 메모리에서 외부의 모든 하위 집합을 갖지 못하게합니다. 그러나 나는 당신이 말한 것처럼 함수를 Rcpp로 옮길 수 있습니다. – Llopis

0

나는 루프에 대한 일반과 방법을 발견 :

x <- 0 
for (i in seq_along(subss)) { 
    for (j in seq_len(i)) { # or for (j in 1:i) as proposed below 
     x <- x + 1 
     message(x) 

     sol[i, j] <- mean(A[subss[[i]], subss[[j]]]) 
     sol[j, i] <- sol[i, j] 
    } 
} 
+1

'for (j in 1 : i)' – Roland

0
for (i in 1:length(subss)) { 
    for (j in 1:i) { 
    message(i, ' ', j, ' - ', mean(A[subss[[i]], subss[[j]]])) # Check iterations and value 
    sol2[i, j] <- sol2[j, i] <- mean(A[subss[[i]], subss[[j]]]) 
    } 
} 

나는 스크립트 값을 확인하고 대칭되지 않습니다

1 1 - 0.635455905252861 
1 2 - 0.638608284398086 
1 3 - 0.488700995299344 
2 1 - 0.568414432255344 
2 2 - 0.602851431118324 
2 3 - 0.516099992596234 
3 1 - 0.595461705311512 
3 2 - 0.656920690399905 
3 3 - 0.460815121419728 

광산 값 (@ 동일 Llopis) :

1 2 - 0.638608284398086 
1 3 - 0.488700995299344 
2 2 - 0.602851431118324 
2 3 - 0.516099992596234 
3 2 - 0.656920690399905 
3 3 - 0.460815121419728 
+0

이 답변이 기존 답변에서 향상된다는 것을 이해하지 못합니다. 어느 값이 어느 값과 같지 않습니까? – Llopis

+0

원래 게시물의 값 : [1 대 3 - 0.488, 3 대 1 - 0.595], [1 대 2 - 0.638, 2 1 - 0.568] –