2015-07-11 93 views
4

我是R的新手,我使用glmer來適應幾個二項模型,我只需要它們調用predict即可使用所得到的概率。不過,我有一個非常大的數據集,甚至只是一個模型的大小變得非常大:減少glmer模型的大小

> library(pryr) 
> object_size(mod) 
701 MB 

模型的係數的大小相比簡直是小巫見大巫:

> object_size(coef(mod)) 
1.16 MB 

一樣大小的擬合值:

> object_size(fitted(mod)) 
25.6 MB 

首先,我不明白爲什麼模型的對象大小如此之大。它似乎包含用於擬合模型的原始數據框架,但即使這樣也不能說明尺寸。爲什麼這麼巨大?

其次,是否有可能將模型剝離爲只需調用預測的部分?如果是這樣,我將如何去做這件事?我發現一個帖子,這是爲glmhttp://blog.yhathq.com/posts/reducing-your-r-memory-footprint-by-7000x.html完成,但似乎glmer模型訪問不同,並有不同的組件。

任何幫助將不勝感激。

編輯:

挖掘到模型的內部:

> object_size(getME(mod, "X")) 
205 MB 
> object_size(getME(mod, "Z")) 
36.9 MB 
> object_size(getME(mod, "Zt")) 
38.4 MB 
> object_size(getME(mod, "Ztlist")) 
41.6 MB 
> object_size(getME(mod, "mmList")) 
38.4 MB 
> object_size(getME(mod, "y")) 
3.2 MB 
> object_size(getME(mod, "mu")) 
3.2 MB 
> object_size(getME(mod, "u")) 
18.4 kB 
> object_size(getME(mod, "b")) 
19.5 kB 
> object_size(getME(mod, "Gp")) 
56 B 
> object_size(getME(mod, "Tp")) 
472 B 
> object_size(getME(mod, "L")) 
15.5 MB 
> object_size(getME(mod, "Lambda")) 
38.1 kB 
> object_size(getME(mod, "Lambdat")) 
38.1 kB 
> object_size(getME(mod, "Lind")) 
9.22 kB 
> object_size(getME(mod, "Tlist")) 
936 B 
> object_size(getME(mod, "A")) 
38.4 MB 
> object_size(getME(mod, "RX")) 
30.3 kB 
> object_size(getME(mod, "RZX")) 
1.05 MB 
> object_size(getME(mod, "sigma")) 
48 B 
> object_size(getME(mod, "flist")) 
4.89 MB 
> object_size(getME(mod, "fixef")) 
4.5 kB 
> object_size(getME(mod, "beta")) 
496 B 
> object_size(getME(mod, "theta")) 
472 B 
> object_size(getME(mod, "ST")) 
936 B 
> object_size(getME(mod, "REML")) 
48 B 
> object_size(getME(mod, "is_REML")) 
48 B 
> object_size(getME(mod, "n_rtrms")) 
48 B 
> object_size(getME(mod, "n_rfacs")) 
48 B 
> object_size(getME(mod, "N")) 
256 B 
> object_size(getME(mod, "n")) 
256 B 
> object_size(getME(mod, "p")) 
256 B 
> object_size(getME(mod, "q")) 
256 B 
> object_size(getME(mod, "p_i")) 
408 B 
> object_size(getME(mod, "l_i")) 
408 B 
> object_size(getME(mod, "q_i")) 
408 B 
> object_size(getME(mod, "mod")) 
48 B 
> object_size(getME(mod, "m_i")) 
424 B 
> object_size(getME(mod, "m")) 
48 B 
> object_size(getME(mod, "cnms")) 
624 B 
> object_size(getME(mod, "devcomp")) 
2.21 kB 
> object_size(getME(mod, "offset")) 
3.2 MB 

> get_obj_size([email protected], "RC") 
         [,1] 
family   673355488 
initialize  673355488 
initialize#lmResp 673355488 
ptr    673355488 
resDev   673355488 
updateMu   673355488 
updateWts   673355488 
wrss    673355488 
eta     3196024 
mu     3196024 
n     3196024 
offset    3196024 
sqrtrwt    3196024 
sqrtXwt    3196024 
weights    3196024 
wtres    3196024 
y     3196024 
Ptr      40 
> get_obj_size([email protected], "RC") 
        [,1] 
beta   449419408 
initialize 449419408 
initializePtr 449419408 
ldL2   449419408 
ldRX2   449419408 
linPred  449419408 
ptr   449419408 
setTheta  449419408 
sqrL   449419408 
u    449419408 
X    204549128 
V    182171288 
Ut    38448168 
Zt    38448168 
LamtUt   38353248 
Xwts   3196024 
RZX    1047176 
Lambdat   38136 
VtV    26192 
delu    18408 
u0    18408 
Utr    18408 
Lind    9224 
beta0    496 
delb    496 
Vtr     496 
theta    72 
Ptr     40 
+0

這是一個很好的問題,但是我們可以請一個小型的可重複使用的例子,或者至少是關於模型尺寸的一些信息(模型框架的尺寸,固定效應係數的數量等等)? –

+0

Hey Ben, 讚我提到過,我是新來的使用R,所以我希望這個信息是你的意思: 用於擬合模型的數據框的大小爲399,498行×14列。有(我相信)57固定效應係數,雖然我不完全確定如何得到。當我在fixef(mod)上調用'dim'時,它返回NULL,但是隻計算它們的數量似乎是57.我可以深入瞭解它並獲取所需的任何信息,但是我可能需要一些關於如何訪問該信息的指針。它需要原始數據框還是可以像glm一樣去除它? –

