Jupyter Notebook – это крайне удобный инструмент для создания красивых аналитических отчетов, так как он позволяет хранить вместе код, изображения, комментарии, формулы и графики:

Ниже мы расскажем о некоторых фишках, которые делают Jupyter очень крутым. О них можно прочитать и в других местах, но если специально не задаваться этим вопросом, то никогда и не прочитаешь.

Jupyter поддерживает множество языков программирования и может быть легко запущен на любом сервере, необходим только доступ по ssh или http. К тому же это свободное ПО.

Основы


Список хоткеев вы найдете в Help > Keyboard Shortcuts (список периодически дополняется, так что не стесняйтесь заглядывать туда снова).

Отсюда можно получить представление о взаимодействии с блокнотом (notebook). Если вы будете постоянно работать c Jupyter, большинство комбинаций вы быстро выучите.

Например,

  • Esc + F позволит найти и заменить только в коде, не учитывая вывод;
  • Esc + O — переключиться на вывод ячейки;
  • Можно выбрать сразу несколько ячеек и удалить/скопировать/вырезать/вставить. Это полезно при необходимости перемещать части блокнота.




Экспорт блокнота


Простейший способ — сохранить блокнот в формате IPython Notebook (.ipynb), но так как их используют не все, есть и другие варианты:

  • Преобразовать блокнот в html-файл;
  • Опубликовать его в gists, который умеет обрабатывать файлы этого формата (см. пример);
  • Сохранить ваш блокнот, например, в dropbox, а затем открыть ссылку в nbviewer;
  • Блокноты умеет открывать github (есть некоторые ограничения, но в большинстве случаев работает), что очень полезно, так как позволяет хранить историю исследования (если исследование доступно широкой публике).

 

Построение графиков


Есть несколько вариантов построения графиков:

  • matplotlib (фактически, стардарт), включается командой %matplotlib inline;
  • %matplotlib notebook — интерактивный режим, но работает очень медленно, так как обработка графика происходит на стороне сервера;
  • mpld3 — альтернативная библиотека визуализации (использующая D3) для matplotlib. Она довольно хороша, хотя и неполна.
  • bokeh лучше подходит для построения интерактивных графиков;
  • plot.ly строит красивые графики, но это будет стоить денег.




Magic-команды


Магические команды (magics) превращают обычный python в магический python. Magic-команды — это ключ к могуществу IPython’а.

# list available python magics
%lsmagic

 

Available line magics:
%alias  %alias_magic  %autocall  %automagic  %autosave  %bookmark  %cat  %cd  %clear  %colors  %config  %connect_info  %cp  %debug  %dhist  %dirs  %doctest_mode  %ed  %edit  %env  %gui  %hist  %history  %killbgscripts  %ldir  %less  %lf  %lk  %ll  %load  %load_ext  %loadpy  %logoff  %logon  %logstart  %logstate  %logstop  %ls  %lsmagic  %lx  %macro  %magic  %man  %matplotlib  %mkdir  %more  %mv  %notebook  %page  %pastebin  %pdb  %pdef  %pdoc  %pfile  %pinfo  %pinfo2  %popd  %pprint  %precision  %profile  %prun  %psearch  %psource  %pushd  %pwd  %pycat  %pylab  %qtconsole  %quickref  %recall  %rehashx  %reload_ext  %rep  %rerun  %reset  %reset_selective  %rm  %rmdir  %run  %save  %sc  %set_env  %store  %sx  %system  %tb  %time  %timeit  %unalias  %unload_ext  %who  %who_ls  %whos  %xdel  %xmode

Available cell magics:
%%!  %%HTML  %%SVG  %%bash  %%capture  %%debug  %%file  %%html  %%javascript  %%js  %%latex  %%perl  %%prun  %%pypy  %%python  %%python2  %%python3  %%ruby  %%script  %%sh  %%svg  %%sx  %%system  %%time  %%timeit  %%writefile

Automagic is ON, % prefix IS NOT needed for line magics.

 

%env


Можно управлять переменными среды для вашего блокнота без перезапуска Jupyter-сервера. Некоторые библиотеки (такие, как theano) используют переменные среды, чтобы контролировать поведение, и %env — самый удобный способ.

#%env - without arguments lists environmental variables
%env OMP_NUM_THREADS=4

 

env: OMP_NUM_THREADS=4

 

Выполнение shell-команд


В Notebook можно вызвать любую shell-команду. Это особенно удобно для управления виртуальной средой.

!pip install numpy
!pip list | grep Theano

 

Requirement already satisfied (use --upgrade to upgrade): numpy in /Users/axelr/.venvs/rep/lib/python2.7/site-packages
Theano (0.8.2)

 

Подавление вывода последней строки


