Машинное обучение Линейная и логистическая регрессия
0%

Линейная и логистическая регрессия

Линейная и логистическая регрессия

Если из всего машинного обучения оставить только два алгоритма, разумно оставить именно эти. Линейная регрессия — это скелет, на который натянуто почти всё остальное: нейросеть без активаций сворачивается в линейную регрессию, градиентный бустинг складывает деревья почти так же, как линейная модель складывает признаки, а последний слой любого классификатора — это логистическая (или softmax) регрессия. Понять эти две модели по-настоящему глубоко дешевле, чем выучить двадцать других по верхам.

Мы разберём: почему минимизируется именно квадрат ошибки, что означает нормальное уравнение геометрически, когда его нельзя решать «в лоб», как регуляризация чинит мультиколлинеарность, почему для классификации нельзя брать MSE, откуда берётся сигмоида и log-loss, как читать коэффициенты и что ломается в проде.

Предполагается, что вы уже знакомы с матричной записью и градиентами (математика для ML) и с подготовкой признаков (данные и признаки) — масштабирование и кодирование категорий здесь влияют на результат сильнее, чем выбор солвера.


1. Постановка: что вообще значит «линейная модель»

Есть выборка из n объектов, каждый описан d числовыми признаками. Складываем их в матрицу плана (design matrix) X размера n × d и вектор ответов y длины n. Модель предполагает:

ŷ_i = w₁·x_i1 + w₂·x_i2 + … + w_d·x_id + b = wᵀx_i + b

Слово «линейная» относится к параметрам, а не к признакам. Модель y = w₁·x + w₂·x² + w₃·log x — по-прежнему линейная регрессия: она линейна по w. Это ключ к тому, что линейные модели вовсе не обречены рисовать прямые: нелинейность заводится через признаки (полиномы, сплайны, бинаризация, взаимодействия), а математика обучения остаётся простой и выпуклой. Ровно эту идею позже доводит до предела ядерный трюк — метод опорных векторов.

Свободный член b (intercept, смещение) удобно спрятать в веса: добавляем к X столбец из единиц и работаем с w ∈ R^(d+1). Дальше в формулах я пишу просто Xw.

Что мы оптимизируем

Функция потерь MSE (mean squared error):

L(w) = (1/n) · Σ_i (y_i − xᵢᵀw)²  =  (1/n) · ‖y − Xw‖²

Почему квадрат, а не модуль? Три независимых аргумента, и их полезно держать в голове, потому что каждый подсказывает, когда квадрат — плохая идея.

  1. Вероятностный. Предположим y = Xw + ε, где шум ε ~ N(0, σ²) независим по объектам. Тогда логарифм правдоподобия равен −(1/2σ²)·‖y − Xw‖² + const, и максимизация правдоподобия (MLE) тождественна минимизации MSE. То есть МНК — это не «просто удобно», а точная оценка при гауссовом шуме. Если шум тяжелохвостый (выбросы), допущение ломается — отсюда чувствительность МНК к выбросам и существование Huber/quantile-регрессии.
  2. Геометрический. Квадрат нормы = евклидово расстояние, а минимум расстояния до линейного подпространства даёт ортогональную проекцию (см. ниже). Красиво и решается точно.
  3. Вычислительный. MSE — гладкая выпуклая квадратичная функция: у неё один минимум, аналитическое решение и простой градиент. |·| не дифференцируем в нуле.

Минимизация MSE даёт условное среднее E[y|x], минимизация MAE — условную медиану. Это не стилистика, а разные бизнес-ответы: для прогноза выручки медиана устойчивее, для суммарных величин корректнее среднее.


2. Геометрия МНК и нормальное уравнение

Множество всех предсказаний, которые модель вообще способна выдать, — это col(X), линейная оболочка столбцов X, подпространство размерности rank(X) ≤ d внутри R^n. Вектор y почти наверняка лежит вне него. Тогда «лучшая» модель — ближайшая точка подпространства, то есть ортогональная проекция y на col(X).

