Примечание
Перейти к концу, чтобы загрузить весь пример кода. или запустить этот пример в вашем браузере через JupyterLite или Binder
Масштабирование параметра регуляризации для SVC
Следующий пример иллюстрирует эффект масштабирования параметра регуляризации при использовании машин опорных векторов для классификации. Для классификации SVC нас интересует минимизация риска для уравнения:
где
- \(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")

В области малых значений C (сильная регуляризация) все коэффициенты, вычисленные моделями, равны нулю, что приводит к сильному недообучению. Действительно, точность в этой области находится на уровне случайности.
Использование стандартного масштаба приводит к относительно стабильному оптимальному значению C, в то время как переход из области недообучения зависит от количества обучающих выборок. Перепараметризация приводит к еще более стабильным результатам.
См., например, теорему 3 статьи On the prediction performance of the Lasso или Simultaneous analysis of Lasso and Dantzig selector, где параметр регуляризации всегда предполагается пропорциональным 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()

В случае штрафа L2 перепараметризация, по-видимому, оказывает меньшее влияние на стабильность оптимального значения регуляризации. Переход из области переобучения происходит в более широком диапазоне, а точность, по-видимому, не ухудшается до уровня случайности.
Попробуйте увеличить значение до n_splits=1_000 для достижения лучших результатов в случае L2, что здесь не показано из-за ограничений в инструменте документации.
Общее время выполнения скрипта: (0 минут 23.118 секунды)
Похожие примеры
© 2007–2025 The scikit-learn developers
Licensed under the 3-clause BSD License.
https://scikit-learn.org/1.6/auto_examples/svm/plot_svm_scale_c.html