Crear y evaluar un modelo de regresión lineal múltiple para predecir las ventas con datos simulados de una empresa dependiendo de las inversiones realizadas en publicidad
Cargar librerías y datos
Limpiar datos si es necesario
Explorar datos
Partir los datos en datos de entrenamiento y datos de validación 70% y 30%
Crear modelo de regresión con los datos de entrenamiento
Evaluar modelo antes de predicciones con los estadísticos. R Square ajustado y Coeficientes
El modelo se acepta si presenta un valor de R Square ajustado por encima del 70%
Predicciones
Evaluar predicciones con respecto a datos reales
Determinar el estadístico rmse para evaluar con respecto a otros modelos
Interpretar el caso
En la mayoría de los problemas de investigación en los que se aplica el análisis de regresión se necesita más de una variable independiente para el modelo de regresión.
La complejidad de la mayoría de mecanismos científicos es tal que, con el fin de predecir una respuesta importante, se requiere un modelo de regresión múltiple. Cuando un modelo es lineal en los coeficientes se denomina modelo de regresión lineal múltiple.
Para el caso de k variables independientes, el modelo que da \(x_1,x_2,x_3...,x_k\), y \(y\) como la variable dependiente.
\(x_1, x_2, x_3,...,x_k\) son las variable s que afectan a la variable dependiente en el modelo de regresión lineal múltiple.
Muchos problemas de investigación y de la industria, requieren la estimación de las relaciones existentes entre el patrón de variabilidad de una variable aleatoria y los valores de una o más variables aleatorias. [@urrutiamosquera2011]
Al generar un modelo de regresión lineal múltiple es importante identificar los estadísticos de R2, que se denomina coeficiente de determinación y es una medida de la proporción de la variabilidad explicada por el modelo ajustado.
De igual forma, el valor de R2 ajustado (R Square Adjusted) o coeficiente de determinación ajustado, es una variación de R2 que proporciona un ajuste para los grados de libertad [@walpole2012].
El estadístico R Ajustado está diseñado para proporcionar un estadístico que castigue un modelo sobreajustado, de manera que se puede esperar que favorezca al modelo [@walpole2012].
Una variable Y puede predecirse conforme y de acuerdo con la siguiente fórmula de la regresión múltiple.
\[ Y = b_0 + b_1{x_1} + b_2{x_2} + b_3{x_3}+ .....b_k{x_k} \]
Para trabajar con código Python, se deben cargan las librerías de Python previamente instaladas con la función py_install() de la librería reticulate de R.
La función repl_python() se utilizar para ejecutar ventana de comando o shell de Python.
Se recomienda instalar estos paquetes de Python
py_install(packages = “pandas”)
py_install(packages = “matplotlib”)
py_install(packages = “numpy”)
py_install(packages = “sklearn”) en R cloud
py_install(“scikit-learn”) R Studio local
py_install(packages = “statsmodels.api”)
py_install(packages = “seaborn”)
En terminal de Python se puede actualizar con conda create -n py3.8 python=3.8 scikit-learn pandas numpy matplotlib
library(reticulate)
import pandas as pd
import numpy as np
import statsmodels.api as sm # Estadísticas R Adjused
import seaborn as sns # Gráficos
from sklearn import linear_model
from sklearn.linear_model import LinearRegression
from sklearn.preprocessing import PolynomialFeatures # Polinomial
import matplotlib.pyplot as plt
from sklearn.model_selection import train_test_split
from sklearn import metrics
from sklearn.metrics import mean_squared_error, r2_score
datos = pd.read_csv("https://raw.githubusercontent.com/rpizarrog/Analisis-Inteligente-de-datos/main/datos/Advertising_Web.csv")
datos
## Unnamed: 0 X TV Radio Newspaper Web Sales
## 0 1 1 230.1 37.8 69.2 306.634752 22.1
## 1 2 2 44.5 39.3 45.1 302.653070 10.4
## 2 3 3 17.2 45.9 69.3 49.498908 9.3
## 3 4 4 151.5 41.3 58.5 257.816893 18.5
## 4 5 5 180.8 10.8 58.4 195.660076 12.9
## .. ... ... ... ... ... ... ...
## 195 196 196 38.2 3.7 13.8 248.841073 7.6
## 196 197 197 94.2 4.9 8.1 118.041856 9.7
## 197 198 198 177.0 9.3 6.4 213.274671 12.8
## 198 199 199 283.6 42.0 66.2 237.498063 25.5
## 199 200 200 232.1 8.6 8.7 151.990733 13.4
##
## [200 rows x 7 columns]
print("Observaciones y variables: ", datos.shape)
## Observaciones y variables: (200, 7)
print("Columnas y tipo de dato")
# datos.columns
## Columnas y tipo de dato
datos.dtypes
## Unnamed: 0 int64
## X int64
## TV float64
## Radio float64
## Newspaper float64
## Web float64
## Sales float64
## dtype: object
Se describen las variables independientes: TV, Radio Newpaper y la variable dependiente Sales.
Valor de etiqueta o variable objetivo deendiente(ventas): que significa el volumen de ventas del producto correspondiente
Las variables independientes: (TV, Radio, Periódico, WEB):
TV: para un solo producto en un mercado determinado, el costo de la publicidad en TV (en miles) Radio: costos de publicidad invertidos en medios de difusión Periódico: costos publicitarios para medios periodísticos.
datos[['TV','Radio', 'Newspaper', 'Web', 'Sales', ]].describe()
## TV Radio Newspaper Web Sales
## count 200.000000 200.000000 200.000000 200.000000 200.000000
## mean 147.042500 23.264000 30.554000 159.587355 14.022500
## std 85.854236 14.846809 21.778621 76.815266 5.217457
## min 0.700000 0.000000 0.300000 4.308085 1.600000
## 25% 74.375000 9.975000 12.750000 99.048767 10.375000
## 50% 149.750000 22.900000 25.750000 156.862154 12.900000
## 75% 218.825000 36.525000 45.100000 212.311848 17.400000
## max 296.400000 49.600000 114.000000 358.247042 27.000000
sns.pairplot(datos, x_vars=['TV','Radio','Newspaper', 'Web'], y_vars='Sales', size=7, aspect=0.8,kind = 'reg')
plt.savefig("pairplot.jpg")
plt.show()
Se observa la relación lineal entre las variables independientes con respecto a ventas, de tal forma que es posible estimar visualmente que la variable Newspaper tal vez tenga poco impacto en las ventas esto por la alta dispersión de los datos. Sin embargo participará en el modelo de regresión lineal múltiple.
Se observa también que la variable Web tiene poca correlación lineal con la variable Sales
Quitar las primeras columnas y dejar TV Radio NewsPaper Web y Sales
print("Variables independientes ")
## Variables independientes
X_independientes = datos.iloc[:,2:6]
X_independientes
## TV Radio Newspaper Web
## 0 230.1 37.8 69.2 306.634752
## 1 44.5 39.3 45.1 302.653070
## 2 17.2 45.9 69.3 49.498908
## 3 151.5 41.3 58.5 257.816893
## 4 180.8 10.8 58.4 195.660076
## .. ... ... ... ...
## 195 38.2 3.7 13.8 248.841073
## 196 94.2 4.9 8.1 118.041856
## 197 177.0 9.3 6.4 213.274671
## 198 283.6 42.0 66.2 237.498063
## 199 232.1 8.6 8.7 151.990733
##
## [200 rows x 4 columns]
print ("Variable dependiente")
## Variable dependiente
Y_dependiente = datos.iloc[:, 6:7]
Y_dependiente
## Sales
## 0 22.1
## 1 10.4
## 2 9.3
## 3 18.5
## 4 12.9
## .. ...
## 195 7.6
## 196 9.7
## 197 12.8
## 198 25.5
## 199 13.4
##
## [200 rows x 1 columns]
Se utiliza semilla 1349 (random_state=1349)
X_entrena,X_valida,Y_entrena,Y_valida = train_test_split(X_independientes, Y_dependiente,train_size=.70, random_state=1349)
print("Estructura de datos de entrenamiento... ", X_entrena.shape)
## Estructura de datos de entrenamiento... (140, 4)
print(X_entrena)
## TV Radio Newspaper Web
## 143 104.6 5.7 34.4 336.571095
## 124 229.5 32.3 74.2 88.080721
## 45 175.1 22.5 31.5 62.809264
## 181 218.5 5.4 27.4 162.387486
## 151 121.0 8.4 48.7 103.255212
## .. ... ... ... ...
## 194 149.7 35.6 6.0 99.579981
## 164 117.2 14.7 5.4 109.008763
## 17 281.4 39.6 55.8 41.755313
## 126 7.8 38.9 50.6 209.471977
## 18 69.2 20.5 18.3 210.489910
##
## [140 rows x 4 columns]
print(X_entrena[['TV']], X_entrena[['Radio']], X_entrena[['Newspaper']])
## TV
## 143 104.6
## 124 229.5
## 45 175.1
## 181 218.5
## 151 121.0
## .. ...
## 194 149.7
## 164 117.2
## 17 281.4
## 126 7.8
## 18 69.2
##
## [140 rows x 1 columns] Radio
## 143 5.7
## 124 32.3
## 45 22.5
## 181 5.4
## 151 8.4
## .. ...
## 194 35.6
## 164 14.7
## 17 39.6
## 126 38.9
## 18 20.5
##
## [140 rows x 1 columns] Newspaper
## 143 34.4
## 124 74.2
## 45 31.5
## 181 27.4
## 151 48.7
## .. ...
## 194 6.0
## 164 5.4
## 17 55.8
## 126 50.6
## 18 18.3
##
## [140 rows x 1 columns]
Se construye el modelo de regresión lineal mútiple
modelo_rm = LinearRegression()
modelo_rm.fit(X_entrena,Y_entrena)
LinearRegression()In a Jupyter environment, please rerun this cell to show the HTML representation or trust the notebook.
LinearRegression()
Se presentan los coeficientes, la intersección \(\beta_0\) y los coeficientes para cada variable independiente, \(\beta_1, \beta_2,\beta_3, \text{ y } \beta_4\)
print ("Intercepción o b0")
## Intercepción o b0
b0 = modelo_rm.intercept_
print (b0)
## [2.21871247]
print ("Coeficientes: b1, b2, b3 y b4")
# print (modelo_rm.coef_)
## Coeficientes: b1, b2, b3 y b4
b1 = modelo_rm.coef_[0, 0:1]
b2 = modelo_rm.coef_[0, 1:2]
b3 = modelo_rm.coef_[0, 2:3]
b4 = modelo_rm.coef_[0, 3:4]
print (b1, b2, b3, b4)
## [0.04590791] [0.18361118] [0.00849482] [0.0032826]
\[ Prediccion:\text { Y} = b_0 + b_1\cdot {x_1} + b_2\cdot{x_2} + b_3\cdot{x_3}+b_3\cdot{x_4} \]
\[ \text{Prediccion Sales} :\text { Y} = b_0 + b_1\cdot {TV} + b_2\cdot{Radio} + b_3\cdot{Newspaper}+b_3\cdot{Web} \]
Sobrepasa el 80% de tal forma que el el modelo SE ACEPTA por este criterio.
print(modelo_rm.score(X_entrena, Y_entrena))
## 0.8976484590445628
Se hacen predicciones con los datos de validación
predicciones = modelo_rm.predict(X_valida)
print(predicciones[:-1])
## [[12.30560849]
## [12.18906704]
## [18.20121304]
## [ 9.39303357]
## [10.19976045]
## [20.67729919]
## [20.76737291]
## [18.43092705]
## [20.76225222]
## [19.40625674]
## [23.54828749]
## [ 9.0060036 ]
## [14.23383502]
## [12.34957726]
## [ 8.91092428]
## [ 7.899225 ]
## [14.77198997]
## [13.36911601]
## [21.08150721]
## [ 7.46422309]
## [ 7.15466106]
## [10.35664746]
## [12.18725794]
## [12.33616659]
## [16.2210175 ]
## [15.22807141]
## [ 9.67291193]
## [15.18964092]
## [12.00835278]
## [ 6.67264066]
## [16.16759824]
## [21.54345675]
## [ 9.9564121 ]
## [17.2014079 ]
## [14.47368234]
## [17.25099038]
## [15.0021531 ]
## [21.37212197]
## [16.05398453]
## [23.25734821]
## [10.52517738]
## [10.43793631]
## [11.89571924]
## [ 6.6071206 ]
## [14.05358645]
## [11.69816351]
## [17.2818735 ]
## [13.21076683]
## [ 8.46327292]
## [ 7.77778198]
## [21.35687321]
## [14.88274541]
## [19.86502537]
## [18.24947089]
## [18.02566924]
## [12.22093084]
## [16.81433386]
## [10.60449165]
## [ 6.76807984]]
print(predicciones.shape)
## (60, 1)
Crear un data.frame llamado comparaciones a partir de la creación de un diccionario con los valores reales del conjunto de entrenamiento y las predicciones calculadas.
Se usa el type() para conocer el tipo de estructura de datos
Se usa el assign() para agregar columnas al df comparaciones
Se usa flatten().tolist() para convertir a una lista de una dimensión.
Al final se tiene un data.frame llamado comparaciones en donde las últimas columnas tienen los valores reales de ‘Sales’ y las predicciones en la variable ‘Predicho’.
print(type(X_valida))
# print(X_valida)
## <class 'pandas.core.frame.DataFrame'>
print(type(predicciones))
# print(predicciones)
## <class 'numpy.ndarray'>
comparaciones = pd.DataFrame(X_valida)
comparaciones = comparaciones.assign(Sales_Real = Y_valida)
comparaciones = comparaciones.assign(Predicho = predicciones.flatten().tolist())
print(comparaciones)
## TV Radio Newspaper Web Sales_Real Predicho
## 179 165.6 10.0 17.6 151.990733 12.6 12.305608
## 7 120.2 19.6 11.6 229.971459 13.2 12.189067
## 153 171.3 39.7 37.7 155.016224 19.0 18.201213
## 140 73.4 17.0 12.9 174.772137 10.9 9.393034
## 144 96.2 14.8 38.9 157.440047 11.4 10.199760
## 52 216.4 41.7 39.6 161.802512 22.6 20.677299
## 54 262.7 28.8 15.9 324.615179 20.2 20.767373
## 188 286.0 13.9 3.7 151.990733 15.9 18.430927
## 185 205.0 45.1 19.6 208.692690 22.6 20.762252
## 133 219.8 33.5 45.1 171.478018 19.6 19.406257
## 101 296.4 36.3 100.9 61.005251 23.8 23.548287
## 125 87.2 11.8 25.9 121.090982 10.6 9.006004
## 120 141.3 26.8 46.2 65.525461 15.5 14.233835
## 190 39.5 41.1 5.8 219.890583 10.8 12.349577
## 66 31.5 24.6 2.2 216.471397 9.5 8.910924
## 196 94.2 4.9 8.1 118.041856 9.7 7.899225
## 165 234.5 3.4 84.8 135.024909 11.9 14.771990
## 122 224.0 2.4 15.6 89.515821 11.6 13.369116
## 111 241.7 38.0 23.2 180.511528 21.8 21.081507
## 172 19.6 20.1 17.0 155.583662 7.6 7.464223
## 127 80.2 0.0 9.2 358.247042 8.8 7.154661
## 180 156.6 2.6 8.3 122.116470 10.5 10.356647
## 2 17.2 45.9 69.3 49.498908 9.3 12.187258
## 57 136.2 19.2 16.6 60.454355 13.2 12.336167
## 48 227.2 15.8 49.9 75.269182 14.8 16.221017
## 21 237.4 5.1 23.5 296.952070 12.5 15.228071
## 73 129.4 5.7 31.3 61.306191 11.0 9.672912
## 156 93.9 43.5 50.5 74.361939 15.3 15.189641
## 75 16.9 43.7 89.4 70.234282 8.7 12.008353
## 10 66.1 5.8 24.2 45.359029 8.6 6.672641
## 40 202.5 22.3 31.6 88.212823 16.6 16.167598
## 137 273.7 28.9 59.7 288.260611 20.8 21.543457
## 149 44.7 25.8 20.6 235.622449 10.1 9.956412
## 187 191.1 28.7 18.2 239.275713 17.3 17.201408
## 103 187.9 17.2 17.9 97.088630 14.7 14.473682
## 27 240.1 16.7 22.9 228.157437 15.9 17.250990
## 154 187.8 21.1 9.5 63.071208 15.6 15.002153
## 42 293.6 27.7 1.8 174.716820 20.7 21.372122
## 118 125.7 36.9 79.2 187.840415 15.9 16.053985
## 61 261.3 42.7 54.7 224.832039 24.2 23.257348
## 158 11.7 36.9 45.2 185.866079 7.3 10.525177
## 82 75.3 20.3 32.5 231.209829 11.3 10.437936
## 31 112.9 17.4 38.6 295.883989 11.9 11.895719
## 119 19.4 16.0 22.3 112.892609 6.6 6.607121
## 100 222.4 4.3 49.8 125.627143 11.7 14.053586
## 80 76.4 26.7 22.3 268.151320 11.8 11.698164
## 102 280.2 10.1 21.4 49.808451 14.8 17.281873
## 167 206.8 5.2 19.4 115.371957 12.2 13.210767
## 56 7.3 28.1 41.4 121.328525 5.5 8.463273
## 65 69.0 9.3 0.9 205.993485 9.3 7.777782
## 47 239.9 41.5 18.5 105.962913 23.2 21.356873
## 110 225.8 8.2 56.5 95.185762 13.4 14.882745
## 104 238.2 34.3 5.3 112.155489 20.7 19.865025
## 193 166.8 42.0 3.6 192.246211 19.6 18.249471
## 105 137.9 46.4 59.0 138.762632 19.2 18.025669
## 116 139.2 14.3 25.6 234.183118 12.2 12.220931
## 163 163.5 36.8 7.4 82.228794 18.0 16.814334
## 12 23.8 35.1 65.9 87.921085 9.2 10.604492
## 117 76.4 0.8 14.8 234.384501 9.4 6.768080
## 55 198.9 49.4 60.0 204.418927 23.7 21.600904
rmse Root Mean Stándard Error (Root-mean-square deviation), este valor normalmente se compara contra otro modelo y el que esté mas cerca de cero es mejor.
La raiz del Error Cuadrático Medio (rmse) es una métrica que dice qué tan lejos están los valores predichos de los valores observados o reales en un análisis de regresión, en promedio. Se calcula como:
\[ rmse = \sqrt{\frac{\sum(predicho_i - real_i)^{2}}{n}} \]
RMSE es una forma útil de ver qué tan bien un modelo de regresión puede ajustarse a un conjunto de datos.
Cuanto mayor sea el rmse, mayor será la diferencia entre los valores predichos y reales, lo que significa que peor se ajusta un modelo de regresión a los datos. Por el contrario, cuanto más pequeño sea el rmse, mejor podrá un modelo ajustar los datos.
print('Mean Squared Error: MSE', metrics.mean_squared_error(Y_valida, predicciones))
## Mean Squared Error: MSE 2.3777256203488135
print('Root Mean Squared Error RMSE:', np.sqrt(metrics.mean_squared_error(Y_valida, predicciones)))
## Root Mean Squared Error RMSE: 1.5419875551861024
score = modelo_rm.score(X_entrena,Y_entrena)
print(score)
#Predict regresión lineal
## 0.8976484590445628
Y_pred =modelo_rm .predict(X_entrena)
print(Y_pred)
## [[ 9.46431394]
## [19.60466947]
## [14.86220442]
## [14.00690337]
## [10.06854733]
## [ 9.54815459]
## [10.21091959]
## [12.43179668]
## [14.40310999]
## [10.88731073]
## [14.18485199]
## [15.2922251 ]
## [18.10015988]
## [ 9.84608779]
## [10.65325189]
## [17.78930083]
## [14.32641432]
## [12.41385538]
## [17.84298025]
## [21.3170269 ]
## [21.71641233]
## [16.9865338 ]
## [ 9.16836413]
## [13.63861274]
## [14.94679253]
## [10.01945031]
## [18.75301023]
## [18.23759182]
## [19.82709652]
## [ 6.22937875]
## [ 3.9395177 ]
## [17.99804483]
## [17.2911393 ]
## [19.87760164]
## [15.9958444 ]
## [17.00682019]
## [13.33898099]
## [12.58175639]
## [ 8.70837166]
## [24.76320901]
## [ 8.17160239]
## [ 3.48231976]
## [15.75859664]
## [11.82406684]
## [14.37998397]
## [20.95354591]
## [ 7.67006848]
## [11.71070983]
## [18.63195529]
## [15.85636253]
## [12.85413923]
## [12.75315398]
## [ 8.39784208]
## [12.07817865]
## [ 9.26438027]
## [17.59758619]
## [ 9.80088117]
## [22.87234833]
## [19.85697981]
## [13.76528876]
## [17.1565973 ]
## [11.89067615]
## [16.74959597]
## [15.62325495]
## [11.54298012]
## [13.68503016]
## [20.88288534]
## [17.05732561]
## [12.0443654 ]
## [17.30721726]
## [19.1308467 ]
## [15.02582528]
## [ 8.94548213]
## [13.21102383]
## [ 8.05058255]
## [13.04045044]
## [23.25571044]
## [10.31129727]
## [10.36804478]
## [ 8.39124557]
## [ 8.42457717]
## [ 5.35253164]
## [12.10782607]
## [17.98148068]
## [ 4.8995536 ]
## [15.64485659]
## [ 8.7568029 ]
## [12.30626443]
## [ 5.69074825]
## [15.85506666]
## [21.62703218]
## [24.32250855]
## [21.42986498]
## [18.3958714 ]
## [ 9.7177871 ]
## [14.41365719]
## [18.82686819]
## [15.17019291]
## [ 7.47895985]
## [14.73260045]
## [19.21703917]
## [10.13049963]
## [18.77897261]
## [16.60523574]
## [21.97163816]
## [15.58129154]
## [ 7.98630478]
## [14.92875908]
## [ 6.88724485]
## [13.64023537]
## [12.44188267]
## [ 4.3351995 ]
## [ 5.58583023]
## [ 8.72139159]
## [ 4.65356784]
## [10.0115481 ]
## [14.85156109]
## [20.83228498]
## [ 7.01043756]
## [13.42406744]
## [19.36058473]
## [14.08926014]
## [16.19305354]
## [12.80645952]
## [16.21253205]
## [13.36803796]
## [16.47771991]
## [ 7.70389297]
## [24.2918348 ]
## [20.52466867]
## [ 6.23614054]
## [24.43357466]
## [20.16088201]
## [ 4.95706745]
## [10.45578563]
## [16.00553546]
## [10.70190857]
## [23.01927942]
## [10.83671961]
## [10.00597862]]
plt.plot(range(len(Y_pred)),Y_pred,'b',label="predict")
#Mostrar imagen
plt.savefig("predict.jpg")
plt.show()
Con este modelo y con estos datos interprete lo siguiente:
Se realiza un análisis d anuncios que se tienen en distintos medios, como la TV y Radio con el objetivo de obtener información sobre cual es más conveniente para invertir.
200 observacione, TV, Radio, Newspaper, Web y Sales son las variables de interes
Las variables independientes son TV, Radio, Newspaper y Web, la variable dependiente es Sales.
70% de entrenamiento y 30% son de validación
Lo son principalmente para TV, Radio y web
En TV es 0.04590791 por encima del 99.9%, en la RADIO es 0.18361118 también por encima de 99.9%, el Newspapper con 0.00849482 por debajo del 90% y finalmente Web con 0.0032826 encima del 99.9%
Tiene un valor de 0.8976484590445628 y representa una certeza de 89.76%
Un valor de 1.5419875551861024 y representa la cantidad de dispresion posible entre los datos presentados
Si, una posibilidad seria un modelo de regresion linear multiple con mas de una variable dependiente o variables independientes
Con la semilla utilizada que es 1349 y y los resultados obtenidos, tiene un grado de confiabilidad muy alto
__Realizando el ejercicio con R se obtuvo un RMSE de 1.717802 y con Python se obtuvo un rmse de 1.54198, lo que significa que en Python se tiene una menor variabilidad o dispersión entre los datos reales