МНК как ортогональная проекция вектора ответов на пространство столбцов

Условие ортогональности остатка ко всем столбцам — это и есть нормальное уравнение:

Xᵀ(y − Xw) = 0   ⇔   XᵀX·w = Xᵀy   ⇔   w* = (XᵀX)⁻¹Xᵀy   (если XᵀX обратима)

Формально это же получается приравниванием градиента к нулю: ∇L = −(2/n)·Xᵀ(y − Xw) = 0. Матрица H = X(XᵀX)⁻¹Xᵀ называется hat-матрицей и является проектором: H² = H. Её диагональные элементы (leverage) показывают, насколько сильно конкретный объект тянет модель на себя, — это стандартный инструмент поиска влиятельных выбросов.

Из проекционной картины сразу следуют полезные факты:

  • Если в модели есть свободный член, сумма остатков ровно ноль, и линия проходит через центроид (x̄, ȳ).
  • R² = 1 − ‖e‖²/‖y − ȳ‖² — доля дисперсии, «объяснённая» проекцией, по теореме Пифагора.
  • Добавление любого нового признака никогда не увеличивает ‖e‖ на обучении: подпространство только расширяется. Отсюда бесполезность для выбора модели и существование adjusted .

Сложность и почему inv() — плохая идея

Способ Время Память Комментарий
Нормальное уравнение через inv O(nd² + d³) O(d²) численно худший вариант
Разложение Холецкого XᵀX O(nd² + d³/3) O(d²) быстро, но обусловленность в квадрате
QR-разложение X O(nd²) O(nd) дефолт для плотных задач
SVD X O(nd²) (с бо́льшей константой) O(nd) устойчиво даже при вырожденности
Градиентный спуск / SGD O(nd) за эпоху O(d) единственный вариант при огромных n

Ключевой численный факт: число обусловленности возводится в квадрат при переходе к XᵀX (cond(XᵀX) = cond(X)²). Если признаки коррелированы и cond(X) ≈ 10⁸, то XᵀX в double-точности уже практически вырождена. Поэтому LAPACK и scipy.linalg.lstsq решают задачу через QR или SVD напрямую по X, минуя XᵀX. numpy.linalg.lstsq использует SVD-подход (gelsd) и корректно возвращает решение минимальной нормы даже для вырожденной X; np.linalg.inv(X.T @ X) в этом случае просто взорвётся. Правило: никогда не пишите inv в продакшн-коде, пишите solve/lstsq.

При d > n (тексты, геномика) XᵀX вырождена принципиально: решений бесконечно много, и нужен либо отбор признаков, либо регуляризация — о ней ниже.


3. Градиентный спуск: когда точного решения не хватает

Аналитика прекрасна до d ~ 10⁴. Дальше O(d³) и матрица d × d в памяти становятся неподъёмными, а данные могут вообще не помещаться в RAM. Тогда — итеративные методы.

градиент MSE:      ∇L(w) = (2/n)·Xᵀ(Xw − y)
шаг:               w ← w − η·∇L(w)

Скорость сходимости batch-градиентного спуска на квадратичной задаче определяется числом обусловленности κ = λ_max/λ_min матрицы XᵀX: ошибка убывает как ((κ−1)/(κ+1))^t. Практический вывод, который стоит выучить наизусть: если признаки не масштабированы, линии уровня — вытянутый овраг, и спуск будет зигзагом ползти к минимуму сотнями итераций. Стандартизация (StandardScaler) — не косметика, а прямое ускорение обучения на порядки. Подробности про масштабирование и утечки при его подгонке — см. данные и признаки.

