Привет! Меня зовут Юра, я из Лаборатории Speech&NLP Инфраструктуры ИИ Контура. Одна из наших крупных задач – это модель для распознавания речи в текст, которая используется для транскрибации звонков и записей рабочих встреч. Мы постоянно работаем над улучшением качества моделей – предлагаем гипотезы и проводим эксперименты. Но для того, чтобы пользователи увидели результаты наших исследований, их надо доставить в продакшен. А это не так-то просто!
Сложность в том, что гипотез много – несколько человек в лаборатории постоянно работают над поиском новых вариантов улучшения модели. Гипотеза обычно касается отдельного этапа пайплайна обучения (получение базовой модели, файнтюн, этапы самообучения) и эффективность гипотезы доказывается проверкой на этом этапе.
Делать релиз целой модели для каждой гипотезы нереально – полное обучение всех этапов занимает 2-4 недели и требует участия других ролей для тестирования. Поэтому в релиз попадает сразу несколько гипотез. Но тут еще один подводный камень: они могут начать непредсказуемо влиять друг на друга.
Поэтому, чтобы управлять этой сложностью с релизом гипотез, сэкономить на комбинаторном переборе вариантов и регулярно доставлять улучшения модели до пользователей мы составили для себя свод гигиенических правил. И хотим ими поделиться.
История из жизни:
Однажды в процессе подготовки модели релиза мы не смогли улучшить метрики текущей модели и начали искать проблему. Причина крылась в том, что в целях ускорения проверки отдельные гипотезы проверялись не на релизной версии процесса обучения, а на упрощенной – меньше данных и более короткое обучение. И когда мы скомбинировали 4-5 изменений разом, модель обучилась до худших метрик качества.
Нам удалось распутать клубок и выкатить релиз. Но поиски оказались непростыми, и мы не могли выкатить релиз полгода. После этого решили зафиксировать методологию, которая поможет снижать риски при комбинировании нескольких гипотез.
Ограничиваем срок
Мы решили, что хотим выпускать релиз примерно раз в квартал. Время выступает ограничивающим фактором, который не позволит накопить десяток экспериментов полугодовой давности на сетапах, отставших от основной ветки. Дополнительный плюс – регулярность релизов помогает тренировать навыки, чтобы они не забывались и не утрачивались.
Чаще выкатывать новую версию не получится, потому что полный цикл обучения занимает до месяца, а для согласования релиза нужно участие других ролей: мы просим основных внутренних пользователей сравнить качество новой и старой версии и заапрувить изменения.
Сейчас время в квартале мы делим на две части: обучение релизной модели (до двух месяцев) и релиз модели в продакшен. На каждом из этапов могут возникнуть неожиданные трудности, поэтому мы закладываем бюджет времени на каждую из двух частей. Такое деление помогает более точно спланировать процесс и делает проще отслеживание динамики.
Но мы решили поменять подход и сделаем два процесса вместо одного – отвяжем обучение модели от релиза. В одном квартале будем готовить новую релизную модель, а для подготовленной в прошлом квартале модели только протаскивать ее по релизному циклу. Появится лаг из-за того, что мы релизим результат с разницей в квартал, но зато горячки и стресса у нас будет меньше.
Назначаем ответственного за релиз
Важно выбрать фичалида, который будет чувствовать свою персональную ответственность за релиз и у которого выделяется достаточное время на задачи. Его приоритет в квартале будет на этих задачах.
Что делает ответственный:
-
Решает, что войдет в релиз
Конечно, это делается вместе с командой, но ответственный имеет большое влияние на решение. Из плюсов быть ответственным – ты можешь протолкнуть гипотезы, которые тебе важны. 🙂
-
Управляет процессом
Ответственный решает, что конкретно он делает, сколько времени ему на это понадобится. Если возникают проблемы, решает, как с ними работать, например, копать проблему или выкидывать проблемную гипотезу и идти дальше.
-
Делает работу «руками»
Собирает пайплайн обучения с выбранными гипотезами, контролирует, чтобы обучение не развалилось в процессе. Остальные коллеги занимаются другими задачами и подключаются только при необходимости. Например, если чью-то гипотезу добавили в релиз, и потом в ней нашли какие-то проблемы, то привлекут того, кто проверял гипотезу, чтобы он разъяснил и помог разобраться.
Ответственные меняются каждый квартал, чтобы не терялся навык и busfactor оставался высоким. Если кто-то назначен ответственным в первый раз, то ему даем наставника из тех, кто уже проходил процесс.
Выбираем гипотезы и определяем ожидания
Выбор направления
Не стоит пытаться достичь нескольких целей одновременно: и уменьшить потребление ресурсов модели, и улучшить качество, и поменять формат хранения модели. Если поставленные цели достигаются одним шагом, например, заменой архитектуры модели, замечательно. Но в остальных случаях, чтобы упростить себе жизнь, лучше двигаться итеративно: выбрать одну цель за раз и сосредоточиться на ее достижении.
Мы заранее выбираем и согласуем направление релиза и ожидания того, что и на сколько хотим улучшить. Если договариваемся улучшать качество, то гипотезы про улучшение производительности оставляем на вторую очередь или переносим на следующий квартал. А крупное изменения архитектуры, для упрощения, не смешиваем с побочными улучшениями.
Пример направления: «Заменить архитектуру JasperNet на архитектуру Сonformer»
На основании чего можем выбирать направление релиза:
-
По запросам от менеджмента на конкретные улучшения. Например, по аналитике проблем или по запросам от пользователей.
-
Исходя из списка гипотез, которые уже проверены и хочется доставить их результаты до пользователей.
-
Исходя из наших собственных планов по развитию технологии.
Отбор гипотез
Набираем список гипотез, которые согласуются с выбранным направлением. Чтобы гипотеза была принята в релизный цикл, она должна быть уже проверена в условиях эксперимента, максимально приближенного к прошлому релизу или его части (например, на этапе файнтюна). Это необходимо, чтобы получить достоверные ожидания по приросту качества.
Важно критически подходить к постановке гипотез и заранее проверять их так, чтобы при релизе не было неожиданностей. Поэтому мы приняли решение не использовать упрощенные сетапы (по времени или с ограниченным числом данных), чтобы исключить необходимость допроверки гипотезы во время подготовки финальной модели.
У нас несколько валидационных датасетов (например, звонки менеджеров по продажам и технической поддержки, записи встреч коллег по видеосвязи) и по каждой гипотезе необходимо получить результаты валидации на каждом наборе данных. Ограниченное число данных используем только в начальном этапе работы над гипотезой, если на то есть необходимость.
Если гипотезу проверили на первом этапе длинного пайплайна, то задаем себе вопрос – доказывает ли это, что гипотеза действительно подтверждена и мы можем рассчитывать на ее метрики? Или для этой гипотезы необходима проверка на всём пайплайне?
Иногда список гипотез получается слишком большим для одного релиза, тогда мы приоритезируем и фильтруем его на основании здравого смысла и паучьего чутья. Например, можем отбирать по оценке прироста качества от гипотезы или повысить приоритет улучшения, в котором заинтересованы пользователи или менеджеры. А если по оценке ответственного какие-то гипотезы несут дополнительные риски или их результаты кажутся неустойчивыми – понижаем приоритет гипотез или не берем их в релиз.
Пример важной для пользователя гипотезы:
Выявили проблему с недостаточно качественным распознавание имен и отчеств. Собрали датасет под эту проблему и планируем доиспользовать его в обучении.
Формирование блоков гипотез
Для каждой гипотезы нереально проводить полный цикл обучения, потому что такой подход займет слишком много времени – обучение всего пайплайна занимает несколько недель. Но и слишком много гипотез опасно сразу добавлять в обучение, потому что в случае проблем будет очень сложно раскопать, в каких гипотезах или их сочетаниях что-то идет не так.
Поэтому мы группируем гипотезы в блоки по срочности/важности/проверенности. Обычно в блок берем не более трех гипотез. Для каждого блока мы проводим полный цикл обучения модели, поэтому не требуется проверять полную комбинаторику того, как согласуются друг с другом все гипотезы. А если проблемы все-таки случатся и придется копать, то надо будет думать об ограниченном числе вещей.
Фиксация ожидаемых метрик
У нас есть ожидания по приросту качества от каждой из гипотез, потому что каждая гипотеза перед принятием ее в релизный цикл уже проверена в условиях эксперимента, максимально приближенного к прошлому релизу или его части (например на этапе файнтюна). Зафиксированные ожидания важны, так как если они разошлись с фактом, то это флаг того, что что-то идет не так. В этом случае для ответственного появляется развилка:
-
Если не достигли ожидаемого качества, но получили прирост метрик, то можно согласиться, что этого достаточно и можно идти дальше.
-
Если метрики слишком сильно отличаются от запланированных, то можно покопать проблему. Для таких ситуаций мы заранее закладываем бюджет времени. Но здесь возникает элемент случайности, потому что непонятно в чем проблема и сколько времени займет ее исправление – может снова начаться исследование в рамках релиза. Поэтому важно сразу установить, сколько мы готовы потратить на попытки исправить проблему.
-
Если метрики слишком сильно отличаются от запланированных, то ответственный имеет право решить, что какую-то гипотезу проще исключить из релиза и перезапустить обучение без нее.
Обучаем пайплайн модели
После того, как гипотезы выбраны и разделены на блоки, переходим к обучению и работаем пошагово.
Проводим обучение одного этапа. Этап/прогон – часть пайплайна обучения: получение базовой модели, ее файнтюн, этапы самообучения (selftrain). В одном прогоне могут участвовать несколько проверенных гипотез из блока. Мы считаем, что все хорошо, если суммарный прирост от комбинации гипотез оказался лучше, чем самая лучшая гипотеза в отдельности. Если метрики соответствуют ожиданиями, то переходим к следующему этапу обучения.
Так мы проводим обучение всего пайплайна и получаем релиз-кандидат, который потенциально можно катить. Переходим к следующему блоку гипотез, выполняем те же шаги и получаем нового кандидата на релиз. Проверяем, пока не закончатся блоки гипотез или отведенное время.
За счет промежуточных кандидатов на релиз повышаем шансы, что вообще сможем что-то новое выкатить.
Чек-лист вопросов для подхода к релизу
Бонусом привожу чек-лист вопросов. Он помогает новичкам, первый раз отвечающим за релиз, не пропустить важные пункты, каждый из которых – плод собранных нами граблей:
-
Есть ли тема релиза?
-
Что будем релизить? Собран ли список гипотез? Есть ли срочные/важные?
-
Все ли гипотезы проверены в продовом пайплайне?
-
Разбиты ли гипотезы на блоки?
-
Есть ли новые валидационные датасеты? (Здесь скрывается опасность, так как нужно получить метрики на этапах старого релиза, чтобы ухудшение качества на новом валсете не было неожиданностью)
-
Есть ли ожидания по приросту качества для каждого этапа/блока гипотез?
-
Влезает ли проверка гипотез в отведенное время?
-
Можно ли что-то выкинуть?
-
Есть ли риски того что что-то пойдет не так? Что с этим делать?
-
Необходима ли дополнительная (помимо уже имеющихся правил) проверка модели в продовом окружении?
Call-to-Action
Как вам наша схема работы – расскажите, какие пробелы и возможности для улучшений вы в ней видите? И как вы собираете релизы из большого количества гипотез?
ссылка на оригинал статьи https://habr.com/ru/articles/862374/
Добавить комментарий