Support Vector Regression (SVR) — это алгоритм регрессионного анализа, основанный на том же принципе, что и Support Vector Machine (SVM), но адаптированный для задач прогнозирования непрерывных значений, а не классификации.


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

Если в SVM мы максимизируем зазор между классами, то в SVR мы пытаемся найти функцию, которая отклоняется от истинных значений не более чем на заданную величину ε (эпсилон), оставаясь при этом как можно более “плоской”.

Проще говоря: “Найти такую линию/поверхность, чтобы как можно больше точек данных лежало внутри ε-трубки вокруг этой линии”.


Ключевые концепции SVR

1. ε-трубка (ε-tube)

  • Это “допустимая зона ошибки” вокруг предсказанной функции
  • Все точки, попадающие внутрь этой трубки, считаются правильно предсказанными
  • Чем шире трубка, тем более гладкой будет регрессионная функция

2. Опорные векторы в SVR

  • Это точки, которые лежат НА или ВНЕ ε-трубки
  • Только эти точки влияют на положение регрессионной функции
  • Точки внутри трубки игнорируются — они считаются правильно предсказанными

3. Функция потерь (ε-insensitive loss function)

  • Ошибка = 0, если разница между предсказанием и истинным значением ≤ ε
  • Ошибка = |факт - предсказание| - ε, если разница > ε

Математическая формулировка

SVR решает следующую задачу оптимизации:

Минимизировать:

При условиях:

где:

  • , — параметры модели
  • — переменные запаса (slack variables), позволяющие точкам выходить за пределы ε-трубки
  • — параметр регуляризации (компромисс между простотой модели и точностью)
  • — ширина трубки

Визуализация SVR

TBD

Параметры SVR и их влияние

1. ε (epsilon) — ширина трубки

  • Малое : Узкая трубка → больше опорных векторов → более точная, но сложная модель
  • Большое : Широкая трубка → меньше опорных векторов → более простая, гладкая модель

2. C — параметр регуляризации

  • Малое : Широкий запас, допускается много ошибок → более простая модель
  • Большое : Узкий запас, штраф за ошибки велик → более точная, но сложная модель

3. Kernel — ядерная функция

  • linear: Линейная регрессия
  • poly: Полиномиальная регрессия
  • rbf: Радиальная базисная функция (наиболее популярна)
  • sigmoid: Сигмоидальное ядро

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

  1. Устойчивость к выбросам: Только опорные векторы влияют на модель
  2. Эффективность в высокоразмерных пространствах
  3. Гибкость: Возможность моделировать сложные нелинейные зависимости через ядра
  4. Контроль над сложностью модели через параметры ε и C
  5. Глобальное решение (в отличие от нейросетей, которые могут сходиться к локальным минимумам)

Недостатки SVR

  1. Требует тщательной настройки гиперпараметров (ε, C, параметры ядра)
  2. Медленная работа на больших датасетах
  3. Плохая интерпретируемость (особенно с нелинейными ядрами)
  4. Чувствительность к масштабированию данных (обязательно нужно масштабировать признаки)

Сравнение SVR с другими методами регрессии

МетодКогда использоватьПреимущества
Linear RegressionЛинейные зависимости, интерпретируемостьБыстрый, простой для понимания
Decision TreeНелинейные зависимости, интерпретируемостьНе требует масштабирования, визуализируем
Random ForestСложные нелинейные зависимостиРобастность, меньше переобучения
SVRСложные нелинейные зависимости, выбросыУстойчивость к выбросам, контроль сложности

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

import numpy as np
import matplotlib.pyplot as plt
from sklearn.svm import SVR
from sklearn.preprocessing import StandardScaler
from sklearn.model_selection import train_test_split
from sklearn.metrics import mean_squared_error, r2_score
 
# Создаем синтетические данные
np.random.seed(42)
X = np.sort(5 * np.random.rand(100, 1), axis=0)
y = np.sin(X).ravel() + np.random.normal(0, 0.1, X.shape[0])
 
# Масштабируем данные (ВАЖНО для SVR!)
scaler_X = StandardScaler()
scaler_y = StandardScaler()
X_scaled = scaler_X.fit_transform(X)
y_scaled = scaler_y.fit_transform(y.reshape(-1, 1)).ravel()
 
# Разделяем на обучающую и тестовую выборки
X_train, X_test, y_train, y_test = train_test_split(
    X_scaled, y_scaled, test_size=0.2, random_state=42)
 
