Если с тобой за карьеру не случалось никаких факапов - либо ты начал свой путь примерно три дня назад, либо на работе ты только тапаешь хомяка или рубишься в Харстоун. Фейлы, провалы, косяки - всё это офигенные способы чему-то научиться и стать лучше, но это работает только, если после факапов проводить их "вскрытие" - анализировать, какие причины привели к неудаче, и что нужно изменить, чтобы уменьшить вероятность возникновения похожей ситуации в будущем.

Если вы хотите узнать ещё больше об организации процессов ML-разработки, подписывайтесь на наш Телеграм-канал Варим ML

Причины факапов можно поделить на такие группы:

  • Личные факторы - усталость, отсутствие мотивации, постоянное переключение контекста, несоблюдение правил

  • Техдолг и инженерная культура - отсутствие тестов, запутанный код и конфиги, неудобная постановка экспериментов, отсутствие версионирования, отсутствие средств мониторинга и алертов, плохая документация, плохие или устаревшие тестовые датасеты, отсутствие возможности быстрого отката релиза

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

  • Случайность - иногда реально все факторы просто складываются против тебя, shit happens

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

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

Это всё теоретические размышления, а что по примерам? Я как раз делал доклад про три факапа, которые случились в Цельсе на разных этапах жизни компании, но записи нет, так что расскажу про них текстом. А ещё недавно был вот такой пост со смешным багом.

Факап 1 - Кошмар с конфигами

  • Время действия - август 2020

  • Человек в ML-отделе - 8

2020 год был знаковым для всей индустрии искусственного интеллекта в рентгенологии, по крайней мере в России. Разбушевался COVID-19, врачи работали на износ, это сильно подогрело интерес к средствам частичной автоматизации и облегчения труда медицинских работников. На этой волне в Москве появился Эксперимент по использованию компьютерного зрения в радиологии. Мы вошли с него в июне с системой по анализу маммографических снимков, а в августе решили зарелизить новую версию с улучшенными метриками. В Эксперименте новая версия модели должна пройти калибровочное тестирование - для проверки метрик на внешнем датасете. Мы его успешно прошли, и новая модель начала работать на проде.

За пару дней мы поняли, что немного ошиблись с настройкой бинарного порога классификации на патологию и норму. На визуализацию для врача и ROC-AUC на потоке это никак не влияло, но немного подкрутить всё равно хотелось. Исторически у нас было два тестовых пайплайна - быстрые тесты на корректность работы системы и долгие тесты, включающие в себя небольшой метрик-тест. Ради такого незначимого изменения гонять долгий пайплайн (больше часа) мне не захотелось, и я оверрайднул пулл-реквест.

Как-то так выглядел этот PR

Через несколько дней я решил посмотреть, что творится на потоке, и у меня слегка похолодело внутри. Вот что я увидел:

А должно быть примерно так:

Почти на всех исследованиях находились какие-то мелкие непонятные объекты. Быстрое расследование показало, что изменён был не порог срабатывания, а порог бинаризации изображения, который используется при поиске маски груди во время препроцессинга. В итоге маски груди находились абсолютно неправильные, маленькие, обрубленные, и в нейронку попадали рандомные рейсайзнутые куски изображения.

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

Какие же выводы я для себя тогда сделал?

Технические:

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

  • Добавляем тест на неизменность результата - если PR не предполагает изменений ответа нейронки, то следует это явно проверить.

  • Проверяем адекватность нейминга в конфигах и вообще корректность его разбиения на подконфиги. bin_threshold - явно плохое название для такой переменной в ML-системе, поскольку может значить много разных вещей.

Процессные и коммуникационные:

  • Не скрываем инциденты, сразу после обнаружения начинаем коммуницировать с клиентами. Тут мы так и поступили, но хорошее поведение тоже нужно подмечать и закреплять.

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

Личные:

  • Правила равны для всех. Конечно, у кого-то должны быть права на оверрайд, но в 99.9% случаев введённые правила должны соблюдаться всеми - от джуна до CTO. Не зря же они внедрялись?

  • Не стоит принимать важные решение в уставшем состоянии. Вся эта возня с Экспериментом изрядно меня потрепала, и мне точно нужно было хорошенько отдохнуть. Это хорошо ещё, что в данном случае последствия были не особо жёсткие.

