Spec-Zone.ru › scikit-learn

Примечание

Перейти в конец, чтобы скачать полный код примера или запустить этот пример в браузере через JupyterLite или Binder.

Масштабируемое обучение с аппроксимацией полиномиального ядра

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

Мы используем набор данных Covtype [2], пытаясь воспроизвести эксперименты из оригинальной статьи о Tensor Sketch [1], то есть алгоритм, реализованный в PolynomialCountSketch.

Сначала мы вычисляем точность линейного классификатора на исходных признаках. Затем обучаем линейные классификаторы на разном количестве признаков (n_components), сгенерированных с помощью PolynomialCountSketch, и масштабируемым образом аппроксимируем точность классификатора с ядром.

# Authors: The scikit-learn developers
# SPDX-License-Identifier: BSD-3-Clause

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

Загрузим набор данных Covtype, который содержит 581 012 образцов с 54 признаками каждый, распределённых по 6 классам. Цель этого набора данных — предсказать тип лесного покрова только по картографическим переменным (без данных дистанционного зондирования). После загрузки мы преобразуем его в задачу бинарной классификации, чтобы привести к виду набора данных на веб-странице LIBSVM [2], который использовался в работе [1].

from sklearn.datasets import fetch_covtype

X, y = fetch_covtype(return_X_y=True)

y[y != 2] = 0
y[y == 2] = 1  # We will try to separate class 2 from the other 6 classes.

Разбиение данных

Здесь мы выбираем 5 000 образцов для обучения и 10 000 для тестирования. Чтобы в точности воспроизвести результаты оригинальной статьи о Tensor Sketch, выберите 100 000 образцов для обучения.

from sklearn.model_selection import train_test_split

X_train, X_test, y_train, y_test = train_test_split(
    X, y, train_size=5_000, test_size=10_000, random_state=42
)

Нормализация признаков

Теперь масштабируем признаки в диапазон [0, 1], чтобы привести их к формату набора данных на веб-странице LIBSVM, а затем нормализуем до единичной длины, как это сделано в оригинальной статье о Tensor Sketch [1].

from sklearn.pipeline import make_pipeline
from sklearn.preprocessing import MinMaxScaler, Normalizer

mm = make_pipeline(MinMaxScaler(), Normalizer())
X_train = mm.fit_transform(X_train)
X_test = mm.transform(X_test)

Создание базовой модели

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

import time

from sklearn.svm import LinearSVC

results = {}

lsvm = LinearSVC()
start = time.time()
lsvm.fit(X_train, y_train)
lsvm_time = time.time() - start
lsvm_score = 100 * lsvm.score(X_test, y_test)

results["LSVM"] = {"time": lsvm_time, "score": lsvm_score}
print(f"Linear SVM score on raw features: {lsvm_score:.2f}%")
Linear SVM score on raw features: 75.62%

Создание модели с аппроксимацией ядра

Затем мы обучаем линейные SVM на признаках, сгенерированных с помощью PolynomialCountSketch при разных значениях n_components, демонстрируя, что такие аппроксимации признакового представления ядра повышают точность линейной классификации. В типичных прикладных сценариях n_components должно быть больше числа признаков во входном представлении, чтобы добиться улучшения по сравнению с линейной классификацией. Как правило, оптимальное соотношение оценки качества и затрат времени выполнения обычно достигается при n_components = 10 * n_features, хотя это может зависеть от конкретного набора данных. Обратите внимание: поскольку исходные образцы содержат 54 признака, явное отображение признаков полиномиального ядра четвёртой степени содержало бы приблизительно 8,5 миллиона признаков (точнее, 54^4). Благодаря PolynomialCountSketch мы можем сжать большую часть дискриминативной информации этого пространства признаков в гораздо более компактное представление. В этом примере мы проводим эксперимент всего один раз (n_runs = 1), однако на практике следует повторить эксперимент несколько раз, чтобы компенсировать стохастический характер PolynomialCountSketch.

from sklearn.kernel_approximation import PolynomialCountSketch

n_runs = 1
N_COMPONENTS = [250, 500, 1000, 2000]