Варианты спуска и их ниши:

  • Batch GD — точный градиент по всей выборке, стабильно, но одна итерация стоит O(nd).
  • SGD — шаг по одному объекту; шумно, зато делает n обновлений за проход. Требует расписания шага (η_t = η₀/(1+λt)) и, как правило, усреднения весов в конце.
  • Mini-batch (32–1024) — компромисс и де-факто стандарт; хорошо векторизуется.
  • L-BFGS — квазиньютоновский метод, дефолт sklearn для логистической регрессии: приближает кривизну без хранения d × d гессиана.

4. Допущения и диагностика: где линейная регрессия врёт

Теорема Гаусса — Маркова говорит: если ошибки имеют нулевое среднее, одинаковую дисперсию и не коррелированы, то МНК — лучшая линейная несмещённая оценка (BLUE). Каждое нарушение имеет узнаваемый симптом.

Допущение Нарушение Симптом Что делать
Линейность по признакам кривая зависимость остатки «улыбаются» на графике e vs ŷ сплайны, полиномы, лог-таргет, деревья
Гомоскедастичность дисперсия растёт с ŷ «воронка» на графике остатков log(y), WLS, робастные ст. ошибки
Независимость ошибок автокорреляция ряд, панель, кластеры ARIMA/бустинг (временные ряды), кластерные ошибки
Нет мультиколлинеарности x₁ ≈ 2x₂ огромные веса разных знаков, VIF > 10 Ridge, PCA (снижение размерности), выкинуть дубль
Нормальность шума тяжёлые хвосты выбросы тянут линию Huber, RANSAC, квантильная регрессия

Про мультиколлинеарность стоит сказать отдельно, потому что это главная практическая боль. Если два признака почти линейно зависимы, XᵀX почти вырождена: решение существует, но неустойчиво. Коэффициенты могут получиться +1500 и −1498, идеально гасящие друг друга на обучении и катастрофически расходящиеся на новых данных. Качество прогноза при этом может оставаться приличным — ломается интерпретация. Диагностика: VIF (variance inflation factor) VIF_j = 1/(1 − R²_j), где R²_j — качество предсказания j-го признака по остальным.

Классическая ошибка — dummy-переменные без выброшенной категории при наличии intercept: столбцы one-hot в сумме дают ровно единичный столбец, и матрица вырождена точно («dummy variable trap»). drop_first=True в pd.get_dummies или drop='first' в OneHotEncoder.


5. Регуляризация: Ridge, Lasso, ElasticNet

Идея простая: добавим к потерям штраф за величину весов и явно купим смещение в обмен на уменьшение дисперсии. Полная теория этого обмена — см. переобучение и регуляризация, здесь — то, что специфично для линейных моделей.

Ridge (L2):       min ‖y − Xw‖² + α‖w‖²₂       →  w* = (XᵀX + αI)⁻¹Xᵀy
Lasso (L1):       min ‖y − Xw‖² + α‖w‖₁        →  нет замкнутой формы, координатный спуск
ElasticNet:       min ‖y − Xw‖² + α(ρ‖w‖₁ + (1−ρ)‖w‖²₂)

Ridge буквально прибавляет α к диагонали: собственные числа становятся λ_i + α, матрица гарантированно обратима при любом α > 0, даже когда d > n. Это самый прямой способ увидеть, что регуляризация — лекарство от вырожденности, а не только от переобучения. В сингулярном базисе Ridge сжимает координаты с коэффициентом λ_i/(λ_i + α): направления с большой дисперсией почти не трогаются, «шумные» направления давятся почти в ноль.

Почему Lasso зануляет, а Ridge — нет? Геометрия ограничений: линии уровня MSE — эллипсы, и они касаются шара ‖w‖₂ ≤ t в случайной точке (обычно не на оси), а ромба ‖w‖₁ ≤ t — с большой вероятностью в вершине, лежащей на оси. Вершина = нулевая координата = признак выброшен. Формально в субградиенте L1 есть постоянная по модулю «сила» α·sign(w), которая не исчезает при w → 0, поэтому решение прилипает к нулю (soft-thresholding).

