Sparse Signal Regression mit L1-basierten Modellen

Machine LearningMachine LearningBeginner
Jetzt üben

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

💡 Dieser Artikel wurde von AI-Assistenten übersetzt. Um die englische Version anzuzeigen, können Sie hier klicken

Einführung

In diesem Lab werden wir demonstrieren, wie man L1-basierte Regressionsmodelle verwendet, um mit hochdimensionalen und dünn besetzten Signalen umzugehen. Insbesondere werden wir drei populäre L1-basierte Modelle vergleichen: Lasso, Automatic Relevance Determination (ARD) und ElasticNet. Wir werden einen synthetischen Datensatz verwenden, um die Leistung dieser Modelle in Bezug auf die Anpassungszeit, den R2-Wert und die Dünnheit der geschätzten Koeffizienten zu veranschaulichen.

VM-Tipps

Nachdem die VM gestartet ist, klicken Sie in der oberen linken Ecke, um zur Registerkarte Notebook zu wechseln und Jupyter Notebook für die Übung zu öffnen.

Manchmal müssen Sie einige Sekunden warten, bis Jupyter Notebook vollständig geladen ist. Die Validierung von Vorgängen kann aufgrund der Einschränkungen von Jupyter Notebook nicht automatisiert werden.

Wenn Sie bei der Lernphase Probleme haben, können Sie Labby gerne fragen. Geben Sie nach der Sitzung Feedback, und wir werden das Problem für Sie prompt beheben.


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{{"Sparse Signal Regression mit L1-basierten Modellen"}} sklearn/model_selection -.-> lab-49187{{"Sparse Signal Regression mit L1-basierten Modellen"}} sklearn/metrics -.-> lab-49187{{"Sparse Signal Regression mit L1-basierten Modellen"}} ml/sklearn -.-> lab-49187{{"Sparse Signal Regression mit L1-basierten Modellen"}} end

Synthetischen Datensatz generieren

Zunächst generieren wir einen Datensatz, bei dem die Anzahl der Stichproben kleiner ist als die Gesamtzahl der Merkmale. Dies führt zu einem unbestimmten System, d.h., die Lösung ist nicht eindeutig, und wir können eine gewöhnliche kleinste Quadrate-Methode nicht alleine anwenden. Regularisierung führt einen Strafbegriff in die Zielfunktion ein, was das Optimierungsproblem modifiziert und helfen kann, die unbestimmte Natur des Systems zu mildern. Wir werden ein Ziel y generieren, das eine lineare Kombination mit abwechselnden Vorzeichen von sinusförmigen Signalen ist. Nur die 10 niedrigsten von den 100 Frequenzen in X werden verwendet, um y zu generieren, während die restlichen Merkmale nicht informativ sind. Dies führt zu einem hochdimensionalen dünn besetzten Merkmalsraum, in dem ein gewisser Grad an L1-Strafe erforderlich ist.

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

In diesem Schritt werden wir demonstrieren, wie man das Lasso-Regressionsmodell verwendet, um die dünn besetzten Koeffizienten des Datensatzes zu schätzen. Wir werden einen festen Wert für den Regularisierungsparameter alpha verwenden. In der Praxis sollte der optimale Parameter alpha durch Übergeben einer TimeSeriesSplit-Querverifizierungsstrategie an ein LassoCV ausgewählt werden. Um das Beispiel einfach und schnell auszuführen, legen wir hier direkt den optimalen Wert für alpha fest.

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}")

Automatic Relevance Determination (ARD)

Eine ARD-Regression ist die bayesische Version des Lasso. Sie kann, wenn erforderlich, Intervallschätzungen für alle Parameter, einschließlich der Fehlervarianz, liefern. Es ist eine geeignete Option, wenn die Signale Gaussian-Rauschen aufweisen.

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 ist ein Mittelweg zwischen Lasso- und Ridge-Regression, da es eine L1- und eine L2-Strafe kombiniert. Die Stärke der Regularisierung wird durch die beiden Hyperparameter l1_ratio und alpha kontrolliert. Für l1_ratio = 0 ist die Strafe reine L2 und das Modell entspricht einer Ridge-Regression. Ähnlich ist l1_ratio = 1 eine reine L1-Strafe und das Modell entspricht einer Lasso-Regression. Für 0 < l1_ratio < 1 ist die Strafe eine Kombination aus L1 und 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}")

Darstellung und Analyse der Ergebnisse

In diesem Schritt verwenden wir eine Heatmap, um die Dünnbesetzung der wahren und geschätzten Koeffizienten der jeweiligen linearen Modelle zu visualisieren.

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()

Zusammenfassung

Es ist bekannt, dass Lasso sparse Daten effektiv wiedergewinnen kann, aber mit stark korrelierten Merkmalen nicht gut abschneidet. Wenn nämlich mehrere korrelierte Merkmale zum Ziel beitragen, wird Lasso schließlich nur eines von ihnen auswählen. Im Falle von dünn besetzten, aber nicht korrelierten Merkmalen wäre ein Lasso-Modell geeignet.

ElasticNet bringt eine gewisse Dünnbesetzung der Koeffizienten ein und reduziert deren Werte auf Null. Somit kann das Modell in Gegenwart von korrelierten Merkmalen, die zum Ziel beitragen, ihre Gewichte reduzieren, ohne sie genau auf Null zu setzen. Dies führt zu einem weniger dünn besetzten Modell als ein reines Lasso und kann auch nicht prädiktive Merkmale erfassen.

ARDRegression ist bei der Behandlung von Gaussian-Rauschen besser, kann aber immer noch nicht mit korrelierten Merkmalen umgehen und erfordert aufgrund der Anpassung eines Priors mehr Zeit.