Иногда вывод не нужен, и в этом случае можно или использовать команду pass с новой строки, или поставить точку запятой в конце строки:

%matplotlib inline
from matplotlib import pyplot as plt
import numpy

 

# if you don't put semicolon at the end, you'll have output of function printed
plt.hist(numpy.linspace(0, 1, 1000)**1.5);




Просмотр исходников функций/классов/чего угодно с помощью вопросительного знака (?, ??)

 

from sklearn.cross_validation import train_test_split
# show the sources of train_test_split function in the pop-up window
train_test_split??

 

# you can use ? to get details about magics, for instance:
%pycat?


вызовет следующее всплывающее окно:

Show a syntax-highlighted file through a pager.

This magic is similar to the cat utility, but it will assume the file
to be Python source and will show it with syntax highlighting.

This magic command can either take a local filename, an url,
an history range (see %history) or a macro as argument ::

%pycat myscript.py
%pycat 7-27
%pycat myMacro
%pycat http://www.example.com/myscript.py

 

Используйте %run для выполнения кода на Python


%run может выполнить код на языке Python из файлов с расширением .py — это поведение хорошо задокументировано.

Но эта команда может выполнять и другие блокноты из Jupyter! Иногда это очень полезно.

Обратите внимание, что %run — это не то же, что импорт python-модуля.

# this will execute all the code cells from different notebooks
%run ./2015-09-29-NumpyTipsAndTricks1.ipynb

 

[49 34 49 41 59 45 30 33 34 57]
[172 177 209 197 171 176 209 208 166 151]
[30 33 34 34 41 45 49 49 57 59]
[209 208 177 166 197 176 172 209 151 171]
[1 0 4 8 6 5 2 9 7 3]
['a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j']
['b' 'a' 'e' 'i' 'g' 'f' 'c' 'j' 'h' 'd']
['a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j']
[1 0 6 9 2 5 4 8 3 7]
[1 0 6 9 2 5 4 8 3 7]
[ 0.93551212  0.75079687  0.87495146  0.3344709   0.99628591  0.34355057
  0.90019059  0.88272132  0.67272068  0.24679158]
[8 4 5 1 9 2 7 6 3 0]





[-5 -4 -3 -2 -1  0  1  2  3  4]
[0 0 0 0 0 0 1 2 3 4]
['eh' 'cl' 'ah' ..., 'ab' 'bm' 'ab']
['ab' 'ac' 'ad' 'ae' 'af' 'ag' 'ah' 'ai' 'aj' 'ak' 'al' 'am' 'an' 'bc' 'bd'
 'be' 'bf' 'bg' 'bh' 'bi' 'bj' 'bk' 'bl' 'bm' 'bn' 'cd' 'ce' 'cf' 'cg' 'ch'
 'ci' 'cj' 'ck' 'cl' 'cm' 'cn' 'de' 'df' 'dg' 'dh' 'di' 'dj' 'dk' 'dl' 'dm'
 'dn' 'ef' 'eg' 'eh' 'ei' 'ej' 'ek' 'el' 'em' 'en' 'fg' 'fh' 'fi' 'fj' 'fk'
 'fl' 'fm' 'fn' 'gh' 'gi' 'gj' 'gk' 'gl' 'gm' 'gn' 'hi' 'hj' 'hk' 'hl' 'hm'
 'hn' 'ij' 'ik' 'il' 'im' 'in' 'jk' 'jl' 'jm' 'jn' 'kl' 'km' 'kn' 'lm' 'ln'
 'mn']
[48 33  6 ...,  0 23  0]
['eh' 'cl' 'ah' ..., 'ab' 'bm' 'ab']
['eh' 'cl' 'ah' ..., 'ab' 'bm' 'ab']
['bf' 'cl' 'dn' ..., 'dm' 'cn' 'dj']
['bf' 'cl' 'dn' ..., 'dm' 'cn' 'dj']



[ 2.29711325  1.82679746  2.65173344 ...,  2.15286813  2.308737    2.15286813]
1000 loops, best of 3: 1.09 ms per loop
The slowest run took 8.44 times longer than the fastest. This could mean that an intermediate result is being cached.
10000 loops, best of 3: 21.5 µs per loop


0.416
0.416

 

%load


Загрузит код напрямую в ячейку. Можно выбрать файл локально или из сети.

Если раскомментировать и выполнить код ниже, содержание ячейки заменится на содержание файла.

# %load http://matplotlib.org/mpl_examples/pylab_examples/contour_demo.py

 

%store — ленивая передача данных между блокнотами

 

data = 'this is the string I want to pass to different notebook'
%store data
del data # deleted variable

 

Stored 'data' (str)

 

# in second notebook I will use:
%store -r data
print data

 

