Примечание
Перейти к концу, чтобы скачать полный пример кода. или запустить этот пример в браузере через JupyterLite или Binder
Прекращение обучения стохастического градиентного спуска по достижению предела
Стохастический градиентный спуск — это метод оптимизации, который минимизирует функцию потерь стохастическим способом, выполняя шаг градиентного спуска для каждого примера данных. В частности, это очень эффективный метод для обучения линейных моделей.
Как стохастический метод, функция потерь не обязательно убывает на каждой итерации, и сходимость гарантируется только в среднем. По этой причине отслеживание сходимости по функции потерь может быть затруднено.
Другой подход заключается в отслеживании сходимости по показателю на проверочном наборе. В этом случае входные данные разбиваются на обучающий и проверочный наборы. Затем модель обучается на обучающем наборе, а критерий остановки основан на показателе прогнозирования, вычисленном на проверочном наборе. Это позволяет нам найти наименьшее количество итераций, достаточное для построения модели, которая хорошо обобщается на новые данные и уменьшает вероятность переобучения на обучающих данных.
Эта стратегия ранней остановки активируется, если early_stopping=True; в противном случае критерий остановки использует только потери на обучении на всех входных данных. Для лучшего управления стратегией ранней остановки мы можем указать параметр validation_fraction, который устанавливает долю входных данных, которую мы оставляем для вычисления показателя на проверочном наборе. Оптимизация будет продолжаться до тех пор, пока показатель на проверочном наборе не улучшится как минимум на tol за последние n_iter_no_change итераций. Фактическое количество итераций доступно в атрибуте n_iter_.
Этот пример демонстрирует, как раннюю остановку можно использовать в модели SGDClassifier, чтобы добиться почти такой же точности, как и в модели, обученной без ранней остановки. Это может значительно сократить время обучения. Обратите внимание, что показатели различаются между критериями остановки даже на ранних итерациях, поскольку часть обучающих данных выделяется для проверочного критерия остановки.
No stopping criterion: ................................................. Training loss: ................................................. Validation score: .................................................
# Authors: The scikit-learn developers
# SPDX-License-Identifier: BSD-3-Clause
import sys
import time
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
from sklearn import linear_model
from sklearn.datasets import fetch_openml
from sklearn.exceptions import ConvergenceWarning
from sklearn.model_selection import train_test_split
from sklearn.utils import shuffle
from sklearn.utils._testing import ignore_warnings
def load_mnist(n_samples=None, class_0="0", class_1="8"):
"""Load MNIST, select two classes, shuffle and return only n_samples."""
# Load data from http://openml.org/d/554
mnist = fetch_openml("mnist_784", version=1, as_frame=False)
# take only two classes for binary classification
mask = np.logical_or(mnist.target == class_0, mnist.target == class_1)
X, y = shuffle(mnist.data[mask], mnist.target[mask], random_state=42)
if n_samples is not None:
X, y = X[:n_samples], y[:n_samples]
return X, y
@ignore_warnings(category=ConvergenceWarning)
def fit_and_score(estimator, max_iter, X_train, X_test, y_train, y_test):
"""Fit the estimator on the train set and score it on both sets"""
estimator.set_params(max_iter=max_iter)
estimator.set_params(random_state=0)
start = time.time()
estimator.fit(X_train, y_train)
fit_time = time.time() - start
n_iter = estimator.n_iter_
train_score = estimator.score(X_train, y_train)
test_score = estimator.score(X_test, y_test)
return fit_time, n_iter, train_score, test_score
# Define the estimators to compare
estimator_dict = {
"No stopping criterion": linear_model.SGDClassifier(n_iter_no_change=3),
"Training loss": linear_model.SGDClassifier(
early_stopping=False, n_iter_no_change=3, tol=0.1
),
"Validation score": linear_model.SGDClassifier(
early_stopping=True, n_iter_no_change=3, tol=0.0001, validation_fraction=0.2
),
}
# Load the dataset
X, y = load_mnist(n_samples=10000)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.5, random_state=0)
results = []
for estimator_name, estimator in estimator_dict.items():
print(estimator_name + ": ", end="")
for max_iter in range(1, 50):
print(".", end="")
sys.stdout.flush()
fit_time, n_iter, train_score, test_score = fit_and_score(
estimator, max_iter, X_train, X_test, y_train, y_test
)
results.append(
(estimator_name, max_iter, fit_time, n_iter, train_score, test_score)
)
print("")
# Transform the results in a pandas dataframe for easy plotting
columns = [
"Stopping criterion",
"max_iter",
"Fit time (sec)",
"n_iter_",
"Train score",
"Test score",
]
results_df = pd.DataFrame(results, columns=columns)
# Define what to plot
lines = "Stopping criterion"
x_axis = "max_iter"
styles = ["-.", "--", "-"]
# First plot: train and test scores
fig, axes = plt.subplots(nrows=1, ncols=2, sharey=True, figsize=(12, 4))
for ax, y_axis in zip(axes, ["Train score", "Test score"]):
for style, (criterion, group_df) in zip(styles, results_df.groupby(lines)):
group_df.plot(x=x_axis, y=y_axis, label=criterion, ax=ax, style=style)
ax.set_title(y_axis)
ax.legend(title=lines)
fig.tight_layout()
# Second plot: n_iter and fit time
fig, axes = plt.subplots(nrows=1, ncols=2, figsize=(12, 4))
for ax, y_axis in zip(axes, ["n_iter_", "Fit time (sec)"]):
for style, (criterion, group_df) in zip(styles, results_df.groupby(lines)):
group_df.plot(x=x_axis, y=y_axis, label=criterion, ax=ax, style=style)
ax.set_title(y_axis)
ax.legend(title=lines)
fig.tight_layout()
plt.show()
Общее время выполнения скрипта: (0 минут 24.043 секунды)
Примеры по теме
© 2007–2025 The scikit-learn developers
Licensed under the 3-clause BSD License.
https://scikit-learn.org/1.6/auto_examples/linear_model/plot_sgd_early_stopping.html

