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

Терминология, используемая в SVM:

· Гиперплоскость. В SVM гиперплоскость — это граница решения, которая разделяет данные на разные классы. Цель SVM — найти наилучшую гиперплоскость, максимально разделяющую разные классы. В двумерном пространстве гиперплоскость — это прямая линия, в трехмерном — плоскость и так далее. Хорошее эмпирическое правило состоит в том, что для n-мерного пространства гиперплоскость обычно имеет n-1 измерение.

· Отступ. Отступ — это расстояние между гиперплоскостью и ближайшими точками данных для каждого класса. Цель SVM — найти гиперплоскость, которая максимизирует запас, что помогает гарантировать, что граница решения находится как можно дальше от точек данных. Чем больше разница, тем лучше разделение классов.

Вот простой математический пример того, как SVM классифицирует данные с двумя признаками (x1 и x2) и двумя классами (A и B):

Цель состоит в том, чтобы найти наилучшую границу (или гиперплоскость), разделяющую два класса. Уравнение гиперплоскости имеет вид:

w1x1 + w2x2 + b = 0

где w1 и w2 — веса, присвоенные функциям x1 и x2, а b — член смещения.

Алгоритм SVM находит веса и смещения, которые максимизируют маржу.

· Опорные векторы. Опорные векторы — это точки данных, которые находятся ближе всего к границе решения (или гиперплоскости). Эти точки играют особую роль в определении местоположения границы решения, потому что цель SVM состоит в том, чтобы найти гиперплоскость, которая максимально разделяет различные классы, максимизируя запас, который представляет собой расстояние между гиперплоскостью и ближайшими точками данных из каждого класса. .

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

· Параметр регуляризации (C): Параметр регуляризации — это настраиваемый параметр, который управляет компромиссом между максимизацией маржи и минимизацией количества ошибочных классификаций. Меньшее значение C приведет к большей марже, но большему количеству ошибочных классификаций, в то время как большее значение C приведет к меньшему марже, но меньшему количеству ошибочных классификаций. По умолчанию значение C равно 1, что соответствует SVM с жестким запасом. Чтобы использовать SVM с мягкой маржой, вы можете установить меньшее значение C, например 0,1.

Типы SVM

Существует два основных типа SVM: линейный SVM и нелинейный SVM.

1. Линейный SVM

Алгоритм Linear Support Vector Machine используется, когда у нас есть линейно разделимые данные. Говоря простым языком, если у нас есть набор данных, который можно разделить на две группы с помощью простой прямой линии, мы называем его линейно разделяемыми данными, а используемый для этого классификатор называется линейным классификатором SVM.

2. Ядро или нелинейный SVM

Алгоритм нелинейной машины опорных векторов используется, когда у нас есть нелинейно разделимые данные. Говоря простым языком, если у нас есть набор данных, который нельзя разделить на две группы с помощью простой прямой линии, мы называем его нелинейными разделимыми данными, а используемый для этого классификатор известен как нелинейный классификатор SVM.

Функции ядра:

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

  1. Линейное ядро. Линейное ядро ​​— это простейшая функция ядра. Он вычисляет скалярное произведение входных признаков, что эквивалентно линейному SVM. Линейное ядро ​​используется, когда данные линейно разделимы.
from sklearn.svm import SVC
clf = SVC(kernel='linear', C=1)

Линейное ядро ​​можно определить как:

K(x, x’) = xT*x’

где x и x 'являются входными функциями, а T обозначает транспонирование матрицы.

2. Полиномиальное ядро: полиномиальное ядро ​​используется для захвата нелинейных отношений между входными объектами. Он вычисляет скалярное произведение входных функций, возведенных в указанную степень.

from sklearn.svm import SVC
clf = SVC(kernel='poly', degree=2, coef0=1, C=1, gamma='auto')

Ядро полинома можно определить как:

K(x, x’) = (gamma * xT * x’ + coef0)^d

где x и x’ — входные признаки, T обозначает транспонирование матрицы, gamma — коэффициент ядра для ‘rbf’, ‘poly’ и ‘sigmoid’. если передается gamma='scale' (по умолчанию), то используется 1 / (n_features * X.var()) в качестве значения гаммы, если 'auto', используется 1 / n_features, coef0 - постоянный член, а d - степень полинома, c является константой

