2012-09-08 18 views
5

में एक बड़े मैट्रिक्स केंद्र मैं केंद्र के लिए एक बड़े मैट्रिक्स है कि मैं करना चाहते हैं:कुशलतापूर्वक आर

X <- matrix(sample(1:10, 5e+08, replace=TRUE), ncol=10000) 

ढूँढना साधन त्वरित और colMeans साथ कुशल है:

means <- colMeans(X) 

लेकिन क्या एक प्रत्येक कॉलम से संबंधित माध्य घटाने के लिए अच्छा (तेज़ और मेमोरी कुशल) तरीका? यह काम करता है, लेकिन यह सही नहीं लगता:

for (i in 1:length(means)){ 
    X[,i] <- X[,i]-means[i] 
} 

क्या कोई बेहतर तरीका है?

/संपादन: यहाँ एक संशोधन विभिन्न मानक DWin लिखा है, एक बड़ा मैट्रिक्स पर, सुझाव अन्य तैनात सहित:

require(rbenchmark) 
X <- matrix(sample(1:10, 5e+07, replace=TRUE), ncol=10000) 
frlp.c <- compiler:::cmpfun(function(mat){ 
    means <- colMeans(mat) 
    for (i in 1:length(means)){ 
    mat[,i] <- mat[,i]-means[i] 
    } 
    return(mat) 
}) 

mat.c <- compiler:::cmpfun(function(mat){ 
    t(t(X) - colMeans(X)) 
}) 

swp.c <- compiler:::cmpfun(function(mat){ 
    sweep(mat, 2, colMeans(mat), FUN='-') 
}) 

scl.c <- compiler:::cmpfun(function(mat){ 
    scale(mat, scale=FALSE) 
}) 

matmult.c <- compiler:::cmpfun(function(mat){ 
    mat-rep(1, nrow(mat)) %*% t(colMeans(mat)) 
}) 

benchmark( 
    frlp.c=frlp.c(X), 
    mat=mat.c(X), 
    swp=swp.c(X), 
    scl=scl.c(X), 
    matmult=matmult.c(X), 
    replications=10, 
    order=c('replications', 'elapsed')) 

matmult समारोह नया विजेता हो रहा है! मैं वास्तव में इन्हें 5e + 08 तत्व मैट्रिक्स पर आज़माकर देखना चाहता हूं, लेकिन मैं रैम से बाहर चल रहा हूं।

 test replications elapsed relative user.self sys.self user.child sys.child 
5 matmult   10 11.98 1.000  7.47  4.47   NA  NA 
1 frlp.c   10 35.05 2.926  31.66  3.32   NA  NA 
2  mat   10 50.56 4.220  44.52  5.67   NA  NA 
4  scl   10 58.86 4.913  50.26  8.42   NA  NA 
3  swp   10 61.25 5.113  51.98  8.64   NA  NA 
+0

शायद 'स्केल' मज़ेदार आपकी मदद कर सकता है। 'स्केल' देखें। एक और उपयोगी काम 'स्वीप' हो सकता है। –

+0

@Jiber: स्केल फ़ंक्शन ऊपर लूप के मुकाबले बहुत धीमा है। हालांकि, काम करना चाहिए, धन्यवाद! – Zach

+0

'वूबर' कौन है? 'बेंचमार्क' समारोह Wacek Kusnierczyk द्वारा लिखा गया था। –

उत्तर

6

यह दोगुनी गति से sweep() के रूप में के बारे में हो रहा है।

X - rep(1, nrow(X)) %*% t(colMeans(X)) 

X <- matrix(sample(1:10, 5e+06, replace=TRUE), ncol=10000) 
system.time(sweep(X, 2, colMeans(X))) 
    user system elapsed 
    0.33 0.00 0.33 
system.time(X - rep(1, nrow(X)) %*% t(colMeans(X))) 
    user system elapsed 
    0.15 0.03 0.19 

DWin संपादित करें: जब मैं ओ पी इस्तेमाल किया (केवल 5e +07) जहां जोश mat2 है मैं, इन समय मिल तुलना में एक छोटे मैट्रिक्स के साथ ऐसा किया (बड़ा एक आभासी स्मृति में अपने Mac पर overflowed w/32GB और जरूरत समाप्त हो):

