Или, скорее, создание повторно используемого конвейера машинного обучения, инициированного одним файлом конфигурации и пятью определяемыми пользователем функциями, которые выполняют классификацию, основаны на точной настройке, распределяются в первую очередь, работают на AWS Sagemaker, используют Huggingface Transformers, Accelerate, наборы данных и Evaluate, PyTorch, wandbи многое другое.

Этот пост первоначально появился в Блоге VISO Trust

Это вводная статья в серии из трех частей. Чтобы перейти к другим сообщениям, ознакомьтесь с разделами Создание конвейера машинного обучения, часть 2: этапы обработки данных или Создание конвейера машинного обучения, часть 3: обучение и вывод.

Введение

В команде Data & Machine Learning в VISO Trust одна из наших основных целей — предоставить Document Intelligence нашей команде аудиторов. Каждый документ, проходящий через систему, подлежит сбору, синтаксическому анализу, переформатированию, анализу, составлению отчетов и многому другому. Часть этого интеллекта автоматически определяет, какой тип документа был загружен в систему. Знание того, какой тип документа поступил в систему, позволяет нам выполнять специализированный анализ этого документа.

Задача маркировки или классификации вещей — это традиционное использование машинного обучения, однако классификация всего документа, который для нас может составлять до 300+ страниц, находится на переднем крае исследований в области машинного обучения. На момент написания этой статьи исследователи спешат использовать достижения в области глубокого обучения и, в частности, в Трансформерах для классификации документов. Фактически, в начале этой задачи я провел некоторое исследование пространства с такими ключевыми словами, как Классификация документов/Разведка/Представление, и наткнулся почти на 30 различных статей, которые используют глубокое обучение и были опубликованы в период с 2020 по 2022 год. Для тех, кто знаком с пробелом, такими именами, как LayoutLM/v2/v3, TiLT/LiLT, SelfDoc, StructuralLM, Longformer/Reformer/Performer/Linformer, UDOP и многими другими.

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

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

Когда я приступил к проверке концепции (pre-ML Pipeline), потребовалось больше месяца, чтобы собрать и очистить данные, подготовить модель, выполнить вывод и заставить все работать в Sagemaker с помощью дистрибутива. С момента создания конвейера машинного обучения мы неоднократно использовали его для быстрого экспериментирования с новыми моделями, переобучения существующих моделей на новых данных и сравнения производительности нескольких моделей. Время, необходимое для проведения нового эксперимента, составляет в среднем от полудня до дня. Это позволило нам выполнять итерации невероятно быстро, быстро запуская модели в производство на нашей платформе Document Intelligence.

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

Настройка эксперимента машинного обучения

Важным архитектурным решением, которое мы приняли в начале, было сохранение экспериментов изолированными и легко воспроизводимыми. Каждый раз, когда выполняется эксперимент, у него есть собственный набор необработанных данных, закодированных данных, файлов докеров, файлов моделей, результатов тестов логического вывода и т. д. Это упрощает отслеживание данного эксперимента в инструментах репозиториев/S3/метрик и его происхождение. как только он находится в производстве. Однако стоит отметить один компромисс: обучающие данные копируются отдельно для каждого эксперимента; для некоторых организаций это просто невозможно, и необходимо более централизованное решение. С учетом сказанного далее следует процесс создания эксперимента.

Эксперимент создается в репозитории экспериментов и привязывается к заявке (например, JIRA), например EXP-3333-longformer. Это имя будет следовать за экспериментом в сервисах; для нас все хранилище происходит на S3, поэтому в корзине эксперимента объекты будут сохранены в родительском каталоге EXP-3333-longformer. Кроме того, в wandb (нашем трекере) имя группы верхнего уровня будет EXP-3333-longformer.

Затем файлы-заглушки копируются и модифицируются в соответствии с особенностями эксперимента. Это включает в себя файл конфигурации и определяемые пользователем заглушки функций, упомянутые выше. Также включены два файла докеров; один файл dockerfile представляет зависимости, необходимые для запуска конвейера, другой представляет зависимости, необходимые для запуска 4 разных этапов в AWS Sagemaker: подготовка данных, обучение или настройка и вывод. Оба этих файла докеров упрощаются за счет расширения базовых файлов докеров, поддерживаемых в библиотеке конвейера машинного обучения; цель состоит в том, чтобы они включали только дополнительные библиотеки, необходимые для эксперимента. Это соответствует соглашению, установленному Контейнерами глубокого обучения AWS (DLC), и, по сути, наш базовый контейнер sagemaker начинается с расширения одного из этих DLC.

Здесь есть важный компромисс: мы используем один монолитный контейнер для выполнения трех разных шагов на Sagemaker. Мы предпочли более простую настройку для экспериментаторов (один dockerfile) вместо необходимости создавать разные контейнеры для каждого шага Sagemaker. Недостатком является то, что для данного шага контейнер, вероятно, будет содержать некоторые ненужные зависимости, которые делают его больше. Давайте посмотрим на пример, чтобы закрепить это.