примечание: значение гаммы по умолчанию — «масштаб», это значение выбрано как оптимальное для большинства наборов данных, но стоит попробовать другие значения, если производительность не оптимальна.

coef0 — это параметр, который используется в полиномиальной и сигмовидной функциях ядра в алгоритме машины опорных векторов (SVM).

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

3. Сигмовидное ядро: вычисляет скалярное произведение входных объектов после применения сигмовидной функции к входным объектам.

from sklearn.svm import SVC
clf = SVC(kernel='sigmoid', gamma=1, coef0=1, C=1)

Сигмовидную функцию ядра можно определить как:

K(x, x’) = th(gamma * xT * x’ + coef0)

где x и x' — входные признаки, T — транспонирование матрицы, gamma — параметр, управляющий наклоном сигмовидной функции, а в сигмовидной функции ядра coef0 — константа, которая добавляется к скалярному произведению входные функции перед применением сигмовидной функции.

4. Gaussian Radial Basis Function (RBF): в библиотеке scikit-learn ядро ​​Gaussian RBF можно установить, передав 'rbf' в качестве значения параметра ядра класса SVC и указав значение gamma с помощью параметра gamma. :

from sklearn.svm import SVC
clf = SVC(kernel='rbf', C=1, gamma=1)

Гауссовский RBF определяется следующим образом:

K(x, x’) = exp(-gamma * ||x — x’||²)

Где x и x’ — входные признаки, ||x — x’|| это евклидово расстояние между входными объектами

Примечание. В методе опорных векторов (SVM) — функция ядра, также известная как функция подобия. Функция сходства отображает входные данные в многомерное пространство признаков путем вычисления скалярного произведения между входными данными и набором базовых функций. Скалярный продукт является мерой сходства между входными данными и базисными функциями. Скалярное произведение между двумя векторами высокое, когда они похожи, и низкое, когда они не похожи.

Подводя итог, можно сказать, что существует два основных типа алгоритмов классификации SVM Hard Margin и Soft Margin:

Жесткая маржа: направлена ​​​​на поиск лучшей гиперплоскости, не допуская какой-либо формы неправильной классификации.

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

Мягкая маржа SVM может быть реализована в Scikit-Learn путем добавления штрафного термина C в svm.SVC. Чем больше C, тем больше штраф получает алгоритм при неправильной классификации.

Поиск нелинейной границы решения:

Один из способов найти нелинейную границу решения в SVM — использовать трюк ядра. Например, допустим, у нас есть набор данных с двумя классами, классом A и классом B, которые не являются линейно разделимыми в их исходном пространстве признаков. Используя ядро ​​RBF, мы можем отображать входные данные в многомерное пространство, где можно найти линейную границу решения, чтобы отделить класс A от класса B.

Для лучшего понимания Kernel Trick посмотрите эти видео:

Выбор ориентиров в SVM:

В алгоритме машины опорных векторов (SVM) опорные точки, также известные как опорные векторы, представляют собой точки во входных данных, которые находятся ближе всего к границе решения и оказывают наибольшее влияние на определение местоположения границы решения. Хитрость ядра достигается путем выбора «ориентировочных точек» в данных. Стоит отметить, что ориентиры выбираются функцией ядра в SVM автоматически, поэтому вам не нужно выбирать их явно. В scikit-learn после обучения модели SVM доступ к опорным векторам можно получить через атрибут support_vectors_ объекта модели. Вот пример:

from sklearn.svm import SVC
from sklearn.datasets import make_classification

# create a synthetic data set
X, y = make_classification(n_samples=1000, n_features=2, n_informative=2, n_redundant=0, n_classes=2, random_state=42)

# fit the model
model = SVC(kernel='linear', C=1, random_state=42)
model.fit(X, y)

# access the support vectors
support_vectors = model.support_vectors_
print("Support Vectors: \n", support_vectors)

Хороший выбор ориентиров приведет к четкому разделению границы, а неправильный выбор приведет к плохому разделению.

Мультиклассовая классификация с использованием SVM:

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

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

