Contexto

El contexto de los datos es una estructura de 3000 registros en donde hay una relación entre la inversión económica en publicidad digital que hace una empresa y los ingresos de la misma. Los datos pueden asociarse a cualquier empresa que invierta en publicidad digital y que evalué la relación con utilidades económicas.

Hay dos variables de interés:

Objetivo

Implementar evaluar y comparar modelo de regresión exponencial contra modelos polinomiales y logarítmicos.

Con los mismos datos se pretende identificar si el modelo exponencial cumple con los postulados de linealidad, homocedasticidad, normalidad e independencia de residuos.

Además el modelo de regresión exponencial será evaluado mediante las métricas r square y RMSE comparando éste contra los otros modelos predictivos con los mismos datos de entrenamiento y validación.

Se espera que la evaluación de los modelos tengan un 90% o superior en r square para ser considerados como procesos predictivos de calidad y se interpretará el mejor modelo el que tenga más bajo estadístico RMSE.

Descripción

Cargar librerías

Se cargan las librerías previamente instaladas en el entorno R Studio

# install.packages("readr")
# install.packages("tidyverse")
# install.packages("psych")
# install.packages("dplyr")
# install.packages("ggplot2")
# install.packages("caret")
# install.packages("broom")
# install.packages("lmtest")
# install.packages("car")
# install.packages("stats")
# install.packages("flextable")
# install.packages("officer")
# install.packages("patchwork")
# install.packages("performance")
# install.packages("see")

library(readr)        # cargar datos datos
library(tidyverse)    # Para manipular
library (psych)       # Para descriobir datos
library(dplyr)        # Manipulación de datos
library(ggplot2)      # gráficos
library(caret)        # partición de datos
library(broom)        # tidy modelos
library(lmtest)       # Durbin-Watson
library(car)          # VIF y diagnóstico
library(stats)        # lm, shapiro.test
library(patchwork)    # Graficos organizados en columnas renglones
# Tablas compatibles con Word
library(flextable)
library(officer)

library(performance) # Para evaluar postulados de modelos
library(see)         # PAra evaluar postulados de modelos dependencia de performance

Cargar funciones

Se cargan las funciones previamente codificadas, algunas repetidas de los otros modelos predictivos y otras ajustadas para la adecuada ejecución de este caso de estudio. Las funciones se encuentran en el enlace de github.com en el espacio del autor:

https://raw.githubusercontent.com/rpizarrog/Libro-Aprendizaje-Automatico.-Casos-de-Estudio-con-R-y-Python/refs/heads/main/R%20MarkDown/funciones/funciones%20para%20exponencial%20RExp.R

# source("../funciones/funciones para exponencial RExp.R")
source("https://raw.githubusercontent.com/rpizarrog/Libro-Aprendizaje-Automatico.-Casos-de-Estudio-con-R-y-Python/refs/heads/main/R%20MarkDown/funciones/funciones%20para%20exponencial%20RExp.R")

Cargar datos

Se cargan los datos con la función f_cargar_datos() del enlace url de gitub.com: https://raw.githubusercontent.com/rpizarrog/Libro-Aprendizaje-Automatico.-Casos-de-Estudio-con-R-y-Python/refs/heads/main/datos/inversion_publicidad_e_ingresos.csv

datos <- f_cargar_datos("https://raw.githubusercontent.com/rpizarrog/Libro-Aprendizaje-Automatico.-Casos-de-Estudio-con-R-y-Python/refs/heads/main/datos/inversion_publicidad_e_ingresos.csv")

Visualizar datos

Se presentan en modo tabla los primeros y últimos registros del conjunto de datos original con la función f_visualizar_head_tail_reducido_word(). Los datos se de origen tienen dos posiciones decimales en las columnas inversion e ingresos.

f_visualizar_head_tail_reducido_word(datos)

inversion

ingresos

14.27

3136.86

11.57

2633.91

3.66

735.15

6.43

1321.73

11.55

2995.15

1.48

633.41

9.86

2191.81

17.36

7456.11

5.8

1106.76

12.04

1811.05

...

...

10.76

2511.47

18.51

9014.26

19.26

8480.39

14.53

5199.28

2.82

817.55

11.87

3527.05

12.47

3772.59

5.04

1163.03

5.03

675.12

5.15

980.72

Descripción estadística

La media aritmética de la variable inversion es alrededor de 10.46 con desviación estándar de 5.58; la media aritmética de la variable ingresos es 3292.89 con una desviación estándar de 2614.84.

