FORCIA CUBEフォルシアの情報を多面的に発信するブログ

データ分析に欠かせないJupyter Notebook・Jupyter Lab より便利に使うためのNotebookバージョン管理のコツ

2018.12.10

アドベントカレンダー2018 テクノロジー

Qiitaのkaggle Advent Calendar 2018 10日目の記事です。

 技術本部の原です。フォルシアでは、Google Hotel Ads のデータ配信システムの開発・運用や、Spook の検索ログなどのデータ分析を行っています。

 データ分析においては、さまざまな試行錯誤が必要です。そのときには、1行から数行のプログラムを実行することと、結果を確認することを繰り返して、対話的にデータ処理を行うと効率良くデータ分析ができます。

 Jupyter Notebook は、そのような対話的なデータの処理に加え、その実行過程を自らの注釈を加えながら記録ができる、データ分析には大変便利なツールです。対話的分析による効率の良さに加え、分析の再現性の確保、他人へのプレゼンテーションも同時に実現します。筆者もJupyter Notebook 、そしてその後継であるJupyter Lab が無くては何も仕事にならないくらい愛用しています。

 この記事では、Jupyter Notebook、 Jupyter Lab、そして、作業記録や再現性の確保には欠かせないNotebook ファイルのバージョン管理について紹介します。

Jupyter とは

 python の対話的コンソールとして ipython があります。その ipython に、Markdown による注釈を追記できるようにしたのが ipython Notebook、さらに、python 以外の言語で利用できるように拡張されたのが、Jupyter Notebook です。Notebook を自分で分析をした記録として作成するのはもちろんのこと、それを他の人と共有することも容易で、github でも Notebook の共有ができるようになっています。
 また、データ分析に限らず、python のコード実行を対話的に行い、その結果をスクリプトとして保存することで、効率よくスクリプトの開発を行うことができます。

Jupyter Notebook を使ってみよう

 ご自分のマシンにインストールしなくても、お試しであれば http://jupyter.org/try から使ってみることができます。

 上のURLのページに現れる"Try Jupyter with Python" をクリックして開くと以下のようなページが現れます。

Jupyter_notebook_top.png

 これが Jupyter Notebook の画面です。このお試しページでは、3つのセルにわたってMarkdownでインストール方法が書かれていますが、気に入ったらそのマニュアルにしたがって、ご自分のマシンにインストールをしてみてください。

 一番下のセルをフォーカスした状態("You can also..." から始まるブロックをクリックする)で、 "b" を押せば、新しいセルが下に追加されます(上に追加したい場合は "a")。

 出てきたセルの中に、"1+1"と入力して Shift+Enter を押してみます。そうすると、下に計算結果である"2" が表示されましたね。

 データ分析においては最初に大きなデータを読み込むことが多いですが、分析のためのコードをスクリプトで記述して書き換えたたびに毎回実行すると、そのデータの読み込みに時間がかかってしまい、分析作業が非効率になってしまいます。Jupyter Notebook を使って対話的に分析すれば、データの読み込みは1回で済みますし、そのデータを用いたいろいろな試行錯誤を、データをそのたびに読み込むことなく実行できて便利です。

Jupyter Lab

 最近になって、Jupyter Notebook の後継である Jupyter Lab が広まりつつあります。Jupyter Notebook の機能に、ファイルブラウザ、コンソール、テキストエディタ、ターミナルなどの機能を付加したものです。まさに、オールインワンの環境です。今後、開発の中心は Jupyter Notebook から Jupyter Lab に移っていく予定です。

 Jupyter Lab も http://jupyter.org/try の "Try JupyterLab"をクリックすることで試用することが出来ます。

JupyterLab_top.png

 これが画面の一例です(上の試用ページにおいて、"Run"-> "Run All Cells"を実行すると、計算が実行されてこのページのような表記になります)。

 Jupyter Notebook と比べると、

  • 左側にファイルブラウザーをはじめとしたメニューがある
  • notebook の上部にタブがあって、複数のファイルを同時に開ける

 などに気がつきます。

 いろいろなデモのファイルがあるので、触ってみるとどんなことができるのか、理解が進むのではないかと思います。

Jupyter Lab の便利なところ

複数ファイルをタブで開ける!

 データ分析をするときには、いろいろなファイルを開きながら作業を行うことも多いです。そのときに、Jupyter Lab では、複数ファイルを同時に開いて、それをタブで切り替えることが出来ます。また、ファイルを選択するときには、左側メニューにあるファイルブラウザが便利です。

