Arrêt précoce du Gradient Stochastique

Machine LearningMachine LearningBeginner
Pratiquer maintenant

This tutorial is from open-source community. Access the source code

💡 Ce tutoriel est traduit par l'IA à partir de la version anglaise. Pour voir la version originale, vous pouvez cliquer ici

Introduction

La descente de gradient stochastique est une technique d'optimisation populaire utilisée pour minimiser une fonction de perte. La technique effectue la descente de gradient étape par étape de manière stochastique, c'est-à-dire en sélectionnant aléatoirement des échantillons à chaque itération. La méthode est efficace, en particulier pour ajuster des modèles linéaires. Cependant, la convergence n'est pas garantie à chaque itération, et la fonction de perte ne diminue pas nécessairement à chaque itération. Dans ce cas, il peut être difficile de surveiller la convergence sur la fonction de perte. Dans ce laboratoire, nous explorerons la stratégie d'arrêt précoce, qui est une approche pour surveiller la convergence sur un score de validation. Nous utiliserons le modèle SGDClassifier de la bibliothèque scikit-learn et l'ensemble de données MNIST pour illustrer comment l'arrêt précoce peut être utilisé pour obtenir presque la même précision qu'un modèle construit sans arrêt précoce, et réduire considérablement le temps d'entraînement.

Conseils sur la VM

Une fois le démarrage de la VM terminé, cliquez dans le coin supérieur gauche pour basculer vers l'onglet Notebook pour accéder à Jupyter Notebook pour la pratique.

Parfois, vous devrez peut-être attendre quelques secondes pour que Jupyter Notebook ait fini de charger. La validation des opérations ne peut pas être automatisée en raison des limites de Jupyter Notebook.

Si vous rencontrez des problèmes pendant l'apprentissage, n'hésitez pas à demander à Labby. Donnez votre feedback après la session, et nous résoudrons rapidement le problème pour vous.


Skills Graph

%%%%{init: {'theme':'neutral'}}%%%% flowchart RL ml(("Machine Learning")) -.-> ml/FrameworkandSoftwareGroup(["Framework and Software"]) sklearn(("Sklearn")) -.-> sklearn/ModelSelectionandEvaluationGroup(["Model Selection and Evaluation"]) sklearn(("Sklearn")) -.-> sklearn/UtilitiesandDatasetsGroup(["Utilities and Datasets"]) sklearn/ModelSelectionandEvaluationGroup -.-> sklearn/model_selection("Model Selection") sklearn/UtilitiesandDatasetsGroup -.-> sklearn/utils("Utilities") sklearn/UtilitiesandDatasetsGroup -.-> sklearn/datasets("Datasets") sklearn/UtilitiesandDatasetsGroup -.-> sklearn/exceptions("Exceptions and Warnings") ml/FrameworkandSoftwareGroup -.-> ml/sklearn("scikit-learn") subgraph Lab Skills sklearn/model_selection -.-> lab-49287{{"Arrêt précoce du Gradient Stochastique"}} sklearn/utils -.-> lab-49287{{"Arrêt précoce du Gradient Stochastique"}} sklearn/datasets -.-> lab-49287{{"Arrêt précoce du Gradient Stochastique"}} sklearn/exceptions -.-> lab-49287{{"Arrêt précoce du Gradient Stochastique"}} ml/sklearn -.-> lab-49287{{"Arrêt précoce du Gradient Stochastique"}} end

Charger les bibliothèques et l'ensemble de données MNIST nécessaires

La première étape consiste à charger les bibliothèques et l'ensemble de données nécessaires. Nous utiliserons les bibliothèques pandas, numpy, matplotlib et scikit-learn. Nous utiliserons également la fonction fetch_openml de scikit-learn pour charger l'ensemble de données MNIST.

import time
import sys
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from sklearn import linear_model
from sklearn.datasets import fetch_openml
from sklearn.model_selection import train_test_split
from sklearn.utils._testing import ignore_warnings
from sklearn.exceptions import ConvergenceWarning
from sklearn.utils import shuffle

