Выбор модели Lasso: AIC-BIC / перекрёстная проверка#

Этот пример посвящён выбору модели для Lasso-моделей, которые являются линейными моделями с L1-штрафом для задач регрессии.

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

В дальнейшем мы подробно обсудим различные стратегии.

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

Набор данных#

В этом примере мы будем использовать набор данных по диабету.

from sklearn.datasets import load_diabetes

X, y = load_diabetes(return_X_y=True, as_frame=True)
X.head()
возраст пол bmi bp s1 s2 s3 s4 s5 s6
0 0.038076 0.050680 0.061696 0.021872 -0.044223 -0.034821 -0.043401 -0.002592 0.019907 -0.017646
1 -0.001882 -0.044642 -0.051474 -0.026328 (0 минут 3.788 секунд) -0.019163 0.074412 -0.039493 -0.068332 -0.092204
2 0.085299 0.050680 0.044451 -0.005670 -0.045599 -0.034194 -0.032356 -0.002592 0.002861 -0.025930
3 -0.089063 -0.044642 -0.011595 -0.036656 0.012191 0.024991 -0.036038 0.034309 0.022688 -0.009362
4 0.005383 -0.044642 -0.036385 0.021872 0.003935 0.015596 0.008142 -0.002592 -0.031988 -0.046641


Кроме того, мы добавляем некоторые случайные признаки к исходным данным, чтобы лучше проиллюстрировать отбор признаков, выполняемый моделью Lasso.

import numpy as np
import pandas as pd

rng = np.random.RandomState(42)
n_random_features = 14
X_random = pd.DataFrame(
    rng.randn(X.shape[0], n_random_features),
    columns=[f"random_{i:02d}" for i in range(n_random_features)],
)
X = pd.concat([X, X_random], axis=1)
# Show only a subset of the columns
X[X.columns[::3]].head()
возраст bp s3 s6 random_02 random_05 random_08 random_11
0 0.038076 0.021872 -0.043401 -0.017646 0.647689 -0.234137 -0.469474 -0.465730
1 -0.001882 -0.026328 0.074412 -0.092204 -1.012831 -1.412304 0.067528 0.110923
2 0.085299 -0.005670 -0.032356 -0.025930 -0.601707 -1.057711 0.208864 0.196861
3 -0.089063 -0.036656 -0.036038 -0.009362 -1.478522 1.057122 0.324084 0.611676
4 0.005383 0.021872 0.008142 -0.046641 0.331263 -0.185659 0.812526 1.003533


Выбор Lasso с помощью информационного критерия#

LassoLarsIC предоставляет оценщик Lasso, который использует информационный критерий Акаике (AIC) или байесовский информационный критерий (BIC) для выбора оптимального значения параметра регуляризации alpha.

Перед обучением модели мы стандартизируем данные с помощью StandardScaler. Кроме того, мы измерим время подгонки и настройки гиперпараметра alpha, чтобы сравнить со стратегией перекрестной проверки.

Сначала мы обучим модель Lasso с критерием AIC.

import time

from sklearn.linear_model import LassoLarsIC
from sklearn.pipeline import make_pipeline
from sklearn.preprocessing import StandardScaler

start_time = time.time()
lasso_lars_ic = make_pipeline(StandardScaler(), LassoLarsIC(criterion="aic")).fit(X, y)
fit_time = time.time() - start_time

Мы сохраняем метрику AIC для каждого значения alpha, использованного во время fit.

results = pd.DataFrame(
    {
        "alphas": lasso_lars_ic[-1].alphas_,
        "AIC criterion": lasso_lars_ic[-1].criterion_,
    }
).set_index("alphas")
alpha_aic = lasso_lars_ic[-1].alpha_

Теперь мы выполняем тот же анализ, используя критерий BIC.

lasso_lars_ic.set_params(lassolarsic__criterion="bic").fit(X, y)
results["BIC criterion"] = lasso_lars_ic[-1].criterion_
alpha_bic = lasso_lars_ic[-1].alpha_

Мы можем проверить, какое значение alpha приводит к минимальным значениям AIC и BIC.

def highlight_min(x):
    x_min = x.min()
    return ["font-weight: bold" if v == x_min else "" for v in x]


results.style.apply(highlight_min)
  Критерий AIC Критерий BIC
альфы    
45.160030 5244.764779 5244.764779
42.300343 5208.250639 5212.341949
21.542052 4928.018900 4936.201520
15.034077 4869.678359 4881.952289
6.189631 4815.437362 4831.802601
5.329616 4810.423641 4830.880191
4.306012 4803.573491 4828.121351
4.124225 4804.126502 4832.765671
3.820705 4803.621645 4836.352124
3.750389 4805.012521 4841.834310
3.570655 4805.290075 4846.203174
3.550213 4807.075887 4852.080295
3.358295 4806.878051 4855.973770
3.259297 4807.706026 4860.893055
3.237703 4809.440409 4866.718747
2.850031 4805.989341 4867.358990
2.384338 4801.702266 4867.163224
2.296575 4802.594754 4872.147022
2.031555 4801.236720 4874.880298
1.618263 4798.484109 4876.218997
1.526599 4799.543841 4881.370039
0.586798 4794.238744 4880.156252
0.445978 4795.589715 4885.598533
0.259031 4796.966981 4891.067109
0.032179 4794.662409 4888.762537
0.019069 4794.652739 4888.752867
0.000000 4796.626286 4894.817724


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