В наш базовый контейнер Sagemaker мы расширяем:

FROM 763104351884.dkr.ecr.us-west-2.amazonaws.com/huggingface-pytorch-training:1.10.2-transformers4.17.0-gpu-py38-cu113-ubuntu20.04

Это дает нам pytorch 1.10.2 с привязками cuda 11.3, трансформаторы 4.17, python 3.8 и ubuntu, готовые к запуску на графическом процессоре. Посмотреть доступные DLC можно здесь. Затем мы добавляем sagemaker-training, accelerate, evaluate, datasets и wandb. Теперь, когда экспериментатор расширяет этот образ, ему нужно беспокоиться только о любых дополнительных зависимостях, которые могут понадобиться его модели. Например, модель может зависеть от детектрона2, что маловероятно среди других экспериментов. Таким образом, экспериментатору нужно было подумать только о расширении базового контейнера sagemaker и установке Dettron2, а о зависимостях было покончено.

С установленными базовыми контейнерами Docker файлы, необходимые для начала эксперимента, будут выглядеть так:

Вкратце, это файлы:

  • settings.ini: единый (проигнорированный git) файл конфигурации, в котором содержатся все настройки для каждого шага конвейера машинного обучения (скопированы в файлы докеров).
  • sagemaker.Dockerfile: расширяет базовый обучающий контейнер, описанный выше, и добавляет любые дополнительные зависимости модели. Во многих случаях будет достаточно самого базового контейнера.
  • run.Dockerfile: расширяет базовый контейнер запуска, описанный выше, и добавляет любые дополнительные зависимости запуска, необходимые экспериментатору. Во многих случаях будет достаточно самого базового контейнера.
  • run.sh: сценарий оболочки, который создает и запускает run.Dockerfile.
  • build_and_push.sh: сценарий оболочки, который создает и отправляет файл sagemaker.Dockerfile в ECR.
  • user_defined_funcs.py:содержит пять определяемых пользователем функций, которые будут вызываться конвейером машинного обучения на различных этапах (скопированы в файлы докеров). Мы обсудим их подробно позже.

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

Run_number будет увеличиваться с каждым последующим запуском эксперимента. Этот номер запуска будет реплицирован в wandb, а также будет добавлен префикс к любой развернутой конечной точке для производства, чтобы точное выполнение эксперимента можно было отследить посредством обучения, сбора метрик и производства. Наконец, давайте посмотрим на получившуюся структуру wandb:

Я надеюсь, что знакомство с интерфейсом экспериментатора облегчит понимание самого пайплайна.

Конвейер машинного обучения

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

Давайте сосредоточимся на ml_pipeline:

В папке environment будут храниться файлы для создания базовых контейнеров, о которых мы говорили ранее, один для запуска фреймворка и один для любого кода, который выполняется в Sagemaker (предварительная обработка, обучение/настройка, вывод). Они названы с использованием тех же условий, что и DLC AWS, поэтому их легко создать несколько версий с разными зависимостями. Мы будем игнорировать тестовую папку до конца этого блога.

В каталоге lib находится наша реализация конвейера машинного обучения. Давайте снова увеличим масштаб только этого каталога.

Давайте начнем с run_framework.py, так как это даст нам общее представление о том, что происходит. Скелет run_framework будет выглядеть так:

Файл settings.ini, определенный пользователем для эксперимента, будет скопирован в один и тот же каталог (BASE_PACKAGE_PATH) внутри каждого док-контейнера и проанализирован в объект с именем MLPipelineConfig(). В нашем случае мы решили использовать Python Decouple для управления конфигурацией. В этом конфигурационном файле начальные настройки следующие: RUN_RECONCILIATION/PREPARATION/TRAINING/TUNING/INFERENCE, поэтому конвейер может быть гибким именно для того, что ищет экспериментатор. Эти значения составляют приведенные выше условия.

Обратите внимание на строку importlib. Эта строка позволяет нам импортировать функции, специфичные для варианта использования, и передавать их в шаги (здесь показано только согласование данных), используя значение конфигурации, установленное экспериментатором для варианта использования.

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

Функция _validate_funcs гарантирует, что функции с такими определениями существуют и что они не определены как pass (т. е. пользователь создал их и определил). Приведенный выше файл user_defined_funcs.py просто определяет их как проход, поэтому пользователь должен перезаписать их, чтобы выполнить действительный запуск. _validate_run_num выдает исключение, если RUN_NUM, определенный в settings.ini, уже существует на s3. Это избавляет нас от распространенных ошибок, которые могут возникнуть через час после начала тренировки.

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