2011-06-23 13 views
6

biegnę z pamięci na normalnym serwerze 8GB pracy z dość małego zestawu danych w kontekście uczenia się maszyny:R rada zarządzanie pamięcią (daszek, model macierze, ramki danych)

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

Jedynym wstępnej -modelowanie krokiem, który znacznie zwiększa zużycie pamięci, przekształca ramkę danych w matrycę modelu. To jest od caret, cor itp. Działa tylko z macierzami (modelowymi). Nawet po usunięciu czynników o wielu poziomach macierz (mergem poniżej) jest dość duża. (sparse.model.matrix/Matrix jest słabo obsługiwany w ogóle, więc nie mogę użyć.)

 
> 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 

Ponadto, ponieważ wielu modelach R nie obsługują przykładowe wagi, musiałam najpierw oversample klasę mniejszościowy, podwajając rozmiar mojego zbioru danych (dlaczego trainf, mergef, mergem mają dwa razy więcej wierszy niż basetrainf).

R jest w tym momencie z wykorzystaniem 1,7 GB pamięci, dzięki czemu moje całkowite wykorzystanie pamięci wynosi 4,3 GB z 7,7 GB.

Następną rzeczą mogę zrobić, to:

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

Bam - w ciągu kilku sekund, Linux out-of-memory zabójca zabija rsession.

Potrafię pobierać próbki z moich danych, podciśnienia zamiast nadprzykładowości itp., Ale nie są one idealne. Co (inaczej) powinienem zrobić (inaczej), bez przepisywania karetki i różnych pakietów modeli, które zamierzam użyć?

FWIW, Nigdy nie natknąłem się na ten problem z innymi programami ML (Weka, Orange itp.), Nawet bez przycinania któregokolwiek z moich czynników, być może z powodu zarówno przykładowego ważenia, jak i obsługi "ramek danych", wszystkie modele.

Kompletny skrypt następująco:

 
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

Czy zmieniło się oprogramowanie, lub wymyślanie rozwiązania w R? Byłbym ciekawy, jakie są wasze bardziej obiecujące podejścia, ponieważ mam podobne problemy. Planuję używać coraz wyższych spec-EC2 maszyn, ponieważ są one wygodne i znam R bardzo dobrze (dopóki nie będę musiał zaimplementować innego rozwiązania). – lockedoff

+0

@lockedoff Skończyło się na tym, że wykonałem znacznie więcej podpróbkowania (jedno z "nieidealnych" rozwiązań, o których wspomniałem - które powinno również obejmować "kup więcej RAM")! – Yang

+0

Jestem teraz w stanie dość szybko ocenić siatki parametrów 3x3x3, używając 'karetki' na ramce danych o wymiarach 350 000 x 30. To zabijało moje 8GB quadcore macbook pro podczas równoległego działania (każdy rdzeń zużywał zbyt dużo pamięci), ale wczoraj dowiedziałem się, że działa bardzo szybko na dużej instancji Amazon High-Memory Double Extra Large (http: //aws.amazon. com/ec2/instance-types/@ przy około 0,42 USD/godz. jako instancji typu spot). – lockedoff

Odpowiedz

5

Sprawdź, czy podstawowy kod losowy numer nie przechowuje lasu drzew. Być może należy zmniejszyć wartość tuneLength, aby wypróbować mniejszą liczbę wartości mtry.

Ponadto, prawdopodobnie dopasowałbym pojedynczy losowy las ręcznie, aby sprawdzić, czy mogę dopasować taki model do mojej maszyny. Jeśli nie możesz dopasować jednego bezpośrednio, nie będziesz w stanie użyć caret, aby dopasować wiele za jednym razem.

W tym momencie myślę, że trzeba ustalić, co powoduje, że pamięć jest balonowa i jak kontrolować dopasowanie modelu, aby nie wymknąć się spod kontroli. Sprawdź, w jaki sposób zadzwonił i jakich opcji używa. Być może uda ci się wyłączyć niektóre z nich (np. Przechowując wspomniany wcześniej las, ale także środki o zmiennej ważności). Po określeniu optymalnej wartości dla mtry, możesz spróbować dopasować model do wszystkich dodatków, które mogą Ci pomóc w interpretacji dopasowania.

+0

Obawiałem się, że to powiesz. randomForest samo zużywa śmieszną ilość pamięci. ntree = 500 daje "Błąd: nie można przydzielić wektora o wielkości 384,7 MB." ntree = 200 działa, ale prawie maksymalizuje pamięć. Wygląda na to, że musiałbym specjalnie potraktować RF (i inne modele, takie jak GBM), lub po prostu porzucić R. Argh, dlaczego wszystko w R zabiera tak dużo pamięci? Naprawdę miałem nadzieję, że robię coś złego lub czegoś brakuje. Zaznaczę twoją odpowiedź jako zaakceptowaną, jeśli nic nie usłyszę. – Yang

+1

@ Yang czy zadzwoniłeś do tego z 'keep.forest = FALSE'? Jeśli nie, zrób to. Czy pasowałeś też do interfejsu formuły lub normalnego interfejsu? Upewnij się, że używasz macierzy, a nie ramek danych. Dlaczego 'mergmem' ma dwa razy więcej wierszy niż' basetrainf'? Rozumiem, dlaczego liczba kolumn jest większa, ale nie dlatego, że liczba wierszy jest dwa razy większa. Pokazywanie nam ** dokładnie ** tego, co zrobiłeś, pomaga, abyśmy nie zgadywali. Zmodyfikuj swój Q za pomocą przykładowego kodu, który próbowałeś (rzeczywiste połączenia). –

+0

@ Yang R przechowuje wszystkie obiekty w pamięci i funkcje często mogą kopiować obiekty, gdy są podzielone na plasterki lub ponownie przydzielone. Jest to generalnie problem z R, ale istnieją sposoby obejścia niektórych problemów i zawsze możesz rzucić więcej pamięci RAM na problem w tych dniach. –

-2

Można spróbować użyć pakietu ff, który realizuje „Memory efektywne przechowywanie dużych danych na dysku i szybkich funkcji dostępu”.

+10

Nie wyrzucaj losowo zaleceń dotyczących ff lub bigmemory. OP poprosił o pomoc w pakiecie kurtużyny i ani ff ani bigmemory z nim nie współpracują. Tak więc ta odpowiedź znajduje się gdzieś pomiędzy pozapartyjnymi a wprowadzającymi w błąd. –

6

Przy tak dużej ilości danych, oszacowane błędy błędu i losowe oszacowania błędów OOB lasu powinny być bardzo zbliżone.Spróbuj użyć modeli trainControl(method = "OOB") i train(), które nie będą pasowały do ​​dodatkowych modeli w próbkowanych zestawach danych.

Należy również unikać interfejsu formuły, takiego jak dżuma.

Możesz również spróbować zamiast tego pakować. Ponieważ nie ma losowej selekcji predyktorów na każdej mierzei, można uzyskać dobry wynik z 50-100 resamples (zamiast wielu innych potrzebnych losowo lasów, aby były skuteczne).

Inni mogą się nie zgodzić, ale uważam też, że modelowanie wszystkich posiadanych danych nie zawsze jest najlepszym podejściem. O ile przestrzeń predyktorów nie jest duża, wiele punktów danych będzie bardzo podobnych do innych i nie przyczyni się zbytnio do dopasowania modelu (oprócz dodatkowej złożoności obliczeniowej i śladu obiektu wynikowego). caret ma funkcję o nazwie maxDissim, która może być przydatna do przerzedzania danych (choć nie jest też zbyt skuteczna).