Regularización en regresión lineal
La regresión lineal estándar minimiza la suma de los errores al cuadrado entre las predicciones y los valores reales. Cuando el conjunto de datos tiene muchas características o hay alta correlación entre ellas, el modelo puede sobreajustarse: aprende el ruido del conjunto de entrenamiento y pierde capacidad de generalizar a datos nuevos.
La regularización introduce un término de penalización en la función de coste que limita la magnitud de los coeficientes, reduciendo el sobreajuste. En Scikit-learn hay dos variantes principales:
- Ridge (regularización L2): penaliza la suma del cuadrado de los coeficientes.
- Lasso (regularización L1): penaliza la suma del valor absoluto de los coeficientes, lo que puede forzar algunos coeficientes exactamente a cero (selección de características implícita).
Ridge Regressión (L2)
En Ridge, la función de coste es:
J(w) = ||Xw - y||² + alpha * ||w||²
El parámetro alpha controla la fuerza de la penalización. Un alpha grande reduce más los coeficientes, aumentando el sesgo pero reduciendo la varianza.
from sklearn.linear_model import Ridge
from sklearn.datasets import make_regression
from sklearn.model_selection import train_test_split
from sklearn.metrics import mean_squared_error, r2_score
import numpy as np
# Generar datos sintéticos con ruido
X, y = make_regression(n_samples=200, n_features=20, noise=15, random_state=42)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
# Entrenar modelo Ridge con alpha=1.0
ridge = Ridge(alpha=1.0)
ridge.fit(X_train, y_train)
y_pred = ridge.predict(X_test)
print(f"R²: {r2_score(y_test, y_pred):.4f}")
print(f"MSE: {mean_squared_error(y_test, y_pred):.4f}")
print(f"Coeficientes (primeros 5): {ridge.coef_[:5]}")
Efecto de alpha en Ridge
Podemos analizar cómo varía el rendimiento y los coeficientes al cambiar alpha:
from sklearn.linear_model import Ridge
from sklearn.datasets import make_regression
from sklearn.model_selection import train_test_split
from sklearn.metrics import r2_score
import numpy as np
X, y = make_regression(n_samples=200, n_features=20, noise=15, random_state=42)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
alphas = [0.001, 0.1, 1.0, 10.0, 100.0, 1000.0]
for alpha in alphas:
ridge = Ridge(alpha=alpha)
ridge.fit(X_train, y_train)
r2 = r2_score(y_test, ridge.predict(X_test))
norma = np.linalg.norm(ridge.coef_)
print(f"alpha={alpha:8.3f} -> R²={r2:.4f}, ||w||={norma:.2f}")
A medida que alpha crece, la norma de los coeficientes disminuye pero también puede bajar el R².
Lasso Regressión (L1)
La función de coste de Lasso es:
J(w) = ||Xw - y||² + alpha * ||w||₁
La penalización L1 puede llevar coeficientes exactamente a cero, actuando como un mecanismo de selección de características.
from sklearn.linear_model import Lasso
from sklearn.datasets import make_regression
from sklearn.model_selection import train_test_split
from sklearn.metrics import r2_score
import numpy as np
# Datos con solo 5 características relevantes de 20
X, y = make_regression(n_samples=200, n_features=20, n_informative=5,
noise=10, random_state=42)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
lasso = Lasso(alpha=1.0)
lasso.fit(X_train, y_train)
print(f"R²: {r2_score(y_test, lasso.predict(X_test)):.4f}")
print(f"Características no nulas: {np.sum(lasso.coef_ != 0)}")
print(f"Coeficientes: {lasso.coef_}")
Con n_informative=5, Lasso idealmente forzará los otros 15 coeficientes a cero.
Comparación: LinearRegressión vs Ridge vs Lasso
from sklearn.linear_model import LinearRegression, Ridge, Lasso
from sklearn.datasets import make_regression
from sklearn.model_selection import train_test_split
from sklearn.metrics import r2_score, mean_squared_error
import numpy as np
X, y = make_regression(n_samples=300, n_features=30, n_informative=10,
noise=20, random_state=42)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
modelos = {
'LinearRegression': LinearRegression(),
'Ridge(alpha=1)': Ridge(alpha=1.0),
'Lasso(alpha=1)': Lasso(alpha=1.0),
}
for nombre, modelo in modelos.items():
modelo.fit(X_train, y_train)
y_pred = modelo.predict(X_test)
r2 = r2_score(y_test, y_pred)
mse = mean_squared_error(y_test, y_pred)
coef_no_nulos = np.sum(modelo.coef_ != 0)
print(f"{nombre:25s} R²={r2:.4f} MSE={mse:.1f} coefs≠0: {coef_no_nulos}")
ElasticNet: combinando L1 y L2
ElasticNet combina las penalizaciones de Ridge y Lasso mediante el parámetro l1_ratio:
from sklearn.linear_model import ElasticNet
from sklearn.datasets import make_regression
from sklearn.model_selection import train_test_split
from sklearn.metrics import r2_score
X, y = make_regression(n_samples=200, n_features=20, n_informative=8,
noise=15, random_state=42)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
# l1_ratio=0 -> Ridge puro, l1_ratio=1 -> Lasso puro
elastic = ElasticNet(alpha=0.5, l1_ratio=0.5)
elastic.fit(X_train, y_train)
print(f"R²: {r2_score(y_test, elastic.predict(X_test)):.4f}")
Selección automática de alpha con RidgeCV y LassoCV
Scikit-learn ofrece versiones con validación cruzada integrada para seleccionar el mejor alpha automáticamente:
from sklearn.linear_model import RidgeCV, LassoCV
from sklearn.datasets import make_regression
from sklearn.model_selection import train_test_split
X, y = make_regression(n_samples=300, n_features=20, noise=10, random_state=42)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
# RidgeCV prueba cada alpha con validación cruzada
alphas = [0.01, 0.1, 1.0, 10.0, 100.0]
ridge_cv = RidgeCV(alphas=alphas, cv=5)
ridge_cv.fit(X_train, y_train)
print(f"Ridge - Mejor alpha: {ridge_cv.alpha_}")
print(f"Ridge - R² test: {ridge_cv.score(X_test, y_test):.4f}")
# LassoCV hace lo mismo con validación cruzada
lasso_cv = LassoCV(alphas=alphas, cv=5, max_iter=5000)
lasso_cv.fit(X_train, y_train)
print(f"Lasso - Mejor alpha: {lasso_cv.alpha_}")
print(f"Lasso - R² test: {lasso_cv.score(X_test, y_test):.4f}")
Cuándo usar cada técnica
| Situación | Técnica recomendada | |-----------|---------------------| | Sobreajuste con muchas características correlacionadas | Ridge | | Datos con muchas características irrelevantes | Lasso (selección implícita) | | Combinación de correlaciones y características irrelevantes | ElasticNet | | Selección automática de alpha | RidgeCV / LassoCV |
La elección entre Ridge y Lasso depende del problema concreto: si se sospecha que pocas características son realmente relevantes, Lasso puede ofrecer un modelo más interpretable al forzar coeficientes a cero. Si todas las características aportan algo, Ridge suele comportarse mejor.
Alan Sastre
Ingeniero de Software y formador, CEO en CertiDevs
Ingeniero de software especializado en Full Stack y en Inteligencia Artificial. Como CEO de CertiDevs, Scikit Learn es una de sus áreas de expertise. Con más de 15 años programando, 6K seguidores en LinkedIn y experiencia como formador, Alan se dedica a crear contenido educativo de calidad para desarrolladores de todos los niveles.
Más tutoriales de Scikit Learn
Explora más contenido relacionado con Scikit Learn y continúa aprendiendo con nuestros tutoriales gratuitos.
Aprendizajes de esta lección
Comprender la regularización L1 (Lasso) y L2 (Ridge) y su efecto en los coeficientes del modelo. Implementar Ridge y Lasso con Scikit-learn y ajustar el hiperparámetro alpha. Comparar el rendimiento de LinearRegressión, Ridge y Lasso sobre un mismo conjunto de datos. Utilizar ElasticNet como combinación de ambas regularizaciones. Seleccionar el valor óptimo de alpha mediante validación cruzada con RidgeCV y LassoCV.