Дискретизация признаков для классификации

Machine LearningMachine LearningBeginner
Практиковаться сейчас

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

💡 Этот учебник переведен с английского с помощью ИИ. Чтобы просмотреть оригинал, вы можете перейти на английский оригинал

Введение

В машинном обучении дискретизация признаков - это метод уменьшения количества непрерывных переменных в наборе данных путем создания ящиков или интервалов для их представления. Этот метод может быть полезен в случаях, когда количество непрерывных переменных велико, и алгоритм требует упрощения для более легкого анализа. В этом лабе мы покажем дискретизацию признаков на синтетических наборах данных для классификации.

Советы по работе с ВМ

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

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

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

Импорт библиотек

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

import numpy as np
import matplotlib.pyplot as plt
from matplotlib.colors import ListedColormap
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
from sklearn.datasets import make_moons, make_circles, make_classification
from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import GridSearchCV
from sklearn.pipeline import make_pipeline
from sklearn.preprocessing import KBinsDiscretizer
from sklearn.svm import SVC, LinearSVC
from sklearn.ensemble import GradientBoostingClassifier
from sklearn.utils._testing import ignore_warnings
from sklearn.exceptions import ConvergenceWarning

Подготовка данных

В этом шаге мы подготовим синтетические наборы данных для классификации для дискретизации признаков. Мы будем использовать библиотеку scikit - learn для генерации трех разных наборов данных: moons,同心圆 (concentric circles) и линейно разделимые данные.

h = 0.02  ## step size in the mesh

n_samples = 100
datasets = [
    make_moons(n_samples=n_samples, noise=0.2, random_state=0),
    make_circles(n_samples=n_samples, noise=0.2, factor=0.5, random_state=1),
    make_classification(
        n_samples=n_samples,
        n_features=2,
        n_redundant=0,
        n_informative=2,
        random_state=2,
        n_clusters_per_class=1,
    ),
]

Определение классификаторов и параметров

В этом шаге мы определим классификаторы и параметры, которые будут использоваться в процессе дискретизации признаков. Мы создадим список классификаторов, который включает логистическую регрессию, линейный классификатор на основе векторных машин (SVM), градиентный бустинг и SVM с ядром радиальной базисной функции. Также мы определим набор параметров для каждого классификатора, которые будут использоваться в алгоритме GridSearchCV.

## list of (estimator, param_grid), where param_grid is used in GridSearchCV
## The parameter spaces in this example are limited to a narrow band to reduce
## its runtime. In a real use case, a broader search space for the algorithms
## should be used.
classifiers = [
    (
        make_pipeline(StandardScaler(), LogisticRegression(random_state=0)),
        {"logisticregression__C": np.logspace(-1, 1, 3)},
    ),
    (
        make_pipeline(StandardScaler(), LinearSVC(random_state=0, dual="auto")),
        {"linearsvc__C": np.logspace(-1, 1, 3)},
    ),
    (
        make_pipeline(
            StandardScaler(),
            KBinsDiscretizer(encode="onehot"),
            LogisticRegression(random_state=0),
        ),
        {
            "kbinsdiscretizer__n_bins": np.arange(5, 8),
            "logisticregression__C": np.logspace(-1, 1, 3),
        },
    ),
    (
        make_pipeline(
            StandardScaler(),
            KBinsDiscretizer(encode="onehot"),
            LinearSVC(random_state=0, dual="auto"),
        ),
        {
            "kbinsdiscretizer__n_bins": np.arange(5, 8),
            "linearsvc__C": np.logspace(-1, 1, 3),
        },
    ),
    (
        make_pipeline(
            StandardScaler(), GradientBoostingClassifier(n_estimators=5, random_state=0)
        ),
        {"gradientboostingclassifier__learning_rate": np.logspace(-2, 0, 5)},
    ),
    (
        make_pipeline(StandardScaler(), SVC(random_state=0)),
        {"svc__C": np.logspace(-1, 1, 3)},
    ),
]

names = [get_name(e).replace("StandardScaler + ", "") for e, _ in classifiers]

Визуализация данных

В этом шаге мы визуализируем синтетические наборы данных для классификации перед дискретизацией признаков. Мы построим точки обучения и тестирования для каждого набора данных.

fig, axes = plt.subplots(
    nrows=len(datasets), ncols=len(classifiers) + 1, figsize=(21, 9)
)

cm_piyg = plt.cm.PiYG
cm_bright = ListedColormap(["#b30065", "#178000"])

