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.

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

Здесь мы выбираем 5000 образцов для обучения и 10000 для тестирования. Чтобы действительно воспроизвести результаты в оригинальной статье о 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.55%
Linear SVM score on 500 PolynomialCountSketch features: 76.92%
Linear SVM score on 1000 PolynomialCountSketch features: 77.79%
Linear SVM score on 2000 PolynomialCountSketch features: 78.59%

Установление модели 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] Pham, Ninh и Rasmus Pagh. «Быстрые и масштабируемые полиномиальные ядра с помощью явных отображений признаков». KDD ‘13 (2013). https://doi.org/10.1145/2487575.2487591

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

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

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 в наборе данных iris

Основные моменты выпуска scikit-learn 0.24

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

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

Spec-Zone.ru

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