Show code cell source
import holoviews as hv
hv.extension('bokeh')
hv.opts.defaults(hv.opts.Curve(width=500),
hv.opts.Histogram(width=500))
from bokeh.plotting import show
import numpy as np
import scipy.stats
import statsmodels.api as sm
from scipy.stats import shapiro
print(f"NumPy versión: {np.__version__}")
print(f"Scipy versión: {scipy.__version__}")
NumPy versión: 1.21.5
Scipy versión: 1.9.1
15. Introducción a la Regresión Lineal#
Muchos problemas pueden formularse como “encontrar una relación” entre dos o más variables. Lo anterior puede interpretarse como predecir o explicar una variable dadas las demás.
Algunos ejemplos:
Predecir ventas dada el dinero invertido en anuncios (ads)
Predecir el tiempo de mañana para Valdivia dadas las condiciones atmosféricas actuales e históricas
Predecir la probabilidad de padecer cancer de pulmón dado el número de cigarrillados fumados diariamente
De lo anterior surgen las siguientes preguntas relevantes:
¿Están estas variables relacionadas?
¿Qué tan fuerte o significativa es dicha relación?
¿Cuál es la naturaleza de esta relación?
Si respondemos estas preguntas estaremos más cerca a entender los procesos subyacentes tras los datos.
15.1. Definiendo regresión#
Regresión se refiere a una familia de modelos estadísticos cuyo fin es encontrar relaciones entre variables. En general esta relación se modela como una función
Esta función mapea un conjunto de variables a una variable:
La/s variable/s de entrada \(X\) se llama/n variable/s independiente/s (IV). También se suelen llamar predictores, características (features), atributos, regresores.
La variable de salida \(Y\) se llama variable dependiente (DV), también se suele llamar respuesta.
El objetivo es estimar \(g\) a patir de datos de la forma:
Nota
La regresión se puede definir desde una perspectiva estadística como un caso particular de ajuste de modelos (estimación de parámetros). También se considera como parte del paradigma de aprendizaje supervisado.
Los métodos de regresión pueden clasificar como parámetricos o no paramétricos. En esta lección nos enfocaremos en los primeros.
Ver también
Los modelos no paramétricos de regresión no tienen estructura predefinida y por ende son más flexibles pero más complejos de ajustar que sus contrapartes paramétricas. Algunos ejemplos son las splines, SVR (support vector regression) y los procesos gaussianos.
Definamos en detalle un modelo paramétrico de regresión. Sea
\(X\) una variable continua D-dimensional (\(X\) puede ser una variable discreta también)
\(Y\) una variable continua unidimensional
\(\{x_i, y_i\}\) con \(i=1,\ldots,N\) un conjunto de \(N\) observaciones de \(X\) e \(Y\)
\(g_b\) un modelo con vector de parámetros \(b\)
El problema de regresión paramétrica consiste en contrar el mejor valor de \(b\) tal que
El modelo paramétrico más simple es cuando la relación entre variables es lineal (aditivo y homogeneo). En este caso hablamos de regresión lineal.
Nota
Una función es lineal si tiene estas propiedades:
Aditividad: \(f(X_1 + X_2) = f(X_1) + f(X_2)\)
Homogeneidad: \(f(aX) = af(X)\)
Advertencia
La regresión lineal es lineal en \(b\) pero no necesariamente en \(X\)
Por ejemplo, el siguiente modelo con entrada unidimensional
es un modelo lineal en \(b\) y
es también lineal en \(b\), sin embargo
no es lineal en \(b\).
15.2. El modelo lineal más simple#
Si consideramos una variable unidimensional \(x_i \in \mathbb{R}, i=1,\ldots,N\), entonces el modelo lineal más simple sería
que tiene \(M=2\) parámetros. Este modelo corresponde a una linea en \(\mathbb{R}^2\) y podemos reconocer:
\(b_0\) como la intercepta (intercept)
\(b_1\) como la pendiente (slope)
Si consideramos una variable de entrada bi-dimensional \(x_i = (x_{i1}, x_{i2}) \in \mathbb{R}^2, i=1,\ldots,N\) entonces tendríamos
que tiene \(M=3\) parámetros. Esto corresponde a un plano en \(\mathbb{R}^3\).
La forma más general asume una variable D-dimensional \(x_i = (x_{i1}, x_{i2}, \ldots, x_{iD}), i=1,\ldots,N\) con
que tiene \(M=D+1\) parámetros. Esto corresponde a un hiperplano en \(\mathbb{R}^M\).
15.2.1. Ajustando el modelo lineal simple: Matemáticamente#
Asumiendo que tenemos \(\{x_i, y_i\}_{i=1,\ldots,N}\) observaciones de las variables unidimensionales \(X\) e \(Y\), y \(X\) se considera dado, ¿cómo encontramos \(b_0\) y \(b_1\) tal que
El valor predicho por el modelo se denomina \(\hat y_i\), y:
Asumimos un término de error o residuo que cumple:
donde los \(e_i\) son i.i.d. Cada \(e_i \sim \cal N(0, \sigma^2)\), \(e_i\) es independiente de \(x_i\), y los \(e_i\) son independientes entre sí mismos.
Así que el error o residuo para la i-ésima observaicón es:
El error or residuo cuadrático para la i-ésima observaicón es:
La suma de los errores cuadrados para todas observaicones es:
Luego podemos ajustar (entrenar) un modelo en base al siguiente criterio de minimizar la suma de cuadrados residuales:
Nota
Desde un punto de vista estadístico, este criterio es razonable si las observaciones de entrenamiento (\(x_i\), \(y_i\)) representan extracciones aleatorias independientes de su población. Pero, aunque las \(x_i\) no se hayan extraído aleatoriamente, el criterio sigue siendo válido si las \(y_i\) son condicionalmente independientes dadas las entradas \(x_i\).
Los \(y_i\) tienen que ser i.i.d.? Los \(x_i\) tienen que ser i.i.d.?
Cómo obtiene los valores de \(b_0\) y \(b_1\)?
Demostración
Si derivamos la expresión \(L\) con respecto a \(b_0\) primero, obtenemos:
donde \(\bar x = \frac{1}{N} \sum_{i=1}^N x_i\), \(\bar y = \frac{1}{N} \sum_{i=1}^N y_i\) y derivamos la expresión \(L\) con respecto a \(b_1\), obtenemos:
donde \(s_{xy}\) es la covarianza muestral insesgada (unbiased sample covariance) de \(x\) y \(y\), y \(s_x^2\) es la varianza muestral insesgada de x.
Puedes resolver las derivaciones arriba?
Hecho interestante Cuando tenemos un modelo de sólo intersección \(b_0\) sin pendientes, \(b_0\) es igual a la media \(\bar{y}\).
15.2.2. Ajustando el modelo lineal simple: Python#
Podemos ajustar un modelo de linea en Python usando la librería scipy.stats con
scipy.stats.linregress(x, # Vector con N valores o matriz de Mx2 (si y no se especifica)
y=None, # Vector con N valores
)
Esta función retorna un objeto cuyos atributos son:
slope: Equivalente a \(\hat b_1\)intercept: Equivalente a \(\hat b_0\)rvalue: El coeficiente de correlación de Pearsonpvalue: Un p-value para la hipótesis nula de que \(b_1 =0\)
Más adelante ahondaremos en el coeficiente de correlación y los test de hipótesis para la regresión lineal. De momento pongamos en práctica la función anterior utilizando datos sintéticos:
np.random.seed(12345)
b, sigma = [0.5 , -1], 0.5
x = np.random.rand(25)*5
def model(x, b):
return b[0] + b[1]*x
y = model(x, b) + sigma*np.random.randn(len(x))
Ajustamos los parámetros a los datos con:
res = scipy.stats.linregress(x, y)
hat_b = np.array([res.intercept, res.slope])
print(f"hat b0: {hat_b[0]:0.5f}, hat b1: {hat_b[1]:0.5f}")
hat b0: 0.42758, hat b1: -0.93605
Y luego utilizamos el modelo ajustado para inferir sobre nuevos valores \(\hat x\). La siguiente gráfica muestra los datos utilizados para entrenar y la inferencia con el modelo ajustado en el rango \([-1,6]\).
hat_x = np.linspace(-1, 6, num=50)
hat_y = model(hat_x, hat_b)
Show code cell source
p_fitted = hv.Curve((hat_x, hat_y), label='Fitted model')
p_data = hv.Scatter((x, y), label='Training data').opts(color='k', size=5)
plot = hv.Overlay([p_data, p_fitted])
show(hv.render(plot))
Se puede apreciar que el modelo sigue bastante de cerca a los datos.
Para evaluar la calidad del ajuste también podemos graficar los residuos, es decir la distancia entre las muestras y la linea ajustada. También podemos inspeccionar el histograma de los residuos.
Para el ejemplo anterior:
hat_y = model(x, hat_b)
residuals = y - hat_y
bins, edges = np.histogram(residuals, density=True)
Show code cell source
p_residuals = hv.Scatter((hat_y, residuals), 'Predicted y', 'Residuals').opts(color='k', size=5, width=350)
p_zero = hv.HLine(0).opts(color='k', line_dash='dashed', alpha=0.5)
p_hist = hv.Histogram((edges, bins), kdims='Residuals', vdims='Density').opts(width=350)
plot = hv.Layout([p_residuals * p_zero, p_hist]).cols(2)
show(hv.render(plot))
print(shapiro(residuals))
ShapiroResult(statistic=0.9754845499992371, pvalue=0.7837038040161133)
En general buscamos residuos que:
Estén concentrados en torno a cero (media 0 en general y en cada \(\hat y_i\))
No estén correlacionados con \(\hat y_i\), tengan mismos varianzas en cada \(\hat y_i\)
Tenga una distribución normal
Advertencia
Si no se cumplen, es un signo de que el modelo escogido (en este caso la linea) no era adecuada para modelar la relación entre las variables de interés. Veamos cómo abordarlo en el próximo capítulo.
15.2.3. Coeficiente de determinación#
Podemos medir la fuerza de la relación lineal o el “fitness” del modelo por el coeficiente de determinación o \(R^2\) (o \(r^2\)):
es decir uno menos la suma de los residuos dividido por la varianza de \(y\). Para la regresión lineal simple el estadístico \(r\) es equivalente al coeficiente de correlación de Pearson en la muestra (sample correlation) entre \(x\) y \(y\). (Si te interesa saber por qué, tratas de hacer la demostración!)
Interpretación de \(r^2\):
Decimos \(100R^2\)% de la variación en \(Y\) se explica por la variación en el predictor \(X\).
Si \(R^2 = 1\), los datos son predichos perfectamente por el modelo. El predictor explica toda la variación en \(Y\).
Si \(R^2 = 0\), el modelo ajustado es una linea horizontal. El predictor no explica la variación en \(Y\).
Advertencia
Si las variables tienen una relación fuerte, pero de naturaleza no-lineal, esta podría no ser detectada por \(R^2\).
El modelo tiene \(R^2\):
res.rvalue**2
0.8900544184564642