Разработка программного обеспечения для науки о данных

О мифах и проблемах ноутбуков Jupyter

Вы можете управлять версиями, тестировать и объединять ноутбуки в модули с помощью текущих инструментов. Давайте обсудим настоящие проблемы.

Блокноты Jupyter, вы их любите или ненавидите. Использование (и неправильное использование) блокнотов Jupyter — одна из самых спорных тем в сообществе данных. Конечно, есть веские причины избегать блокнотов, но хотелось бы, чтобы разговор был сосредоточен на реальных проблемах, а не на повторном обсуждении уже решенных вопросов. В этом сообщении блога я обсуждаю наиболее распространенные мифы о ноутбуках и комментирую критические нерешенные проблемы.

«Вы не можете контролировать версии блокнотов»

Как правило, записные книжки представляют собой .ipynb файлы. Под капотом файлы .ipynb представляют собой файлы JSON с предопределенной схемой, и они сохраняют код и выходные данные в одном файле. Автономные блокноты удобны: вы можете работать в блокноте, сохранить его, вернуться к нему завтра, и результаты будут там. Предостережение в том, что ими сложно управлять с помощью git. Во-первых, файлы .ipynb увеличивают размер репозитория git, а во-вторых, git diff (и GitHub Pull Requests) не будут работать. Вот так выглядит представление различий для блокнота на GitHub:

К счастью, мы можем легко это исправить. Существует официальное расширение JupyerLab, которое интегрирует git прямо в интерфейс Jupyter, позволяя вам (среди прочего) различать блокноты. Вот как это выглядит:

Вы можете видеть, что он четко показывает разницу, текущая версия на git имеет график с красными границами, а новая — с зелеными.

Другой вариант — использовать nbdime, который позволяет делать то же самое из терминала (на самом деле расширение JupyterLab использует nbdime под капотом).

Третий вариант (и мой любимый!) — Jupytext. Этот пакет позволяет открывать .py файлов как записные книжки. Таким образом, вы можете редактировать свой код в интерактивном режиме, но после сохранения он сохранит файл .py.

При использовании Jupytext вы можете использовать git diff и запросы на вытягивание, поскольку ваши блокноты представляют собой простые сценарии. Основное предостережение заключается в том, что выходные данные теряются после закрытия файла, но вы можете использовать функцию сопряжения Jupytext, которая сохраняет результаты в отдельном файле .ipynb, эффективно сохраняя исходный код и выводя два разных файла.

«Нельзя тестировать ноутбуки»

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

Более простой альтернативой является запуск дымового теста (т. е. проверка работы записной книжки, но без проверки вывода). Вы можете написать подобный скрипт для выполнения в вашей системе CI (например, GitHub Actions):

Наконец, вас может заинтересовать модульное тестирование частей записной книжки (например, функции, определенной внутри записной книжки). Я рекомендую определять функции вне блокнота и импортировать их в блокнот. Таким образом, вы можете выполнять модульное тестирование функций так же, как и любую другую функцию. Однако, если вы хотите написать функцию внутри файла .ipynb, вы можете использовать testbook.

Testbook позволяет извлекать определения из файла .ipynb и тестировать их:

«Вы не можете разделить ноутбуки на модули»

Еще одна критика заключается в том, что вы не можете разделить ноутбуки на модули. Впрочем, с Плумбером все просто. Допустим, у вас есть три блокнота ( load.ipynb, clean.ipynb и plot.ipynb), вы можете создать конвейер, который выполняет их в следующем порядке:

Затем вы можете запустить их с помощью:

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

Попробуйте!

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

Итак, каковы настоящие проблемы?

Скрытое состояние

Учитывая блокнот, мы говорим, что он имеет скрытое состояние, когда его выполнение линейно возвращает выходные данные, отличные от сохраненных. Например, левый блокнот не имеет скрытого состояния, потому что если вы перезапустите ядро ​​и запустите все ячейки по порядку, вы получите те же результаты (число 3). Но правый блокнот имеет скрытое состояние: если мы перезапустим ядро ​​и запустим все ячейки по порядку, окончательный вывод не совпадет (записано 42, но мы получим 3). Эта проблема настолько распространена, что о ней даже есть запись в блоге Nature. Скрытый делает невозможным воспроизведение наших результатов.

Мы можем частично решить эту проблему с помощью тестирования: мы можем выполнять наши блокноты линейно на каждом git push, чтобы обеспечить воспроизводимые результаты. Однако это не решает проблему полностью, так как мы все еще можем получить скрытое состояние во время разработки блокнота и выяснить это, пока не отправим в репозиторий и не сломается CI.

Популярным подходом являются реактивные блокноты, которые автоматически пересчитывают ячейки, чтобы предотвратить скрытое состояние. Например, скажем, у меня есть такой блокнот:

Если я запускаю реактивный блокнот и редактирую ячейку a = 1, блокнот автоматически запускает третью и четвертую ячейки (total = a + b и total), поскольку они зависят от значения a, эффективно обновляя и печатая новое значение переменной total . Реактивность — удобная функция, уже доступная в Pluto, системе ноутбуков для Джулии, а также в некоторых коммерческих дистрибутивах Jupyter. К счастью, люди уже работают над решением с открытым исходным кодом для реактивных ядер в Jupyter.

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

Качество кода

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

Многие утверждают, что блокноты приводят к плохому качеству кода. Это правда? Я так не думаю. Некачественный код существует везде; это не эксклюзивная проблема Jupyter. Я считаю, что в ноутбуках так много трудночитаемого кода, потому что Jupyter демократизировал вычисления. Вам больше не нужно осваивать IDE и терминал для разработки кода анализа данных; Вы можете открыть блокнот и сразу приступить к работе. Так внезапно у нас появилось много людей, не связанных с программным обеспечением, которые работают учеными данных во всех отраслях, и это фантастическая вещь. Каждый должен иметь возможность кодировать и создавать ценность, и Jupyter — это входная дверь для многих людей в мир вычислений.

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

Заключительные мысли

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

Первоначально опубликовано на ploomber.io