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 представляет собой линейную комбинацию синусоидальных сигналов с чередующимися знаками. Для генерации y используются только 10 самых низких частот из 100 в X, а остальные признаки не несут информации. В результате получается высокоразмерное разреженное пространство признаков, где необходима определенная степень 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.002s
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.061s
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 — The Annals of Statistics, 2009, т. 37, № 1, 246–270

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

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–2026 The scikit-learn developers
Licensed under the 3-clause BSD License.
https://scikit-learn.org/1.9/auto_examples/linear_model/plot_lasso_and_elasticnet.html

Spec-Zone.ru

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