2011-06-23 53 views
6

我是一個正常的8GB內存的服務器上運行內存,在機器學習方面一個相當小的數據集工作:R存貯器管理諮詢(尖,模型矩陣,數據幀)

 
> dim(basetrainf) # this is a dataframe 
[1] 58168 118 

唯一預模型步驟我將其中顯着增加的內存消耗是將數據幀轉換爲模型矩陣。這是因爲caretcor等僅適用於(模型)矩陣。即使在去除多個層次的因素後,矩陣(下面的mergem)也相當大。 (sparse.model.matrix/Matrix普遍支持不好,所以我不能使用。)

 
> lsos() 
       Type  Size PrettySize Rows Columns 
mergem   matrix 879205616 838.5 Mb 115562  943 
trainf  data.frame 80613120 76.9 Mb 106944  119 
inttrainf  matrix 76642176 73.1 Mb 907 10387 
mergef  data.frame 58264784 55.6 Mb 115562  75 
dfbase  data.frame 48031936 45.8 Mb 54555  115 
basetrainf data.frame 40369328 38.5 Mb 58168  118 
df2  data.frame 34276128 32.7 Mb 54555  103 
tf   data.frame 33182272 31.6 Mb 54555  98 
m.gbm   train 20417696 19.5 Mb  16  NA 
res.glmnet  list 14263256 13.6 Mb  4  NA 

而且,由於許多R型號不支持例如重量,我只好先過採樣少數類,加倍我的數據集的大小(爲什麼trainf,mergef,mergem的行數是basetrainf的兩倍)。

R在這一點上使用1.7GB的內存,使我的總內存使用量高達7.7GB的4.3GB。

接下來我要做的事情是:

 
> m = train(mergem[mergef$istrain,], mergef[mergef$istrain,response], method='rf') 

巴姆 - 在幾秒鐘內,在Linux外的內存殺手殺死rsession。

我可以採樣我的數據,欠採樣而不是過採樣等,但這些都是不理想的。我應該做些什麼(不同的)(不同的),重寫脫字符和我打算使用的各種模型包?我從來沒有遇到與其他ML軟件(Weka,Orange等)有關的問題,即使沒有刪除我的任何因素,可能是因爲既有示例加權也有「數據框架」支持所有型號。

完整的腳本如下:

 
library(caret) 
library(Matrix) 
library(doMC) 
registerDoMC(2) 

response = 'class' 

repr = 'dummy' 
do.impute = F 

xmode = function(xs) names(which.max(table(xs))) 

read.orng = function(path) { 
    # read header 
    hdr = strsplit(readLines(path, n=1), '\t') 
    pairs = sapply(hdr, function(field) strsplit(field, '#')) 
    names = sapply(pairs, function(pair) pair[2]) 
    classes = sapply(pairs, function(pair) 
    if (grepl('C', pair[1])) 'numeric' else 'factor') 

    # read data 
    dfbase = read.table(path, header=T, sep='\t', quote='', col.names=names, na.strings='?', colClasses=classes, comment.char='') 

    # switch response, remove meta columns 
    df = dfbase[sapply(pairs, function(pair) !grepl('m', pair[1]) && pair[2] != 'class' || pair[2] == response)] 

    df 
} 

train.and.test = function(x, y, trains, method) { 
    m = train(x[trains,], y[trains,], method=method) 
    ps = extractPrediction(list(m), testX=x[!trains,], testY=y[!trains,]) 
    perf = postResample(ps$pred, ps$obs) 
    list(m=m, ps=ps, perf=perf) 
} 