# Создаем и обучаем различные SVR модели
svr_models = {
    'SVR с RBF ядром': SVR(kernel='rbf', C=100, gamma=0.1, epsilon=0.1),
    'SVR с линейным ядром': SVR(kernel='linear', C=100, epsilon=0.1),
    'SVR с полиномиальным ядром': SVR(kernel='poly', C=100, degree=3, epsilon=0.1)
}
 
# Обучаем и оцениваем модели
plt.figure(figsize=(15, 5))
 
for i, (name, model) in enumerate(svr_models.items()):
    # Обучение
    model.fit(X_train, y_train)
    
    # Предсказание
    y_pred = model.predict(X_test)
    
    # Оценка качества
    mse = mean_squared_error(y_test, y_pred)
    r2 = r2_score(y_test, y_pred)
    
    # Визуализация
    plt.subplot(1, 3, i+1)
    
    # Сортируем для красивого графика
    X_sorted = np.sort(X_test, axis=0)
    y_pred_sorted = model.predict(X_sorted)
    
    plt.scatter(X_test, y_test, color='darkorange', label='Данные')
    plt.plot(X_sorted, y_pred_sorted, color='navy', label='SVR')
    plt.xlabel('X')
    plt.ylabel('y')
    plt.title(f'{name}\nMSE: {mse:.3f}, R²: {r2:.3f}')
    plt.legend()
 
plt.tight_layout()
plt.show()

Подбор гиперпараметров для SVR

from sklearn.model_selection import GridSearchCV
 
# Параметры для поиска
param_grid = {
    'C': [0.1, 1, 10, 100],
    'epsilon': [0.01, 0.1, 0.2, 0.5],
    'gamma': ['scale', 'auto', 0.1, 1],
    'kernel': ['rbf', 'linear', 'poly']
}
 
# Создаем SVR модель
svr = SVR()
 
# Поиск по сетке
grid_search = GridSearchCV(
    svr, param_grid, cv=5, scoring='neg_mean_squared_error', 
    n_jobs=-1, verbose=1
)
 
# Запускаем поиск
grid_search.fit(X_train, y_train)
 
# Лучшие параметры
print("Лучшие параметры:", grid_search.best_params_)
print("Лучший MSE:", -grid_search.best_score_)
 
# Используем лучшую модель
best_svr = grid_search.best_estimator_
y_pred_best = best_svr.predict(X_test)

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

Хорошие сценарии для SVR:

  • Данные с сложными нелинейными зависимостями
  • Наличие выбросов в данных
  • Высокоразмерные данные
  • Когда нужен контроль над сложностью модели

Плохие сценарии для SVR:

  • Очень большие датасеты (сотни тысяч+ примеров)
  • Требуется интерпретируемость модели
  • Ограниченные вычислительные ресурсы
  • Простые линейные зависимости

Пример применения SVR

Задача: Прогнозирование цен на недвижимость

  • Признаки: площадь, количество комнат, район, этаж и т.д.
  • Целевая переменная: цена квартиры
from sklearn.datasets import fetch_california_housing
 
# Загружаем данные о недвижимости
housing = fetch_california_housing()
X, y = housing.data, housing.target
 
# Масштабируем данные
scaler = StandardScaler()
X_scaled = scaler.fit_transform(X)
 
# Обучаем SVR
svr = SVR(kernel='rbf', C=10, epsilon=0.1)
svr.fit(X_scaled, y)
 
# Сравниваем с линейной регрессией
from sklearn.linear_model import LinearRegression
lr = LinearRegression()
lr.fit(X_scaled, y)
 
print(f"SVR R²: {svr.score(X_scaled, y):.3f}")
print(f"Linear Regression R²: {lr.score(X_scaled, y):.3f}")

Краткий итог

  • SVR — это регрессионный метод на основе SVM
  • Основная идея: Найти функцию, чтобы большинство точек лежало внутри ε-трубки
  • Ключевые параметры: ε (ширина трубки), C (регуляризация), ядро
  • Преимущества: Устойчивость к выбросам, гибкость, контроль сложности
  • Недостатки: Требует настройки, медленный на больших данных, требует масштабирования
  • Лучше всего подходит для сложных нелинейных задач с выбросами

SVR — это мощный инструмент в арсенале data scientist’а, особенно когда традиционные методы регрессии не справляются со сложными нелинейными зависимостями.