🔴 Сложный ⏱️ 55 минут

Функция распределения

📋 Содержание урока

Функция распределения 📊

Ты выкатил модель в прод. Через неделю приходит дежурный инженер и говорит: «Сервис тормозит, пользователи жалуются». Ты открываешь дашборд, смотришь на среднее время ответа — $180$ мс. Отлично же! SLA у вас $500$ мс, запас двукратный. Ты пишешь в чат «всё в порядке, среднее в норме», и через два дня получаешь разбор инцидента, где чёрным по белому: каждый двадцатый запрос отваливался по таймауту, а самые тяжёлые клиенты — те, у кого больше данных, — ловили это постоянно.

Что произошло? Среднее — это одно число, и оно не знает ничего про хвост. Оно одинаковое у сервиса, который стабильно отвечает за $180$ мс, и у сервиса, который в $95\%$ случаев отвечает за $60$ мс, а в $5\%$ — за две секунды. Чтобы различить эти два мира, нужен объект, который хранит всю информацию о случайной величине сразу: не «в среднем сколько», а «какая доля значений лежит левее любой заданной границы». Такой объект есть, он ровно один, и называется он функция распределения.

В прошлом уроке мы ввели случайную величину и научились описывать её рядом распределения — таблицей «значение → вероятность». Для дискретной величины это работает. А что делать с временем ответа сервиса, которое может быть любым положительным числом? Таблица не влезет: значений континуум, а вероятность каждого конкретного — ноль. Нужен другой язык описания, единый для всех случайных величин на свете — дискретных, непрерывных и смешанных. Этот язык — функция $F(x)$, которая каждому числу $x$ сопоставляет вероятность того, что величина окажется левее него.

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

🎯 Ты узнаешь:

  • Что такое функция распределения $F(x) = P(X < x)$, чем она отличается от ряда распределения и почему существует у любой случайной величины
  • Четыре свойства $F$, из которых выводится вся остальная арифметика вероятностей: $P(a \le X < b) = F(b) - F(a)$
  • Почему у дискретной величины график ступенчатый и скачок в точке равен вероятности этого значения, а у непрерывной $P(X = a) = 0$ — но это вовсе не значит «невозможно»
  • Как через $F$ определяются медиана, квантили и перцентили — включая коварный случай, когда квантиль не единственный
  • Как обратная функция $F^{-1}$ превращает равномерный random() в любое распределение, и почему ROC-кривая — это параметрический график двух функций распределения

История: откуда это взялось?

Идея «накопленной вероятности» появилась задолго до того, как получила имя. Уже в 1733 году Абрахам де Муавр, приближая биномиальные вероятности гладкой кривой, фактически считал суммы вида $P(k_1 \le k \le k_2)$ — то есть работал с накопленными вероятностями, хотя отдельной функции для этого не выделял. Пьер-Симон Лаплас в «Аналитической теории вероятностей» (1812) систематически пользовался интегралами от плотности по промежутку — и снова это была накопленная вероятность, но без самостоятельного статуса.

Настоящий поворот случился в XIX веке у Пафнутия Чебышёва и его учеников — Андрея Маркова и Александра Ляпунова. Им нужно было доказывать предельные теоремы для сумм случайных величин, у которых плотности может не быть вовсе (или про неё ничего не известно). Ляпунов в работах 1900–1901 годов формулирует условия центральной предельной теоремы именно в терминах функций распределения — и это оказывается принципиально: сходимость функций распределения (её позже назовут слабой сходимостью, или сходимостью по распределению) работает там, где сходимость плотностей просто не имеет смысла. С этого момента $F(x)$ перестаёт быть техническим приёмом и становится главным объектом теории.

Точку поставил Андрей Николаевич Колмогоров в 1933 году в «Основных понятиях теории вероятностей». В его аксиоматике случайная величина — это измеримая функция на вероятностном пространстве, а функция распределения — её полный «паспорт»: две случайные величины могут быть устроены совершенно по-разному (одна — результат броска кубика в Москве, другая — шум датчика в Токио), но если их функции распределения совпадают, то с вероятностной точки зрения они неразличимы. Более того, Колмогоров показал: любая функция, обладающая четырьмя свойствами, которые мы сейчас разберём, является функцией распределения какой-то случайной величины. Не «бывает», а точно есть — это теорема о существовании.

А сегодня эта функция — самая используемая вещь в прикладной статистике и ML, только под разными именами. scipy.stats.norm.cdf — это она. Перцентиль p95 на дашборде Grafana — это её обратная. numpy.random.exponential внутри устроен через неё. ROC-кривая — это параметрический график двух таких функций. Калибровочная кривая, KS-тест на дрейф данных, квантильные бины в LightGBM, winsorize для выбросов — везде под капотом одна и та же $F(x)$, придуманная для доказательства предельных теорем сто с лишним лет назад.


Определение: одна функция вместо всей таблицы

Интуиция

Представь, что у тебя есть длинная линейка — числовая ось, — и вдоль неё как-то распределена «вероятностная масса» общим весом $1$. У дискретной величины эта масса сидит комками в отдельных точках: комок $0{,}2$ в точке $1$, комок $0{,}5$ в точке $2$. У непрерывной — размазана тонким слоем, как масло по хлебу, и в каждой отдельной точке её ровно ноль, зато на любом отрезке — что-то есть.

Теперь берём ползунок и медленно ведём его слева направо по этой оси. И в каждый момент спрашиваем: сколько массы уже осталось позади? Вот эта «показания счётчика в зависимости от положения ползунка» и есть функция распределения. Слева, в минус бесконечности, счётчик показывает $0$ — ничего ещё не набрали. Справа, в плюс бесконечности, показывает $1$ — набрали всё. По дороге счётчик может расти скачками (когда ползунок проезжает комок) или плавно (когда едет по размазанному слою), но назад он не откатывается никогда.

Это очень естественная конструкция. Когда ты смотришь на дашборд и видишь «$95\%$ запросов быстрее $340$ мс» — это ровно значение функции распределения времени ответа в точке $340$: $F(340) = 0{,}95$. Когда HR говорит «твоя зарплата выше, чем у $70\%$ коллег» — это $F(\text{зарплата}) = 0{,}7$. Когда врач говорит про рост ребёнка «$60$-й перцентиль» — это опять она.

Определение: Функцией распределения случайной величины $X$ называется функция $F(x)$, определённая для всех вещественных $x$ равенством

$$F(x) = P(X < x)$$

то есть вероятность того, что случайная величина примет значение, строго меньшее $x$.

Обрати внимание на слово «строго». Здесь есть развилка, о которой обязательно нужно договориться заранее.

Две конвенции: $<$ и $\le$ — и почему это не мелочь

В литературе встречаются два определения:

  • Русская традиция (Гмурман, Вентцель, большинство отечественных учебников): $F(x) = P(X < x)$ — строгое неравенство.
  • Международная традиция (Феллер, Биллингсли, вся англоязычная литература и весь научный софт): $F(x) = P(X \le x)$ — нестрогое. Английское название — cumulative distribution function, CDF.

Для непрерывной величины разницы нет вообще никакой: там $P(X = x) = 0$, и обе формулы дают одно и то же число. Разница вылезает только в точках, где сидит «комок» вероятности — то есть у дискретных и смешанных величин.

$$\underbrace{P(X \le x)}_{\text{нестрогая версия}} = \underbrace{P(X < x)}_{\text{строгая версия}} + P(X = x)$$

Разница — ровно размер скачка в точке $x$.

Практическое следствие, которое стоит запомнить намертво:

  • при $F(x) = P(X < x)$ функция непрерывна слева: $F(x - 0) = F(x)$;
  • при $F(x) = P(X \le x)$ функция непрерывна справа: $F(x + 0) = F(x)$.

В этом уроке мы работаем со строгой версией $F(x) = P(X < x)$ — она принята в курсе и даёт красивую формулу $P(a \le X < b) = F(b) - F(a)$. Но когда ты сядешь за код, помни: scipy.stats.binom.cdf(k, n, p) возвращает $P(X \le k)$, потому что весь научный софт живёт по международной конвенции. Это одна из самых частых причин ошибки «на единицу» при работе с дискретными распределениями.

📌 Мнемоника: в русской конвенции $F$ смотрит строго налево, значение в точке ещё «не засчитано»; в международной — точка уже включена. Проверить, какая конвенция у тебя в коде, можно одной строкой: для честной монеты binom.cdf(0, 1, 0.5) даст $0{,}5$ (значит, $\le$), а не $0$.

Почему $F$ существует всегда

Ряд распределения (таблица «значение → вероятность») существует только у дискретных величин. Плотность (о ней — в следующем уроке) — только у непрерывных. А функция распределения есть у любой случайной величины: вопрос «какова вероятность, что $X$ меньше $x$?» осмыслен всегда, для любого $x$.

Больше того, $F$ задаёт распределение однозначно и полностью. Если ты знаешь $F$, ты можешь восстановить вероятность любого разумного события, связанного с $X$: попадание в интервал, в объединение интервалов, в точку. Ничего больше знать не нужно. Именно поэтому $F$ называют паспортом случайной величины.

Примеры с разбором

Пример 1 (простой): построй функцию распределения для броска монеты

Пусть $X$ — число орлов при одном броске честной монеты: $X = 0$ с вероятностью $0{,}5$ и $X = 1$ с вероятностью $0{,}5$.

Решение:

Шаг 1. Возьмём произвольное $x \le 0$. Событие $\{X < x\}$ означает, что число орлов меньше $x \le 0$. Но $X$ принимает только значения $0$ и $1$, оба $\ge 0$. Значит, событие невозможно: $F(x) = 0$.

Отдельно проверим точку $x = 0$: $F(0) = P(X < 0) = 0$ — значение $X = 0$ сюда не входит, потому что неравенство строгое.

Шаг 2. Пусть $0 < x \le 1$. Тогда $\{X < x\}$ выполняется только при $X = 0$ (значение $1$ не подходит: при $x \le 1$ неравенство $1 < x$ ложно). Значит, $F(x) = P(X = 0) = 0{,}5$.

Шаг 3. Пусть $x > 1$. Теперь подходят оба значения: и $0 < x$, и $1 < x$. Значит, $F(x) = P(X = 0) + P(X = 1) = 1$.

Шаг 4. Собираем ответ:

$$F(x) = \begin{cases} 0, & x \le 0 \\ 0{,}5, & 0 < x \le 1 \\ 1, & x > 1 \end{cases}$$

Проверка: слева функция уходит в $0$, справа — в $1$, не убывает ✅

Ответ: ступенчатая функция с двумя скачками по $0{,}5$ — в точках $x = 0$ и $x = 1$.


Пример 2 (средний): равномерная величина на отрезке

Датчик выдаёт число, равномерно распределённое на отрезке $[0; 4]$: вероятность попасть в любой подотрезок пропорциональна его длине. Найди $F(x)$.

Решение:

Шаг 1. При $x \le 0$ левее $x$ никакой вероятностной массы нет: $F(x) = 0$.

Шаг 2. При $0 < x \le 4$ событие $\{X < x\}$ — это попадание в отрезок $[0; x)$ длины $x$. Вся масса $1$ размазана по отрезку длины $4$, значит, на кусок длины $x$ приходится доля

$$F(x) = \frac{x - 0}{4 - 0} = \frac{x}{4}$$

Шаг 3. При $x > 4$ вся масса уже позади: $F(x) = 1$.

Шаг 4. Ответ:

$$F(x) = \begin{cases} 0, & x \le 0 \\ \dfrac{x}{4}, & 0 < x \le 4 \\ 1, & x > 4 \end{cases}$$

Проверка: $F(2) = 0{,}5$ — ровно половина массы левее середины отрезка, логично ✅ График — прямая линия, поднимающаяся от $(0;0)$ до $(4;1)$, с горизонтальными «полками» слева и справа.

Ответ: $F(x) = x/4$ на $[0;4]$, $0$ слева и $1$ справа.


Пример 3 (сложный): обратная задача — восстановить величину по её $F$

Дана функция

$$F(x) = \begin{cases} 0, & x \le -1 \\ 0{,}25, & -1 < x \le 2 \\ 0{,}6, & 2 < x \le 5 \\ 1, & x > 5 \end{cases}$$