Факап 2 - Катастрофа с округлением

  • Время действия - декабрь 2020

  • Человек в ML-отделе - 12

К концу года наши системы по ММГ и ФЛГ уже работали в продакшне по полгода, и мы решили выводить в Эксперимент новый сервис - детекция COVID-19 на компьютерной томографии лёгких. Задача с точки зрения ML не очень сложная, на внутренних тестах мы получили ROC-AUC выше 0.9.

Схема работы нашего сервиса по сравнению с первыми прототипами немного усложнилась, появилась прослойка между клиентом и нейронкой в виде бэкенда, который отвечает за получение и валидацию исследований, отправку запросов на ML, получение результатов в виде JSON, а также генерацию ответов для клиента - обычно в виде SR и SC-серий.

Очередное калибровочное тестирование, уже знакомая процедура - 100 исследований, 50 с патологией, 50 без патологии. Несколько дней ждём результаты, а на выходе получаем ROC-AUC 0.53. Настолько негенерализуемая модель получилась? Данные слишком отличаются?

Конечно же, нет. При таком расхождении между внутренними и внешними тестами ответ почти всегда один и тот же - баг. Оказалось, что ML отдаёт вероятность в формате float от 0 до 1, а на бэкенде она автоматически округлялась до ближайшего целого и отдавалась в формате 1-100. Вероятности были не очень откалиброванные и почти все округлялись просто до единицы. Отсюда и "рандомный" AUC.

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

Технические:

  • Необходимо внедрить автоматическое end-to-end тестирование. Тесты на ML-часть сервиса недостаточны для покрытия таких случаев, нужно проверять то, что в итоге видит и получает клиент.

Процессные и коммуникационные:

  • Требуется перестроить коммуникацию между командами ML и бэка, очевидно, здесь случился рассинхрон по контракту взаимодействия. Вероятно, требуется какая-то роль аналитика для "перевода" между двумя командами и создания постановок задач для бэкенда при изменениях на ML.

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

Личные:

  • С ростом компании растёт и количество точек, где что-то может пойти не так, особенно это касается зон взаимодействия между командами. Поэтому важно не зацикливаться на своей области интереса (в моём случае - ML), и вовремя переключаться на новые проблемы.

Факап 3 - Who will watch the watchmen?

  • Время действия - сентябрь 2022

  • Человек в ML-отделе - 20

Прошло ещё два года, и сервис КТ ОГК разросся аж до 8 патологий и стал так называемым "комплексным сервисом". К тому моменту у нас уже был накоплен солидный опыт разработки, тестирования и продакшн-эксплуатации ML-систем в рентгенологии.

Месяцы поиска данных, разметки, обучения моделей, заворачивания их в единый сервис - и мы готовы тестироваться. Открываю протокол результатов - и по 6 из 8 патологий результаты по ROC-AUC в районе 0.5. Короче, легче монетку подбросить.

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

Спустя несколько месяцев мы решили ещё раз попытать счастья с улучшенными моделями, но тут - бомба. Ребята внезапно смогли почти точно воспроизвести метрики с тестирования. Дело было вот в чём. Система отдаёт 9 вероятностей - 8 вероятностей по каждой патологии и общую вероятность наличия хотя бы одной патологии, которая рассчитывалась просто как максимум по всем остальным вероятностям. Оказалось, что метрики воспроизводятся, если для каждой патологии в качестве вероятности брать именно эту общую максимальную вероятность. Упс. Пара популярных патологий чаще всего влияли на этот максимум, по ним и были более-менее нормальные метрики.

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

Технические и процессные:

  • Проблема может находиться и вне пределов компании. Такие кейсы намного сложнее обнаружить и доказать, но возможность эту отбрасывать не стоит.

  • Доверяйте внутренней валидации! Уроки Кеггла актуальны и для реального мира и продакшн-систем. Если между внутренними и внешними метриками слишком радикальное расхождение - либо что-то не так со своей валидацией и это надо срочно фиксить, либо что-то не так с внешними тестами.

Личные:

  • Нужно доверять свои командам и их компетентности. Да, ошибиться может каждый, но если ты не доверяешь людям, которых нанял - а на своём ли ты вообще месте?

Если вы хотите узнать ещё больше об организации процессов ML-разработки, подписывайтесь на наш Телеграм-канал Варим ML

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