Jak mogę zapisywać pliki równolegle bez automatycznego zwiększania rozmiaru pliku?

9

Mam 2 skrypty, które robią dokładnie to samo.

Ale jeden skrypt tworzy 3 pliki RData o wadze 82,7 KB, a drugi skrypt tworzy 3 pliki RData o wadze 120 KB.

pierwszy nie jest równoległy:

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

 })

Drugi jest równoległy:

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)

drugi skrypt tworzy pliki ważące o 42% więcej.

Jak mogę zapisywać pliki równolegle bez automatycznego zwiększania rozmiaru pliku?

Dima Ha
źródło
Czy chcesz zmniejszyć ogólny rozmiar plików modeli, czy jest to bardziej techniczna ciekawość, dlaczego pliki są większe? Jakiego większego celu szukasz?
Roger-123
Musisz zablokować dostęp do pliku, gdy jest on zapisywany przez wątek. Inny sposób? plik zostanie uszkodzony.
Profesor08,
@ Profesor08 Jak zablokować dostęp do pliku podczas jego zapisu?
Dima Ha
@ Roger-123 Próbuję zmniejszyć rozmiar pamięci zapisanych plików.
Dima Ha
@DimaHa może próbować google coś takiego, r lang lock filea po 5 sekundach znajdziesz żądany pakiet cran.r-project.org/web/packages/filelock/filelock.pdf
Profesor08

Odpowiedzi:

2

Jak wspomnieli inni, w plikach lub podobnych obiektach może znajdować się niewielka ilość informacji o środowisku, których prawdopodobnie nie zauważysz, z wyjątkiem tego, że pliki są tak małe.

Jeśli interesuje Cię tylko rozmiar pliku, spróbuj zapisać modele na jednej liście, a następnie zapisz je w jednym pliku. ddplymożemy obsłużyć tylko data.frame w wyniku działania funkcji, więc musimy użyć dlplyzamiast tego, aby nakazać mu zapisanie wyników na liście. W ten sposób zapisano tylko jeden plik o rozmiarze 60 KB.

Oto przykład tego, o czym mówię:

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
źródło
3

Nie używałem ddply do równoległego zapisywania obiektów, więc sądzę, że plik staje się znacznie większy, ponieważ kiedy zapisujesz obiekt modelu, przenosi on również pewne informacje o środowisku, z którego jest zapisywany.

Więc używając powyższego kodu ddply, rozmiary mam:

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

Istnieją dwie opcje, jedna z nich to 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

Lub użyć saveRDS (i ddply?), Ponieważ masz tylko jeden obiekt do zapisania:

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 

Zrobisz readRDSzamiast, loadaby uzyskać plik:

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  

Możemy spojrzeć na współczynniki w porównaniu z obiektem rda:

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  

Obiekty nie są identyczne z powodu części środowiska, ale pod względem przewidywania lub innych rzeczy, do których zwykle go używamy, działa:

identical(predict(m1,data.frame(iris[1:10,])),predict(m2,data.frame(iris[1:10,])))
StupidWolf
źródło