Мы школа онлайн-образования, которая уже три года делает курсы по Data Science и разработке. Одна из наших целей — собрать коммьюнити классных специалистов и делиться крутыми и неочевидными знаниями. Так был рождён Симулятор ML — место, в котором начинающие и опытные специалисты решают задачи разной сложности, разрабатывают проекты в командах, осваивают новые инструменты, развивают продуктовое мышление и постоянно растут в профессии.

А, как это свойственно коммьюнити, горящему идеей, студенты и авторы хотят делиться своими инсайтами и открытиями, которые дадут свежий взгляд на устоявшиеся практики. Сегодня хотим поделиться статьей автора Симулятора ML Богдана Печёнкина о том, как лучше использовать анализ ошибок для разработки ML систем.

Certainly, coming up with new ideas is important.

But even more important, to understand the results.

— Ilya Sutskever, сооснователь OpenAI

Введение

Всем привет! Меня зовут Богдан Печёнкин. Я Senior ML Engineer в компании BrandsGoDigital и больше всего известен как автор Симулятора ML.

Мой первый пост на Хабре посвящался 10 первым ошибкам в карьере ML-инженера, что тесно связано с сегодняшней темой. Анализируя свои и чужие ошибки, Я пришёл к выводу, что один из самых недооценённых этапов в построении ML систем — это, как ни странно, анализ ошибок. Он даёт глубокое понимание не только наших моделей, но и данных и метрик, с которыми мы работаем. Сегодня Я хочу поделиться с вами тем, почему анализ ошибок так важен, каким образом его проводить и как он может помочь вам в дизайне и разработке более надёжных и эффективных ML продуктов.

Что такое анализ ошибок?

Каждая модель машинного обучения несовершенна и имеет свои границы применимости: на одних данных она работает лучше, на других хуже, а где-то — совсем плохо.

All models are wrong, but some are useful.

– George Box, британский статистик

Определяя, как ведёт себя текущая модель в каждом отдельном кейсе, «в какую сторону» ошибается, мы получаем неоценимые подсказки, какие новые признаки нам нужны, какие преобразования целевой переменной попробовать, каких данных нам не хватает и так далее. Таким образом, анализ ошибок — это важнейший этап построения модели перед проведением A/B экспериментов, её тестированием в боевых условиях.

Но почему нам мало обычной кросс-валидации?

Когда мы считаем метрику на отложенной выборке, мы, по сути, агрегируем ошибки со всех объектов в одно число. Если у нас кросс-валидация вместо отложенной выборки и несколько метрик вместо одной, мы всё ещё агрегируем разного рода ошибки со всех объектов в некую «среднюю температуру по больнице».

Например, считаем MAE, WAPE, wQL в регрессии, или LogLoss в классификации. 

Aгрегированная метрика не показывает, как ошибка распределяется по разным объектам, какое у неё распределение, а тем более — что нужно поменять в собранной ML системе, чтобы скорректировать ошибку (какие у метрики «драйверы роста»?). 

Метрики сообщают нам, что стало либо «хуже», либо «лучше», но подсказок, что делать дальше, из-за чего результат именно такой и что надо менять в ML системе, они не дадут.

Анализ ошибок — процесс прямо противоположный подсчёту метрики: агрегированную метрику мы разбиваем на компоненты — и анализируем их в совокупности. Это даёт нам полную картину: где и как система проявляет себя и какие встречаются паттерны в разных сегментах объектов отложенной выборки.

Анализ ошибок как back-propagation для ML пайплайна
Анализ ошибок как back-propagation для ML пайплайна

Мне нравится проводить параллель с алгоритмом back-propagation: мы пробрасываем градиент ошибки от самых последних слоёв нейросети к самым первым, соответствующим образом обновляя каждый компонент сети. Анализ ошибок — это ровно такое же «взятие градиента метрики», но на этот раз для всего ML пайлпайна.

План рассказа

  1. Введение в остатки и псевдоостатки

  • Определение понятий «остатков» и «псевдоостатков» в контексте регрессии и классификации.

  1. Визуальный и статистический анализ остатков

  • Методы визуализации распределения остатков.

  • Применение статистических тестов для оценки смещения, гетероскедастичности и нормальности остатков.

  • Что такое fairness и его роль при принятии решения о деплое модели.

  1. Анализ кейсов работы модели

  • Разбор наилучших, наихудших и крайних сценариев работы модели.

  • Моделирование ошибок с помощью Adversarial Validation

  1. Анализ ошибок в нестандартных задачах машинного обучения

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