f_describir_datos(datos)
## $describe
##           vars    n    mean      sd  median trimmed     mad    min      max
## inversion    1 3000   10.46    5.48   10.57   10.45    7.01   1.00    19.99
## ingresos     2 3000 3292.89 2614.84 2378.60 2922.31 2179.86 380.58 12670.12
##              range skew kurtosis    se
## inversion    18.99 0.00    -1.20  0.10
## ingresos  12289.54 1.06     0.22 47.74
## 
## $structure
## [1] "'data.frame':\t3000 obs. of  2 variables:\n $ inversion: num  14.27 11.57 3.66 6.43 11.55 ...\n $ ingresos : num  3137 2634 735 1322 2995 ..."

Desarrollo

Ahora siguiendo la metodología se parten los datos originales en 70% datos de entrenamiento y 30% datos de validación, usando la función f_particionar_datos():

particion <- f_particionar_datos(datos)

datos_entrenamiento <- particion$datos_entrenamiento
datos_validacion <- particion$datos_validacion

Se presentan los primeros y últimos seis registros de los datos de entrenamiento:

f_visualizar_head_tail_reducido_word(datos_entrenamiento, n=6)

inversion

ingresos

4.79

990.4

13.76

3702.78

1.4

715.41

17.23

7582.77

2.67

777.97

3.14

823.83

...

...

5

1435.39

12.57

3026.77

11.82

3125.27

15.71

5485.21

17.05

6354.96

6.05

1220.9

Ahora los datos de validación

f_visualizar_head_tail_reducido_word(datos_validacion, n=6)

inversion

ingresos

14.27

3136.86

11.57

2633.91

1.48

633.41

5.39

1246.62

3.92

881.46

7.78

1766

...

...

10.75

3209.89

6.81

1543.35

10.76

2511.47

14.53

5199.28

11.87

3527.05

5.15

980.72

Modelo exponencial

Se construye el modelo de regresión exponencial usando la función f_construir_modelo_exp() con los datos de entrenamiento y las variables independiente inversion y dependiente ingresos respectivamente; el modelo se guarda en la variable llamada modelo_exp.

modelo_exp <- f_construir_modelo_exp(datos, "inversion", "ingresos")
f_ecuaciones_modelos(
  modelos = list(modelo_exp),
  nombres = c("Modelo Exponencial")
)
## 
## ============================
## Modelo Exponencial 
## ============================
## 
## Coeficientes:
## (Intercept)   inversion 
##      6.1999      0.1502 
## 
## Ecuación:
##  ŷ = 492.6852 * e^(0.1502 * x)

Modelos polinomial y logarítmico

Se construyen los modelos polinomiales de segundo y quinto orden así como el modelo de regresión logarítmico, con los cuales se pretende comparar el rendimiento predictivo de los modelos.

modelo_RL <- f_construir_modelo_log(datos, "inversion", "ingresos")
modelo_RP2 <- f_construir_modelo(datos, "inversion", "ingresos" , 2)
modelo_RP5 <- f_construir_modelo(datos, "inversion", "ingresos" , 5)

Las funciones deben encapsular esta sintaxis para la construcción de los cuatro modelos:

  • modelo_exp <- lm(log(ingresos) ~ inversion, data = datos_entrenamiento)

  • modelo_RL <- lm(ingresos ~ log(inversion), data = datos_entrenamiento)

  • modelo_RP2 <- lm(ingresos ~ poly(inversion, 2, raw = TRUE), data = datos_entrenamiento)

  • modelo_RP5 <- lm(ingresos ~ poly(inversion, 5, raw = TRUE), data = datos_entrenamiento)

Ya que se tienen los cuatro modelos, exponencial, logarítmico y polinomial de segundo y quinto orden, ahora se verifica si estos cumplen con los postulados de linealidad, homocedasticidad, normalidad e independencia de residuos.

Postulados de los modelos

Linealidad

En la FIGURA todos los modelos se observa que hay cierta linealidad de las estimaciones, aunque deficiente el modelo de regresión logarítmica. No se observa una linea recta en la tendencia de la relación de la inversión y los ingresos, por lo que de inicio se descartó el modelo de regresión lineal simple.

modelos <- list(modelo_exp, modelo_RL, modelo_RP2, modelo_RP5)

nombres <- c(
  "Exponencial",
  "Logarítmico",
  "Polinomial 2",
  "Polinomial 5"
)

f_matriz_dispersion_modelos_tendencia(
  modelos,
  datos,
  "inversion",
  "ingresos",
  nombres
)

