Введение
В этом лабораторном занятии мы покажем, как использовать модели регрессии на основе L1 для обработки высокомерных и разреженных сигналов. В частности, мы сравним три популярные модели на основе L1: Lasso, Automatic Relevance Determination (ARD) и ElasticNet. Мы будем использовать синтетический датасет, чтобы проиллюстрировать производительность этих моделей в терминах времени подгонки, R2-оценки и разреженности оцененных коэффициентов.
Советы по использованию ВМ
После запуска ВМ нажмите в левом верхнем углу, чтобы переключиться на вкладку Notebook и получить доступ к Jupyter Notebook для практики.
Иногда вам может потребоваться подождать несколько секунд, пока Jupyter Notebook не загрузится полностью. Валидация операций не может быть автоматизирована из-за ограничений Jupyter Notebook.
Если вы сталкиваетесь с проблемами во время обучения, не стесняйтесь обращаться к Labby. Оставьте отзыв после занятия, и мы оперативно решим проблему для вас.
Генерация синтетического датасета
Сначала мы генерируем датасет, в котором количество выборок меньше общего количества признаков. Это приводит к недоопределенной системе, то есть решение не является уникальным, и мы не можем применить обычные наименьшие квадраты самостоятельно. Регуляризация вводит штрафную функцию в функцию целевого функционала, которая изменяет задачу оптимизации и может помочь облегчить недоопределенность системы. Мы сгенерируем целевую переменную 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)
## 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
В этом шаге мы покажем, как использовать модель Lasso-регрессии для оценки разреженных коэффициентов датасета. Мы будем использовать фиксированное значение параметра регуляризации alpha. На практике оптимальный параметр alpha должен быть выбран путём передачи стратегии кросс-валидации TimeSeriesSplit в LassoCV. Чтобы сделать пример простым и быстро исполняемым, мы здесь напрямую задаём оптимальное значение для 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}")
Automatic Relevance Determination (ARD)
АРД-регрессия представляет собой байесовскую версию Lasso. Она может выдавать интервальные оценки для всех параметров, включая дисперсию ошибки, при необходимости. Это подходящий вариант, когда сигналы имеют гауссовский шум.
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 представляет собой компромисс между Lasso и Ridge-регрессией, так как комбинирует L1- и L2-штрафы. Величина регуляризации контролируется двумя гиперпараметрами l1_ratio и alpha. При l1_ratio = 0 штраф является чисто L2, и модель эквивалентна Ridge-регрессии. Аналогично, l1_ratio = 1 представляет собой чисто L1-штраф, и модель эквивалентна Lasso-регрессии. При 0 < l1_ratio < 1 штраф является комбинацией L1 и 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}")
Построение и анализ результатов
В этом шаге мы используем тепловую карту для визуализации разреженности истинных и оцененных коэффициентов соответствующих линейных моделей.
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": "значения коэффициентов"},
cmap="seismic_r",
)
plt.ylabel("линейная модель")
plt.xlabel("коэффициенты")
plt.title(
f"Коэффициенты моделей\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()
Обзор
Известно, что Lasso эффективно восстанавливает разреженные данные, но плохо справляется с сильно коррелированными признаками. Действительно, если несколько коррелированных признаков влияют на целевую переменную, Lasso в итоге выберет только один из них. В случае разреженных, но не коррелированных признаков модель Lasso будет более подходящей.
ElasticNet вводит некоторую разреженность в коэффициентах и сужает их значения до нуля. Таким образом, при наличии коррелированных признаков, влияющих на целевую переменную, модель все еще способна уменьшить их веса, не устанавливая их точно в нуль. Это приводит к менее разреженной модели, чем чистый Lasso, и может также захватывать не предсказательные признаки.
ARDRegression лучше справляется с гауссовским шумом, но все еще не способна обрабатывать коррелированные признаки и требует большего количества времени из-за настройки априорной вероятности.