Практические нюансы, о которые спотыкаются все:

  • Регуляризация не инвариантна к масштабу. Признак в миллиметрах получит вес в 1000 раз больше, чем он же в метрах, и будет несправедливо оштрафован. Масштабировать обязательно.
  • Intercept не штрафуют. Иначе модель не сможет сдвинуть предсказание к среднему таргета. sklearn это делает правильно, самописный код — часто нет.
  • Lasso при коррелированных признаках выбирает произвольного представителя группы и зануляет остальных, причём выбор нестабилен между фолдами. Если нужна стабильность — ElasticNet.
  • α подбирается по кросс-валидации; для Ridge существует эффективный LOO-CV в замкнутой форме (RidgeCV с store_cv_values), для Lasso — путь регуляризации целиком (lasso_path, LARS).

6. Линейная регрессия: код

import numpy as np
from sklearn.datasets import make_regression
from sklearn.linear_model import RidgeCV
from sklearn.model_selection import KFold, cross_val_score
from sklearn.pipeline import make_pipeline
from sklearn.preprocessing import StandardScaler

# --- 1. Реализация «с нуля»: два пути к одному ответу ------------------------
def ols_normal_equation(X, y, alpha=0.0):
    """Ridge/МНК через устойчивое решение системы, БЕЗ явного обращения матрицы."""
    n, d = X.shape
    X1 = np.hstack([np.ones((n, 1)), X])          # столбец единиц под intercept
    A = X1.T @ X1
    if alpha > 0:
        penalty = alpha * np.eye(d + 1)
        penalty[0, 0] = 0.0                        # intercept не штрафуем
        A = A + penalty
    # solve вместо inv: та же сложность, лучшая численная устойчивость
    return np.linalg.solve(A, X1.T @ y)

def ols_qr(X, y):
    """Численно предпочтительный путь: QR по X, без формирования XᵀX."""
    X1 = np.hstack([np.ones((len(X), 1)), X])
    Q, R = np.linalg.qr(X1)                        # X1 = QR, R верхнетреугольная
    return np.linalg.solve(R, Q.T @ y)             # обратная подстановка O(d²)

X, y = make_regression(n_samples=2000, n_features=20, noise=12.0, random_state=0)
theta_ne = ols_normal_equation(X, y)
theta_qr = ols_qr(X, y)
print("нормальное уравнение и QR совпадают:",
      np.allclose(theta_ne, theta_qr, atol=1e-6))

# --- 2. То же в sklearn, правильно: препроцессинг внутри пайплайна ----------
model = make_pipeline(
    StandardScaler(),
    RidgeCV(alphas=np.logspace(-3, 3, 25)),        # alpha подбирается по CV
)
cv = KFold(n_splits=5, shuffle=True, random_state=42)
scores = cross_val_score(model, X, y, cv=cv, scoring="neg_root_mean_squared_error")
print(f"RMSE по 5 фолдам: {-scores.mean():.3f} ± {scores.std():.3f}")

model.fit(X, y)
print("выбранная alpha:", model[-1].alpha_)

Почему Pipeline, а не «отмасштабировал заранее и забыл»: StandardScaler, обученный на всей выборке до разбиения, протаскивает статистики теста в обучение — это утечка, и CV-оценка получается оптимистичной. Пайплайн переобучает скейлер внутри каждого фолда. Это самая частая и самая незаметная ошибка в проектах — подробнее — см. оценка моделей.


7. От регрессии к классификации: почему нельзя просто предсказывать 0/1

Соблазн: закодировать классы как 0 и 1 и обучить обычный МНК. Что ломается:

  1. Предсказания выходят за [0, 1] — «вероятность» 1.7 или −0.4 бессмысленна.
  2. Квадратичная потеря штрафует «слишком уверенные правильные» ответы. Объект класса 1 с предсказанием 3.0 даёт потерю 4.0, хотя он классифицирован идеально. Один далёкий, но легко отделимый объект будет разворачивать границу.
  3. Границы смещаются при дисбалансе — МНК подгоняет среднее, а не разделяет.
  4. Для 3+ классов числовое кодирование навязывает несуществующий порядок.

