Нет, нет, я совсем не про геометрию или физику, я про множество!

Квадрат Серпинского

Правда красота? Квадрат Серпинского - по истине восхитительная вещь, особенно с точки зрения теории множеств, ведь если взять ручку и попробовать на нем нарисовать овал не отрывая руки, то вы не сможете его нарисовать так, чтобы в него не вошли белые области - это и есть неформальное определение "везде неплотного множества".

Почему я упоминаю его? Ну, просто дело в том, что как будто бы современные неглубокие знания очень многих начинающих дата-сайнтистов автору представляются именно таким образом. Да, что уж греха таить, знания автора тоже не так уж и далеки от квадрата Серпинского. Воспринимайте аналогию следующим образом: пусть какой-нибудь нарисованный таким образом овал - это какая-нибудь тема в машинном обучении и вся печаль в том, что стоит чуть отойти от этой темы или уйти в ее глубь, то сразу появляются пробелы и непонимания.

Автор действительно убежден, что не так важно в каком количестве тем вы разбираетесь, как важно то, насколько хорошо вы разбираетесь в том, в чем считаете, что разбираетесь, ибо как говорил Брюс Ли: «Я не боюсь того, кто изучает десять тысяч тем машинного обучения. Я боюсь того, кто изучает одну тему десять тысяч раз».

Какая тут связь с машинным обучением, спросите вы? Автор начал изучать, что же такое машинное обучение еще в далеком 2019-ом году, как только окончил 2-ой курс университета, и автору как-то сразу интуиция подсказывала, что карьера в машинном обучении не заканчивается на fit/predict, что должно быть сильно больше понимания в том, что мы fit'им и что predict'им.

Так вот, а теперь к сути. Хотелось бы попробовать озвучить некоторый, как кажется, более глубокий взгляд на привычные уже нам в ML вещи, вероятно, написать даже целую серию статей и попробовать в них посмотреть на многие классические аспекты машинного обучения с сильным погружением в теорию вероятности, математический анализ и линейную алгебру, или обратить внимание на просто некоторые неочевидные вещи, ибо как говорил Станиславский "не надо помнить, надо понимать" :)

PS: он так не говорил, автор это выдумал.

Accuracy, Precision, Recall, F1-score

Так и тянется рука приписать слева `from sklearn.metrics import`, не правда ли? :D

В этой статье речь пойдет про эти четыре, всем нам уже привычные, метрики классификации.

Если вы хоть чуть-чуть знакомы с тем, что такое "метрика классификации", то вам, вероятно, знакомы эти слова или по крайней мере первое - Accuracy. Но что в них может быть такого особенного?! Кажется, что размышление над этим вопросом заканчиваются где-то на "использовать это не очь, использовать это круть" ну или хотя бы на "использовать это, если классы сбалансированы, а это если нет". Такие же мысли посещали и автора, но давайте попробуем немножечко посмотреть на это математически!

Столп 1-ый

Для начала сформулируем, во что же мы сейчас будем углубляться.


И так, пусть

n \in \{1,2,3,...\}  - количество\ объектов\ в \ рассматриваемой \ выборке,\\C \in \{2,3,4,...\} - количество \ классов,\\\bar{t} \in \{0, 1, 2, ..., C-1\}^n - вектор \ длины \ n \ с \ реальными \ метками \ классов,\\\bar{y} \in \{0, 1, 2, ..., C-1\}^n - вектор \ длины \ n \ со \ спрогнозированными \ метками \ классов.

На основе этих обозначений введем следующие функции для более простого формального изложения последующего материала:

  • Пусть количество объектов, являющихся представителями класса "c" и при этом помеченных нашим алгоритмом как "c", будем называть true positive rate'ом и будем считать его равным значению следующей функции:

