Reutilización de un modelo integrado en R


82

Al construir un modelo en R, ¿cómo guarda las especificaciones del modelo para poder reutilizarlo en datos nuevos? Digamos que construyo una regresión logística sobre datos históricos pero no tendré nuevas observaciones hasta el próximo mes. ¿Cuál es el mejor enfoque?

Cosas que he considerado:

  • Guardar el objeto del modelo y cargarlo en una nueva sesión
  • Sé que algunos modelos se pueden exportar con PMML, pero realmente no he visto nada sobre la importación de PMML

Simplemente, estoy tratando de tener una idea de lo que hace cuando necesita usar su modelo en una nueva sesión.

Gracias por adelantado.


Bueno, siempre puede "guardar" una fórmula modelo y proporcionar datos actualizados en el dataargumento ... suponiendo que lo entendí correctamente ...
aL3xa

Hmm, ¿qué quieres decir con reutilización? ¿Predecir las nuevas observaciones o actualizar el ajuste del modelo para usar las nuevas observaciones más las antiguas?
Gavin Simpson

@Gavin. Quiero usar el modelo que desarrollé para predecir nuevos valores en datos que aún no tengo y que podrían no tener por algún tiempo.
Btibert3

1
@ Bitbert3 OK, entonces la sección de apertura de mi respuesta es lo que haría. Guardar el objeto del modelo en el disco es más que aceptable, pero es importante guardar el código / script R utilizado para generar el modelo en primer lugar para que su investigación / modelado sea reproducible.
Gavin Simpson

Respuestas:


143

Reutilizar un modelo para predecir nuevas observaciones

Si el modelo no es computacionalmente costoso, tiendo a documentar todo el proceso de construcción del modelo en un script R que vuelvo a ejecutar cuando es necesario. Si un elemento aleatorio está involucrado en el ajuste del modelo, me aseguro de establecer una semilla aleatoria conocida.

Si el modelo es computacionalmente costoso de calcular, todavía uso un script como el anterior, pero guardo los objetos del modelo usando save()into y rda object. Luego tiendo a modificar el script de modo que si el objeto guardado existe, lo cargue o, si no, reajuste el modelo, usando una if()...elsecláusula simple envuelta alrededor de las partes relevantes del código.

Al cargar su objeto de modelo guardado, asegúrese de volver a cargar los paquetes necesarios, aunque en su caso, si el modelo logit se ajusta a través de glm(), no habrá paquetes adicionales para cargar más allá de R.

Aquí hay un ejemplo:

> 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 quisiera automatizar esto, probablemente haría lo siguiente en 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)

Por supuesto, el código de generación de datos sería reemplazado por un código que cargue sus datos reales.

Actualizar un modelo previamente ajustado con nuevas observaciones

Si desea reajustar el modelo utilizando nuevas observaciones adicionales. Entonces update()es una función útil. Todo lo que hace es reajustar el modelo con uno o más de los argumentos del modelo actualizados. Si desea incluir nuevas observaciones en los datos utilizados para ajustar el modelo, agregue las nuevas observaciones al marco de datos pasado al argumento 'data'y luego haga lo siguiente:

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

donde m1es el ajuste del modelo original, guardado, . ~ .son los cambios de fórmula del modelo, que en este caso significa incluir todas las variables existentes en los lados izquierdo y derecho de ~(en otras palabras, no hacer cambios en la fórmula del modelo), y dfes el marco de datos utilizado para ajustarse al modelo original, ampliado para incluir las observaciones recientemente disponibles.

Aquí hay un ejemplo de trabajo:

> 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

Otros han mencionado en los comentarios formula(), que extraen la fórmula de un modelo ajustado:

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

Sin embargo, si el ajuste del modelo implica argumentos adicionales, como 'family'o 'subset'argumentos en funciones de ajuste del modelo más complejas. Si update()hay métodos disponibles para la función de ajuste de su modelo (que son para muchas funciones de ajuste comunes, como glm()), proporciona una forma más sencilla de actualizar un ajuste de modelo que extraer y reutilizar la fórmula del modelo.

Si tiene la intención de hacer todo el modelado y la predicción futura en R, realmente no parece tener mucho sentido abstraer el modelo a través de PMML o similar.


1
+1 y si tuviera la amabilidad de resistirse a editar sus respuestas para que encajen en cualquier respuesta que esté preparando ... ;-)
Joris Meys

¡@Joris no es una perra precognitiva! ;-) +1 para update
Gavin Simpson

1
Esta es una gran respuesta. Espero que alguien seleccione las respuestas SO [r] como esta y las junte como un tutorial.
JD Long

1
Excelente respuesta. Gracias por los ejemplos que ha dado.
nhern121

1
Exactamente lo que estaba buscando. Quiero hacer +1000 ... Gracias
Adjeiinfo

7

Si usa el mismo nombre del marco de datos y las variables, puede (al menos para lm()y glm()) usar la función updateen el modelo guardado:

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)

Por supuesto, esto es sin ninguna preparación de los datos y así sucesivamente. Simplemente reutiliza el conjunto de especificaciones del modelo. Tenga en cuenta que si cambia los contrastes mientras tanto, el nuevo modelo se actualiza con los nuevos contrastes, no con el anterior.

Entonces, el uso de un script es en la mayoría de los casos la mejor respuesta. Se pueden incluir todos los pasos en una función de conveniencia que solo toma el marco de datos, para que pueda obtener el script y luego usar la función en cualquier conjunto de datos nuevo. Vea también la respuesta de Gavin para eso.

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.