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

В каких ситуациях линейная модель неудачна?

2.0 Middle🔥 111 комментариев
#Машинное обучение#Статистика и A/B тестирование

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI30 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Когда линейная модель неудачна

Ситуация 1: Нелинейная зависимость

Истинная зависимость между X и y не является линейной. Линейная модель даст низкий R².

import numpy as np
from sklearn.linear_model import LinearRegression
from sklearn.preprocessing import PolynomialFeatures

# Данные с синусоидальной зависимостью
X = np.linspace(0, 10, 100).reshape(-1, 1)
y = np.sin(X).ravel() + np.random.normal(0, 0.1, 100)

# Линейная модель
model_linear = LinearRegression()
model_linear.fit(X, y)
print(f"Linear R²: {model_linear.score(X, y):.3f}")  # ~0.002

# С полиномиальными признаками
features = PolynomialFeatures(degree=3)
X_poly = features.fit_transform(X)
model_poly = LinearRegression()
model_poly.fit(X_poly, y)
print(f"Poly R²: {model_poly.score(X_poly, y):.3f}")  # ~0.99

Ситуация 2: Мультиколлинеарность

Признаки сильно коррелированы. Коэффициенты становятся нестабильными и непредсказуемыми.

import pandas as pd
from statsmodels.stats.outliers_influence import variance_inflation_factor

X = np.random.randn(100, 3)
X[:, 1] = X[:, 0] + np.random.normal(0, 0.1, 100)  # Почти копия X[:, 0]
X[:, 2] = X[:, 0] * 2

df = pd.DataFrame(X, columns=['X1', 'X2', 'X3'])
vif = [variance_inflation_factor(X, i) for i in range(3)]
print(f"VIF: {vif}")  # > 10 указывает на проблему

# Решение: Ridge Regression
from sklearn.linear_model import Ridge
model = Ridge(alpha=1.0)
model.fit(X, y)

Ситуация 3: Выбросы

Линейная регрессия очень чувствительна к экстремальным значениям, которые сильно влияют на наклон линии.

# С выбросом в конце
y_with_outlier = y.copy()
y_with_outlier[-1] = 100

model = LinearRegression()
model.fit(X, y_with_outlier)

# Решение: HuberRegressor
from sklearn.linear_model import HuberRegressor
model_robust = HuberRegressor(epsilon=1.35)
model_robust.fit(X, y_with_outlier)

Ситуация 4: Взаимодействие признаков

Эффект одного признака зависит от значения другого. Например, цена зависит от площади * качество локации.

# Истинная зависимость с взаимодействием
X = np.random.randn(100, 2)
y = X[:, 0] * X[:, 1] + np.random.normal(0, 0.5, 100)

model_simple = LinearRegression()
model_simple.fit(X, y)
print(f"R² без взаимодействия: {model_simple.score(X, y):.3f}")

# Добавляем interaction term
X_with_interaction = np.column_stack([X, X[:, 0] * X[:, 1]])
model_int = LinearRegression()
model_int.fit(X_with_interaction, y)
print(f"R² с взаимодействием: {model_int.score(X_with_interaction, y):.3f}")

Ситуация 5: Гетероскедастичность

Дисперсия ошибок непостоянна и зависит от X. Модель неправильно оценивает доверительные интервалы.

# Дисперсия растёт с X
y = 2 * X.ravel() + np.random.normal(0, X.ravel(), 100)

# Решение: Weighted Least Squares
from sklearn.linear_model import LinearRegression
model = LinearRegression()
model.fit(X, y)
residuals = y - model.predict(X)

# Взвешиваем по дисперсии
weights = 1 / (np.abs(residuals) + 0.01)
model_weighted = LinearRegression()
model_weighted.fit(X, y, sample_weight=weights)

Ситуация 6: Автокорреляция остатков

Особенно актуально для временных рядов. Текущая ошибка коррелирует с предыдущей.

# Временной ряд с автокоррелированными ошибками
time = np.arange(100).reshape(-1, 1)
y = 2 * time.ravel() + np.cumsum(np.random.normal(0, 1, 100))

# Решение: ARIMA для временных рядов
from statsmodels.tsa.arima.model import ARIMA
model = ARIMA(y, order=(1, 1, 1))
fitted = model.fit()

Ситуация 7: Недостаточно данных (N < D)

Количество примеров меньше количества признаков. Модель переполняется и получает идеальный training score.

# 10 примеров, 1000 признаков
X_small = np.random.randn(10, 1000)
y_small = np.random.randn(10)

model = LinearRegression()
model.fit(X_small, y_small)
print(f"Training R²: {model.score(X_small, y_small):.3f}")  # 1.0 (переполнение!)

# Решение: Lasso для отбора признаков
from sklearn.linear_model import Lasso
model_lasso = Lasso(alpha=0.1)
model_lasso.fit(X_small, y_small)

Ситуация 8: Категориальные переменные без обработки

Строки нельзя передавать прямо в linear regression. Нужна кодировка.

import pandas as pd

df = pd.DataFrame({
    'city': ['New York', 'Los Angeles', 'Chicago'],
    'price': [500000, 600000, 400000]
})

# One-Hot Encoding
X = pd.get_dummies(df[['city']])
# city_Chicago | city_Los Angeles | city_New York
#           0  |               0  |            1
#           0  |               1  |            0
#           1  |               0  |            0

Ситуация 9: Несбалансированные классы (классификация)

При LogisticRegression с дисбалансом (99% класса 0, 1% класса 1) модель почти всё классифицирует как 0.

from sklearn.linear_model import LogisticRegression
from sklearn.datasets import make_classification

X, y = make_classification(n_samples=1000, weights=[0.99, 0.01])

# Без балансировки
model = LogisticRegression()
model.fit(X, y)

# Решение: class_weight='balanced'
model_balanced = LogisticRegression(class_weight='balanced')
model_balanced.fit(X, y)

Ситуация 10: Сложные нелинейные взаимодействия

y зависит от сложных комбинаций и нелинейных трансформаций X.

# Сложная нелинейность
X = np.random.randn(100, 3)
y = (X[:, 0]**2) * np.exp(X[:, 1]) + np.sin(X[:, 2]) + noise

model_linear = LinearRegression()
print(f"Linear R²: {model_linear.score(X, y):.3f}")  # Низкий

# Решение: GradientBoosting
from sklearn.ensemble import GradientBoostingRegressor
model_gb = GradientBoostingRegressor()
model_gb.fit(X, y)
print(f"GBM R²: {model_gb.score(X, y):.3f}")  # Намного выше

Как выявить проблемы

  1. Визуализация: scatter plot показывает нелинейность
  2. Остатки: plot остатков vs предсказания показывает паттерны
  3. VIF: > 10 означает мультиколлинеарность
  4. Durbin-Watson: < 2 означает автокорреляцию
  5. Q-Q plot: отклонения от нормального распределения

Практический совет

Если R² < 0.6 и данные выглядят нелинейно:

  • Используй Polynomial Features или Splines
  • Попробуй Tree-based модели (RandomForest, GBM)
  • Используй Neural Networks для сложных зависимостей

Линейная модель — хороший baseline, но не универсальное решение.

В каких ситуациях линейная модель неудачна? | PrepBro