tp(\bar{t}, \bar{y}, c) = \sum^{n-1}_{i=0}{I[\bar{t}_i = c, \bar{y}_i = c]}
  • Пусть количество объектов, НЕ являющихся представителями класса "c", но при этом помеченных нашим алгоритмом как "c", будем называть false positive rate'ом и будем считать его равным значению следующей функции:

fp(\bar{t}, \bar{y}, c) = \sum^{n-1}_{i=0}{I[\bar{t}_i \neq c, \bar{y}_i = c]}
  • Пусть количество объектов, являющихся представителями класса "c", но при этом помеченных нашим алгоритмом как НЕ "c" будем называть false negative rate'ом и будем считать его равным значению следующей функции:

fn(\bar{t}, \bar{y}, c) = \sum^{n-1}_{i=0}{I[\bar{t}_i = c, \bar{y}_i \neq c]}

Чтож-ж, чуткий читатель может заметить, что тут нет true negative rate'а... хмм... ну что же, а вот и первый столп - ОН И НЕ НУЖЕН!


Действительно, лучше это будет понятно дальше, но, вообще говоря, когда рассматривается задача в общем виде, в которой может быть как 2, так и больше классов, то оказывается, что лучше и не определять никакое "количество объектов, НЕ являющихся представителями класса "c", но при этом помеченных нашим алгоритмом как НЕ "c"", т.к. это может иметь смысл только в бинарном случае, ибо в нем, мы предполагаем, что если объект имеет метку класса не равную "c", то он точно имеет метку равную "1-c", а в общем случае, когда имеем необязательно ровно два класса, то, пробегая по всем классам, вводить это понятие и не нужно, т.к. такие примеры уже учтены.

Что же, если последняя фраза непонятна до конца, то не расстраивайтесь, прочитайте ее еще раз и соотнесите с тем, что она лишь многословное описание следующего лаконичного выражения:

\sum^{C-1}_{c=0}(tp(\bar{t}, \bar{y}, c) + fp(\bar{t}, \bar{y}, c) + fn(\bar{t}, \bar{y}, c))=\\=\sum^{C-1}_{c=0}\sum^{n}_{i=1}(1 - I[\bar{t_i}\neq c,\bar{y_i}\neq c])=\sum^{n}_{i=1}\sum^{C-1}_{c=0}(1 - I[\bar{t_i}\neq c,\bar{y_i}\neq c])=\\=\{\sum^{C-1}_{c=0}(1 - I[t\neq c,y\neq c]) = 1, т.к. объект \ не\ может\ не\ принадлежать\ ни\ одному\ классу\\ и\ не\ может\ принадлежать\ больше, чем\ одному\ классу\}=\\=\sum^n_{i=0}1=n

Столп 2-ой

Давайте теперь сделаем некоторый неожиданный поворот сюжета и определим precision и recall не так, как вы привыкли:

Пусть

precision_c:=pr(t,y,c)=p(t=c|y=c),\\recall_c:=rc(t,y,c)=p(y=c|t=c).

То есть как условные вероятности. Что же это все значит?! Давайте разбираться и попробуем перевести на человеческий язык то, что здесь написано.

А написано следующее:

Рассмотрим некоторый случайно взятый объект в рассматриваемой задаче, тогда precision будет численно характеризовать величину вероятности события, при котором объект принадлежит к классу "c", при условии, что наш алгоритм предсказал ему принадлежность к классу "c", а recall тогда будет характеризовать величину вероятности события, при котором наш алгоритм предскажет принадлежность объекта к классу "c", при условии, что объект действительно принадлежит к классу "c". И это второй столп :) Я бы даже сказал, что один из самых важных в этой статье, ибо если такое определение эквивалентно с тем, как принято его вводить, то этот теоретико-вероятностный подход вносит действительно очень большую ясность в то, почему это действительно важные метрики, и позволяет на новом уровне интерпретировать динамику их изменения на графиках, допустим, при валидации.

Что же, а теперь попробуем определенным образом расписать эти вероятности.