Нужна модель, которая выдаёт вероятность. Трюк логистической регрессии: предсказывать не саму вероятность (она зажата в отрезок), а логит — логарифм отношения шансов, который свободно живёт на всей числовой прямой:

odds = p/(1−p) ∈ (0, +∞)         logit(p) = ln(p/(1−p)) ∈ (−∞, +∞)
ln(p/(1−p)) = wᵀx + b            ⇔        p = σ(wᵀx + b) = 1/(1 + e^-(wᵀx+b))

Сигмоида и линейная граница решения

Отсюда сразу два вывода. Первый: граница решения p = 0.5 соответствует wᵀx + b = 0 — это гиперплоскость, логистическая регрессия остаётся линейным классификатором. Второй: ‖w‖ управляет крутизной перехода. Если данные линейно разделимы, правдоподобие растёт монотонно при ‖w‖ → ∞ — оптимум не достигается, веса расходятся. Именно поэтому в sklearn регуляризация в LogisticRegression включена по умолчанию (C=1.0): без неё солвер на разделимых данных не сойдётся.

Функция потерь: log-loss

Модель Бернулли: P(y=1|x) = p, P(y=0|x) = 1−p. Правдоподобие выборки — Π p_i^{y_i}(1−p_i)^{1−y_i}; берём минус логарифм и делим на n:

L(w) = −(1/n) Σ_i [ y_i·ln p_i + (1−y_i)·ln(1−p_i) ],   p_i = σ(xᵢᵀw)

Это кросс-энтропия. Она наказывает уверенную ошибку неограниченно (−ln(0.001) ≈ 6.9), то есть заставляет модель быть честной в вероятностях, а не только «угадывать класс».

Магия при дифференцировании: производная сигмоиды σ'(z) = σ(z)(1−σ(z)) ровно сокращается со знаменателем логарифма, и градиент выходит той же формы, что у линейной регрессии:

∇L(w) = (1/n)·Xᵀ(σ(Xw) − y)

Разница только в том, что Xw пропущено через сигмоиду. Гессиан H = (1/n)·XᵀSX, где S = diag(p_i(1−p_i)) — положительно полуопределён, значит задача выпуклая: локальный минимум единственный и глобальный. Замкнутого решения, в отличие от МНК, нет — сигмоида делает уравнение трансцендентным, поэтому только итерации.


8. Логистическая регрессия: код

import numpy as np
from sklearn.datasets import make_classification
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import roc_auc_score, log_loss, brier_score_loss
from sklearn.model_selection import train_test_split
from sklearn.pipeline import make_pipeline
from sklearn.preprocessing import StandardScaler

def sigmoid_stable(z):
    """Численно устойчивая сигмоида: при z = -800 наивный exp(-z) даёт overflow."""
    out = np.empty_like(z, dtype=float)
    pos, neg = z >= 0, z < 0
    out[pos] = 1.0 / (1.0 + np.exp(-z[pos]))
    ez = np.exp(z[neg])                    # exp от отрицательного числа безопасен
    out[neg] = ez / (1.0 + ez)
    return out

def fit_logreg(X, y, lr=0.5, epochs=800, l2=1e-2):
    """Batch GD с L2. Сложность: O(nd) на эпоху по времени, O(d) по памяти."""
    n, d = X.shape
    w, b = np.zeros(d), 0.0
    for _ in range(epochs):
        p = sigmoid_stable(X @ w + b)
        grad_w = X.T @ (p - y) / n + l2 * w    # штраф не касается b
        grad_b = (p - y).mean()
        w -= lr * grad_w
        b -= lr * grad_b
    return w, b

def log_loss_manual(y, p, eps=1e-15):
    p = np.clip(p, eps, 1 - eps)               # без клиппинга log(0) = -inf
    return -np.mean(y * np.log(p) + (1 - y) * np.log(1 - p))