De la librería “performance” y “see” previamente instaladas, en R se puede verificar postulados y específicamente la linealidad de los modelos con check_model(modelo, check = “linearity”); con la función extraer_plot() se van guardando los gráficos de los valores ajustados y los residuos para luego observar el postulado de linealidad.

En la FIGURA Se aprecia que el mejor modelo que ofrece linealidad es el exponencial arriba izquierda, luego, abajo los modelos polinomiales ofrecen linealidad de manera parcial el de segundo grado y mas acertado el de quinto orden, el modelo que no cumple este postulado es de regresión logarítimica.

En su libro MONTGOMERY menciona que un gráfico de los residuos frente a los valores ajustados son útiles para detectar varios tipos comunes de deficiencias del modelo, por ejemplo la linealidad. Si este gráfico se parece coinciden la linea verde y negra punteada al centro se está interpretando que el modelo ofrece linealidad en los residuos de lo contrario es posible que decir que hay deficiencias en el modelo.

#-----------------------------------------
# FUNCIÓN para detectar postulado de linealidad en los modelos de regresión

extraer_plot <- function(modelo){
  
  # abrir dispositivo temporal invisible
  grDevices::png(filename = tempfile())
  
  p <- plot(check_model(modelo, check = "linearity"))
  
  dev.off()
  
  return(p[[1]])
}

#-----------------------------------------
# Generar gráficos
#-----------------------------------------
g1 <- extraer_plot(modelo_exp) + ggtitle("Exponencial")
g2 <- extraer_plot(modelo_RL)  + ggtitle("Logarítmico")
g3 <- extraer_plot(modelo_RP2) + ggtitle("Polinomial 2")
g4 <- extraer_plot(modelo_RP5) + ggtitle("Polinomial 5")

#-----------------------------------------
# PANEL FINAL
#-----------------------------------------
(g1 | g2) / (g3 | g4)  + 
  plot_annotation(title = "Evaluación de linealidad de modelos")

Homocedasticidad

El análisis gráfico de los residuos indica que ninguno de los modelos verificados cumple estrictamente con el supuesto de homocedasticidad. Sin embargo, el modelo polinomial de segundo grado presenta la mejor aproximación, al mostrar una dispersión de residuos relativamente más uniforme en comparación con los demás modelos. El modelo exponencial exhibe un patrón de heterocedasticidad moderada, mientras que el modelo logarítmico evidencia una clara mala especificación. Por su parte, el modelo polinomial de quinto grado presenta una dispersión aparentemente más controlada.

modelos <- list(modelo_exp, modelo_RL, modelo_RP2, modelo_RP5)

nombres <- c(
  "Exponencial",
  "Logarítmico",
  "Polinomial 2",
  "Polinomial 5"
)

f_matriz_verificar_homocedasticidad(
  modelos,
  datos,
  "inversion",
  "ingresos",
  nombres
)

Con la función check_model(modelo, check = “homogeneity”) se verifica homocedasticidad de los residuos.

En la GRAFICA se observa que únicamente el modelo exponencial ofrece un panorama de dispersión de residuos constantes o que es el que cumple con el postulado de homocedasticidad de manera clara; en contraste, los modelos logarítmico y polinomiales exhiben patrones de varianza creciente, evidenciando problemas de heterocedasticidad.

#-----------------------------------------
# FUNCIÓN para homocedasticidad

extraer_plot_homo <- function(modelo){
  
  # dispositivo temporal invisible
  grDevices::png(filename = tempfile())
  
  p <- plot(check_model(modelo, check = "homogeneity"))
  
  dev.off()
  
  return(p[[1]])
}

#-----------------------------------------
# Generar gráficos
#-----------------------------------------
g1 <- extraer_plot_homo(modelo_exp) + ggtitle("Exponencial")
g2 <- extraer_plot_homo(modelo_RL)  + ggtitle("Logarítmico")
g3 <- extraer_plot_homo(modelo_RP2) + ggtitle("Polinomial 2")
g4 <- extraer_plot_homo(modelo_RP5) + ggtitle("Polinomial 5")

#-----------------------------------------
# PANEL 2x2
#-----------------------------------------
(g1 | g2) / (g3 | g4)  + 
  plot_annotation(title = "Evaluación de homocedasticidad de modelos")

Normalidad

El análisis de normalidad de los residuos indica que ninguno de los modelos cumple estrictamente con el supuesto de normalidad, como lo evidencian los histogramas, los gráficos QQ Plot y los resultados de la prueba de Shapiro-Wilk. Sin embargo, es importante considerar que, debido al tamaño de la muestra, incluso pequeñas desviaciones respecto a la normalidad pueden resultar estadísticamente significativas.

