Machine Learning на базе Jupyter Notebooks в Delivery Hero

Підписуйтеся на Telegram-канал «DOU #tech», щоб не пропустити нові технічні статті.

Всем привет, меня зовут Николай Белозёров, я Senior Data Engineer в Delivery Hero и пишу из солнечного Берлина.

Я хочу поделиться с вами опытом о том, как мы используем Jupyter Notebooks для тренировки наших моделей и не только.

О Delivery Hero

Delivery Hero — это ведущая в мире платформа доставки продуктов, предоставляющая услуги примерно в 50 странах Азии, Европы, Латинской Америки, Ближнего Востока и Северной Африки. Компания начинала свою деятельность с доставки еды в 2011 году и сегодня имеет собственную платформу доставки на четырех континентах. Кроме того, Delivery Hero является пионером в области быстрой доставки (q-commerce), следующего поколения электронной коммерции, стремящейся доставлять продукты и товары для дома покупателям менее чем за час, а часто и за 10-15 минут. Компания Delivery Hero со штаб-квартирой в Берлине, Германия, с 2017 года котируется на Франкфуртской фондовой бирже, а в 2020 году стала частью ведущего индекса DAX (Deutscher Aktienindex).

Чем занимается моя команда

Моя команда была сформирована три года назад и в начале состояла всего лишь из двух человек: меня, ответственного за разработку, и менеджера, ответственного за Data Science часть. Через несколько месяцев к нам присоединился Data Scientist, который начал работать над улучшением нашей модели. За все это время команда выросла в 2,5 раза.

Описание наших Data Science Use Cases

Первым и главным Data Science use case, над которым мы работали, было предсказание времени доставки заказа.

Оценка времени доставки заказа является важной частью обеспечения позитивного опыта для пользователей. Delivery Hero на большинстве своих рынков либо использует собственную логистику (OD — Own Delivery), либо полагается на доставку заказа самими ресторанами (VD — Vendor Delivery). Data-driven способ для оценки времени доставки требует наличия определенных сигналов, с помощью которых, мы можем приблизительно/фактически знать время предыдущих заказов, чтобы использовать эти данные для предсказания/оценки времени доставки для будущих заказов.

Очень важно давать пользователю правильные ожидания в плане времени доставки заказа.

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

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

Эту проблему мы и пытались решить. А теперь давайте приступим к технической части.

Что такое Jupyter notebooks

Я не буду углубляться сильно в детали о Jupyter Notebooks, так как это не совсем цель этой статьи, вы можете больше почитать здесь:

Jupyter Notebooks является одним из самых популярных и давно полюбившихся инструментов, когда дело доходит анализа данных и разработки моделей.

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

Jupyter Notebooks состоят из двух главных компонентов: web interface для написания кода и server часть для выполнения кода, написанного пользователем.

Что пользователи ценят в jupyter notebooks

  • Это один из самых популярных интерфейсов для разработки моделей и как результат большинство Data Scientist/Data Analyst знают, как работать с ним.
  • За счет простого и понятного интерфейса среда разработки позволяет очень быстро начать работу, даже если пользователь не имеет предыдущего опыта.
  • Позволяют очень быстро изменять и адаптировать решения, а также проверять результаты, — что является очень важным в разработке моделей.
  • Благодаря популярности и большому сообществу, доступно огромное количество разных расширений, которые позволят улучшать работу с ноутбуками.

Недостатки jupyter notebooks

  • Отсутствие совместной работы нескольких людей одновременно.
  • В чистом виде довольно сложно внедрить в стандартный цикл разработки.
  • Сложно тестировать.
  • Отсутствие параметризации.
  • Отсутствие version control/истории изменений.
  • Довольно часто сложно поддерживать качество самих notebooks.

Что обычно говорят о jupyter notebooks

Почему мы решили пойти эти путем

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