Остатки и псевдоостатки

Остатки (residuals)

Что формально мы имеем в виду, говоря «ошибки»? Введём понятие «остатков».

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

residuals = y_true – y_pred

Остаток — это буквально «то, что осталось недопредсказанным», часть значения таргета, которую модель не смогла объяснить с учётом имеющихся признаков.

Остатки — «то, что осталось недопредсказанным»
Остатки «то, что осталось недопредсказанным»

Псевдоостатки в классификации

Что может служить остатками в бинарной классификации? Да, мы можем также смотреть на разницу между предсказанной вероятностью (скажем, 0.42) и метками класса 0 и 1. Мы уже упорядочим объекты по размеру их ошибки, но будет ли это самым информативным способом их анализа? Более естественно оперировать слагаемыми LogLoss, поскольку так мы учитываем ещё и вклад каждой ошибки в общую метрику, её вес.

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

y log(p) + (1−y) log(1−p)

То слагаемые (y log(p) + (1−y) log(1−p)) представляют собой псевдоостатки. Так мы не просто считаем недопредсказанную часть целевой переменной, но ещё и «взвешиваем» объекты пропорционально их влиянию на метрику.

Псевдоостатки в общем случае

Если задуматься, большинство метрик, которые мы используем в машинном обучении (и абсолютно все лоссы) — представляют собой усреднение ошибок по каждому объекту, посчитанных тем или иным образом (вспомните, какие есть исключения из правила?).

  • Mean Squared Error (MSE):
    ∑ (y_true - y_pred)2 → sign(y_true – y_pred) * (y_true – y_pred)2

  • Mean Absolute Error (MAE):
    ∑ |y_true - y_pred| → y_true – y_pred

  • Mean Absolute Percentage Error (MAPE):
    ∑ |y_true - y_pred| / y_true → 1 – y_pred / y_true

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

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

Визуализация остатков

Распределение остатков

Допустим, мы рассчитали остатки. Основываясь на них, какие выводы мы можем сделать? (Примечание: здесь и далее будем использовать термины «остатки», «псевдоостатки» и «ошибки» как взаимозаменяемые). 

Для начала мы анализируем их в совокупности — смотрим на их распределение. Распределение остатков позволяет нам «проверить на прочность» наши базовые предположения (assumptions) относительно данных, модели и других компонентов системы.

К примеру, вот наш коллега обучил модель прогноза спроса, визуализировал распределение остатков.

import seaborn as sns
import matplotlib.pyplot as plt


plt.figure()
sns.histplot(residuals, kde=True)
plt.title('Distribution of Residuals')
plt.xlabel('Residuals')
plt.ylabel('Frequency')
plt.show()

И увидел один из графиков ниже:

Три примера наблюдаемого распределения остатков во время анализа модели прогноза
Три примера наблюдаемого распределения остатков во время анализа модели прогноза

Какие выводы сделал бы наш коллега, посмотрев на эти три картинки?

  • Остатки распределены практически нормально (как мы и хотели):
    ✓ assumptions are met!

  • Распределение нормальное, но с большим хвостом влево (недопредсказания):
    ✗ assumptions are not met!

  • Распределение не нормальное и имеет две моды:
    ✗ assumptions are not met!

Какие шаги по улучшению модели он бы предпринял дальше?

  1. В первом случае, наш коллега, вероятно, оставил бы модель без изменений, однако для полной уверенности перешёл бы к статистическим тестам и проверке скедастичности.

  2. Здесь наш коллега возможно бы использовал логарифмирование таргета перед квантильной регрессией, чтобы минимизировать влияние больших значений.

  3. В этом случае, возможно, стоит перейти к более сложным методам, таким как бустинг, чтобы уловить пропущенные моделью паттерны.

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

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

Статистические гипотезы

Свойства распределения можно формулировать в виде статистических гипотез. Так, чтобы оценить наличие или отсутствие смещения (bias), мы сравниваем среднее у распределения остатков с нулём, используя t-тест для одной выборки. Тест учтёт их разброс и отвергнет гипотезу о несмещённости остатков, только если наблюдаемое смещение выходит за рамки погрешности.