this is the string I want to pass to different notebook

 

%who для анализа переменных глобального пространства имен

 

# pring names of string variables
%who str

 

 data 

 

Тайминг


Если вы хотите замерить время выполнения программы или найти узкое место в коде, на помощь придет IPython.

%%time
import time
time.sleep(2) # sleep for two seconds

 

CPU times: user 1.23 ms, sys: 4.82 ms, total: 6.05 ms
Wall time: 2 s

 

# measure small code snippets with timeit !
import numpy
%timeit numpy.random.normal(size=100)

 

The slowest run took 13.85 times longer than the fastest. This could mean that an intermediate result is being cached.
100000 loops, best of 3: 6.35 µs per loop

 

%%writefile pythoncode.py

import numpy
def append_if_not_exists(arr, x):
    if x not in arr:
        arr.append(x)
        
def some_useless_slow_function():
    arr = list()
    for i in range(10000):
        x = numpy.random.randint(0, 10000)
        append_if_not_exists(arr, x)

 

Overwriting pythoncode.py

 

# shows highlighted source of the newly-created file
%pycat pythoncode.py

 

from pythoncode import some_useless_slow_function, append_if_not_exists

 

Профилирование: %prun, %lprun, %mprun

 

# shows how much time program spent in each function
%prun some_useless_slow_function()


Пример вывода:

26338 function calls in 0.713 seconds

   Ordered by: internal time

   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
    10000    0.684    0.000    0.685    0.000 pythoncode.py:3(append_if_not_exists)
    10000    0.014    0.000    0.014    0.000 {method 'randint' of 'mtrand.RandomState' objects}
        1    0.011    0.011    0.713    0.713 pythoncode.py:7(some_useless_slow_function)
        1    0.003    0.003    0.003    0.003 {range}
     6334    0.001    0.000    0.001    0.000 {method 'append' of 'list' objects}
        1    0.000    0.000    0.713    0.713 <string>:1(<module>)
        1    0.000    0.000    0.000    0.000 {method 'disable' of '_lsprof.Profiler' objects}

 

%load_ext memory_profiler

 

# tracking memory consumption (show in the pop-up)
%mprun -f append_if_not_exists some_useless_slow_function()

 

('',)


Пример вывода:

Line #    Mem usage    Increment   Line Contents
================================================
     3     20.6 MiB      0.0 MiB   def append_if_not_exists(arr, x):
     4     20.6 MiB      0.0 MiB       if x not in arr:
     5     20.6 MiB      0.0 MiB           arr.append(x)


%lprun позволяет профилировать с точностью до строк кода, но, кажется, в последнем релизе Python он не работает, так что в этот раз обойдемся без магии:

import line_profiler
lp = line_profiler.LineProfiler()
lp.add_function(some_useless_slow_function)
lp.runctx('some_useless_slow_function()', locals=locals(), globals=globals())
lp.print_stats()

 

Timer unit: 1e-06 s

Total time: 1.27826 s
File: pythoncode.py
Function: some_useless_slow_function at line 7

Line #      Hits         Time  Per Hit   % Time  Line Contents
==============================================================
     7                                           def some_useless_slow_function():
     8         1            5      5.0      0.0      arr = list()
     9     10001        17838      1.8      1.4      for i in range(10000):
    10     10000        38254      3.8      3.0          x = numpy.random.randint(0, 10000)
    11     10000      1222162    122.2     95.6          append_if_not_exists(arr, x)

 

Дебаг с помощью %debug


У Jupyter есть собственный интерфейс для ipdb, что позволяет зайти внутрь функции и посмотреть, что в ней происходит.

Это не PyCharm — потребуется время, чтобы освоить, но при необходимости дебага на сервере это может быть единственным вариантом (кроме pdb через терминал).

#%%debug filename:line_number_for_breakpoint
# Here some code that fails. This will activate interactive context for debugging


Немного более простой способ — команда %pdb, которая активирует дебаггер, когда выбрасывается исключение:

# %pdb

# def pick_and_take():
#     picked = numpy.random.randint(0, 1000)
#     raise NotImplementedError()
    
# pick_and_take()

 

Запись формул в LateX


Маркдаун ячейки могут отрисовывать формулы LateX с помощью MathJax.

P(A|B) = {P(B|A)P(A) \over P(B)}


Маркдаун — важная часть блокнотов, так что не забывайте использовать его выразительные возможности!

Использование разных языков внутри одного блокнота


Если вы соскучились по другим языкам программирования, можете использовать их в Jupyter Notebook:

  • %%python2
  • %%python3
  • %%ruby
  • %%perl
  • %%bash
  • %%R,


но, разумеется, среда должна быть настроена соответствующим образом.

