Линейная и логистическая регрессия
Если из всего машинного обучения оставить только два алгоритма, разумно оставить именно эти. Линейная регрессия — это скелет, на который натянуто почти всё остальное: нейросеть без активаций сворачивается в линейную регрессию, градиентный бустинг складывает деревья почти так же, как линейная модель складывает признаки, а последний слой любого классификатора — это логистическая (или 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‖²
Почему квадрат, а не модуль? Три независимых аргумента, и их полезно держать в голове, потому что каждый подсказывает, когда квадрат — плохая идея.
- Вероятностный. Предположим
y = Xw + ε, где шумε ~ N(0, σ²)независим по объектам. Тогда логарифм правдоподобия равен−(1/2σ²)·‖y − Xw‖² + const, и максимизация правдоподобия (MLE) тождественна минимизации MSE. То есть МНК — это не «просто удобно», а точная оценка при гауссовом шуме. Если шум тяжелохвостый (выбросы), допущение ломается — отсюда чувствительность МНК к выбросам и существование Huber/quantile-регрессии. - Геометрический. Квадрат нормы = евклидово расстояние, а минимум расстояния до линейного подпространства даёт ортогональную проекцию (см. ниже). Красиво и решается точно.
- Вычислительный. 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‖на обучении: подпространство только расширяется. Отсюда бесполезностьR²для выбора модели и существование adjustedR².
Сложность и почему 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) — не косметика, а прямое ускорение обучения на порядки. Подробности про масштабирование и утечки при его подгонке — см. данные и признаки.
или итеративный солвер| D[StandardScaler / RobustScaler] C -->|Чистый МНК без штрафа| E[Можно без масштабирования] D --> F{Размер задачи} E --> F F -->|n, d малы; d < 10k| G[Точное решение: QR / SVD] F -->|n огромно, d умеренно| H[Mini-batch SGD / Adam] F -->|d >> n, разреженные признаки| I[Координатный спуск, L1] G --> J[Диагностика остатков] H --> J I --> J J -->|Структура в остатках| B J -->|Остатки похожи на шум| K[Валидация и калибровка] K --> L[Деплой и мониторинг дрейфа]
Варианты спуска и их ниши:
- 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 и обучить обычный МНК. Что ломается:
- Предсказания выходят за
[0, 1]— «вероятность» 1.7 или −0.4 бессмысленна. - Квадратичная потеря штрафует «слишком уверенные правильные» ответы. Объект класса 1 с предсказанием 3.0 даёт потерю 4.0, хотя он классифицирован идеально. Один далёкий, но легко отделимый объект будет разворачивать границу.
- Границы смещаются при дисбалансе — МНК подгоняет среднее, а не разделяет.
- Для 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%.
отложенная сверка с реальным исходом L-->>M: сигнал на переобучение при дрейфе
Эта диаграмма — не абстракция: расхождение между офлайн-трансформацией признаков и онлайн-версией (training/serving skew) остаётся причиной номер один тихой деградации моделей в проде. Детали инфраструктуры — см. MLOps.
10. Типичные ошибки
- Не масштабировали признаки при регуляризации. Штраф распределяется по единицам измерения, а не по важности. Ridge на нестандартизованных данных даёт бессмысленный результат.
- Считали
inv(X.T @ X). Работает на игрушках, взрывается на коррелированных признаках.np.linalg.lstsqилиscipy.linalg.lstsq. - Интерпретировали коэффициенты при мультиколлинеарности. «Признак вреден, у него вес −1498» — нет, у него просто есть почти-близнец с весом +1500. Сначала VIF, потом выводы.
- Путали
Cиalpha. ВLogisticRegression/SVCпараметрC = 1/alpha: большеC— слабее регуляризация. Ошибка направления в grid search стоит многих часов. - Оценивали классификатор по accuracy при дисбалансе. При 1% позитивов константа «всё нули» даёт 99%. Смотрите PR-AUC, recall на фиксированной precision, издержки.
- Подбирали порог на тесте. Порог — тоже параметр; настраивайте на валидации.
- Обучали скейлер/энкодер до сплита. Утечка, оптимистичная оценка, сюрприз в проде.
- Экстраполировали. Линейная модель уверенно выдаёт цифру за пределами диапазона обучения — и почти всегда врёт. Отрицательная предсказанная цена — классика.
- Забыли, что корреляция не причинность. Коэффициент — это связь при фиксированных остальных признаках модели, а не причинный эффект. Добавление коллайдера в признаки способно перевернуть знак (парадокс Симпсона).
- Полный 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 ближайших соседей и наивный байесовский классификатор
Если хочется сначала закрепить, как правильно измерять качество всего, что мы здесь обучили, — загляните в оценку моделей; общая карта трека собрана в карте трека.