X, y = make_classification(n_samples=6000, n_features=15, n_informative=6,
                           weights=[0.9, 0.1], random_state=7)   # дисбаланс 9:1
X_tr, X_te, y_tr, y_te = train_test_split(X, y, test_size=0.3,
                                          stratify=y, random_state=7)

mu, sd = X_tr.mean(0), X_tr.std(0)             # статистики ТОЛЬКО по трейну
w, b = fit_logreg((X_tr - mu) / sd, y_tr)
p_te = sigmoid_stable((X_te - mu) / sd @ w + b)
print(f"своя реализация: log-loss={log_loss_manual(y_te, p_te):.4f} "
      f"ROC-AUC={roc_auc_score(y_te, p_te):.4f}")

# Референс: sklearn, L-BFGS, веса классов под дисбаланс
clf = make_pipeline(
    StandardScaler(),
    LogisticRegression(C=1.0, solver="lbfgs", max_iter=1000,
                       class_weight="balanced"),
)
clf.fit(X_tr, y_tr)
p_sk = clf.predict_proba(X_te)[:, 1]
print(f"sklearn: log-loss={log_loss(y_te, p_sk):.4f} "
      f"ROC-AUC={roc_auc_score(y_te, p_sk):.4f} "
      f"Brier={brier_score_loss(y_te, p_sk):.4f}")

# Интерпретация: exp(коэффициента) = во сколько раз меняются шансы
coefs = clf[-1].coef_[0]
for i in np.argsort(-np.abs(coefs))[:5]:
    print(f"признак {i:2d}: w={coefs[i]:+.3f}  odds ratio={np.exp(coefs[i]):.2f}")

Три детали, ради которых стоит перечитать код:

  • sigmoid_stable. Наивный 1/(1+np.exp(-z)) при большом отрицательном z даёт переполнение и nan в градиенте. В боевых реализациях используют log1p/logaddexp или сразу считают log-loss через np.logaddexp(0, -z*(2y-1)), не материализуя p.
  • Клиппинг вероятностей перед логарифмом — обязателен.
  • class_weight="balanced" умножает вклад объектов редкого класса на n/(K·n_k). Это меняет обучение, но не отменяет необходимости настраивать порог отдельно.

Решатели: чем отличаются и что выбрать

Солвер Метод Штрафы Когда брать
lbfgs квазиньютоновский L2, none дефолт, плотные данные, d до десятков тысяч
newton-cholesky точный ньютон L2, none n >> d, мало признаков — очень быстро
liblinear координатный спуск L1, L2 малые датасеты, нужна L1
saga стохастический с вариансной редукцией L1, L2, ElasticNet, none большие разреженные данные, multinomial + L1

Метод Ньютона (IRLS) сходится квадратично и берёт 5–10 итераций вместо тысяч, но требует O(d³) на шаг для решения системы с гессианом — отсюда правило: мало признаков → Ньютон, много признаков → L-BFGS или SAGA.

Много классов

Два подхода. One-vs-Rest: K независимых бинарных моделей, вероятности нормируются постфактум — просто, параллелится, но вероятности несогласованы. Multinomial (softmax): одна модель с K векторами весов и общей нормировкой,

P(y = k | x) = exp(w_kᵀx) / Σ_j exp(w_jᵀx)

Softmax-версия статистически корректнее и обычно даёт лучший log-loss; она же — ровно последний слой любой нейросетевой классификации (нейронные сети). Заметьте вырожденность: прибавление общего вектора ко всем w_k не меняет ответ, поэтому multinomial-логрег без регуляризации не имеет единственного решения.


9. Калибровка и порог: где теряют деньги

Модель отдаёт p, продукт принимает решение. Между ними — два независимых вопроса.

Ранжирование (ROC-AUC) отвечает: правильно ли модель упорядочивает объекты. Калибровка (Brier, reliability curve) отвечает: если модель сказала «0.3», то в 30% таких случаев событие действительно происходит?

