newsmode
search
Меню
arrow_back Назад

Why You Need to Follow Up After Your Data Science Project

auto_awesomeКраткое саммари

Юджин Ян объясняет, почему после завершения data science проекта недостаточно просто закоммитить код. Код первой итерации обычно неаккуратен: остаются тупиковые эксперименты, важна последовательность запуска шагов, а Jupyter-ноутбуки плохо работают с git (изменение одной строки кода раздувает git diff из-за выходных данных ячеек). Автор предлагает три практики: делать работу воспроизводимой при каждом запуске (Makefile для окружения, скрипт запуска ноутбуков по порядку, фиксация seed, Docker-образ и README), документировать всё в стиле прикладной научной статьи (мотивация, обзор литературы, данные, методология, результаты, следующие шаги) и обязательно делиться результатами с разными аудиториями. В качестве примера он приводит классификатор товаров для e-commerce (top-3 точность 95%), вокруг которого после простого UI и заметки во внутренней рассылке возник благоприятный цикл новых коллабораций и доверия. Эти follow-up практики занимают неделю-две, но многократно окупаются за счёт воспроизводимости, передачи знаний, вовлечения сообщества и брендинга команды.

Почему нужно довести дело до конца после завершения data science проекта

[ mechanism datascience productivity ] · чтение на 12 мин

После завершения data science проекта возникает соблазн просто закоммитить код и считать дело сделанным. В конце концов, с git у нас есть изменения кода — этого ведь достаточно, верно? Если бы.

Код первой итерации неаккуратен, особенно на ранних стадиях data science проектов, таких как эксперименты и proof of concept (POC). Из-за этого спустя несколько месяцев становится сложно воспроизвести достигнутую точность в 98,67%. Среди проблем:

Тупиковый код: мы провели множество экспериментов и столкнулись с множеством тупиков; они всё ещё присутствуют в коде. Через несколько месяцев будет трудно отделить тупиковые ветки от рабочего подхода. Неверная последовательность запуска: data science пайплайны строго последовательны; каждый шаг зависит от предыдущего. Запустите их в другом порядке — и получите другие результаты. Плохой контроль версий для ноутбуков Jupyter: data science прототипы в основном делаются в Jupyter-ноутбуках. К сожалению, ноутбуки плохо работают с git. Повторный запуск ноутбука приводит к различиям в тысячи строк и затуманивает изменения в коде.

Ноутбуки Jupyter сегодня — неотъемлемая часть процесса экспериментов в data science. Выводы ячеек (например, изображения, таблицы, логи и т. д.) можно хранить прямо в ноутбуках и легко ими делиться. Другие могут открыть ноутбук и — не перезапуская его — увидеть код и результаты.

Это связано с тем, что Jupyter-ноутбуки хранятся в формате json с метаданными, исходным кодом, форматированным текстом, медиа и т. д. К сожалению, это плохо сочетается с git, который лучше всего работает с простым текстом.

Выводы ячеек, которые мы так любим, могут раздражать при использовании контроля версий (например, git). Хотя небольшое изменение в коде меняет и вывод, изменение вывода куда объёмнее и отвлекает от изменения кода (в git diff). Из-за этого сложно совместно работать над ноутбуками.

Just a single-line code change

«Да я просто меняю одну строку кода, чтобы добавить сетку. Ничего страшного.»

В примере выше мы строим ту же синусоиду, только добавляем сетку справа. Это чисто эстетика, на результаты это не влияет. Однако при ревью pull request мы увидим приведённый ниже git diff. И это от изменения одной строки кода — такое быстро становится неуправляемым.

Jupyter notebook dif diff from a single-line code change

И всё это — от изменения одной строки кода. Ошеломляет, да?

В результате у меня выработалась привычка конвертировать Jupyter-ноутбуки в .py на каждой вехе, попутно проводя рефакторинг. Существуют и другие инструменты для решения этой проблемы, такие как nbdime, reviewNB и jupytext.

Кроме того, мой друг Yi Xiang недавно написал классный пост о том, как писать файлы .py и запускать их как псевдо-Jupyter-ноутбуки в Docker. Это ещё один отличный способ обойти проблему контроля версий.

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

Экономия времени (в долгосрочной перспективе): Память быстро деградирует, и вскоре вы не будете помнить того, чего не будете помнить. Ваше будущее «я» поблагодарит вас за сэкономленные усилия при попытке разобраться в обоснованиях, методологии и результатах. Передача знаний: команда сможет продолжить работу над проектом в ваше отсутствие (и вас не дёрнут пейджером во время отпускной сиесты в Гранаде). Новые идеи и сотрудничество: возникают новые идеи и возможности для сотрудничества по применению вашей работы к другим сценариям (см. 👉 ниже). Вовлечение сообщества: сообщество учится на вашем опыте (и ошибках). Это помогает брендингу и рекрутингу вашей команды, а также вашему личному профилю.

Одним из моих первых проектов было создание классификатора товаров для e-commerce платформы. Цель состояла в том, чтобы автоматически классифицировать сотни тысяч новых товаров, добавляемых ежедневно.