Подобным образом, мы можем оценить нормальность распределения, используя критерий Колмогорова-Смирнова. Очевидно, здесь глаз человека даже менее надёжен, чем стат. тест, сравнивающий «отклонение» от нормального распределения численно.

На выходе статистического критерия мы получаем p-value вероятность встретить наблюдаемое значение статистики или более экстремальное при условии, что нулевая гипотеза верна.

  • В случае смещения нулевая гипотеза: остатки не имеют смещения.

  • В случае нормальности нулевая гипотеза: остатки распределены нормально.

Для принятия решения мы руководствуемся уровнем значимости α (например, 5%) или, иначе, уровнем ошибки I рода. Уровень значимости сообщает, начиная с какой степени «невероятности» нулевой гипотезы мы её отвергнем.

Гетероскедастичность

Ещё два свойства распределения, которые мы можем оценивать, — гомоскедастичность и гетероскедастичность. Гомоскедастичность (homo + scedasticity) — буквально «одинаковый разброс». Соответственно, гетероскедастичность (hetero + scedasticity) — «разный разброс».

Кейс 1: гомоскедастичное распределение остатков вдоль значений целевой переменной; кейсы 2-3: гетероскедастичное (с разным паттерном)
Кейс 1: гомоскедастичное распределение остатков вдоль значений целевой переменной;
кейсы 2-3: гетероскедастичное (с разным паттерном)

О чём речь в случае остатков? Мы хотим знать, насколько сильно дисперсия остатков варьируется для разных значений целевой переменной. Наблюдаем ли мы, что на малых значениях остатки маленькие, а с ростом таргета они растут (или наоборот)? Наблюдаем ли мы, что на малых и больших значениях таргета (на краях) остатки имеют больший разброс, чем в середине (в основной массе распределения таргетов)? Или остатки везде однородные?

Обратите внимание, что скедастичность остатков (и псевдоостатков) может кардинально отличаться при переходе от одной метрики к другой (например, от разностей таргетов и предиктов — к квадратам разностей), поскольку каждая метрика по-своему взвешивает разные ошибки в зависимости от их знака и величины.

Для гомоскедастичности существует несколько статистических тестов: 

  • Bartlett's test

  • Levene's test

  • Fligner-Killeen's test

Все они доступны в пакете scipy.stats. Это семейство тестов называют ANOVA-тестами (ANalysis Of VAriance). Каждый них принимает на вход набор подвыборок и оценивает, насколько валидно предположение, что каждая из подвыборок имеет одну и ту же дисперсию. 

Для нас подвыборками будут служить бины из остатков, разбитых по мере увеличения таргета. Например, бьём таргет на 5 бинов по пороговым квантилям: 0.2, 0.4, 0.6, 0.8.

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

Diagnostic Plots

Diagnostic Plots представляют собой ещё один метод для анализа распределения остатков в дополнение к статистическим тестам. Это набор специфических визуализаций остатков и предсказаний целевой переменной в разных разрезах.

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

1. Residuals vs. Fitted

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

Residual vs. Fitted Plots (хороший и плохой случаи)
Residual vs. Fitted Plots (хороший и плохой случаи)

2. Normal Q-Q Plot

Q-Q Plot — это способ визуализации отклонения от заданного распределения. Для его отрисовки мы визуализируем, какие теоретические квантили были бы у нашей выборки (остатков), будь она взята из предполагаемого распределения, и какие квантили на самом деле, поэтому график называется Q-Q (Quantile-Quantile) Plot.

Чем больше реальные значения отклоняются от прямой линии, тем менее вероятно, что выборка взята из этого распределения. Частным случаем служит Normal Q-Q Plot, где мы сравниваем выборку с нормальным распределением (ещё один способ оценить, распределены ли остатки нормально — и, если нет, в каких конкретно значениях).

Normal Q-Q Plots (хороший и плохой случаи)
Normal Q-Q Plots (хороший и плохой случаи)

3. Scale-Location Plot

Scale-Location Plot помогает в оценке скедастичности распределения (гетероскедастичности либо гомоскедастичности, с которыми мы уже успели познакомиться). Для его отрисовки мы берём предсказания против корня модуля стандартизированных остатков. 

Если распределение одинаково для всех предсказаний (иметь одного масштаба отклонение), то остатки считаются гомоскедастичными относительно предсказанного значения. Если мы видим растущий или убывающий тренд, другую неоднородность — значит, присутствует гетероскедастичность.

