Введение
В этом практическом занятии будет показано, как использовать приближение полиномиального ядра в scikit-learn для эффективного генерации приближений пространства признаков с полиномиальным ядром. Это используется для обучения линейных классификаторов, которые приближают точность классификаторов с ядром. Будем использовать датасет Covtype, который содержит 581 012 образцов по 54 признака каждому, распределенных по 6 классам. Цель этого датасета - предсказать тип лесного покрова только по картографическим переменным (без данных, полученных с помощью дистанционного зондирования). После загрузки мы преобразуем его в задачу бинарной классификации, чтобы соответствовать версии датасета на веб-странице LIBSVM, которая использовалась в оригинальной статье.
Советы по использованию ВМ
После запуска ВМ кликните в верхнем левом углу, чтобы переключиться на вкладку Notebook и получить доступ к Jupyter Notebook для практики.
Иногда вам может потребоваться подождать несколько секунд, пока Jupyter Notebook загрузится. Валидация операций не может быть автоматизирована из-за ограничений Jupyter Notebook.
Если вы сталкиваетесь с проблемами во время обучения, не стесняйтесь обращаться к Labby. Оставьте отзыв после занятия, и мы оперативно решим проблему для вас.
Загрузка и подготовка данных
Сначала мы загрузим датасет Covtype и преобразуем его в задачу бинарной классификации, выбрав только один класс. Затем мы разделим данные на обучающий и тестовый наборы и нормализуем признаки.
from sklearn.datasets import fetch_covtype
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import MinMaxScaler, Normalizer
## Загрузка датасета Covtype, выбор только одного класса
X, y = fetch_covtype(return_X_y=True)
y[y!= 2] = 0
y[y == 2] = 1
## Разделение данных на обучающий и тестовый наборы
X_train, X_test, y_train, y_test = train_test_split(
X, y, train_size=5000, test_size=10000, random_state=42
)
## Нормализация признаков
mm = make_pipeline(MinMaxScaler(), Normalizer())
X_train = mm.fit_transform(X_train)
X_test = mm.transform(X_test)
Создание базовой модели
Мы обучим линейный SVM на исходных признаках, чтобы создать базовую модель, и выведем ее точность.
from sklearn.svm import LinearSVC
## Обучаем линейный SVM на исходных признаках
lsvm = LinearSVC(dual="auto")
lsvm.fit(X_train, y_train)
lsvm_score = 100 * lsvm.score(X_test, y_test)
## Выводим точность базовой модели
print(f"Linear SVM score on raw features: {lsvm_score:.2f}%")
Создание модели приближения ядра
Теперь мы обучим линейные SVM на признаках, сгенерированных с использованием PolynomialCountSketch с разными значениями n_components. Мы будем использовать цикл для перебора различных значений n_components и выводить точность каждой модели.
from sklearn.kernel_approximation import PolynomialCountSketch
n_runs = 1
N_COMPONENTS = [250, 500, 1000, 2000]
for n_components in N_COMPONENTS:
ps_lsvm_score = 0
for _ in range(n_runs):
## Обучаем линейный SVM на признаках, сгенерированных с использованием PolynomialCountSketch
pipeline = make_pipeline(
PolynomialCountSketch(n_components=n_components, degree=4),
LinearSVC(dual="auto"),
)
pipeline.fit(X_train, y_train)
ps_lsvm_score += 100 * pipeline.score(X_test, y_test)
ps_lsvm_score /= n_runs
## Выводим точность модели
print(f"Linear SVM score on {n_components} PolynomialCountSketch features: {ps_lsvm_score:.2f}%")
Создание модели SVM с ядром
Мы обучим SVM с ядром, чтобы увидеть, насколько хорошо PolynomialCountSketch приближает производительность ядра.
from sklearn.svm import SVC
## Обучаем SVM с ядром
ksvm = SVC(C=500.0, kernel="poly", degree=4, coef0=0, gamma=1.0)
ksvm.fit(X_train, y_train)
ksvm_score = 100 * ksvm.score(X_test, y_test)
## Выводим точность SVM с ядром
print(f"Kernel-SVM score on raw features: {ksvm_score:.2f}%")
Сравнение результатов
Мы построим графики результатов различных методов в зависимости от их времени обучения, чтобы сравнить их производительность.
import matplotlib.pyplot as plt
## Построение графиков результатов различных методов
fig, ax = plt.subplots(figsize=(7, 7))
ax.scatter(
[
lsvm_time,
],
[
lsvm_score,
],
label="Linear SVM",
c="green",
marker="^",
)
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(
[
ksvm_time,
],
[
ksvm_score,
],
label="Kernel SVM",
c="red",
marker="x",
)
ax.set_xlabel("Training time (s)")
ax.set_ylabel("Accuracy (%)")
ax.legend()
plt.show()
Резюме
В этом практическом занятии показано, как использовать приближение полиномиального ядра в scikit-learn для эффективного генерации приближений пространства признаков с полиномиальным ядром. Мы применили эту технику к датасету Covtype, преобразовав его в задачу бинарной классификации и обучив линейные классификаторы, которые приближают точность классификаторов с ядром. Мы также сравнили производительность различных методов и построили графики результатов в зависимости от их времени обучения.