Логистическая регрессия хороша тем, что при правильной спецификации она калибрована «из коробки» — log-loss является proper scoring rule и достигает минимума на истинных вероятностях. Но калибровку легко сломать: сильная регуляризация сжимает вероятности к 0.5, class_weight="balanced" и undersampling систематически завышают p для редкого класса (нужна поправка на prior), а SVM и деревья вообще не дают вероятностей в этом смысле.

Порог 0.5 — произвольная константа, оптимальная только при равных ценах ошибок и балансе классов. Правильно: минимизировать ожидаемые издержки. Если пропуск фрода стоит C_FN, а ложная тревога C_FP, оптимальный порог равен C_FP/(C_FP + C_FN) — при фроде это единицы процентов, а не 50%.

Эта диаграмма — не абстракция: расхождение между офлайн-трансформацией признаков и онлайн-версией (training/serving skew) остаётся причиной номер один тихой деградации моделей в проде. Детали инфраструктуры — см. MLOps.


10. Типичные ошибки

  1. Не масштабировали признаки при регуляризации. Штраф распределяется по единицам измерения, а не по важности. Ridge на нестандартизованных данных даёт бессмысленный результат.
  2. Считали inv(X.T @ X). Работает на игрушках, взрывается на коррелированных признаках. np.linalg.lstsq или scipy.linalg.lstsq.
  3. Интерпретировали коэффициенты при мультиколлинеарности. «Признак вреден, у него вес −1498» — нет, у него просто есть почти-близнец с весом +1500. Сначала VIF, потом выводы.
  4. Путали C и alpha. В LogisticRegression/SVC параметр C = 1/alpha: больше C — слабее регуляризация. Ошибка направления в grid search стоит многих часов.
  5. Оценивали классификатор по accuracy при дисбалансе. При 1% позитивов константа «всё нули» даёт 99%. Смотрите PR-AUC, recall на фиксированной precision, издержки.
  6. Подбирали порог на тесте. Порог — тоже параметр; настраивайте на валидации.
  7. Обучали скейлер/энкодер до сплита. Утечка, оптимистичная оценка, сюрприз в проде.
  8. Экстраполировали. Линейная модель уверенно выдаёт цифру за пределами диапазона обучения — и почти всегда врёт. Отрицательная предсказанная цена — классика.
  9. Забыли, что корреляция не причинность. Коэффициент — это связь при фиксированных остальных признаках модели, а не причинный эффект. Добавление коллайдера в признаки способно перевернуть знак (парадокс Симпсона).
  10. Полный one-hot вместе с intercept — вырожденная матрица.

11. Почему линейные модели живы в 2026

Градиентный бустинг (ансамбли и бустинг) почти всегда обыгрывает логрег по метрике на табличных данных. И тем не менее:

  • Скоринг и регулируемые области. В кредитном скоринге доминирует логистическая регрессия на WoE-биннированных признаках (scorecard): она объяснима построчно, требования регуляторов (ECOA/GDPR, «право на объяснение») выполняются буквально, а веса переводятся в баллы.
  • Огромная разреженность. CTR-предсказание: миллиарды показов, десятки миллионов хешированных признаков. Логрег с feature hashing и FTRL-Proximal обучается онлайн одним проходом — это была рабочая лошадка рекламы Google (McMahan et al., 2013), и её потомки живут в Vowpal Wabbit до сих пор. Дерево на таких данных просто не построишь.
  • Baseline, который дисциплинирует. Первая модель в любом проекте должна быть линейной: она даёт нижнюю границу качества за минуты и мгновенно вскрывает утечки — если логрег выдаёт AUC 0.999, вы не гений, у вас в признаках протёк таргет.
  • Латентность и цена. Инференс — одно скалярное произведение: единицы микросекунд, килобайты весов, тривиальный деплой хоть в SQL, хоть на edge.
  • Мета-модель в стэкинге и последний слой нейросети — тоже она.

