1

double サイズ 19347 x 19347 の最大 110 の共分散行列を作成し、それらをすべて加算する必要があります。

これ自体はそれほど難しくなく、小さな行列の場合は次のコードで問題なく動作します。

covmat <- matrix(0, ncol=19347, nrow=19347)
files<-list.files("path/to/folder/")
for(name in files){
  text <- readLines(paste("path/to/folder/", name, sep=""),  n=19347, encoding="UTF-8")
   for(i in 1:19347){
    for(k in 1:19347){
      covmat[i, k]  <- covmat[i,k] + (as.numeric(text[i]) * as.numeric(text[k]))
    }
  }
}

メモリを節約するために、個々の行列を計算するのではなく、各ファイルをループするときにそれらを加算します。

問題は、使用する必要がある実際のデータで実行すると、時間がかかりすぎることです。実際にはそれほど多くのデータはありませんが、CPU とメモリを集中的に使用するジョブだと思います。したがって、約 10 時間実行しても結果は計算されません。

Map Reduce (AWS EMR) の使用を検討しましたが、ビッグデータの問題ではないため、これが Map Reduce の問題であるとは思わないという結論に達しました。ただし、これは私が遊んでいたマッパーとリデューサーのコードです。

#Mapper
text <- readLines("stdin",  n=4, encoding="UTF-8")
covmat <- matrix(0, ncol=5, nrow=5)

for(i in 1:5){
  for(k in 1:5){
     covmat[i, k]  <- (as.numeric(text[i]) * as.numeric(text[k]))
  }
}

cat(covmat)

#Reducer
trimWhiteSpace <- function(line) gsub("(^ +)|( +$)", "", line)
splitIntoWords <- function(line) unlist(strsplit(line, "[[:space:]]+"))
final <- matrix(0, ncol=19347, nrow=19347)
## **** could wo with a single readLines or in blocks
con <- file("stdin", open = "r")
while (length(line <- readLines(con, n = 1, warn = FALSE)) > 0) {

    line <- trimWhiteSpace(line)
    words <- splitIntoWords(line)
    final <- final + matrix(as.numeric(words), ncol=19347, nrow=19347)
}
close(con)
cat(final)

誰でもこの問題を解決する方法を提案できますか?

前もって感謝します

編集

以下のコメンターの何人かからの大きな助けのおかげで、コードを修正して、はるかに効率的になりました。

files<-list.files("path/to/file")
covmat <- matrix(0, ncol=19347, nrow = 19347)
for(name in files){
   invec <- scan(paste("path/to/file", name, sep=""))
   covmat <- covmat + outer(invec,invec, "*")
}

これは、私が処理しようとしているファイルの例です。

1       0.00114582882882883
2      -0.00792611711711709
...                     ...
19346  -0.00089507207207207
19347  -0.00704709909909909

プログラムを実行すると、ファイルごとに約 10 分かかります。これをスピードアップする方法について誰かアドバイスはありますか?

私は 8 GB の RAM を持っていますが、プログラムを実行すると、R はそのうちの 4.5 GB しか使用せず、少量の空き容量があります。

Mac OS X Snow Leopard と R 64bit v. 2.15 を実行しています。

4

2 に答える 2

4

あなたのループのロジックに懸念があります。基本的に covmat + outer(in.vec) である結果を計算しています。

   text <- c("1", "5", "8")
    for(i in 1:3){
     for(k in 1:3){
       covmat[i, k]  <-  (as.numeric(text[i]) * as.numeric(text[k]))
     }
   }
 covmat
     [,1] [,2] [,3]
[1,]    1    5    8
[2,]    5   25   40
[3,]    8   40   64
 outer(as.numeric(text),as.numeric(text), "*")
     [,1] [,2] [,3]
[1,]    1    5    8
[2,]    5   25   40
[3,]    8   40   64

それは間違いではありません.Rで大幅に単純化できるものであり、それが本当に必要な場合は、このベクトル化された関数で内側の2つのループ全体を置き換えることができます:

invec <- scan(paste("path/to/folder/", name, sep="")
covmat <- outer(invec,invec, "*")

また、連続するファイルの各結果を最も外側のループで上書きしていますが、これはあなたがやりたいと言ったことではありません。そのため、これらの行列を格納するデータ構造を決定する必要がある場合があります。自然な選択はリストです:

matlist <- list()
files<-list.files("path/to/folder/")
    for(name in files){
         invec <- scan(paste("path/to/folder/", name, sep="")
         covmat <- outer(invec,invec, "*")
         matlist[[name]] <- covmat
                      }

これで、「matlist」には、そのディレクトリにあるファイルと同じ数の行列が含まれているはずです。名前または入力順でアクセスできます。次の方法で名前を取得できます。

names(matlist)
于 2012-06-10T15:21:20.957 に答える
1

多分

covmat <- matrix(0, ncol=19347, nrow = 19347)
files <- paste("path/to/folder/", list.files("path/to/folder/"), sep = '')
for(name in files){
  vec <- scan(name,  nlines = 19347)
  mat <- outer(vec, vec, '*')
  covmat <- covmat + mat
}

私は推測していますが、多分あなたは本当に次のようなものを望んでいます...

numFiles <- 110
mat <- matrix(0, ncol= numFiles, nrow = 19347)
files <- paste("path/to/folder/", list.files("path/to/folder/"), sep = '')
for(i in 1:numFiles){
  mat[i,] <- scan(files[i],  nlines = 19347)
}
covmat <- cov(mat)
于 2012-06-10T14:48:11.927 に答える