Esta función se ejecuta a continuación:

modelos <- list(modelo_exp, modelo_RL, modelo_RP2, modelo_RP5)

nombres <- c(
  "Exponencial",
  "Logarítmico",
  "Polinomial 2",
  "Polinomial 5"
)

f_matriz_verificar_normalidad(
  modelos,
  datos_entrenamiento,
  "inversion",
  "ingresos",
  nombres
)

Ahora con la sintaxis check_model(modelo, check = “normality”), en la FIGURA visualmente hablando, se distingue que ninguna distribución de los residuales de ningún modelo tiene un comportamiento normal, el que más se acerca es el modelo el exponencial.

# Función para verificar normalidad de residuos
extraer_plot_normalidad <- function(modelo){
  
  # dispositivo temporal invisible
  grDevices::png(filename = tempfile())
  
  p <- plot(check_model(modelo, check = "normality"))
  
  dev.off()
  
  return(p[[1]])
}
#-----------------------------------------
# Generar gráficos
#-----------------------------------------
g1 <- extraer_plot_normalidad(modelo_exp) + ggtitle("Exponencial")
g2 <- extraer_plot_normalidad(modelo_RL)  + ggtitle("Logarítmico")
g3 <- extraer_plot_normalidad(modelo_RP2) + ggtitle("Polinomial 2")
g4 <- extraer_plot_normalidad(modelo_RP5) + ggtitle("Polinomial 5")

#-----------------------------------------
# PANEL 2x2
#-----------------------------------------
(g1 | g2) / (g3 | g4) +
  plot_annotation(title = "Evaluación de normalidad de los residuos")

Independencia de residuos

Se ejecuta la función f_matriz_verificar_independencia_residuos() que recibe los argumentos de los cuatro modelos previamente construidos y calcula la prueba Durbin-Watson, además visualiza que no existe alguna posible correlación de los residuales en todos los modelos.

La prueba Durbin-Watson calcula valores muy cercanos a 2; todos los modelos ofrecen independencia en los residuos, se interpreta que los residuales no tienen correlación en este modelo lo que garantiza que todos los modelos cumplen con el supuesto de independencia de los residuales.

modelos <- list(modelo_exp, modelo_RL, modelo_RP2, modelo_RP5)

nombres <- c(
  "Exponencial",
  "Logarítmico",
  "Polinomial 2",
  "Polinomial 5"
)
f_matriz_verificar_independencia_residuos(
  modelos,
  datos_entrenamiento,
  "inversion",
  "ingresos",
  nombres
)

La independencia de los residuos no se evalúa directamente mediante la función check_model(), sin embargo existen otras alternativas para verificar esta prueba de correlación de residuos.

Coeficientes de los modelos

Se extraen de cada modelos los coeficientes que sirven para construir las ecuaciones matemáticas que permiten deducir las predicciones de acuerdo al modelo exponencial, logarítmico y polinomiales de primer segundo y quinto grado.

Se ejecuta para ello la función f_ecuaciones_modelos() la cual extrae a partir de los modelos, los coeficientes.

f_ecuaciones_modelos(modelos, nombres)
## 
## ============================
## Exponencial 
## ============================
## 
## Coeficientes:
## (Intercept)   inversion 
##      6.1999      0.1502 
## 
## Ecuación:
##  ŷ = 492.6852 * e^(0.1502 * x) 
## 
## ============================
## Logarítmico 
## ============================
## 
## Coeficientes:
##    (Intercept) log(inversion) 
##      -2891.902       2878.404 
## 
## Ecuación:
##  ŷ = -2891.9018 + 2878.4038 * ln(inversion) 
## 
## ============================
## Polinomial 2 
## ============================
## 
## Coeficientes:
##                     (Intercept) poly(inversion, 2, raw = TRUE)1 
##                       1151.4060                       -203.1744 
## poly(inversion, 2, raw = TRUE)2 
##                         30.5988 
## 
## Ecuación:
##  ŷ = 1151.406 - 203.1744 * poly(inversion, 2, raw = TRUE)1 + 30.5988 * poly(inversion, 2, raw = TRUE)2 
## 
## ============================
## Polinomial 5 
## ============================
## 
## Coeficientes:
##                     (Intercept) poly(inversion, 5, raw = TRUE)1 
##                        650.1501                        -76.8217 
## poly(inversion, 5, raw = TRUE)2 poly(inversion, 5, raw = TRUE)3 
##                         51.8806                         -5.5779 
## poly(inversion, 5, raw = TRUE)4 poly(inversion, 5, raw = TRUE)5 
##                          0.3336                         -0.0059 
## 
## Ecuación:
##  ŷ = 650.1501 - 76.8217 * poly(inversion, 5, raw = TRUE)1 + 51.8806 * poly(inversion, 5, raw = TRUE)2 - 5.5779 * poly(inversion, 5, raw = TRUE)3 + 0.3336 * poly(inversion, 5, raw = TRUE)4 - 0.0059 * poly(inversion, 5, raw = TRUE)5

