Regresión de Señales Dispersas con Modelos Basados en L1

Machine LearningMachine LearningBeginner
Practicar Ahora

This tutorial is from open-source community. Access the source code

💡 Este tutorial está traducido por IA desde la versión en inglés. Para ver la versión original, puedes hacer clic aquí

Introducción

En este laboratorio, demostraremos cómo usar modelos de regresión basados en L1 para tratar señales de alta dimensión y dispersas. En particular, compararemos tres modelos populares basados en L1: Lasso, Determinación Automática de Relevancia (ARD) y ElasticNet. Usaremos un conjunto de datos sintético para ilustrar el rendimiento de estos modelos en términos de tiempo de ajuste, puntuación R2 y esparcidad de los coeficientes estimados.

Consejos sobre la VM

Una vez que se haya iniciado la VM, haga clic en la esquina superior izquierda para cambiar a la pestaña Cuaderno y acceder a Jupyter Notebook para practicar.

A veces, es posible que tenga que esperar unos segundos a que Jupyter Notebook termine de cargarse. La validación de las operaciones no se puede automatizar debido a las limitaciones de Jupyter Notebook.

Si tiene problemas durante el aprendizaje, no dude en preguntar a Labby. Deje comentarios después de la sesión y resolveremos rápidamente el problema para usted.


Skills Graph

%%%%{init: {'theme':'neutral'}}%%%% flowchart RL sklearn(("Sklearn")) -.-> sklearn/CoreModelsandAlgorithmsGroup(["Core Models and Algorithms"]) sklearn(("Sklearn")) -.-> sklearn/ModelSelectionandEvaluationGroup(["Model Selection and Evaluation"]) ml(("Machine Learning")) -.-> ml/FrameworkandSoftwareGroup(["Framework and Software"]) sklearn/CoreModelsandAlgorithmsGroup -.-> sklearn/linear_model("Linear Models") sklearn/ModelSelectionandEvaluationGroup -.-> sklearn/model_selection("Model Selection") sklearn/ModelSelectionandEvaluationGroup -.-> sklearn/metrics("Metrics") ml/FrameworkandSoftwareGroup -.-> ml/sklearn("scikit-learn") subgraph Lab Skills sklearn/linear_model -.-> lab-49187{{"Regresión de Señales Dispersas con Modelos Basados en L1"}} sklearn/model_selection -.-> lab-49187{{"Regresión de Señales Dispersas con Modelos Basados en L1"}} sklearn/metrics -.-> lab-49187{{"Regresión de Señales Dispersas con Modelos Basados en L1"}} ml/sklearn -.-> lab-49187{{"Regresión de Señales Dispersas con Modelos Basados en L1"}} end

Generar un conjunto de datos sintético

Primero, generamos un conjunto de datos donde el número de muestras es menor que el número total de características. Esto conduce a un sistema subdeterminado, es decir, la solución no es única y no podemos aplicar un método de mínimos cuadrados ordinarios por sí solo. La regularización introduce un término de penalización en la función objetivo, lo que modifica el problema de optimización y puede ayudar a aliviar la naturaleza subdeterminada del sistema. Generaremos un objetivo y que sea una combinación lineal con signos alternados de señales senoidales. Solo las 10 frecuencias más bajas de las 100 en X se utilizan para generar y, mientras que el resto de las características no son informativas. Esto resulta en un espacio de características disperso de alta dimensión, donde es necesaria cierta penalización L1.

import numpy as np

rng = np.random.RandomState(0)
n_samples, n_features, n_informative = 50, 100, 10
time_step = np.linspace(-2, 2, n_samples)
freqs = 2 * np.pi * np.sort(rng.rand(n_features)) / 0.01
X = np.zeros((n_samples, n_features))

for i in range(n_features):
    X[:, i] = np.sin(freqs[i] * time_step)

idx = np.arange(n_features)
true_coef = (-1) ** idx * np.exp(-idx / 10)
true_coef[n_informative:] = 0  ## sparsify coef
y = np.dot(X, true_coef)

## introduce random phase using numpy.random.random_sample
## add some gaussian noise using numpy.random.normal
for i in range(n_features):
    X[:, i] = np.sin(freqs[i] * time_step + 2 * (rng.random_sample() - 0.5))
    X[:, i] += 0.2 * rng.normal(0, 1, n_samples)

y += 0.2 * rng.normal(0, 1, n_samples)

## split the data into train and test sets using train_test_split from sklearn
from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.5, shuffle=False)

Lasso