Scale-Location Plots (хороший и плохой случаи)
Scale-Location Plots (хороший и плохой случаи)

4. Cook's Distance Plot

Cook's Distance является мерой влияния каждого отдельного наблюдения на модель в целом. Она помогает выявить наиболее влиятельные объекты в данных, что может быть полезно при проверке модели на наличие аномалий или выбросов, которые могут сильно искажать её предсказания.

Для построения Cook's Distance Plot визуализируются предсказанные значения против расстояния Кука. В каждой точке графика расстояние Кука представляет собой сумму отклонений предсказаний, полученных при удалении данного наблюдения, к предсказаниям, полученным на всем наборе данных.

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

Cook's Distance Plots (хороший и плохой случаи)
Cook's Distance Plots (хороший и плохой случаи)

Diagnostic Plots

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

4 Diagnostic Plots
4 Diagnostic Plots

Существуют готовые пакеты отрисовки всех четырёх графиков. Например, в языке программирования R они входят в стандартную библиотеку и доступны вызовом функции plot на уже обученной линейной модели.

Fairness

Когда мы улучшаем модель, мы не хотим, чтобы метрика росла на одних сегментах пользователей и падала на других (даже если в среднем она оказывается выше). Бенефиты от прироста метрики легко могут быть перечёркнуты негативным User Experience «пострадавшей» группы пользователей — и за счёт совсем других метрик.

Чтобы этого избежать, мы должны смотреть не только на то, выросла ли метрика или упала, но и на то, как она размазана по всем объектам (например, по всем пользователям или по всем товарам). Для этого вводят концепт Fairness (в переводе с английского, «справедливость»).

Идеализированный пример:

Два ML инженера разрабатывали улучшение бейзлайн-модели. Оба из них получили сокращение MAE (Mean Absolute Error) на 20%. Как их рассудить? Чью модель выкатывать на A/B тест? Первая модель дала небольшой равномерный прирост для всех объектов. Вторая модель сильно сократила ошибку на половине объектов и немного увеличила на другой половиние.

Одного и того же аплифта можно добиться разными путями
Одного и того же аплифта можно добиться разными путями

Как мы видим из примера, одного и того же улучшения метрики можно добиться разными способами. Мы предпочтём скорее, чтобы метрика везде выросла понемногу, нежели чтобы где-то она сильно выроста, а где-то просела. Поэтому даже если суммарная метрика выросла, этого ещё не достаточно, чтобы принять решение, что новая модель лучше и её нужно катить в прод!

Аналогично можно представить, что неравномерный прирост (unfair uplift) был получен по ключевой онлайн-метрике и во время A/B теста (эксперимента на реальных пользователях), что также может послужить сигналом, что данную модель не стоит раскатывать на остальном трафике.

Gini Index

В экономике для количественной оценки «справедливости» распределения часто используют Gini-индекс, особенно при анализе распределения доходов населения определённой страны.

Gini-индекс варьируется от 0 до 1, где 0 обозначает идеальное равенство (т. е. все значения равны), а 1 обозначает максимальное неравенство (одно значение максимально, все остальные минимальны). Чем выше индекс Gini, тем более несправедливым считается распределение.

Индекс Gini для распределения доходов
Индекс Gini для распределения доходов

То же касается и распределения ошибок. Встретить случай, когда малое число объектов вносит львиную долю вклада в ошибку, для нас нежелательно. Почти во всех случаях для нас предпочтительнее «размазать» ошибку по разным объектам (или, скажем, для некой группы особых объектов построить отдельную модель), чем встретить явный перекос.

Достичь полностью равномерного распределения ошибок невозможно, и к этому нет смысла стремиться как к самоцели, так же как и к равномерному распределению доходов. Однако, кроме точности предсказания, оценивать, что Gini Index не снижаеся более чем на X%, — это полезно. Здесь нам главное избегать вырожденных случаев.

Кроме того, мы можем добавить и более простые эвристики, которые в лоб считают, на какой доле объектов мы увеличили качество, на какой просадили (по разнице знаков остатков).

Best Case / Worse Case / Corner Case

Изучив остатки в их совокупности и проанализировав их верхнеуровневые свойства, мы спускаемся на один уровень ниже. А именно начинаем искать в них паттерны. Так мы понимаем, «в какую сторону» нужно корректировать модель или остальные компоненты пайплайна обучения, когда что-то сломалось.

