2017-02-14 1 views
3

Dies ist eine knifflige, da ich kein reproduzierbares Beispiel liefern kann, aber ich hoffe, dass andere Erfahrung damit haben.saveRDS aufblasen Größe des Objekts

Im Wesentlichen habe ich eine Funktion, die eine große Menge von Daten aus einem DB holt, reinigt und die Größe reduziert und einige Parameter durchläuft, um eine Reihe von LM-Modellobjekten, Parameterwerten und anderen Referenzwerten zu erzeugen. Dies wird zu einer komplexen Listenstruktur zusammengefasst, die ungefähr 10 MB groß ist.

Es soll dann als eine RDS-Datei auf AWS S3 gespeichert werden, wo es in einer Produktionsumgebung abgerufen wird, um Vorhersagen zu erstellen.

z.B.

db.connection <- db.connection.object 


build_model_list <- function(db.connection) { 


clean_and_build_models <- function(db.connection, other.parameters) { 


get_db_data <- function(db.connection, some.parameters) {# Retrieve db data} ## Externally defined 

db.data <- get_db_data() 


build_models <- function(db.data, some.parameters) ## Externally defined 

clean_data <- function(db.data, some.parameters) {# Cleans and filters data based on parameters} ## Externally defined 


clean.data <- clean_data() 


lm_model <- function(clean.data) {# Builds lm model based on clean.data} ## Externally defined 

lm.model <- lm_model() 


return(list(lm.model, other.parameters))} ## Externally defined 


looped.model.object <- llply(some.parameters, clean_and_build_models) 

return(looped.model.object)} 


model.list <- build_model_list() 

saveRDS(model.list, "~/a_place/model_list.RDS") 

Die Frage, die ich bekommen habe, ist, dass ‚model.list‘ Objekt, das nur 10 MB im Speicher wird auf viele GBs aufzublasen, wenn ich vor Ort als RDS speichern oder versuchen zu AWS S3 zu laden.

Ich sollte beachten, dass obwohl die Funktion sehr große Mengen von Daten verarbeitet (~ 5 Millionen Zeilen), die Daten in den Ausgaben nicht mehr als ein paar hundert Zeilen verwendet werden.

Lesen der begrenzten Info zu diesem auf Stack Exchange, ich habe gefunden, dass das Verschieben einiger der extern definierten Funktionen (als Teil eines Pakets) innerhalb der Hauptfunktion (z. B. clean_data und lm_model) hilft, die RDS-Speichergröße zu reduzieren.

Dies hat jedoch einige große Nachteile.

Erstens ist es Versuch und Irrtum und folgt keiner klaren logischen Reihenfolge, mit häufigen Abstürzen und ein paar Stunden, um das Listenobjekt aufzubauen, es ist ein sehr langer Debugging-Zyklus.

Zweitens bedeutet es, dass meine Hauptfunktion viele Hunderte von Zeilen lang sein wird, die zukünftige Änderungen und Debugging viel komplizierter machen werden.

Meine Frage an Sie ist:

Hat jemand vor diesem Problem gestoßen?

Irgendwelche Hypothesen, was das verursacht?

Hat jemand eine logische Versuchs- und Irrtumslösung gefunden?

Danke für Ihre Hilfe.

+0

Möglicherweise im Zusammenhang mit dieser http://r.789695.n4.nabble.com/Model-Objekt-when-generated-in-a-function-saves-entire-environment-when-saved-td4723192.html – kennyB

Antwort

2

Es dauerte ein wenig zu graben, aber ich fand tatsächlich eine Lösung am Ende.

Es stellt sich heraus, dass es die lm-Modellobjekte waren, die die schuldige Partei waren. Auf der Grundlage dieser sehr hilfreichen Artikel:

https://blogs.oracle.com/R/entry/is_the_size_of_your

Es stellt sich heraus, dass die lm.object $ terms Komponente eine Komponente eine Umgebung enthält, die Verweise auf die Objekte in der globalen Umwelt, wenn das Modell gebaut wurde. Unter Umständen wird beim Speichern von RDS R versucht, die Umgebungsobjekte in das Speicherobjekt einzuzeichnen.

Da ich ~ 0,5GB in der globalen Umgebung und eine Liste Array von ~ 200 lm Modellobjekte hatte, verursacht dies das RDS-Objekt zu dramatisch aufblasen, da es tatsächlich versucht, ~ 100 GB Daten zu komprimieren.

Um zu testen, ob dies das Problem verursacht. Führen Sie den folgenden Code aus:

as.matrix(lapply(lm.object, function(x) length(serialize(x,NULL)))) 

Dies wird Ihnen sagen, ob die $ terms-Komponente aufbläht.

Der folgende Code wird die Umweltreferenzen aus der $ terms Komponente entfernen:

rm(list=ls(envir = attr(lm.object$terms, ".Environment")), envir = attr(lm.object$terms, ".Environment")) 

gewarnt, obwohl es auch alle globalen Umwelt Objekte entfernen wird es verweist.

Verwandte Themen