Логистическая регрессия 🎲
Название сбивает с толку с первого дня знакомства: «логистическая регрессия» звучит как ещё один способ предсказывать число, продолжение линейной и полиномиальной регрессии из прошлых уроков. На деле это одна из самых используемых на практике моделей классификации — предсказания не числа, а класса: спам или не спам, одобрить кредит или отказать, уйдёт клиент или останется, злокачественная опухоль или доброкачественная. Слово «регрессия» осталось в названии по историческим причинам, о которых ты узнаешь через пару абзацев, и путаница с ним настолько распространена, что открывает список частых ошибок в конце этого урока.
Идея логистической регрессии обманчиво простая: взять ту же линейную комбинацию признаков $w_0 + w_1 x_1 + \dots + w_n x_n$, что и в линейной регрессии, а затем пропустить её через специальную S-образную функцию — сигмоиду, — которая сжимает любое вещественное число в диапазон от 0 до 1. Получившееся число интерпретируется как вероятность принадлежности к положительному классу. Это решает конкретную и очень практическую проблему: линейная регрессия могла бы в принципе предсказать вероятность как есть, но ничто не мешает ей выдать $-0{,}3$ или $1{,}8$ — числа, бессмысленные как вероятности. Сигмоида устраняет эту проблему математически, а не заплаткой вроде обрезания значений после предсказания.
Эта модель — фундамент, на котором держится огромный пласт прикладного Data Science. sklearn.linear_model.LogisticRegression — одна из первых моделей, которую пробуют на любой задаче бинарной классификации: она быстро обучается даже на сотнях тысяч примеров, не требует подбора десятков гиперпараметров, устойчиво работает и, что особенно ценно в банковском скоринге, медицине и страховании, даёт интерпретируемые коэффициенты — можно объяснить регулятору или врачу, почему модель приняла именно такое решение. Именно поэтому логистическая регрессия почти всегда служит baseline-моделью: первым результатом, с которым сравнивают более сложные модели вроде градиентного бустинга или нейросетей, — если сложная модель не побеждает простую логистическую регрессию с заметным отрывом, возможно, усложнение того не стоило.
И, забегая вперёд по курсу: сигмоида и её многоклассовое обобщение softmax, которые ты выучишь сегодня, — это ровно те же функции, которые стоят на выходном слое подавляющего большинства классифицирующих нейросетей. Слой Dense(1, activation='sigmoid') в бинарной классификации или Dense(K, activation='softmax') в многоклассовой — это буквально логистическая регрессия, встроенная в конец глубокой сети поверх признаков, которые сеть выучила сама. Понимание сегодняшнего урока — это понимание того, как принимает решение последний слой практически любого классификатора, от простейшего до самого сложного.
История
Сигмоидальная функция появилась в науке задолго до машинного обучения и вообще до появления статистики как отдельной дисциплины в её современном виде. В 1838 году бельгийский математик Пьер Франсуа Ферхюльст искал способ описать рост населения точнее, чем простая экспоненциальная модель Мальтуса, которая предсказывала бесконечный неограниченный рост. Ферхюльст предложил модель, в которой скорость роста населения замедляется по мере приближения к некоему пределу — ограниченности ресурсов территории. Решением дифференциального уравнения этой модели оказалась ровно та самая S-образная кривая, которую Ферхюльст назвал «логистической» (по всей видимости, от французского «logis» — «жильё, размещение», в намёке на ограниченность жизненного пространства). Отсюда и происходит слово «логистическая» в названии сегодняшнего урока — оно не имеет никакого отношения к логистике как к перевозкам грузов, это лингвистическое совпадение.
Статистическое применение той же кривой для задачи классификации оформилось намного позже. В середине XX века биостатистики и эпидемиологи искали способ моделировать вероятность события (заболевание, смерть, выздоровление) как функцию факторов риска. В 1958 году английский статистик Дэвид Кокс опубликовал работу «The regression analysis of binary sequences», в которой систематически изложил модель бинарной регрессии через логистическую функцию, включая метод оценки параметров через максимальное правдоподобие — тот самый принцип, который ты уже видел в уроке 246 и который сегодня даст нам формулу функции потерь. Термин «регрессия» в названии модели — прямое наследие этой статистической традиции: Кокс формально рассматривал задачу как регрессию для параметра распределения Бернулли (вероятности), а не как явную задачу «классификации» в современном машинно-обучающем смысле — это разграничение оформилось только десятилетия спустя.
К 1970–80-м годам логистическая регрессия стала стандартным инструментом биостатистики, эпидемиологии (знаменитое Фрамингемское исследование сердечно-сосудистых заболеваний активно использовало логистическую регрессию для оценки факторов риска) и страховой математики. Когда в 1980–90-е годы формирующаяся область машинного обучения начала систематизировать методы классификации, логистическая регрессия перекочевала туда почти без изменений — просто с новым, вычислительным акцентом: вместо аналитических таблиц коэффициентов теперь параметры обучались градиентным спуском на больших наборах данных. Сегодня, несмотря на десятилетия существования и появление куда более сложных моделей, логистическая регрессия остаётся одной из самых часто разворачиваемых в продакшене моделей — именно за счёт сочетания скорости, устойчивости и интерпретируемости.
Сигмоида и модель логистической регрессии
Интуиция
Возьми линейную регрессию и представь, что тебе нужно предсказать не цену квартиры, а вероятность того, что клиент вернёт кредит. Линейная комбинация признаков $z = w_0 + w_1 x_1 + \dots + w_n x_n$ по-прежнему может пригодиться — доход, кредитная история, возраст действительно должны как-то суммарно влиять на вероятность возврата, — но сама эта сумма $z$ может принять любое значение от $-\infty$ до $+\infty$, а вероятность обязана лежать строго между 0 и 1. Нужна функция-«переходник», которая берёт любое вещественное число на входе и всегда отдаёт число в диапазоне $(0, 1)$ на выходе, при этом монотонно: чем больше $z$, тем ближе выход к 1, чем меньше $z$, тем ближе к 0.
Именно такой переходник — сигмоида. Её график — гладкая S-образная кривая: при больших отрицательных $z$ она почти сливается с нулевой линией, при больших положительных $z$ — почти сливается с линией единицы, а в районе $z=0$ круто и почти линейно переходит от одного значения к другому, проходя ровно через точку $(0,\ 0{,}5)$. Эта середина — не случайность, а прямое следствие симметрии формулы: сигмоида одинаково «не уверена» в обе стороны вблизи нуля и полностью «уверена» на удалении от него в любую сторону.
Формальное определение
Логистическая модель бинарной классификации.
$$z = w_0 + w_1 x_1 + w_2 x_2 + \dots + w_n x_n = w^\top x$$$$p = \sigma(z) = \frac{1}{1 + e^{-z}}$$где $z$ — логит (линейная комбинация признаков, та же величина, что предсказывала бы обычная линейная регрессия), а $p \in (0,1)$ — предсказанная моделью вероятность того, что объект принадлежит положительному классу ($y=1$). Решение о классе принимается по порогу: обычно $\hat y = 1$, если $p \ge 0{,}5$ (что эквивалентно $z \ge 0$), и $\hat y = 0$ иначе.
Обрати внимание на удобное алгебраическое свойство сигмоиды, которое пригодится ниже: $1 - \sigma(z) = \sigma(-z)$ — вероятность «не быть положительным классом» устроена зеркально симметрично относительно нуля.
Примеры
Пример 1: вероятность сдачи экзамена по числу часов подготовки. Пусть подобранная на исторических данных модель имеет веса $w_0 = -4$, $w_1 = 0{,}8$ (на один час подготовки), а единственный признак $x_1$ — число часов, потраченных на подготовку. Для студента, готовившегося 5 часов: $z = -4 + 0{,}8 \cdot 5 = 0$, значит $p = \sigma(0) = 0{,}5$ — модель абсолютно не уверена, и порог классификации проходит ровно здесь. Для студента, готовившегося 8 часов: $z = -4 + 0{,}8 \cdot 8 = 2{,}4$, тогда $e^{-2{,}4} \approx 0{,}0907$ и $p = 1/(1+0{,}0907) \approx 0{,}917$ — 91,7% шанс сдать. А для того, кто готовился всего 2 часа: $z = -4+1{,}6 = -2{,}4$, и по симметрии сигмоиды $p = 1 - 0{,}917 = 0{,}083$ — те же 8,3%, только теперь это шанс сдать (то есть модель почти уверена в провале).
Пример 2: банковский скоринг по двум признакам. Модель одобрения кредита использует доход в десятках тысяч рублей ($x_1$) и признак наличия других непогашенных долгов ($x_2 \in \{0,1\}$), с весами $w_0=-1$, $w_1=0{,}5$, $w_2=-2$. Клиент А: доход 40 тыс. ($x_1=4$), долгов нет ($x_2=0$): $z = -1 + 0{,}5\cdot4 - 2\cdot0 = 1$, $p = \sigma(1) = 1/(1+e^{-1}) \approx 1/(1{,}368) \approx 0{,}731$ — 73,1% вероятность одобрения. Клиент Б: доход 20 тыс. ($x_1=2$), есть долги ($x_2=1$): $z = -1+1-2=-2$, $p=\sigma(-2)\approx 1/(1+7{,}389)\approx0{,}119$ — всего 11,9%. Разница в один «включённый» бинарный признак долга здесь стоит модели больше 60 процентных пунктов уверенности — потому что вес $w_2=-2$ довольно велик по модулю.
Пример 3: почему просто линейная регрессия здесь не подойдёт. Возьми ту же формулу скоринга, но представь клиента с доходом 200 тыс. ($x_1=20$) без долгов. Если бы вероятность моделировалась напрямую линейной функцией $y = -1+0{,}5\cdot20 = 9$, результат — «вероятность» 9, то есть в 9 раз больше единицы, полная бессмыслица. Логистическая модель эту проблему не испытывает в принципе: $z=9$ по-прежнему вычисляется как логит, но $p=\sigma(9) \approx 0{,}9999$ — сигмоида просто «насыщается» около единицы и никогда не превысит её, сколько бы ни рос сам логит. В этом всё преимущество: линейная комбинация признаков внутри модели может расти неограниченно, а итоговый выход остаётся корректной вероятностью всегда.
Почему это важно
Сигмоида — не единственный способ получить число от 0 до 1, но именно она обладает удобными математическими свойствами (гладкая производная, выражаемая через саму себя: $\sigma'(z) = \sigma(z)(1-\sigma(z))$), которые сделают следующий раздел про обучение градиентным спуском заметно проще. А главное — та же самая функция ровно в том же виде используется как активация выходного нейрона в бинарных классификаторах на основе нейросетей: логистическая регрессия — это нейросеть с нулём скрытых слоёв, один линейный слой плюс сигмоида на выходе. Осваивая эту модель, ты параллельно осваиваешь то, как принимает решение последний слой практически любой нейросети для задачи «да/нет».
Функция потерь: кросс-энтропия и почему не MSE
Интуиция
Чтобы обучить модель — подобрать веса $w$ — нужна функция потерь, которая говорит, насколько предсказание $p$ далеко от истинной метки $y \in \{0, 1\}$. Интуитивно хочется штрафовать модель тем сильнее, чем увереннее она ошиблась: предсказание $p=0{,}51$ при истинном $y=0$ — почти угадала, лёгкая ошибка; а предсказание $p=0{,}99$ при истинном $y=0$ — уверенно и грубо ошиблась, такое должно штрафоваться значительно жёстче, не пропорционально, а непропорционально сильнее. Именно такое поведение и даёт кросс-энтропия (её ещё называют log loss, логарифмической функцией потерь): она использует логарифм, который стремится к бесконечности по мере приближения предсказанной вероятности к «неправильному» краю.
Эта же функция потерь — не произвольный инженерный выбор. Она прямо следует из принципа максимального правдоподобия, разобранного в уроке 246: если считать, что $y_i$ — реализация случайной величины Бернулли с параметром $p_i$, то логарифм правдоподобия всего датасета — это в точности минус кросс-энтропия с точностью до знака. Минимизировать кросс-энтропию значит максимизировать вероятность того, что модель с такими весами действительно сгенерировала бы именно те метки, которые лежат в обучающей выборке.
Формальное определение
Функция потерь: бинарная кросс-энтропия (log loss).
$$L(w) = -\frac{1}{n}\sum_{i=1}^{n} \Big[ y_i \log p_i + (1-y_i)\log(1-p_i) \Big], \quad p_i = \sigma(x_i^\top w)$$Для каждого отдельного примера только одно из двух слагаемых в квадратных скобках «активно»: если $y_i=1$, вклад в потерю равен $-\log p_i$; если $y_i=0$ — вклад равен $-\log(1-p_i)$.
О выпуклости этой функции по $w$ подробно говорить не будем — она уже полностью доказана в уроке 278 через гессиан $\nabla^2 L(w) = \frac{1}{n}X^\top S X$, где $S = \operatorname{diag}(p_i(1-p_i))$ положительно полуопределена при любых данных. Здесь мы опираемся на этот результат как на готовый факт и переходим сразу к практике.
Примеры
Пример 1: цена уверенности. Модель предсказала $p=0{,}9$ для истинного $y=1$: потеря $= -\log(0{,}9) \approx 0{,}105$ — почти ничего, модель была права и уверена. Теперь та же модель предсказала $p=0{,}1$ для истинного $y=1$ (то есть уверенно ошиблась в противоположную сторону): потеря $=-\log(0{,}1) \approx 2{,}303$. Разница в 22 раза при том, что разница в предсказанной вероятности была всего лишь «наоборот» — это и есть та самая непропорциональная жёсткость наказания за уверенную ошибку, которую даёт логарифм.
Пример 2: средняя потеря на мини-датасете. Три примера: $(y_1=1, p_1=0{,}8)$, $(y_2=0, p_2=0{,}3)$, $(y_3=1, p_3=0{,}6)$. Потери по отдельности: $-\log(0{,}8)\approx0{,}223$; для второго примера $y=0$, значит используем $-\log(1-0{,}3)=-\log(0{,}7)\approx0{,}357$; для третьего $-\log(0{,}6)\approx0{,}511$. Средняя потеря: $(0{,}223+0{,}357+0{,}511)/3 \approx 0{,}364$. Именно эту усреднённую величину и минимизирует градиентный спуск на каждой итерации обучения.
Пример 3: почему не MSE — затухающие градиенты. Возьми среднеквадратичную ошибку $\text{MSE} = (p-y)^2$ вместо кросс-энтропии, применённую к тому же $p=\sigma(z)$. По правилу дифференцирования сложной функции градиент MSE по весам содержит множитель $p(1-p)$ — это производная сигмоиды. Возьми пример уверенной ошибки: $p=0{,}98$, $y=0$ (модель почти уверена в положительном классе, а истина — отрицательный). Множитель $p(1-p) = 0{,}98\cdot0{,}02 = 0{,}0196$ — крошечное число, потому что сигмоида в этой точке уже почти горизонтальна (насыщена). Градиент MSE для такого примера практически гаснет, хотя модель ошиблась максимально уверенно и как раз в этот момент должна получить самый сильный сигнал для исправления. У кросс-энтропии логарифм при дифференцировании математически ровно сокращает этот множитель $p(1-p)$, и итоговый градиент по логиту оказывается равен просто $(p-y) = 0{,}98$ — почти в 50 раз больше, чем у MSE в этом же примере. Это ключевая практическая деталь: кросс-энтропия даёт «здоровые», не затухающие градиенты именно там, где модель ошибается сильнее всего, а MSE в паре с сигмоидой — наоборот, замедляется ровно в области насыщения, где нужно учиться быстрее всего.
Почему это важно
Выбор функции потерь — не формальность. Кросс-энтропия для логистической регрессии — это одновременно (1) прямое следствие метода максимального правдоподобия для распределения Бернулли (урок 246), (2) доказанно выпуклая функция без плохих локальных минимумов (урок 278), и (3) функция с практически более здоровым поведением градиента по сравнению с MSE, что напрямую ускоряет и стабилизирует обучение. Именно поэтому в sklearn.linear_model.LogisticRegression, в nn.BCELoss() из PyTorch и в binary_crossentropy из Keras по умолчанию используется именно кросс-энтропия, а не среднеквадратичная ошибка, — и теперь ты знаешь три независимые причины, почему это не случайное соглашение.
Обучение градиентным спуском
Интуиция
У линейной регрессии есть красивое аналитическое решение — нормальные уравнения $w^* = (X^\top X)^{-1}X^\top y$, вычисляемые за один шаг матричной алгебры. У логистической регрессии такого прямого решения нет: сигмоида внутри логарифма делает уравнение $\nabla L(w) = 0$ нелинейным относительно $w$, и явно выразить $w$ через $X$ и $y$ невозможно. Поэтому логистическую регрессию обучают итеративно — небольшими шагами в сторону уменьшения потерь, то есть градиентным спуском (или его более быстрыми родственниками — методом Ньютона, L-BFGS и другими, которые sklearn использует под капотом в зависимости от выбранного solver).
Хорошая новость в том, что тебе не нужно беспокоиться, застрянет ли градиентный спуск где-то «не там». Функция потерь кросс-энтропии выпукла — это строго доказано в уроке 278 через гессиан $\nabla^2 L(w) = \frac1n X^\top S X \succeq 0$, — а значит, по главной теореме того же урока, у неё вообще нет «плохих» локальных минимумов: куда бы градиентный спуск ни пришёл, эта точка гарантированно окажется глобальным минимумом. Не «скорее всего», а математически доказуемо для любых данных и любой начальной точки.
Формальное определение
Градиент кросс-энтропии по весам:
$$\nabla L(w) = \frac{1}{n} X^\top (p - y)$$где $p$ — вектор предсказанных вероятностей, $y$ — вектор истинных меток. Обрати внимание, насколько простая эта формула по сравнению с исходным логарифмическим выражением — это прямое следствие того самого удачного сокращения множителя $p(1-p)$, о котором говорилось в предыдущем разделе.
Шаг градиентного спуска:
$$w \leftarrow w - \alpha \, \nabla L(w)$$где $\alpha$ — скорость обучения (learning rate). Шаги повторяются до сходимости — то есть до тех пор, пока изменение $L(w)$ между итерациями не станет пренебрежимо малым.
Примеры
Пример 1: один шаг градиентного спуска вручную. Модель с единственным весом $w$ (без свободного члена) и два примера: $x_1=2, y_1=1$ и $x_2=-1, y_2=0$. Старт: $w_0=0$. На старте $z_1=0$, $z_2=0$, значит $p_1=p_2=0{,}5$ — модель максимально не уверена. Градиент: $\nabla L = \frac12\big[(0{,}5-1)\cdot2 + (0{,}5-0)\cdot(-1)\big] = \frac12\big[-1-0{,}5\big] = -0{,}75$. При скорости обучения $\alpha=0{,}1$: $w_1 = 0 - 0{,}1\cdot(-0{,}75) = 0{,}075$.
Пример 2: второй шаг — видно направление сходимости. С $w_1=0{,}075$: $z_1=0{,}15$, $p_1=\sigma(0{,}15)\approx0{,}537$ (выросла к нужной цели $y_1=1$); $z_2=-0{,}075$, $p_2=\sigma(-0{,}075)\approx0{,}481$ (снизилась к нужной цели $y_2=0$). Новый градиент: $\nabla L = \frac12\big[(0{,}537-1)\cdot2+(0{,}481-0)\cdot(-1)\big]=\frac12\big[-0{,}926-0{,}481\big]\approx-0{,}703$. Следующий шаг: $w_2 = 0{,}075-0{,}1\cdot(-0{,}703) \approx 0{,}145$. Заметь: $p_1$ последовательно растёт к 1, а $p_2$ последовательно падает к 0 — именно то поведение, которого требует выпуклость: монотонное приближение к оптимуму без «перескоков» в другую область.
Пример 3: разные солверы sklearn сходятся к одному и тому же ответу.
from sklearn.linear_model import LogisticRegression
for solver in ["liblinear", "lbfgs", "newton-cg"]:
model = LogisticRegression(solver=solver, max_iter=1000)
model.fit(X_train, y_train)
print(solver, model.coef_)
Запусти этот код на одних и тех же данных — и веса model.coef_ окажутся практически идентичными для всех трёх солверов (с точностью до вычислительной погрешности), несмотря на то что это совершенно разные численные алгоритмы оптимизации (метод координатного спуска, квазиньютоновский L-BFGS, метод Ньютона). Это не совпадение и не удача — это прямое следствие теоремы урока 278: раз задача выпукла, у неё ровно один класс эквивалентных ответов (глобальный минимум, единственный при строгой выпуклости), и любой корректно работающий метод оптимизации в него попадёт.
Почему это важно
Гарантия сходимости к глобальному минимуму — не теоретическая красивость, а причина, по которой логистическую регрессию можно уверенно ставить в продакшен без опасений, что «сегодня модель переобучилась иначе, чем вчера». В отличие от нейросети, которую по-хорошему стоит обучать несколько раз с разной случайной инициализацией и выбирать лучший запуск по валидации (потому что её функция потерь невыпукла — это прямо обсуждалось в уроке 278), логистическая регрессия при фиксированных данных и достаточном числе итераций даёт один и тот же ответ каждый раз — воспроизводимость, которую индустрия (особенно регулируемая — банки, страхование, медицина) очень ценит.
Многоклассовая логистическая регрессия: softmax
Интуиция
Сигмоида отлично работает, когда классов ровно два, но что если классов больше — например, нужно классифицировать рукописную цифру от 0 до 9, или определить тональность отзыва как «негативный / нейтральный / позитивный»? Прямая идея — завести отдельный логит $z_k$ для каждого из $K$ классов (свой набор весов на класс), а затем превратить набор из $K$ произвольных вещественных чисел в набор из $K$ вероятностей, которые в сумме дают ровно 1. Функция, которая это делает, называется softmax — «мягкий» аналог функции argmax (которая просто выбрала бы класс с наибольшим логитом и присвоила бы ему вероятность 1, а остальным — 0): softmax вместо жёсткого выбора распределяет вероятностную массу между всеми классами пропорционально экспонентам их логитов, оставляя место для неопределённости.
Формальное определение
Softmax-функция для $K$ классов:
$$z_k = w_k^\top x, \qquad p_k = \frac{e^{z_k}}{\sum_{j=1}^{K} e^{z_j}}, \qquad k=1,\dots,K$$Числитель — экспонента логита нужного класса, знаменатель — сумма экспонент логитов всех классов, что гарантирует $\sum_k p_k = 1$ и $p_k > 0$ для каждого класса.
Категориальная кросс-энтропия (обобщение log loss на много классов, с one-hot-кодированной истинной меткой $y_{ik}$):
$$L(w) = -\frac1n \sum_{i=1}^n \sum_{k=1}^K y_{ik} \log p_{ik}$$
Примеры
Пример 1: числовой пример на три класса. Логиты $z = [2,\ 1,\ 0]$. Экспоненты: $e^2\approx7{,}389$, $e^1\approx2{,}718$, $e^0=1$. Сумма $\approx11{,}107$. Вероятности: $p_1 \approx 7{,}389/11{,}107 \approx 0{,}665$, $p_2\approx2{,}718/11{,}107\approx0{,}245$, $p_3\approx1/11{,}107\approx0{,}090$. Проверка: $0{,}665+0{,}245+0{,}090=1{,}000$ — корректное распределение вероятностей, и класс 1 с наибольшим логитом получил наибольшую вероятность, как и следовало ожидать.
Пример 2: softmax при $K=2$ — это ровно сигмоида. Зафиксируем логит одного класса за «опорный» на нуле ($z_0=0$), а логит второго — произвольный $z_1$. Тогда $p_1 = \dfrac{e^{z_1}}{e^{0}+e^{z_1}} = \dfrac{e^{z_1}}{1+e^{z_1}}$. Раздели числитель и знаменатель на $e^{z_1}$: $p_1 = \dfrac{1}{e^{-z_1}+1} = \sigma(z_1)$ — в точности та же сигмоида, с которой начинался этот урок. Многоклассовая логистическая регрессия и бинарная — не две разные модели, а одна и та же модель, где бинарный случай — это частный случай при $K=2$.
Пример 3: код и связь с нейросетями.
from sklearn.linear_model import LogisticRegression
model = LogisticRegression(multi_class="multinomial", solver="lbfgs")
model.fit(X_train, y_train) # y_train содержит несколько классов, например 0, 1, 2
probs = model.predict_proba(X_new) # массив вероятностей по каждому классу, строки суммируются в 1
Ровно та же математика — линейный слой плюс softmax плюс категориальная кросс-энтропия — стоит в конце практически любой классифицирующей нейросети: nn.Linear(hidden_dim, K) вместе с nn.CrossEntropyLoss() в PyTorch (которая внутри уже применяет softmax) или Dense(K, activation='softmax') вместе с categorical_crossentropy в Keras. Разница между глубокой сетью для классификации ImageNet на 1000 классов и сегодняшней многоклассовой логистической регрессией — только в том, что признаки $x$ в первом случае не сырые пиксели, а результат работы десятков свёрточных слоёв перед ними. Сам механизм принятия финального решения — идентичен.
Почему это важно
Понимание softmax как прямого обобщения сигмоиды снимает распространённый барьер при переходе от классического ML к глубокому обучению: это не новая, незнакомая концепция, а старая знакомая формула, применённая к $K$ классам вместо двух. Каждый раз, когда ты видишь на выходе нейросети слой softmax и рядом с ним категориальную кросс-энтропию, ты теперь точно знаешь, что происходит математически — потому что уже разобрал это на модели, которую можно полностью посчитать вручную на бумаге.
Интерпретация коэффициентов: отношение шансов
Интуиция
В линейной регрессии интерпретация коэффициента предельно простая: «увеличение $x_1$ на единицу увеличивает предсказание $y$ на $w_1$». В логистической регрессии так сказать нельзя — сигмоида нелинейна, и одно и то же увеличение $x_1$ на единицу меняет вероятность $p$ на разную величину в зависимости от того, в какой точке сигмоиды ты находишься: сильно около середины ($p\approx0{,}5$), почти незаметно у краёв ($p$ близко к 0 или к 1). Зато есть величина, которая меняется от $x_1$ строго линейно — это не сама вероятность, а её логарифм отношения шансов (log-odds), то есть в точности логит $z$.
Формальное определение
Отношение шансов (odds) и его связь с логитом:
$$\text{odds} = \frac{p}{1-p} = e^{z} = e^{w_0+w_1x_1+\dots+w_nx_n}$$$$\log(\text{odds}) = z = w_0+w_1x_1+\dots+w_nx_n$$Если увеличить признак $x_1$ на единицу (остальные признаки зафиксированы), логит увеличится на $w_1$, а сами шансы (odds) домножатся на $e^{w_1}$ — эту величину и называют odds ratio, отношением шансов.
Примеры
Пример 1: бинарный признак курения в модели риска заболевания. Пусть коэффициент при признаке «курит» равен $w_{\text{smoker}}=0{,}7$. Тогда $e^{0{,}7}\approx2{,}01$: у курящего человека шансы (не вероятность напрямую, а именно шансы $p/(1-p)$) заболеть примерно вдвое выше, чем у некурящего с теми же остальными характеристиками.
Пример 2: непрерывный признак возраста. Коэффициент при возрасте (в годах) $w_{\text{age}}=0{,}05$: $e^{0{,}05}\approx1{,}051$ — каждый дополнительный год увеличивает шансы события на 5,1%, при прочих равных условиях. За десять лет эффект накапливается мультипликативно: $e^{0{,}05\cdot10}=e^{0{,}5}\approx1{,}649$ — шансы вырастают почти в 1,65 раза, а не просто в 10 раз по 5,1% сложением.
Пример 3: почему константный odds ratio — не то же самое, что константное изменение вероятности. Возьми odds ratio ровно 2 (шансы удваиваются) в двух разных стартовых точках. Для редкого события с базовой вероятностью $p=0{,}01$: базовые шансы $0{,}01/0{,}99\approx0{,0101}$, после удвоения $\approx0{,}0202$, новая вероятность $p'=0{,}0202/1{,}0202\approx0{,}0198$ — рост всего на 0,98 процентного пункта. Для события с базовой вероятностью $p=0{,}5$: шансы $=1$, после удвоения $=2$, новая вероятность $p'=2/3\approx0{,}667$ — рост сразу на 16,7 процентного пункта. Тот же самый odds ratio 2 в разных точках даёт совершенно разный сдвиг вероятности — это тонкость, которую нужно проговаривать явно, объясняя результаты нетехнической аудитории, чтобы её не поняли неправильно.
Почему это важно
Интерпретация через odds ratio — одна из главных практических причин, по которой логистическая регрессия по-прежнему широко используется там, где решения нужно объяснять: кредитному скорингу нужно указать регулятору, за что именно клиенту дали отказ, врачу нужно объяснить пациенту вклад каждого фактора риска, страховой компании нужно обосновать тариф. Ни один градиентный бустинг или нейросеть не дают настолько же прямого, буквально в одну экспоненту, перевода коэффициента в понятную бизнес-метрику «во сколько раз меняются шансы».
Практика: 30 заданий
Базовые задания (1–10)
Задание 1: Вычисли $\sigma(0)$.
Задание 2: Вычисли $\sigma(2)$.
Задание 3: Даны веса $w_0=-3$, $w_1=1$ и признак $x=5$. Вычисли логит $z$ и вероятность $p$.
Задание 4: Модель предсказала $p=0{,}7$ для истинного $y=1$. Вычисли log loss для этого примера.
Задание 5: Модель предсказала $p=0{,}2$ для истинного $y=0$. Вычисли log loss.
Задание 6: Покажи, что при $p=0{,}5$ log loss одинаков независимо от того, $y=0$ или $y=1$.
Задание 7: Переведи вероятность $p=0{,}8$ в шансы (odds).
Задание 8: Даны шансы $\text{odds}=3$. Найди соответствующую вероятность $p$.
Задание 9: Коэффициент при признаке «возраст» $w_{\text{age}}=0{,}03$. Во сколько раз изменятся шансы события за 10 лет разницы в возрасте?
Задание 10: При пороге классификации $0{,}5$ определи предсказанный класс для логита $z=-0{,}5$.
Средние задания (11–20)
Задание 11: Вычисли значение производной сигмоиды $\sigma'(z)=\sigma(z)(1-\sigma(z))$ в точке $z=0$.
Задание 12: Для $p=0{,}7$, $y=1$, $x=2$ вычисли вклад этого примера в градиент кросс-энтропии по формуле $(p-y)\cdot x$.
Задание 13: Для $p=0{,}95$, $y=0$ сравни множитель градиента MSE ($2p(1-p)$, без учёта $(p-y)$) и множитель градиента кросс-энтропии (константа 1, без учёта $(p-y)$).
Задание 14: Вычисли softmax для логитов $z=[1,\ 1,\ 1]$.
Задание 15: Покажи алгебраически, что softmax с опорным логитом $z_0=0$ и вторым логитом $z_1$ сводится к сигмоиде $\sigma(z_1)$.
Задание 16: Даны веса $w_0=-6$, $w_1=2$, $w_2=3$. Найди уравнение границы решения (где $p=0{,}5$) как зависимость $x_2$ от $x_1$.
Задание 17: Объясни на примере двух точек ($y_1=1, p_1=0{,}8$) и ($y_2=0, p_2=0{,}4$), почему минимизация кросс-энтропии эквивалентна максимизации правдоподобия распределения Бернулли (связь с уроком 246).
Задание 18: Опираясь на результат урока 278 ($\nabla^2 L(w)=\frac1nX^\top SX \succeq 0$) и Ridge-регуляризацию из урока 312, объясни, почему регуляризованная логистическая регрессия $L_{\text{ridge}}(w)=L(w)+\frac{\lambda}{2}\|w\|^2$ строго выпукла при любом $\lambda>0$.
Задание 19: В датасете 95% примеров класса 0 и 5% класса 1. Объясни, почему порог $0{,}5$ и метрика accuracy могут вводить в заблуждение, и предложи альтернативу (связь с уроком 309).
Задание 20: Напиши код обучения LogisticRegression с параметром регуляризации C=0.1 и объясни связь C с параметром $\lambda$ из урока 312.
Продвинутые задания (21–30)
Задание 21: Выведи полную формулу градиента $\partial L/\partial w$ для одного примера через цепное правило, начиная с $L=-[y\log p+(1-y)\log(1-p)]$, $p=\sigma(z)$, $z=w^\top x$.
Задание 22: Датасет из трёх примеров: $(x_1=1,y_1=1)$, $(x_2=-1,y_2=0)$, $(x_3=2,y_3=1)$, модель с одним весом $w_0=0$, $\alpha=0{,}2$. Сделай два шага градиентного спуска.
Задание 23: Докажи в общем виде (для произвольного $K$), что softmax с опорным логитом $z_1=0$ сводится к $K-1$-мерному обобщению сигмоиды, выразив $p_k$ для $k\ge2$ через логиты $z_2,\dots,z_K$.
Задание 24: Для одинакового odds ratio $=2$ сравни изменение вероятности при базовой вероятности $p=0{,}01$ и при $p=0{,}5$ (см. пример 3 раздела про odds ratio) и сформулируй общий вывод.
Задание 25: Объясни риск переполнения при прямом вычислении softmax для больших логитов (например, $z=[1000,\ 999,\ 998]$) и выведи log-sum-exp трюк — вычитание максимума логита перед экспонированием.
Задание 26: Опираясь на теорему урока 278 («у выпуклой функции любой локальный минимум — глобальный») и доказанную в этом уроке выпуклость кросс-энтропии, объясни, почему солверы liblinear, lbfgs, newton-cg и saga в sklearn сходятся к практически одинаковым коэффициентам на одной и той же задаче.
Задание 27: Докажи, что граница решения $\{x : p(x)=0{,}5\}$ логистической регрессии — всегда гиперплоскость, и объясни, почему это фундаментальное ограничение модели.
Задание 28: Дана функция потерь с весами классов $L=-\frac1n\sum_i c_{y_i}\big[y_i\log p_i+(1-y_i)\log(1-p_i)\big]$, $c_1=5$, $c_0=1$. Вычисли взвешенный вклад в потерю для примера ($y=1$, $p=0{,}3$) с весом и без веса класса.
Задание 29: Три класса, два примера. Пример 1: логиты $z=[1, 0, -1]$, истинный класс 1 (то есть $y=[1,0,0]$). Пример 2: логиты $z=[0, 2, 0]$, истинный класс 2 ($y=[0,1,0]$). Вычисли softmax для обоих примеров и среднюю категориальную кросс-энтропию.
Задание 30: Своими словами объясни, как сигмоида с log loss для бинарной классификации и softmax с категориальной кросс-энтропией для многоклассовой связаны с выходным слоем нейросетей, приведи конкретные названия функций из PyTorch или Keras.
Частые ошибки
Ошибка 1. Считают, что логистическая регрессия предсказывает число, как обычная (линейная) регрессия, из-за слова «регрессия» в названии.
Как выглядит: попытка интерпретировать выход model.predict() как непрерывную величину или удивление, что модель выдаёт только 0 и 1.
Почему возникает: название исторически унаследовано от статистической традиции (урок про Дэвида Кокса и регрессию для параметра распределения Бернулли), а не отражает современное разделение задач на регрессию и классификацию.
Как правильно: логистическая регрессия — модель классификации; она напрямую предсказывает вероятность класса через predict_proba(), а predict() лишь применяет к этой вероятности порог (обычно $0{,}5$) и возвращает метку класса.
Ошибка 2. Интерпретируют сырой логит $z$ (выход model.decision_function()) напрямую как вероятность, не пропуская его через сигмоиду.
Как выглядит: «модель выдала z=3, значит, вероятность 3» или сравнение логитов с порогом $0{,}5$ вместо порога $0$.
Почему возникает: логит и вероятность связаны монотонно, поэтому кажется, что можно работать с любым из двух без разницы.
Как правильно: логит $z$ лежит на всей числовой прямой, вероятность $p=\sigma(z)$ — строго в $(0,1)$; порог $p\ge0{,}5$ эквивалентен порогу $z\ge0$, но сравнивать логит напрямую с $0{,}5$ (как если бы это была вероятность) — грубая ошибка.
Ошибка 3. Используют MSE вместо кросс-энтропии по инерции от линейной регрессии, не задумываясь о последствиях.
Как выглядит: реализация логистической регрессии «с нуля», где функция потерь скопирована из кода линейной регрессии — среднеквадратичная ошибка применяется к выходу сигмоиды.
Почему возникает: MSE — первая функция потерь, которую изучают, и кажется универсальной для любой задачи с числовым выходом.
Как правильно: для сигмоиды используй кросс-энтропию — она не только теоретически обоснована через максимальное правдоподобие (урок 246), но и даёт значительно более здоровые, не затухающие градиенты при уверенных ошибках, что напрямую ускоряет обучение.
Ошибка 4. Интерпретируют коэффициент $w_1$ как прямое изменение вероятности при увеличении $x_1$ на единицу.
Как выглядит: «коэффициент 0,05 означает, что вероятность вырастет на 5%» — независимо от того, в какой точке сигмоиды находится модель.
Почему возникает: привычка к линейной регрессии, где коэффициент действительно и есть прямое изменение предсказания.
Как правильно: коэффициент $w_1$ линейно связан с логитом (log-odds), а не с самой вероятностью; правильная интерпретация — через odds ratio $e^{w_1}$ («шансы изменятся в $e^{w_1}$ раз»), и, как показано в задании 24, одинаковый odds ratio даёт разный сдвиг вероятности в разных точках.
Ошибка 5. Не масштабируют признаки перед обучением регуляризованной логистической регрессии (связь с уроком 312).
Как выглядит: один признак измеряется в рублях (диапазон до миллионов), другой — в долях от единицы; после обучения с L2-регуляризацией коэффициент при «крупном» признаке подавлен несоразмерно сильно.
Почему возникает: штраф регуляризации одинаково давит на все веса по величине, но веса при признаках разного масштаба изначально имеют разный порядок величины.
Как правильно: перед обучением регуляризованной логистической регрессии сначала примени StandardScaler (или аналог) ко всем числовым признакам — ровно та же рекомендация, что уже звучала для Ridge и Lasso в уроке 312, здесь она не менее критична.
Ошибка 6. Оставляют порог классификации по умолчанию на $0{,}5$ вне зависимости от дисбаланса классов и реальной стоимости ошибок разного рода.
Как выглядит: на сильно несбалансированном датасете (редкое, но дорогое событие — мошенничество, серьёзное заболевание) модель почти никогда не предсказывает положительный класс при пороге $0{,}5$, хотя predict_proba даёт разумные вероятности.
Почему возникает: порог $0{,}5$ — значение по умолчанию во всех библиотеках, и кажется «нейтральным» решением, не требующим дополнительного анализа.
Как правильно: подбирай порог осознанно, исходя из ROC-кривой или PR-кривой (урок 308) и реальной асимметрии стоимости ложноположительных и ложноотрицательных ошибок (урок 309) — для редких и дорогих событий порог часто стоит заметно снижать ниже $0{,}5$.
Главное запомнить
-
Логистическая регрессия — модель бинарной классификации, несмотря на слово «регрессия» в названии, доставшееся от статистической традиции Дэвида Кокса.
-
Модель строится в два шага: линейная комбинация признаков $z=w^\top x$ (логит), затем сигмоида $p=\sigma(z)=1/(1+e^{-z})$ сжимает логит в вероятность $(0,1)$.
-
Функция потерь — бинарная кросс-энтропия (log loss), которая математически эквивалентна максимизации правдоподобия распределения Бернулли (прямая связь с уроком 246).
-
Кросс-энтропия предпочтительнее MSE не только теоретически, но и практически: её градиент по логиту упрощается ровно до $(p-y)$, без затухающего множителя $p(1-p)$, который делает обучение с MSE медленным именно там, где модель уверенно ошибается.
-
Кросс-энтропия логистической регрессии доказуемо выпукла (гессиан $\frac1nX^\top SX\succeq0$, урок 278) — градиентный спуск гарантированно сходится к глобальному минимуму вне зависимости от точки старта и выбранного солвера.
-
Многоклассовое обобщение сигмоиды — softmax: превращает $K$ произвольных логитов в распределение вероятностей, при $K=2$ в точности сводится к обычной сигмоиде.
-
Коэффициенты модели интерпретируются через отношение шансов (odds ratio): увеличение признака на единицу домножает шансы события на $e^{w_i}$, а не сдвигает саму вероятность на фиксированную величину.
-
Граница решения логистической регрессии — всегда линейная гиперплоскость $w^\top x=0$; для существенно нелинейно разделимых данных нужны полиномиальные признаки или другие модели.
-
Сигмоида и softmax с соответствующими функциями потерь — это ровно тот же механизм, что используется на выходном слое нейросетей для бинарной и многоклассовой классификации.
-
sklearn.linear_model.LogisticRegression— типичный baseline-классификатор в реальных ML-проектах: быстрый, устойчивый, интерпретируемый ориентир, с которым сравнивают более сложные модели.
Связь с темами курса
Что нужно было знать до этого урока
Этот урок прямо опирается на три предыдущих. Из урока 246 про оценку параметров и метод максимального правдоподобия взят принцип, из которого выводится сама формула кросс-энтропии, — минимизация log loss эквивалентна максимизации правдоподобия распределения Бернулли, и сегодня этот вывод был доведён до окончательной практической формы. Из урока 278 про выпуклые функции взят уже полностью доказанный факт, что гессиан кросс-энтропии логистической регрессии положительно полуопределён ($\nabla^2L(w)=\frac1nX^\top SX$, где $S=\operatorname{diag}(p_i(1-p_i))$) — этот вывод здесь не повторялся, а использовался как готовый результат, чтобы объяснить, почему обучение градиентным спуском гарантированно сходится к глобальному минимуму. Из урока 312 про Ridge и Lasso — L2-регуляризация, которая при добавлении к логистической регрессии по тому же самому аргументу (сдвиг гессиана на $\lambda I$) восстанавливает строгую выпуклость и единственность решения, а также требование масштабировать признаки перед регуляризованным обучением.
Что изучить дальше
Следующий урок 314 переходит к принципиально другому подходу — методу k ближайших соседей (k-Nearest Neighbors), непараметрической модели классификации, которая вообще не строит линейную границу решения и не имеет весов для обучения в привычном смысле: решение принимается по соседям в пространстве признаков в момент предсказания. Контраст с логистической регрессией будет наглядным: там, где логистическая регрессия жёстко ограничена линейной границей (задание 27 этого урока), k-NN может в принципе аппроксимировать сколь угодно сложную, изогнутую границу — ценой потери интерпретируемости коэффициентов и заметно более медленного предсказания на больших датасетах.
Где это нужно в жизни
🏦 Кредитный скоринг. Банки и МФО по всему миру используют логистическую регрессию (или её прямое развитие — модели на основе WOE-преобразований) как основу скоринговых карт именно из-за требований регуляторов к объяснимости решений — каждый отказ в кредите можно разложить на вклад отдельных факторов через коэффициенты и odds ratio.
🏥 Медицинская диагностика и эпидемиология. Логистическая регрессия — стандартный инструмент для оценки факторов риска заболеваний (курение, возраст, давление) начиная с классических эпидемиологических исследований середины XX века; odds ratio остаётся стандартной метрикой в медицинских публикациях по сей день.
📧 Спам-фильтрация и модерация контента. Простые и быстрые логистические классификаторы поверх признаков текста (или как часть ансамбля с более сложными моделями) до сих пор используются там, где нужна скорость обработки миллионов сообщений в реальном времени.
📉 Отток клиентов (churn) и конверсия. Телеком-операторы и подписочные сервисы предсказывают вероятность ухода клиента или вероятность конверсии в покупку логистической регрессией как быстрым интерпретируемым baseline перед тестированием более тяжёлых моделей.
🧠 Глубокое обучение. Финальный слой практически любой классифицирующей нейросети — от простого MLP до трансформеров для текста и свёрточных сетей для изображений — математически идентичен сигмоиде или softmax из сегодняшнего урока, применённым к выученным сетью признакам вместо сырых.
Интересные факты
-
Слово «логистическая» в названии не имеет никакого отношения к логистике как отрасли перевозок — оно происходит от предложенного Пьером Франсуа Ферхюльстом в 1838 году термина для S-образной кривой ограниченного роста населения, за сто с лишним лет до появления самой модели классификации.
-
Несмотря на слово «регрессия» в названии, современное машинное обучение однозначно относит логистическую регрессию к алгоритмам классификации — это один из самых стойких примеров того, как историческое название модели расходится с её актуальной классификацией по типу решаемой задачи.
-
Функция softmax получила своё название как «мягкая» версия функции argmax: если softmax применить к логитам, один из которых значительно больше остальных, распределение вероятностей окажется практически вырожденным — почти вся масса сосредоточится на одном классе, приближая жёсткий (hard) выбор argmax, но никогда не достигая его в точности, поскольку экспонента строго положительна для любого конечного логита.
-
Фрамингемское исследование сердечно-сосудистых заболеваний, одно из самых влиятельных долгосрочных эпидемиологических исследований в истории медицины (начато в 1948 году в городе Фрамингем, США), стало одной из первых масштабных практических площадок для применения логистической регрессии к оценке факторов риска — результаты этого исследования напрямую сформировали современное представление о факторах риска инфаркта и инсульта.
Лайфхаки
-
Перед обучением регуляризованной логистической регрессии (с
penalty='l2'или'l1') всегда сначала масштабируй признаки черезStandardScaler— иначе штраф регуляризации по-разному «давит» на признаки разного масштаба, что прямо повторяет предупреждение из урока про Ridge и Lasso. -
Для несбалансированных классов сразу пробуй параметр
class_weight='balanced'вLogisticRegression— это автоматически взвешивает вклад редкого класса в функцию потерь (как в задании 28), часто без необходимости вручную передискретизировать датасет. -
Не полагайся на accuracy как единственную метрику качества — сразу смотри на
predict_proba, ROC-AUC и confusion matrix (уроки 307–309), особенно если классы несбалансированы или ошибки разных типов стоят по-разному. -
Если реализуешь softmax или кросс-энтропию вручную (не через готовую библиотечную функцию), обязательно используй log-sum-exp трюк — вычитание максимального логита перед экспонированием (задание 25) — иначе на больших логитах получишь переполнение (
inf/NaN) в вычислениях. -
Используй логистическую регрессию как первый, самый быстрый baseline на новой задаче классификации — если более сложная модель (градиентный бустинг, нейросеть) не даёт заметного прироста качества по сравнению с ней, возможно, дополнительная сложность того не стоит, а интерпретируемость коэффициентов при этом будет потеряна зря.
-
Если нужно объяснить коэффициенты модели нетехнической аудитории, переводи их в odds ratio через $e^{w_i}$ и формулируй как «шансы изменяются в стольких-то раз», а не как «вероятность меняется на столько-то процентов» — вторая формулировка технически некорректна почти всегда, что подробно разобрано в задании 24.
Логистическая регрессия — модель, с которой сегодня начинается вся линейка классификаторов курса, и лучший способ увидеть в ней не просто «ещё одну формулу», а рабочий инструмент — прогнать её на реальных данных и честно сравнить с более сложными моделями, которые встретятся впереди. В следующий раз, когда ты увидишь вызов model.predict_proba(X) в чужом или своём коде, или строку Dense(1, activation='sigmoid') в архитектуре нейросети, ты будешь точно знать, какая арифметика стоит за этими несколькими символами — от логита и сигмоиды до кросс-энтропии, выпуклости и гарантированной сходимости градиентного спуска, которую ты не просто принял на веру, а прошёл шаг за шагом сам.
Понял тему? Закрепи в боте! 🚀
Попрактикуйся на задачах и получи персональные рекомендации от AI
💪 Начать тренировку