for n_components in N_COMPONENTS:
    ps_lsvm_time = 0
    ps_lsvm_score = 0
    for _ in range(n_runs):
        pipeline = make_pipeline(
            PolynomialCountSketch(n_components=n_components, degree=4),
            LinearSVC(),
        )

        start = time.time()
        pipeline.fit(X_train, y_train)
        ps_lsvm_time += time.time() - start
        ps_lsvm_score += 100 * pipeline.score(X_test, y_test)

    ps_lsvm_time /= n_runs
    ps_lsvm_score /= n_runs

    results[f"LSVM + PS({n_components})"] = {
        "time": ps_lsvm_time,
        "score": ps_lsvm_score,
    }
    print(
        f"Linear SVM score on {n_components} PolynomialCountSketch "
        f"features: {ps_lsvm_score:.2f}%"
    )
Linear SVM score on 250 PolynomialCountSketch features: 76.22%
Linear SVM score on 500 PolynomialCountSketch features: 77.60%
Linear SVM score on 1000 PolynomialCountSketch features: 77.75%
Linear SVM score on 2000 PolynomialCountSketch features: 78.26%

Создание модели SVM с ядром

Обучим SVM с ядром, чтобы оценить, насколько хорошо PolynomialCountSketch аппроксимирует эффективность ядра. Разумеется, это может занять некоторое время, поскольку класс SVC обладает относительно низкой масштабируемостью. Именно поэтому аппроксиматоры ядер так полезны:

from sklearn.svm import SVC

ksvm = SVC(C=500.0, kernel="poly", degree=4, coef0=0, gamma=1.0)

start = time.time()
ksvm.fit(X_train, y_train)
ksvm_time = time.time() - start
ksvm_score = 100 * ksvm.score(X_test, y_test)

results["KSVM"] = {"time": ksvm_time, "score": ksvm_score}
print(f"Kernel-SVM score on raw features: {ksvm_score:.2f}%")
Kernel-SVM score on raw features: 79.78%

Сравнение результатов

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

import matplotlib.pyplot as plt

fig, ax = plt.subplots(figsize=(7, 7))
ax.scatter(
    [
        results["LSVM"]["time"],
    ],
    [
        results["LSVM"]["score"],
    ],
    label="Linear SVM",
    c="green",
    marker="^",
)

ax.scatter(
    [
        results["LSVM + PS(250)"]["time"],
    ],
    [
        results["LSVM + PS(250)"]["score"],
    ],
    label="Linear SVM + PolynomialCountSketch",
    c="blue",
)

for n_components in N_COMPONENTS:
    ax.scatter(
        [
            results[f"LSVM + PS({n_components})"]["time"],
        ],
        [
            results[f"LSVM + PS({n_components})"]["score"],
        ],
        c="blue",
    )
    ax.annotate(
        f"n_comp.={n_components}",
        (
            results[f"LSVM + PS({n_components})"]["time"],
            results[f"LSVM + PS({n_components})"]["score"],
        ),
        xytext=(-30, 10),
        textcoords="offset pixels",
    )

ax.scatter(
    [
        results["KSVM"]["time"],
    ],
    [
        results["KSVM"]["score"],
    ],
    label="Kernel SVM",
    c="red",
    marker="x",
)

ax.set_xlabel("Training time (s)")
ax.set_ylabel("Accuracy (%)")
ax.legend()
plt.show()
plot scalable poly kernels

Литература

[1] (1,2,3)

Фам, Нинь и Расмус Паг. «Быстрые и масштабируемые полиномиальные ядра с помощью явных отображений признаков». KDD ‘13 (2013). https://doi.org/10.1145/2487575.2487591

[2] (1,2)

Репозиторий бинарных наборов данных LIBSVM https://www.csie.ntu.edu.tw/~cjlin/libsvmtools/datasets/binary.html

Общее время выполнения скрипта: (0 минут 20.253 секунды)

Launch binder
Launch JupyterLite

Download Jupyter notebook: plot_scalable_poly_kernels.ipynb

Download Python source code: plot_scalable_poly_kernels.py

Download zipped: plot_scalable_poly_kernels.zip

Связанные примеры

Аппроксимация явного отображения признаков для RBF-ядер

Построение графиков различных классификаторов SVM на наборе данных ирисов

Основные нововведения scikit-learn 0.24

SVM-Anova: SVM с одномерным отбором признаков

© 2007–2026 The scikit-learn developers
Licensed under the 3-clause BSD License.
https://scikit-learn.org/1.9/auto_examples/kernel_approximation/plot_scalable_poly_kernels.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API