Spec-Zone.ru › scikit-learn

Примечание

Перейти в конец, чтобы скачать полный код примера или запустить этот пример в браузере с помощью JupyterLite или Binder.

Масштабирование параметра регуляризации для SVC

В следующем примере показано влияние масштабирования параметра регуляризации при использовании машин опорных векторов для классификации. Для классификации с помощью SVC нас интересует минимизация риска для уравнения:

\[C \sum_{i=1, n} \mathcal{L} (f(x_i), y_i) + \Omega (w)\]

где

  • \(C\) используется для задания степени регуляризации
  • \(\mathcal{L}\) — функция loss для наших выборок и параметров модели.
  • \(\Omega\) — функция penalty от параметров модели

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

Например, при использовании перекрёстной проверки для задания степени регуляризации с помощью C количество объектов в основной задаче будет отличаться от количества объектов в меньших задачах внутри фолдов перекрёстной проверки.

Поскольку функция потерь зависит от количества объектов, оно влияет на выбранное значение C. Возникает вопрос: «Как оптимально скорректировать C с учётом различного количества обучающих объектов?»

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

Генерация данных

В этом примере мы исследуем влияние перепараметризации параметра регуляризации C с учётом количества объектов при использовании штрафа L1 или L2. Для этого мы создаём синтетический набор данных с большим количеством признаков, лишь некоторые из которых информативны. Поэтому мы ожидаем, что регуляризация будет уменьшать коэффициенты до нуля (штраф L2) или точно до нуля (штраф L1).

from sklearn.datasets import make_classification

n_samples, n_features = 100, 300
X, y = make_classification(
    n_samples=n_samples, n_features=n_features, n_informative=5, random_state=1
)

Случай штрафа L1

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

Мы задаём линейный SVC со штрафом L1.

from sklearn.svm import LinearSVC

model_l1 = LinearSVC(penalty="l1", loss="squared_hinge", dual=False, tol=1e-3)

С помощью перекрёстной проверки вычисляем среднюю оценку на тестовых данных для различных значений C.

import numpy as np
import pandas as pd

from sklearn.model_selection import ShuffleSplit, validation_curve

Cs = np.logspace(-2.3, -1.3, 10)
train_sizes = np.linspace(0.3, 0.7, 3)
labels = [f"fraction: {train_size}" for train_size in train_sizes]
shuffle_params = {
    "test_size": 0.3,
    "n_splits": 150,
    "random_state": 1,
}

results = {"C": Cs}
for label, train_size in zip(labels, train_sizes):
    cv = ShuffleSplit(train_size=train_size, **shuffle_params)
    train_scores, test_scores = validation_curve(
        model_l1,
        X,
        y,
        param_name="C",
        param_range=Cs,
        cv=cv,
        n_jobs=2,
    )
    results[label] = test_scores.mean(axis=1)
results = pd.DataFrame(results)
import matplotlib.pyplot as plt

fig, axes = plt.subplots(nrows=1, ncols=2, sharey=True, figsize=(12, 6))

# plot results without scaling C
results.plot(x="C", ax=axes[0], logx=True)
axes[0].set_ylabel("CV score")
axes[0].set_title("No scaling")

for label in labels:
    best_C = results.loc[results[label].idxmax(), "C"]
    axes[0].axvline(x=best_C, linestyle="--", color="grey", alpha=0.7)

# plot results by scaling C
for train_size_idx, label in enumerate(labels):
    train_size = train_sizes[train_size_idx]
    results_scaled = results[[label]].assign(
        C_scaled=Cs * float(n_samples * np.sqrt(train_size))
    )
    results_scaled.plot(x="C_scaled", ax=axes[1], logx=True, label=label)
    best_C_scaled = results_scaled["C_scaled"].loc[results[label].idxmax()]
    axes[1].axvline(x=best_C_scaled, linestyle="--", color="grey", alpha=0.7)

axes[1].set_title("Scaling C by sqrt(1 / n_samples)")

_ = fig.suptitle("Effect of scaling C with L1 penalty")
Effect of scaling C with L1 penalty, No scaling, Scaling C by sqrt(1 / n_samples)

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

Использование масштаба по умолчанию приводит к относительно стабильному оптимальному значению C, тогда как момент выхода из области недообучения зависит от количества обучающих объектов. Перепараметризация даёт ещё более стабильные результаты.

См., например, теорему 3 в статье О качестве предсказаний Lasso или статью Одновременный анализ Lasso и селектора Данцига, где предполагается, что параметр регуляризации всегда пропорционален 1 / sqrt(n_samples).

Случай штрафа L2

Похожий эксперимент можно провести со штрафом L2. В этом случае теория утверждает, что для достижения состоятельности предсказаний параметр штрафа должен оставаться постоянным по мере роста количества объектов.

model_l2 = LinearSVC(penalty="l2", loss="squared_hinge", dual=True)
Cs = np.logspace(-8, 4, 11)

labels = [f"fraction: {train_size}" for train_size in train_sizes]
results = {"C": Cs}
for label, train_size in zip(labels, train_sizes):
    cv = ShuffleSplit(train_size=train_size, **shuffle_params)
    train_scores, test_scores = validation_curve(
        model_l2,
        X,
        y,
        param_name="C",
        param_range=Cs,
        cv=cv,
        n_jobs=2,
    )
    results[label] = test_scores.mean(axis=1)
results = pd.DataFrame(results)
import matplotlib.pyplot as plt

fig, axes = plt.subplots(nrows=1, ncols=2, sharey=True, figsize=(12, 6))

# plot results without scaling C
results.plot(x="C", ax=axes[0], logx=True)
axes[0].set_ylabel("CV score")
axes[0].set_title("No scaling")

for label in labels:
    best_C = results.loc[results[label].idxmax(), "C"]
    axes[0].axvline(x=best_C, linestyle="--", color="grey", alpha=0.8)

# plot results by scaling C
for train_size_idx, label in enumerate(labels):
    results_scaled = results[[label]].assign(
        C_scaled=Cs * float(n_samples * np.sqrt(train_sizes[train_size_idx]))
    )
    results_scaled.plot(x="C_scaled", ax=axes[1], logx=True, label=label)
    best_C_scaled = results_scaled["C_scaled"].loc[results[label].idxmax()]
    axes[1].axvline(x=best_C_scaled, linestyle="--", color="grey", alpha=0.8)
axes[1].set_title("Scaling C by sqrt(1 / n_samples)")

fig.suptitle("Effect of scaling C with L2 penalty")
plt.show()
Effect of scaling C with L2 penalty, No scaling, Scaling C by sqrt(1 / n_samples)

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

Для улучшения результатов в случае L2 попробуйте увеличить значение до n_splits=1_000; этот вариант здесь не показан из-за ограничений сборщика документации.

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

Launch binder
Launch JupyterLite

Download Jupyter notebook: plot_svm_scale_c.ipynb

Download Python source code: plot_svm_scale_c.py

Download zipped: plot_svm_scale_c.zip

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

Штраф L1 и разреженность в логистической регрессии

Коэффициенты Ridge в зависимости от регуляризации L2

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

Важность масштабирования признаков

© 2007–2026 The scikit-learn developers
Licensed under the 3-clause BSD License.
https://scikit-learn.org/1.9/auto_examples/svm/plot_svm_scale_c.html

Spec-Zone.ru

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