Построение сеточного поиска для цифр

Beginner

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

Введение

В этом практическом занятии показано, как выполнять настройку гиперпараметров с использованием кросс-валидации с помощью библиотеки scikit-learn. Цель - классифицировать изображения рукописных цифр с использованием бинарной классификации для более простого понимания: определение, является ли цифра 8 или нет. В качестве датасета используется digits dataset. Затем производится измерение производительности выбранных гиперпараметров и обученной модели на специальном наборе для оценки, который не использовался на этапе выбора модели.

Советы по использованию ВМ

После запуска ВМ нажмите в левом верхнем углу, чтобы переключиться на вкладку Notebook и получить доступ к Jupyter Notebook для практики.

Иногда вам может потребоваться подождать несколько секунд, пока Jupyter Notebook не загрузится полностью. Валидация операций не может быть автоматизирована из-за ограничений Jupyter Notebook.

Если вы сталкиваетесь с проблемами во время обучения, не стесняйтесь обращаться к Labby. Оставьте отзыв после занятия, и мы оперативно решим проблему для вас.

Загрузка данных

Мы загрузим датасет digits и сгладим изображения до векторов. Каждый пиксель изображения размером 8 на 8 пикселей должен быть преобразован в вектор из 64 пикселей. Таким образом, мы получим окончательный массив данных формы (n_images, n_pixels). Также мы разделим данные на обучающий и тестовый наборы равного размера.

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)

Мы определим функцию, которую будем передавать в параметр refit экземпляра GridSearchCV. Она будет реализовывать пользовательскую стратегию для выбора наилучшего кандидата из атрибута cv_results_ экземпляра GridSearchCV. Как только кандидат выбран, он автоматически переобучается экземпляром GridSearchCV.

Здесь стратегия заключается в том, чтобы сократить список моделей, которые являются наилучшими по точности и полноте. Из выбранных моделей мы в конечном итоге выбираем самую быструю модель при предсказании. Обратите внимание, что эти пользовательские выборы совершенно произвольны.

import pandas as pd
from sklearn.metrics import classification_report

def print_dataframe(filtered_cv_results):
    """Pretty print for filtered dataframe"""
    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"precision: {mean_precision:0.3f} (±{std_precision:0.03f}),"
            f" recall: {mean_recall:0.3f} (±{std_recall:0.03f}),"
            f" for {params}"
        )
    print()


def refit_strategy(cv_results):
    """Define the strategy to select the best estimator.

    The strategy defined here is to filter-out all results below a precision threshold
    of 0.98, rank the remaining by recall and keep all models with one standard
    deviation of the best by recall. Once these models are selected, we can select the
    fastest model to predict.

    Parameters
    ----------
    cv_results : dict of numpy (masked) ndarrays
        CV results as returned by the `GridSearchCV`.

    Returns
    -------
    best_index : int
        The index of the best estimator as it appears in `cv_results`.
    """
    ## print the info about the grid-search for the different scores
    precision_threshold = 0.98

    cv_results_ = pd.DataFrame(cv_results)
    print("All grid-search results:")
    print_dataframe(cv_results_)

    ## Filter-out all results below the threshold
    high_precision_cv_results = cv_results_[
        cv_results_["mean_test_precision"] > precision_threshold
    ]

    print(f"Models with a precision higher than {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",
        ]
    ]

    ## Select the most performant models in terms of recall
    ## (within 1 sigma from the best)
    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(
        "Out of the previously selected high precision models, we keep all the\n"
        "the models within one standard deviation of the highest recall model:"
    )
    print_dataframe(high_recall_cv_results)

    ## From the best candidates, select the fastest model to predict
    fastest_top_recall_high_precision_index = high_recall_cv_results[
        "mean_score_time"
    ].idxmin()

    print(
        "\nThe selected final model is the fastest to predict out of the previously\n"
        "selected subset of best models based on precision and recall.\n"
        "Its scoring time is:\n\n"
        f"{high_recall_cv_results.loc[fastest_top_recall_high_precision_index]}"
    )

    return fastest_top_recall_high_precision_index

Определение гиперпараметров

Мы определим гиперпараметры и создадим экземпляр 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
)

Обучение модели и предсказание

Мы обучим модель и сделаем предсказания на наборе для оценки.

grid_search.fit(X_train, y_train)

## The parameters selected by the grid-search with our custom strategy are:
grid_search.best_params_

## Finally, we evaluate the fine-tuned model on the left-out evaluation set: the
## `grid_search` object **has automatically been refit** on the full training
## set with the parameters selected by our custom refit strategy.
y_pred = grid_search.predict(X_test)
print(classification_report(y_test, y_pred))

Резюме

В этом практическом занятии мы научились настраивать гиперпараметры с использованием кросс-валидации с помощью библиотеки scikit-learn. Мы использовали датасет digits и определили пользовательскую стратегию переобучения, чтобы выбрать наилучшего кандидата из атрибута cv_results_ экземпляра GridSearchCV. Наконец, мы оценили настройленную модель на оставленном на тестирование наборе данных.