За пару месяцев был разработан MVP (top-3 точность 95%) и выведен в продакшен. Затем я потратил некоторое время на создание простого пользовательского интерфейса (похожего на этот) и написал о нём в нашу внутреннюю data science рассылку.

A simple user interface for our product classifier

Никто не попробовал команды curl. Но когда мы поделились UI, наш демо-сервер упал. 🤷‍♂️

Мы не ожидали такого положительного отклика. Команда поиска захотела вместе поработать над классификатором поискового намерения: по поисковому запросу — какие категории товаров наиболее релевантны? Команда отзывов о товарах хотела помощи в классификации отзывов: какие отзывы стоит одобрить? Какие отклонить и по каким причинам (например, нецензурная лексика, личные данные, спам и т. д.)?

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

Это третья часть (после) трёхчастной серии о практиках data science проектов. См. также часть 1 (до) и часть 2 (во время).

Применимы ли эти практики ко мне?

Это может быть к вам неприменимо, если:

Вы работаете над data science проектами однопоточно, от задачи к исследованию и решению, за пару месяцев. Вы дисциплинированно проводите рефакторинг и подчищаете свой код, поддерживая его DRY. Вы последовательно документируете свою работу (например, обоснования, методологию, результаты и т. д.) так, чтобы другие могли воспроизвести результаты.

Если вы делаете всё вышеперечисленное — браво! Можете сразу перейти к последнему шагу. В противном случае — читайте дальше.

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

Сделайте свою работу воспроизводимой при каждом запуске, всегда

Помните, как вы возвращались к проекту (несколько месяцев спустя), запускали код и получали те же результаты снова? Вот и я нет.

Однажды мне пришлось подхватить проект, сделанный кем-то другим (кто покинул организацию ещё до моего прихода). Результаты проекта (то есть метрики машинного обучения) уже были представлены и зафиксированы для клиента — но я не мог их #$^!@% воспроизвести. Последовали дни и недели выяснения того, какую перестановку ноутбуков запускать в каком магическом порядке — никому не должно приходиться через это проходить.

Слишком легко наплодить копий Jupyter-ноутбуков, что приводит к ноутбучному аду.

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

«Всегда пишите код так, как будто сопровождать его в итоге будет склонный к насилию психопат, который знает, где вы живёте» — John Woods

Всё начинается со скрипта для воспроизведения вашего окружения кода. Я использую Makefile; запуск make setup создаст виртуальное окружение python и установит необходимые зависимости.

setup: python -m venv .venv && . .venv/bin/activate pip install --upgrade pip pip install -r requirements.dev pip install -r requirements.prod

Затем у меня есть скрипт, чтобы запустить код или ноутбуки сквозным образом, в правильной последовательности (см. 👉 ниже). Один из шагов должен включать разбиение на train-validation. Финальный шаг должен оценивать и сравнивать метрики модели на валидационном наборе — метрики оценки должны быть идентичными при каждом запуске.

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

Если ваш пайплайн может работать на одной машине, создайте для него docker-образ — это позволит поднимать свежее, чистое окружение при каждом запуске. (Если нет, запускайте пайплайн на кластере spot instance.) Docker-контейнер настроит окружение и запустит скрипты, выбросив ошибку, если результаты будут отличаться.

Не забудьте предоставить README о том, как запускать ваш пайплайн и проверять результаты. Попросите одного-двух коллег по команде проверить воспроизводимость.

Нам понадобится несколько дополнительных скриптов, чтобы настроить Docker-контейнер для запуска наших ноутбуков. Сначала — простой shell-скрипт, который запускает ноутбуки по порядку. Он должен выполнять и обновлять ноутбуки с выводом, позволяя нам просматривать результаты в удобное время.

jupyter nbconvert --ExecutePreprocessor.timeout=-1 --execute --inplace --to notebook notebooks/1-data-prep.ipynb jupyter nbconvert --ExecutePreprocessor.timeout=-1 --execute --inplace --to notebook notebooks/2-feature-engineering.ipynb jupyter nbconvert --ExecutePreprocessor.timeout=-1 --execute --inplace --to notebook notebooks/2b-data-visualizations.ipynb jupyter nbconvert --ExecutePreprocessor.timeout=-1 --execute --inplace --to notebook notebooks/3-train-val-split.ipynb jupyter nbconvert --ExecutePreprocessor.timeout=-1 --execute --inplace --to notebook notebooks/4-train-model.ipynb

Затем — Dockerfile, который собирает наш образ с необходимыми зависимостями python. Здесь я использую простой requirements.txt.

FROM python:3.8 LABEL maintainer='eugeneyan <[email protected]>' WORKDIR /poc-docker-template COPY ./requirements.txt /poc-docker-template/ # Install python requirements RUN pip install -r requirements.txt

С этим сборка Docker-образа и сквозной запуск Jupyter-ноутбуков сводятся просто к:

# Build the container and tag it as 'poc-docker-template' docker build --tag poc-docker-template . # Run the container and the script 'run.sh' docker run --rm -v $(PWD):/poc-docker-template --name tmp -t poc-docker-template /bin/bash run.sh

