Машина опорных векторов (SVM)
Введение в SVM
Машины опорных векторов (SVM) - это мощные, но гибкие алгоритмы машинного обучения с учителем, которые используются как для классификации, так и для регрессии. Но обычно они используются в задачах классификации. В 1960-х годах SVM были впервые представлены, но позже они были усовершенствованы в 1990 году. SVM имеют свой уникальный способ реализации по сравнению с другими алгоритмами машинного обучения. В последнее время они чрезвычайно популярны из-за их способности обрабатывать несколько непрерывных и категориальных переменных.
Работа SVM
Модель SVM - это в основном представление различных классов на гиперплоскости в многомерном пространстве. Гиперплоскость будет генерироваться SVM итеративно, чтобы можно было минимизировать ошибку. Цель SVM - разделить наборы данных на классы, чтобы найти максимальную маргинальную гиперплоскость (MMH).
Следующие важные концепции в SVM -
Support Vectors- Точки данных, которые находятся ближе всего к гиперплоскости, называются опорными векторами. Разделительная линия будет определена с помощью этих точек данных.
Hyperplane - Как мы видим на приведенной выше диаграмме, это плоскость принятия решений или пространство, которое разделено между набором объектов, имеющих разные классы.
Margin- Его можно определить как разрыв между двумя линиями на точках данных шкафа разных классов. Его можно рассчитать как перпендикулярное расстояние от линии до опорных векторов. Большая маржа считается хорошей маржей, а небольшая маржа - плохой.
Основная цель SVM - разделить наборы данных на классы, чтобы найти максимальную маргинальную гиперплоскость (MMH), и это можно сделать в следующих двух шагах:
Во-первых, SVM будет итеративно генерировать гиперплоскости, что наилучшим образом разделяет классы.
Затем он выберет гиперплоскость, которая правильно разделяет классы.
Реализация SVM на Python
Для реализации SVM в Python мы начнем с импорта стандартных библиотек следующим образом:
import numpy as np
import matplotlib.pyplot as plt
from scipy import stats
import seaborn as sns; sns.set()
Затем мы создаем образец набора данных с линейно разделяемыми данными из sklearn.dataset.sample_generator для классификации с использованием SVM -
from sklearn.datasets.samples_generator import make_blobs
X, y = make_blobs(n_samples=100, centers=2, random_state=0, cluster_std=0.50)
plt.scatter(X[:, 0], X[:, 1], c=y, s=50, cmap='summer');
Следующим будет результат после создания образца набора данных, состоящего из 100 образцов и 2 кластеров:
Мы знаем, что SVM поддерживает дискриминационную классификацию. он отделяет классы друг от друга, просто находя линию в случае двух измерений или многообразие в случае нескольких измерений. Он реализован в приведенном выше наборе данных следующим образом:
xfit = np.linspace(-1, 3.5)
plt.scatter(X[:, 0], X[:, 1], c=y, s=50, cmap='summer')
plt.plot([0.6], [2.1], 'x', color='black', markeredgewidth=4, markersize=12)
for m, b in [(1, 0.65), (0.5, 1.6), (-0.2, 2.9)]:
plt.plot(xfit, m * xfit + b, '-k')
plt.xlim(-1, 3.5);
Результат выглядит следующим образом -
Из приведенного выше вывода видно, что есть три разных разделителя, которые отлично различают указанные выше образцы.
Как уже говорилось, основная цель SVM - разделить наборы данных на классы, чтобы найти максимальную граничную гиперплоскость (MMH), следовательно, вместо того, чтобы рисовать нулевую линию между классами, мы можем провести вокруг каждой линии поле некоторой ширины до ближайшей точки. Это можно сделать следующим образом -
xfit = np.linspace(-1, 3.5)
plt.scatter(X[:, 0], X[:, 1], c=y, s=50, cmap='summer')
for m, b, d in [(1, 0.65, 0.33), (0.5, 1.6, 0.55), (-0.2, 2.9, 0.2)]:
yfit = m * xfit + b
plt.plot(xfit, yfit, '-k')
plt.fill_between(xfit, yfit - d, yfit + d, edgecolor='none',
color='#AAAAAA', alpha=0.4)
plt.xlim(-1, 3.5);
Из приведенного выше изображения в выходных данных мы легко можем наблюдать «поля» в рамках дискриминантных классификаторов. SVM выберет линию, которая максимизирует маржу.
Затем мы будем использовать классификатор опорных векторов Scikit-Learn для обучения модели SVM на этих данных. Здесь мы используем линейное ядро для соответствия SVM следующим образом:
from sklearn.svm import SVC # "Support vector classifier"
model = SVC(kernel='linear', C=1E10)
model.fit(X, y)
Результат выглядит следующим образом -
SVC(C=10000000000.0, cache_size=200, class_weight=None, coef0=0.0,
decision_function_shape='ovr', degree=3, gamma='auto_deprecated',
kernel='linear', max_iter=-1, probability=False, random_state=None,
shrinking=True, tol=0.001, verbose=False)
Теперь, для лучшего понимания, ниже будут построены функции принятия решения для 2D SVC:
def decision_function(model, ax=None, plot_support=True):
if ax is None:
ax = plt.gca()
xlim = ax.get_xlim()
ylim = ax.get_ylim()
Для оценки модели нам нужно создать сетку следующим образом:
x = np.linspace(xlim[0], xlim[1], 30)
y = np.linspace(ylim[0], ylim[1], 30)
Y, X = np.meshgrid(y, x)
xy = np.vstack([X.ravel(), Y.ravel()]).T
P = model.decision_function(xy).reshape(X.shape)
Затем нам нужно построить границы решения и поля следующим образом:
ax.contour(X, Y, P, colors='k',
levels=[-1, 0, 1], alpha=0.5,
linestyles=['--', '-', '--'])
Теперь аналогичным образом постройте опорные векторы следующим образом:
if plot_support:
ax.scatter(model.support_vectors_[:, 0],
model.support_vectors_[:, 1],
s=300, linewidth=1, facecolors='none');
ax.set_xlim(xlim)
ax.set_ylim(ylim)
Теперь используйте эту функцию для соответствия нашим моделям следующим образом:
plt.scatter(X[:, 0], X[:, 1], c=y, s=50, cmap='summer')
decision_function(model);
Из вышеприведенного вывода мы можем наблюдать, что классификатор SVM соответствует данным с полями, то есть пунктирными линиями и опорными векторами, ключевыми элементами этого соответствия, касающимися пунктирной линии. Эти точки опорных векторов хранятся в атрибуте support_vectors_ классификатора следующим образом:
model.support_vectors_
Результат выглядит следующим образом -
array([[0.5323772 , 3.31338909],
[2.11114739, 3.57660449],
[1.46870582, 1.86947425]])
Ядра SVM
На практике алгоритм SVM реализуется с помощью ядра, которое преобразует пространство входных данных в требуемую форму. SVM использует технику, называемую трюком с ядром, в которой ядро берет низкоразмерное входное пространство и преобразует его в более высокомерное пространство. Проще говоря, ядро преобразует неразрывные проблемы в отдельные проблемы, добавляя к ним дополнительные измерения. Это делает SVM более мощным, гибким и точным. Ниже приведены некоторые из типов ядер, используемых SVM.
Линейное ядро
Его можно использовать как скалярное произведение между любыми двумя наблюдениями. Формула линейного ядра следующая:
k (x, x i ) = сумма (x * x i )
Из приведенной выше формулы мы видим, что произведение двух векторов говорит & - это сумма умножения каждой пары входных значений.
Полиномиальное ядро
Это более обобщенная форма линейного ядра и различают искривленное или нелинейное входное пространство. Ниже приводится формула для полиномиального ядра -
K (x, xi) = 1 + сумма (x * xi) ^ d
Здесь d - степень полинома, которую нам нужно указать вручную в алгоритме обучения.
Ядро радиальной базисной функции (RBF)
Ядро RBF, в основном используемое в классификации SVM, отображает входное пространство в неопределенное пространство. Следующая формула объясняет это математически -
K (x, xi) = exp (-гамма * сумма ((x - xi ^ 2))
Здесь гамма варьируется от 0 до 1. Нам нужно вручную указать ее в алгоритме обучения. Хорошее значение гаммы по умолчанию - 0,1.
Поскольку мы реализовали SVM для линейно разделяемых данных, мы можем реализовать его на Python для данных, которые не являются линейно разделяемыми. Это можно сделать с помощью ядер.
пример
Ниже приведен пример создания классификатора SVM с использованием ядер. Мы будем использовать набор данных iris из scikit-learn -
Мы начнем с импорта следующих пакетов -
import pandas as pd
import numpy as np
from sklearn import svm, datasets
import matplotlib.pyplot as plt
Теперь нам нужно загрузить входные данные -
iris = datasets.load_iris()
Из этого набора данных мы берем первые две функции следующим образом:
X = iris.data[:, :2]
y = iris.target
Затем мы построим границы SVM с исходными данными следующим образом:
x_min, x_max = X[:, 0].min() - 1, X[:, 0].max() + 1
y_min, y_max = X[:, 1].min() - 1, X[:, 1].max() + 1
h = (x_max / x_min)/100
xx, yy = np.meshgrid(np.arange(x_min, x_max, h),
np.arange(y_min, y_max, h))
X_plot = np.c_[xx.ravel(), yy.ravel()]
Теперь нам нужно предоставить значение параметра регуляризации следующим образом:
C = 1.0
Затем объект классификатора SVM может быть создан следующим образом:
Svc_classifier = svm.SVC (ядро = 'линейный', C = C) .fit (X, y)
Z = svc_classifier.predict(X_plot)
Z = Z.reshape(xx.shape)
plt.figure(figsize=(15, 5))
plt.subplot(121)
plt.contourf(xx, yy, Z, cmap=plt.cm.tab10, alpha=0.3)
plt.scatter(X[:, 0], X[:, 1], c=y, cmap=plt.cm.Set1)
plt.xlabel('Sepal length')
plt.ylabel('Sepal width')
plt.xlim(xx.min(), xx.max())
plt.title('Support Vector Classifier with linear kernel')
Вывод
Text(0.5, 1.0, 'Support Vector Classifier with linear kernel')
Для создания классификатора SVM с rbf ядро, мы можем изменить ядро на rbf следующим образом -
Svc_classifier = svm.SVC(kernel='rbf', gamma =‘auto’,C=C).fit(X, y)
Z = svc_classifier.predict(X_plot)
Z = Z.reshape(xx.shape)
plt.figure(figsize=(15, 5))
plt.subplot(121)
plt.contourf(xx, yy, Z, cmap=plt.cm.tab10, alpha=0.3)
plt.scatter(X[:, 0], X[:, 1], c=y, cmap=plt.cm.Set1)
plt.xlabel('Sepal length')
plt.ylabel('Sepal width')
plt.xlim(xx.min(), xx.max())
plt.title('Support Vector Classifier with rbf kernel')
Вывод
Text(0.5, 1.0, 'Support Vector Classifier with rbf kernel')
Мы устанавливаем значение гаммы на «авто», но вы также можете указать его значение от 0 до 1.
Плюсы и минусы классификаторов SVM
Плюсы SVM-классификаторов
Классификаторы SVM обеспечивают высокую точность и хорошо работают с пространством больших размеров. Классификаторы SVM в основном используют подмножество обучающих точек, поэтому в результате используется очень меньше памяти.
Минусы классификаторов SVM
У них много времени на обучение, поэтому на практике они не подходят для больших наборов данных. Другой недостаток заключается в том, что классификаторы SVM плохо работают с перекрывающимися классами.