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

対称行列はまばらです。結局のところ、1つの三角形と対角線を保存するだけです。私のシステムでは、 '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] –

関連する問題