← Назад к вопросам

Объясните алгоритм машинного обучения SVM

2.0 Middle🔥 221 комментариев
#Машинное обучение

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI30 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Support Vector Machine (SVM): нахождение оптимальной разделяющей гиперплоскости

Основная идея

SVM ищет гиперплоскость (линию в 2D, плоскость в 3D, гиперплоскость в N-D), которая:

  1. Максимально разделяет два класса
  2. Имеет наибольший зазор (margin) от обоих классов
  3. Как можно ближе находится в центре между классами
2D пример:

Класс 1: x
Класс 2: o

     x   |
     x   |  ← оптимальная гиперплоскость
xxx xxxx|
oooo    |oo
     o  |
        o

Маргин (зазор) максимален

История

1995: Vapnik и коллеги создают SVM
1995-2005: Становится очень популярным
2005-2024: Вытеснена нейросетями, но ещё используется

Математика (упрощённо)

Линейно разделяемый случай

Гиперплоскость: w·x + b = 0

Ограничения (constraints):
y_i * (w·x_i + b) >= 1, для всех i

Маргин = 2 / ||w||

Цель: максимизировать маргин
⟺ минимизировать ||w||²

Это задача квадратичного программирования

Ядра (Kernels): волшебство SVM

Линейная гиперплоскость не может разделить XOR или спиральные данные.

Решение: Kernel Trick - преобразование в более высокое измерение

В исходном пространстве (2D): НЕ разделяемо
    x o x
    o x o
    x o x

После kernel преобразования в 3D: разделяемо!
    /\
   /  \  ← плоскость разделяет классы
  /____\

Типы ядер

1. Linear (линейное ядро)

K(x_i, x_j) = x_i · x_j

Используется для:
- Линейно разделяемых данных
- Больших датасетов (быстро)
- Текстовых данных (часто линейны)

2. Polynomial (полиномиальное ядро)

K(x_i, x_j) = (x_i · x_j + c)^d

Параметры:
- d = степень (2, 3, ...)
- c = constant

Используется для:
- Умеренно нелинейных данных
- Когда есть полиномиальные отношения

3. RBF (Radial Basis Function)

K(x_i, x_j) = exp(-gamma * ||x_i - x_j||²)

Параметр:
- gamma = 1/(2*sigma²)

Используется для:
- Нелинейных данных (по умолчанию)
- Неизвестной структуры данных
- Самое универсальное ядро

4. Sigmoid

K(x_i, x_j) = tanh(alpha * x_i · x_j + c)

Редко используется, похож на нейросеть

Практическая реализация

from sklearn.svm import SVC
import numpy as np
from sklearn.datasets import make_classification
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score, confusion_matrix

# Данные
X, y = make_classification(n_samples=200, n_features=2, 
                           n_informative=2, n_redundant=0,
                           random_state=42)

X_train, X_test, y_train, y_test = train_test_split(
    X, y, test_size=0.2, random_state=42
)

# SVM с линейным ядром
svm_linear = SVC(kernel='linear', C=1.0)
svm_linear.fit(X_train, y_train)
y_pred_linear = svm_linear.predict(X_test)
print(f"Linear SVM Accuracy: {accuracy_score(y_test, y_pred_linear):.3f}")

# SVM с RBF ядром
svm_rbf = SVC(kernel='rbf', C=1.0, gamma='scale')
svm_rbf.fit(X_train, y_train)
y_pred_rbf = svm_rbf.predict(X_test)
print(f"RBF SVM Accuracy: {accuracy_score(y_test, y_pred_rbf):.3f}")

# SVM с полиномиальным ядром
svm_poly = SVC(kernel='poly', C=1.0, degree=3)
svm_poly.fit(X_train, y_train)
y_pred_poly = svm_poly.predict(X_test)
print(f"Polynomial SVM Accuracy: {accuracy_score(y_test, y_pred_poly):.3f}")

Важные параметры

1. C (Regularization Parameter)

C = 1 / λ (где λ - параметр регуляризации)

C высокий (C=100):
- Модель штрафует ошибки на обучении
- Может переобучиться
- Маргин меньше

C низкий (C=0.01):
- Позволяет ошибки на обучении
- Более мягкая граница
- Маргин больше
- Лучшая обобщаемость

