Tracer la recherche sur grille des chiffres

Beginner

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

Introduction

Ce laboratoire montre comment effectuer un réglage d'hyperparamètres avec validation croisée à l'aide de la bibliothèque scikit-learn. L'objectif est de classifier des images de chiffres manuscrits en utilisant une classification binaire pour faciliter la compréhension : identifier si un chiffre est un 8 ou non. L'ensemble de données utilisé est l'ensemble de données digits. Les performances des hyperparamètres sélectionnés et du modèle entraîné sont ensuite mesurées sur un ensemble d'évaluation dédié qui n'a pas été utilisé lors de l'étape de sélection du modèle.

Conseils sur la machine virtuelle

Une fois le démarrage de la machine virtuelle 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 limitations 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.

Charger les données

Nous allons charger l'ensemble de données digits et aplatir les images en vecteurs. Chaque image de 8 pixels sur 8 doit être transformée en un vecteur de 64 pixels. Ainsi, nous obtiendrons un tableau de données final de forme (n_images, n_pixels). Nous allons également diviser les données en un ensemble d'entraînement et un ensemble de test de taille égale.

from sklearn import datasets
from sklearn.model_selection import train_test_split

digits = datasets.load_digits()

n_samples = len(digits.images)
X = digits.images.reshape((n_samples, -1))
y = digits.target == 8

X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.5, random_state=0)

Définir une stratégie de recherche sur grille

Nous allons définir une fonction à passer au paramètre refit de l'instance GridSearchCV. Elle implémentera la stratégie personnalisée pour sélectionner le meilleur candidat à partir de l'attribut cv_results_ de GridSearchCV. Une fois le candidat sélectionné, il est automatiquement réajusté par l'instance GridSearchCV.

Ici, la stratégie est de sélectionner les modèles qui sont les meilleurs en termes de précision et de rappel. Parmi les modèles sélectionnés, nous sélectionnons finalement le modèle le plus rapide à prédire. Remarquez que ces choix personnalisés sont entièrement arbitraires.

import pandas as pd
from sklearn.metrics import classification_report

def print_dataframe(filtered_cv_results):
    """Affiche joliment un DataFrame filtré"""
    for mean_precision, std_precision, mean_recall, std_recall, params in zip(
        filtered_cv_results["mean_test_precision"],
        filtered_cv_results["std_test_precision"],
        filtered_cv_results["mean_test_recall"],
        filtered_cv_results["std_test_recall"],
        filtered_cv_results["params"],
    ):
        print(
            f"précision: {mean_precision:0.3f} (±{std_precision:0.03f}),"
            f" rappel: {mean_recall:0.3f} (±{std_recall:0.03f}),"
            f" pour {params}"
        )
    print()


def refit_strategy(cv_results):
    """Définit la stratégie pour sélectionner le meilleur estimateur.

    La stratégie définie ici est de filtrer tous les résultats inférieurs à un seuil de précision
    de 0,98, de classer les résultats restants par rappel et de conserver tous les modèles
    avec une écart-type de l'ordre du meilleur modèle en termes de rappel. Une fois ces modèles
    sélectionnés, nous pouvons sélectionner le modèle le plus rapide à prédire.

    Paramètres
    ----------
    cv_results : dict de tableaux ndarray (masqués) de numpy
        Résultats de la validation croisée renvoyés par `GridSearchCV`.

    Retours
    -------
    best_index : int
        L'index du meilleur estimateur tel qu'il apparaît dans `cv_results`.
    """
    ## Affiche les informations sur la recherche sur grille pour les différents scores
    precision_threshold = 0,98

    cv_results_ = pd.DataFrame(cv_results)
    print("Tous les résultats de la recherche sur grille :")
    print_dataframe(cv_results_)

    ## Filtre tous les résultats inférieurs au seuil
    high_precision_cv_results = cv_results_[
        cv_results_["mean_test_precision"] > precision_threshold
    ]

    print(f"Modèles avec une précision supérieure à {precision_threshold} :")
    print_dataframe(high_precision_cv_results)

    high_precision_cv_results = high_precision_cv_results[
        [
            "mean_score_time",
            "mean_test_recall",
            "std_test_recall",
            "mean_test_precision",
            "std_test_precision",
            "rank_test_recall",
            "rank_test_precision",
            "params",
        ]
    ]

    ## Sélectionne les modèles les plus performants en termes de rappel
    ## (à l'intérieur d'un écart-type du meilleur)
    best_recall_std = high_precision_cv_results["mean_test_recall"].std()
    best_recall = high_precision_cv_results["mean_test_recall"].max()
    best_recall_threshold = best_recall - best_recall_std

    high_recall_cv_results = high_precision_cv_results[
        high_precision_cv_results["mean_test_recall"] > best_recall_threshold
    ]
    print(
        "Parmi les modèles à haute précision précédemment sélectionnés, nous conservons tous les\n"
        "modèles à l'intérieur d'un écart-type du modèle à rappel le plus élevé : "
    )
    print_dataframe(high_recall_cv_results)

    ## Parmi les meilleurs candidats, sélectionne le modèle le plus rapide à prédire
    fastest_top_recall_high_precision_index = high_recall_cv_results[
        "mean_score_time"
    ].idxmin()

    print(
        "\nLe modèle final sélectionné est le plus rapide à prédire parmi les précédemment\n"
        "sélectionnés dans le sous-ensemble de meilleurs modèles basé sur la précision et le rappel.\n"
        "Son temps de scoring est :\n\n"
        f"{high_recall_cv_results.loc[fastest_top_recall_high_precision_index]}"
    )

    return fastest_top_recall_high_precision_index

Définir les hyperparamètres

Nous allons définir les hyperparamètres et créer l'instance GridSearchCV.

from sklearn.model_selection import GridSearchCV
from sklearn.svm import SVC

tuned_parameters = [
    {"kernel": ["rbf"], "gamma": [1e-3, 1e-4], "C": [1, 10, 100, 1000]},
    {"kernel": ["linear"], "C": [1, 10, 100, 1000]},
]

grid_search = GridSearchCV(
    SVC(), tuned_parameters, scoring=["precision", "recall"], refit=refit_strategy
)

Ajuster le modèle et effectuer des prédictions

Nous allons ajuster le modèle et effectuer des prédictions sur l'ensemble d'évaluation.

grid_search.fit(X_train, y_train)

## Les paramètres sélectionnés par la recherche sur grille avec notre stratégie personnalisée sont :
grid_search.best_params_

## Enfin, nous évaluons le modèle affiné sur l'ensemble d'évaluation non utilisé : l'objet
## `grid_search` **a été automatiquement réajusté** sur l'ensemble d'entraînement
## complet avec les paramètres sélectionnés par notre stratégie de réajustement personnalisée.
y_pred = grid_search.predict(X_test)
print(classification_report(y_test, y_pred))

Sommaire

Dans ce laboratoire, nous avons appris à effectuer un réglage d'hyperparamètres avec validation croisée à l'aide de la bibliothèque scikit - learn. Nous avons utilisé l'ensemble de données digits et défini une stratégie de réajustement personnalisée pour sélectionner le meilleur candidat à partir de l'attribut cv_results_ de l'instance GridSearchCV. Enfin, nous avons évalué le modèle affiné sur l'ensemble d'évaluation non utilisé.