## Charger l'ensemble de données MNIST
def load_mnist(n_samples=None, class_0="0", class_1="8"):
    """Charger MNIST, sélectionner deux classes, mélanger et retourner seulement n_samples."""
    ## Charger les données à partir de http://openml.org/d/554
    mnist = fetch_openml("mnist_784", version=1, as_frame=False, parser="pandas")

    ## ne prendre que deux classes pour la classification binaire
    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

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)

Définir l'estimateur et la stratégie d'arrêt précoce

La prochaine étape consiste à définir l'estimateur et la stratégie d'arrêt précoce. Nous utiliserons le modèle SGDClassifier de scikit-learn. Nous définirons trois critères d'arrêt différents : aucun critère d'arrêt, perte d'entraînement et score de validation. Nous utiliserons la fonction fit_and_score pour ajuster l'estimateur sur l'ensemble d'entraînement et le noter sur les deux ensembles.

@ignore_warnings(category=ConvergenceWarning)
def fit_and_score(estimator, max_iter, X_train, X_test, y_train, y_test):
    """Ajuster l'estimateur sur l'ensemble d'entraînement et le noter sur les deux ensembles"""
    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

## Définir l'estimateur à comparer
estimator_dict = {
    "Aucun critère d'arrêt": linear_model.SGDClassifier(n_iter_no_change=3),
    "Perte d'entraînement": linear_model.SGDClassifier(
        early_stopping=False, n_iter_no_change=3, tol=0.1
    ),
    "Score de validation": linear_model.SGDClassifier(
        early_stopping=True, n_iter_no_change=3, tol=0.0001, validation_fraction=0.2
    ),
}

Entraîner et évaluer l'estimateur

La prochaine étape consiste à entraîner et évaluer l'estimateur en utilisant chacun des critères d'arrêt. Nous utiliserons une boucle pour itérer sur chaque estimateur et critère d'arrêt, et nous utiliserons une autre boucle pour itérer sur différents nombres maximaux d'itérations. Nous stockerons ensuite les résultats dans un DataFrame pandas pour une représentation graphique facile.

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("")

## Transformer les résultats en un DataFrame pandas pour une représentation graphique facile
columns = [
    "Critère d'arrêt",
    "max_iter",
    "Temps d'ajustement (sec)",
    "n_iter_",
    "Score d'entraînement",
    "Score de test",
]
results_df = pd.DataFrame(results, columns=columns)

Tracer les résultats

La dernière étape consiste à tracer les résultats. Nous utiliserons deux sous-graphiques pour tracer les scores d'entraînement et de test, ainsi que le nombre d'itérations et le temps d'ajustement. Nous utiliserons différents styles de lignes pour chaque estimateur et critère d'arrêt.

## Définir ce qui doit être tracé
lines = "Critère d'arrêt"
x_axis = "max_iter"
styles = ["-.", "--", "-"]

## Premier graphique : scores d'entraînement et de test
fig, axes = plt.subplots(nrows=1, ncols=2, sharey=True, figsize=(12, 4))
for ax, y_axis in zip(axes, ["Score d'entraînement", "Score de test"]):
    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 graphique : n_iter et temps d'ajustement
fig, axes = plt.subplots(nrows=1, ncols=2, figsize=(12, 4))
for ax, y_axis in zip(axes, ["n_iter_", "Temps d'ajustement (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()

Sommaire

Dans ce laboratoire, nous avons exploré la stratégie d'arrêt précoce pour surveiller la convergence sur un score de validation lors de l'utilisation du Gradient Stochastique pour minimiser une fonction de perte. Nous avons utilisé le modèle SGDClassifier de scikit-learn et l'ensemble de données MNIST pour illustrer comment l'arrêt précoce peut être utilisé pour obtenir une précision presque identique à celle d'un modèle construit sans arrêt précoce, et réduire considérablement le temps d'entraînement. Nous avons défini trois critères d'arrêt différents : aucun critère d'arrêt, perte d'entraînement et score de validation, et utilisé une boucle pour entraîner et évaluer l'estimateur en utilisant chacun des critères d'arrêt. Nous avons ensuite tracé les résultats en utilisant différents styles de lignes pour chaque estimateur et critère d'arrêt.