Wie kann ich Dateien parallel speichern, ohne die Dateigröße automatisch zu erhöhen?

9

Ich habe 2 Skripte, die genau das Gleiche tun.

Ein Skript erstellt jedoch 3 RData-Dateien mit einem Gewicht von 82,7 KB und das andere Skript erstellt 3 RData-Dateien mit einem Gewicht von 120 KB.

der erste ist ohne Parallele:

library("plyr")
ddply(.data = iris,
      .variables = "Species",
      ##.parallel=TRUE,##Without parallel
      .fun = function(SpeciesData){

      #Create Simple Model -------------------------------------------------------------  
      Model <- lm(formula = "Sepal.Length~Sepal.Width+Petal.Length+Petal.Width",data = SpeciesData)

      #Save The Model -------------------------------------------------------------               
       save(Model,
            compress = FALSE,
            file = gsub(x =  "Species.RData",
                        pattern = "Species",
                        replacement = unique(SpeciesData$Species)))

 })

Der zweite ist mit parallel:

library("plyr")
doSNOW::registerDoSNOW(cl<-snow::makeCluster(3))
ddply(.data = iris,
      .variables = "Species",
      .parallel=TRUE,##With parallel
      .fun = function(SpeciesData){

      #Create Simple Model -------------------------------------------------------------  
      Model <- lm(formula = "Sepal.Length~Sepal.Width+Petal.Length+Petal.Width",data = SpeciesData)

      #Save The Model -------------------------------------------------------------               
       save(Model,
            compress = FALSE,
            file = gsub(x =  "Species.RData",
                        pattern = "Species",
                        replacement = unique(SpeciesData$Species)))

 })
snow::stopCluster(cl)

Das zweite Skript erstellt Dateien, die 42% mehr wiegen.

Wie kann ich Dateien parallel speichern, ohne die Dateigröße automatisch zu erhöhen?

Dima Ha
quelle
Möchten Sie die Gesamtdateigröße der Modelle reduzieren, oder ist dies eher eine technische Neugier, warum die Dateien größer sind? Was ist das größere Ziel, das Sie suchen?
Roger-123
Sie müssen den Zugriff auf die Datei blockieren, während sie vom Thread geschrieben wird. Ein anderer Weg? Datei wird beschädigt.
Profesor08
@ Profesor08 Wie blockiere ich den Zugriff auf Dateien während des Schreibens?
Dima Ha
@ Roger-123 Ich versuche die Speichergröße der gespeicherten Dateien zu reduzieren.
Dima Ha
@DimaHa kann versuchen, so etwas wie zu googeln r lang lock fileund nach 5 Sekunden finden Sie das gewünschte Paket cran.r-project.org/web/packages/filelock/filelock.pdf
Profesor08

Antworten:

2

Wie andere bereits erwähnt haben, gibt es möglicherweise eine kleine Menge an Informationen über die Umgebung, die in den Dateien oder ähnlichem gespeichert wird, die Sie wahrscheinlich nicht bemerken würden, außer dass die Dateien so klein sind.

Wenn Sie nur an der Dateigröße interessiert sind, speichern Sie die Modelle in einer einzigen Liste und speichern Sie diese dann in einer Datei. ddplykann nur einen data.frame als Ergebnis der Funktion verarbeiten, daher müssen wir ihn dlplystattdessen anweisen , die Ergebnisse in einer Liste zu speichern. Dadurch wurde nur eine Datei gespeichert, die 60 KB groß war.

Hier ist ein Beispiel dafür, wovon ich spreche:

library("plyr")
doSNOW::registerDoSNOW(cl<-snow::makeCluster(3))
models<-dlply(.data = iris,
      .variables = "Species",
      .parallel=TRUE,##With parallel
      .fun = function(SpeciesData){

        #Create Simple Model -------------------------------------------------------------  
        lm(formula = Sepal.Length~Sepal.Width+Petal.Length+Petal.Width, data = SpeciesData)
      })
snow::stopCluster(cl)

save(models, compress= FALSE, file= 'combined_models')
Roger-123
quelle
3

Ich habe ddply nicht zum Parallelisieren von Speicherobjekten verwendet, daher wird die Datei vermutlich viel größer, da sie beim Speichern von Modellobjekten auch einige Informationen über die Umgebung enthält, aus der sie gespeichert wird.

Wenn Sie also Ihren obigen ddply-Code verwenden, habe ich folgende Größen:

sapply(dir(pattern="RData"),file.size)
setosa.RData versicolor.RData  virginica.RData 
       36002            36002            36002 

Es gibt zwei Möglichkeiten, eine ist die Verwendung von purrr / furrr:

library(furrr)
library(purrr)

func = function(SpeciesData){
  Model <- lm(formula = "Sepal.Length~Sepal.Width+Petal.Length+Petal.Width",data = SpeciesData)
  save(Model,
       compress = FALSE,
       file = gsub(x =  "Species.RData",
                   pattern = "Species",
                   replacement = unique(SpeciesData$Species)))
}

split(iris,iris$Species) %>% future_map(func)

sapply(dir(pattern="RData"),file.size)
    setosa.RData versicolor.RData  virginica.RData 
           25426            27156            27156

Oder um saveRDS (und ddply?) Zu verwenden, da Sie nur ein Objekt zum Speichern haben:

ddply(.data = iris,
      .variables = "Species",
      .parallel=TRUE,##With parallel
      .fun = function(SpeciesData){
        Model <- lm(formula = "Sepal.Length~Sepal.Width+Petal.Length+Petal.Width",data = SpeciesData)
        saveRDS(Model,
             gsub(x =  "Species.rds",
                         pattern = "Species",
                         replacement = unique(SpeciesData$Species)))

      })

sapply(dir(pattern="rds"),file.size)
    setosa.rds versicolor.rds  virginica.rds 
          6389           6300           6277 

Sie werden tun, readRDSanstatt loaddie Datei zu erhalten:

m1 = readRDS("setosa.rds")
m1
Call:
lm(formula = "Sepal.Length~Sepal.Width+Petal.Length+Petal.Width", 
    data = SpeciesData)

Coefficients:
 (Intercept)   Sepal.Width  Petal.Length   Petal.Width  
      2.3519        0.6548        0.2376        0.2521  

Wir können die Koeffizienten im Vergleich zum rda-Objekt betrachten:

m2 = get(load("setosa.RData"))
m2

Call:
lm(formula = "Sepal.Length~Sepal.Width+Petal.Length+Petal.Width", 
    data = SpeciesData)

Coefficients:
 (Intercept)   Sepal.Width  Petal.Length   Petal.Width  
      2.3519        0.6548        0.2376        0.2521  

Die Objekte sind aufgrund der Umgebungsteile nicht identisch, aber in Bezug auf Vorhersage oder andere Dinge, für die wir sie normalerweise verwenden, funktioniert es:

identical(predict(m1,data.frame(iris[1:10,])),predict(m2,data.frame(iris[1:10,])))
Blöder Wolf
quelle