Spec-Zone.ru › scikit-learn

Примечание

Перейти к концу для скачивания полного кода примера. или для запуска этого примера в вашем браузере через JupyterLite или Binder

Модели, основанные на L1, для разреженных сигналов

В данном примере сравниваются три модели регрессии на основе L1 на синтетическом сигнале, полученном из разреженных и коррелированных признаков, которые дополнительно искажены аддитивным гауссовским шумом:

  • модель Lasso;
  • модель Автоматического определения релевантности - ARD;
  • модель Elastic-Net.

Известно, что оценки Lasso оказываются близки к оценкам модели выбора при увеличении размерности данных, при условии, что нерелевантные переменные не слишком коррелированы с релевантными. При наличии коррелированных признаков Lasso сам по себе не может выбрать правильный шаблон разреженности [1].

Здесь мы сравниваем производительность трех моделей по показателю \(R^2\), времени обучения и разреженности оцениваемых коэффициентов по сравнению с истинными значениями.

# Authors: The scikit-learn developers
# SPDX-License-Identifier: BSD-3-Clause

Генерация синтетического набора данных

Мы генерируем набор данных, где количество выборок меньше общего числа признаков. Это приводит к недоопределенной системе, т. е. решение не является уникальным, и поэтому мы не можем применить обычный метод наименьших квадратов сам по себе. Регуляризация добавляет член штрафа к целевой функции, что изменяет задачу оптимизации и может помочь смягчить недоопределенность системы.

Целевой y является линейной комбинацией синусоидальных сигналов с чередующимися знаками. Использованы только 10 наименьших из 100 частот в X для генерации y, в то время как остальные признаки не информативны. Это приводит к высокоразмерному разреженному пространству признаков, где необходима какая-то степень 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)

Некоторые из информативных признаков имеют близкие частоты, чтобы вызвать (анти-)корреляции.

freqs[:n_informative]
array([ 2.9502547 , 11.8059798 , 12.63394388, 12.70359377, 24.62241605,
       37.84077985, 40.30506066, 44.63327171, 54.74495357, 59.02456369])

Случайная фаза вводится с помощью numpy.random.random_sample, а некоторый гауссовский шум (реализованный с помощью 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)

Такие разреженные, шумные и коррелированные признаки могут быть получены, например, от сенсорных узлов, контролирующих некоторые переменные окружающей среды, поскольку они обычно регистрируют похожие значения в зависимости от их расположения (пространственная корреляция). Мы можем визуализировать целевую переменную.

import matplotlib.pyplot as plt

plt.plot(time_step, y)
plt.ylabel("target signal")
plt.xlabel("time")
_ = plt.title("Superposition of sinusoidal signals")
Superposition of sinusoidal signals

Для простоты данные разбиваются на обучающую и тестовую выборки. На практике следует использовать TimeSeriesSplit кросс-валидацию для оценки дисперсии тестовой метрики. Здесь мы установили shuffle="False", так как при работе с данными, имеющими временную зависимость, нельзя использовать обучающие данные, которые следуют за тестовыми данными.

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)

В дальнейшем мы вычислим производительность трех моделей на основе L1 по показателю качества подгонки \(R^2\) и времени обучения. Затем мы построим график для сравнения разреженности оцениваемых коэффициентов с истинными коэффициентами и, наконец, проанализируем полученные результаты.

Lasso

В этом примере мы демонстрируем Lasso с фиксированным значением параметра регуляризации alpha. На практике оптимальный параметр alpha следует выбирать, передавая TimeSeriesSplit стратегию кросс-валидации в LassoCV. Чтобы сохранить пример простым и быстрым в выполнении, мы здесь непосредственно задаем оптимальное значение для alpha.

from time import time

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

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}")
Lasso fit done in 0.001s
Lasso r^2 on test data : 0.480

Автоматическое определение релевантности (ARD)

Регрессия ARD является байесовской версией Lasso. Она может давать интервальные оценки для всех параметров, включая дисперсию ошибки, если это необходимо. Это подходящий вариант, когда сигналы имеют гауссовский шум. См. пример Сравнение линейных байесовских регрессоров для сравнения ARDRegression и BayesianRidge регрессоров.

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}")
ARD fit done in 0.019s
ARD r^2 on test data : 0.543

ElasticNet

ElasticNet является промежуточным вариантом между Lasso и Ridge, так как объединяет L1 и L2-штрафы. Величина регуляризации контролируется двумя гиперпараметрами l1_ratio и alpha. Для l1_ratio = 0 штраф представляет собой чистую L2-регуляризацию, и модель эквивалентна Ridge. Аналогично, l1_ratio = 1 представляет собой чистый L1-штраф, и модель эквивалентна Lasso. Для 0 < l1_ratio < 1 штраф представляет собой комбинацию L1 и L2.

Как и прежде, мы обучаем модель с фиксированными значениями alpha и l1_ratio. Для выбора их оптимальных значений мы использовали ElasticNetCV, что не показано здесь для простоты примера.

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}")
ElasticNet fit done in 0.001s
ElasticNet r^2 on test data : 0.636

График и анализ результатов

В этом разделе мы используем тепловую карту для визуализации разреженности истинных и оцениваемых коэффициентов соответствующих линейных моделей.

import matplotlib.pyplot as plt
import pandas as pd
import seaborn as sns
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()
Models' coefficients Lasso $R^2$: 0.480, ARD $R^2$: 0.543, ElasticNet $R^2$: 0.636

В данном примере ElasticNet дает лучший результат и захватывает большинство предсказательных признаков, но все еще не находит все истинные компоненты. Обратите внимание, что как ElasticNet, так и ARDRegression приводят к менее разреженной модели, чем Lasso.

Выводы

Lasso известен тем, что эффективно восстанавливает разреженные данные, но плохо работает с сильно коррелированными признаками. Действительно, если несколько коррелированных признаков вносят вклад в целевую переменную, Lasso в итоге выберет только один из них. В случае разреженных, но некоррелированных признаков, модель Lasso будет более подходящей.

ElasticNet вносит некоторую разреженность в коэффициенты и сжимает их значения к нулю. Таким образом, при наличии коррелированных признаков, которые вносят вклад в целевую переменную, модель по-прежнему способна уменьшить их веса, не устанавливая их точно в ноль. Это приводит к менее разреженной модели, чем чисто Lasso, и может захватить также и непредсказательные признаки.

ARDRegression лучше справляется с гауссовским шумом, но по-прежнему не может обрабатывать коррелированные признаки и требует большего времени из-за подгонки априорного распределения.

Ссылки

[1]

“Восстановление разреженных представлений с использованием метода LASSO для высокомерных данных” N. Meinshausen, B. Yu - Журнал «Annals of Statistics» 2009, том 37, № 1, 246-270

Общее время выполнения скрипта: (0 минут 0.517 секунд)

Launch binder
Launch JupyterLite

Download Jupyter notebook: plot_lasso_and_elasticnet.ipynb

Download Python source code: plot_lasso_and_elasticnet.py

Download zipped: plot_lasso_and_elasticnet.zip

Связанные примеры

Lasso для плотных и разреженных данных

Пути LASSO, LASSO-LARS и Elastic Net

Совместный отбор признаков с помощью многозадачного LASSO

Влияние регуляризации модели на ошибки обучения и тестирования

© 2007–2025 The scikit-learn developers
Licensed under the 3-clause BSD License.
https://scikit-learn.org/1.6/auto_examples/linear_model/plot_lasso_and_elasticnet.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API