Мы уже упоминали, что оценивать вероятности классов как \(softmax(f_w(x_i))\) для какой-то произвольной функции \(f_w\) – это дело подозрительное. В этом разделе мы поговорим о том, как это делать хорошо и правильно.
Ограничимся пока случаем двуклассовой классификации с классами 0 и 1. Пожалуй, если утверждается, что мы предсказываем корректную вероятность класса 1 (обозначим её \(q(x_i)\)), то прогноз «объект \(x_i\) принадлежит классу 1 с вероятностью \(\frac23\)» должен сбываться в \(\frac23\) случаев. То есть, условно говоря, если мы возьмём все объекты, которым мы предсказали вероятностью \(\frac23\), то среди них что-то около двух третей действительно имеет класс 1. На математическом языке это можно сформулировать так: Если \(\widehat{p}\) – предсказанная вероятность класса 1, то \(P(y_i = 1 \vert q(x_i) = \widehat{p}) = \widehat{p}\).
К сожалению, в реальной жизни \(\widehat{p}\) – это скорее всего вещественные числа, которые будут различными для различных \(y_i\), и никаких вероятностей мы не посчитаем, но мы можем разбить отрезок \([0,1]\) на бины, внутри каждого из которых уже вычислить, каковая там доля объектов класса 1, и сравнить эту долю со средним значением вероятности в бине:
У модели, которая идеально предсказывает вероятности (как обычно говорят, у идеально калиброванной модели) красные точки на диаграме калибровки должны совпадать с синими.
А вот на картинке выше это не так: красные точки всегда ниже синих. Давайте поймём, что это значит. Получается, что наша модель систематически завышает предсказанную вероятность (синие точки), и порог отсечения нам, выходит, тоже надо было бы сдвинуть вправо:
Но такая картинка, пожалуй, говорит о какой-то серьёзной патологии классификатора; гораздо чаще встречаются следующие две ситуации:
Слишком уверенный (overconfident) классификатор:
Такое случается с сильными классификаторыми (например, нейросетями), которые учились на метки классов, а не на вероятности: тем самым процесс обучения стимулировал их всегда давать как можно более близкий к 0 или 1 ответ.
Неуверенный (underconfident) классификатор:
Такое может случиться, например, если мы слишком много обращаем внимания на трудные для классификации объекты на границе классов (как, скажем, в SVM), в каком-то смысле в ущерб более однозначно определяемым точкам. Этим же могут и грешить модели на основе бэггинга (например, случайный лес). Грубо говоря, среднее нескольких моделей предскажет что-то близкое к единице только если все слагаемые предскажут что-то, близкое к единице – но из-за дисперсии моделей это будет случаться реже, чем могло бы. См. статью.
Вам даже будут приводить какие-то обоснования. Важно понимать, что происходит на самом деле, и не дать ввести себя в заблуждение. В качестве противоядия от иллюзий предлагаем рассмотреть два примера.
Обучим на нём логистическую регрессию из sklearn безо всяких параметров (то есть \(L^2\)-регуляризованную, но это не так важно). Классы не так-то просто разделить, вот и логистическая регрессия так себе справляется. Ниже изображена часть тестовой выборки вместе с предсказанными вероятностями классов для всех точек области
Видим, что модель не больно-то уверена в себе, и ясно почему: признаковое описание достаточно бедное и не позволяет нам хорошо разделить классы, хотя, казалось бы, это можно довольно неплохо сделать.
Видим, что имеет место сочетание двух проблем: неуверенности посередине и очень уверенных ошибок по краям.
Нарисуем теперь калибровочные кривые для обеих моделей:
Калибровочные кривые весьма примечательны; в любом случае ясно, что с предсказанием вероятностей всё довольно плохо. Посмотрим ещё, какие вероятности наши классификаторы чаще приписывают объектам:
Как и следовало ожидать, предсказания слабого классификатора тяготеют к серединке (та самая неуверенность), а среди предсказаний переобученного очень много крайне уверенных (и совсем не всегда правильных).
Попробуем понять и простить её.
Как мы помним, логистическая регрессия учится путём минимизации функционала
\[l(X, y) = -\sum_{i=1}^N(y_i\log(\sigma(\langle w, x_i\rangle)) + (1 - y_i)\log(1 - \sigma(\langle w, x_i\rangle)))\]Отметим между делом, что каждое слагаемое – это кроссэнтропия распределения \(P\), заданного вероятностями \(P(0) = 1 - \sigma(\langle w, x_i\rangle)\) и \(P(1) = \sigma(\langle w, x_i\rangle)\), и тривиального распределения, которое равно \(y_i\) с вероятностью \(1\).
Допустим, что мы обучили по всему универсуму данных \(\mathbb{X}\) идеальную логистическую регрессию с идеальными весами \(w^{\ast}\). Пусть, далее, оказалось, что у нас есть \(n\) объектов \(x_1,\ldots,x_n\) с одинаковым признаковым описанием (то есть по сути представленных одинаковыми векторами \(x_i\)), но, возможно, разными истинными метками классов \(y_1,\ldots,y_n\). Тогда соответствующий им кусок функции потерь имеет вид
\[-\left(\sum_{i=1}^ny_i\right)\log(\sigma(\langle w, x_1\rangle)) -\left(\sum_{i=1}^n (1 - y_i)\right)\log(1 - \sigma(\langle w, x_1\rangle)) =\] \[=-n\left(\vphantom{\frac12}p_0\log(\sigma(\langle w, x_1\rangle)) + p_1\log(1 - \sigma(\langle w, x_1\rangle))\right)\]где \(p_j\) – частота \(j\)-го класса среди истинных меток. В скобках также стоит кросс-энтропия распределения, задаваемого частотой меток истинных классов, и распределения, предсказываемого логистической регрессией. Минимальное значение кросс-энтропии (и минимум функции потерь) достигается, когда
\[\sigma(\langle w, x_1\rangle) = p_0,\quad 1 - \sigma(\langle w, x_1\rangle) = p_1\]Теперь, если признаковое описание данных достаточно хорошее (то есть классы не перемешаны как попало и всё-таки близки к разделимым) и в то же время модель не переобученная (то есть, в частности, предсказания вероятностей не скачут очень уж резко – вспомните второй пример), то результат, полученный для \(n\) совпадающих точек будет приблизительно верным и для \(n\) достаточно близких точек: на всех них модель будет выдавать примерно долю положительных, то есть тоже хорошую оценку вероятности.
Пусть наша модель (бинарной классификации) для каждого объекта \(x_i\) выдаёт некоторое число \(q(x_i)\in[0,1]\). Как же эти числа превратить в корректные вероятности?
Вместо разности модулей можно рассматривать и разность квадратов.
Метод довольно простой и понятный, но требует подбора числа бинов и предсказывает лишь дискретное множество вероятностей.
Минимизация осуществляется при помощи pool adjacent violators algorithm, и эти страницы слишком хрупки, чтобы выдержать его формулировку.
где \(a\) и \(b\) подбираются методом максимального правдоподобия на отложенной выборке:
\[-\sum_{i=1}^N(\vphantom{\frac12}y_i\log(\sigma(q(x_i)) + (1 - y_i)\log(1 - \sigma(q(x_i))))\longrightarrow\min\limits_{a,b}\]Для избежания переобучения Платт предлагал также заменить метки \(y_i\) и \((1 - y_i)\) на регуляризованные вероятности таргетов:
\[t_0 = \frac1{\#\{i \vert y_i = 0\} + 2},\quad t_0 = \frac{\#\{i \vert y_i = 1\}}{\#\{i \vert y_i = 0\} + 2}\]Калибровка Платта неплохо справляется с выколачиванием вероятностей из SVM, но для более хитрых классификаторов может спасовать. В целом, можно показать, что этот метод хорошо работает, если для каждого из истинных классов предсказанные вероятности \(q(x_i)\) распределы нормально с одинаковыми дисперсиями. Подробнее об этом вы можете почитать в этой статье. Там же описано обобщение данного подхода – бета-калибровка.
С большим количеством других методов калибровки вы можете познакомиться в этой статье
Калибровочные кривые хорошо показывают, что есть проблемы, но как оценить наши потуги по улучшению предсказания вероятностей? Хочется иметь какую-то численную метрику. Мы упомянем две разновидности, которые по сути являются прямым воплощением описанных выше идей.
или
\[\max\limits_{j=1,\ldots,k}\left|\overline{y}(\mathbb{B}_j) - \overline{q}(\mathbb{B}_j)\right|\]где \(\overline{y}(\mathbb{B}_j)\) – среднее значение \(y_i\), а \(\overline{q}(\mathbb{B}_j)\) – среднее значение \(q(x_i)\) для \(x_i\), таких что \(q(x_i)\in\mathbb{B}_j\). Проблема этого способа в том, что мы можем очень по-разному предсказывать в каждом из бинов вероятности (в том числе константой) без ущерба для метрики.
Казалось бы, в чём смысл? Немного подрастить мотивацию помогает следующий пример. Допустим, наши таргеты совершенно случайны, то есть \(P(y_i = 1 \vert x_i) = P(y_i)\). Тогда хорошо калиброванный классификатор должен для каждого \(x_i\) предсказывать вероятность \(\frac12\); соответственно, его brier score равен \(\frac14\). Если же классификатор хоть в одной точке выдаёт вероятность \(p>\frac12\), то в маленькой окрестности он должен выдавать примерно такие же вероятности; поскольку же таргет случаен, локальный кусочек суммы из brier score будет иметь вид \(\frac{N'}{2}p^2 + \frac{N'}{2}(1-p)^2 < \frac{N'}2\), что хуже, чем получил бы всегда выдающий \(\frac12\) классификатор.
Не обязательно брать квадратичную ошибку; сгодится и наш любимый log-loss:
\[\sum_{i=1}^N\left(\vphantom{\frac12}y_i\log{q(x_i)} + (1 - y_i)\log(1 - q(x_i))\right)\]Это же и помогает высветить ограничения подхода, если вспомнить рассуждения о калиброванности логистической регрессии. Для достаточно гладких классификатора и датасета briar score и log-loss будут адекватными средствами оценки, но если нет – возможно всякое.
Вопрос на засыпку: а как быть, если у нас классификация не бинарная, а многоклассовая? Что такое хорошо калиброванный классификатор? Как это определить численно? Как заставить произвольный классификатор предсказывать вероятности?
Мы не будем про это рассказывать, но призываем читателя подумать над этим самостоятельно или, например, посмотреть туториал с ECML KDD 2020.