Это монтирует нашу локальную директорию проекта в контейнер через -v $(PWD):/poc-docker-template. Таким образом, хотя наши ноутбуки (в директории проекта) запускаются в контейнере, обновления отразятся локально. Думайте об этом как об (одноразовом) виртуальном окружении, включающем операционную систему.

Подробнее смотрите в этом GitHub-репозитории. Попробуйте сами.

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

Документируйте всё, особенно то, чего нет в коде

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

Поэтому документация важна. Я склонен писать её как статью для отраслевой конференции / прикладную научную работу. Она должна охватывать:

Мотивация: почему эта проблема или возможность важна? Какова оценочная выгода (например, улучшение клиентского опыта, рост выручки, экономия затрат)? Обзор литературы: как другие пытались решить эту проблему? Что сработало (и не сработало)? Как эти подходы определили нашу дорожную карту? Данные: каков наш источник данных? Какая у них схема? Каковы их особенности и недостатки? Какой временной период мы использовали? Методология: как мы очищали данные и создавали признаки? Какие техники машинного обучения мы пробовали? О чём говорит анализ (например, кривые обучения, компромиссы)? Как мы оценивали подходы (например, ML-метрики, задержка инференса, ограничения по ресурсам)? Результаты: каковы были результаты офлайн-валидации? Если проводились A/B-тесты, каковы их итоги? Каковы наш анализ и интерпретация? Следующие шаги: как можно улучшить существующую реализацию? Какие идеи кажутся наиболее перспективными при наименьших усилиях?

«Документация как секс: когда она хороша — она очень, очень хороша; а когда плоха — всё равно лучше, чем ничего.» — Dick Brandon

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

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

Документацию (вероятно, это word-документ или wiki) затем можно поделиться с командой для передачи знаний и обратной связи. Вместе с рабочим кодом кто-то другой сможет подхватить с того места, где вы остановились, повышая bus factor проекта.

Не будьте тем человеком, который написал кучу кода и ушёл.️

Не держите свою отличную работу при себе — делитесь ею

Жаль держать работу при себе или в пределах своей команды. Есть множество площадок, где можно ею поделиться: (внутренние) демо, конференции, митапы и техноблоги (как рабочие, так и личные).

Это не требует больших дополнительных усилий — просто выберите релевантные разделы из вашей документации и подстройте их под разные аудитории, такие как:

Внутренние стейкхолдеры: у них есть бизнес-контекст и мотивация, и они хотят сосредоточиться больше на результатах (читай: 💰💰💰). Не нагружайте техническими деталями. Они будут спрашивать: «Чем это поможет мне?» Практики: у них есть технические знания, и им интересны ваше исследование, методология, реализация и (неудачные) результаты экспериментов. Смело углубляйтесь в детали. Они будут спрашивать: «Как мне это воспроизвести?» Продуктовые и бизнес-лидеры: им больше интересен общий обзор, и они сосредоточены на сценариях использования и результатах. Они будут спрашивать: «Как мне применить это к моему продукту/организации?»

Меня всегда удивляют выгоды от того, что делишься своими усилиями, как рабочими, так и личными. Во-первых, есть огромное удовлетворение от обмена с сообществом, и оно часто благодарно. Это помогает индустрии и сообществу учиться на вашем опыте и неудачах и расти.

Знание, которым поделились = Знание в квадрате

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

Наконец, это ещё и отличный способ выстроить своё присутствие и отношения с единомышленниками-практиками. Я завёл много друзей, делясь своей работой онлайн и на митапах. (Если вы подумываете выступить с докладом по data science, вот семь советов, как сделать его крутым).

Эти практики окупаются многократно

«Ого, это похоже на кучу усилий», — думаете вы.

Да, эти follow-up практики действительно занимают время (примерно неделю или две, в зависимости от масштаба проекта). Однако долгосрочные выгоды намного перевешивают усилия — поверьте мне на слово и просто попробуйте хотя бы раз, пожалуйста.

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

Помните, как вы возвращались к проекту (несколько месяцев спустя), запускали код и получали те же результаты снова? Вот и я нет. Код первой итерации деградирует слишком быстро. Кроме того, есть много выгоды от обмена своей работой. Вот что сработало для меня👇 https://t.co/r8WpA7KXP1— Eugene Yan (@eugeneyan) 22 июля 2020

Спасибо Yang Xinyi и Tyler Wince за чтение черновиков.

Если вы нашли это полезным, пожалуйста, цитируйте эту заметку так:

Yan, Ziyou. (Jul 2020). Why You Need to Follow Up After Your Data Science Project. eugeneyan.com. https://eugeneyan.com/writing/why-you-need-to-follow-up-after-your-data-science-project/.

или

@article{yan2020follow, title = {Why You Need to Follow Up After Your Data Science Project}, author = {Yan, Ziyou}, journal = {eugeneyan.com}, year = {2020}, month = {Jul}, url = {https://eugeneyan.com/writing/why-you-need-to-follow-up-after-your-data-science-project/} }



Присоединяйтесь к 11 800+ читателям, получающим обновления о машинном обучении, RecSys, LLM и инженерии.