MLлогистическая регрессияклассификация

Логистическая регрессия простыми словами для аналитика

2026-07-11 11 мин

Логистическая регрессия — это модель, которая по набору признаков возвращает вероятность события: уйдёт ли клиент, кликнет ли он по баннеру, вернёт ли кредит. На вход подаёте признаки (сколько дней клиент неактивен, средний чек, число обращений в поддержку), на выходе получаете число от 0 до 1 — вероятность того, что интересующее событие произойдёт. Несмотря на слово «регрессия» в названии, задача здесь классификационная: мы отделяем «случится» от «не случится», просто делаем это мягко — через вероятность, а не сразу через жёсткий ярлык.

Я пользуюсь ей чаще любой другой модели. Она быстрая, объяснимая, редко переобучается на разумном числе признаков, а её коэффициенты можно принести продакту или риск-менеджеру и внятно объяснить, что на что влияет. Для аналитика это обычно первая модель, которую строишь на любой задаче про «да/нет», и часто она же остаётся в проде.

Почему для предсказания вероятности не подходит линейная регрессия?

Кажется логичным: взять обычную линейную регрессию, где целевая переменная — 0 или 1, обучить её и считать предсказание вероятностью. На практике это ломается сразу в двух местах.

Первое — линейная модель ничем не ограничена по диапазону. Формула вида y = b0 + b1*x1 + b2*x2 может выдать и 1.4, и минус 0.3. А вероятность живёт строго между 0 и 1. Что такое «вероятность оттока 140%» — непонятно, и никакой честной интерпретации у этого нет.

Второе — линейная регрессия предполагает, что связь между признаком и целевой переменной прямая и постоянная. Но с вероятностями так не бывает. Разница между вероятностью 0.01 и 0.02 для бизнеса огромна (риск удвоился), а разница между 0.50 и 0.51 почти незаметна. Линейная модель обеих этих разниц «не чувствует» — для неё это просто плюс 0.01. Нужна функция, которая по краям (у 0 и у 1) двигается осторожно, а в середине — резче. Именно это и делает логистическая регрессия.

Что такое сигмоида и зачем она превращает число в вероятность?

Сигмоида — это функция-переводчик. Она берёт любое число от минус бесконечности до плюс бесконечности и сжимает его в интервал от 0 до 1. Формула словами: p = 1 / (1 + e^(-z)), где z — это как раз линейная комбинация b0 + b1*x1 + b2*x2 + ....

Логика двухшаговая. Сначала модель считает обычную линейную сумму z — тут всё как в линейной регрессии. Потом прогоняет z через сигмоиду и получает вероятность. Если z большое положительное — сигмоида даёт близко к 1. Если большое отрицательное — близко к 0. Если z = 0 — ровно 0.5.

График сигмоиды похож на растянутую букву S: пологие хвосты по краям и крутой подъём в середине. За счёт этих пологих хвостов модель никогда не выходит за границы вероятности и заодно правильно ведёт себя на экстремальных значениях — чтобы сдвинуть вероятность с 0.99 до 0.999, признаку нужно измениться сильнее, чем чтобы сдвинуть её с 0.5 до 0.6. Это ровно то поведение, которого мы ждём от честной вероятности.

Что такое log-odds и при чём тут коэффициенты модели?

Здесь появляется главная идея, из-за которой модель вообще линейная. Сигмоида нелинейна по вероятности, но если развернуть её обратно, окажется, что линейной суммой z модель описывает не саму вероятность, а логарифм шансов — log-odds.

Шансы (odds) — это отношение «вероятность события к вероятности его отсутствия»: odds = p / (1 - p). Если вероятность оттока 0.8, шансы равны 0.8 / 0.2 = 4, то есть «четыре к одному, что уйдёт». Логарифм этих шансов и есть та величина, которую логистическая регрессия моделирует прямой линией: log(p / (1 - p)) = b0 + b1*x1 + b2*x2 + ....

Отсюда простая трактовка коэффициентов: каждый b показывает, на сколько меняется log-odds при росте признака на единицу. Знак говорит направление — плюс тянет вероятность вверх, минус вниз. Проблема только в том, что «изменение log-odds» — плохой язык для разговора с бизнесом. Мало кто на встрече оперирует логарифмами шансов. Поэтому коэффициенты почти всегда переводят в odds ratio.

Как читать коэффициенты через odds ratio?

Odds ratio — это просто экспонента от коэффициента: odds_ratio = e^b. Она отвечает на понятный вопрос: во сколько раз меняются шансы события, когда признак вырастает на единицу.

Разбираю на примере. Допустим, модель предсказывает отток, и у признака «число обращений в поддержку за месяц» коэффициент получился примерно 0.69. Тогда odds ratio равно e^0.69, а это примерно 2. Читается так: каждое дополнительное обращение в поддержку удваивает шансы на отток, при прочих равных. Если коэффициент отрицательный, скажем минус 0.69, то odds ratio будет около 0.5 — шансы уменьшаются вдвое. Коэффициент близко к нулю даёт odds ratio около 1, то есть признак почти не влияет.

Два предостережения, которые я всегда держу в голове. Первое: odds ratio — это про шансы, а не напрямую про вероятность, и во сколько именно раз изменится вероятность, зависит от того, с какого уровня стартуем. Второе: сравнивать коэффициенты между признаками честно только тогда, когда признаки в одном масштабе. Средний чек в тысячах рублей и возраст в годах несопоставимы «в лоб», поэтому перед сравнением важности я обычно стандартизирую признаки. Разбор того, как коэффициенты складываются в интерпретацию бизнес-модели, удобно тренировать на разборах из раздела кейсов — там связь «модель — решение» видна на живых задачах.

