DS в реальном мире

Как провести рефакторинг записной книжки Jupyter

Улучшите свою кодовую базу и станьте более продуктивными с помощью этих методов

В мире машинного обучения код может быстро запутаться.

То, что начинается как отличная модель машинного обучения, легко превращается в большой кусок кода, который трудно понять. Изменение кода становится болезненным и подверженным ошибкам, и практикующим ML становится все труднее развивать свои ML-решения для удовлетворения новых {бизнес-требований, стратегий разработки функций, данных}.

В этой статье я поделюсь с вами своим процессом рефакторинга записной книжки Jupyter и покажу вам, как я перевожу ее из неподдерживаемого состояния в {читаемое, проверенное, поддерживаемое} состояние. Когда наша кодовая база будет всесторонне протестирована и станет понятной, будет намного проще расширять и развивать наше решение машинного обучения.

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

1. Шесть подготовительных шагов, позволяющих провести рефакторинг.

Рефакторинг - это изменение кода для облегчения понимания и модификации без изменения его наблюдаемого поведения. (Перефразировано из Рефакторинга - Мартин Фаулер)

Код не всегда можно отредактировать.

Долгое время я смотрел на свои записные книжки Jupyter и думал, как бы его улучшить. Я знаю, что мне нужно писать тесты и рефакторинг кода. Но есть некоторые валуны, мешающие мне сделать первый шаг: (i) страх, что я могу что-то сломать, (ii) страх, что я могу удалить код, который нужен кому-то другому, (iii) громоздкая механика рефакторинга в записных книжках Jupyter (например, попробуйте переименование переменной).

Дважды проведя этот семинар по рефакторингу, я обнаружил шесть подготовительных шагов, которые включают и ускоряют рефакторинг:

  1. Запустите блокнот от начала до конца и убедитесь, что все работает.
  • Это избавит вас от ненужной боли, связанной с необходимостью выяснять, сломали ли мы что-то во время рефакторинга или код уже был сломан.

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. Что мы получили за все эти неприятности?

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

Комбинация автоматических тестов и рефакторинга может во многом помочь нам:

  1. Сокращение циклов обратной связи. Благодаря автоматизированным тестам вы теперь можете сразу узнавать о появлении ошибок и ошибок. Если охват тестированием является исчерпывающим, это также придаст вам уверенности в том, что все в порядке, и сэкономит ваше время от ручного тестирования всего ноутбука Jupyter.
  2. Сокращение отходов. С помощью тестов и модульных функций вы можете уменьшить усилия, затрачиваемые на (i) чтение деталей реализации, которые не имеют отношения к вашей задаче, (ii) удерживание всей записной книжки Jupyter в нашей голове, даже если мы просто хотели изменить одну простую вещь, (iii ) исправление ошибок, которые мы случайно ввели вчера, и (iv) [вставьте то, из-за чего вы часами смотрели в свой блокнот].
  3. Увеличение потока. Все это означает, что вы можете сосредоточиться на поставленной задаче (например, интегрировать новый набор функций) и предоставить ценность вместо утомительных, расточительных задач, упомянутых выше 😎

Спасибо, что дочитали до этого места! Надеюсь, это было для вас полезно 🚀🚀🚀

Чтобы увидеть практический пример того, как я реорганизую блокнот Jupyter, просмотрите эту демонстрацию!

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