セルの順序の入れ替えがマウスのドラッグでできる!

 これは画期的!下の方で下書きを兼ねて試行錯誤して、固まったコードを簡単に適切な場所に移動することが出来ます。

Jupyter Lab でハマってしまうところ

コピー & ペースト

 マウスでコピー&ペーストをしたい部分を選択しておいて Ctrl + C, Ctrl + Vとやりたいところですが、できないようです。ならばと、右クリックでブラウザのメニューからコピー & ペーストをしてやろうと思うのですが、右クリックすると Jupyter Lab のメニュー(セルの操作など)が出てきてしまい、コピー & ペーストができません。ブラウザの右クリックメニューを出すには、Shift を押しながら右クリックをします(普段はマウスを使わずにキーボードで操作をしている身としては面倒ではありますが)。

 なお、"Setting"メニューの中に "Text Editor Keybind" という項目があり、"Sublime", "vi", "emacs" などが選択できるようになっています。しかし、これはNotebookではなく、テキストエディタ機能でのキーバインドの選択になっており、Notebook のキーバインドには影響を与えないようです。

覚えておくと便利なキーバインド

編集モード(カーソルがセルの中にあるとき)

  • Shift-Enter: セルのコードを実行する
  • Tab: 変数などの補完
  • Shift-Tab: 関数などのヘルプの表示
  • Tab: Esc: 編集モードから抜け出す

編集モード(カーソルがセルの中にあるとき)

  • Shift-Enter: セルのコードを実行する
  • Tab: 変数などの補完
  • Shift-Tab: 関数などのヘルプの表示
  • Tab: Esc: 編集モードから抜け出す

編集モード以外(セルがフォーカスされている場合)

  • a:上に新しいセルを挿入する
  • b:下に新しいセルを挿入する
  • m: セルを Markdown モードに切り替える
  • dd: セルを削除する
  • Enter: 選択されているセルの編集モードに入る

Notebook ファイルのバージョン管理

 分析作業を記録し、再現性を確保するためには、Notebook ファイルのバージョン管理は必須だと筆者は考えています。Jupyter Notebook や Jupyter Lab で生成されるNotebook ファイル (拡張子: .ipynb、以下、「ipynb ファイル」という)は、JSONで記述されたテキストファイルですので、git などでバージョン管理が出来ますが、後述の通り、Notebook 上での変更と ipynb ファイルのJSONで記述されたファイルの変更の対応が直感的ではないことが多く、工夫が必要です。

 ここでは、ipynb ファイルのバージョン管理に便利な Extensions をいくつか紹介します。

Extension とは?

 Jupyter Notebook や Jupyter Lab は、拡張機能(Extension)をプラグインすることが出来ます。

 https://github.com/topics/jupyterlab-extension には数多くの Jupyter Notebook/Lab のExtension が一覧になっています(Jupyter Notebook 用の Extension の多くは Jupyter Lab でもそのまま使えます)。

バージョン管理に便利な Extension

jupyterlab-git

jupyterlab-git は、git のGUI操作盤を画面左側のメニューに追加します。 この Extension は、様々なメニューが表示されるようになった Jupyter Lab ならではのものです。 インストール方法は、リンク先のページを参照してください。簡単にできます。 インストールが終わってJupyter Lab を再起動すると、左側メニューに git のロゴで表示されるタブが追加されます。ここに、staged (git add されたファイル)、Changed (git の管理下にあるが git add して staging されていないファイル)、Untracked (git の管理下にないファイル)が表示されます。各ファイルの名前の先頭にマウスをあわせると表示される上矢印がついたボタンをクリックすると git add することが出来ます。git add されたファイルをgit commitするには、change log をテキストボックスに記入して✓ボタンをクリックします。 git そのものの操作は、Terminal でやったほうが早いという方はそれでもいいでしょうが、このExtensionを使うことで、git 管理がされていないファイルや、変更が加えられたのにコミットされていないファイルがすぐにわかるようになることがポイントです(これはすごく重要!)。

jupyterlab-git.png

nbdime

 すでに述べたように、ipynb ファイルは JSON で記述されていますが、ユーザーが入力したコードや出力結果だけでなく、さまざまな属性が記録されています。

 たとえば、上の図で、一番上のセルに"1+2"となっていたものを図のように"1+3"に変更したときの ipynb ファイルの git diffによる差分は以下のようになります。