%%ruby
puts 'Hi, this is ruby.'

 

Hi, this is ruby.

 

%%bash
echo 'Hi, this is bash.'

 

Hi, this is bash.

 

Анализ Big Data


Существует несколько решений, чтобы запрашивать/обрабатывать большие объемы данных:

  • ipyparallel (бывший ipython cluster) — хороший инструмент для простых операций map-reduce на Python. Мы используем его в rep для обучения большого количества моделей машинного обучения параллельно.
  • pyspark
  • spark-sql magic %%sql

 

Ваши коллеги могут экспериментировать с вашим кодом, ничего не устанавливая


Такие сервисы, как mybinder, предоставляют доступ к Jupiter Notebook со всеми установленными библиотеками, так что пользователь может с полчаса поиграться с вашим кодом, имея под рукой только браузер.

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

Написание функций на других языках


Иногда скорости NumPy бывает недостаточно, и мне необходимо написать немного быстрого кода. В принципе, можно собрать нужные функции в динамические библиотеки, а затем написать обертку на Python…

Но гораздо лучше, когда скучная часть работы сделана за нас, правда?

Ведь можно написать нужные функции на Cython или Fortran и использовать их напрямую из кода на Python.

Для начала нужно установить модули

!pip install cython fortran-magic

 

%load_ext Cython

 

 %%cython
def myltiply_by_2(float x):
    return 2.0 * x
 

 

myltiply_by_2(23.)

 

 46.0 


Лично я предпочитаю Fortran, на котором, я считаю, удобно писать функции для обработки большого объема численных данных. Подробнее о его использовании можно почитать здесь.

%load_ext fortranmagic

 

/Users/axelr/.venvs/rep/lib/python2.7/site-packages/IPython/utils/path.py:265: UserWarning: get_ipython_cache_dir has moved to the IPython.paths module
  warn("get_ipython_cache_dir has moved to the IPython.paths module")

 

%%fortran
subroutine compute_fortran(x, y, z)
    real, intent(in) :: x(:), y(:)
    real, intent(out) :: z(size(x, 1))

    z = sin(x + y)

end subroutine compute_fortran

 

compute_fortran([1, 2, 3], [4, 5, 6])

 

array([-0.95892429,  0.65698659,  0.41211849], dtype=float32)


Должен заметить, что есть и другие способы ускорить ваш код на Python. Примеры можно найти в моем блокноте.

Множественный курсор


С недавнего времени Jupyter поддерживает множественный курсор, такой, как в Sublime или IntelliJ!


Источник: swanintelligence.com/multi-cursor-in-jupyter.html

Расширения Jupyter-contrib


устанавливаются с помощью

!pip install https://github.com/ipython-contrib/jupyter_contrib_nbextensions/tarball/master
!pip install jupyter_nbextensions_configurator
!jupyter contrib nbextension install --user
!jupyter nbextensions_configurator enable --user




Это целое семейство различных расширений, включая, например, jupyter spell-checker и code-formatter, которых по умолчанию в Jupyter нет.

RISE: презентации в Notebook


Расширение, написанное Damian Avila, позволяет демонстрировать блокноты как презентации. Пример такой презентации: bollwyvl.github.io/live_reveal/#/7

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

Система вывода Jupyter


Блокноты отображаются в HTML, и вывод ячейки тоже может быть в формате HTML, так что вы можете выводить все, что душе угодно: видео, аудио, изображения.

В этом примере я просматриваю содержимое директории с картинками в моем репозитории и отображаю первые пять из них.

import os
from IPython.display import display, Image
names = [f for f in os.listdir('../images/ml_demonstrations/') if f.endswith('.png')]








Я мог бы получить тот же список bash-командой,


потому что magic-команды и bash-вызовы возвращают переменные Python:

names = !ls ../images/ml_demonstrations/*.png
names[:5]

 

['../images/ml_demonstrations/colah_embeddings.png',
 '../images/ml_demonstrations/convnetjs.png',
 '../images/ml_demonstrations/decision_tree.png',
 '../images/ml_demonstrations/decision_tree_in_course.png',
 '../images/ml_demonstrations/dream_mnist.png']

 

Повторное подключение к ядру


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

Теперь опция Reconnect to kernel позволяет заново подключиться к работающему ядру, не прерывая вычислений, и увидеть последний вывод (хотя какая-то часть вывода все же будет потеряна).

Пишите ваши посты в Notebook


такие, как этот. Используйте nbconvert, чтобы экспортировать в HTML.

Полезные ссылки

 


Notebook с оригиналом этого поста можно скачать из репозитория.

Источник

By Ruslan Novikov

Интернет-предприниматель. Фулстек разработчик. Маркетолог. Наставник.