DS в реальном мире
Как провести рефакторинг записной книжки Jupyter
Улучшите свою кодовую базу и станьте более продуктивными с помощью этих методов
В мире машинного обучения код может быстро запутаться.
То, что начинается как отличная модель машинного обучения, легко превращается в большой кусок кода, который трудно понять. Изменение кода становится болезненным и подверженным ошибкам, и практикующим ML становится все труднее развивать свои ML-решения для удовлетворения новых {бизнес-требований, стратегий разработки функций, данных}.
В этой статье я поделюсь с вами своим процессом рефакторинга записной книжки Jupyter и покажу вам, как я перевожу ее из неподдерживаемого состояния в {читаемое, проверенное, поддерживаемое} состояние. Когда наша кодовая база будет всесторонне протестирована и станет понятной, будет намного проще расширять и развивать наше решение машинного обучения.
Примечание. Если вы не уверены в необходимости рефакторинга записных книжек Jupyter, ознакомьтесь с этой статьей 👻
1. Шесть подготовительных шагов, позволяющих провести рефакторинг.
Рефакторинг - это изменение кода для облегчения понимания и модификации без изменения его наблюдаемого поведения. (Перефразировано из Рефакторинга - Мартин Фаулер)
Код не всегда можно отредактировать.
Долгое время я смотрел на свои записные книжки Jupyter и думал, как бы его улучшить. Я знаю, что мне нужно писать тесты и рефакторинг кода. Но есть некоторые валуны, мешающие мне сделать первый шаг: (i) страх, что я могу что-то сломать, (ii) страх, что я могу удалить код, который нужен кому-то другому, (iii) громоздкая механика рефакторинга в записных книжках Jupyter (например, попробуйте переименование переменной).
Дважды проведя этот семинар по рефакторингу, я обнаружил шесть подготовительных шагов, которые включают и ускоряют рефакторинг:
- Запустите блокнот от начала до конца и убедитесь, что все работает.
- Это избавит вас от ненужной боли, связанной с необходимостью выяснять, сломали ли мы что-то во время рефакторинга или код уже был сломан.
2. Сделайте копию оригинальной записной книжки.
- Это удивительно важный шаг. Это освободит нас от любых эмоциональных привязанностей («ммм, я не знаю, кому-то может понадобиться эта диаграмма») и позволит безжалостно очистить любой несущественный код.
- Разделив эти задачи (а именно, преобразование основных данных и представление), мы можем иметь две отдельные вещи, которые хорошо справляются с каждой проблемой, вместо одной гигантской записной книжки, которая одновременно выполняет и то, и другое катастрофическим образом.
3. Преобразуйте записную книжку Jupyter в простой файл Python.
- Это даст вам все преимущества использования IDE (например, автозаполнение, intellisense, встроенная документация, форматирование, автоматическое переименование, линтинг, сочетания клавиш и т. Д.). Это делает ваш рефакторинг более эффективным.
- Команда:
jupyter nbconvert —-to script mynotebook.ipynb
4. Удалите операторы печати, например print(...)
, df.head()
, df.plot(...)
- Это устраняет шум и визуальный беспорядок и значительно упрощает следующий шаг.
5. Прочтите блокнот и перечислите запахи кода.
- Этот список запахов кода, которые вы определяете, становится списком задач в вашем рефакторинге (см. Пример). Это также избавит вас от некоторых умственных ресурсов от постоянных размышлений о том, что делать дальше.
6. Определите границы рефакторинга и добавьте тест характеристики.
- Тест характеризации рассматривает вашу программу как черный ящик и характеризует ее поведение (например, мой ноутбук выводит модель с показателем точности 68%) и утверждает эту характеристику (т.е. тест не проходит, если мы запустим наш код и получите модель с показателем точности менее 68%)
- Это, пожалуй, самый важный шаг!
- Тест характеризации даст вам быструю обратную связь, потому что он может выполняться непрерывно по мере выполнения рефакторинга. Если вы случайно внесете критические изменения, он сообщит вам в течение нескольких секунд.
- Без характеристического теста вам пришлось бы вручную перезапускать и повторно запускать весь блокнот Jupyter так часто, что является громоздким, сильно нарушающим ваш поток, и, следовательно, 2019.
- Этот шаг немного сложно объяснить письменными словами, поэтому я записал эту демонстрацию, чтобы показать вам, как определить границы рефакторинга и написать тест характеристики, чтобы включить ваш рефакторинг.
2. Цикл рефакторинга (ура!)
В цикле рефакторинга мы постепенно и итеративно улучшаем наш код путем (i) добавления модульных тестов и (ii) абстрагирования сложных деталей реализации в модульные и читаемые функции.
Цикл рефакторинга выглядит следующим образом:
1. Определите блок кода, который можно извлечь в чистую функцию (т. Е. Функцию, которая возвращает точно такие же выходные данные для заданного ввода, независимо от того, когда и где она выполняется).
2. Напишите модульный тест. (см. демо)
- Запустите модульные тесты в режиме просмотра: например,
nosetests -—with-watch —-rednose
- Напишите модульный тест для блока кода
3. Сделайте тест пройденным.
- Определите новую функцию и поместите ее в новый модуль / файл Python (или в существующий, если в вашем коде есть подходящий).
- Перенести существующую реализацию из записной книжки в эту функцию
- Пройдите неудачный тест
4. В записной книжке замените исходный кодовый блок новой определенной функцией.
5. Убедитесь, что тесты для определения характеристик все еще проходят.
6. Зафиксируйте свои изменения в git.
Теперь, если вы чувствуете, что код, который вы только что извлекли, можно было бы еще улучшить, вы можете провести его дальнейший рефакторинг с помощью подстраховки вашего нового модульного теста.
В противном случае вы можете повторить цикл рефакторинга для другого блока кода в записной книжке Jupyter и повторять до тех пор, пока кодовая база не будет всесторонне протестирована и преобразована в удобное для чтения и поддерживаемое состояние.
3. Что мы получили за все эти неприятности?
Вкратце, вы можете перейти от грязной, трудно читаемой записной книжки к протестированной и модульной кодовой базе. 🎉🎉🎉
Комбинация автоматических тестов и рефакторинга может во многом помочь нам:
- Сокращение циклов обратной связи. Благодаря автоматизированным тестам вы теперь можете сразу узнавать о появлении ошибок и ошибок. Если охват тестированием является исчерпывающим, это также придаст вам уверенности в том, что все в порядке, и сэкономит ваше время от ручного тестирования всего ноутбука Jupyter.
- Сокращение отходов. С помощью тестов и модульных функций вы можете уменьшить усилия, затрачиваемые на (i) чтение деталей реализации, которые не имеют отношения к вашей задаче, (ii) удерживание всей записной книжки Jupyter в нашей голове, даже если мы просто хотели изменить одну простую вещь, (iii ) исправление ошибок, которые мы случайно ввели вчера, и (iv) [вставьте то, из-за чего вы часами смотрели в свой блокнот].
- Увеличение потока. Все это означает, что вы можете сосредоточиться на поставленной задаче (например, интегрировать новый набор функций) и предоставить ценность вместо утомительных, расточительных задач, упомянутых выше 😎
Спасибо, что дочитали до этого места! Надеюсь, это было для вас полезно 🚀🚀🚀
Чтобы увидеть практический пример того, как я реорганизую блокнот Jupyter, просмотрите эту демонстрацию!
Это часть серии руководств Привычки программирования для специалистов по анализу данных, цель которых - помочь специалистам по данным стать более продуктивными за счет изучения хороших навыков программирования.