Как мне выполнить модульное тестирование функции в конвейере CI, которая использует файлы моделей, не являющиеся частью git remote?

#unit-testing #machine-learning #mocking #continuous-integration #dvc

#модульное тестирование #машинное обучение #издевательство #непрерывная интеграция #dvc

Вопрос:

Я разрабатываю репозитории машинного обучения, для запуска которых требуются довольно большие обученные файлы моделей. Эти файлы не являются частью git remote, но отслеживаются DVC и сохраняются в отдельном удаленном хранилище. Я сталкиваюсь с проблемами, когда пытаюсь запустить модульные тесты в конвейере CI для функций, которым требуются эти файлы моделей для их прогнозирования. Поскольку у меня нет доступа к ним в git remote, я не могу их протестировать.

Какова наилучшая практика, которую люди обычно делают в этой ситуации? Я могу придумать пару вариантов —

  • Извлеките модели из DVC remote внутри конвейера CI. Я не хочу этого делать, потому что загрузка моделей каждый раз, когда вы хотите запустить push-код, быстро съест мои минуты использования для CI и является дорогостоящим вариантом.
  • Используется unittest.mock для имитации вывода из предсказания модели и тестирования других частей моего кода. Это то, что я делаю сейчас, но это своего рода проблема с макетными функциями unittest. Насколько я могу судить, этот модуль на самом деле не был разработан с учетом ML. В нем отсутствуют (или его трудно найти) некоторые функции, которые мне бы очень понравились. Существуют ли какие-либо хорошие инструменты для этого, специально предназначенные для ML?
  • Сделайте странное переформатирование определения функции, которое позволяет мне по существу выполнять вариант 2, но без макетного модуля. То есть просто протестируйте окружающую логику и не беспокойтесь о выходе модели.
  • Просто поместите файлы моделей в git remote и покончите с этим. Используйте DVC только для отслеживания данных.

Что люди обычно делают в этой ситуации?

Ответ №1:

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

Хотя это не черно-белое. Если вы по какой-то причине видите, что проще использовать реальную модель (например, она сильно меняется, и ее проще использовать вместо поддержки и обновления заглушек / приспособлений), вы потенциально можете ее кэшировать.

Я думаю, чтобы помочь вам с макетом, вам нужно будет поделиться некоторыми техническими деталями — как выглядит функция, что вы пробовали, какие сбои и т.д.

чтобы сделать это, потому что загрузка моделей каждый раз, когда вы хотите запустить push-код, быстро съест мои минуты использования для CI и является дорогостоящим вариантом.

Я думаю, что вы потенциально можете использовать системный кэш CI, чтобы не загружать его снова и снова. Это репозиторий, связанный с действиями GitHub, это CircleCI. Идея одинакова для всех распространенных поставщиков CI. Кстати, какой из них вы планируете использовать?

Просто поместите файлы моделей в git remote и покончите с этим. Используйте DVC только для отслеживания данных.

Это может быть так, но если модели достаточно велики, вы значительно загрязните историю Git. В некоторых системах CI это может стать еще медленнее, поскольку они будут получать это с помощью regular git clone . Фактически, загрузка моделей в любом случае.

Кстати, если вы используете DVC или нет, взгляните на другой проект с открытым исходным кодом, созданный специально для CI / CD для ML — CML.

Комментарии:

1. Спасибо за ответ. Я не знал о кэшировании, и это звучит как хороший вариант, чтобы попробовать. Я использую GitLab CI, и, похоже, он также поддерживает кэширование. Проблема с mocking заключается в том, что мне нужно генерировать большие массивы numpy, выходные данные которых должны отличаться при каждом вызове функции (в цикле тестируемой функции). Кроме того, я также хотел бы, чтобы фиктивная функция генерировала свои выходные данные на основе заданных входных данных. Я не уверен, как заставить их работать.