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