Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
Линейная регрессия: полное объяснение
Основная идея
Линейная регрессия — это метод для предсказания непрерывного значения (y) на основе одной или нескольких входных переменных (x). Модель предполагает, что зависимость между x и y линейная.
Математическое определение
Для простой линейной регрессии (одна переменная):
y = β₀ + β₁*x + ε
Где:
y = целевая переменная (continuous value)
x = входная переменная
β₀ = intercept (смещение, точка где линия пересекает ось Y)
β₁ = slope (наклон, как y меняется при изменении x на 1 единицу)
ε = ошибка (error term, шум)
Для множественной линейной регрессии (несколько переменных):
y = β₀ + β₁*x₁ + β₂*x₂ + ... + βₙ*xₙ + ε
В матричной форме:
y = X * β + ε
Где:
X = матрица признаков (n_samples × n_features)
β = вектор коэффициентов (n_features × 1)
ε = вектор ошибок (n_samples × 1)
Как работает обучение
Цель: найти коэффициенты β₀, β₁, ..., βₙ, которые минимизируют ошибку.
Функция потерь (Loss function) — Mean Squared Error (MSE):
MSE = (1/n) * Σ(y_pred - y_actual)²
= (1/n) * Σ(β₀ + β₁*x₁ + ... + βₙ*xₙ - y)²
Где:
n = количество примеров
Σ = сумма по всем примерам
Мы хотим найти β, которые минимизируют эту функцию.
Методы решения
1. Аналитическое решение (Closed-form) — Normal Equation
Это математическое решение, которое находит оптимальные β напрямую:
# Normal Equation
β = (X^T * X)^(-1) * X^T * y
Где:
X^T = транспонированная матрица X
(X^T*X)^(-1) = обратная матрица
Пример в Python:
import numpy as np
from numpy.linalg import inv
# Добавляем column of 1s для intercept
X = np.column_stack([np.ones(n), X_original])
# Вычисляем коэффициенты
beta = inv(X.T @ X) @ X.T @ y
Преимущества:
- Находит оптимальное решение за один раз
- Быстро для малого количества признаков
Недостатки:
- Если матрица X^T*X не invertible (сингулярна) — падает
- Сложно для больших наборов данных (O(n³) сложность)
- Чувствительна к multicollinearity
2. Градиентный спуск (Gradient Descent)
Итеративный метод: мы начинаем с случайных β и постепенно их улучшаем.
# Gradient Descent
Шаг 1: Инициализируем β случайно (или нулями)
Шаг 2: Для каждой итерации t = 1, 2, ..., T:
a) Вычисляем gradient (производную MSE по β):
dL/dβ = (2/n) * X^T * (X*β - y)
b) Обновляем β в направлении противоположном градиенту:
β ← β - α * dL/dβ
Где α = learning rate (как быстро мы обновляем)
Шаг 3: Повторяем, пока loss не сходится
Варианты градиентного спуска:
# Batch Gradient Descent
# Используем ВСЕ данные для одного обновления β
beta = beta - learning_rate * gradient(X, y, beta)
# Результат: плавная, стабильная сходимость, но медленно
# Stochastic Gradient Descent (SGD)
# Используем ОДИН random пример для обновления
for i in range(n):
random_idx = random.randint(0, n-1)
x_i = X[random_idx]
y_i = y[random_idx]
beta = beta - learning_rate * gradient(x_i, y_i, beta)
# Результат: быстро, но шумно, может не сойтись
# Mini-batch Gradient Descent (лучший вариант)
batch_size = 32
for batch_idx in range(0, n, batch_size):
X_batch = X[batch_idx:batch_idx+batch_size]
y_batch = y[batch_idx:batch_idx+batch_size]
beta = beta - learning_rate * gradient(X_batch, y_batch, beta)
# Результат: хороший баланс между скоростью и стабильностью
Преимущества:
- Работает для больших датасетов
- Понятный процесс
- Гибкий (легко добавить регуляризацию)
Недостатки:
- Нужно выбрать learning rate
- Может застрять в локальном минимуме (но для линейной регрессии не существует локальных минимумов)
Реализация в Python
from sklearn.linear_model import LinearRegression
import numpy as np
# Создаём модель
model = LinearRegression()
# Обучаем на data
model.fit(X_train, y_train)
# Предсказываем
y_pred = model.predict(X_test)
# Коэффициенты
print("Intercept (β₀):", model.intercept_)
print("Coefficients (β₁, β₂, ...):", model.coef_)
Требования и предположения
Для хорошей работы линейной регрессии нужны:
-
Linearity — связь между X и y должна быть линейной
- Проверка: scatter plot
- Если нелинейная — добавь polynomial features
-
Independence — примеры должны быть независимы
- Проверка: ACF plot (для временных рядов)
- Если зависимы — используй другие методы (ARIMA, LSTM)
-
Homoscedasticity — дисперсия ошибок должна быть постоянной
- Проверка: residuals plot
- Если нарушено — используй weighted regression
-
Normality — ошибки должны распределяться нормально
- Проверка: Q-Q plot
- Если нарушено — может помочь log-трансформация y
-
No multicollinearity — признаки не должны быть сильно скоррелированы
- Проверка: VIF (Variance Inflation Factor) < 5
- Если нарушено — удали коррелированные признаки или используй Ridge/Lasso
Регуляризация
Проблема: если у нас много признаков, модель может переобучиться
Ridge Regression (L2):
Loss = MSE + λ * Σ(β²) # Штрафуем большие коэффициенты
model = Ridge(alpha=1.0)
Lasso Regression (L1):
Loss = MSE + λ * Σ|β| # Может обнулить коэффициенты
model = Lasso(alpha=1.0)
Elastic Net (L1 + L2):
Loss = MSE + λ₁ * Σ|β| + λ₂ * Σ(β²)
model = ElasticNet(alpha=1.0, l1_ratio=0.5)
Метрики качества
from sklearn.metrics import mean_squared_error, r2_score, mean_absolute_error
# MSE (Mean Squared Error) — средняя квадратная ошибка
mse = mean_squared_error(y_test, y_pred)
# RMSE (Root MSE) — корень из MSE, в тех же единицах что y
rmse = np.sqrt(mse)
# MAE (Mean Absolute Error) — средняя абсолютная ошибка
mae = mean_absolute_error(y_test, y_pred)
# R² score — доля дисперсии, которую объясняет модель (0-1)
r2 = r2_score(y_test, y_pred)
# R² = 0.9 → модель объясняет 90% дисперсии
Когда использовать
-
Используй когда:
- Зависимость между x и y линейная
- Нужна интерпретируемая модель
- Мало данных или признаков
- Нужна быстрая модель
-
Не используй когда:
- Зависимость нелинейная
- Очень много признаков (используй Ridge/Lasso)
- Нужна максимальная точность (tree-based методы обычно лучше)