Как выбрать гиперпараметры модели?
Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
Как выбрать гиперпараметры модели?
Выбор гиперпараметров (hyperparameter tuning) — это одна из самых критических задач в machine learning. Неправильный выбор может привести к переобучению, недообучению или просто к субоптимальному качеству модели. Давайте разберём все методы и лучшие практики.
Основные типы гиперпараметров
Для модели линейной регрессии с регуляризацией:
- Коэффициент регуляризации (alpha, lambda): контролирует силу штрафа
- Тип регуляризации: L1 (Lasso), L2 (Ridge), ElasticNet
Для Random Forest:
- n_estimators: количество деревьев
- max_depth: максимальная глубина дерева
- min_samples_split: минимум samples для разделения узла
- min_samples_leaf: минимум samples в листе
Для нейронных сетей:
- learning_rate: скорость обучения
- batch_size: размер батча
- number of layers: количество слоёв
- units per layer: количество нейронов в слое
Метод 1: Grid Search (Сетка параметров)
Grid Search — это исчерпывающий поиск по предопределённой сетке значений.
from sklearn.model_selection import GridSearchCV
from sklearn.ensemble import RandomForestClassifier
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
# Загрузка данных
X, y = load_iris(return_X_y=True)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2)
# Определяем сетку параметров
param_grid = {
'n_estimators': [10, 50, 100, 200],
'max_depth': [None, 5, 10, 15],
'min_samples_split': [2, 5, 10],
'min_samples_leaf': [1, 2, 4]
}
# GridSearchCV
grid_search = GridSearchCV(
RandomForestClassifier(random_state=42),
param_grid,
cv=5, # 5-fold cross-validation
n_jobs=-1, # используй все ядра
verbose=1
)
grid_search.fit(X_train, y_train)
print(f"Лучшие параметры: {grid_search.best_params_}")
print(f"Лучшая точность (CV): {grid_search.best_score_:.4f}")
print(f"Точность на тестовом наборе: {grid_search.score(X_test, y_test):.4f}")
# Доступ к результатам
results_df = pd.DataFrame(grid_search.cv_results_)
print(results_df[['param_n_estimators', 'param_max_depth', 'mean_test_score']].head(10))
Преимущества:
- Гарантированно найдёт лучшие параметры из сетки
- Легко использовать
- Хорошо распараллеливается
Недостатки:
- Экспоненциальный рост вычислений с количеством параметров
- Неэффективен для непрерывных параметров
- С 4 параметрами по 5 значений = 625 моделей!
Метод 2: Random Search (Случайный поиск)
Random Search — случайная выборка из параметров.
from sklearn.model_selection import RandomizedSearchCV
import scipy.stats as stats
# Распределения для параметров
param_distributions = {
'n_estimators': stats.randint(10, 200),
'max_depth': [None, 5, 10, 15, 20, 30],
'min_samples_split': stats.randint(2, 20),
'min_samples_leaf': stats.randint(1, 10),
'max_features': ['sqrt', 'log2']
}
# RandomizedSearchCV
random_search = RandomizedSearchCV(
RandomForestClassifier(random_state=42),
param_distributions,
n_iter=50, # только 50 комбинаций вместо 625
cv=5,
n_jobs=-1,
random_state=42
)
random_search.fit(X_train, y_train)
print(f"Лучшие параметры: {random_search.best_params_}")
print(f"Лучшая точность (CV): {random_search.best_score_:.4f}")
Преимущества:
- Много быстрее GridSearch
- Хорошо исследует пространство параметров
- Может быть столь же эффективен при правильном количестве итераций
Недостатки:
- Не гарантирует нахождение оптимума
- Требует больше итераций для гарантии качества
Метод 3: Bayesian Optimization (Оптимизация Байеса)
Bayesian Optimization — использует вероятностную модель для умного выбора параметров.
from skopt import BayesSearchCV
from skopt.space import Integer, Categorical
from sklearn.ensemble import RandomForestClassifier
# Определяем пространство поиска
search_spaces = {
'n_estimators': Integer(10, 200),
'max_depth': Integer(5, 30),
'min_samples_split': Integer(2, 20),
'min_samples_leaf': Integer(1, 10),
'max_features': Categorical(['sqrt', 'log2', None])
}
# BayesSearchCV
bayes_search = BayesSearchCV(
RandomForestClassifier(random_state=42),
search_spaces,
n_iter=20, # намного меньше итераций нужно
cv=5,
n_jobs=-1,
random_state=42,
verbose=1
)
bayes_search.fit(X_train, y_train)
print(f"Лучшие параметры: {bayes_search.best_params_}")
print(f"Лучшая точность: {bayes_search.best_score_:.4f}")
Преимущества:
- Очень эффективен: требует намного меньше итераций
- Использует информацию из предыдущих итераций
- Может работать с непрерывными параметрами
Недостатки:
- Сложнее в использовании
- Требует установки дополнительных библиотек (scikit-optimize)
Метод 4: Optuna (Современный подход)
Optuna — фреймворк для гиперпараметрической оптимизации с поддержкой pruning.
import optuna
from sklearn.ensemble import RandomForestClassifier
from sklearn.model_selection import cross_val_score
def objective(trial):
# Определяем параметры
n_estimators = trial.suggest_int('n_estimators', 10, 200)
max_depth = trial.suggest_int('max_depth', 5, 30)
min_samples_split = trial.suggest_int('min_samples_split', 2, 20)
min_samples_leaf = trial.suggest_int('min_samples_leaf', 1, 10)
max_features = trial.suggest_categorical('max_features', ['sqrt', 'log2'])
# Создаём модель
clf = RandomForestClassifier(
n_estimators=n_estimators,
max_depth=max_depth,
min_samples_split=min_samples_split,
min_samples_leaf=min_samples_leaf,
max_features=max_features,
random_state=42
)
# Вычисляем кросс-валидацию
scores = cross_val_score(clf, X_train, y_train, cv=5, scoring='accuracy')
return scores.mean()
# Создаём study
study = optuna.create_study(direction='maximize')
study.optimize(objective, n_trials=50)
print(f"Лучшие параметры: {study.best_params}")
print(f"Лучшая точность: {study.best_value:.4f}")
# Визуализация
optuna.visualization.plot_optimization_history(study).show()
Преимущества:
- Очень гибкий и мощный
- Поддерживает pruning (отсекает плохие ветки)
- Хорошо документирован
- Простой API
Лучшие практики выбора гиперпараметров
1. Стратегия поиска
# Стратегия 1: Грубый поиск -> Тонкий поиск
# Сначала GridSearch с широким диапазоном
coarse_params = {
'n_estimators': [50, 100, 200],
'max_depth': [5, 15, 30]
}
# Потом RandomSearch в узком диапазоне
fine_params = {
'n_estimators': stats.randint(80, 150),
'max_depth': stats.randint(10, 20)
}
2. Кросс-валидация
# Используй StratifiedKFold для несбалансированных классов
from sklearn.model_selection import StratifiedKFold
cv = StratifiedKFold(n_splits=5, shuffle=True, random_state=42)
# Или TimeSeriesSplit для временных рядов
from sklearn.model_selection import TimeSeriesSplit
tscv = TimeSeriesSplit(n_splits=5)
3. Масштабирование параметров
# Логарифмическое масштабирование для некоторых параметров
from sklearn.model_selection import GridSearchCV
import numpy as np
param_grid = {
'C': np.logspace(-4, 4, 20), # от 10^-4 до 10^4
'gamma': np.logspace(-3, 3, 20)
}
4. Ранняя остановка для итеративных моделей
from sklearn.ensemble import GradientBoostingClassifier
from sklearn.model_selection import learning_curve
# Gradient Boosting с validation_fraction и n_iter_no_change
gb = GradientBoostingClassifier(
n_estimators=500,
learning_rate=0.1,
validation_fraction=0.2,
n_iter_no_change=10, # ранняя остановка
tol=1e-4,
random_state=42
)
Сравнение методов по скорости
| Метод | Скорость | Качество | Сложность |
|---|---|---|---|
| Grid Search | Медленно | Хорошо | Низкая |
| Random Search | Быстро | Хорошо | Низкая |
| Bayesian Optimization | Очень быстро | Отлично | Средняя |
| Optuna | Очень быстро | Отлично | Средняя |
| Halving Grid Search | Быстро | Отлично | Средняя |
Итоговая рекомендация
- Для быстрого прототипирования: Random Search (50-100 итераций)
- Для production моделей: Optuna или Bayesian Optimization (20-50 итераций)
- Для маленьких пространств параметров: Grid Search
- Для больших моделей (LightGBM, XGBoost): Optuna с pruning
# Практический шаблон
from optuna import create_study
from optuna.pruners import MedianPruner
from optuna.samplers import TPESampler
study = create_study(
direction='maximize',
sampler=TPESampler(seed=42),
pruner=MedianPruner()
)
study.optimize(objective, n_trials=50, n_jobs=-1)
best_model = train_final_model(study.best_params)
Вывод: выбор метода зависит от размера пространства параметров и доступных вычислительных ресурсов. Для большинства случаев рекомендуется Optuna или Bayesian Optimization как оптимальный баланс скорости и качества.