$ git diff
diff --git a/test1.ipynb b/test1.ipynb
index d1a3dbe..6c021ff 100644
--- a/test1.ipynb
+++ b/test1.ipynb
@@ -2,22 +2,22 @@
  "cells": [
   {
    "cell_type": "code",
-   "execution_count": 2,
+   "execution_count": 3,
    "metadata": {},
    "outputs": [
     {
      "data": {
       "text/plain": [
-       "3"
+       "4"
       ]
      },
-     "execution_count": 2,
+     "execution_count": 3,
      "metadata": {},
      "output_type": "execute_result"
     }
    ],
    "source": [
-    "1+2"
+    "1+3"
    ]
   },
   {

 コード本体の他にも差分が生じることが分かります。これだと、一見、何が変わったのかよくわかりません。

 そこで、nbdimeをインストールします(インストール方法はリンク先を参照)。これをインストールすると、いくつかのコマンドがインストールされます。その一つ、nbdiffをipynb ファイルが置かれているディレクトリ上でターミナルから実行すると、

$ nbdiff
nbdiff test1.ipynb (HEAD) test1.ipynb
--- test1.ipynb (HEAD)  (no timestamp)
+++ test1.ipynb  2018-12-02 22:07:46.881431
## replaced /cells/0/execution_count:
-  2
+  3

## modified /cells/0/outputs/0/data/text/plain:
-  3
+  4

## replaced /cells/0/outputs/0/execution_count:
-  2
+  3

## modified /cells/0/source:
-  1+2
+  1+3

 という差分表示が得られます。これはgit diffの表示を編集したものになっています。前よりは見やすくなったものの、まだわかりづらいかもしれません。

 そこで、nbdiff-webをターミナルで実行すると、Webブラウザーに次のようなページが表示されます。

jupyterlab_nbdiff-web.png

 この表示なら、どこが変更になったのかが一目瞭然です。ipynb ファイルの差分表示にはこの Extension は欠かせません。

 なお、$ nbdime config-git --enable --globalを実行すると、ipynb ファイルに対する git diffnbdiff によるものに置き換えることも出来ます。

jupytext

少し別のアプローチとしては、jupytext を活用する方法があります。

 jupytext を用いると、ipynb ファイルを保存する際に Markdown や出力を取り去ったスクリプト(python なら .py ファイル)を同時に出力することができます。その機能を使ってpy ファイルを自動出力させて、オリジナルの ipynb ファイルと py ファイルの両方を git でバージョン管理をすれば、py の履歴を見ることでユーザーが作成した入力コードの履歴を簡単に追うことが出来ます。

 この jupytext は、別の用途でも非常に便利に使えます。このツールの最大の特徴は ipynb ファイルとこのツールによって変換されたファイルが双方向に連動していること。jupytertext が出力した py ファイルをお好みのエディタで編集した後に、jupyter 側の ipynb ファイルを再読み込みすれば、py に加えた修正が ipynb ファイルにも反映されます。ですので、ipynb ファイルの代わりに同時出力される py ファイルの編集(リファクタリングなど)を使い慣れた別のエディタで行い、それを ipynb ファイルに戻すことも可能です。

 作者によるデモの動画も参考になるかもしれません(英語による講演ですが)。ぜひ使ってみてください。

さいごに

 データ分析には欠かせない Jupyter Notebook や Jupyter Lab 。データ分析だけでなく、スクリプトの開発にも便利に使えます。まずは上のデモページから体験してみてください。また、Jupyter Notebook をすでに使っている方は、ぜひ、Jupyter Lab も試してみてください。より便利に使える事が実感していただけると思います。

 筆者は git が大好きで、Notebook ファイルのバージョン管理にもつかっていますが、Jupyter Notebook を使い始めたばかりの時には、差分を見てもNotebookの何が変わっているのかがよくわからないので、Notebook ファイルについては git はただのバップアップツールになっていました。しかし、ここに書いたような手法を見つけてからは、Notebook ファイルのバージョン管理も不自由なく行えています。また、jupytertext はバージョン管理だけでなく、使いなればエディタを活用しながら Jupyter も使える優れものです(Emacs からは離れられない筆者にとっては、Emacs も Jupyter Lab も活用できる革命的なExtensionでした)。

 この記事がこれからJupyter を使う方、また、使い始めている方への助けになれば幸いです。

この記事を書いた人

原旅人

フォルシアが日本唯一のインテグレーションパートナーに認定されているGoogle Hotel Ads のデータ配信システムの開発・運用を手がけるWebアプリエンジニアであるとともに、Spook の検索ログなどのデータ分析を担うデータサイエンティスト。