Scikit-Learn MLPClassifier: Стратегии стохастического обучения

Beginner

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

Введение

В этом практическом занятии (лабораторной работе) вы научитесь использовать класс MLPClassifier из библиотеки Scikit-learn для сравнения эффективности различных стохастических методов обучения, таких как SGD и Adam. MLPClassifier представляет собой нейронную сеть-классификатор, которая использует метод обратного распространения ошибки (backpropagation) для оптимизации весов сети. Цель этого практического занятия - показать, как различные стохастические методы обучения могут влиять на кривые потерь при обучении MLPClassifier. В этом примере мы будем использовать несколько небольших наборов данных, хотя наблюдаемая в этих примерах общая тенденция, по-видимому, сохраняется и для более крупных наборов данных.

Советы по работе с виртуальной машиной (VM)

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

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

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

Импорт необходимых библиотек

Сначала нам нужно импортировать необходимые библиотеки, в том числе MLPClassifier, MinMaxScaler, datasets и matplotlib.pyplot. Мы также импортируем ConvergenceWarning, чтобы игнорировать предупреждения о неконвергенции во время обучения.

import warnings

import matplotlib.pyplot as plt

from sklearn.neural_network import MLPClassifier
from sklearn.preprocessing import MinMaxScaler
from sklearn import datasets
from sklearn.exceptions import ConvergenceWarning

Определение различных стратегий обучения

Далее нам нужно определить различные стратегии обучения, которые мы хотим сравнить. Мы определим несколько различных графиков изменения скорости обучения (learning rate schedules) и параметров момента (momentum), включая постоянную скорость обучения, постоянную скорость обучения с моментом, постоянную скорость обучения с моментом Нестерова (Nesterov's momentum), обратно-пропорциональную скорость обучения (inv-scaling learning-rate), обратно-пропорциональную скорость обучения с моментом, обратно-пропорциональную скорость обучения с моментом Нестерова и метод Адама (adam). Мы также определим метки (labels) и аргументы для построения графиков (plot_args), которые будем использовать при построении графиков позже.

## different learning rate schedules and momentum parameters
params = [
    {
        "solver": "sgd",
        "learning_rate": "constant",
        "momentum": 0,
        "learning_rate_init": 0.2,
    },
    {
        "solver": "sgd",
        "learning_rate": "constant",
        "momentum": 0.9,
        "nesterovs_momentum": False,
        "learning_rate_init": 0.2,
    },
    {
        "solver": "sgd",
        "learning_rate": "constant",
        "momentum": 0.9,
        "nesterovs_momentum": True,
        "learning_rate_init": 0.2,
    },
    {
        "solver": "sgd",
        "learning_rate": "invscaling",
        "momentum": 0,
        "learning_rate_init": 0.2,
    },
    {
        "solver": "sgd",
        "learning_rate": "invscaling",
        "momentum": 0.9,
        "nesterovs_momentum": True,
        "learning_rate_init": 0.2,
    },
    {
        "solver": "sgd",
        "learning_rate": "invscaling",
        "momentum": 0.9,
        "nesterovs_momentum": False,
        "learning_rate_init": 0.2,
    },
    {"solver": "adam", "learning_rate_init": 0.01},
]

labels = [
    "constant learning-rate",
    "constant with momentum",
    "constant with Nesterov's momentum",
    "inv-scaling learning-rate",
    "inv-scaling with momentum",
    "inv-scaling with Nesterov's momentum",
    "adam",
]

plot_args = [
    {"c": "red", "linestyle": "-"},
    {"c": "green", "linestyle": "-"},
    {"c": "blue", "linestyle": "-"},
    {"c": "red", "linestyle": "--"},
    {"c": "green", "linestyle": "--"},
    {"c": "blue", "linestyle": "--"},
    {"c": "black", "linestyle": "-"},
]

Определение функции для построения кривых обучения

Далее нам нужно определить функцию, которая будет строить кривые обучения для каждой стратегии обучения на каждом наборе данных. Функция принимает набор данных (X, y), ось для построения графика и название набора данных. Мы будем использовать MinMaxScaler для масштабирования данных и MLPClassifier для обучения нейронной сети. Мы обучим сеть с использованием каждой стратегии обучения, игнорируя предупреждения о неконвергенции, и построим кривые обучения для каждой стратегии на одном графике.

def plot_on_dataset(X, y, ax, name):
    ## for each dataset, plot learning for each learning strategy
    print("\nlearning on dataset %s" % name)
    ax.set_title(name)

    X = MinMaxScaler().fit_transform(X)
    mlps = []
    if name == "digits":
        ## digits is larger but converges fairly quickly
        max_iter = 15
    else:
        max_iter = 400

    for label, param in zip(labels, params):
        print("training: %s" % label)
        mlp = MLPClassifier(random_state=0, max_iter=max_iter, **param)

        ## some parameter combinations will not converge as can be seen on the
        ## plots so they are ignored here
        with warnings.catch_warnings():
            warnings.filterwarnings(
                "ignore", category=ConvergenceWarning, module="sklearn"
            )
            mlp.fit(X, y)

        mlps.append(mlp)
        print("Training set score: %f" % mlp.score(X, y))
        print("Training set loss: %f" % mlp.loss_)
    for mlp, label, args in zip(mlps, labels, plot_args):
        ax.plot(mlp.loss_curve_, label=label, **args)

Загрузка или генерация небольших наборов данных

Теперь нам нужно загрузить или сгенерировать небольшие наборы данных, которые мы будем использовать в этом примере. Мы будем использовать набор данных ирисов (iris dataset), набор данных с рукописными цифрами (digits dataset) и два набора данных, сгенерированных с использованием функций make_circles и make_moons.

iris = datasets.load_iris()
X_digits, y_digits = datasets.load_digits(return_X_y=True)
data_sets = [
    (iris.data, iris.target),
    (X_digits, y_digits),
    datasets.make_circles(noise=0.2, factor=0.5, random_state=1),
    datasets.make_moons(noise=0.3, random_state=0),
]

Построение кривых обучения для каждого набора данных

Наконец, мы можем построить кривые обучения для каждого набора данных, используя функцию plot_on_dataset. Мы создадим сетку графиков размером 2x2 и построим каждый набор данных на отдельной оси.

fig, axes = plt.subplots(2, 2, figsize=(15, 10))

for ax, data, name in zip(
    axes.ravel(), data_sets, ["iris", "digits", "circles", "moons"]
):
    plot_on_dataset(*data, ax=ax, name=name)

fig.legend(ax.get_lines(), labels, ncol=3, loc="upper center")
plt.show()

Резюме

В этом практическом занятии (lab) мы использовали MLPClassifier из библиотеки Scikit-learn для сравнения эффективности различных стохастических стратегий обучения, включая стохастический градиентный спуск (SGD) и метод Адама (Adam), на нескольких небольших наборах данных. Мы определили различные графики изменения скорости обучения (learning rate schedules) и параметры момента (momentum), а затем обучили MLPClassifier с использованием каждой стратегии. Мы построили кривые обучения для каждой стратегии на каждом наборе данных и посмотрели, как различные стратегии могут повлиять на кривые потерь при обучении. Мы продемонстрировали важность выбора правильной стратегии обучения для данного набора данных и задачи.