Capítulo 4

Regresión Lineal (visión ML)

4.1 Regresión como MLE

Desde la perspectiva de ML, la regresión lineal es un modelo probabilístico:

y=wx+ε,εN(0,σ2)y = \mathbf{w}^\top \mathbf{x} + \varepsilon, \quad \varepsilon \sim \mathcal{N}(0, \sigma^2)

La verosimilitud de los datos es:

p(yX,w)=i=1n12πσ2exp((yiwxi)22σ2)p(\mathbf{y} \mid X, \mathbf{w}) = \prod_{i=1}^n \frac{1}{\sqrt{2\pi\sigma^2}} \exp\left(-\frac{(y_i - \mathbf{w}^\top \mathbf{x}_i)^2}{2\sigma^2}\right)

Maximizar el log- likelihood equivale a minimizar el MSE:

logp(yX,w)=n2log(2πσ2)12σ2i=1n(yiwxi)2\log p(\mathbf{y} \mid X, \mathbf{w}) = -\frac{n}{2}\log(2\pi\sigma^2) - \frac{1}{2\sigma^2}\sum_{i=1}^n (y_i - \mathbf{w}^\top \mathbf{x}_i)^2

Minimizar el MSE es lo mismo que MLE con ruido gaussiano.

4.2 Basis Functions

La linealidad es en los parámetros, no en las features. Podemos transformar X:

y=wϕ(x)y = \mathbf{w}^\top \phi(\mathbf{x})

Polinomial

ϕ(x)=[1,x,x2,,xd]\phi(x) = [1, x, x^2, \ldots, x^d]

Gaussianas (RBF)

ϕj(x)=exp((xμj)22s2)\phi_j(x) = \exp\left(-\frac{(x-\mu_j)^2}{2s^2}\right)

Sigmoide

ϕj(x)=σ(xμjs)\phi_j(x) = \sigma\left(\frac{x-\mu_j}{s}\right)

4.3 Ridge como Máximo a Posteriori (MAP)

Ridge no es solo un truco numérico. Es equivalente a poner un prior Gaussiano sobre w:

p(w)=N(0,λ1I)p(\mathbf{w}) = \mathcal{N}(\mathbf{0}, \lambda^{-1} I)

El MAP queda:

wMAP=argmaxwlogp(yX,w)+logp(w)\mathbf{w}_{\text{MAP}} = \arg\max_\mathbf{w} \log p(\mathbf{y} \mid X, \mathbf{w}) + \log p(\mathbf{w})
=argminwyXw2+λw2= \arg\min_\mathbf{w} \|y - X\mathbf{w}\|^2 + \lambda \|\mathbf{w}\|^2
python
import numpy as np
from sklearn.linear_model import RidgeCV
from sklearn.preprocessing import PolynomialFeatures

X = np.linspace(0, 2, 20)[:, None]
y_true = np.sin(2 * np.pi * X.ravel())
y = y_true + 0.2 * np.random.randn(20)

model = RidgeCV(alphas=np.logspace(-3, 3, 50))
pipe = make_pipeline(PolynomialFeatures(15), model)
pipe.fit(X, y)
print(f"Alpha óptimo: {model.alpha_:.3f}")

4.4 LASSO y Selección de Variables

LASSO usa la penalización L1, que induce esparsidad — muchos coeficientes se vuelven exactamente cero. Equivale a un prior Laplace sobre w.

minwyXw2+λw1\min_{\mathbf{w}} \|y - X\mathbf{w}\|^2 + \lambda \|\mathbf{w}\|_1

La geometría explica por qué L1 produce ceros: las esquinas de la región factible (rombos) caen en los ejes. L2 (círculos) no tiene esquinas.

python
from sklearn.linear_model import LassoCV
from sklearn.datasets import make_regression

X, y = make_regression(n_samples=200, n_features=50,
                       n_informative=5, noise=0.5, random_state=42)

lasso = LassoCV(cv=5, alphas=np.logspace(-4, 1, 50))
lasso.fit(X, y)
n_cero = (lasso.coef_ == 0).sum()
print(f"Alpha: {lasso.alpha_:.4f}, Coefs cero: {n_cero}/50")

4.5 Elastic Net

Combina L1 y L2 para lo mejor de ambos mundos:

minwyXw2+λ1w1+λ2w2\min_{\mathbf{w}} \|y - X\mathbf{w}\|^2 + \lambda_1 \|\mathbf{w}\|_1 + \lambda_2 \|\mathbf{w}\|^2

Útil cuando hay grupos de features correlacionadas — LASSO tiende a elegir solo una del grupo, Elastic Net las selecciona en grupo.

python
from sklearn.linear_model import ElasticNetCV

en = ElasticNetCV(cv=5, l1_ratio=[.1, .5, .7, .9, .95, .99, 1])
en.fit(X, y)
print(f"l1_ratio óptimo: {en.l1_ratio_:.2f}")

4.6 Evaluación

Métricas clave para regresión:

MSE

1n(yiy^i)2\frac{1}{n}\sum (y_i - \hat{y}_i)^2

RMSE

MSE\sqrt{\text{MSE}}

MAE

1nyiy^i\frac{1}{n}\sum |y_i - \hat{y}_i|

1(yiy^i)2(yiyˉ)21 - \frac{\sum(y_i - \hat{y}_i)^2}{\sum(y_i - \bar{y})^2}

4.7 Ejemplo Completo

python
import numpy as np
from sklearn.pipeline import make_pipeline
from sklearn.preprocessing import StandardScaler, PolynomialFeatures
from sklearn.linear_model import RidgeCV, LassoCV
from sklearn.model_selection import train_test_split
from sklearn.metrics import mean_squared_error

X = np.linspace(0, 3, 150)[:, None]
y = np.sin(X.ravel()) + 0.3 * np.random.randn(150)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2)

pipe_ridge = make_pipeline(PolynomialFeatures(12), StandardScaler(),
                           RidgeCV(alphas=np.logspace(-3, 3, 50)))
pipe_lasso = make_pipeline(PolynomialFeatures(12), StandardScaler(),
                           LassoCV(alphas=np.logspace(-4, 1, 50)))

pipe_ridge.fit(X_train, y_train)
pipe_lasso.fit(X_train, y_train)

print(f"Ridge test MSE: {mean_squared_error(y_test, pipe_ridge.predict(X_test)):.4f}")
print(f"Lasso test MSE: {mean_squared_error(y_test, pipe_lasso.predict(X_test)):.4f}")