Ответ
В своих проектах я применяю комбинацию методов для борьбы с переобучением, начиная с простых и переходя к более сложным:
1. Регуляризация — добавляю штраф за сложность модели:
# L1 (Lasso) и L2 (Ridge) регуляризация
from sklearn.linear_model import LogisticRegression
# L1 регуляризация - для отбора признаков
l1_model = LogisticRegression(
penalty='l1',
C=0.1, # обратная сила регуляризации
solver='liblinear'
)
# L2 регуляризация - для уменьшения весов
l2_model = LogisticRegression(
penalty='l2',
C=0.1,
solver='lbfgs',
max_iter=1000
)
# ElasticNet - комбинация L1 и L2
from sklearn.linear_model import ElasticNet
elastic_model = ElasticNet(
alpha=0.1,
l1_ratio=0.5 # 0.5 = 50% L1, 50% L2
)
2. Ранняя остановка (Early Stopping) — для итеративных алгоритмов:
# Для Gradient Boosting
import xgboost as xgb
xgb_model = xgb.XGBClassifier(
n_estimators=1000, # Ставим большое число
early_stopping_rounds=50,
eval_metric='logloss',
eval_set=[(X_val, y_val)] # Валидационный набор
)
# Для нейросетей в TensorFlow/Keras
import tensorflow as tf
early_stopping = tf.keras.callbacks.EarlyStopping(
monitor='val_loss',
patience=10,
restore_best_weights=True # Важно: восстанавливаем лучшие веса
)
model.fit(X_train, y_train,
validation_data=(X_val, y_val),
epochs=100,
callbacks=[early_stopping],
verbose=0)
3. Dropout — для нейронных сетей:
model = tf.keras.Sequential([
tf.keras.layers.Dense(128, activation='relu'),
tf.keras.layers.Dropout(0.5), # 50% нейронов отключаются случайно
tf.keras.layers.Dense(64, activation='relu'),
tf.keras.layers.Dropout(0.3), # 30% отключаются
tf.keras.layers.Dense(10, activation='softmax')
])
4. Аугментация данных — для изображений и текстов:
# Для изображений
from tensorflow.keras.preprocessing.image import ImageDataGenerator
datagen = ImageDataGenerator(
rotation_range=20,
width_shift_range=0.2,
height_shift_range=0.2,
shear_range=0.2,
zoom_range=0.2,
horizontal_flip=True,
fill_mode='nearest'
)
5. Упрощение модели:
# Для деревьев
from sklearn.tree import DecisionTreeClassifier
simple_tree = DecisionTreeClassifier(
max_depth=5, # Ограничиваем глубину
min_samples_split=20, # Минимум samples для разделения
min_samples_leaf=10 # Минимум samples в листе
)
# Для нейросетей
simple_nn = tf.keras.Sequential([
tf.keras.layers.Dense(32, activation='relu'), # Меньше нейронов
tf.keras.layers.Dense(16, activation='relu'),
tf.keras.layers.Dense(1, activation='sigmoid')
])
6. Кросс-валидация — для надежной оценки:
from sklearn.model_selection import cross_val_score
scores = cross_val_score(
estimator=model,
X=X_train,
y=y_train,
cv=5, # 5-fold кросс-валидация
scoring='accuracy',
n_jobs=-1
)
print(f"Средняя accuracy: {scores.mean():.3f} (±{scores.std():.3f})")
7. Batch Normalization — стабилизация обучения нейросетей:
model = tf.keras.Sequential([
tf.keras.layers.Dense(128),
tf.keras.layers.BatchNormalization(), # Нормализуем активации
tf.keras.layers.Activation('relu'),
tf.keras.layers.Dropout(0.5)
])
Моя стратегия:
- Начинаю с кросс-валидации и мониторинга разницы train/val ошибок
- Для линейных моделей → регуляризация (L1 если нужно отобрать признаки, L2 если нет)
- Для деревьев → ограничение глубины и минимального размера узлов
- Для бустинга → ранняя остановка + небольшая скорость обучения
- Для нейросетей → dropout + batch normalization + early stopping
- Для изображений → аугментация + dropout
Важнее всего понимать, почему модель переобучается: мало данных, слишком сложная модель или шумные признаки. Диагностика определяет лечение.