2011-06-23 6 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の2倍の行数を持つ理由)

Rはこの時点で1.7GBのメモリを使用しているため、私の合計メモリ使用量は7.7GBのうち4.3GBまでになります。

私は次のことは、次のとおりです。

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

バム - 数秒で、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') 
+0

ソフトウェアを切り替えることになったのか、Rで解決したのですか?あなたのより有望なアプローチのいくつかが私が似たような問題を抱えていることを聞くことに興味があります。私は、より高性能なEC2マシンを使うつもりです。なぜなら、それらは便利で、私はRを非常によく知っているからです(他のソリューションを実装する必要があるまで)。 – lockedoff

+0

@lockedoff私は、より多くのサブサンプリング(私が言及した「理想的でない」ソリューションの1つです。 – Yang

+0

私は今、350,000 x 30のデータフレームで 'キャレット 'を使って3x3x3のパラメータグリッドをかなり素早く評価できるようになりました。これは私の8GBクアッドコアのMacbook Proを並列で実行すると(それぞれのコアが多すぎるメモリを使用していた)、昨日私はAmazonのHigh-Memory Double Extra Large Instance(http://aws.amazon。 com/ec2/instance-types/@をスポットインスタンスとして約$ 0.42 /時間で提供しています)。 – lockedoff

答えて

5

ランダムなフォレストコードがツリーのフォレストを格納していないことを確認してください。おそらくの値が少なくなるようにtuneLengthを減らしてください。

また、おそらく単なるランダムなフォレストを手作業で取り入れて、私のマシンにこのようなモデルを適合させることができるかどうかを確認することになります。 1つに直接当てはまらない場合は、キャレットを一度に多くの人に合わせることはできません。

この時点で、メモリがバルーンになる原因と、モデルフィッティングを制御して制御不能にならないようにする方法を検討する必要があると思います。 キャレットrandomForest()とどのようなオプションを使用して呼び出すのかを考えてください。あなたはそれらのいくつかをオフにすることができるかもしれません(私が前に述べた森林の保存のように、しかし重要な可変手段)。 mtryの最適値を決定したら、フィットを解釈するのに役立つ可能性があるすべてのエクスをモデルにフィットさせることができます。

+0

私はあなたがこれを言うと恐れていました。 randomForest自体は、ばかげた量のメモリを消費します。 ntree = 500は "エラー:サイズ384.7Mbのベクトルを割り当てることができません"を示します。 ntree = 200は動作しますが、メモリをほぼ最大にします。 RF(とGBMのような他のモデル)を特別に扱わなければならないか、R. Arghを捨てなければならないように見えます。私は何か間違っていることや何かを逃していることを本当に望んでいました。私は何も聞こえなければあなたの答えを受け入れたものとしてマークします。 – Yang

+1

@Yang 'keep.forest = FALSE'でそれを呼びましたか?もしそうでなければ、それをしてください。また、数式インターフェースまたは通常のインターフェースを使用してフィットしましたか?データフレームではなく行列を使用していることを確認してください。 'mergmem'はなぜ' basetrainf'の2倍の行を持っていますか?私は列の数がなぜ大きいのか理解していますが、なぜ2倍の行があるのか​​分かりません。私たちを** **正確に**あなたが援助したことは、私たちが推測のままにされないように助けてください。試したサンプルコード(実際の呼び出し)でQを編集してください。 –

+0

@Yang Rはメモリ内のすべてのオブジェクトを保持しており、スライス(サブセット)または再割り当てされたときにオブジェクトを頻繁にコピーできます。これはRの一般的な問題ですが、いくつかの問題が丸められています。最近問題が発生した場合、常にRAMを増やすことができます。 –

-2

あなたが「ディスクと高速アクセス機能に大きなデータのメモリ効率ストレージ」を実装FFパッケージを使用しようとすることができます。

+10

ffまたはbigmemoryの推奨事項をランダムに投げ捨ててはいけません。 OPは、キャレット・パッケージのヘルプについて尋ねましたが、ffもbigmemoryもそれを使っていませんでした。だから、この答えは基底と誤解を招くようなものの間のどこかにある。 –

6

多くのデータでは、再サンプリングされたエラー推定値とランダムフォレストのOOBエラー推定値はかなり近いはずです。trainControl(method = "OOB")train()を使用してみると、再サ​​ンプリングされたデータセットの余分なモデルに適合しません。

また、ペストのようなフォーミュラインターフェースは避けてください。

代わりに袋詰めを試みることもできます。各唾液には予測因子がランダムに選択されていないので、50-100のリサンプルで効果を発揮することができます。

これ以外の理由があるかもしれませんが、私が持っているすべてのデータをモデリングしても、必ずしも最良の方法とは限りません。予測子空間が大きい場合を除き、データ点の多くは他のものと非常によく似ており、計算の複雑さや結果として生じるオブジェクトのフットプリントに加えて、モデル適合にあまり寄与しません。 caretにはmaxDissimという機能があり、データを間引くのに役立ちます(どちらもあまり効率的ではありませんが)。