Но давайте сначала внесем еще немного формализма и определим, что же вообще такое вероятность. Охх, тут бы наверное еще постов 10 написать, чтобы апеллировать к чему-то, ну совсе-е-ем строгому, но давайте опустим это и напишем консервативное и очень давнее определение, обоснование уместности которого мы опустим:

Пусть в природе нашей задачи существует ровно N объектов, тогда верно следующее:

p(y=c)=\sum^{N}_{k=1}\frac{I[y_k=c]}{N},

в случае, если природа нашей задачи характеризуется счетным множеством, то запись будет следующей:

p(y=c)=\lim_{N\to+\infty}\sum^{N}_{k=1}\frac{I[y_k=c]}{N}. \ (*)

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

Пусть\ A\ и\ B - некоторые\ события, тогда\\ p(A|B)=\frac{p(A,B)}{p(B)}.

Хорошо, а теперь давайте объединим эти две формулы и распишем, допустим, precision (оставим вывод для recall'а читателю, чтобы сократить и так уже некороткое изложение):

p(t=c|y=c)=\frac{p(t=c,y=c)}{p(y=c)}=\{применяем\ (*)\}=\\=\frac{\lim_{N\to+\infty}\sum^{N}_{k=1}\frac{I[t_k=c,y_k=c]}{N}}{\lim_{N\to+\infty}\sum^{N}_{k=1}\frac{I[y_k=c]}{N}}=...

а теперь давайте сделаем некоторое допущение, пусть все-таки у нас нет доступа ко всем объектам (или, если говорить в терминах математической статистики, "ко всей генеральной совокупности"), но есть к некоторому его подмножеству, то есть пусть наша выборка семплирована равновероятным образом, тогда предел можно убрать и просто помнить, что чем больше размер выборки, полученной таким образом, тем ближе значения к тем, что считаются через предел:

...= \{пусть\ \bar{y}\ и\ \bar{t} -\ соответствующие\ выборки\}=p(t=c|y=c)=\frac{p(t=c,y=c)}{p(y=c)}\approx\\\approx\frac{\sum^{N}_{k=1}\frac{I[t_k=c,y_k=c]}{N}}{\sum^{N}_{k=1}\frac{I[y_k=c]}{N}}=\frac{\sum^{N}_{k=1}I[t_k=c,y_k=c]}{\sum^{N}_{k=1}I[y_k=c]}=\\=\frac{\sum^{N}_{k=1}I[t_k=c,y_k=c]}{\sum^{N}_{k=1}I[(t_k=c\ или\ t_k\neq c),y_k=c]}=\\=\frac{\sum^{N}_{k=1}I[t_k=c,y_k=c]}{\sum^{N}_{k=1}(I[t_k=c,y_k=c] + I[t_k\neq c,y_k=c])}=\\=\frac{\sum^{N}_{k=1}I[t_k=c,y_k=c]}{\sum^{N}_{k=1}I[t_k=c,y_k=c] + \sum^{N}_{k=1}I[t_k\neq c,y_k=c]}=\\=\frac{tp(\bar{t},\bar{y},c)}{tp(\bar{t},\bar{y},c) + fp(\bar{t},\bar{y},c)}.

Получаем уже всем известные равенства, которые обычно вводятся сразу как определения:

pr(\bar{t},\bar{y},c)=\frac{tp(\bar{t},\bar{y},c)}{tp(\bar{t},\bar{y},c) + fp(\bar{t},\bar{y},c)};\ \ rc(\bar{t},\bar{y},c)=\frac{tp(\bar{t},\bar{y},c)}{tp(\bar{t},\bar{y},c) + fn(\bar{t},\bar{y},c)};\\f1(\bar{t},\bar{y},c)=\frac{2*pr(\bar{t},\bar{y},c)*rc(\bar{t},\bar{y},c)}{pr(\bar{t},\bar{y},c) + rc(\bar{t},\bar{y},c)}.

Таким образом, если наши рассматриваемые объекты получены из генеральной совокупности максимально случайным образом (точнее говоря "равновероятно"), то чем больше выборка, тем точнее посчитанные нами precision и recall приближают значения (точнее говоря "аппроксимируют") упомянутые выше условные вероятности.

Столп 3-й

Так, а теперь мы уже совсем близко к финальному определению метрик для некоторой общей задачи с "c" классами, осталось только напомнить, что метрики многоклассовой классификации разделяются на micro, macro и weighted.

Сформулируем их определения:

accuracy := acc(\bar{t},\bar{y},C)=\frac{\sum^{C-1}_{c=0}tp(\bar{t},\bar{y},c)}{n}=\{или, если\ без\ C\} = \frac{\sum^{n}_{i=1}I[\bar{t_i}=\bar{y_i}]}{n};\\precision_{micro}:=PR_{micro}(\bar{t},\bar{y},C)=\frac{\sum^{C-1}_{c=0}tp(\bar{t},\bar{y},c)}{\sum^{C-1}_{c=0}tp(\bar{t},\bar{y},c) + \sum^{C-1}_{c=0}fp(\bar{t},\bar{y},c)};\\recall_{micro}:=RC_{micro}(\bar{t},\bar{y},C)=\frac{\sum^{C-1}_{c=0}tp(\bar{t},\bar{y},c)}{\sum^{C-1}_{c=0}tp(\bar{t},\bar{y},c) + \sum^{C-1}_{c=0}fn(\bar{t},\bar{y},c)};\\F1_{micro}:=F1_{micro}(\bar{t},\bar{y},C)=\frac{2*PR_{micro}(\bar{t},\bar{y},C)*RC_{micro}(\bar{t},\bar{y},C)}{PR_{micro}(\bar{t},\bar{y},C) + RC_{micro}(\bar{t},\bar{y},C)};\\precision_{macro}:=PR_{macro}(\bar{t},\bar{y},C)=\frac{\sum^{C-1}_{c=0}pr(\bar{t},\bar{y},c)}{C};\\recall_{macro}:=RC_{macro}(\bar{t},\bar{y},C)=\frac{\sum^{C-1}_{c=0}rc(\bar{t},\bar{y},c)}{C};\\F1_{macro}:=F1_{macro}(\bar{t},\bar{y},C)=\frac{\sum^{C-1}_{c=0}f1(\bar{t},\bar{y},c)}{C};\\precision_{weighted}:=PR_{weighted}(\bar{t},\bar{y},C)=\frac{\sum^{C-1}_{c=0}(pr(\bar{t},\bar{y},c) * (\frac{\sum^n_{i=1}I[\bar{t_i}=c]}{n}))}{C};\\recall_{weighted}:=RC_{weighted}(\bar{t},\bar{y},C)=\frac{\sum^{C-1}_{c=0}(rc(\bar{t},\bar{y},c) * (\frac{\sum^n_{i=1}I[\bar{t_i}=c]}{n}))}{C};\\F1_{weighted}:=F1_{weighted}(\bar{t},\bar{y},C)=\frac{\sum^{C-1}_{c=0}(f1(\bar{t},\bar{y},c) * (\frac{\sum^n_{i=1}I[\bar{t_i}=c]}{n}))}{C}.

Такс-с, а что же тут еще у нас осталось интересного? А на самом деле осталось. На этот раз не будем томить и просто выпишем последние утверждения и докажем их:

1.\ acc(\bar{t},\bar{y},C)=PR_{micro}(\bar{t},\bar{y},C)=RC_{micro}(\bar{t},\bar{y},C)=F1_{micro}(\bar{t},\bar{y},C);2.\ Если\ \forall c\in\{0,1,C-1\}\ верно\  \frac{\sum^n_{i=1}I[\bar{y_i}=c]}{n}=const,\ то\\ acc(\bar{t},\bar{y},C)=PR_{macro}(\bar{t},\bar{y},C)=RC_{macro}(\bar{t},\bar{y},C);3.\ pr(\bar{t},\bar{y},c)=rc(\bar{y},\bar{t},c),\ f1(\bar{t},\bar{y},c)=f1(\bar{y},\bar{t},c).

В целях незагромождения повествования доказательства можно найти ниже:

Действительно, precision и recall имеют своеобразную обратную зависимость по аргументам, а micro метрики представляют собой просто новый взгляд на число полученное подсчетом accuracy.

Итог

Таким образом, в этой статье нам удалось посмотреть на уже привычные метрики совершенно непривычным взглядом, более того, теперь, когда вы будете отрисовывать графики обучения своих нейронных сетей через matplotlib или tensorboard, вы будете совершенно по-иному смотреть на их динамику, вы будете знать заранее, что фактически, если у вас классы на валидации сбалансированы, то достаточно рисовать только accuracy, macro precision и macro f1, больше вы не будете представлять никакие круги и квадраты, никакие подбитые/неподбитые самолеты, какие-нибудь отсеивающие сетки и т.п., вы можете их вспоминать, чтобы вспомнить формулу, но у вас теперь будет понимание того, как численное значение precision'а и recall'а характеризует прогноз вашей модели с точки зрения вероятности.

Что же, это дебютная статья автора, он будет очень благодарен любой конструктивной критике и фидбеку в комментариях, так же дайте знать, если вам импонирует подобные "уплотнения множеств", автор в свою очередь будет рад написать еще серию подобных статей наподобие "интерпретации ROC-AUC'а", "почему не оптимизируют MSE при классификации", "теория за скользящим экспоненциальным средним" или "почему человеческий мозг тоже оптимизирует logloss".

До новых встреч :)