Мы старались использовать serverless-решения и готовые сервисы, которые были доступны на AWS и GCP, а также open source-решения, которые могли бы ускорить разработку наших моделей.

Беря во внимание размер нашей команды, мы старались достичь максимального уровня автономности и эффективности работы каждого члена команды.

Все вышесказанное и повлияло на платформу, которую мы построили.

В самом начале работы над будущей платформой (на деле изначально это была просто автоматизация работы для Data Scientist) мы выделили список целей которые мы хотим достичь:

  • Позволить Data Scientist работать и главное деплоить модели без помощи инженеров.
  • Сделать возможность иметь историю и версии для моделей и notebooks.
  • Возможность отправить результаты модели и дата анализ стейкхолдерам.
  • Использовать типичные инженерные практики для жизненного цикла модели.
  • Сделать возможность параметризировать модели чтобы легко адаптировать модели для релизов в разные страны.
  • Иметь возможность релизить модели часто.

Что же вышло в итоге

Платформу, которую мы построили, можно разделить на три части.

Model development

Является главным инструментом Data Scientist для разработки моделей. Мы используем Amazon Sagemaker как главный инструмент для разработки моделей и соответственно Jupyter Notebooks внутри.

Почему Amazon Sagemaker?

  • По сути это платформа, которая позволяет использовать Jupyter Notebooks serverless и не тратя время на настройку ресурсов.
  • Позволяет частично достичь совместной работы на одном сервере.
  • Позволяет легко scale up/scale down по требованию.
  • Возможность настраивать окружение для Data Scientist.

Оптимизация среды разработки для Data Scientist

Как я уже упоминал, мы пытаемся сделать работу каждого члена команды как можно более эффективной. Так как одним из основных инструментов (по крайней мере в нашей команде) для Data Scientists является Jupyter Notebook, который работает на базе AWS Sagemaker. Мы старались улучшить эту среду с помощью различных расширений таких как: code_prettify/code_prettify, execute_time/ExecuteTime, collapsible_headings

и с помощью автоматизации окружения на Sagemaker:

  • автоматически останавливать sagemaker/jupyter notebooks после определенного времени неактивности;
  • автоматически создавать (устанавливать специальный список библиотек и пакетов) окружение для Data Scientists.

Важную роль во всем процессе разработки моделей сыграл ReviewNB.

Более подробно про можно почитать тут и тут. Вкратце, это сервис который позволяет делать код ревью для jupyter notebooks, с возможностью комментирования каждой строки и полной интеграцией с github.

Без использования этого сервиса делать код review для jupyter notebooks на github практически невозможно ввиду того, что github не может рендерить объемные jupyter notebooks.

ReviewNB является платным сервисом. Конечно, все, что он предоставляет, возможно добиться разработав свое собственное решение и используя open-source (к примеру — nbdime.readthedocs.io/en/latest), но мы не были готовы инвестировать время и ресурсы в разработку подобного решения и выбрали использовать платную версию.

ReviewNB в итоге уже год как получил широкое распространение внутри компании среди Data Scientists и в этом году мы продлили лицензию на сервис, несмотря на то, что они увеличили стоимость. ReviewNB так же предоставляет self-hosted версию.

На стадии Release Notebook мы попытались использовать типичные практики разработки: CI/CD и контейнеризацию. Готовый jupyter notebook добавляется в уже подготовленный специальный Docker image для последующей тренировки модели.

Model training

Главным компонентом для тренировки моделей в нашем случае выступает Airflow, который мы используем также для всех наших data pipelines.

Airflow позволяет запускать тренинг вручную либо по расписанию.

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

И теперь мы переходим к самой интересной части, как же все таки мы тренируем модель с Jupyter Notebooks.

А помогаете нам в этом papermill. Изначально библиотека была разработана в Netflix и по сути они были пионерами «здорового концепта» использования jupyter notebooks для запуска моделей.

papermill — это библиотека для параметризации, запуска и анализа Jupyter Notebooks.

