В предыдущей статье была объяснена математическая основа 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 с ядром, который учитывает нелинейную разделимость; оба они станут темами будущих статей.