2017-07-27 187 views
1

當我在R中使用矩陣子集時,似乎對內存使用有誤解。當我嘗試編寫交叉驗證函數時遇到了,但我認爲問題更一般。下面我已經制作了一個小例子。R索引,矩陣乘法

# parameters 
n <- 1e6 # the real data are much bigger, but this will do 
m <- 50 
nfolds <- 10 
X <- matrix(rnorm(n*m,0,1),nrow=n,ncol=m) 
y <- rnorm(n,0,1) 
mse <- rep(0,nfolds) 
foldid <- sample(rep(seq(nfolds), length = n)) 

# produces big spikes in memory 
for (i in (1:nfolds)) { 
    which <- foldid == i 
    xpx <- crossprod(X[!which,]) 
    xpy <- crossprod(X[!which,],y[!which]) 
    b <- solve(xpx,xpy) 
    mse[i] <- mean((y[which] - X[which,] %*% b)**2) 
} 

# does not produce spikes in memory usage 
for (i in (1:nfolds)) { 
    xpx <- crossprod(X) 
    xpy <- crossprod(X,y) 
    b <- solve(xpx,xpy) 
    mse[i] <- mean((y - X %*% b)**2) 
} 

我不明白爲什麼第一個循環產生的內存使用大向上尖峯,而雖然有嚴格的更大的矩陣相乘的第二循環不。

回答

1

我們來比較第一行和循環。

首先,簡單crossprod

xpx <- crossprod(X) 

沒有子集,你用矩陣X(已有400 MB)和xpx(小)工作。

其次,與子集:

xpx <- crossprod(X[!which,]) 

在這裏,你有X工作,臨時矩陣X[!which,]xpx。附加矩陣X[!which,]需要額外的360 MB內存。

object.size(X[!which,]) 
# 360000200 bytes 

R具有較差的內存管理,所以臨時矩陣可能在一段時間內不會被丟棄。