Evaluación del modelo

La calidad y eficiencia predictiva de los modelos de regresión se valora calculando los estadísticos r-square y RMSE; r-square mide la representatividad que tiene variable independiente sobre al variable dependiente en cuanto a la variabilidad de esta última y RMSE identifica que tanto se acerca o se desvían las predicciones con respecto a los valores reales.

Para valorar con estos estadísticos, se requieren los datos de validación y los modelos participantes.

Con estos datos, los modelos que están por encima de un 90% en r square y que se establecieron como métrica importante para valorar la calidad predictiva son los mismos son el de regresión exponencial y polinomiales de segundo y quinto orden. De estos el que mejor representa a la variable dependiente es el modelo predictivo polinomial de quinto orden; en cuanto al estadístico RMSE el mejor modelo es el polinomial de quinto orden porque aleja en menor medida las predicciones de los valores reales.

modelos <- list(modelo_exp, modelo_RL, modelo_RP2, modelo_RP5)

nombres <- c(
  "Exponencial",
  "Logarítmico",
  "Polinomial 2",
  "Polinomial 5"
)
f_evaluar_modelos_varios(modelos, datos_validacion, "ingresos", nombres)

Interpretación del caso

Se implementó un modelo de regresión exponencial con un conjunto de datos estructurados bivariados de tres mil registros, las variables de interés fueron la inversión económica en publicidad como variable independiente llamada inversion y los ingresos que una empresa tiene como variable dependiente denominada ingresos. Los datos pueden descargagrse para su an[alisis y estudio en el espacio del autor en github.com en https://raw.githubusercontent.com/rpizarrog/Libro-Aprendizaje-Automatico.-Casos-de-Estudio-con-R-y-Python/refs/heads/main/datos/inversion_publicidad_e_ingresos.csv

El caso de estudio carga las librerías y funciones previamente codificadas para el adecuado funcionamiento; las funciones se encuentra en el espacio github en el espacio del autor: https://raw.githubusercontent.com/rpizarrog/Libro-Aprendizaje-Automatico.-Casos-de-Estudio-con-R-y-Python/refs/heads/main/R%20MarkDown/funciones/funciones%20para%20exponencial%20RExp.R.

El caso de estudio puede recrearse en el el portal de rpubs.com en el espacio del autor: https://rpubs.com/rpizarrog/1418739.

La partición de los datos se hizo 70% para datos de entrenamiejto y 30% para datos de validación.

Además de la construcción de un modelo de regresión exponencial, el caso compara los postulados y los estadísticos de rendimiento r square y RMSE con otros tres modelos; modelos logarítmico, polinomial de segundo orden y polinomial de quinto orden.

Con respecto a la linealidad de los residuos y los valores ajustados, todos los modelos cumplen con este supuesto excepto el modelo logarítmico.

Con respecto al supuesto de homocedasticidad, el modelo que ofrece este valoración es el de regresión exponencial, por el contrario los otros modelos presentan condiciones de heterocedasticidad del residuos.

Al haber evaluado el supuesto de normalidad de los residuos, el modelo que mejor cumple con este criterio sin llegar a pasar la prueba de Shapiro Wilk, es el modelo exponencial; ninguno de los modelos cumple con este supuesto.

Con respecto al postulado de independencia de residuos, al haber ejecutado la prueba Durbin-Watson se concluye que todos los modelos ofrecen independencia en los residuos.

Además de las funciones que el autor sugiere se recomienda utilizar la función check_model() de la librería performance con dependendencia del paquete see para evaluar postulados de linealidad, homocedasticidad y normalidad de residuos en los modelos de regresión.

Habiendo evaluado la calidad predictiva de los modelos con r square y RMSE, se puede concluir que para esto datos el mejor modelo es el de regresión exponencial seguido del polinomial de quinto orden. El modelo que no sobrepasa el tipo del 90% en r square establecido al inició es el logarítmico.

Este caso de estudio hizo una comparación de modelos predictivos para datos bivariados, no significa que un modelo es mejor que otro, simplemente que para estos datos existen modelos como el exponencial que mejor se ajusta en las predicciones.