+0

此外,我會對可重現的例子感興趣,但我想這對於這個目的來說太大了。它可以在cbpp數據上完成嗎? –

回答

3

發佈作爲一個不完整的答案現在:

library("lme4") 
gm1 <- glmer(cbind(incidence, size - incidence) ~ period + (1 | herd), 
       data = cbpp, family = binomial) 
library("pryr") 
object_size(gm1) ## 505 kB 

繼史蒂夫·沃克的S3/S4/Reference類字典上市提取領域:

get_obj_size <- function(obj,type="S4") { 
    fields <- switch(type, 
        S4=slotNames(obj), 
        RC=ls(obj)) 
    get_field <- switch(type, 
        S4=function(x) slot(obj,x), 
        RC=function(x) obj[[x]]) 
    field_list <- setNames(lapply(fields,get_field),fields) 
    cbind(sort(sapply(field_list,object_size),decreasing=TRUE)) 
} 
get_obj_size(gm1) 
##   [,1] 
## resp 356620 ## 'response module' 
## pp  355420 ## 'predictor module' 
## frame  6640 
## optinfo 1748 
## devcomp 1424 
## call  1244 
## flist  1232 
## cnms  224 
## u   152 
## beta  56 
## Gp   32 
## lower  32 
## theta  32 

它將值得進一步挖掘響應和預測模塊,看看有什麼/有什麼大,有些信息將被存儲在環境這些組件​​

。例如,我認爲,這通常是相同的尺寸低於組件的整體轉換實際上不是獨立的,而是具有相同的環境...

get_obj_size([email protected],"RC") 
##      [,1] 
## initialize  356620 
## initialize#lmResp 356620 
## ptr    356620 
## resDev   356620 
## setOffset   356620 
## updateMu   356620 
## updateWts   356620 
## wrss    356620 
## family    26016 
## eta     472 
## mu     472 
## n     472 
## offset    472 
## sqrtrwt    472 
## sqrtXwt    472 
## weights    472 
## wtres    472 
## y     472 
## Ptr     20 

另一個查看存儲哪些組件的方法是使用object_size(getME(model,component))並重復通過eval(formals(getME)$name)列出的組件;這與信息在內部存儲的方式不太精確,但會讓您瞭解需要多少空間來容納(例如)固定效應或隨機效應模型矩陣。

我從事這方面的更多一些,並有部分解決,但還有存儲,我似乎無法找到/修剪掉的正確很多(,這需要在Github上的最新版本lme4:我不得不稍微修改predict函數以減弱對內部結構的依賴)。

glmer_chop <- function(object) { 
    newobj <- object 
    [email protected] <- model.frame(object)[0,] 
    [email protected] <- with([email protected], 
        new("merPredD", 
         Lambdat=Lambdat, 
         Lind=Lind, 
         theta=theta, 
         u=u,u0=u0, 
         n=nrow(X), 
         X=matrix(1,nrow=nrow(X)), 
         Zt=Zt)) ## .sparseDiagonal(n,shape="g"))) 
    [email protected] <- new("glmResp",family=binomial(),y=numeric(0)) 
    return(newobj) 
} 
get_obj_size(environment([email protected]$initialize),"RC") 
fm1 <- glmer(use ~ urban+age+livch+(1|district), Contraception, binomial) 
object_size(Contraception) ## 133 kB 
object_size(fm1) ## 1.05 MB 
object_size(fm2 <- glmer_chop(fm1)) ## 699 kB 
get_obj_size(fm2)   ## 'pp' is 547200 bytes 
get_obj_size([email protected],"RC") ## 'initialize' object is 547200 
saveRDS(fm2,file="tmp.rds") 
fm2 <- readRDS("tmp.rds") 
object_size(fm2) ## 796 kB 
rm(fm1) 
pp <- predict(fm2,newdata=Contraception) 
object_size(fm2) ## still 796K; no sharing 

最後注意到compare_size(fm2)證實,這裏的大多數信息都存儲在環境中,而不是在對象本身(但我不知道怎麼compare_size/object.size處理引用類...)

+0

的什麼佔用了大部分空間比看上去類似於您的例子: > get_obj_size(MOD) [,1] 幀695761408 電話673359304 RESP 673355784 第449419704 的flist 4894888 ü18408 devcomp 2208 optinfo 1488 CNMS 624 測試496 下72 THETA 72 的Gp 56 然而,遇到一些麻煩挖掘到對象本身: > object_size(getME(MOD, 「響應」)) 錯誤match.arg(名稱): 'ARG' 應該是「X」,「Z」之一,... 很抱歉的格式這裏。 –

+0

應該是例如'object_size(getME(mod,「X」))' –

+0

對不起,我最初完全誤解了你。我使用組件大小的結果更新了我的初始帖子。固定效應和隨機效應係數分別持有fixef和u嗎?如果是這樣,那麼與其餘部分相比,這些是微不足道的。 –

0

您對存儲空間或內存的關注?如果是關於存儲的話,其中一個選擇就是嵌入調用,以便在生成預測的代碼中估計模型,這樣您就不會實際存儲模型對象。喜歡的東西:

predictions <- predict(glmer(y ~ x, family = binomial), type = "response") 
+0

不幸的是,這是關於內存。我需要一次在內存中放置好幾個模型,當我開始加載其中的一些時,我的系統完全窒息。 –

+0

啊,對不起,我也迷路了。祝你好運。 – ulfelder