Комментарии (4)


  1. GBR-613
    20.11.2023 12:12

    Кто объяснит тупому недоучке, чем F1 score лучше, чем FM score? И чем плохо просто пользоваться средним арифметическим между precision и recall?


    1. DavidKharazian Автор
      20.11.2023 12:12

      Добрый день!

      Что вы имеете ввиду под FM-score? Простите, я не слышал о таком, поправьте меня, если я не прав, но наверное вы хотели спросить про более общий вариант F-beta score? Если так, то я дам ответ дальше.

      Что же насчет второй части вашего вопроса - известны 3 концептуально разных усреднений:
      - Среднее арифметическое: (x_1 + ... + x_n) / n
      - Среднее геометрическое: (x_1 * ... * x_n)**(1/n)
      - Среднее гармоническое: n / (1/x_1 + ... + 1/x_n)

      Я бы посоветовал вам погуглить какие-нибудь статейки на эту тему, даже википедию почитать. ИМХО - это просто принципиально разные способы получить число лежащее где-то между всеми x_1, ..., x_n. Но только у последних двух есть свойство, что если хотя бы один из x_i = 0, то и все среднее = 0.

      В случае с precision и recall нам это и нужно, как я написал в статье, это просто условные вероятности, но двух противоположных событий (p(предсказан класс C|верный класс = C) и наоборот p(верный класс = C|предсказан класс C)), усредняя таким образом мы получаем величину, которая характеризует именно мощность алгоритма в таком случае, если хотя бы одна из величин близка или равно нулю, то и среднее гармоническое и среднее геометрическое будет, а вот среднее арифметическое совсем нет, оно будет примерно равно половине второй вероятности (вообще среднее арифметическое это аппроксимация мат.ожидания, а аппроксимация мат.ожидания вероятностей такой природы, да и всего по двум числам - ну такое, вообще природа не очь понятна этого действия).

      Может возникнуть ризонный вопрос, почему тогда не использовать среднее геометрическое вместо среднего гармонического. Хмм, вообще интересный вопрос, я думаю можно поискать мб даже какие-то оригинальные статьи, мб на arxiv'е что-то будет. Я предположу, что дело просто в производной: при стремлении к граничным значениям, когда precision или recall близки к 0, геометрическое очень быстро к 0 стремится, в то время как гармоническое не так быстро. Можете в geogebra'е построить графики и убедиться, ну или явно рассмотреть градиент.

      Так вот, возвращаясь к F-beta: коэффициент beta - это просто величина, которой мы регулируем важность precision'а над recall'ом или наоборот. Пример: хотим построить нейронную сеть, которая предсказывает наличие онкологического заболевания. Тогда precision - кол-во верных диагнозов из всех поставленных, а recall - кол-во установленных диагнозов для людей с наличием заболевания на самом деле. Так вот не так страшно выписать терапию здоровому человеку, чем НЕ выписать ее больному, поэтому в валидации алгоритма для такой задачи, можно было бы в F-beta-score'е придать чуть больший вес recall'у.
      В любом случае, они задаются спецификой задачи, мне лично импонирует простота, ибо выбор этого beta обычно просто на глаз берется, я так не люблю.


  1. AntonKuvaldin
    20.11.2023 12:12

    Автор, это просто великолепно! Я даже решил зарегистрироваться на Хабре ради того, чтобы оставить этот комментарий.

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

    Замечания косметические, но если интересно:

    1. В статье часто упоминаются true positive rate, fpr и тд, но насколько я понимаю, имеются в виду на самом деле просто true positive, false positive и тд, без rate. Rate - это доля. К примеру TPR=TP/(TP+FN)=recall

    2. В конце первого столпа, в формуле суммирования по значениям таргета: сумма от k=0 до С-1, наверное имелось в виду сумма от с=0 до С-1

    3. "тут бы наверное еще постов 10 написать, чтобы апеллировать к чему-то, ну совсе-е-ем строгому" - хотелось бы увидеть ссылку на какой-нибудь параграф в какой-нибудь книге, я бы с удовольствием почитал

    Спасибо за материал! Очень жду новых статей. Лайк, подписка


    1. DavidKharazian Автор
      20.11.2023 12:12

      Большое спасибо, но вы мне льстите :)

      Отдельное спасибо за ваши замечания, все по делу.
      1. Да, вы не первый, кто замечает подобное. Когда я писал, мне захотелось какое-то существительное поставить после true positive и тп. Слово rate в английском показалось подходящим т.к. на слуху в машинном обучении и как бы на примере курса евро (euro rate) или акций вроде как и не передает смысл числа только от 0 до 1. Но наверное было не лучшим решением раз оно вводит не одного человека в заблуждение. Тем более коллизия с TRP действительно уместна. Возможно действительно стоит исправить.
      2. Да, вы правы, поправил, большое спасибо!:)
      3. Что касается книг:
      - Вообще мне импонирует строгое определение по Колмогорову, мне читали это в рамках лекций в университете, вот их сборник: https://teach-in.ru/file/synopsis/pdf/probabilistic-model-M.pdf, определение вероятности дается на 9-ой странице, см. "вероятностная мера". Вообще мне очень нравятся эти лекции, первая 1/2 - 2/3 книги очень хорошие, стараюсь не забывать, то что там написано. Дальше уже для совсем любителей.
      - Определение условной вероятности мне нравится вот такое (см. ниже). К сожалению, не смог тут найти книгу, имя лектора тоже не помню:( Читали мне на спецкурсе "Байесовские методы оптимизации" на ВМК МГУ весной 2022-го, но сборника лекций как выше видимо нет т.к. это не основной курс.

      Вообще очень советую поизучать теорию Байеса, я бы советовал что-то построже, без научпопа. Вводить вероятность как выше конечно правильно, но вот только почувствовать ее не получается. А вот после понимания теории Байеса появляется совсем новый взгляд на мир и то, что же в себе несет это число от 0 до 1.