Вы бы поверили, если бы я сказал вам, что наша команда обучает глубокие нейронные сети на удаленной машине с графическим процессором с помощью единственного коммита git? Продолжайте читать, чтобы узнать, как вы можете добиться этого.
Обучение моделей глубокого обучения часто является ручным и трудоемким процессом, что означает, что его может быть трудно воспроизвести, и он подвержен человеческим ошибкам. До CI/CD мой обычный рабочий процесс исследования модели включал довольно много ручных шагов:
- SSH на наш сервер GPU.
- Запустите блокнот Jupyter внутри контейнера Docker.
- Загружайте данные с помощью таких инструментов, как rsync.
- Экспериментируйте с моделями, оценивайте и сохраняйте лучшую модель.
- Загрузите обученную модель и упакуйте ее для производства.
Хотя этот подход может прекрасно работать в случаях, когда модель обучается и развертывается только один раз, он имеет серьезные недостатки в непрерывном рабочем процессе обработки данных, когда ожидается много итераций с моделями и данными. Вот лишь некоторые основные проблемы, которые могут возникнуть на этом пути:
- Устаревшая кодовая база — вы можете просто забыть зафиксировать изменения и отправить их в свой центральный репозиторий git.
- Неуместные данные и файлы моделей — легко потеряться в разных версиях данных или забыть загрузить последние данные и загрузить окончательную модель.
- Предварительная обработка данных в продакшне — их необходимо заново воссоздать для продакшена и синхронизировать в двух кодовых базах.
- Делитесь экспериментами — ваши товарищи по команде не смогут получить доступ к вашим файлам, им придется настраивать среду с нуля.
Чтобы избежать этих проблем, автоматическое обучение моделей глубокого обучения можно интегрировать в конвейер CI/CD (непрерывная интеграция и непрерывное развертывание), что может значительно упростить процесс и сделать его более эффективным. Это можно сделать, включив процесс обучения в качестве шага в конвейер и запуская его автоматически при внесении изменений в код.
Я покажу вам, как это сделать в Gitlab CI/CD.
GitLab CI/CD — это встроенный инструмент непрерывной интеграции, непрерывной доставки и непрерывного развертывания, входящий в состав GitLab. Это позволяет разработчикам автоматизировать процесс создания, тестирования и развертывания своего кода. Кроме того, разработчики могут выявлять и устранять проблемы на ранних этапах процесса разработки, а также быстрее и надежнее вносить изменения в код.
Подобно традиционной разработке программного обеспечения, некоторые задачи обучения модели также могут быть интегрированы в CI/CD. После настройки репозитория gitlab и подключения gitlab-runners для выполнения задач становится довольно легко определить конвейеры CI/CD. Вот общие шаги для начала:
- Создайте файл YAML с именем
.gitlab-ci.yml.
- Определите этапы и задания, которые будут выполняться всякий раз, когда код отправляется в источник. Этап – это группа заданий, которые представляют этап конвейера. Например, общие этапы конвейера включают: сборка, тестирование, развертывание. Задания — это отдельные задачи на этапе, которые выполняют определенные действия, такие как компиляция кода, выполнение тестов или развертывание в определенной среде.
- Для каждого задания определите необходимые сценарии и команды для запуска.
- Отправьте свой код в репозиторий и запустите конвейер. GitLab автоматически запустит конвейер и выполнит шаги, определенные в файле .gitlab-ci.yml.
- По мере запуска конвейера GitLab будет отображать ход и результаты каждого этапа конвейера.
- Если конвейер завершится успешно, модель будет развернута в производственной среде.
Например, у вас может быть:
- этап сборки, на котором выполняется ваш сценарий обучения;
- этап тестирования, который запускает вашу модель в соответствии с проверочным набором;
- этап развертывания, на котором модель развертывается в производственной среде.
stages: - build - test - deploy train_model: stage: build script: - python main.py train --data path/to/train/data --write-model path/to/best.model eval_model: stage: test script: - python main.py test --data path/to/test/data --model path/to/best.model upload_model: stage: deploy script: - python main.py --model path/to/best.model
Этот образец настройки позволяет автоматизировать весь процесс обучения модели, от запуска сценария обучения до тестирования модели и ее развертывания в производственной среде. Это может помочь сэкономить время и ресурсы, а также снизить риск человеческой ошибки.
В нашем случае у нас есть сервер DGX с несколькими графическими процессорами, и нам нужно обучать наши глубокие нейронные сети на удаленном сервере с доступом ssh. У каждого пользователя есть права docker на этой машине, тогда как gitlab-runners устанавливаются на отдельную машину, но подключены в одной сети с DGX.
Учитывая все эти нюансы, мы решили разделить обучение модели на три этапа:
- Создать — создать образ Docker и отправить его в реестр Docker. На этом этапе добавляются сценарии обучения и оценки, зависимости pip и другие файлы конфигурации. При обновлении кода образ докера будет перестроен, чтобы содержать все последние изменения. Пример dockerfile может выглядеть так:
FROM nvidia/cuda:11.3-devel-ubuntu20.04 COPY requirements.txt . RUN pip install --no-cache -r requirements.txt COPY . /app WORKDIR /app
2. Pull — войдите в систему с графическим процессором, извлеките последний образ Docker и загрузите обучающие данные.
3. Обучить — войдите в систему с графическим процессором и запустите обучение модели. Этот шаг включает в себя оценку модели, экспорт лучшей модели в onnx и регистрацию метрик и модели на сервере отслеживания MLflow.
Это наш .gitlab-ci.yml:
variables: # docker image name will correspond to a gitlab project name # and docker tag will be a git branch name DOCKER_IMAGE_TAG: $CI_REGISTRY$CI_PROJECT_NAME:$CI_COMMIT_REF_SLUG # we assume that a user pushing a commit to git is able # to log in to the DGX server USER: $CI_USERNAME # DGX host can be a domain address or IP DGX_HOST: 10.10.10.10 MLFLOW_TRACKING_URI: https://my-mlflow-url.com/ before_script: # this script will run before each job - export DGX="-i path/to/private.key -l $USER $DGX_HOST" stages: - build - pull - train .trigger-training-commit-message: rules: # model training steps will be only launched if # a commit message starts with "train ..." - if: "$CI_COMMIT_MESSAGE =~ /^train.*/" build: extends: # we will use the same `rules` for each job - .trigger-training-commit-message stage: build script: # we'll pull and existing docker image if it exists # to save some time during a docker-build process - docker pull -q $DOCKER_IMAGE_TAG || true - >- docker build --cache-from $DOCKER_IMAGE_TAG -t $DOCKER_IMAGE_TAG . - docker push $DOCKER_IMAGE_TAG pull: extends: - .trigger-training-commit-message stage: pull script: # this script logs in to the DGX machine, # pulls a docker images built during the previous stage # and downloads a training dataset to ./data folder. - >- ssh $DGX <<EOF set -e docker pull --quiet $DOCKER_IMAGE_TAG docker run --rm \ -v "$PROJECT_DIR/data/:/app/data/" $DOCKER_IMAGE_TAG bash get_data.sh EOF train: extends: - .trigger-training-commit-message stage: train timeout: 24h script: # this runs model training, evaluation and logging # inside an nvidia docker container with a GPU #2 - >- ssh $DGX <<EOF set -e docker run --rm \ -v "$PROJECT_DIR/data/:/app/data/" \ -e "NVIDIA_VISIBLE_DEVICES=1" \ --runtime nvidia \ --shm-size 10g \ $DOCKER_IMAGE_TAG python train.py --data data/processed/dataset EOF
Могут быть разные стратегии относительно того, когда запускать обучение модели, поскольку мы не хотим делать это каждый раз, когда вносим небольшое изменение в код. Некоторые люди могут предпочесть иметь выделенную ветку git исключительно для обучения модели, мы, с другой стороны, решили запустить обучение модели в зависимости от конкретного сообщения коммита git. Я вижу несколько преимуществ этой стратегии:
- Будет трудно непреднамеренно обучить модель, и мы можем использовать стратегию git-flow, чтобы поддерживать наш код в актуальном состоянии.
- Для обучения модели требуется сообщение фиксации, которое всегда будет полезно, чтобы вернуться в историю и просмотреть изменения, которые приводят к улучшению или снижению показателей.
Эта задача может представлять изрядную долю проблем и требовать больших усилий, проб и ошибок и терпения. Тем не менее, чувство выполненного долга и удовлетворения, которое приходит от преодоления этих препятствий и достижения успеха, в конечном итоге того стоит. Тяжелая работа и целеустремленность в конечном итоге окупятся в виде личного и профессионального роста.
В дополнение к улучшению вашего собственного набора навыков, ваши товарищи по команде и вы сами через несколько месяцев в будущем получите большую пользу от автоматизированного CI / CD для обучения моделей. Преимущества очевидны:
- обучающие эксперименты по существу воспроизводимы, поскольку код всегда обновляется, а данные доступны для загрузки из общих ресурсов.
- журналы обучения модели сохраняются, вы всегда можете вернуться и прочитать выходные данные регистратора или оператора print.
- конвейер побуждает разработчика использовать централизованное хранилище для отслеживания экспериментов и регистрации моделей, которое должно быть доступно для каждого члена команды.
Если вам нравятся идеи в этом посте, не стесняйтесь поделиться им со своими коллегами и друзьями и задать вопросы в комментариях ниже.