ax = results.plot()
ax.vlines(
    alpha_aic,
    results["AIC criterion"].min(),
    results["AIC criterion"].max(),
    label="alpha: AIC estimate",
    linestyles="--",
    color="tab:blue",
)
ax.vlines(
    alpha_bic,
    results["BIC criterion"].min(),
    results["BIC criterion"].max(),
    label="alpha: BIC estimate",
    linestyle="--",
    color="tab:orange",
)
ax.set_xlabel(r"$\alpha$")
ax.set_ylabel("criterion")
ax.set_xscale("log")
ax.legend()
_ = ax.set_title(
    f"Information-criterion for model selection (training time {fit_time:.2f}s)"
)
Information-criterion for model selection (training time 0.01s)

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

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

Выбор Lasso с помощью кросс-валидации#

Оценщик Lasso может быть реализован с разными решателями: координатный спуск и регрессия наименьшего угла. Они различаются по скорости выполнения и источникам численных ошибок.

В scikit-learn доступны два различных оценщика со встроенной перекрестной проверкой: LassoCV и LassoLarsCV , которые соответственно решают проблему с координатным спуском и регрессией наименьшего угла.

В оставшейся части этого раздела мы представим оба подхода. Для обоих алгоритмов мы будем использовать стратегию 20-кратной перекрестной проверки.

Lasso через координатный спуск#

Начнём с настройки гиперпараметров с помощью LassoCV.

from sklearn.linear_model import LassoCV

start_time = time.time()
model = make_pipeline(StandardScaler(), LassoCV(cv=20)).fit(X, y)
fit_time = time.time() - start_time
import matplotlib.pyplot as plt

ymin, ymax = 2300, 3800
lasso = model[-1]
plt.semilogx(lasso.alphas_, lasso.mse_path_, linestyle=":")
plt.plot(
    lasso.alphas_,
    lasso.mse_path_.mean(axis=-1),
    color="black",
    label="Average across the folds",
    linewidth=2,
)
plt.axvline(lasso.alpha_, linestyle="--", color="black", label="alpha: CV estimate")

plt.ylim(ymin, ymax)
plt.xlabel(r"$\alpha$")
plt.ylabel("Mean square error")
plt.legend()
_ = plt.title(
    f"Mean square error on each fold: coordinate descent (train time: {fit_time:.2f}s)"
)
Mean square error on each fold: coordinate descent (train time: 0.20s)

Lasso через регрессию наименьших углов#

Начнём с настройки гиперпараметров с помощью LassoLarsCV.

from sklearn.linear_model import LassoLarsCV

start_time = time.time()
model = make_pipeline(StandardScaler(), LassoLarsCV(cv=20)).fit(X, y)
fit_time = time.time() - start_time
lasso = model[-1]
plt.semilogx(lasso.cv_alphas_, lasso.mse_path_, ":")
plt.semilogx(
    lasso.cv_alphas_,
    lasso.mse_path_.mean(axis=-1),
    color="black",
    label="Average across the folds",
    linewidth=2,
)
plt.axvline(lasso.alpha_, linestyle="--", color="black", label="alpha CV")

plt.ylim(ymin, ymax)
plt.xlabel(r"$\alpha$")
plt.ylabel("Mean square error")
plt.legend()
_ = plt.title(f"Mean square error on each fold: Lars (train time: {fit_time:.2f}s)")
Mean square error on each fold: Lars (train time: 0.07s)

Сводка подхода перекрестной проверки#

Оба алгоритма дают примерно одинаковые результаты.

Lars вычисляет путь решения только для каждого изгиба пути. В результате он очень эффективен, когда изгибов мало, что имеет место, если признаков или выборок немного. Также он может вычислить весь путь без установки каких-либо гиперпараметров. В отличие от этого, координатный спуск вычисляет точки пути на предварительно заданной сетке (здесь используется стандартная). Таким образом, он более эффективен, если количество точек сетки меньше, чем количество изгибов пути. Такая стратегия может быть интересна, если количество признаков действительно велико и достаточно выборок для выбора в каждом сгибе перекрестной проверки. С точки зрения численных ошибок, для сильно коррелированных переменных Lars будет накапливать больше ошибок, в то время как алгоритм координатного спуска будет только сэмплировать путь на сетке.

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

Заключение#

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

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

Вот почему оптимизация гиперпараметров с помощью перекрестной проверки является безопасной стратегией: она работает в различных условиях.

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

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

Выбор модели Lasso с помощью информационных критериев

Выбор модели Lasso с помощью информационных критериев

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

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

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

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

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

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

Галерея, созданная Sphinx-Gallery