Réutilisation d’un modèle construit en R

Lors de la création d’un modèle en R, comment enregistrez-vous les spécifications du modèle pour pouvoir les réutiliser sur de nouvelles données? Disons que je construis une régression logistique sur les données historiques mais que je n’aurai pas de nouvelles observations avant le mois prochain. Quelle est la meilleure approche?

Les choses que j’ai considérées:

  • Enregistrement de l’object de modèle et chargement dans une nouvelle session
  • Je sais que certains modèles peuvent être exportés avec PMML, mais n’ont rien vu sur l’importation de PMML

Simplement, j’essaie d’avoir une idée de ce que vous faites lorsque vous devez utiliser votre modèle dans une nouvelle session.

Merci d’avance.

Réutiliser un modèle pour prévoir de nouvelles observations

Si le modèle n’est pas coûteux en calcul, j’ai tendance à documenter l’intégralité du processus de création de modèle dans un script R que je réexécute en cas de besoin. Si un élément aléatoire est impliqué dans l’ajustement du modèle, je m’assure de définir une graine aléatoire connue.

Si le calcul est coûteux à calculer, j’utilise toujours un script comme ci-dessus, mais enregistre les objects du modèle en utilisant save() dans et rda object. J’ai alors tendance à modifier le script de telle sorte que si l’object enregistré existe, chargez-le ou sinon, remettez le modèle en place, en utilisant une simple clause if()...else entourant les parties pertinentes du code.

Lors du chargement de votre object modèle sauvegardé, assurez-vous de recharger tous les paquets requirejs, bien que dans votre cas, si le modèle logit était ajusté via glm() , aucun paquet supplémentaire ne serait chargé au-delà de R.

Voici un exemple:

 > set.seed(345) > df <- data.frame(x = rnorm(20)) > df <- transform(df, y = 5 + (2.3 * x) + rnorm(20)) > ## model > m1 <- lm(y ~ x, data = df) > ## save this model > save(m1, file = "my_model1.rda") > > ## a month later, new observations are available: > newdf <- data.frame(x = rnorm(20)) > ## load the model > load("my_model1.rda") > ## predict for the new `x`s in `newdf` > predict(m1, newdata = newdf) 1 2 3 4 5 6 6.1370366 6.5631503 2.9808845 5.2464261 4.6651015 3.4475255 7 8 9 10 11 12 6.7961764 5.3592901 3.3691800 9.2506653 4.7562096 3.9067537 13 14 15 16 17 18 2.0423691 2.4764664 3.7308918 6.9999064 2.0081902 0.3256407 19 20 5.4247548 2.6906722 

Si vous voulez automatiser cela, alors je ferais probablement ce qui suit dans un script:

 ## data df <- data.frame(x = rnorm(20)) df <- transform(df, y = 5 + (2.3 * x) + rnorm(20)) ## check if model exists? If not, refit: if(file.exists("my_model1.rda")) { ## load model load("my_model1.rda") } else { ## (re)fit the model m1 <- lm(y ~ x, data = df) } ## predict for new observations ## new observations newdf <- data.frame(x = rnorm(20)) ## predict predict(m1, newdata = newdf) 

Bien entendu, le code de génération de données serait remplacé par du code chargeant vos données réelles.

Mise à jour d'un modèle précédemment ajusté avec de nouvelles observations

Si vous souhaitez replacer le modèle en utilisant de nouvelles observations supplémentaires. Ensuite, update() est une fonction utile. Tout ce qu'il fait, c'est de remettre le modèle à jour avec un ou plusieurs arguments du modèle mis à jour. Si vous souhaitez inclure de nouvelles observations dans les données utilisées pour ajuster le modèle, ajoutez les nouvelles observations au bloc de données transmis à l'argument 'data' , puis procédez comme suit:

 m2 <- update(m1, . ~ ., data = df) 

m1 est l'original, l'ajustement du modèle enregistré,. . ~ . est la modification de la formule du modèle, qui dans ce cas signifie inclure toutes les variables existantes à gauche et à droite de ~ (en d'autres termes, ne pas modifier la formule du modèle), et df est la trame de données utilisée pour l'original modèle, élargi pour inclure les observations nouvellement disponibles.

Voici un exemple de travail:

 > set.seed(123) > df <- data.frame(x = rnorm(20)) > df <- transform(df, y = 5 + (2.3 * x) + rnorm(20)) > ## model > m1 <- lm(y ~ x, data = df) > m1 Call: lm(formula = y ~ x, data = df) Coefficients: (Intercept) x 4.960 2.222 > > ## new observations > newdf <- data.frame(x = rnorm(20)) > newdf <- transform(newdf, y = 5 + (2.3 * x) + rnorm(20)) > ## add on to df > df <- rbind(df, newdf) > > ## update model fit > m2 <- update(m1, . ~ ., data = df) > m2 Call: lm(formula = y ~ x, data = df) Coefficients: (Intercept) x 4.928 2.187 

D'autres ont mentionné dans la formula() commentaires formula() , qui extrait la formule d'un modèle ajusté:

 > formula(m1) y ~ x > ## which can be used to set-up a new model call > ## so an alternative to update() above is: > m3 <- lm(formula(m1), data = df) 

Cependant, si l'ajustement du modèle implique des arguments supplémentaires, tels que 'family' arguments 'family' ou 'subset' dans des fonctions d'ajustement de modèle plus complexes. Si les méthodes update() sont disponibles pour votre fonction d'ajustement de modèle (elles le sont pour de nombreuses fonctions d'ajustement courantes, telles que glm() ), elles simplifient la mise à jour d'un modèle.

Si vous avez l'intention de faire toutes les modélisations et les prédictions futures dans R, il ne semble pas vraiment utile d'extraire le modèle via PMML ou similaire.

Si vous utilisez le même nom que le dataframe et les variables, vous pouvez (au moins pour lm() et glm() ) utiliser la update à update la fonction sur le modèle enregistré:

 Df <- data.frame(X=1:10,Y=(1:10)+rnorm(10)) model <- lm(Y~X,data=Df) model Df <- rbind(Df,data.frame(X=2:11,Y=(10:1)+rnorm(10))) update(model) 

Ceci est bien sûr sans aucune préparation des données et ainsi de suite. Il réutilise simplement le jeu de spécifications du modèle. Sachez que si vous modifiez les contrastes entre-temps, le nouveau modèle est mis à jour avec les nouveaux contrastes, pas l'ancien.

L'utilisation d'un script est donc dans la plupart des cas la meilleure réponse. On pourrait inclure toutes les étapes dans une fonction pratique qui prend uniquement le dataframe, de sorte que vous pouvez générer le script, puis utiliser la fonction sur tout nouveau jeu de données. Voir aussi la réponse de Gavin pour cela.