Comment puis-je enregistrer des fichiers en parallèle sans augmenter automatiquement la taille du fichier?

9

J'ai 2 scripts qui font exactement la même chose.

Mais un script produit 3 fichiers RData qui pèsent 82,7 Ko, et l'autre script crée 3 fichiers RData qui pèse 120 Ko.

le premier est sans parallèle:

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

 })

La seconde est à parallèle:

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)

le deuxième script crée des fichiers qui pèsent 42% de plus.

Comment puis-je enregistrer des fichiers en parallèle sans augmenter automatiquement la taille du fichier?

Dima Ha
la source
Cherchez-vous à réduire la taille globale des fichiers des modèles ou est-ce une curiosité plus technique pour savoir pourquoi les fichiers sont plus gros? Quel est le plus grand objectif que vous recherchez?
Roger-123
Vous devez bloquer l'accès au fichier pendant qu'il écrit par le thread. Autrement? le fichier sera cassé.
Profesor08
@ Profesor08 Comment bloquer l'accès au fichier pendant qu'il écrit?
Dima Ha
@ Roger-123 J'essaie de réduire la taille de la mémoire des fichiers enregistrés.
Dima Ha
@DimaHa peut essayer de google quelque chose comme r lang lock fileet après 5 secondes, vous trouverez le package souhaité cran.r-project.org/web/packages/filelock/filelock.pdf
Profesor08

Réponses:

2

Comme d'autres l'ont mentionné, il peut y avoir une petite quantité d'informations sur l'environnement qui est enregistrée dans les fichiers ou similaire que vous ne remarquerez probablement pas, sauf que les fichiers sont si petits.

Si la taille du fichier vous intéresse uniquement, essayez d'enregistrer les modèles dans une seule liste, puis enregistrez-la dans un fichier. ddplyne peut gérer un data.frame qu'à la suite de la fonction, nous devons donc utiliser à la dlplyplace pour lui dire de stocker les résultats dans une liste. Cette opération a enregistré dans un seul fichier qui était 60k.

Voici un exemple de ce dont je parle:

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
la source
3

Je n'ai pas utilisé ddply pour paralléliser la sauvegarde d'objets, donc je suppose que le fichier devient beaucoup plus volumineux car lorsque vous enregistrez un objet modèle, il contient également des informations sur l'environnement à partir duquel il est enregistré.

Donc, en utilisant votre code ddply ci-dessus, les tailles que j'ai sont les suivantes:

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

Il existe deux options, l'une consiste à utiliser 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

Ou d'utiliser saveRDS (et ddply?) Car vous n'avez qu'un seul objet à enregistrer:

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 

Vous ferez readRDSau lieu de loadrécupérer le fichier:

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  

On peut regarder les coefficients en comparaison avec l'objet 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  

Les objets ne sont pas identiques à cause des parties de l'environnement, mais en termes de prédiction ou d'autres choses pour lesquelles nous l'utilisons normalement, cela fonctionne:

identical(predict(m1,data.frame(iris[1:10,])),predict(m2,data.frame(iris[1:10,])))
StupidWolf
la source