Papermill позволяет:

  • параметризовать jupyter notebooks
  • запускать jupyter notebooks

Так выглядит запуск jupyter notebooks с помощью papermill

Для того, чтобы использовать параметры из papermill, они должны быть прописаны в самом jupyter notebook.

Все параметры для jupyter notebooks и модели мы храним в airflow в yaml формате. Такой способ позволяет Data Scientist легко манипулировать параметрами и быть полностью ответственному за тренировку моделей.

Как я уже упоминал ранее, мы пытались выбирать везде serverless решения, поэтому все тренировки моделей выполняется с помощью AWS Batch. AWS Batch позволяет нам быстро изменять ресурсы для тренировок моделей, в тоже время не заботясь о самой инфраструктуре, а лишь манипулируя параметрами такими как CPU и Memory.

Как видно на картинке ниже, конфигурация для ресурсов, которые нужны для тренировки каждой модели, указана вместе с конфигурацией для самой модели. Таким образом, в случае, когда ресурсы нужно добавить, это может быть осуществлено самим Data Scientist без помощи инженера — путем изменения конфигурационного файла.

Model reports

Как только тренировка модели завершена, мы сохраняем готовую модель и артефакты для модели на наш Model Store на s3. Далее модель будет загружена из Model Store внутри сервиса, который и использует модель для предсказания. Также мы сохраняем отчет (отчет генерируется с помощью papermill) после тренировки модели в виде html (по сути готовый jupyter notebook с графиками и результатами).

Структура отчета выглядит таким образом: model-report-store/model-name/model-version/training-date/report-name.html

Такая структура позволяет нам всегда иметь доступ к историческим результатам тренировок моделей и разных версий моделей.

Model serving

Процедура запуска моделей для real-time у нас довольно стандартная — мы используем REST api сервисы на базе falcon или fastapi. По сути, это просто обертка для модели с REST интерфейсом и различными функциями мониторинга. Сам сервис работает внутри AWS EKS. При запуске сервис подтягивает модель с Model Store (s3) и потом периодически обновляет ее.

Model monitoring and quality

Важным аспектом, который стоит упомянуть, является мониторинг и трекинг качества значений, которые выдает наша модель. Кроме стандартных решений этих проблем: DataDog для мониторинга сервиса, BigQuery для сбора и последующего анализа значений, DataStudio — для создания отчетов, Slack — для уведомлений — в нашем случае большую роль сыграло использование Great Expectations.

Great Expectations — это open source библиотека, которая позволяет создавать unit-tests для данных и следить за тем, как показатели модели меняются за определенный период времени. Библиотека поддерживает интеграцию со многими популярными сервисами и инструментами в BigData/ML мире и в частности с Airflow. Мы используем Great Expectations для того, чтобы следить за значениями, которые наша модель генерирует. Для этого наши Data Analysts создали список правил/expectations, которые мы ежедневно/иногда каждый час используем для проверки данных, генерируемых нашими моделями.

Финальный взгляд на платформу, которую мы построили:

Итоги нашей работы

Позитивные стороны

Подводя итоги работы над нашей платформой и использования ее для работы над Data Science решениями, я могу выделить такие плюсы:

  • Наша платформа позволяет нам иметь короткие циклы разработки и реализа моделей.
  • Для новых пользователей платформы — Data Scientists и Data Analysts — адаптация к работе с платформой происходит очень быстро.
  • Весь процесс от разработки модели до релиза в production может быть полностью контролирован Data Scientists или Data Analysts без особой помощи от инженеров.
  • Позволяет оптимизировать тренировку моделей с большим количество параметров. В нашем случае, учитывая, что мы тренируем модели для 15+ стран, возможность использования одного и того же jupyter notebook с разными параметрами в зависимости от страны, стало ключевым фактором.
  • Позволяет иметь подробную визуализацию и отчетность каждого шага тренировки модели в jupyter notebook.