En este paso, demostraremos cómo usar el modelo de regresión Lasso para estimar los coeficientes dispersos del conjunto de datos. Usaremos un valor fijo del parámetro de regularización alpha. En la práctica, el parámetro óptimo alpha debería seleccionarse pasando una estrategia de validación cruzada TimeSeriesSplit a un LassoCV. Para mantener el ejemplo simple y rápido de ejecutar, aquí establecemos directamente el valor óptimo para alpha.

from sklearn.linear_model import Lasso
from sklearn.metrics import r2_score
from time import time

t0 = time()
lasso = Lasso(alpha=0.14).fit(X_train, y_train)
print(f"Lasso fit done in {(time() - t0):.3f}s")

y_pred_lasso = lasso.predict(X_test)
r2_score_lasso = r2_score(y_test, y_pred_lasso)
print(f"Lasso r^2 on test data : {r2_score_lasso:.3f}")

Determinación Automática de Relevancia (ARD)

Una regresión ARD es la versión bayesiana del Lasso. Puede producir estimaciones de intervalo para todos los parámetros, incluyendo la varianza del error, si es necesario. Es una opción adecuada cuando las señales tienen ruido gaussiano.

from sklearn.linear_model import ARDRegression

t0 = time()
ard = ARDRegression().fit(X_train, y_train)
print(f"ARD fit done in {(time() - t0):.3f}s")

y_pred_ard = ard.predict(X_test)
r2_score_ard = r2_score(y_test, y_pred_ard)
print(f"ARD r^2 on test data : {r2_score_ard:.3f}")

ElasticNet

ElasticNet es un enfoque intermedio entre la regresión Lasso y Ridge, ya que combina una penalización L1 y una penalización L2. La cantidad de regularización está controlada por los dos hiperparámetros l1_ratio y alpha. Para l1_ratio = 0, la penalización es pura L2 y el modelo es equivalente a una regresión Ridge. Del mismo modo, l1_ratio = 1 es una penalización pura L1 y el modelo es equivalente a una regresión Lasso. Para 0 < l1_ratio < 1, la penalización es una combinación de L1 y L2.

from sklearn.linear_model import ElasticNet

t0 = time()
enet = ElasticNet(alpha=0.08, l1_ratio=0.5).fit(X_train, y_train)
print(f"ElasticNet fit done in {(time() - t0):.3f}s")

y_pred_enet = enet.predict(X_test)
r2_score_enet = r2_score(y_test, y_pred_enet)
print(f"ElasticNet r^2 on test data : {r2_score_enet:.3f}")

Representación gráfica y análisis de los resultados

En este paso, usamos un mapa de calor para visualizar la esparsidad de los coeficientes reales y estimados de los respectivos modelos lineales.

import matplotlib.pyplot as plt
import seaborn as sns
import pandas as pd
from matplotlib.colors import SymLogNorm

df = pd.DataFrame(
    {
        "True coefficients": true_coef,
        "Lasso": lasso.coef_,
        "ARDRegression": ard.coef_,
        "ElasticNet": enet.coef_,
    }
)

plt.figure(figsize=(10, 6))
ax = sns.heatmap(
    df.T,
    norm=SymLogNorm(linthresh=10e-4, vmin=-1, vmax=1),
    cbar_kws={"label": "coefficients' values"},
    cmap="seismic_r",
)
plt.ylabel("linear model")
plt.xlabel("coefficients")
plt.title(
    f"Models' coefficients\nLasso $R^2$: {r2_score_lasso:.3f}, "
    f"ARD $R^2$: {r2_score_ard:.3f}, "
    f"ElasticNet $R^2$: {r2_score_enet:.3f}"
)
plt.tight_layout()

Resumen

Se sabe que Lasso recupera datos dispersos de manera efectiva, pero no funciona bien con características altamente correlacionadas. De hecho, si varias características correlacionadas contribuyen al objetivo, Lasso terminaría seleccionando solo una de ellas. En el caso de características dispersas pero no correlacionadas, un modelo Lasso sería más adecuado.

ElasticNet introduce cierta esparsidad en los coeficientes y los reduce a cero. Por lo tanto, en presencia de características correlacionadas que contribuyen al objetivo, el modelo todavía es capaz de reducir sus pesos sin establecirlos exactamente en cero. Esto da como resultado un modelo menos disperso que un Lasso puro y puede capturar también características no predictivas.

ARDRegression es mejor cuando se trata de manejar ruido gaussiano, pero todavía no es capaz de manejar características correlacionadas y requiere una cantidad mayor de tiempo debido a la adaptación de una distribución a priori.