首页 文章

R内存管理建议(插入符号,模型矩阵,数据帧)

提问于
浏览
6

我在正常的8GB服务器上运行内存不足,在服务器学习环境中使用相当小的数据集:

> 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')

Bam - 在几秒钟内,Linux内存杀手杀死了rsession .

我可以对我的数据进行采样,采样不足而不是过采样等,但这些都不是理想的 . 我应该做什么(不同的),没有重写插入符号和我打算使用的各种模型包?

FWIW,我从来没有遇到过其他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')

3 回答

  • 5

    检查基础 randomForest 代码是否存储了树林 . 也许减少 tuneLength ,以便尝试更少的 mtry 值 .

    此外,我可能只是手动拟合一个随机森林,看看我是否可以在我的机器上安装这样的模型 . 如果你能够't fit one directly, you won'能够使用 caret 适合多个一起去 .

    在这一点上,我认为你需要找出导致内存膨胀的原因,以及如何控制模型拟合,使其不会失控 . 因此,请确定 caret 如何调用 randomForest() 以及它使用的选项 . 您可能可以关闭其中一些(例如存储我之前提到的森林,还有变量重要性度量) . 一旦确定了 mtry 的最佳值,您就可以尝试使用您可能希望帮助解释拟合的所有附加物来拟合模型 .

  • -2

    利用这么多数据,重采样误差估计和随机森林OOB误差估计应该非常接近 . 尝试使用 trainControl(method = "OOB")train() 将不适合重采样数据集上的额外模型 .

    另外,避免像瘟疫那样的公式界面 .

    您也可以尝试装袋 . 由于每次吐痰都没有随机选择预测因子,因此您可以通过50-100次重采样获得良好的结果(而不是随机森林需要的更多结果才能生效) .

    其他人可能不同意,但我也认为对所有数据建模并不总是最好的方法 . 除非预测器空间很大,否则许多数据点将与其他数据点非常相似,并且对模型拟合没有太大贡献(除了额外的计算复杂性和结果对象的占用空间) . caret 有一个名为 maxDissim 的函数,可能有助于细化数据(尽管它也不是非常有效)

  • 6

    您可以尝试使用ff包,它实现了“磁盘上大数据的内存高效存储和快速访问功能” .

相关问题