Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI29 мар. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
Методы борьбы с переобучением линейных моделей
Переобучение (Overfitting) в линейных моделях происходит, когда модель заучивает шум в тренировочных данных вместо обучения закономерностям. Для линейных моделей есть проверенные способы борьбы.
1. Основная концепция: Bias-Variance Trade-off
import numpy as np
import matplotlib.pyplot as plt
from sklearn.linear_model import LinearRegression, Ridge, Lasso
from sklearn.model_selection import learning_curve, cross_val_score
from sklearn.datasets import make_regression
from sklearn.preprocessing import PolynomialFeatures
# Генерируем данные
np.random.seed(42)
X = np.linspace(0, 10, 100).reshape(-1, 1)
y = 3*X.ravel() + np.random.normal(0, 5, 100) # Линейная зависимость + шум
# Переобучение: добавляем полиномиальные признаки
poly = PolynomialFeatures(degree=10)
X_poly = poly.fit_transform(X)
# Модели
model_simple = LinearRegression()
model_overfit = LinearRegression()
model_simple.fit(X, y)
model_overfit.fit(X_poly, y)
print("Простая линейная модель:")
print(f" Train score: {model_simple.score(X, y):.4f}")
print(f" Coef: {model_simple.coef_[0]:.4f}")
print("\nПереобученная модель (полином степени 10):")
print(f" Train score: {model_overfit.score(X_poly, y):.4f}")
print(f" Коэффициенты (первые 5): {model_overfit.coef_[:5]}")
print(f" Легко видеть: все коэффициенты разные, очень большие")
print("""
┌────────────────────────┬──────────┬──────────┐
│ Модель │ Bias │ Variance │
├────────────────────────┼──────────┼──────────┤
│ Простая линейная │ Высокий │ Низкий │
│ Полином степени 10 │ Низкий │ Высокий │
│ Ridge/Lasso │ Средний │ Средний │
└────────────────────────┴──────────┴──────────┘
""")
2. Метод 1: L2 Регуляризация (Ridge Regression)
from sklearn.linear_model import RidgeCV
from sklearn.metrics import mean_squared_error
class RidgeRegularization:
"""
Ridge Regression (L2):
Формула: ||y - Xw||^2 + alpha * ||w||^2
Что делает:
- Добавляет штраф за большие коэффициенты
- Все признаки остаются в модели (все коэффициенты != 0)
- Уменьшает амплитуду коэффициентов
"""
@staticmethod
def compare_alphas():
# Генерируем данные с переобучением
X, y = make_regression(n_samples=100, n_features=10, noise=50, random_state=42)
# Тестируем разные alpha
alphas = [0.001, 0.01, 0.1, 1, 10, 100]
results = []
for alpha in alphas:
ridge = Ridge(alpha=alpha)
# Cross-validation
cv_scores = cross_val_score(ridge, X, y, cv=5, scoring='neg_mean_squared_error')
mse = -cv_scores.mean()
ridge.fit(X, y)
# Размер коэффициентов
coef_norm = np.linalg.norm(ridge.coef_)
results.append({
'alpha': alpha,
'cv_mse': mse,
'coef_norm': coef_norm
})
for r in results:
print(f"Alpha={r['alpha']}: MSE={r['cv_mse']:.2f}, ||coef||={r['coef_norm']:.2f}")
# Best alpha
best = min(results, key=lambda x: x['cv_mse'])
print(f"\nОптимальный alpha: {best['alpha']} (MSE={best['cv_mse']:.2f})")
@staticmethod
def ridge_cv_example():
"""Автоматический выбор alpha с RidgeCV"""
X, y = make_regression(n_samples=100, n_features=10, noise=50)
# Автоматический поиск оптимального alpha
ridge_cv = RidgeCV(alphas=[0.1, 1, 10, 100], cv=5)
ridge_cv.fit(X, y)
print(f"\nОптимальный alpha: {ridge_cv.alpha_}")
print(f"Score: {ridge_cv.score(X, y):.4f}")
print(f"Коэффициенты (меньшие по амплитуде): {ridge_cv.coef_[:5]}")
RidgeRegularization.compare_alphas()
3. Метод 2: L1 Регуляризация (Lasso)
from sklearn.linear_model import LassoCV
class LassoRegularization:
"""
Lasso (L1) Regression:
Формула: ||y - Xw||^2 + alpha * ||w||_1
Что делает:
- Штраф за абсолютное значение коэффициентов
- Обнуляет некоторые коэффициенты (feature selection!)
- Автоматическая селекция признаков
"""
@staticmethod
def feature_selection():
# Данные с переобучением
X, y = make_regression(n_samples=100, n_features=20, n_informative=5, noise=50)
# LassoCV автоматически подбирает alpha
lasso_cv = LassoCV(cv=5, random_state=42)
lasso_cv.fit(X, y)
print(f"Оптимальный alpha: {lasso_cv.alpha_:.4f}")
print(f"Score: {lasso_cv.score(X, y):.4f}")
# Какие признаки обнулены
non_zero = np.sum(lasso_cv.coef_ != 0)
zero = np.sum(lasso_cv.coef_ == 0)
print(f"\nКоличество ненулевых коэффициентов: {non_zero}")
print(f"Количество нулевых коэффициентов: {zero}")
print(f"Важные признаки: {np.where(lasso_cv.coef_ != 0)[0]}")
@staticmethod
def ridge_vs_lasso():
"""
Сравнение Ridge и Lasso
"""
X, y = make_regression(n_samples=100, n_features=10, noise=50)
ridge = RidgeCV(cv=5)
lasso = LassoCV(cv=5)
ridge.fit(X, y)
lasso.fit(X, y)
print("\nRidge vs Lasso:")
print(f"Ridge - Score: {ridge.score(X, y):.4f}, Non-zero coef: {np.sum(ridge.coef_ != 0)}")
print(f"Lasso - Score: {lasso.score(X, y):.4f}, Non-zero coef: {np.sum(lasso.coef_ != 0)}")
print("""
Когда использовать:
- Ridge: когда все признаки релевантны
- Lasso: когда нужна feature selection (sparse solution)
""")
LassoRegularization.feature_selection()
LassoRegularization.ridge_vs_lasso()
4. Метод 3: Elastic Net (комбинация Ridge + Lasso)
from sklearn.linear_model import ElasticNetCV
class ElasticNetRegularization:
"""
Elastic Net:
Формула: ||y - Xw||^2 + alpha * (l1_ratio * ||w||_1 + (1-l1_ratio) * ||w||^2)
Комбинирует Ridge и Lasso:
- l1_ratio = 0: Pure Ridge
- l1_ratio = 1: Pure Lasso
- 0 < l1_ratio < 1: Комбинация обоих
"""
@staticmethod
def example():
X, y = make_regression(n_samples=100, n_features=10, noise=50)
# ElasticNetCV подбирает alpha и l1_ratio
en = ElasticNetCV(
l1_ratio=[0.1, 0.5, 0.7, 0.9, 0.95, 0.99],
cv=5,
random_state=42
)
en.fit(X, y)
print(f"\nOptimal alpha: {en.alpha_:.4f}")
print(f"Optimal l1_ratio: {en.l1_ratio_:.2f}")
print(f"Score: {en.score(X, y):.4f}")
print(f"Non-zero coefficients: {np.sum(en.coef_ != 0)}")
ElasticNetRegularization.example()
5. Метод 4: Early Stopping
from sklearn.linear_model import SGDRegressor
from sklearn.model_selection import train_test_split
class EarlyStopping:
"""
Early Stopping:
Идея: Во время обучения мониторим ошибку на validation set
Останавливаем когда validation error перестаёт улучшаться
Работает с:
- SGDRegressor, SGDClassifier (стохастический градиентный спуск)
- Любыми итеративными алгоритмами
"""
@staticmethod
def example():
X, y = make_regression(n_samples=200, n_features=10, noise=50)
X_train, X_val, y_train, y_val = train_test_split(X, y, test_size=0.2)
# SGDRegressor с early stopping
sgd = SGDRegressor(
loss='squared_error',
n_iter_no_change=10, # Остановиться если 10 итераций без улучшения
validation_fraction=0.2, # Использовать 20% для validation
early_stopping=True,
random_state=42
)
sgd.fit(X_train, y_train)
print(f"\nОбучено на {sgd.n_iter_} итерациях (early stopping)")
print(f"Train score: {sgd.score(X_train, y_train):.4f}")
print(f"Validation score: {sgd.score(X_val, y_val):.4f}")
EarlyStopping.example()
6. Метод 5: Уменьшение количества признаков
from sklearn.feature_selection import SelectKBest, f_regression
from sklearn.decomposition import PCA
class DimensionalityReduction:
"""
Борьба с переобучением через уменьшение размерности
"""
@staticmethod
def select_k_best():
"""SelectKBest: выбрать топ K признаков"""
X, y = make_regression(n_samples=100, n_features=20, n_informative=5)
# Выбираем топ 5 признаков
selector = SelectKBest(score_func=f_regression, k=5)
X_selected = selector.fit_transform(X, y)
# Какие признаки выбраны
selected_features = selector.get_support()
print(f"\nВыбранные признаки: {np.where(selected_features)[0]}")
print(f"Форма X до: {X.shape}")
print(f"Форма X после: {X_selected.shape}")
# Обучаем модель на выбранных признаках
model = LinearRegression()
cv_scores = cross_val_score(model, X_selected, y, cv=5)
print(f"CV score (5 best features): {cv_scores.mean():.4f}")
@staticmethod
def pca_example():
"""PCA: выбрать топ principal components"""
X, y = make_regression(n_samples=100, n_features=20)
# Берём 5 главных компонент (объясняют 95% variance)
pca = PCA(n_components=5)
X_pca = pca.fit_transform(X)
print(f"\nPCA - Variance explained ratio: {pca.explained_variance_ratio_.sum():.2%}")
print(f"Форма X до: {X.shape}")
print(f"Форма X после PCA: {X_pca.shape}")
model = LinearRegression()
cv_scores = cross_val_score(model, X_pca, y, cv=5)
print(f"CV score (5 PCA components): {cv_scores.mean():.4f}")
DimensionalityReduction.select_k_best()
DimensionalityReduction.pca_example()
7. Метод 6: Cross-Validation для оценки generalization
from sklearn.model_selection import cross_validate
class ProperValidation:
"""
Правильная валидация для обнаружения переобучения
"""
@staticmethod
def detect_overfitting():
X, y = make_regression(n_samples=100, n_features=10, noise=50)
# Обучаем разные модели
models = {
'Simple Linear': LinearRegression(),
'Ridge (alpha=0.1)': Ridge(alpha=0.1),
'Ridge (alpha=1)': Ridge(alpha=1),
'Ridge (alpha=100)': Ridge(alpha=100),
}
for name, model in models.items():
# Cross-validation на training set
cv_results = cross_validate(
model, X, y, cv=5,
scoring=['r2', 'neg_mean_squared_error'],
return_train_score=True
)
train_r2 = cv_results['train_r2'].mean()
test_r2 = cv_results['test_r2'].mean()
gap = train_r2 - test_r2 # Переобучение
print(f"{name}:")
print(f" Train R2: {train_r2:.4f}")
print(f" Test R2: {test_r2:.4f}")
print(f" Gap: {gap:.4f} {'(OVERFITTING!)' if gap > 0.1 else ''}")
print()
ProperValidation.detect_overfitting()
8. Сравнение методов
┌──────────────────────────┬───────────┬──────────┬──────────────┐
│ Метод │ Сложность │ Скорость │ Эффективность│
├──────────────────────────┼───────────┼──────────┼──────────────┤
│ Ridge (L2) │ Низкая │ Быстро │ Хорошая │
│ Lasso (L1) │ Средняя │ Средне │ Отличная │
│ Elastic Net │ Средняя │ Средне │ Отличная │
│ Feature Selection │ Средняя │ Быстро │ Хорошая │
│ PCA │ Средняя │ Быстро │ Хорошая │
│ Early Stopping │ Средняя │ Средне │ Отличная │
│ Cross-Validation │ Низкая │ Медленно │ Диагностика │
└──────────────────────────┴───────────┴──────────┴──────────────┘
Заключение
Методы борьбы с переобучением в линейных моделях:
- Ridge (L2): Универсальное решение, когда все признаки важны
- Lasso (L1): Когда нужна автоматическая feature selection
- Elastic Net: Комбинация, best of both worlds
- Feature Selection: SelectKBest для явного выбора признаков
- PCA: Уменьшение размерности, сохранение главного
- Early Stopping: Для итеративных алгоритмов
- Cross-Validation: Диагностика переобучения
Best Practice:
- Начни с Ridge (alpha=1.0) как baseline
- Используй RidgeCV или LassoCV для подбора гиперпараметров
- Если нужна интерпретируемость → Lasso (sparse)
- Если все признаки важны → Ridge
- Всегда используй cross-validation для оценки
- Мониторь train vs validation error
- Если gap > 0.1 → увеличивай регуляризацию