Например, допустим, мы хотим разделить изображения животных на 4 разных класса: кошки, собаки, птицы и рыбы. Используя метод «один против всех», мы обучим 4 разных бинарных классификатора:

Классификатор, отделяющий кошек от не кошек (собак, птиц, рыб)

Классификатор, который отделяет собак от не-собак (кошки, птицы, рыбы)

Классификатор, отделяющий птиц от нептиц (кошки, собаки, рыбы)

Классификатор, отделяющий рыбу от нерыбы (кошки, собаки, птицы)

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

from sklearn.svm import SVC
from sklearn.datasets import make_classification
from sklearn.multiclass import OneVsRestClassifier

# create a synthetic data set
X, y = make_classification(n_samples=1000, n_features=2, n_informative=2, n_redundant=0, n_classes=4, random_state=42)

# fit the model using the One-vs-All method
model = OneVsRestClassifier(SVC(kernel='linear', C=1, random_state=42))
model.fit(X, y)

Один против одного – это еще один метод многоклассовой классификации с использованием машин опорных векторов (SVM) или других бинарных классификаторов. Основная идея состоит в том, чтобы обучить бинарный классификатор для каждой пары классов. Например, если у вас есть три класса, вы должны обучить три классификатора:

Классификатор 1: отделяет класс 1 от класса 2.

Классификатор 2: отделяет класс 1 от класса 3.

Классификатор 3: отделяет класс 2 от класса 3.

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

from sklearn.multiclass import OneVsOneClassifier

# fit the model using the One-vs-One method
model = OneVsOneClassifier(SVC(kernel='linear', C=1, random_state=42))
model.fit(X, y)

обратите внимание, что метод «один против одного» более затратен в вычислительном отношении, чем метод «один против всех», поскольку требует обучения n (n-1)/2 классификаторов для n классов, но может привести к лучшей производительности для некоторых наборов данных.

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

from sklearn.datasets import load_iris
from sklearn.svm import SVC
from sklearn.model_selection import train_test_split
from sklearn.model_selection import GridSearchCV
from sklearn.metrics import accuracy_score

iris = load_iris()
X, y = iris.data, iris.target

# split the data into train and test sets
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)

params_grid = [{'kernel': ['rbf'], 'gamma': [1e-3, 1e-4],
                     'C': [1, 10, 100, 1000]},
                    {'kernel': ['linear'], 'C': [1, 10, 100, 1000]}]

# Performing CV to tune parameters for best SVM fit 
svm_model = GridSearchCV(SVC(), params_grid, cv=5)
svm_model.fit(X_train, y_train)

# View the accuracy score
print('Best score for training data:', svm_model.best_score_,"\n") 

# View the best parameters for the model found using grid search
print('Best C:',svm_model.best_estimator_.C,"\n") 
print('Best Kernel:',svm_model.best_estimator_.kernel,"\n")
print('Best Gamma:',svm_model.best_estimator_.gamma,"\n")

final_model = svm_model.best_estimator_
# make predictions on the test set
y_pred = final_model.predict(X_test)

# evaluate the model's performance
acc = accuracy_score(y_test, y_pred)
print('Accuracy:', acc)

вывод может выглядеть так-

Best score for training data: 0.9583333333333334 

Best C: 1000 

Best Kernel: rbf 

Best Gamma: 0.001 

Accuracy: 1.0

Примечание: params_grid можно записать по-другому:

params_grid = {'kernel': {'rbf': {'gamma': [1e-3, 1e-4], 'C': [1, 10, 100, 1000]},
'linear': {'C': [1, 10, 100, 1000]}}}

Здесь поиск по сетке настроен на изучение различных комбинаций двух типов функций ядра: «rbf» (радиальная базисная функция) и «линейная».

Для ядра «rbf» поиск по сетке будет пробовать разные комбинации двух гиперпараметров: gamma и C.

Для «линейного» ядра поиск по сетке будет пробовать разные комбинации одного гиперпараметра: C

Последнее примечание. Спасибо за внимание! Я надеюсь, что вы найдете эту статью информативной.

Хотите связаться со мной? Напишите мне в LinkedIn