Best Case & Worst Case

Зная остатки, можно проанализировать поведение модели в лучших и худших сценариях. Для этого мы выводим топ-20, топ-50, топ-100 объектов по величине остатков и ищем в них общие паттерны.

  • Например, если мы прогнозируем число заказов в приложении доставки и видим, что наша модель систематически недооценивает спрос на веганскую и вегетарианскую еду, а также на блюда, которые попадали под промоакции. Мы пришли к выводу, что в качестве признаков нужно добавить «тип кухни» и, кроме того, подключить источник данных, содержащий «промо календарь».

  • Другой случай: мы попробовали построить модель прогноза на Трансформерах, распределение её остатков принципиально отличается от текущей модели в проде. Метрика лучше. Мы хотим с нуля проанализировать, на каких блюдах и на каких пользователях прогноз спроса точнее всего. Где пролегает текущая «граница применимости» текущей модели, чтобы раскатить её в первую очередь на той части данных, где она чувствует себя лучше всего. Для этого мы выводим топ-1000, топ-5000, топ-10,000 объектов с наименьшей ошибкой.

Одним из наилучших методов является автоматическое сохранение объектов с наибольшими ошибками (debug samples) в качестве артефактов при каждом запуске обучения. Благодаря этому мы сможем быстро и легко заметить общие паттерны (сходу получаем багаж идей для улучшения пайплайна) и в будущем проследить, как менялся характер ошибки по мере выкатки новых улучшений и добавления новых признаков.

Как мы с помощью ClearML автоматически сохраняем top-30 ошибок в качестве артефактов при каждом запуске обучающего пайплайна
Как мы с помощью ClearML автоматически сохраняем top-30 ошибок в качестве артефактов при каждом запуске обучающего пайплайна

Corner Case Analysis

В то время как анализ лучших и худших случаев направлен на выявление общих паттернов на основе остатков, corner case analysis фокусируется на том, какие остатки характерны для объектов с конкретными особенностями.

Слева: worst-case analysis; справа: corner-case analysis
Слева: worst-case analysis; справа: corner-case analysis
  • Так, если у остатков разный разброс на разных по масштабу таргетах (например, мы предсказываем выручку и наибольший вклад делают ошибки в предсказании наименьших значений выручки, близких к нулю), тогда нам стоит вывести группу объектов с наименьшими таргетами, посмотреть на их остатки.

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

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

Кривая эластичности из учебников
Кривая эластичности из учебников

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

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

Например, -10%, -9%, -8%, …, +9%, +10% от последней наценки.

Чтобы понять, делает ли обученная модель осмысленные предсказания, мы смотрим на графики кривой эластичности по каждому товару. Если не вдаваться в детали, эластичность – это и есть зависимость спроса от цены, которую мы получаем подставляя цены и делая прогноз для новой точки. 

Верхнеуровневая схема инференса модели
Верхнеуровневая схема инференса модели

Ожидаемое поведение: чем выше цена, тем ниже спрос, и наоборот. Эластичные товары имеют “более крутую” кривую: малейшее увеличение цены ведёт к сильному спаду спроса, и наоборот. Неэластичные имеют более “плоскую” зависимость: мы можем наглеть в цене, а спрос – не сильно упадёт (значит, заработаем больше денег).

GMV (Gross Merchandise Value) – аналог товарооборота (выручки) для e-commerce. Для нашего сервиса он играет роль «спроса».
GMV (Gross Merchandise Value) – аналог товарооборота (выручки) для e-commerce. Для нашего сервиса он играет роль «спроса».

Однако, начав анализ первых графиков эластичности, мы обнаружили вот какую картину:

Вместо монотонной гладкой кривой, мы увидели «лесенку»
Вместо монотонной гладкой кривой, мы увидели «лесенку»

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

Дело в том, что в качестве модели прогноза у нас был CatBoost и обучался он на большом числе товаров. Как мы знаем, градиентный бустинг (начиная с LightGBM) делает квантизацию всех признаков перед обучением (разбивая на бины +- одинаковых размеров), таким образом, с десятков уникальных значений по каждому признаку мы переходим, например, к 256 или 512 значениям. Это обеспечивает ускорение обучения за счёт потери части сигнала в признаках.

