← Назад к вопросам

Какие знаешь изменяемые типы данных?

1.0 Junior🔥 111 комментариев
#Python

Комментарии (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         │ Низкая    │ Медленно  │ Диагностика  │
└──────────────────────────┴───────────┴──────────┴──────────────┘

Заключение

Методы борьбы с переобучением в линейных моделях:

  1. Ridge (L2): Универсальное решение, когда все признаки важны
  2. Lasso (L1): Когда нужна автоматическая feature selection
  3. Elastic Net: Комбинация, best of both worlds
  4. Feature Selection: SelectKBest для явного выбора признаков
  5. PCA: Уменьшение размерности, сохранение главного
  6. Early Stopping: Для итеративных алгоритмов
  7. Cross-Validation: Диагностика переобучения

Best Practice:

  • Начни с Ridge (alpha=1.0) как baseline
  • Используй RidgeCV или LassoCV для подбора гиперпараметров
  • Если нужна интерпретируемость → Lasso (sparse)
  • Если все признаки важны → Ridge
  • Всегда используй cross-validation для оценки
  • Мониторь train vs validation error
  • Если gap > 0.1 → увеличивай регуляризацию
Какие знаешь изменяемые типы данных? | PrepBro