Какие ограничения мы выявили

Конечно, это решение не является идеальным и не подойдет для всех Data Science решений ввиду таких ограничений:

  • В целом, весь процесс описанный выше работает идеально для простых моделей — regression, xgboost.
  • В случае, если ваша модель нуждается в больших объемах данных — вам все равно нужно иметь отдельный ETL процесс. В нашем случае, так как мы работали только с тремя месяцами данных — это не было большой проблемой.
  • Вам нужно создать атмосферу внутри команды, когда Data Scientist полностью берет на себя ответственность за то, что он делает, так как его действия напрямую влияют на результаты работы всей команды.
  • Несмотря на то, что тренировки моделей происходили автоматически, время от времени нам было необходимо изменять размер ресурсов для тренировки моделей. У нас есть план над автоматизацией этого процесса.

Выводы

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

  • Подход, описанный выше, работает очень хорошо для небольших и опытных команд, где вы можете доверять друг другу.
  • Чтобы достичь хороших результатов, вам нужно иметь хороший мониторинг качества вашей модели.
  • Интеграционные тесты являются важным компонентом в релизе моделей и помогли нам найти очень много ошибок перед релизом.
  • Serverless — это наше будущее. Может показаться, что такой подход выходит дороже и сложно контролировать стоимость ресурсов, но на деле выходит, что самый дорогой ресурс — это люди и время, а в случае с ML время играет еще более ключевой фактор. Поэтому лучше потратить время на улучшение моделей, чем на построение инфраструктуры, когда уже есть возможность взять что-то готовое.
  • Используйте code-review для jupyter notebooks — это позволяет не только найти проблемы на ранних этапах, но и делится знаниями внутри команды.

Что дальше

Несмотря на то, что у нас уже есть платформа, которая работает и удовлетворяет много наших потребностей — в ней все еще не хватает очень много функций. За эти 2 года ML мир очень сильно скакнул и на рынке появилось очень много уже готовых решений как полноценных aka ML Platforms, так и различных сервисов которые позволяет вам решать определенные проблемы в Model Lifecycle, даже появился такой термин как MLOps.

Поэтому на данном этапе мы смотрим в сторону использования дополнительно более готовых решений таких как Sagemaker Studio или VertexAI

Надеюсь статья была интересная. Оставляйте ваши комментарии внизу, либо вы всегда можете связаться со мной для более детальных вопросов через Linkedin, Telegram (@nick_bilozerov) bkb nickdani.ua@gmail.com

И конечно же, мы ищем людей. Если вам показалось интересным, то чем моя команда занимается и вы хотите поработать в международной компании в «силиконовой столице» Европы — Берлине, пишите! У нас много открытых позиций и еще больше интересных проектов: Customer Data Platform, Fraud Detection, Food Graph, ML Platform, Data Platform. Мы ищем: Data Engineers, Go Developers, MLOps Engineers, Data Scientists, Data/ML Product Managers. Компания предоставляет очень хороший релокационный пакет. За подробностями пишите в ЛС.

Вы можете больше узнать о том, чем мы занимаемся:

👍НравитсяПонравилось0
В избранноеВ избранном3
LinkedIn
Допустимые теги: blockquote, a, pre, code, ul, ol, li, b, i, del.
Ctrl + Enter
Допустимые теги: blockquote, a, pre, code, ul, ol, li, b, i, del.
Ctrl + Enter

Використовую Jupyter Notebook для дебагу кусків коду Python. Прод крутиться на databricks, там дрібні куски коду ранити не дуже вигідно, особливо якщо в процесі дебагу доведеться ранити сотню разів. Бо databricks в режимі «ранимо вручну» використовує analytics cluster, який в нашому випадку має 4 ядра (дорого), а в режимі джобів чекає навіть декілька хвилин поки з’явиться вільний aws ec2 інстанс. Для порівняння — Jupyter Notebook «просто» раниться локально (стартує миттєво), не потрібно орендувати дорогі інстанси.