test replications elapsed relative user.self sys.self user.child sys.child 
2 mat2   1 0.546 1.000000  0.287 0.262   0   0 
3 mat   1 2.372 4.344322  1.569 0.812   0   0 
1 frlp   1 2.520 4.615385  1.720 0.809   0   0 
4 swp   1 2.990 5.476190  1.959 1.043   0   0 
5 scl   1 3.019 5.529304  1.984 1.046   0   0 
+0

मैं भीड़ में हूं या मैं कुछ बेहतर समय प्रदर्शन करता हूं। कृपया, अगर आप उन्हें निष्पादित करते हैं तो कोई भी मुझे अपने उत्तर में जोड़ने के लिए स्वतंत्र महसूस करता है। –

+0

धन्यवाद एक गुच्छा, @Dwin। यह देखने के लिए वास्तव में दिलचस्प है कि सरल मैट्रिक्स ऑपरेशंस कितनी तेजी से हैं। –

6

क्या यह आपके लिए उपयोगी हो सकता है?

sweep(X, 2, colMeans(X)) # this substracts the colMean to each col 
scale(X, center=TRUE, scale=FALSE) # the same 

sweep(X, 2, colMeans(X), FUN='/') # this makes division 

आप for पाश आप compiler पैकेज से cmpfun उपयोग कर सकते हैं के आधार पर अपने कोड को गति चाहते हैं। उदाहरण

X <- matrix(sample(1:10, 500000, replace=TRUE), ncol=100) # some data 
means <- colMeans(X) # col means 

library(compiler) 

# One of your functions to be compiled and tested 
Mean <- function(x) { 
    for (i in 1:length(means)){ 
     X[,i] <- X[,i]-means[i] 
    } 
    return(X) 
} 



CMean <- cmpfun(Mean) # compiling the Mean function 

system.time(Mean(X)) 
    user system elapsed 
    0.028 0.016 0.101 
system.time(CMean(X)) 
    user system elapsed 
    0.028 0.012 0.066 

शायद यह सुझाव आपकी मदद कर सकता है।

3

मैं देख सकता हूं कि जिलर आपके इच्छित चीज़ों के बारे में अनिश्चित क्यों था, क्योंकि एक बिंदु पर आप विभाजन के लिए पूछते हैं लेकिन आपके कोड में आप घटाव का उपयोग करते हैं। उन्होंने सुझाव दिया कि स्वीप ऑपरेशन यहां अधूरा है। बस पैमाने का उपयोग कर यह करना होगा:

cX <- scale(X, scale=FALSE) # does the centering with subtraction of col-means 
sX <- scale(X, center=FALSE) # does the scaling operation 
csX <- scale(X) # does both 

(यह विश्वास है कि scale धीमी है मुश्किल है देखो यह कोड है पर स्तंभों पर sweep उपयोग करता है।।)

scale.default # since it's visible. 

एक मैट्रिक्स दृष्टिकोण:

t(t(X)/colMeans(X)) 

संपादित करें: कुछ समय (मैं scale के बारे में गलत था-स्वीप-कोलमेन के बराबर):

require(rbenchmark) 
benchmark(
    mat={sX <- t(t(X)/colMeans(X)) }, 
    swp ={swX <- sweep(X, 2, colMeans(X), FUN='/')}, 
    scl={sX <- scale(X, center=FALSE)}, 
    replications=10^2, 
    order=c('replications', 'elapsed')) 
#----------- 
    test replications elapsed relative user.self sys.self user.child sys.child 
1 mat   100 0.015 1.000000  0.015  0   0   0 
2 swp   100 0.015 1.000000  0.015  0   0   0 
3 scl   100 0.025 1.666667  0.025  0   0   0 

