7 Stimmen

R-Speicherverwaltungstipps (caret, Modellmatrizen, Datenrahmen)

Ich laufe auf einem normalen 8GB-Server mit einem ziemlich kleinen Datensatz in einem Machine-Learning-Kontext aus dem Speicher:

\> dim(basetrainf) # dies ist ein Datenrahmen
\[1\] 58168   118

Der einzige Vorverarbeitungsschritt, den ich unternehme, der den Speicherverbrauch signifikant erhöht, besteht darin, einen Datenrahmen in eine Modellmatrix zu konvertieren. Dies liegt daran, dass caret, cor usw. nur mit (Modell-)Matrizen arbeiten. Selbst nach dem Entfernen von Faktoren mit vielen Stufen ist die Matrix (mergem unten) ziemlich groß (sparse.model.matrix/Matrix wird im Allgemeinen schlecht unterstützt, daher kann ich das nicht verwenden).

\> lsos()
                 Typ      Größe Schöne Größe   Zeilen Spalten
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

Weil viele R-Modelle keine Beispielmengen unterstützen, musste ich zuerst die Minderheitsklasse überabtasten und die Größe meines Datensatzes verdoppeln (deshalb haben trainf, mergef, mergem doppelt so viele Zeilen wie basetrainf).

R verwendet jetzt 1,7 GB Speicher, was meinen Gesamtspeicherbedarf auf 4,3 GB von 7,7 GB bringt.

Als nächstes mache ich folgendes:

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

Bam - in wenigen Sekunden tötet der Linux Out-of-Memory-Killer rsession.

Ich kann meine Daten sampeln, undersampeln usw., aber das sind keine idealen Lösungen. Was soll ich also (anders) machen, ohne caret und die verschiedenen Modellpakete, die ich verwenden möchte, neu zu schreiben?

Zum Thema, ich hatte dieses Problem noch nie mit anderen ML-Software (Weka, Orange, usw.), auch ohne das Entfernen meiner Faktoren, vielleicht aufgrund von Gewichtung von Beispielen und der "Datenrahmen"-Unterstützung über alle Modelle hinweg.

Vollständiges Skript folgt:

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

response = 'Klasse'

repr = 'dummy'
do.impute = F

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

read.orng = function(path) {
  # Header lesen
  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\])) 'numerisch' else 'Faktor')

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

  # Antwort umschalten, Metasäulen entfernen
  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)
}

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

7voto

Max Punkte 391

Mit so vielen Daten sollten die neu abgeschätzten Fehlerschätzungen und die random forest OOB-Fehlerschätzungen ziemlich nahe beieinander liegen. Versuchen Sie trainControl(method = "OOB") zu verwenden und train() wird die zusätzlichen Modelle nicht auf den neu abgeschätzten Datensätzen anpassen.

Außerdem sollten Sie die Formel-Schnittstelle wie die Pest vermeiden.

Sie könnten auch stattdessen Bagging ausprobieren. Da es keine zufällige Auswahl von Prädiktoren bei jedem Splits gibt, können Sie mit 50-100 Neuabtastungen gute Ergebnisse erzielen (anstatt der vielen, die von random forests benötigt werden, um effektiv zu sein).

Andere mögen anderer Meinung sein, aber ich denke auch, dass es nicht immer der beste Ansatz ist, alle verfügbaren Daten zu modellieren. Falls der Prädiktorraum nicht groß ist, werden viele Datenpunkte sehr ähnlich zu anderen sein und tragen nicht viel zur Modellanpassung bei (abgesehen von der zusätzlichen Berechnungskomplexität und dem Footprint des resultierenden Objekts). caret hat eine Funktion namens maxDissim, die hilfreich sein könnte, um die Daten zu reduzieren (obwohl sie auch nicht besonders effizient ist)

6voto

Gavin Simpson Punkte 163780

Überprüfen Sie, ob der zugrunde liegende randomForest-Code den Wald der Bäume nicht speichert. Möglicherweise reduzieren Sie die tuneLength, damit weniger Werte von mtry ausprobiert werden.

Außerdem würde ich wahrscheinlich einfach einen einzelnen Random Forest manuell anpassen, um zu sehen, ob ich ein solches Modell auf meinem Rechner anpassen könnte. Wenn Sie nicht direkt einpassen können, können Sie caret nicht verwenden, um viele auf einmal anzupassen.

An diesem Punkt denke ich, dass Sie herausfinden müssen, was dazu führt, dass der Speicher zu hoch ansteigt, und wie Sie das Modellanpassen steuern können, damit es nicht außer Kontrolle gerät. Finden Sie heraus, wie caret randomForest() aufruft und welche Optionen es verwendet. Möglicherweise können Sie einige davon deaktivieren (wie das Speichern des Waldes, von dem ich zuvor gesprochen habe, aber auch die Variablengewichtungsmessungen). Sobald Sie den optimalen Wert für mtry bestimmt haben, können Sie versuchen, das Modell mit allen Extras anzupassen, die Ihnen bei der Interpretation der Anpassung helfen sollen.

-1voto

rafalotufo Punkte 3822

Sie können versuchen, das ff-Paket zu verwenden, das die "speichereffiziente Speicherung großer Daten auf der Festplatte und schnelle Zugriffsfunktionen" implementiert.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X