Распределение числа объектов в каждом бакете после квантизации
Распределение числа объектов в каждом бакете после квантизации

Таким образом, даже несмотря на то, что цена и признаки на основе цены выходили в топ по важности, тем не менее, модель была физически «нечувствительна» к малым вариациям цены, на которых мы затем её хотели применять.

Решение: повысить гранулярность квантизации (скажем, до 4096 или 8192). В результате мы получили графики с уже осмысленным «гладким» возрастанием спроса по мере уменьшением цены.

Моделируем ошибку

Но вернёмся к worst-case анализу.

Допустим, мы выделили группу объектов, на которых модель показала наихудшие результаты. Как нам это знание использовать для определения «градиента» ML системы, поиска наискорейшего шага её улучшения? Смотреть на ошибки, конечно, можно и вручную, особенно когда признаков мало, а объектов выделено немного. Но что если того и того становится слишком много?

Наверняка, есть пути автоматизировать и этот процесс, ведь мы инженеры...

И такой приём действительно есть: Что, если использовать одну модель машинного обучения для предсказания ошибок другой модели машинного обучения?

Adversarial Validation

Adversarial Validation — приём, который мы сегодня применим для выделения паттернов в ошибках. Он происходит от соревнований по машинному обучению на Kaggle. В соревнованиях участники стремятся улучшить качество своих моделей, используя наиболее умные и сложные методы. Часто они сталкиваются с проблемой, когда их модели хорошо работают на обучающем наборе данных, но плохо на отложенной выборке (тестовом наборе данных, целевые переменные, для которых надо предсказать). 

Почему так происходит?

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

  2. Вторая возможная причина: и от этого куда труднее спастись — тестовый набор данных может существенно отличаться от обучающего набора данных. Именно это называется «расхождением распределений».


Идея применения Adversarial Validation для анализа ошибок
Идея применения Adversarial Validation для анализа ошибок

Чтобы оценить, насколько два распределения похожи или не похожи (и в каких признаках именно), мы можем обучить отдельную модель-классификатор. Все объекты обучающей выборки примут класс 0, а все объекты тестовой — класс 1.

Если разница между выборками несущественна (например, ROC-AUC ≈ 0.5), это означает, что распределения обучающего и тестового набора данных схожи.

Если между выборками большая разница (например, ROC-AUC > 0.6), тогда выборки уже различимы, мы можем из обучающей выборки выделить самые похожие на тест объекты и использовать их как отложенную валидационную выборку.

Именно это и называется Adversarial Validation.

Граница применимости модели

Если задуматься, этот подход можно применить к любым двум выборкам, чтобы выявить между ними отличия. Более того, поняв, что две группы объектов различимы, мы можем заглянуть в Feature Importance модели (а выбор подходящей модели для анализа ошибок — отдельный разговор) и узнать, в каких именно признаках различие между выборками себя выдаёт.

Как Adversarial Validation «завести» для анализа ошибок? Какие две выборки у нас есть?

  1. Отбираем топ ошибок модели (например, топ-1000 или топ-10%). Это наши worst-cases.

  2. Присваиваем им класс 1, а всем остальным («здоровым») объектам — класс 0.
    Наши выборки: «хорошо прогнозируемые» и «плохо прогнозируемые».

  3. Строим вспомогательную модель-классификатор, которая пытается предсказать, является ли объект «плохо прогнозируемым». Эта модель будет использовать признаки объектов (возможно даже куда больший набор, чем тот, на основе которого мы обучаем основную модель), чтобы понять, чем так отличаются «плохие объекты».

  4. Если модель классифицирует «хорошо прогнозируемые» и «плохо прогнозируемые» объекты с достаточной точностью (ROC-AUC > 0.6), то это говорит о том, что ошибка модели зависит от значений некоторых признаков.

  5. Анализируем важность признаков в этой модели (например, по SHAP-values), чтобы определить, какие признаки сильнее всего влияют на ошибки основной модели. 

Это подскажет, паттерны в каких признаках сейчас основная модель не понимает чаще всего. Это направляет вектор нашего поиска новых признаков (и их трансформаций), обогащения датасета и, возможно, модификацией loss-функции или процесса предобработки целевых переменных.

Анализ ошибок за пределами регрессии и классификации

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