2. Gamma (для RBF ядра)

Gamma контролирует "коэффициент распространения" ядра

Гамма высокая (gamma=10):
- Каждая точка влияет только на ближайших соседей
- Может привести к переобучению

Гамма низкая (gamma=0.001):
- Каждая точка влияет далеко
- Более гладкая граница
- Может недообучиться

Векторы поддержки (Support Vectors)

НЕ ВСЕ точки данных одинаково важны!

Векторы поддержки = точки, которые:
- Находятся ближе всего к границе
- Определяют положение границы
- Влияют на результат

Другие точки можно удалить, граница не изменится
# Доступ к векторам поддержки
svm = SVC(kernel='rbf')
svm.fit(X_train, y_train)

print(f"Количество векторов поддержки: {len(svm.support_vectors_)}")
print(f"Всего точек: {len(X_train)}")
print(f"Процент: {100*len(svm.support_vectors_)/len(X_train):.1f}%")

# Визуализация
if X_train.shape[1] == 2:  # только если 2 признака
    plt.scatter(X_train[:, 0], X_train[:, 1], c=y_train, cmap='viridis')
    # отметь векторы поддержки
    plt.scatter(svm.support_vectors_[:, 0], svm.support_vectors_[:, 1],
                s=300, linewidth=1.5, edgecolors='black', 
                facecolors='none', label='Support Vectors')
    plt.legend()
    plt.show()

SVM для регрессии

from sklearn.svm import SVR

# Вместо классификации предсказываем непрерывное значение
X = np.array(range(100)).reshape(-1, 1)
y = np.sin(X).flatten()

svr = SVR(kernel='rbf', C=100, gamma='scale')
svr.fit(X, y)
y_pred = svr.predict(X)

# С параметром epsilon
# Модель позволяет ошибку epsilon без штрафа
svr_eps = SVR(kernel='rbf', C=100, epsilon=0.1)

Преимущества SVM

1. Хорошо для разделяющих задач
   - Четкая теория
   - Гарантированный глобальный оптимум

2. Работает в высоких измерениях
   - Ядра позволяют работать с очень высокими размерностями

3. Гибкий
   - Много ядер для разных типов данных

4. Хорошая обобщаемость
   - Маржин максимизируется

5. Вычислительно эффективно
   - Использует только векторы поддержки
   - Быстрее нейросетей

Недостатки SVM

1. Медленен на больших данных
   - Обучение O(n²) или O(n³)
   - Для 1M+ строк не подходит

2. Сложная интерпретация
   - Сложнее чем деревья решений
   - Трудно объяснить решение

3. Требует нормализации
   - Масштабируй признаки перед SVM

4. Выбор ядра критичен
   - Неправильное ядро = плохое качество
   - Требует экспериментирования

5. Вытеснен нейросетями
   - Для нелинейных задач нейросети лучше

Когда использовать SVM

Используй SVM когда:

  1. Данные небольшие (< 100K строк)
  2. Задача бинарной классификации
  3. Данные не имеют очевидной структуры
  4. Нужна высокая точность
  5. Требуется интерпретируемость (частично)

НЕ используй SVM когда:

  1. Данные очень большие (> 1M строк)
  2. Есть нелинейная структура (используй нейросети)
  3. Нужна максимальная скорость обучения
  4. Нужна интерпретируемость (используй деревья)
  5. Мультиклассовая классификация (есть лучшие методы)

Тюнинг параметров

from sklearn.model_selection import GridSearchCV

params = {
    'C': [0.1, 1, 10, 100],
    'gamma': ['scale', 'auto', 0.001, 0.01],
    'kernel': ['linear', 'rbf', 'poly']
}

grid_search = GridSearchCV(SVC(), params, cv=5)
grid_search.fit(X_train, y_train)

print(f"Лучшие параметры: {grid_search.best_params_}")
print(f"Лучший score: {grid_search.best_score_}")

Заключение

SVM - это мощный классификатор, основанный на поиске оптимальной разделяющей гиперплоскости с максимальным зазором. Ядра позволяют работать с нелинейными данными. Хотя SVM вытеснена нейросетями, она остаётся полезной для средних датасетов с чёткой структурой классов. Главное - правильно выбрать ядро и настроить параметры C и gamma.