Как основу для рекомендаций линейные модели используют в logistic MF и factorization machines (рекомендательные системы), а обобщение на другие распределения таргета даёт целое семейство GLM: пуассоновская регрессия для счётчиков, гамма — для сумм страховых выплат, tweedie — для частоты-тяжести. Все они обучаются тем же IRLS.

Сводка trade-offs

Критерий Линейная / логистическая регрессия Бустинг на деревьях
Обучение O(nd) за эпоху, часто секунды десятки минут
Инференс O(d), микросекунды O(деревья × глубина)
Нелинейности руками (сплайны, взаимодействия) автоматически
Экстраполяция линейная (опасно, но предсказуемо) константа за краем
Интерпретация коэффициенты, odds ratio SHAP, приблизительно
Малые выборки устойчива переобучается
Калибровка почти из коробки требует изотонической/Платта
Требует масштабирования да нет

12. Мини-итог

  • Линейная регрессия = ортогональная проекция y на пространство столбцов X; нормальное уравнение XᵀXw = Xᵀy — это условие ортогональности остатка, а не магия.
  • MSE = MLE при гауссовом шуме. Меняете допущение о шуме — меняете функцию потерь.
  • Решайте через QR/SVD (lstsq), а не через inv: cond(XᵀX) = cond(X)².
  • Регуляризация L2 делает задачу обратимой всегда, L1 — ещё и отбирает признаки. Оба штрафа требуют масштабирования и не трогают intercept.
  • Логистическая регрессия — линейная модель логита; сигмоида переводит скор в вероятность, log-loss = MLE для Бернулли, задача выпуклая, решается L-BFGS/Ньютоном.
  • Метрика, калибровка и порог — три разных решения; 0.5 почти никогда не оптимален.
  • В проде линейные модели выигрывают там, где важны объяснимость, латентность, онлайн-обучение и разреженность, — и всегда служат честным baseline.

Источники

  • Trevor Hastie, Robert Tibshirani, Jerome Friedman. The Elements of Statistical Learning, главы 3 (линейные методы регрессии) и 4 (линейные методы классификации) — бесплатный PDF
  • Gareth James et al. An Introduction to Statistical Learning, главы 3 и 4 — islp.stat.cmu.edu
  • Christopher Bishop. Pattern Recognition and Machine Learning, глава 4 (IRLS, softmax) — PDF от Microsoft Research
  • Gene Golub, Charles Van Loan. Matrix Computations — QR, SVD и обусловленность наименьших квадратов
  • Документация scikit-learn: Linear Models, Probability calibration
  • H. B. McMahan et al. Ad Click Prediction: a View from the Trenches, KDD 2013 — PDF (FTRL-Proximal, логрег в проде)
  • R. Tibshirani. Regression Shrinkage and Selection via the Lasso, JRSS-B, 1996 — DOI
  • H. Zou, T. Hastie. Regularization and Variable Selection via the Elastic Net, 2005 — PDF
  • Статистическая сторона GLM: statsmodels docs

Что дальше

Мы разобрали модели, которые проводят одну гиперплоскость через всё пространство — они глобальны и параметричны. Следующая статья показывает противоположный полюс: методы, которые вообще не строят глобальную функцию, а принимают решение по локальному окружению объекта или по простому вероятностному допущению о независимости признаков.

k ближайших соседей и наивный байесовский классификатор

Если хочется сначала закрепить, как правильно измерять качество всего, что мы здесь обучили, — загляните в оценку моделей; общая карта трека собрана в карте трека.

Нашли неточность? Выделите фрагмент текста — рядом появится жучок.

Нужен разбор именно вашей ситуации?

Статья описывает общий случай. Если у вас частный — можно разобрать его отдельно, платно. А если не хватает целого материала, предложите тему: её оплачивают вскладчину, и она выходит открытой для всех.

Доска запросов