कुछ मजेदार चीजें तब होती हैं जब आप इसे स्केल करते हैं। उपरोक्त timigns सैम मैट्रिक्स-एक्स के साथ पागल थे।

 benchmark( 
     frlp ={means <- colMeans(X) 
         for (i in 1:length(means)){ 
           X[,i] <- X[,i]-means[i] 
           } 
         }, 
     mat={sX <- t(t(X) - colMeans(X)) }, 
     swp ={swX <- sweep(X, 2, colMeans(X), FUN='-')}, 
     scl={sX <- scale(X, scale=FALSE)}, 
    replications=10^2, 
    order=c('replications', 'elapsed')) 
#  
    test replications elapsed relative user.self sys.self user.child sys.child 
2 mat   100 2.075 1.000000  1.262 0.820   0   0 
3 swp   100 2.964 1.428434  1.917 1.058   0   0 
4 scl   100 2.981 1.436627  1.935 1.059   0   0 
1 frlp   100 3.651 1.759518  2.540 1.128   0   0 
+0

भ्रम के लिए खेद है। मैंने अपना प्रश्न संपादित किया। – Zach

+0

असल में, ऐसा लगता है कि मेरे लूप के रूप में दोनों स्वीप और स्केल लगभग धीमे होते हैं। – Zach

+0

मैंने अपनी मूल पोस्ट संपादित की। बेंचमार्क कोड के लिए धन्यवाद। हालांकि, ऐसा लगता है कि लूप वास्तव में बड़े matrices (5,000 पंक्तियों, 10,000 cols, या 50,000 पंक्तियों और 10,000 cols) पर सबसे तेज़ है। – Zach

3

शायद आपके frlp() समारोह संकलन चीज़ें थोड़ी गति होगा: आप क्या उपयोग कर रहे थे नीचे के करीब कुछ के साथ है?

frlp.c <- compiler:::cmpfun(function(mat){ 
       means <- colMeans(mat) 
       for (i in 1:length(means)){ 
       mat[,i] <- mat[,i]-means[i] 
       } 
       mat 
      } 
     ) 

[संपादित करें]: मुझे यह सब कुछ तेज़ नहीं था, लेकिन मैं नीचे X बहुत पैमाने पर करने के अपने कंप्यूटर पर काम करने के लिए किया था।यह अच्छी तरह से बड़े पैमाने सकता है, पता नहीं है

तुम भी JIT साथ तुलना करने के लिए इच्छा हो सकती है:

frlp.JIT <- function(mat){ 
       means <- colMeans(mat) 
       compiler::enableJIT(2) 
       for (i in 1:length(means)){ 
       mat[,i] <- mat[,i]-means[i] 
       } 
       mat 
      } 
1

यहाँ कुछ अधिक कर रहे हैं, कोई भी जितनी जल्दी जोश के रूप में:

X <- matrix(runif(1e6), ncol = 1000) 
matmult <- function(mat) mat - rep(1, nrow(mat)) %*% t(colMeans(mat)) 
contender1 <- function(mat) mat - colMeans(mat)[col(mat)] 
contender2 <- function(mat) t(apply(mat, 1, `-`, colMeans(mat))) 
contender3 <- function(mat) mat - rep(colMeans(mat), each = nrow(mat)) 
contender4 <- function(mat) mat - matrix(colMeans(mat), nrow(mat), ncol(mat), 
             byrow = TRUE) 
benchmark(matmult(X), 
      contender1(X), 
      contender2(X), 
      contender3(X), 
      contender4(X), 
      replications = 100, 
      order=c('replications', 'elapsed')) 
#  test replications elapsed relative user.self sys.self 
# 1 matmult(X)   100 1.41 1.000000  1.39  0.00 
# 5 contender4(X)   100 1.90 1.347518  1.90  0.00 
# 4 contender3(X)   100 2.69 1.907801  2.69  0.00 
# 2 contender1(X)   100 2.74 1.943262  2.73  0.00 
# 3 contender2(X)   100 6.30 4.468085  6.26  0.03 

ध्यान दें कि मैं numerics, नहीं पूर्णांकों का एक मैट्रिक्स पर परीक्षण कर रहा हूँ; मुझे लगता है कि अधिक लोगों को यह उपयोगी लगेगा (यदि इससे कोई फर्क पड़ता है।)

संबंधित मुद्दे