# From 
sparse.cor = function(x){ 
    memory.limit(size=10000) 
    n 200 levels') 
badfactors = sapply(mergef, function(x) 
    is.factor(x) && (nlevels(x) 200)) 
mergef = mergef[, -which(badfactors)] 

print('remove near-zero variance predictors') 
mergef = mergef[, -nearZeroVar(mergef)] 

print('create model matrix, making everything numeric') 
if (repr == 'dummy') { 
    dummies = dummyVars(as.formula(paste(response, '~ .')), mergef) 
    mergem = predict(dummies, newdata=mergef) 
} else { 
    mat = if (repr == 'sparse') model.matrix else sparse.model.matrix 
    mergem = mat(as.formula(paste(response, '~ .')), data=mergef) 
    # remove intercept column 
    mergem = mergem[, -1] 
} 

print('remove high-correlation predictors') 
merge.cor = (if (repr == 'sparse') sparse.cor else cor)(mergem) 
mergem = mergem[, -findCorrelation(merge.cor, cutoff=.75)] 

print('try a couple of different methods') 
do.method = function(method) { 
    train.and.test(mergem, mergef[response], mergef$istrain, method) 
} 
res.gbm = do.method('gbm') 
res.glmnet = do.method('glmnet') 
res.rf = do.method('parRF') 
+0

您是否最終切換軟件或在R中提出解決方案?我會很好奇聽到一些更有前途的方法,因爲我有類似的問題。我計劃使用越來越多的更高規格的EC2機器,因爲它們很方便,而且我非常瞭解R(直到我需要實施其他解決方案)。 – lockedoff

+0

@lockedoff我最終做了更多次取樣(我提到的其中一個「非理想」解決方案 - 也應該包括「購買更多內存」)! – Yang

+0

我現在能夠相當快地在350,000 x 30數據幀上使用'caret'評估3x3x3參數網格。當平行運行時(每個核心使用的內存太多),這會導致我的8GB quadcore macbook pro死機,但昨天我發現它在亞馬遜的高內存雙額外大型實例(http://aws.amazon。 com/ec2/instance-types/@作爲現場實例,價格約爲0.42美元/小時)。 – lockedoff

回答

5

檢查底層randomForest代碼沒有存儲樹林。也許減少tuneLength,以便嘗試更少的值mtry

另外,我可能只是手工合適一個隨機森林,看看我是否可以在我的機器上安裝這樣的模型。如果你不能直接放入一個,你將無法使用插入符號來適應許多人。

在這一點上,我認爲你需要找出導致內存膨脹的原因以及如何控制模型擬合,以避免氣球失去控制。因此,計算如何插入調用randomForest()和它正在使用的選項。你可能可以將其中的一些關閉(如存儲我之前提到的森林,但也包括可變重要性措施)。確定mtry的最佳值後,您可以嘗試使用所有可能需要幫助解釋擬合的附加項來擬合模型。

+0

我很害怕你會這樣說。 randomForest本身確實消耗了大量的內存。 ntree = 500給出「錯誤:不能分配大小爲384.7 Mb的向量」。 ntree = 200的作品,但幾乎最大的內存。看起來我必須特別對待RF(以及其他模型,如GBM),或者只是溝渠R.Argh,爲什麼R中的所有內容都佔用了太多內存?我真的希望我做錯了什麼或缺少什麼。如果我沒有聽到任何其他信息,我會將您的答案標記爲已接受。 – Yang

+1

@Yang你是否用'keep.forest = FALSE'來稱呼?如果沒有,那就這樣做。另外,你是否適合使用公式界面或普通界面?確保你使用的是矩陣,而不是數據框。爲什麼'mergmem'的行數是'basetrainf'的兩倍?我明白爲什麼列的數量更大,但不是爲什麼有兩倍的行數。向我們展示**完全**您做了什麼幫助,以便我們不會猜測。請使用您嘗試的示例代碼編輯您的Q(實際調用)。 –

+0

@Yang R擁有內存中的所有對象,並且函數可以經常在對象被切片(子集)或重新分配時複製對象。這對R來說是一個問題,但有些方法可以解決一些問題,而且這些天你總是可以拋出更多的RAM來解決問題。 –

-2

你可以嘗試使用FF包,它實現了「記憶高效的存儲在磁盤上,快速訪問功能大數據」。

+10

不要隨意丟棄ff或bigmemory的建議。 OP詢問了有關脫字符包的幫助,既不是ff也不是大內存。所以這個答案是在基地之外和誤導之間。 –

6

有了這麼多的數據,重採樣誤差估計和隨機森林OOB誤差估計應該非常接近。嘗試使用trainControl(method = "OOB")train()將不適合重採樣數據集上的額外模型。

另外,避免像鼠疫這樣的公式界面。

您也可以嘗試裝袋。由於在每個唾液中不存在隨機選擇的預測因子,因此可以用50-100個重採樣(而不是隨機森林需要的更多效果)獲得好的結果。

其他人可能不同意,但我也認爲對所有數據進行建模並不總是最好的方法。除非預測變量空間很大,否則許多數據點將與其他變量非常相似,並且對模型擬合(除了額外的計算複雜性和所得到的對象的佔用空間)貢獻不大。 caret有一個功能,稱爲maxDissim,這可能有助於細化數據(雖然它也不是非常有效)