## iterate over datasets
for ds_cnt, (X, y) in enumerate(datasets):
    print(f"\ndataset {ds_cnt}\n---------")

    ## split into training and test part
    X_train, X_test, y_train, y_test = train_test_split(
        X, y, test_size=0.5, random_state=42
    )

    ## create the grid for background colors
    x_min, x_max = X[:, 0].min() - 0.5, X[:, 0].max() + 0.5
    y_min, y_max = X[:, 1].min() - 0.5, X[:, 1].max() + 0.5
    xx, yy = np.meshgrid(np.arange(x_min, x_max, h), np.arange(y_min, y_max, h))

    ## plot the dataset first
    ax = axes[ds_cnt, 0]
    if ds_cnt == 0:
        ax.set_title("Input data")
    ## plot the training points
    ax.scatter(X_train[:, 0], X_train[:, 1], c=y_train, cmap=cm_bright, edgecolors="k")
    ## and testing points
    ax.scatter(
        X_test[:, 0], X_test[:, 1], c=y_test, cmap=cm_bright, alpha=0.6, edgecolors="k"
    )
    ax.set_xlim(xx.min(), xx.max())
    ax.set_ylim(yy.min(), yy.max())
    ax.set_xticks(())
    ax.set_yticks(())

Реализация дискретизации признаков

В этом шаге мы реализуем дискретизацию признаков на наборах данных с использованием класса KBinsDiscretizer из scikit - learn. Это дискретизирует признаки, создавая набор ящиков (bins), а затем кодирует дискретные значения методом one - hot. Затем мы подгоняем данные под линейный классификатор и оцениваем производительность.

## iterate over classifiers
for est_idx, (name, (estimator, param_grid)) in enumerate(zip(names, classifiers)):
    ax = axes[ds_cnt, est_idx + 1]

    clf = GridSearchCV(estimator=estimator, param_grid=param_grid)
    with ignore_warnings(category=ConvergenceWarning):
        clf.fit(X_train, y_train)
    score = clf.score(X_test, y_test)
    print(f"{name}: {score:.2f}")

    ## plot the decision boundary. For that, we will assign a color to each
    ## point in the mesh [x_min, x_max]*[y_min, y_max].
    if hasattr(clf, "decision_function"):
        Z = clf.decision_function(np.column_stack([xx.ravel(), yy.ravel()]))
    else:
        Z = clf.predict_proba(np.column_stack([xx.ravel(), yy.ravel()]))[:, 1]

    ## put the result into a color plot
    Z = Z.reshape(xx.shape)
    ax.contourf(xx, yy, Z, cmap=cm_piyg, alpha=0.8)

    ## plot the training points
    ax.scatter(
        X_train[:, 0], X_train[:, 1], c=y_train, cmap=cm_bright, edgecolors="k"
    )
    ## and testing points
    ax.scatter(
        X_test[:, 0],
        X_test[:, 1],
        c=y_test,
        cmap=cm_bright,
        edgecolors="k",
        alpha=0.6,
    )
    ax.set_xlim(xx.min(), xx.max())
    ax.set_ylim(yy.min(), yy.max())
    ax.set_xticks(())
    ax.set_yticks(())

    if ds_cnt == 0:
        ax.set_title(name.replace(" + ", "\n"))
    ax.text(
        0.95,
        0.06,
        (f"{score:.2f}").lstrip("0"),
        size=15,
        bbox=dict(boxstyle="round", alpha=0.8, facecolor="white"),
        transform=ax.transAxes,
        horizontalalignment="right",
    )

Визуализация результатов

В этом шаге мы визуализируем результаты процесса дискретизации признаков. Мы построим точность классификации на наборе тестовых данных для каждого классификатора и набора данных.

plt.tight_layout()

## Add suptitles above the figure
plt.subplots_adjust(top=0.90)
suptitles = [
    "Линейные классификаторы",
    "Дискретизация признаков и линейные классификаторы",
    "Нелинейные классификаторы",
]
for i, suptitle in zip([1, 3, 5], suptitles):
    ax = axes[0, i]
    ax.text(
        1.05,
        1.25,
        suptitle,
        transform=ax.transAxes,
        horizontalalignment="центр",
        size="x-large",
    )
plt.show()

Обзор

В этом практическом занятии мы продемонстрировали дискретизацию признаков на синтетических наборах данных для классификации с использованием scikit - learn. Мы подготовили данные, определили классификаторы и параметры, реализовали дискретизацию признаков и визуализировали результаты. Эта техника предварительной обработки может быть полезна для уменьшения сложности набора данных и улучшения производительности линейных классификаторов. Однако ее следует использовать с осторожностью и в сочетании с другими методами, чтобы избежать переобучения.