Как собрать логистическую регрессию на sklearn?

Минимальный, но рабочий скелет для задачи про отток. Данные — таблица клиентов с признаками и флагом churned (1 — ушёл, 0 — остался).

import pandas as pd
import numpy as np
from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import train_test_split
from sklearn.metrics import classification_report, roc_auc_score

X = df[['recency_days', 'orders_count', 'avg_check', 'support_tickets']]
y = df['churned']

X_train, X_test, y_train, y_test = train_test_split(
    X, y, test_size=0.25, random_state=42, stratify=y
)

model = LogisticRegression(max_iter=1000)
model.fit(X_train, y_train)

# главное: берём вероятности, а не жёсткие метки
proba = model.predict_proba(X_test)[:, 1]
print('ROC-AUC:', roc_auc_score(y_test, proba))

Обратите внимание на predict_proba вместо predict. predict сразу отдаёт классы, зашивая внутри порог 0.5, а мне почти всегда нужны именно вероятности — из них я потом сам выберу порог под задачу. Ещё две вещи в реальном проекте: stratify=y держит долю классов одинаковой в трейне и тесте (важно, когда события редкие), а признаки перед обучением стоит масштабировать через StandardScaler — и для сходимости, и чтобы коэффициенты были сравнимы.

А вот перевод коэффициентов в человеческий язык — тот самый odds ratio:

coefs = pd.Series(model.coef_[0], index=X.columns)
odds_ratio = np.exp(coefs)
print(odds_ratio.sort_values(ascending=False))

Значения odds ratio заметно больше 1 — признаки, толкающие к оттоку; заметно меньше 1 — удерживающие. Этот же код удобно гонять в Python-тренажёре на своих данных, а синтаксис pandas и sklearn под рукой — в справочнике по Python.

Как выбрать порог классификации?

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

Порог — это бизнес-рычаг, а не техническая константа. Двигая его, вы обмениваете одни ошибки на другие. Понизили порог до 0.3 — ловите больше уходящих клиентов, но и чаще беспокоите лояльных ложной тревогой. Подняли до 0.7 — реже дёргаете лояльных, но пропускаете часть настоящего оттока. «Правильного» порога в отрыве от задачи не существует: он зависит от того, что дороже — пропущенный отток или зря потраченный на удержание бюджет.

threshold = 0.35
pred = (proba >= threshold).astype(int)
print(classification_report(y_test, pred))

Я обычно не угадываю порог, а перебираю сетку значений и смотрю, при каком precision и recall дают устраивающий бизнес баланс. И держу в голове, что при сильном дисбалансе классов accuracy бесполезна: если уходит 3% клиентов, модель «всем ставлю 0» будет права в 97% случаев и при этом абсолютно бесполезна.

Precision или recall — что важнее для вашей задачи?

Это две стороны одной ошибки, и выбор между ними определяется ценой промаха. Precision отвечает на вопрос «из тех, кого модель пометила как отток, сколько реально ушли» — то есть насколько можно доверять сигналу «положительный». Recall отвечает на вопрос «из всех реально ушедших сколько модель поймала» — то есть какую долю событий мы не проспали.

Дальше это чистая экономика. В задаче про удержание, где ретеншен-акция дешёвая, а потеря клиента дорогая, я тяну recall вверх: лучше отправить лишнюю скидку сомневающимся, чем упустить уходящего. Разговор про ценность удержанного пользователя удобно вести на языке продуктовых метрик — например, DAU и связанных с ним показателей. А в антифроде, где каждое ложное срабатывание блокирует платёж честного человека и бьёт по опыту, я поднимаю precision: блокируем только когда действительно уверены. Общий метрикой качества вероятностей поверх всех порогов служит ROC-AUC — она не зависит от конкретного порога и показывает, насколько хорошо модель в принципе разделяет классы. Такие вопросы про баланс метрик почти гарантированно попадаются на собеседованиях — их разбор есть в подборке вопросов с интервью.

Чем логистическая регрессия отличается от линейной, если коротко?

Различие в том, что они предсказывают и в каком пространстве работают линейно. Линейная регрессия предсказывает непрерывное число (выручку, чек, время доставки) и моделирует его прямой линией напрямую. Логистическая предсказывает вероятность события, а линейной суммой описывает не саму вероятность, а её log-odds, после чего сигмоида загоняет результат в диапазон 0–1.

Отсюда тянутся все остальные отличия. У линейной регрессии выход не ограничен, у логистической — строго между 0 и 1. Коэффициенты линейной читаются как «плюс столько-то единиц целевой переменной», коэффициенты логистической — как odds ratio, «во столько-то раз меняются шансы». Обучаются они тоже по-разному: линейная минимизирует квадраты ошибок, логистическая максимизирует правдоподобие через log-loss. И оценивают их разными метриками — RMSE и R² против precision, recall и ROC-AUC. При этом общий каркас один: и там, и там сумма b0 + b1*x1 + ..., просто логистическая добавляет поверх сигмоиду. Поэтому перейти от одной к другой в голове несложно, если держать в уме эти две-три развилки. Закрепить разницу на практике проще всего, порешав практические задания на обе модели подряд.

Если хотите отработать это не на пальцах, а руками — соберите свою логистическую регрессию на реальных данных в Python-тренажёре; в Pro открыт полный набор задач по ML, метрикам и разбору моделей, чтобы довести навык до автомата без спешки.

Закрепи Python на задачах
402 Python-задачи через pandas/numpy/scipy — попробуй бесплатно.
Python-тренажёр →