2015-08-24 6 views
26

Блокнот Jupyter (iPython) заслуженно известен как хороший инструмент для прототипирования кода и интерактивного использования всех видов машинного обучения. Но когда я использую его, я неизбежно столкнуться следующее:Рекомендации по превращению ноутбуков jupyter в скрипты python

  • ноутбук быстро становится слишком сложным и запутанна, чтобы сохранить и улучшить далее как ноутбук, и я должен сделать питон сценарии из него;
  • Когда дело доходит до производственного кода (например, тот, который нужно повторно запускать каждый день), ноутбук снова не самый лучший формат.

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

  1. Просто конвертировать .ipynb в .py и, с небольшими изменениями, жесткий код всех трубопроводов из записной книжки в один питон скрипт.

    • '+': быстрый
    • '-': грязный, не гибкий, не удобно поддерживать
  2. Сделать один сценарий со многими функциями (примерно, 1 функции для каждого из них или две ячейки), пытаясь включить этапы трубопровода с отдельными функциями и назовите их соответственно. Затем укажите все параметры и глобальные константы через argparse.

    • '+': более гибкое использование; более читаемый код (если вы правильно трансформировали логику конвейера в функции)
    • '-': часто трубопровод НЕ расщепляется на логически завершенные части, которые могут стать функциями без каких-либо причуд в коде. Все эти функции, как правило, необходимо вызывать только один раз в скрипте, а не много раз называть внутри циклов, карт и т. Д. Кроме того, каждая функция обычно выводит выходные данные всех функций, называемых ранее, поэтому приходится передавать много аргументов каждому функция.
  3. То же самое, что и пункт (2), но теперь оберните все функции внутри класса. Теперь все глобальные константы, а также выходы каждого метода могут быть сохранены как атрибуты класса.

    • «+»: вам не нужно пройти много аргументов для каждого метода - все предыдущие выходы уже хранятся в виде атрибутов
    • «-»: общая логика задачи по-прежнему не учитываются - это конвейер данных и машинного обучения, а не только класс. Единственная цель для класса должна быть создана, вызывать все методы последовательно один за другим, а затем удаляться. Кроме того, классы довольно долго реализуются.
  4. Преобразование ноутбука в модуль python с несколькими скриптами. Я не пробовал это, но я подозреваю, что это самый длинный способ справиться с этой проблемой.

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

Народ, пожалуйста, поделитесь своими идеями и опытом. Вы когда-нибудь сталкивались с этой проблемой? Как вы справились с этим?

+0

Вы хотите извлечь код python из файла Notebook? – kxxoling

+0

Я делал это пару раз - это как раз то, что я упоминаю в пункте (1). У этого есть некоторые недостатки. Во-первых, негибкий жесткий код. Во-вторых, как правило, вы не хотите выполнять каждую ячейку в ноутбуке один за другим (может быть много чисто визуализации или просто лишних ячеек), поэтому вам все равно нужно очистить код после экспорта - такой же объем работы, как если бы вы просто скопировали вложенные ячейки вручную. – kurtosis

+0

Вы можете написать сценарий для извлечения всего кода Python вместо ручного. Это то, что вы хотите? – kxxoling

ответ

8

У нас есть аналогичная проблема. Однако мы используем несколько ноутбуков для прототипирования результатов, которые должны стать также несколькими скриптами python.

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

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

Больше всего мы не боимся рефакторинга :)

+0

Это звучит как хороший подход: кажется, невозможно сделать рефакторинг непосредственно внутри ноутбука - будь то ipython/jupyter, zeppelin, spark-notebook .. что угодно. Это шоу-шоу. Поэтому ваша характеристика ноутбука как «конфигурации» является дополнительным аспектом для моего рассмотрения, что это инструмент презентации, но не один из них. – javadba

3

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

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

Базовый пример содержимого ячейки с «минимальными» испытаний и строки документации:

def zip_count(f): 
    """Given zip filename, returns number of files inside. 

    str -> int""" 
    from contextlib import closing 
    with closing(zipfile.ZipFile(f)) as archive: 
     num_files = len(archive.infolist()) 
    return num_files 

zip_filename = 'data/myfile.zip' 

# Make sure `myfile` always has three files 
assert zip_count(zip_filename) == 3 
# And total zip size is under 2 MB 
assert os.path.getsize(zip_filename)/1024**2 < 2 

print(zip_count(zip_filename)) 

После того, как вы экспортировали его оголить .py файлы, ваш код будет, вероятно, не может быть структурирована на классы еще. Но стоит потратить усилия на то, чтобы отредактировать ваш ноутбук до такой степени, что он имеет набор документированных функций, каждый из которых имеет набор простых операторов assert, которые можно легко переместить в tests.py для тестирования с pytest, unittest или что у вас есть. Если это имеет смысл, сложение этих функций в методы для ваших классов мертво-легко после этого.

Если все идет хорошо, все, что вам нужно сделать после этого, - написать if __name__ == '__main__': и его «крючки»: если вы пишете сценарий, который вызывается терминалом, вам нужно будет handle command-line arguments, если вы написав модуль, который вы хотите подумать о its API with the __init__.py file и т. д.

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

Вот несколько идей для рабочего процесса ноутбук-на-скрипт:

  1. Экспорт Jupyter ноутбуков в файл Python (.py) через графический интерфейс.
  2. Удалите «вспомогательные» линии, которые не выполняют фактическую работу: print заявления, графики и т. Д.
  3. Если необходимо, объедините свою логику в классы. Единственная дополнительная работа по рефакторингу должна заключаться в том, чтобы написать ваши докстры и атрибуты вашего класса.
  4. Напишите входные данные вашего сценария с помощью if __name__ == '__main__'.
  5. Отделите свои assert инструкций для каждой из ваших функций/методов и внесите минимальный набор тестов в tests.py.