Parada temprana del Descenso de Gradiente Estocástico

Machine LearningMachine LearningBeginner
Practicar Ahora

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

💡 Este tutorial está traducido por IA desde la versión en inglés. Para ver la versión original, puedes hacer clic aquí

Introducción

El Descenso de Gradiente Estocástico es una técnica de optimización popular utilizada para minimizar una función de pérdida. La técnica realiza pasos de descenso de gradiente de manera estocástica, es decir, seleccionando aleatoriamente muestras para cada iteración. El método es eficiente, especialmente para ajustar modelos lineales. Sin embargo, no está garantizada la convergencia en cada iteración, y la función de pérdida no necesariamente disminuye en cada iteración. En este caso, puede ser difícil monitorear la convergencia en la función de pérdida. En este laboratorio, exploraremos la estrategia de parada temprana, que es un enfoque para monitorear la convergencia en una puntuación de validación. Utilizaremos el modelo SGDClassifier de la biblioteca scikit-learn y el conjunto de datos MNIST para ilustrar cómo la parada temprana se puede utilizar para lograr una precisión casi igual a la de un modelo construido sin parada temprana, y reducir significativamente el tiempo de entrenamiento.

Consejos sobre la VM

Una vez finalizada la inicialización de la VM, haga clic en la esquina superior izquierda para cambiar a la pestaña Cuaderno y acceder a Jupyter Notebook para practicar.

A veces, es posible que tenga que esperar unos segundos a que Jupyter Notebook termine de cargarse. La validación de operaciones no se puede automatizar debido a las limitaciones de Jupyter Notebook.

Si tiene problemas durante el aprendizaje, no dude en preguntar a Labby. Deje comentarios después de la sesión y resolveremos rápidamente el problema para usted.


Skills Graph

%%%%{init: {'theme':'neutral'}}%%%% flowchart RL sklearn(("Sklearn")) -.-> sklearn/ModelSelectionandEvaluationGroup(["Model Selection and Evaluation"]) sklearn(("Sklearn")) -.-> sklearn/UtilitiesandDatasetsGroup(["Utilities and Datasets"]) ml(("Machine Learning")) -.-> ml/FrameworkandSoftwareGroup(["Framework and Software"]) 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{{"Parada temprana del Descenso de Gradiente Estocástico"}} sklearn/utils -.-> lab-49287{{"Parada temprana del Descenso de Gradiente Estocástico"}} sklearn/datasets -.-> lab-49287{{"Parada temprana del Descenso de Gradiente Estocástico"}} sklearn/exceptions -.-> lab-49287{{"Parada temprana del Descenso de Gradiente Estocástico"}} ml/sklearn -.-> lab-49287{{"Parada temprana del Descenso de Gradiente Estocástico"}} end

Cargar las bibliotecas necesarias y el conjunto de datos MNIST

El primer paso es cargar las bibliotecas necesarias y el conjunto de datos. Utilizaremos las bibliotecas pandas, numpy, matplotlib y scikit-learn. También usaremos la función fetch_openml de scikit-learn para cargar el conjunto de datos 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

## Cargar el conjunto de datos MNIST
def load_mnist(n_samples=None, class_0="0", class_1="8"):
    """Cargar MNIST, seleccionar dos clases, barajar y devolver solo n_samples."""
    ## Cargar datos de http://openml.org/d/554
    mnist = fetch_openml("mnist_784", version=1, as_frame=False, parser="pandas")

    ## tomar solo dos clases para la clasificación binaria
    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)

Definir el estimador y la estrategia de parada temprana

El siguiente paso es definir el estimador y la estrategia de parada temprana. Utilizaremos el modelo SGDClassifier de scikit-learn. Definiremos tres criterios de parada diferentes: sin criterio de parada, pérdida de entrenamiento y puntuación de validación. Usaremos la función fit_and_score para ajustar el estimador en el conjunto de entrenamiento y evaluarlo en ambos conjuntos.

@ignore_warnings(category=ConvergenceWarning)
def fit_and_score(estimator, max_iter, X_train, X_test, y_train, y_test):
    """Ajustar el estimador en el conjunto de entrenamiento y evaluarlo en ambos conjuntos"""
    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

## Definir el estimador para comparar
estimator_dict = {
    "Sin criterio de parada": linear_model.SGDClassifier(n_iter_no_change=3),
    "Pérdida de entrenamiento": linear_model.SGDClassifier(
        early_stopping=False, n_iter_no_change=3, tol=0.1
    ),
    "Puntuación de validación": linear_model.SGDClassifier(
        early_stopping=True, n_iter_no_change=3, tol=0.0001, validation_fraction=0.2
    ),
}

Entrenar y evaluar el estimador

El siguiente paso es entrenar y evaluar el estimador utilizando cada criterio de parada. Utilizaremos un bucle para iterar sobre cada estimador y criterio de parada, y utilizaremos otro bucle para iterar sobre diferentes iteraciones máximas. Luego almacenaremos los resultados en un dataframe de pandas para una representación gráfica fácil.

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

## Transformar los resultados en un dataframe de pandas para una representación gráfica fácil
columns = [
    "Criterio de parada",
    "max_iter",
    "Tiempo de ajuste (seg)",
    "n_iter_",
    "Puntuación de entrenamiento",
    "Puntuación de prueba",
]
results_df = pd.DataFrame(results, columns=columns)

Representar los resultados

El último paso es representar los resultados. Utilizaremos dos subgráficos para representar las puntuaciones de entrenamiento y prueba, y el número de iteraciones y el tiempo de ajuste. Utilizaremos diferentes estilos de línea para cada estimador y criterio de parada.

## Definir lo que se va a representar
lines = "Criterio de parada"
x_axis = "max_iter"
styles = ["-.", "--", "-"]

## Primera representación: puntuaciones de entrenamiento y prueba
fig, axes = plt.subplots(nrows=1, ncols=2, sharey=True, figsize=(12, 4))
for ax, y_axis in zip(axes, ["Puntuación de entrenamiento", "Puntuación de prueba"]):
    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()

## Segunda representación: n_iter y tiempo de ajuste
fig, axes = plt.subplots(nrows=1, ncols=2, figsize=(12, 4))
for ax, y_axis in zip(axes, ["n_iter_", "Tiempo de ajuste (seg)"]):
    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()

Resumen

En este laboratorio, exploramos la estrategia de parada temprana para monitorear la convergencia en una puntuación de validación al utilizar el Descenso de Gradiente Estocástico para minimizar una función de pérdida. Utilizamos el modelo SGDClassifier de scikit-learn y el conjunto de datos MNIST para ilustrar cómo la parada temprana se puede utilizar para alcanzar una precisión casi igual a la de un modelo construido sin parada temprana, y reducir significativamente el tiempo de entrenamiento. Definimos tres criterios de parada diferentes: sin criterio de parada, pérdida de entrenamiento y puntuación de validación, y utilizamos un bucle para entrenar y evaluar el estimador utilizando cada criterio de parada. Luego representamos los resultados utilizando diferentes estilos de línea para cada estimador y criterio de parada.