І все ж не все можна навіть просто подебажити в Jupyter Notebook. Я не копав надто глибоко аби з’ясувати причини, однак якийсь наче банальний запит sql (ок, не надто легкий, але цілком оптимізований) може призвести до того що в Jupyter вилітає кернел. Ну тут просто переключаюся назад в databricks.

Кернел может вылетать из-за нехватки памяти — если sql ранится и выгружает все в память.

Хм... 16 гіг оперативи, кількість даних ну не те щоб гігантська.

Скейлинг кластера и старт джобов в Databricks решается через instance pools (не мгновенно конечно, но у нас стартует все обычно в пределах минуты, если это не «холодный» пул утром).
Если нужен SQL — Snowflake конечно решает. У нас все работает в связке Databricks <-> Snowflake + Immuta для Data Governance.

В нас якраз використовується Snowflake. В зв’язці з Jupyter Notebook банальні запити призводять до падіння kernel. Оперативки на локальному компі 16 гіг. Кількість даних не те щоб гігантська. Буває що навіть падає на етапі конекту до Snowflake. Із databricks такого не відбувається. Я вже було забив на це, але оскільки почали цю розмову, то може хтось стикався.

Читают через docs.snowflake.com/...​ase-to-a-pandas-dataframe ? Если падает через этот api (который под капотом использует pyarrow/flight), то значит в pandas не влазит, можно попробовать вычитать батчами и впихнуть в какой-то vaex например.

Мы в Jupyter Notebooks используем BQ как сорс данных и запускаем тоже SQL запросы, проблем вроде не было. даже на несокльких Gb данных. возможно, проблема именно с

Snowflake

коннектом или нетворкингом. я бы рекомендовал попробовать отправить sql запросы из терминала jupyter и посмотреть как отработает

мы решили отказаться от Sagemaker notebooks (плохая кастомизация) и поставили свой jupyterhub с интергацией с keycloak

Интересно, у нас как раз таки наоборот ситуация. Одна из команд поддерживала jupyterhub и в итоге переехали на sagemaker studio. Мы решили наши проблемы с кастомизацией через life-cycle config. Сейчас мы в процессе сравнения Sagemaker Studio и VertexAI. Мы перенесли наши текущие sagemaker notebooks на Sagemaker Studio — и студия выглядит очень перспективно. Было бы интересно услышать какие проблемы с кастомизацией у вас были :)

у нас изначально были Sagemaker notebook instances там совсем все плохо. Студия намного лучше. но у нас возникли проблемы с интеграций с keycloak , мы не используем AWS SSO и мы не нашли как сделать персональные ноутбуки: чтобы никто кроме собственника не мог туда залогиниться. Также нам надо было использовать GWT token пользователя внутри нотебуков для работы с внутренними сервисами

да с AWS SSO + Sagemaker Studio там не все так просто, мы в компании используем Okta, но тк компания очень большая но у нас нет доступа к настройкам Okta и мы не можем сделать интеграцию с студией. Поэтому пришлось идти через обходные пути и IAM роли и динамические полиси под пользователя. Но да я понимаю проблему, когда дело доходит до специфической кастомизации задачи становятся очень не тривиальными

спасибо за статью, несколько вещей почерпнул для себя. а KubeFLow вы не рассматривали?

рассматриваем, но больше как альтернативу, но на данный момент в меньшей степени тк все таки для KubeFlow нужно супортить ифраструктуру и для рядового датасаянтиста «интерфейс» kubeflow сложноват. Sagemaker Studio позволяет тренировать модели без супорта инфраструктуры и по сути поддержки со стороны инжинеров — что дает больше свободы для DS. VertexAI от Google предоставляет возможность тренировки моделей и они под капотом используют kubeflow

Подписаться на комментарии