1. Сегментация изображений (Image Segmentation). В области компьютерного зрения задача сегментации изображений заключается в выделении определенных областей или объектов на изображении, соответствующих определённым классам. «Остатками» здесь является разница предсказанной маски сегментации (контура объекта) и истинной. С помощью наложения масок или использование цветовых карт, мы можем быстро определить области изображения, где модель допускает ошибки (например, плохо отделяет мелкие детали, волосы или ошибочно выделяет зеркальное отражение). 

В сегментации картинок остатками может служить разница между реальными масками объектов и предсказанными: False Negatives (FN), ошибочно не выделенные регионы изображения, — и False Positives (FP), ошибочно выделенные.
В сегментации картинок остатками может служить разница между реальными масками объектов и предсказанными: False Negatives (FN), ошибочно не выделенные регионы изображения, — и False Positives (FP), ошибочно выделенные.

С другой стороны, мы можем оперировать не пикселями, а самими картинками: просматривать топ-N изображений с самой большой ошибкой после обучения и анализировать, есть ли в них какой-либо паттерн. Так, например, модель может некорректно работать на картинках с тёмным освещением, с зеркалами, с большим количеством объектов или на специфическом фоне. Обнаруженные закономерности подсказывают, каких данных (на какие паттерны) нужно добавить в выборку больше, либо как нужно модифицировать loss-функцию (чтобы модель была внимательнее на границах масок сегментации).

2. Генерация звука (Voice Cloning). В задачах генерации аудио, таких как генерация голоса или Text-to-Speech (TTS), важным элементом анализа ошибок является использование Attention Plots. Они показывают, на какие части исходного текста модель обращала особое внимание при генерации каждого отдельного звука. Это позволяет выявить неправильные соответствия и улучшить качество генерации. 

Кроме того, существует подход Guided Attention, который дополнительно штрафует модель за отклонение от линейного отображения позиции символа в позицию звука. Как мы помним, анализ ошибок служит в том числе и для проверки на прочность наших предположений о модели (model assumptions).

Как с увеличением числа итераций Attention Plot приближается к диагональному: во втором случае, с применением Guided Attention Loss, сходимость к «осмысленному» распределению внимания происходит уже на ранних фазах обучения — также в копилку идей для артефактов, которые полезно собирать при каждом запуске обучающего пайплайна.
Как с увеличением числа итераций Attention Plot приближается к диагональному: во втором случае, с применением Guided Attention Loss, сходимость к «осмысленному» распределению внимания происходит уже на ранних фазах обучения — также в копилку идей для артефактов, которые полезно собирать при каждом запуске обучающего пайплайна.

3. Рекомендательные и поисковые движки. Ещё пример — рекомендательные системы. Вместо предсказанной одной цифры, как в классификации и регрессии, мы имеем рейтинг объектов, которые мы порекомендовали бы пользователю. Существует несколько метрик, сравнивающих гипотетическую выдачу и то, что пользователь реально кликал/покупал/смотрел.

Одна из таких метрик — NDCG. Несмотря на отличный от регрессии и классификации формат «предсказаний», эта метрика усредняет качество рекомендации по всем объектам. Значит, ничего не мешает посмотреть на best/worst/corner кейсы по аналогии с регрессией и классификацией: узнать, какие запросы наша система «понимает» хуже всего; как ведёт себя на пользователях с длинной и короткой историей запросов (или просмотров); нет ли очевидных проблем, например, зацикливания на том, что пользователь уже покупал или смотрел?

Вывод

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

Когда мы создали baseline с минимальным датасетом, анализ ошибок позволяет нам определить её сильные и слабые стороны, а также выявить моменты, которые требуют оптимизации (что далеко не всегда требует сразу заводить бустинги или BERTы). Этот анализ даёт нам понимание о том, какие улучшения модели следует внести в следующем цикле. Так, на каждой итерации, мы заменяем модель на более сложную, добавляем новые факторы в датасет, анализируем ошибки и сравниваем их с ошибками предыдущей версии. 

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

Анализ ошибок это лишь часть задач инженера по машинному обучению. Кроме анализа ошибок в повседневной работе мы разрабатываем метрики, собираем датасеты, обучаем сами модели, деплоим и тестируем ML-сервисы, проводим A/B-тесты и много чего ещё, порой выходящего за рамки теоретического понимания, как работают модели машинного обучения. 

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


  1. odmin227
    12.09.2023 20:37

    Красивая картиночка