В предыдущей статье была объяснена математическая основа SVM с жесткими границами. В итоге формулировка сводилась к компактной функции стоимости J(α), которую нужно было максимизировать.

В этой статье метод градиентного восхождения используется в качестве последовательной максимальной оптимизации, что означает, что градиентное восхождение итеративно улучшает аппроксимацию значений α, что приводит к максимальному значению функции J. Итерационная процедура метода градиентного восхождения задается следующим правилом обновления:

Приведенное выше правило обновления означает, что для фиксированного числа итераций n, на каждой итерации i значение α вычисляется как сумма предыдущее значение α(из итерацииi-1)и коэффициент изменения J(α) относительно α. λ называется «скоростью обучения» на жаргоне машинного обучения, и он гарантирует, что по мере приближения алгоритма к оптимальному решению размер шага будет уменьшаться, следовательно, не будет превышено конечное значение. решение из-за неуместно большого обновления dJ/dα.

После вычисления конечных значений α вектор w может быть восстановлен по следующему уравнению:

Помните, что w и b рассчитываются с использованием только опорных векторов; причина этого объясняется в разделе восстановление w из предыдущей статьи.

Достаточно вычислить значение b, используя только один опорный вектор, но обычно оно рассчитывается как среднее значение всех значений b, каждое из которых связано с одним опорным вектором. Пусть S будет набором всех опорных векторов, тогда:

  • |С| количество элементов в S.

Теперь все элементы, необходимые для построения алгоритма SVM с жесткой маржой, готовы. Они включены в следующий фрагмент кода, который предоставляет ООП-модель SVM с жесткими границами в Python.

Этот код был опробован на двух игрушечных наборах данных, один из которых сгенерирован синтетическим образом с использованием функции make_blobs из sklearn.datasets, а другой представляет собой настроенный набор данных Iris. Давайте посмотрим, как приведенная выше реализация работает на обоих из них.

Синтетический набор данных

Функция make_blobs использовалась для генерации данных, состоящих из двух признаков и одной переменной ответа. Переменная ответа содержит бинарные классы {0, 1}, которые линейно разделимы и не имеют перекрытия между собой; кроме того, классы были преобразованы в {-1, 1}, чтобы соответствовать настройке алгоритма SVM.

Визуализация приведенных выше данных выглядит следующим образом:

После нескольких проб с количеством эпох (итераций) было принято решение создать экземпляр класса HardMarginSVM с 5000 эпохами. Хотя количество эпох выглядит относительно большим, модель работала довольно быстро; чтобы соответствовать тренировочным данным, потребовалось 0,06 секунды.

Оценка прогноза модели на тестовых данных составляет 100% (данные простые!).

После того, как экземпляр svm был приспособлен к обучающим данным, значения w и b используются для визуализации границы классификации. Чтобы иметь возможность сделать эту визуализацию, необходимо помнить, что вертикальная ось представлена ​​переменной x2. Следовательно, необходимо извлечь формулу для x2 со ссылкой на x1, которая является переменной на горизонтальной оси.

Разверните wx+b=0, учитывая, что вектор w = [w1, w2],данные имеют два признакаx = [x1, x2]

Следуя той же методике, что и для wx+b=0, x2, для wx+b=1, wx+b=-1 выглядит следующим образом

Три варианта приведенных выше уравнений x2 можно объединить в одну функцию; назовем его get_x2

Где параметр смещение👆может принимать значения 0, 1 или -1.

Теперь, зная минимальное и максимальное значения данных на оси x1, соответствующие значения на оси x2 вычисляются с помощью функции get_x2. . Затем для каждого смещения строится соответствующая линия путем соединения двух точек (min_x1, get_x2(min_x1, *args)), (max_x1, get_x2(max_x1, *args)).

Индивидуальный набор данных Iris

Второй пример представлен на реальном наборе данных, так что, когда SVM с жесткими границами подгоняется к нему, а затем строится, переменные горизонтальной оси и вертикальной оси имеют семантику, а не только x1 и x2, как в случае синтетических данных. В этом примере используется известный исторический набор данных Iris; он упакован в библиотеку Scikit-Learn и предоставляется функцией sklearn.datasets.load_iris(*args, **kwargs). Вот пять строк, выбранных случайным образом, вместе с кодом, который их создает:

Набор данных Iris имеет три класса цветов: «Setosa», «Versicolor» и «Virginica», которые закодированы в целевом столбце как 0, 1 и 2 соответственно. Чтобы данные визуализировались в 2D, один из классов должен быть удален из целевого столбца, и должны быть сохранены только два признака. Чтобы сделать разумный выбор, какие функции и классы оставить, давайте визуализируем взаимосвязь между функциями и посмотрим, как они влияют на кластеризацию групп.

Из приведенного выше графика было решено исключить класс 1, то есть «Versicolor», наряду с удалением признаков «длина чашелистика (см)» и «ширина лепестка (см)».

Теперь данные имеют два признака: «ширина чашелистика (см)» и «длина лепестка (см)» и, кроме того, два класса в целевом столбце: «Setosa» и «Virginica», закодированные как 0 и 1 соответственно. Их следует преобразовать в -1 и 1, чтобы они соответствовали настройке SVM. 0 → -1 и 2 → 1.

Визуализация данных после настройки

С этого момента мы можем следовать тем же шагам, что и в предыдущем примере.

  • Создание экземпляра HardMarginSVM
  • Сопоставьте его с данными
  • визуализировать границу классификации.

Визуализация результата будет выглядеть следующим образом:

Заключение:

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