Восстанови ряд распределения и найди $P(X = 2)$, $P(X \ge 2)$, $P(-1 \le X < 5)$.

Решение:

Шаг 1. Функция ступенчатая, значит, величина дискретная. Скачки происходят в точках $-1$, $2$, $5$ — это и есть возможные значения $X$.

Шаг 2. Размер скачка в точке $a$ равен вероятности значения $a$. Считаем скачки как «значение справа минус значение в точке»:

  • в точке $-1$: $0{,}25 - 0 = 0{,}25$;
  • в точке $2$: $0{,}6 - 0{,}25 = 0{,}35$;
  • в точке $5$: $1 - 0{,}6 = 0{,}4$.

Шаг 3. Ряд распределения:

$x_i$ $-1$ $2$ $5$
$p_i$ $0{,}25$ $0{,}35$ $0{,}4$

Контроль: $0{,}25 + 0{,}35 + 0{,}4 = 1$ ✅

Шаг 4. $P(X = 2) = 0{,}35$ — это размер скачка, найденный на шаге 2.

Шаг 5. $P(X \ge 2) = 1 - P(X < 2) = 1 - F(2) = 1 - 0{,}25 = 0{,}75$.

Проверим напрямую: $P(X = 2) + P(X = 5) = 0{,}35 + 0{,}4 = 0{,}75$ ✅

Шаг 6. $P(-1 \le X < 5) = F(5) - F(-1) = 0{,}6 - 0 = 0{,}6$.

Проверим: в промежуток $[-1; 5)$ попадают значения $-1$ и $2$, их суммарная вероятность $0{,}25 + 0{,}35 = 0{,}6$ ✅

Ответ: $P(X=2) = 0{,}35$; $P(X \ge 2) = 0{,}75$; $P(-1 \le X < 5) = 0{,}6$.

Почему это важно

Функция распределения — это единый интерфейс ко всем случайным величинам сразу. В коде это буквально так: у любого объекта scipy.stats есть метод .cdf(), и неважно, дискретное это распределение или непрерывное. Один и тот же алгоритм — например, KS-тест на дрейф данных или метод обратного преобразования для сэмплирования — работает через этот интерфейс с чем угодно.

И ещё: именно на языке функций распределения формулируется сходимость по распределению. Когда говорят «сумма нормируется к нормальному закону» (центральная предельная теорема, урок 241), имеют в виду поточечную сходимость $F_n(x) \to \Phi(x)$. Никакого другого языка для этого утверждения нет — плотности могут не существовать, а $F$ есть всегда.


Свойства функции распределения

Интуиция

Вернёмся к образу ползунка и счётчика. Из него сразу видно, как $F$ обязана себя вести:

  • счётчик не может уменьшаться — масса, оставшаяся позади, только накапливается;
  • значения счётчика лежат между $0$ и $1$ — это вероятность;
  • в самом начале (минус бесконечность) он показывает $0$, в самом конце — $1$;
  • разность показаний в двух точках — это масса, набранная между ними.

Вот и все свойства. Дальше — аккуратные формулировки и доказательства.

Свойство 1 (ограниченность): $0 \le F(x) \le 1$ для любого $x$.

Почему: $F(x)$ — это вероятность события $\{X < x\}$, а любая вероятность лежит между нулём и единицей. Тут нечего доказывать сверх аксиом.

Свойство 2 (неубывание): если $x_1 < x_2$, то $F(x_1) \le F(x_2)$.

Доказательство. Событие $\{X < x_2\}$ можно разбить на два несовместных: «$X < x_1$» и «$x_1 \le X < x_2$». По теореме сложения (урок 229):

$$P(X < x_2) = P(X < x_1) + P(x_1 \le X < x_2)$$

то есть

$$F(x_2) = F(x_1) + P(x_1 \le X < x_2)$$

Второе слагаемое неотрицательно как вероятность, значит, $F(x_2) \ge F(x_1)$. ∎

Из этого же равенства сразу выпадает главная рабочая формула урока:

Свойство 3 (вероятность попадания в промежуток):

$$P(a \le X < b) = F(b) - F(a)$$

Обрати внимание на асимметрию неравенств: левый конец включён, правый — нет. Это прямое следствие конвенции $F(x) = P(X < x)$. Если бы мы работали с $F(x) = P(X \le x)$, формула была бы $P(a < X \le b) = F(b) - F(a)$ — включён правый конец. Обе версии верны каждая в своей системе, путать их нельзя.

Свойство 4 (пределы на бесконечностях):

$$\lim_{x \to -\infty} F(x) = 0, \qquad \lim_{x \to +\infty} F(x) = 1$$

Почему: событие $\{X < x\}$ при $x \to -\infty$ стягивается к невозможному (случайная величина принимает конечные значения, значит, левее любой достаточно далёкой границы её не бывает), а при $x \to +\infty$ раздувается до достоверного. Формально это следует из непрерывности вероятностной меры на монотонных последовательностях событий — аксиома непрерывности в системе Колмогорова.

Практическое следствие: если тебе дали «функцию распределения», у которой предел справа равен, скажем, $0{,}8$ — это не функция распределения. Где-то потеряли $20\%$ вероятностной массы (или условие задачи содержит параметр, который надо найти именно из этого условия — типовой приём).

Свойство 5 (непрерывность слева): $F(x - 0) = F(x)$, то есть $\lim_{t \to x^-} F(t) = F(x)$ в каждой точке.

Почему: возьмём возрастающую последовательность $t_n \uparrow x$. События $\{X < t_n\}$ расширяются и в пределе дают ровно $\{X < x\}$ (любой исход, где $X < x$, попадёт в какое-то $\{X < t_n\}$ при достаточно большом $n$; исход с $X = x$ не попадёт ни в одно). По непрерывности меры $F(t_n) \to F(x)$. ∎

А вот справа $F$ может иметь разрыв — и именно этот разрыв несёт информацию о «комках» вероятности:

Свойство 6 (скачок = вероятность точки):

$$P(X = a) = F(a + 0) - F(a)$$

где $F(a+0) = \lim_{t \to a^+} F(t)$ — предел справа.

Доказательство. $F(a + 0) = \lim P(X < t)$ при $t \downarrow a$. События $\{X < t\}$ сужаются к $\{X \le a\}$, значит, $F(a+0) = P(X \le a)$. Вычитаем $F(a) = P(X < a)$:

$$F(a+0) - F(a) = P(X \le a) - P(X < a) = P(X = a) \qquad \blacksquare$$

Это ключ ко всей арифметике. Если $F$ непрерывна в точке $a$, скачка нет, и $P(X = a) = 0$. Если есть скачок высотой $h$, то $P(X = a) = h$.

Таблица переводов: любое событие через $F$

Из свойств 3 и 6 выводятся формулы для всех типов промежутков. Держи её под рукой — она закрывает $90\%$ задач:

