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
- Устойчивость к выбросам: Только опорные векторы влияют на модель
- Эффективность в высокоразмерных пространствах
- Гибкость: Возможность моделировать сложные нелинейные зависимости через ядра
- Контроль над сложностью модели через параметры ε и C
- Глобальное решение (в отличие от нейросетей, которые могут сходиться к локальным минимумам)
Недостатки SVR
- Требует тщательной настройки гиперпараметров (ε, C, параметры ядра)
- Медленная работа на больших датасетах
- Плохая интерпретируемость (особенно с нелинейными ядрами)
- Чувствительность к масштабированию данных (обязательно нужно масштабировать признаки)
Сравнение 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’а, особенно когда традиционные методы регрессии не справляются со сложными нелинейными зависимостями.