2つのループがあります:1つはnmf.rank
に、1つは1:resamp.iterations
にあります。したがって、i
とn
の両方をnmf.sub
に渡す必要があります。以下のように:効率は約(以下)コメントについて
nmf.sub <- function(n, i){
## the index is a permutation of the original matrix at a 0.8
## resampling proportion (doesn't really matter)
sub.data.matrix <- data.matrix[, (index[n, ])]
## want to change 2 to i
temp.result <- nmf(sub.data.matrix, rank = i, seed = 12345)
return(temp.result)
}
resamp.iterations <- 10
nmf.rank <- 2:4
res <- lapply(nmf.rank, function(i){
results.list <- mclapply(mc.cores = 16, 1:resamp.iterations,
function(n) nmf.sub(n,i))
})
## then you can flatten/reshape res
:数値計算の大部分は意味では、従ってループが適切に設定され、NMF()関数内で実行される各プロセス/コア数値的に集中的な仕事を得る。しかし、計算を高速化するためには、シード12345の代わりに以前に計算した結果を使用することを検討することもできます(後者のシードを使用するのは何らかの理由で必須です)。次の例では、実行時間が30〜40%短縮されます。
library(NMF)
RNGkind("L'Ecuyer-CMRG") ## always use this when using mclapply()
nr <- 19
nc <- 2e2
set.seed(123)
data.matrix <- matrix(rexp(nc*nr),nr,nc)
resamp.iterations <- 10
nmf.rank <- 2:4
index <- t(sapply(1:resamp.iterations, function(n) sample.int(nc,nc*0.8)))
nmf.sub <- function(n, i){
sub.data.matrix <- data.matrix[ ,index[n, ]]
temp.result <- nmf(sub.data.matrix, rank = i, seed = 12345)
return(temp.result)
}
## version 1
system.time({
res <- lapply(nmf.rank, function(i){
results.list <- mclapply(mc.cores = 16, 1:resamp.iterations,
function(n) nmf.sub(n,i))
})
})
## version 2: swap internal and external loops
system.time({
res <-
mclapply(mc.cores=16, 1:resamp.iterations, function(n){
res2 <- nmf(data.matrix[ ,index[n, ]], rank=2, seed = 12345)
res3 <- nmf(data.matrix[ ,index[n, ]], rank=3, seed = 12345)
res4 <- nmf(data.matrix[ ,index[n, ]], rank=4, seed = 12345)
list(res2,res3,res4)
})
})
## version 3: use previous calculation as starting point
## ==> 30-40% reduction in computing time
system.time({
res <-
mclapply(mc.cores=16, 1:resamp.iterations, function(n){
res2 <- nmf(data.matrix[ ,index[n, ]], rank=2, seed = 12345)
res3 <- nmf(data.matrix[ ,index[n, ]], rank=3, seed = res2)
res4 <- nmf(data.matrix[ ,index[n, ]], rank=4, seed = res3)
list(res2,res3,res4)
})
})
治療のように機能しました!ありがとう! これを実行する最も効率的な方法であるかどうかは分かりますか。私はダミー行列を使って関数を作っていますが、実際の行列は191 x 20000のようなものになり、反復は1000に設定されます –
上記の編集をご覧ください。最高の再現性を得るために、私は常に '' RNGkind( "L'Ecuyer-CMRG")をmclapply()または他の並列ライブラリで使用します。 –
シードは、我々が生物学的データをクラスタリングしているので再現性のために行うものであり、我々はある程度の再現を望んでいる。 あなたのコメントは非常に参考になります。これを私のコードに追加します。 –