Событие Через $F$ (конвенция $F(x) = P(X
$P(X < a)$ $F(a)$
$P(X \le a)$ $F(a + 0) = F(a) + P(X = a)$
$P(X \ge a)$ $1 - F(a)$
$P(X > a)$ $1 - F(a) - P(X = a)$
$P(a \le X < b)$ $F(b) - F(a)$
$P(a < X < b)$ $F(b) - F(a) - P(X = a)$
$P(a \le X \le b)$ $F(b) - F(a) + P(X = b)$
$P(X = a)$ $F(a+0) - F(a)$

Для непрерывной величины все $P(X = a) = 0$, и таблица схлопывается: любой промежуток с концами $a$ и $b$ имеет вероятность $F(b) - F(a)$, а строгость неравенств вообще не играет роли. Это огромное упрощение — и одновременно ловушка, потому что для дискретных величин так делать нельзя.

Теорема о характеризации

Теорема: Функция $F: \mathbb{R} \to [0;1]$ является функцией распределения некоторой случайной величины тогда и только тогда, когда она (а) не убывает, (б) непрерывна слева, (в) имеет пределы $0$ в $-\infty$ и $1$ в $+\infty$.

Это очень сильное утверждение: три простых условия — и объект гарантированно существует. Нарисовал любую неубывающую лесенку от нуля до единицы — и уже задал какое-то распределение. В задачах это работает как чек-лист: чтобы проверить, годится ли данная функция на роль $F$, прогоняешь три пункта, и если хоть один нарушен — ответ «не является».

Примеры с разбором

Пример 4 (простой): считаем вероятности по готовой $F$

Дана $F(x) = 0$ при $x \le 0$; $F(x) = x/4$ при $0 < x \le 4$; $F(x) = 1$ при $x > 4$. Найди $P(1 \le X < 3)$, $P(X \ge 2)$, $P(X = 2)$.

Решение:

Шаг 1. $P(1 \le X < 3) = F(3) - F(1) = \dfrac{3}{4} - \dfrac{1}{4} = \dfrac{1}{2} = 0{,}5$.

Шаг 2. $P(X \ge 2) = 1 - F(2) = 1 - \dfrac{2}{4} = 0{,}5$.

Шаг 3. $F$ непрерывна всюду (в точках $0$ и $4$ куски стыкуются: $0/4 = 0$ и $4/4 = 1$), скачков нет, значит, $P(X = 2) = 0$.

Проверка на здравый смысл: отрезок $[1;3)$ — это половина отрезка $[0;4]$, и вероятность вышла ровно $0{,}5$ ✅

Ответ: $0{,}5$; $0{,}5$; $0$.


Пример 5 (средний): находим параметр из условия на пределы

Функция задана как

$$F(x) = \begin{cases} 0, & x \le 0 \\ a x^2, & 0 < x \le 3 \\ 1, & x > 3 \end{cases}$$

Найди $a$ и вычисли $P(1 \le X < 2)$.

Решение:

Шаг 1. Функция распределения не может иметь скачка «вникуда»: если бы в точке $x = 3$ был разрыв, там сидел бы комок вероятности. Условие задачи ничего такого не предполагает, а сама формула $ax^2$ должна дорасти до $1$ на правом конце своего участка. Значит, нужно склеить куски:

$$a \cdot 3^2 = 1 \quad \Rightarrow \quad 9a = 1 \quad \Rightarrow \quad a = \frac{1}{9}$$

Шаг 2. Проверим левую склейку: при $x \to 0^+$ получаем $a \cdot 0 = 0$ — совпадает с нулевым куском, разрыва нет ✅

Шаг 3. Проверим неубывание: $x^2/9$ на $(0;3]$ растёт, потому что при $0 < x_1 < x_2$ разность $\dfrac{x_2^2 - x_1^2}{9} = \dfrac{(x_2-x_1)(x_2+x_1)}{9} > 0$ ✅

Шаг 4. Считаем:

$$P(1 \le X < 2) = F(2) - F(1) = \frac{4}{9} - \frac{1}{9} = \frac{3}{9} = \frac{1}{3}$$

Ответ: $a = \dfrac{1}{9}$, $P(1 \le X < 2) = \dfrac{1}{3} \approx 0{,}333$.


Пример 6 (сложный): смешанная величина — и почему таблица переводов необходима

Время ожидания ответа от кеша устроено так: с вероятностью $0{,}3$ ответ приходит мгновенно (кеш-хит, время ровно $0$), иначе время равномерно распределено на $(0; 1]$ секунды. Найди $F(x)$, затем $P(X = 0)$, $P(X \le 0{,}5)$, $P(X > 0{,}5)$ и $P(0 < X < 0{,}5)$.

Решение:

Шаг 1. Разберём величину по кускам. Масса $0{,}3$ сидит комком в точке $0$. Оставшаяся масса $0{,}7$ размазана равномерно по отрезку $(0;1]$.

Шаг 2. При $x \le 0$: левее нуля ничего нет (и сам ноль не засчитывается, неравенство строгое). $F(x) = 0$.

Шаг 3. При $0 < x \le 1$: позади остался весь комок $0{,}3$ плюс доля $x$ от размазанной массы $0{,}7$:

$$F(x) = 0{,}3 + 0{,}7x$$

Шаг 4. При $x > 1$: $F(x) = 1$. Проверим склейку: $0{,}3 + 0{,}7 \cdot 1 = 1$ ✅

Шаг 5. Скачок в нуле: $F(0 + 0) - F(0) = 0{,}3 - 0 = 0{,}3$. Значит, $P(X = 0) = 0{,}3$ — сходится с условием ✅

Шаг 6. $P(X \le 0{,}5) = F(0{,}5) + P(X = 0{,}5)$. В точке $0{,}5$ функция непрерывна, скачка нет, $P(X = 0{,}5) = 0$. Значит:

$$P(X \le 0{,}5) = F(0{,}5) = 0{,}3 + 0{,}7 \cdot 0{,}5 = 0{,}65$$

Шаг 7. $P(X > 0{,}5) = 1 - F(0{,}5) - P(X=0{,}5) = 1 - 0{,}65 - 0 = 0{,}35$.

Шаг 8. $P(0 < X < 0{,}5) = F(0{,}5) - F(0) - P(X = 0) = 0{,}65 - 0 - 0{,}3 = 0{,}35$.

Проверим иначе: это ровно половина «размазанного» куска, то есть $0{,}7 \cdot 0{,}5 = 0{,}35$ ✅

Ответ: $F(x) = 0$ при $x \le 0$; $0{,}3 + 0{,}7x$ при $0 < x \le 1$; $1$ при $x > 1$. Далее: $0{,}3$; $0{,}65$; $0{,}35$; $0{,}35$.

📌 Смешанные величины — это не экзотика из учебника. Время ответа сервиса с кешем, сумма страховой выплаты (с вероятностью $p$ — ноль, иначе непрерывная), выручка с пользователя (много нулей плюс непрерывный хвост), задержка в очереди (может быть ровно $0$, если очередь пуста) — всё это смеси. И описать их можно только через $F$: ни ряда распределения, ни плотности у них нет.

Почему это важно

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

А формула $P(a \le X < b) = F(b) - F(a)$ — это рабочая лошадка. В коде она выглядит как dist.cdf(b) - dist.cdf(a) и используется постоянно: вероятность попадания метрики в допустимый коридор, доля объектов со скором в бине при калибровке, вероятность, что латентность уложится в SLA, ожидаемая доля попаданий в доверительный интервал.


Дискретная величина: лесенка со скачками

Интуиция

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

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

Правило: График функции распределения дискретной величины — ступенчатая линия. Скачок в точке $x_i$ равен $p_i = P(X = x_i)$. Высота полки правее точки $x_i$ равна сумме всех вероятностей значений, не превосходящих $x_i$:

$$F(x) = \sum_{i:\, x_i < x} p_i$$

Сумма всех скачков равна $1$ — это просто $\sum p_i = 1$, записанное на языке графика. Полезная картинка: лестница, которая начинается на нулевом этаже, заканчивается на первом, а высота каждой ступеньки — вероятность соответствующего значения. Самые вероятные значения дают самые высокие ступеньки.

Про то, как рисовать концы полок при нашей конвенции $F(x) = P(X < x)$: функция непрерывна слева, значит, левый конец каждой полки закрашен (значение достигается), а правый — выколот. Если бы работали с $\le$-конвенцией, было бы наоборот. На экзамене за это снимают баллы, в жизни — путают на единицу при работе с квантилями.

Примеры с разбором

Пример 7 (простой): три броска монеты

$X$ — число орлов при трёх бросках честной монеты. Построй $F(x)$ и найди $P(1 \le X < 3)$.

Решение:

Шаг 1. Ряд распределения по формуле Бернулли (урок 233), $n = 3$, $p = 0{,}5$:

$k$ $0$ $1$ $2$ $3$
$P$ $1/8$ $3/8$ $3/8$ $1/8$

Контроль: $1/8 + 3/8 + 3/8 + 1/8 = 1$ ✅

Шаг 2. Накапливаем слева направо. При $x \le 0$ ничего левее нет: $F = 0$. Проехали точку $0$ — добавили $1/8$. Проехали $1$ — добавили $3/8$, стало $1/2$. Проехали $2$ — стало $7/8$. Проехали $3$ — стало $1$.

Шаг 3. Записываем:

$$F(x) = \begin{cases} 0, & x \le 0 \\ 1/8, & 0 < x \le 1 \\ 1/2, & 1 < x \le 2 \\ 7/8, & 2 < x \le 3 \\ 1, & x > 3 \end{cases}$$

Шаг 4. $P(1 \le X < 3) = F(3) - F(1) = \dfrac{7}{8} - \dfrac{1}{8} = \dfrac{6}{8} = \dfrac{3}{4}$.

Проверка напрямую: в промежуток $[1;3)$ попадают значения $1$ и $2$: $3/8 + 3/8 = 6/8$ ✅

Ответ: ступенчатая $F$ с четырьмя скачками $1/8,\ 3/8,\ 3/8,\ 1/8$; $P(1 \le X < 3) = 3/4$.


Пример 8 (средний): игральный кубик и обе конвенции сразу

$X$ — число очков на честном кубике. Построй $F$ и посчитай $P(X \le 3)$ двумя способами: через нашу конвенцию и через международную.

Решение:

Шаг 1. Все шесть значений равновероятны: $p_i = 1/6$. Накопленные суммы дают полки $0,\ \tfrac16,\ \tfrac26,\ \tfrac36,\ \tfrac46,\ \tfrac56,\ 1$.

$$F(x) = \frac{\lceil x \rceil - 1}{6} \ \text{ при } 1 \le x \le 7, \quad \text{строго: } F(x) = \frac{k-1}{6} \text{ при } k - 1 < x \le k,\ k = 1,\dots,6$$

Проще списком: $F(x) = 0$ при $x \le 1$; $1/6$ при $1 < x \le 2$; $2/6$ при $2 < x \le 3$; $3/6$ при $3 < x \le 4$; $4/6$ при $4 < x \le 5$; $5/6$ при $5 < x \le 6$; $1$ при $x > 6$.

Шаг 2. Наша конвенция. $P(X \le 3) = F(3) + P(X = 3) = \dfrac{2}{6} + \dfrac{1}{6} = \dfrac{3}{6} = \dfrac{1}{2}$.

Тут легко ошибиться: $F(3) = 2/6$, а вовсе не $3/6$, потому что $F(3) = P(X < 3) = P(X \in \{1,2\})$.

Шаг 3. Международная конвенция. Там $\tilde F(x) = P(X \le x)$, и сразу $\tilde F(3) = 3/6 = 1/2$. В коде: scipy.stats.randint(1, 7).cdf(3) вернёт 0.5.

Шаг 4. Ответы совпали — и должны были: событие-то одно и то же, различаются только записи.

Ответ: $P(X \le 3) = 1/2$; в нашей конвенции это $F(3) + P(X=3)$, в международной — просто $\tilde F(3)$.


Пример 9 (сложный): дискретная величина с бесконечным числом значений

Ты тестируешь флаки-тест: он падает с вероятностью $0{,}5$ независимо от прошлых запусков. $X$ — номер запуска, на котором тест впервые упал ($X = 1, 2, 3, \dots$). Найди $F(x)$ и вероятность $P(X \ge 4)$.

Решение:

Шаг 1. «Первое падение на $k$-м запуске» означает: $k-1$ раз прошёл ($0{,}5$ каждый раз) и на $k$-м упал. По независимости:

$$P(X = k) = 0{,}5^{k-1} \cdot 0{,}5 = 0{,}5^{k}$$

Контроль: $\sum_{k \ge 1} 0{,}5^k$ — геометрическая прогрессия со знаменателем $0{,}5$ и первым членом $0{,}5$: сумма $= \dfrac{0{,}5}{1 - 0{,}5} = 1$ ✅

Шаг 2. Для целого $n \ge 1$ считаем $F(n) = P(X < n) = P(X \le n - 1)$:

$$F(n) = \sum_{k=1}^{n-1} 0{,}5^{k} = \frac{0{,}5(1 - 0{,}5^{\,n-1})}{1 - 0{,}5} = 1 - 0{,}5^{\,n-1}$$

Шаг 3. Проверим на маленьких числах. $F(1) = 1 - 0{,}5^0 = 0$ — верно, левее единицы значений нет. $F(2) = 1 - 0{,}5 = 0{,}5$ — верно, это $P(X = 1)$. $F(3) = 1 - 0{,}25 = 0{,}75 = P(X=1) + P(X=2)$ ✅

Шаг 4. Общая запись для любого вещественного $x$: полки между целыми, $F(x) = 1 - 0{,}5^{\lceil x \rceil - 1}$ при $x > 1$ (где $\lceil x \rceil$ — округление вверх), $F(x) = 0$ при $x \le 1$.

Шаг 5. $P(X \ge 4) = 1 - F(4) = 1 - (1 - 0{,}5^3) = 0{,}125$.

Проверим смыслом: $X \ge 4$ означает, что первые три запуска прошли успешно, вероятность $0{,}5^3 = 0{,}125$ ✅

Ответ: $F(n) = 1 - 0{,}5^{\,n-1}$ для целых $n \ge 1$, ступеньки высотой $0{,}5^k$; $P(X \ge 4) = 0{,}125$.

Заметь важное: ступенек бесконечно много, они становятся всё мельче, и $F$ подбирается к единице, никогда её не достигая при конечном $x$. Предел на бесконечности всё равно равен $1$ — свойство выполнено.

Почему это важно

Ступенчатая $F$ — это буквально то, с чем ты работаешь при сэмплировании категориального распределения. Когда языковая модель выбирает следующий токен, она берёт вектор вероятностей после softmax, считает кумулятивную сумму (np.cumsum — это и есть построение $F$ по ряду распределения), бросает random() и смотрит, в какую ступеньку попал. Реализация в одну строку: np.searchsorted(cumsum, u) — двоичный поиск по лесенке. Мы разберём этот механизм подробно в ML-блоке.

И вторая вещь: эмпирическая функция распределения любой выборки — тоже ступенчатая, с одинаковыми ступеньками высотой $1/n$. То есть всё, что ты сейчас узнал про лесенки, применимо к любому массиву чисел, который у тебя есть в датафрейме.


Непрерывная величина: гладкая кривая и парадокс нулевой вероятности

Интуиция

Если у величины нет «комков» — то есть $F$ непрерывна всюду, — то величину называют непрерывной. График $F$ идёт без разрывов: плавно поднимается от $0$ к $1$, иногда быстрее, иногда медленнее. Крутизна подъёма показывает, где вероятностная масса гуще: там, где $F$ растёт быстро, значения встречаются часто; где $F$ почти горизонтальна, значения редки.

Вот эта самая «крутизна подъёма» — производная $F'(x)$ — и есть плотность вероятности, главный герой следующего урока. Пока просто зафиксируем связь: $F$ — накопитель, плотность — скорость накопления. Одна получается из другой дифференцированием, обратно — интегрированием. Все технические детали (почему это корректно, что делать в точках излома, как считать вероятности через интеграл) разберём в уроке 236.

Главная особенность непрерывного случая:

Свойство: Если $F$ непрерывна в точке $a$, то $P(X = a) = 0$.

Это прямое следствие свойства 6: скачка нет, значит, $F(a+0) - F(a) = 0$, значит, $P(X = a) = 0$. Для непрерывной величины это верно во всех точках.

«Вероятность ноль» ≠ «невозможно»

Вот тут у людей ломается интуиция, и ломается справедливо. Если вероятность того, что время ответа окажется ровно $180{,}0000\ldots$ мс, равна нулю — то как вообще хоть какое-то время получается? Ведь какое-то значение да выпадает, и у него вероятность ноль!

Разберём честно. В теории вероятностей есть два разных понятия, которые в дискретном мире совпадают, а в непрерывном расходятся:

  • невозможное событие — то, которое не содержит ни одного исхода (например, «кубик выпал семёркой»);
  • событие вероятности ноль — то, которое содержит исходы, но его вероятностная мера равна нулю.

Аналогия, которая всё ставит на место: возьми отрезок $[0;4]$ и спроси, какую долю его длины занимает точка $x = 2$. Ответ — ноль: у точки нет длины. Но точка на отрезке есть! Она не «не существует», у неё просто нулевая мера. Ровно то же самое с вероятностью: масса размазана по континууму, и на каждую отдельную точку приходится ноль, а на любой отрезок — что-то положительное.

Практический вывод: для непрерывной величины осмысленны вопросы вида «какова вероятность попасть в промежуток», а не «в точку». И это не философия, а прямое указание, как формулировать задачи. Вместо «вероятность, что латентность равна $200$ мс» — «вероятность, что латентность в диапазоне от $195$ до $205$ мс». Второе считается, первое всегда даёт ноль.

📌 Кстати, отсюда же берётся приятный побочный эффект: для непрерывной величины все четыре записи промежутка равновероятны:

$$P(a < X < b) = P(a \le X < b) = P(a < X \le b) = P(a \le X \le b) = F(b) - F(a)$$

Можно не думать о строгости неравенств вообще. Для дискретных так делать нельзя — там каждая скобка меняет ответ.

Примеры с разбором

Пример 10 (простой): экспоненциальное время между запросами

Время между запросами к сервису распределено экспоненциально: $F(x) = 1 - e^{-x/2}$ при $x \ge 0$ и $F(x) = 0$ при $x < 0$ (время в секундах, средний интервал $2$ с). Найди $P(X < 2)$ и $P(X \ge 4)$.

Решение:

Шаг 1. $P(X < 2) = F(2) = 1 - e^{-1}$.

Считаем: $e^{-1} \approx 0{,}3679$, значит, $P \approx 0{,}6321$.

Шаг 2. $P(X \ge 4) = 1 - F(4) = 1 - (1 - e^{-2}) = e^{-2} \approx 0{,}1353$.

Шаг 3. Проверка на разумность: средний интервал $2$ с, и вероятность, что пауза окажется вдвое длиннее среднего, — около $13{,}5\%$. Правдоподобно: экспоненциальное распределение имеет длинный хвост ✅

Ответ: $P(X < 2) = 1 - e^{-1} \approx 0{,}6321$; $P(X \ge 4) = e^{-2} \approx 0{,}1353$.


Пример 11 (средний): вероятность «точного попадания» — считаем честно

Датчик выдаёт значение, равномерное на $[0;4]$. Найди $P(X = 2)$, $P(|X - 2| < 0{,}01)$ и $P(|X - 2| < 10^{-6})$.

Решение:

Шаг 1. $F(x) = x/4$ на отрезке — функция непрерывна всюду, скачков нет. Значит, $P(X = 2) = 0$.

Шаг 2. $|X - 2| < 0{,}01$ означает $X \in (1{,}99;\ 2{,}01)$. По непрерывности строгость неравенств не важна:

$$P = F(2{,}01) - F(1{,}99) = \frac{2{,}01 - 1{,}99}{4} = \frac{0{,}02}{4} = 0{,}005$$

Шаг 3. Аналогично для окна $10^{-6}$: длина промежутка $2 \cdot 10^{-6}$, вероятность

$$P = \frac{2 \cdot 10^{-6}}{4} = 5 \cdot 10^{-7}$$

Шаг 4. Смотрим на динамику: сужаем окно — вероятность падает пропорционально ширине и стремится к нулю. Ноль в пределе — это и есть $P(X = 2)$. При этом при любом положительном окне вероятность строго положительна: событие вполне себе достижимо.

Ответ: $0$; $0{,}005$; $5 \cdot 10^{-7}$. Нулевая вероятность точки — это предел, а не запрет.


Пример 12 (сложный): проверяем кандидата на роль $F$ и считаем вероятности

Дана функция $F(x) = \dfrac{x^2}{1 + x^2}$ при $x \ge 0$ и $F(x) = 0$ при $x < 0$. Является ли она функцией распределения? Если да — найди $P(1 \le X < \sqrt{3})$ и $P(X \ge 1)$.

Решение:

Шаг 1. Пределы. При $x \to +\infty$ делим числитель и знаменатель на $x^2$:

$$\frac{x^2}{1+x^2} = \frac{1}{1/x^2 + 1} \longrightarrow \frac{1}{0 + 1} = 1 \ ✅$$

При $x \to -\infty$ функция тождественно $0$ ✅

Шаг 2. Неубывание. Проверим напрямую, без производной. Пусть $0 \le x_1 < x_2$. Заметим, что

$$F(x) = \frac{x^2}{1+x^2} = 1 - \frac{1}{1+x^2}$$

Раз $x_1^2 < x_2^2$, то $1 + x_1^2 < 1 + x_2^2$, значит, $\dfrac{1}{1+x_1^2} > \dfrac{1}{1+x_2^2}$, значит, вычитаемое у $x_2$ меньше, и $F(x_1) < F(x_2)$ ✅

(Тот же вывод даёт производная $F'(x) = \dfrac{2x}{(1+x^2)^2} \ge 0$ при $x \ge 0$ — и заодно это будущая плотность из урока 236.)

Шаг 3. Непрерывность. В точке $0$: $F(0) = 0/1 = 0$, слева тоже $0$ — стыкуется. На остальных точках дробь непрерывна (знаменатель не обращается в ноль) ✅

Все три условия теоремы о характеризации выполнены — это функция распределения непрерывной величины.

Шаг 4. $P(1 \le X < \sqrt{3}) = F(\sqrt{3}) - F(1)$.

$$F(\sqrt3) = \frac{3}{1+3} = \frac{3}{4}, \qquad F(1) = \frac{1}{1+1} = \frac{1}{2}$$$$P = \frac{3}{4} - \frac{1}{2} = \frac{1}{4} = 0{,}25$$

Шаг 5. $P(X \ge 1) = 1 - F(1) = 1 - \dfrac12 = \dfrac12$.

Ответ: да, является; $P(1 \le X < \sqrt3) = 0{,}25$; $P(X \ge 1) = 0{,}5$.

Почему это важно

Понимание «$P(X = a) = 0$, но событие возможно» — это не абстрактная тонкость, а прямое требование к тому, как ты формулируешь задачи с непрерывными данными. Именно поэтому в ML нет «вероятности конкретного значения признака», а есть плотность; именно поэтому в правдоподобии для непрерывных моделей стоит плотность, а не вероятность (и значение log-likelihood может быть положительным — плотность не обязана быть $\le 1$); именно поэтому дискретизация непрерывной величины в бины — не порча данных, а единственный способ перевести её на язык вероятностей.


Квантили, медиана и обратная функция

Интуиция

До сих пор мы задавали вопрос «дано значение $x$ — какая доля массы левее?». Это прямой ход: $x \mapsto F(x)$. Но в реальной работе гораздо чаще нужен обратный вопрос: «дана доля $p$ — какое значение её отсекает?».

  • «Какое время ответа не превышается в $95\%$ случаев?» — это перцентиль p95.
  • «Какая зарплата делит рынок пополам?» — это медиана.
  • «Начиная с какого значения признака объекты считаем выбросами?» — это квантиль уровня $0{,}99$.
  • «Какой порог поставить, чтобы модель помечала подозрительными ровно $2\%$ транзакций?» — это квантиль скора уровня $0{,}98$.

Все эти вопросы — про обратную функцию к $F$. Она называется квантильной функцией, обозначается $F^{-1}$ или $Q(p)$, и берёт на вход вероятность, а отдаёт значение.

Определение: Квантилем уровня $p$ (где $0 < p < 1$) случайной величины $X$ называется такое число $x_p$, что

$$P(X < x_p) \le p \le P(X \le x_p)$$

Квантиль уровня $0{,}5$ называется медианой. Квантили уровней $0{,}25$, $0{,}5$, $0{,}75$ называются квартилями, квантиль уровня $k/100$ — $k$-м перцентилем.

Определение выглядит громоздко из-за двойного неравенства, но оно устроено так специально: только в таком виде оно работает и для непрерывных величин, и для дискретных, где $F$ прыгает через уровень $p$ и точного решения уравнения $F(x) = p$ может не существовать.

Непрерывный случай: просто решаем уравнение

Если $F$ непрерывна и строго возрастает на промежутке, где живёт величина, всё просто: квантиль $x_p$ — это единственный корень уравнения

$$F(x_p) = p$$

и квантильная функция — обычная обратная функция:

$$x_p = F^{-1}(p)$$

Медиана: решаем $F(m) = 0{,}5$. Перцентиль p95: решаем $F(x) = 0{,}95$.

Геометрически это отражение графика $F$ относительно прямой $y = x$: берём кривую, поворачиваем оси — по горизонтали теперь вероятность от $0$ до $1$, по вертикали — значения величины.

Дискретный случай: две ловушки

Тут интереснее, и обе ловушки стоит увидеть на пальцах.

Ловушка 1: уравнение $F(x) = p$ может не иметь решений. У ступенчатой функции есть только конечный набор значений-полок. Если $p$ попало между двумя полками, ни в одной точке $F(x) = p$ не выполняется. Определение через двойное неравенство это чинит: квантиль — это точка скачка, который «перепрыгивает» уровень $p$.

Ловушка 2: решений может быть бесконечно много. Если $p$ совпало ровно с высотой полки, то на всей этой полке $F(x) = p$, и любая её точка формально годится в квантили. Медиана величины «монета: $0$ или $1$ с вероятностями $0{,}5$» — это любое число из $[0;1]$. Именно поэтому в софте используют соглашение: брать наименьшее подходящее значение.

Определение (обобщённая обратная функция): Квантильной функцией называется

$$F^{-1}(p) = \inf\{x : P(X \le x) \ge p\}$$

то есть наименьшее значение, левее которого (включительно) накоплено не меньше $p$ массы.

Именно эту формулу реализует scipy.stats.<dist>.ppf(p) (ppf — percent point function) и numpy.quantile при method='inverted_cdf'. Обрати внимание: внутри стоит $P(X \le x)$, нестрогое неравенство, — то есть в определении квантиля мир живёт по международной конвенции даже в русских учебниках. Это не противоречие, а сознательный выбор: с нестрогой версией $\inf$ всегда достигается, и функция получается корректно определённой в каждой точке.

📌 Отдельно про эмпирические квантили. Когда ты считаешь p95 по массиву чисел, единственно верной формулы нет: существует девять (!) общепринятых определений, и numpy.quantile поддерживает их через параметр method. По умолчанию numpy использует линейную интерполяцию между соседними порядковыми статистиками, а не строгую обобщённую обратную. Поэтому p95 из numpy, из Prometheus и из ClickHouse на одних и тех же данных могут слегка различаться — и это не баг, а разные соглашения. Для больших выборок разница пренебрежима, для выборки из $20$ значений — вполне заметна.

Примеры с разбором

Пример 13 (простой): медиана равномерного и экспоненциального распределений

Найди медиану для (а) равномерного на $[0;10]$; (б) экспоненциального с $F(x) = 1 - e^{-0{,}25x}$.

Решение (а):

Шаг 1. $F(x) = x/10$ на $[0;10]$.

Шаг 2. Решаем $\dfrac{m}{10} = 0{,}5 \Rightarrow m = 5$.

Проверка: серединная точка отрезка делит равномерную массу пополам ✅

Решение (б):

Шаг 1. Решаем $1 - e^{-0{,}25 m} = 0{,}5$, то есть $e^{-0{,}25m} = 0{,}5$.

Шаг 2. Логарифмируем: $-0{,}25 m = \ln 0{,}5 = -\ln 2$, откуда

$$m = \frac{\ln 2}{0{,}25} = 4\ln 2 \approx 4 \cdot 0{,}6931 = 2{,}7726$$

Шаг 3. Сравним со средним значением экспоненциального распределения: оно равно $1/0{,}25 = 4$ (это мы строго докажем в уроке 237). Медиана $2{,}77$ заметно меньше среднего $4$.

Ответ: (а) $m = 5$; (б) $m = 4\ln 2 \approx 2{,}77$, что меньше среднего $4$.

Разрыв между медианой и средним — фирменный признак правого хвоста. Половина пауз короче $2{,}77$ с, но редкие длинные паузы тянут среднее вверх до $4$. Ровно та же история с латентностью сервиса, с чеком в интернет-магазине, с зарплатами и с длиной текстов в датасете.


Пример 14 (средний): квантиль дискретной величины — обе ловушки в одной задаче

Дискретная величина принимает значения $1, 2, 3, 4$ с вероятностями $0{,}1;\ 0{,}3;\ 0{,}4;\ 0{,}2$. Найди медиану, квантиль уровня $0{,}8$ и квантиль уровня $0{,}3$.

Решение:

Шаг 1. Построим накопленные суммы $\tilde F(x) = P(X \le x)$ — с ними удобнее работать при поиске квантилей:

$x$ $1$ $2$ $3$ $4$
$p_i$ $0{,}1$ $0{,}3$ $0{,}4$ $0{,}2$
$P(X \le x)$ $0{,}1$ $0{,}4$ $0{,}8$ $1{,}0$
$P(X < x)$ $0$ $0{,}1$ $0{,}4$ $0{,}8$

Шаг 2. Медиана ($p = 0{,}5$). Ищем $x$, для которого $P(X < x) \le 0{,}5 \le P(X \le x)$.

Проверим $x = 3$: $P(X < 3) = 0{,}4 \le 0{,}5$ ✅ и $P(X \le 3) = 0{,}8 \ge 0{,}5$ ✅ — подходит.

Проверим $x = 2$: $P(X \le 2) = 0{,}4 < 0{,}5$ ✗ — не подходит.

Медиана $= 3$, единственная. Обрати внимание: точного решения уравнения $F(x) = 0{,}5$ здесь нет — уровень $0{,}5$ «проскакивается» скачком в точке $3$ (с $0{,}4$ до $0{,}8$). Это ловушка 1.

Шаг 3. Квантиль уровня $0{,}8$. Проверим $x = 3$: $P(X < 3) = 0{,}4 \le 0{,}8$ ✅ и $P(X \le 3) = 0{,}8 \ge 0{,}8$ ✅ — подходит.

Проверим $x = 4$: $P(X < 4) = 0{,}8 \le 0{,}8$ ✅ и $P(X \le 4) = 1 \ge 0{,}8$ ✅ — тоже подходит!

Формально годится любое $x \in [3; 4]$ — это ловушка 2 (уровень совпал с высотой полки). По соглашению $\inf$ берём наименьшее: $x_{0{,}8} = 3$.

Шаг 4. Квантиль уровня $0{,}3$. Проверим $x = 2$: $P(X < 2) = 0{,}1 \le 0{,}3$ ✅ и $P(X \le 2) = 0{,}4 \ge 0{,}3$ ✅ — подходит, единственный.

Ответ: медиана $= 3$; $x_{0{,}8} = 3$ (формально любое из $[3;4]$, по соглашению $3$); $x_{0{,}3} = 2$.


Пример 15 (сложный): строим квантильную функцию целиком

Для смешанной величины из примера 6 ($F(x) = 0$ при $x \le 0$; $0{,}3 + 0{,}7x$ при $0 < x \le 1$; $1$ при $x > 1$) построй квантильную функцию $F^{-1}(p)$ на всём интервале $p \in (0;1)$ и найди медиану, p10 и p95.

Решение:

Шаг 1. Работаем с нестрогой версией: $\tilde F(x) = P(X \le x)$. Для нашей величины $\tilde F(0) = 0{,}3$ (комок в нуле уже засчитан), а дальше $\tilde F(x) = 0{,}3 + 0{,}7x$ на $(0;1]$ — совпадает с $F$, поскольку в этих точках скачков нет.

Шаг 2. Случай $p \le 0{,}3$. Наименьшее $x$ с $\tilde F(x) \ge p$ — это $x = 0$, потому что уже в нуле накоплено $0{,}3 \ge p$. Значит, $F^{-1}(p) = 0$ для всех $p \in (0; 0{,}3]$.

Комок вероятности в точке превратился в горизонтальную полку квантильной функции. Логично: обратная функция меняет местами скачки и полки.

Шаг 3. Случай $p > 0{,}3$. Решаем $0{,}3 + 0{,}7x = p$:

$$x = \frac{p - 0{,}3}{0{,}7}$$

Шаг 4. Итого:

$$F^{-1}(p) = \begin{cases} 0, & 0 < p \le 0{,}3 \\[4pt] \dfrac{p - 0{,}3}{0{,}7}, & 0{,}3 < p < 1 \end{cases}$$

Шаг 5. Считаем конкретные квантили.

Медиана: $p = 0{,}5 > 0{,}3$, значит, $m = \dfrac{0{,}5 - 0{,}3}{0{,}7} = \dfrac{0{,}2}{0{,}7} \approx 0{,}2857$.

p10: $p = 0{,}1 \le 0{,}3$, значит, $x_{0{,}1} = 0$. То есть десятая часть запросов обслуживается за нулевое время — это кеш-хиты.

p95: $x_{0{,}95} = \dfrac{0{,}95 - 0{,}3}{0{,}7} = \dfrac{0{,}65}{0{,}7} \approx 0{,}9286$.

Проверка p95: подставим обратно: $F(0{,}9286) = 0{,}3 + 0{,}7 \cdot 0{,}9286 = 0{,}3 + 0{,}65 = 0{,}95$ ✅

Ответ: $F^{-1}(p) = 0$ при $p \le 0{,}3$ и $\dfrac{p-0{,}3}{0{,}7}$ при $p > 0{,}3$; медиана $\approx 0{,}286$ с, p10 $= 0$, p95 $\approx 0{,}929$ с.

📌 Здесь видно правило-зеркало: скачок $F$ ↔ полка $F^{-1}$, полка $F$ ↔ скачок $F^{-1}$. У дискретной величины $F$ — сплошные ступеньки, значит, $F^{-1}$ — тоже ступеньки, только «повёрнутые». У непрерывной строго возрастающей — обе гладкие.

Почему это важно

Квантили — это язык, на котором в индустрии описывают распределения, потому что они устойчивы. Среднее можно испортить одним выбросом: добавь в выборку из тысячи значений одно значение $10^9$, и среднее улетит. Медиана не шелохнётся. Именно поэтому SLA пишут в перцентилях («p99 < 300 мс»), а не в средних; поэтому в мониторинге строят квантильные графики; поэтому робастная нормализация признаков (RobustScaler в sklearn) вычитает медиану и делит на межквартильный размах, а не на стандартное отклонение.

И вторая причина: квантильная функция — это генератор. Из неё выводится способ породить любое распределение из одного random(). Разбираем прямо сейчас.


Функция распределения в машинном обучении

Метод обратного преобразования: как из random() получить что угодно

У тебя есть ровно один источник случайности — генератор равномерных чисел на $[0;1)$. Всё остальное (нормальный шум, экспоненциальные интервалы, категориальный выбор токена, дропаут-маска) строится из него. Механизм — квантильная функция.

Теорема (метод обратного преобразования): Пусть $U$ — равномерная величина на $(0;1)$, а $F$ — произвольная функция распределения. Тогда величина

$$X = F^{-1}(U)$$

имеет функцию распределения ровно $F$.

Доказательство для строго возрастающей непрерывной $F$ занимает одну строку. Обратная функция монотонна, поэтому неравенство $F^{-1}(U) < x$ равносильно $U < F(x)$:

$$P(X < x) = P\big(F^{-1}(U) < x\big) = P\big(U < F(x)\big) = F(x)$$

последнее равенство — потому что для равномерной на $(0;1)$ величины $P(U < t) = t$ при $t \in [0;1]$. ∎

Практический рецепт из трёх шагов:

  1. Выписать $F$ нужного распределения.
  2. Решить уравнение $F(x) = u$ относительно $x$ — получить $F^{-1}$.
  3. Подставить туда random().

Для экспоненциального распределения это выглядит так: $1 - e^{-\lambda x} = u \Rightarrow x = -\dfrac{\ln(1-u)}{\lambda}$. А поскольку $1 - U$ распределена так же, как $U$, в коде обычно пишут просто $x = -\ln(u)/\lambda$ — и именно эта строчка стоит внутри numpy.random.exponential.

📌 Обратной формулы в замкнутом виде может и не быть — например, для нормального распределения $\Phi^{-1}$ не выражается через элементарные функции. Тогда используют либо численную аппроксимацию (scipy.special.ndtri), либо специальные трюки: преобразование Бокса-Мюллера, ziggurat-алгоритм. Но идея «взять равномерное и прогнать через обратную $F$» остаётся базовой и работает для любого распределения, у которого $F$ считается.

Сэмплирование токена: лесенка, cumsum и бинарный поиск

Когда языковая модель выбирает следующий токен, происходит ровно метод обратного преобразования для дискретной величины. Softmax даёт вектор вероятностей $p_1, \dots, p_V$ по словарю. Дальше:

  1. Считаем кумулятивную сумму c = np.cumsum(p) — это и есть построение $F$ по ряду распределения, полки лесенки.
  2. Бросаем $u = $ random().
  3. Ищем первую ступеньку, которая перепрыгнула уровень $u$: idx = np.searchsorted(c, u) — двоичный поиск за $O(\log V)$.

Это буквально обобщённая обратная функция $F^{-1}(u) = \inf\{x : P(X \le x) \ge u\}$, реализованная в одну строку. Температура $T$ в сэмплировании меняет вектор $p$ (логиты делятся на $T$ перед softmax), а значит меняет форму лесенки: при $T \to 0$ одна ступенька занимает почти всю высоту, и выбор становится детерминированным (это greedy decoding); при большом $T$ ступеньки выравниваются, и выбор приближается к равномерному по словарю.

Top-$p$ (nucleus) sampling — это тоже операция над $F$, причём буквально квантильная: берём минимальный набор самых вероятных токенов, у которых накопленная вероятность достигает $p$, то есть отрезаем всё, что лежит правее квантиля уровня $p$, и ренормируем остаток.

Перцентили в мониторинге: почему дашборд со средним бесполезен

Вернёмся к истории из начала урока. Среднее время ответа — это одно число, которое сворачивает всю $F$ в точку и теряет хвост. Перцентили сохраняют форму:

  • p50 (медиана) — как живёт типичный запрос;
  • p95, p99 — как живут худшие; именно они попадают в SLA;
  • p99.9 — как живут самые крупные клиенты, потому что клиент, делающий тысячу запросов на страницу, встретит свой «один из тысячи» гарантированно.

Ключевая вещь, которую стоит запомнить намертво: перцентили не складываются. Если страница собирается из пяти последовательных вызовов сервисов, каждый с p99 = $100$ мс, то p99 страницы — это НЕ $500$ мс и НЕ $100$ мс. Вероятность, что хотя бы один из пяти вызовов попадёт в свой худший процент, равна $1 - 0{,}99^5 \approx 0{,}049$ — то есть почти каждая двадцатая страница ловит хвост хотя бы одного сервиса. Это явление называют tail amplification, и с ним борются не оптимизацией среднего, а архитектурой: hedged requests (послать копию запроса на вторую реплику и взять первый ответ), таймауты с ретраем, деградация вместо ожидания.

Эмпирическая функция распределения и тест на дрейф

Если у тебя есть выборка $x_1, \dots, x_n$, можно построить её собственную функцию распределения — эмпирическую:

$$\hat F_n(x) = \frac{\#\{i : x_i < x\}}{n}$$

Это ступенчатая функция с $n$ одинаковыми ступеньками высотой $1/n$ (если значения не повторяются). По сути ты присвоил каждому наблюдению вероятность $1/n$ и построил лесенку.

Теорема Гливенко-Кантелли (её называют основной теоремой статистики) утверждает, что $\hat F_n$ сходится к настоящей $F$ равномерно по всей оси при $n \to \infty$. Это фундамент всей непараметрической статистики и бутстрэпа: выборка «знает» распределение целиком, а не только его среднее.

Отсюда же — рабочий инструмент детекции дрейфа данных. Статистика Колмогорова-Смирнова

$$D_n = \sup_x \big|\hat F_n(x) - F(x)\big|$$

измеряет максимальный вертикальный зазор между двумя лесенками (или между лесенкой и гладкой кривой). Двухвыборочный вариант сравнивает эмпирические $F$ обучающей и продакшн-выборок признака: если $D$ вылез за критическое значение, распределение поехало, и модель работает не на тех данных, на которых училась. scipy.stats.ks_2samp — три строчки в пайплайне мониторинга.

ROC-кривая — это параметрический график двух функций распределения

Бинарный классификатор выдаёт скор $s$. У положительных объектов скор имеет своё распределение $F_1$, у отрицательных — своё $F_0$. Выбираем порог $t$ и считаем две доли:

$$\mathrm{TPR}(t) = P(s \ge t \mid y = 1) = 1 - F_1(t), \qquad \mathrm{FPR}(t) = P(s \ge t \mid y = 0) = 1 - F_0(t)$$

ROC-кривая — это множество точек $\big(1 - F_0(t),\ 1 - F_1(t)\big)$, когда $t$ пробегает всю ось. То есть параметрический график двух функций распределения, где параметром служит порог. Всё, что мы знаем про $F$, немедленно превращается в свойства ROC:

  • кривая идёт из $(1;1)$ в $(0;0)$ и монотонна — потому что обе $F$ не убывают;
  • полное совпадение $F_0 = F_1$ (модель ничего не различает) даёт диагональ и AUC $= 0{,}5$;
  • ROC не меняется при любом монотонном преобразовании скора — потому что $F$ преобразуется вместе с осью, а точки кривой остаются те же. Отсюда важный вывод: AUC ничего не говорит о калибровке. Модель с AUC $0{,}95$ может выдавать «вероятности» $0{,}3$ там, где реальная частота $0{,}9$, и ROC этого не заметит.

Для эмпирических данных обе $F$ — ступенчатые, поэтому ROC получается ломаной, а AUC равна доле пар «положительный-отрицательный», в которых положительный получил больший скор (статистика Манна-Уитни).

Квантили как рабочий инструмент препроцессинга

Три вещи, которые ты почти наверняка встретишь в коде:

  • Квантильное бинирование. Histogram-based градиентный бустинг (LightGBM, HistGradientBoostingClassifier) не перебирает все пороги, а заранее режет признак на $\sim 256$ бинов по квантилям и работает с номерами бинов. Границы бинов — это значения $F^{-1}(k/256)$.
  • Робастная нормализация. RobustScaler вычитает медиану и делит на межквартильный размах $\mathrm{IQR} = x_{0{,}75} - x_{0{,}25}$. Один выброс на миллион не сдвинет ни то, ни другое, тогда как среднее и стандартное отклонение улетят.
  • Квантильное преобразование. QuantileTransformer применяет к признаку его собственную $\hat F$ — получается равномерное распределение (это следствие теоремы о вероятностном интегральном преобразовании), а потом, если надо, прогоняет результат через $\Phi^{-1}$ и получает нормальное. Тяжёлые хвосты сжимаются, шкала становится одинаковой у всех признаков. Деревьям это безразлично (они инвариантны к монотонным преобразованиям), а линейным моделям и нейросетям помогает заметно.

И ещё одно свойство, которое стоит держать в голове постоянно: квантили инвариантны к монотонным преобразованиям. Если $g$ строго возрастает, то $g$-квантиль равен квантилю от $g$: $x_p\big(g(X)\big) = g\big(x_p(X)\big)$. Для среднего это неверно. Практически: p95 логарифма латентности — это логарифм p95 латентности, поэтому можно спокойно считать перцентили в логарифмической шкале; а вот среднее логарифма — совсем не логарифм среднего, и на этой подмене погорело немало отчётов.

Почему это важно

Обрати внимание, что произошло. Одна функция $F(x) = P(X < x)$ породила: генератор случайных чисел любого распределения, механизм выбора токена в LLM, язык SLA и мониторинга, тест на дрейф данных, ROC-кривую, робастную нормализацию и бинирование признаков. Это не совпадение — просто $F$ и есть полное описание случайной величины, и любой вопрос про случайность неизбежно оказывается вопросом про неё.


Практика: 30 заданий

Базовые (задания 1-10)

Задание 1: Дана функция распределения

$$F(x) = \begin{cases} 0, & x \le 2 \\ 0{,}4, & 2 < x \le 5 \\ 0{,}7, & 5 < x \le 8 \\ 1, & x > 8 \end{cases}$$

Найди $P(X < 5)$, $P(2 \le X < 8)$, $P(X = 5)$ и $P(X \ge 5)$.


Задание 2: Случайная величина принимает значение $0$ с вероятностью $0{,}7$ и значение $3$ с вероятностью $0{,}3$. Построй её функцию распределения.


Задание 3: Датчик выдаёт значение, равномерно распределённое на отрезке $[2; 6]$. Найди $F(x)$ и вычисли $P(3 \le X < 5)$.


Задание 4: Функция распределения непрерывна всюду, кроме точки $x = 1$, где $F(1) = 0{,}2$, а предел справа $F(1+0) = 0{,}55$. Найди $P(X = 1)$, $P(X \le 1)$ и $P(X > 1)$.


Задание 5: Может ли функция

$$F(x) = \begin{cases} 0, & x \le 0 \\ \sin x, & 0 < x \le \pi \\ 1, & x > \pi \end{cases}$$

быть функцией распределения?


Задание 6: Найди параметр $a$, при котором функция

$$F(x) = \begin{cases} 0, & x \le 0 \\ a x^3, & 0 < x \le 2 \\ 1, & x > 2 \end{cases}$$

является функцией распределения непрерывной величины, и вычисли $P(0{,}5 \le X < 1)$.


Задание 7: Время ответа сервиса распределено экспоненциально: $F(x) = 1 - e^{-x/100}$ при $x \ge 0$ (время в миллисекундах). Какая доля запросов обслуживается быстрее $200$ мс? Какая доля не укладывается в $300$ мс?


Задание 8: Величина равномерно распределена на отрезке $[10; 50]$. Найди медиану и оба квартиля.


Задание 9: По функции распределения

$$F(x) = \begin{cases} 0, & x \le -2 \\ 0{,}1, & -2 < x \le 0 \\ 0{,}5, & 0 < x \le 3 \\ 0{,}9, & 3 < x \le 7 \\ 1, & x > 7 \end{cases}$$

восстанови ряд распределения и найди $P(0 \le X < 7)$.


Задание 10: Монету бросают дважды, $X$ — число выпавших орлов. Построй $F(x)$ и найди $P(X \ge 1)$.


Средние (задания 11-20)

Задание 11: В батче $3$ объекта, модель ошибается на каждом независимо с вероятностью $0{,}2$. $X$ — число ошибок в батче. Построй $F(x)$, найди $P(X \ge 1)$ и $P(1 \le X < 3)$.


Задание 12: Выручка с одного пользователя устроена так: с вероятностью $0{,}6$ он ничего не покупает (выручка ровно $0$), иначе тратит сумму, равномерно распределённую на $(0; 500]$ рублей. Найди $F(x)$, $P(X = 0)$, $P(X \le 200)$, медиану и перцентиль p90.


Задание 13: Дискретная величина принимает значения $10,\ 20,\ 30,\ 40,\ 50$ с вероятностями $0{,}05;\ 0{,}15;\ 0{,}3;\ 0{,}3;\ 0{,}2$. Найди медиану, квантиль уровня $0{,}95$ и квантиль уровня $0{,}2$.


Задание 14: Для величины с $F(x) = \dfrac{x^2}{9}$ на $(0; 3]$ (и $0$ слева, $1$ справа) построй квантильную функцию и найди медиану и p90.


Задание 15: Флаки-тест падает в каждом запуске независимо с вероятностью $0{,}2$. $X$ — номер запуска, на котором он впервые упал. Найди $F(x)$ и определи, сколько запусков нужно сделать, чтобы поймать падение с вероятностью не менее $0{,}9$.


Задание 16: Функция распределения задана формулой $F(x) = a + b\,\operatorname{arctg}\dfrac{x}{2}$ для всех вещественных $x$. Найди $a$ и $b$, медиану и $P(-2 \le X < 2)$.


Задание 17: Латентность сервиса распределена экспоненциально: $F(x) = 1 - e^{-x/80}$ (в миллисекундах). Найди p50, p95 и p99. Во сколько раз p99 больше медианы?


Задание 18: Запрос отправляется параллельно на $3$ реплики, и ответ считается готовым, когда ответили все три. Латентность каждой реплики равномерна на $[0; 100]$ мс, реплики независимы. Найди функцию распределения общего времени $Y = \max(X_1, X_2, X_3)$, его медиану и p95. Сравни с одной репликой.


Задание 19: Проверь, является ли функцией распределения $F(x) = 1 - \dfrac{1}{x^2}$ при $x \ge 1$ и $F(x) = 0$ при $x < 1$. Если да — найди медиану и p99 и оцени тяжесть хвоста.


Задание 20: Замерили латентность восьми запросов (мс): $12,\ 47,\ 23,\ 89,\ 35,\ 47,\ 150,\ 8$. Построй эмпирическую функцию распределения, найди эмпирическую медиану и p75, сравни медиану со средним.


Продвинутые (задания 21-30)

Задание 21: Выведи формулу метода обратного преобразования для экспоненциального распределения с параметром $\lambda$ и сгенерируй одно значение при $\lambda = 0{,}5$, если random() вернул $u = 0{,}37$. Объясни, почему в реальном коде пишут $-\ln(u)/\lambda$, а не $-\ln(1-u)/\lambda$.


Задание 22: Языковая модель после softmax выдала вероятности для пяти токенов: A $= 0{,}5$; B $= 0{,}2$; C $= 0{,}15$; D $= 0{,}1$; E $= 0{,}05$. (а) Какой токен будет выбран, если random() вернул $u = 0{,}73$? (б) Какие токены останутся при top-$p$ сэмплировании с $p = 0{,}9$ и какими станут их вероятности после ренормировки?


Задание 23: Классификатор выдал скоры. Положительные объекты (их $4$): $0{,}9;\ 0{,}8;\ 0{,}6;\ 0{,}35$. Отрицательные (их $6$): $0{,}7;\ 0{,}5;\ 0{,}4;\ 0{,}3;\ 0{,}2;\ 0{,}1$. Построй ROC-кривую как параметрический график двух функций распределения и посчитай AUC двумя способами.


Задание 24: Докажи вероятностное интегральное преобразование: если $X$ непрерывна и её $F$ строго возрастает, то $Y = F(X)$ равномерно распределена на $(0;1)$. Приведи три применения этого факта в ML.


Задание 25: Ты мониторишь дрейф данных. Признак приведён к равномерному на $[0;1]$ по обучающей выборке. За сегодня пришло $5$ значений: $0{,}05;\ 0{,}15;\ 0{,}35;\ 0{,}55;\ 0{,}60$. Посчитай статистику Колмогорова-Смирнова и реши, есть ли дрейф на уровне значимости $0{,}05$ (критическое значение для $n = 5$ равно $0{,}565$).


Задание 26: Приём hedged requests: запрос отправляется сразу на $2$ реплики, берётся первый пришедший ответ. Латентность каждой реплики экспоненциальна с $F(x) = 1 - e^{-x/100}$ мс, реплики независимы. Найди распределение времени $Y = \min(X_1, X_2)$, его медиану и p99. Сравни с одной репликой и обобщи на $n$ реплик.


Задание 27: Сервис устроен так: $70\%$ запросов обслуживаются из кеша за время, равномерное на $(0; 10]$ мс, остальные $30\%$ идут в базу, и там время экспоненциально со средним $100$ мс. Найди $F(x)$ при $x > 10$, посчитай среднюю латентность, p95, p99 и p99.9. Выполняется ли SLA «p99 не выше $500$ мс»? А «p99.9 не выше $500$ мс»?


Задание 28: Признак «число заказов пользователя» на выборке из $10$ человек принял значения $0,\ 0,\ 0,\ 1,\ 1,\ 2,\ 3,\ 5,\ 12,\ 40$. Разбей его на $4$ квантильных бина (как это делает histogram-based бустинг) и объясни, почему бины получились неравными по наполнению.


Задание 29: Нужно сэмплировать экспоненциальное время ($\lambda = 0{,}01$, среднее $100$), но только из хвоста $X > 200$. Отбраковка (генерировать и выбрасывать всё, что $\le 200$) слишком дорога. Выведи формулу усечённого сэмплирования через обратную функцию, посчитай значение при $u = 0{,}5$ и объясни результат.


Задание 30: Признак распределён по Парето: $F(x) = 1 - \dfrac{1}{x^2}$ при $x \ge 1$. Ты применяешь QuantileTransformer(output_distribution='normal'), то есть композицию $z = \Phi^{-1}\big(F(x)\big)$. Посчитай, во что перейдут значения $1{,}2$, $2$ и $10$, и объясни, что произошло с выбросом и каким моделям это поможет.


Частые ошибки

Ошибка 1: путать конвенции $F(x) = P(X < x)$ и $F(x) = P(X \le x)$

Неправильно: решить задачу по учебнику в русской конвенции, получить $F(3) = 2/6$ для кубика, а потом проверить себя кодом scipy.stats.randint(1,7).cdf(3), увидеть $0{,}5$ и решить, что где-то ошибка в арифметике.

Правильно: это две разные функции, отличающиеся ровно на $P(X = 3) = 1/6$. Русская $F(3) = P(X < 3) = 2/6$, международная $\tilde F(3) = P(X \le 3) = 3/6$. Перевод в обе стороны: $\tilde F(x) = F(x) + P(X = x)$.

Почему важно: это самая частая ошибка «на единицу» при работе с дискретными распределениями. В коде она проявляется так: чтобы получить $P(X \ge k)$ через scipy, надо писать dist.sf(k-1), а не 1 - dist.cdf(k) — второе даёт $P(X > k)$, то есть теряет целое значение $k$. При $k$ около медианы ошибка может достигать десятков процентов. Для непрерывных величин разницы нет вообще, поэтому привычка «да какая разница» формируется на непрерывных задачах и взрывается на дискретных.


Ошибка 2: применять формулу $P(a \le X \le b) = F(b) - F(a)$ к дискретной величине

Неправильно: «Кубик. $P(2 \le X \le 5) = F(5) - F(2) = \dfrac46 - \dfrac16 = \dfrac36 = 0{,}5$».

Правильно: формула $F(b) - F(a)$ считает вероятность промежутка $[a; b)$, где правый конец не включён. Значение $X = 5$ выпало из счёта. Верно так:

$$P(2 \le X \le 5) = F(5) - F(2) + P(X = 5) = \frac46 - \frac16 + \frac16 = \frac46 \approx 0{,}667$$

Почему важно: ошибка ровно на одну ступеньку лесенки, и чем меньше значений у величины, тем она больнее. У бинарной величины «одна ступенька» — это половина всей массы. Спасательный приём: у дискретной величины всегда выписывай явно, какие значения попадают в промежуток, и сверяй с суммой их вероятностей. Формула $F(b) - F(a)$ без поправок безопасна только для непрерывных величин.


Ошибка 3: считать, что $P(X = a) = 0$ означает «событие невозможно»

Неправильно: «Латентность непрерывна, значит вероятность получить ровно $180$ мс равна нулю, значит такого не бывает. Но замер показал $180$ мс — противоречие, теория неверна».

Правильно: нулевая вероятность и невозможность — разные вещи. Невозможное событие не содержит ни одного исхода; событие вероятности ноль исходы содержит, просто его мера равна нулю — как длина точки на отрезке. Осмысленный вопрос про непрерывную величину — это вопрос про промежуток: $P(179{,}5 \le X < 180{,}5)$, а не $P(X = 180)$.

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


Ошибка 4: не проверять, что $F$ дорастает до единицы

Неправильно: «Дана $F(x) = \dfrac{x}{5}$ при $0 < x \le 3$, $0$ слева, $1$ справа. Считаем $P(1 \le X < 2) = \dfrac25 - \dfrac15 = 0{,}2$».

Правильно: сначала надо было посмотреть на стык в точке $3$: $\dfrac35 = 0{,}6$, а справа стоит $1$. Это скачок величиной $0{,}4$ — то есть в точке $x = 3$ сидит комок вероятности $0{,}4$, и величина не непрерывная, а смешанная. Ответ $0{,}2$ для этого конкретного промежутка случайно верен, но любой вопрос вида «найди медиану», «найди $P(X \le 3)$», «непрерывна ли величина» будет решён неправильно.

Почему важно: проверка склеек — это пятнадцать секунд, которые ловят как ошибки в условии, так и собственные опечатки. Обратный вариант той же ошибки: если в задаче есть неизвестный параметр, его почти всегда находят именно из условия «$F$ доходит ровно до $1$». Не проверил склейки — не нашёл параметр.


Ошибка 5: мониторить среднее вместо перцентилей

Неправильно: «Средняя латентность $33{,}5$ мс при SLA $500$ мс — запас в пятнадцать раз, всё отлично».

Правильно: посчитать хвост. В задании 27 при среднем $33{,}5$ мс перцентиль p99 оказался $340$ мс, а p99.9 — $570$ мс, то есть SLA нарушен. Среднее и хвост — независимые характеристики: у двух сервисов может быть одинаковое среднее и различающиеся в десять раз перцентили.

Почему важно: пользователь чувствует не среднее, а свой личный запрос, и если страница собирает данные из двадцати вызовов, он видит максимум из двадцати, а не среднее. Отсюда правило индустрии: SLA формулируется в перцентилях, алерты вешаются на p95/p99, а среднее оставляют для оценки нагрузки на инфраструктуру. Тот же принцип работает и с метриками моделей: средняя ошибка регрессии ничего не говорит о том, насколько чудовищным бывает худший прогноз.


Ошибка 6: складывать перцентили

Неправильно: «Страница делает $5$ последовательных вызовов, у каждого p99 $= 100$ мс. Значит p99 страницы $= 500$ мс».

Правильно: перцентили не аддитивны. Правильная величина — это $F$ суммы, и её надо считать свёрткой или симуляцией. Зато мгновенно считается кое-что другое: вероятность, что хотя бы один из пяти вызовов попадёт в свой худший процент, равна $1 - 0{,}99^5 \approx 0{,}049$. То есть почти каждая двадцатая страница ловит хвост хотя бы одного сервиса.

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


Ошибка 7: искать квантиль дискретной величины как корень уравнения $F(x) = p$

Неправильно: «Величина принимает значения $10,20,30,40,50$ с вероятностями $0{,}05;\,0{,}15;\,0{,}3;\,0{,}3;\,0{,}2$. Ищем p95: решаем $F(x) = 0{,}95$... такого $x$ нет, значит задача некорректна».

Правильно: у ступенчатой $F$ уравнение $F(x) = p$ может не иметь решений (уровень перепрыгивается скачком) или иметь их бесконечно много (уровень совпал с полкой). Работающее определение — обобщённая обратная: $F^{-1}(p) = \inf\{x : P(X \le x) \ge p\}$. Здесь $P(X \le 40) = 0{,}8 < 0{,}95$, $P(X \le 50) = 1 \ge 0{,}95$, значит $x_{0{,}95} = 50$.

Почему важно: это не педантизм — от выбора соглашения зависят реальные цифры в отчётах. У numpy.quantile девять вариантов параметра method, и по умолчанию используется линейная интерполяция, а не обобщённая обратная. Поэтому p95 одних и тех же данных, посчитанный в numpy, в Prometheus и в ClickHouse, может различаться. На больших выборках разница пренебрежима, на выборке из двадцати значений — вполне заметна, и спор «у меня в дашборде другое число» решается не пересчётом, а сверкой методов.


Ошибка 8: считать, что среднее переносится через преобразование так же, как квантиль

Неправильно: «Латентность сильно скошена, поэтому буду работать в логарифмах. Среднее логарифма посчитал, экспоненту взял — получил среднюю латентность».

Правильно: через строго возрастающее преобразование $g$ квантили переносятся точно: $x_p\big(g(X)\big) = g\big(x_p(X)\big)$, потому что монотонное преобразование не меняет порядок и, значит, не меняет накопленные доли. А среднее — нет: $\mathrm{E}\,g(X) \ne g(\mathrm{E}\,X)$. Экспонента среднего логарифма — это среднее геометрическое, и для скошенных данных оно систематически меньше среднего арифметического.

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


Главное запомнить

📝 Ключевые понятия

Функция распределения: $F(x) = P(X < x)$ — вероятность того, что величина окажется строго левее $x$. Существует у любой случайной величины (в отличие от ряда распределения и плотности) и задаёт её распределение однозначно и полностью.

Четыре обязательных свойства: $0 \le F \le 1$; $F$ не убывает; $F$ непрерывна слева; $F(-\infty) = 0$, $F(+\infty) = 1$. Эти три условия (неубывание, непрерывность слева, пределы) не только необходимы, но и достаточны — по теореме о характеризации любая такая функция задаёт какую-то случайную величину.

Главная рабочая формула: $P(a \le X < b) = F(b) - F(a)$. Левый конец включён, правый — нет; это прямое следствие конвенции со строгим неравенством.

Скачок = вероятность точки: $P(X = a) = F(a+0) - F(a)$. Если $F$ непрерывна в точке — вероятность этой точки ноль; если есть скачок высотой $h$ — вероятность равна $h$.

Три типа величин на одном языке: дискретная — чистая лесенка, $F(x) = \sum_{x_i < x} p_i$; непрерывная — гладкая кривая без скачков, все $P(X = a) = 0$; смешанная — и то и другое. Смеси описываются только через $F$: ни ряда, ни плотности у них нет.

Нулевая вероятность $\ne$ невозможность: у непрерывной величины любая конкретная точка имеет вероятность ноль, но выпадает же что-то. Аналогия — длина точки на отрезке. Осмысленные вопросы про непрерывную величину — только про промежутки.

Две конвенции: русская $F(x) = P(X < x)$ (непрерывна слева) и международная $F(x) = P(X \le x)$ (непрерывна справа, именно её реализует весь научный софт). Разница ровно в $P(X = x)$ и видна только на дискретных и смешанных величинах.

Квантиль уровня $p$: число $x_p$ с условием $P(X < x_p) \le p \le P(X \le x_p)$. Для непрерывной строго возрастающей $F$ это просто корень уравнения $F(x) = p$; для дискретной пользуемся обобщённой обратной $F^{-1}(p) = \inf\{x : P(X \le x) \ge p\}$ — она определена всегда и единственна. Медиана — квантиль уровня $0{,}5$.

Метод обратного преобразования: если $U$ равномерна на $(0;1)$, то $X = F^{-1}(U)$ имеет распределение $F$. Обратное утверждение — вероятностное интегральное преобразование: $F(X)$ равномерна на $(0;1)$. Из этой пары вырастают генераторы случайных чисел, сэмплирование токенов, QuantileTransformer и равномерность p-value.

Квантили устойчивы и инвариантны: один выброс не двигает медиану и IQR, тогда как среднее и стандартное отклонение улетают. Через любое строго возрастающее преобразование квантили переносятся точно ($x_p(g(X)) = g(x_p(X))$), а среднее — нет.

Перцентили не складываются: p99 цепочки из пяти сервисов не равен ни сумме, ни максимуму их p99. Считать хвост суммы надо свёрткой или симуляцией; зато вероятность «хотя бы один попал в свой худший процент» считается мгновенно: $1 - 0{,}99^n$.


Связь с другими темами курса

Что нужно было знать до этого урока.

Урок 234 («Случайные величины») дал сам объект: величину, её возможные значения и ряд распределения. Сегодняшняя $F$ — это накопленная версия того же ряда, и переход между ними механический: из ряда в $F$ — кумулятивная сумма, из $F$ в ряд — размеры скачков.

Урок 229 (теоремы сложения и умножения) — фундамент всех доказательств этого урока. Разбиение события $\{X < x_2\}$ на два несовместных даёт неубывание $F$ и формулу $P(a \le X < b) = F(b) - F(a)$; умножение вероятностей независимых событий даёт распределения максимума и минимума ($F^n$ и $1 - (1-F)^n$) в заданиях 18 и 26.

Урок 233 (схема Бернулли) снабдил нас рядом распределения для примеров с батчами и ошибками модели, а урок 228 (геометрическая вероятность) — идеей «вероятность пропорциональна длине», из которой сразу получается равномерное распределение и его $F(x) = \dfrac{x-a}{b-a}$.

Что изучить дальше.

Следующий урок 236 («Плотность вероятности») вводит производную $f(x) = F'(x)$ — скорость накопления массы. Всё, что мы сегодня считали как разность $F(b) - F(a)$, превратится в интеграл $\int_a^b f(x)\,dx$, и появится удобный аппарат для непрерывных величин.

Уроки 237-238 (математическое ожидание и дисперсия) дадут числовые характеристики, которые сворачивают $F$ в пару чисел, — и заодно объяснят, почему такое сворачивание иногда теряет главное (пример из задания 16: у распределения Коши $F$ есть, а среднего нет).

Урок 240 («Основные распределения») наполнит каркас содержанием: биномиальное, пуассоновское, равномерное, нормальное, экспоненциальное — у каждого своя $F$ и своя квантильная функция, и все они реализованы в scipy.stats через один и тот же интерфейс .cdf() / .ppf().

Урок 241 (центральная предельная теорема) сформулирован именно на языке функций распределения: $F_n(x) \to \Phi(x)$ поточечно. Другого языка для этого утверждения не существует, потому что плотности могут не существовать, а $F$ есть всегда. Урок 242 (закон больших чисел) объяснит, почему эмпирическая $\hat F_n$ сходится к настоящей $F$ — та самая теорема Гливенко-Кантелли, на которой держится бутстрэп.

Уроки 245-248 переводят всё это в статистику: доверительные интервалы строятся через квантили, проверка гипотез — через $P(T \ge t)$, то есть хвост функции распределения, а критерий согласия (хи-квадрат в уроке 248, Колмогорова-Смирнова — его непараметрический родственник) прямо сравнивает эмпирическую $F$ с теоретической.

Где это нужно в жизни.

💻 В программировании. Генераторы случайных чисел любого распределения (numpy.random, метод обратного преобразования внутри); перцентильные SLA и алерты на p95/p99 в мониторинге; hedged requests и таймауты, рассчитанные по квантилям; нагрузочное тестирование, где отчёт всегда в перцентилях, а не в среднем; выбор размера буфера или таймаута как $F^{-1}(0{,}999)$.

🤖 В ML/AI. Сэмплирование токена через cumsum + searchsorted, top-$p$ (nucleus) и температура — операции над лесенкой $F$; ROC-кривая как параметрический график двух функций распределения и AUC как доля правильно упорядоченных пар; калибровка вероятностей и калибровочная кривая; QuantileTransformer и RobustScaler; квантильное бинирование признаков в LightGBM; квантильная регрессия с pinball-лоссом, которая предсказывает не среднее, а заданный перцентиль; conformal prediction, где интервал предсказания — это квантиль распределения невязок; детекция дрейфа данных через KS-тест на эмпирических $F$.

📊 В Data Science. ECDF-график вместо гистограммы (не нужно выбирать число бинов, видно хвосты и атомы); медиана и IQR как устойчивые характеристики; winsorize и клиппинг выбросов по квантилям; когортный анализ по перцентилям; бутстрэп, который целиком стоит на эмпирической функции распределения; A/B-тесты на перцентилях, а не на средних, когда метрика скошена.

🔬 В науке. Слабая сходимость (сходимость по распределению) — базовое понятие теории вероятностей, определённое через $F$; предельные теоремы Ляпунова и Линдеберга; критерии согласия и непараметрическая статистика; в физике — распределения энергий и функция Ферми-Дирака, по сути та же накопленная вероятность; в биометрии — перцентильные шкалы роста и веса детей; в гидрологии и страховании — расчёт «столетнего паводка» как квантиля уровня $0{,}99$ годового максимума.


Интересные факты

💡 Функция распределения получила официальный статус в один год с самой теорией вероятностей. Колмогоров опубликовал «Основные понятия теории вероятностей» в 1933 году — и в той же статье, где вероятность впервые определялась аксиоматически как мера, он ввёл и критерий согласия, сравнивающий эмпирическую $F$ с теоретической. Через шесть лет Николай Смирнов обобщил его на две выборки, и с тех пор тест носит двойное имя. То есть инструмент, которым сегодня проверяют дрейф данных в проде, ровесник самого понятия вероятностного пространства.

💡 «Основная теорема статистики» звучит скромнее, чем есть. Теорема Гливенко-Кантелли (1933) утверждает, что эмпирическая функция распределения сходится к настоящей равномерно по всей числовой оси — не в отдельных точках, а вся кривая целиком, с гарантированной скоростью. Именно поэтому бутстрэп работает: перевыбирая из имеющихся данных, ты фактически перевыбираешь из $\hat F_n$, а она уже почти неотличима от $F$. Без этой теоремы вся непараметрическая статистика висела бы в воздухе.

💡 ROC-кривая родилась в радиолокации. Аббревиатура расшифровывается как Receiver Operating Characteristic — «рабочая характеристика приёмника». Во время Второй мировой инженеры разбирались, почему операторы радаров по-разному отличают самолёт от помехи: у каждого свой порог срабатывания, и кривая описывала весь набор возможных компромиссов между пропуском цели и ложной тревогой. Потом метод забрала психофизика (теория обнаружения сигнала), потом медицинская диагностика, и только в 1990-х он попал в машинное обучение. За полвека сменились три области, а формула — «параметрический график двух функций распределения» — не изменилась ни на символ.

💡 Хвост дороже среднего: статья, изменившая инженерную культуру. В 2013 году Джефф Дин и Луис Барросо опубликовали «The Tail at Scale», где показали простую арифметику: если сборка страницы требует ста параллельных вызовов, то доля страниц, поймавших хотя бы один p99-ответ, равна $1 - 0{,}99^{100} \approx 63\%$. Не один процент, а почти две трети. После этой статьи hedged requests, micro-partitioning и агрессивные таймауты стали стандартом проектирования распределённых систем, а дашборды со средним временем ответа — признаком дурного тона.

💡 Слово «перцентиль» придумал Гальтон, слово «квантиль» — Кендалл. Фрэнсис Гальтон ввёл перцентили в 1885 году, работая с антропометрическими данными: ему нужен был способ описать положение человека в популяции без привязки к единицам измерения. Общий термин «квантиль» появился только в 1940 году у Мориса Кендалла — на полвека позже частного случая. А сама идея делить распределение на равные по вероятности части восходит к медианам в демографических таблицах XVII века, задолго до того, как была сформулирована теория вероятностей.


Лайфхаки и полезные трюки

1. Чек-лист «это вообще функция распределения?» за пятнадцать секунд

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

Пример: дана $F(x) = ax^2$ на $(0;3]$. Первым делом смотрим правый конец: $9a$ должно равняться $1$, значит $a = 1/9$. Параметр найден до того, как ты вообще начал что-то считать.


2. Читай скачки глазами

Высота вертикального отрезка на графике $F$ — это вероятность соответствующей точки. Дискретная величина — сплошные скачки; непрерывная — ни одного; смешанная — скачки плюс наклонные участки. По одной картинке ты сразу знаешь тип величины и весь её ряд распределения.

Пример: на графике латентности видна вертикальная ступенька высотой $0{,}3$ в нуле — значит $30\%$ запросов обслуживаются мгновенно (кеш-хиты), и никакая «средняя латентность» этого не покажет.


3. В коде используй sf, а не 1 - cdf

Функция выживания sf(x) $= 1 - F(x)$ реализована отдельно и считается численно устойчиво в хвосте. Разность $1 - 0{,}9999999$ в float64 теряет почти все значащие цифры, а sf даёт правильный ответ до $10^{-300}$.

Пример: norm.sf(10) вернёт $7{,}62 \cdot 10^{-24}$, а 1 - norm.cdf(10) вернёт ровно $0$ — потому что cdf(10) округлилось до единицы. Для дискретных величин там же спрятана шпаргалка по конвенциям: $P(X \ge k)$ — это sf(k-1), а не sf(k).


4. Квантили считай в удобной шкале, среднее — нет

Через любое строго возрастающее преобразование квантили переносятся точно: $x_p(\log X) = \log x_p(X)$. Значит перцентили латентности можно спокойно считать в логарифмической шкале, в нормализованной, в ранговой — и возвращаться обратно без искажений.

Пример: гистограмма латентности в линейной шкале нечитаема (всё слипается у нуля, один хвост до горизонта). Строй её в $\log$, находи p95 там, потом бери экспоненту — получишь ровно p95 исходных данных. С арифметическим средним такой фокус даст среднее геометрическое, то есть заниженный ответ.


5. Рисуй ECDF вместо гистограммы

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

Пример: две гистограммы латентности до и после релиза выглядят «примерно одинаково», а два ECDF на одних осях сразу показывают, что после релиза кривая расходится с исходной начиная с уровня $0{,}9$ — то есть поехал именно хвост. Это же и есть визуализация KS-статистики: максимальный вертикальный зазор между кривыми.


6. Сэмплирование категориального — три строки на любом языке

Кумулятивная сумма плюс двоичный поиск: c = np.cumsum(p), u = rng.random(), idx = np.searchsorted(c, u). Это обобщённая обратная функция в чистом виде, работает за $O(\log n)$ и не требует никаких библиотек распределений.

Пример: нужно сэмплировать из словаря на $50\,000$ токенов — линейный перебор даст $50\,000$ сравнений на токен, searchsorted — шестнадцать. При генерации длинного текста разница заметна невооружённым глазом.


7. Усечённое сэмплирование — растяни random(), а не отбраковывай

Чтобы сгенерировать значение при условии $X \ge a$, не надо генерировать в цикле и выбрасывать негодные. Достаточно растянуть равномерное число на нужный участок: $x = F^{-1}\big(F(a) + u\,(1 - F(a))\big)$. Один вызов вместо случайного их числа.

Пример: нужны значения из хвоста $X > 1000$ экспоненциального распределения со средним $100$. Отбраковка потребует в среднем $e^{10} \approx 22\,000$ попыток на одно число; формула выше — ровно одну.


8. Проверяй ответ обратной подстановкой

Нашёл квантиль — подставь его обратно в $F$ и убедись, что получилось исходное $p$. Это ловит и арифметические ошибки, и путаницу со знаком логарифма, и ошибки в выборе куска кусочно-заданной функции.

Пример: в задании 27 получили p99 $= 340{,}1$ мс. Проверка: $1 - 0{,}3\,e^{-3{,}401} = 1 - 0{,}3 \cdot 0{,}03333 = 1 - 0{,}01 = 0{,}99$ ✅ Пятнадцать секунд — и ты точно знаешь, что не ошибся.


9. Фиксируй метод расчёта перцентилей в отчёте

У numpy.quantile девять реализаций, у Prometheus своя (по бакетам гистограммы, с интерполяцией внутри бакета), у ClickHouse — свои функции quantile, quantileExact, quantileTDigest. На одних и тех же данных они дают разные числа.

Пример: «у меня p99 = 340 мс, а в Grafana 380» — это почти наверняка не расхождение данных, а разные методы: Prometheus считает перцентиль по границам бакетов и в широком бакете может ошибаться на десятки процентов. Прежде чем искать баг в данных, сверь методы.


Заключение

Оглянись на то, что произошло за урок. Мы взяли одну-единственную функцию — «какая доля массы лежит левее $x$» — и оказалось, что этого достаточно, чтобы описать любую случайную величину на свете: дискретную с её лесенкой, непрерывную с её гладкой кривой, смешанную, у которой нет ни ряда распределения, ни плотности. Из четырёх её свойств вывелась вся арифметика вероятностей промежутков. Из её скачков — вероятности отдельных точек. Из её обращения — медиана, перцентили, SLA, генератор случайных чисел любого закона, сэмплирование токенов, квантильная нормализация признаков и ROC-кривая.

И самое ценное, что стоит унести, — это смена оптики. До этого урока «случайная величина» описывалась вопросом «а сколько в среднем?». Теперь у тебя есть аппарат, который отвечает на честный вопрос: «а как оно распределено целиком?» Среднее — одно число, свернувшее всю картину и потерявшее хвост; функция распределения — вся картина без потерь. Дежурный инженер из истории в начале урока смотрел на среднее и не видел, что каждый двадцатый запрос отваливается по таймауту. Ты теперь смотришь на p95 и p99 — и видишь.

Эта привычка стоит дорого в буквальном смысле. Она отличает мониторинг, который ловит проблемы, от мониторинга, который рисует зелёные графики, пока пользователи уходят. Она отличает препроцессинг, устойчивый к выбросам, от препроцессинга, который ломается на одном аномальном значении. И она отличает выводы из данных, которые выдерживают проверку, от выводов, построенных на одном свёрнутом числе.

В следующем уроке мы посмотрим на $F$ под микроскопом: возьмём производную и получим плотность вероятности — скорость, с которой накапливается масса. Оказывается, гораздо удобнее рисовать и интерпретировать именно её: горбы плотности показывают, где значения гуще, а площадь под кривой на промежутке — это ровно та вероятность, которую мы сегодня считали разностью $F(b) - F(a)$. Функция распределения останется фундаментом, а плотность станет рабочим инструментом. Погнали. 🚀

Понял тему? Закрепи в боте! 🚀

Попрактикуйся на задачах и получи персональные рекомендации от AI

💪 Начать тренировку
💬 Есть вопрос? Спроси бота!