全プログラマに捧ぐ！図解「ノートブック」

[Jupyter Notebook](https://jupyter.org/)を使い始めて半年経ちました。最初は機械学習のためのツールとして触り始めましたが、徐々にデータサイエンティストだけの玩具にしておくのは勿体無いと思うようになってきました。本記事では一般のプログラマにも伝わるようになるべく図解で「ノートブック」を解説してみたいと思います。

(本記事は[自分のブログ](https://hinastory.github.io/cats-cats-cats/2019/04/06/understanding-notebook/)からの転載記事です。)

## はじめに

本記事はJupyter Notebookにおける「ノートブック」という機能に着目して解説したものです。「ノートブック」は、REPL[^1]の進化形態であり、仮にデータサイエンティストでないとしても全プログラマが知っていて損はないアイデアだと思います。

[^1]: REPLは「Read-Eval-Print loop」の略で、入力された部分ごとに評価して表示すること繰り返す、対話型実行環境を意味しています。PythonにおけるIPythonやRubyにおけるirbにあたります。インタラクティブシェルと呼ばれることもあります。

## ノートブックとは

ノートブックとは以下の図のように「`コード`」と「`実行結果`」と「`コードのメモ`」をまとめたものです。コードのメモは恐らくプログラマの方にはおなじみのMarkdown形式で記述することができます。

ノートブックの凄いところはこのプログラムの理解に必要な３点セットを上手にまとめている点です。これらがバラバラに管理されていたとなると、プログラムのコードの動作を他人に理解させようとすると非常に苦労することが目に見えますし、もちろん書いた本人にも優しくないです(笑)。

<img src="https://hinastory.github.io/cats-cats-cats/gallery/daily/tools/jupyter/notebook-a.png"></img>

面白いのは以下の図のようにコードだけでなくメモも「`実行`(Run)」できる点です。実行後のプログラムのコードの下にはコード実行結果が出力されているのはお分かり頂けると思いますが、メモの実行結果はMarkdownがレンダリングされた結果となります。また図を見てお分かりのとおり、コードやメモはきちんと色付けされており視認性も良いです。

<img src="https://hinastory.github.io/cats-cats-cats/gallery/daily/tools/jupyter/notebook-b.png"></img>

ノートブックが実行されるのは以下の図のようにノートブックサーバになります。コードやメモはそれぞれノートブックの中の「セル」と呼ばれるものに格納されていて、セル単位で対話的に実行が可能です。

<img src="https://hinastory.github.io/cats-cats-cats/gallery/daily/tools/jupyter/notebook-c.png"></img>

また、コードの編集や実行はブラウザを通して行うことになりますが、マウス操作以外にもキーボードショートカットやコード補完等が使えるので一般的なWebページ以上に快適な作業が可能です。

## ノートブックと実行結果

実行結果とはプログラム自体が画面に出力したものと、プログラムの「`最後の行の戻り値`」になります。以下のノートブックの一部を使って説明します。

<img src="https://hinastory.github.io/cats-cats-cats/gallery/daily/tools/jupyter/notebook-1.png"></img>

上記の灰色の枠内がプログラムです。半径5の円の面積を計算しています。その枠の下の「`78.53981633974483`」が戻り値になります。これはプログラムの最後の行の「`math.pi * r ** 2`」を評価した結果が戻り値になっています。

初めての人が陥りやすい罠として、最後の行を「`area = math.pi * r ** 2`」のような代入文にして、何も表示されず困るというものがあります。これはPythonの代入が戻り値を持たない仕様のためにおこる現象です[^2]。この場合は代入文の後に「`area`」を追加して最後の行を表示したい変数に変更するか、以下のように`print`関数で明示的に画面出力すれば良いです[^3]。

<img src="https://hinastory.github.io/cats-cats-cats/gallery/daily/tools/jupyter/notebook-2.png"></img>


さらにノートブックは、テキスト以外にも他のライブラリと連携してリッチな出力結果を実現できます。以下は表を表示してみました。

<img src="https://hinastory.github.io/cats-cats-cats/gallery/daily/tools/jupyter/notebook-3.png"></img>

グラフも表示可能です。

<img src="https://hinastory.github.io/cats-cats-cats/gallery/daily/tools/jupyter/notebook-4.png"></img>

画像処理結果の表示もお手の物です。

<img src="https://hinastory.github.io/cats-cats-cats/gallery/daily/tools/jupyter/notebook-5.png"></img>

動画の埋め込み[^4]なんかも可能です。

<img src="https://hinastory.github.io/cats-cats-cats/gallery/daily/tools/jupyter/notebook-6.png"></img>


[^2]: Pythonでは代入以外にも`if`や`while`等の制御構造も戻り値を持ちません。一方Rubyのように、代入や`if`や`while`が戻り値を持つ言語もあります。
[^3]: `print`は戻り値を持たない関数なので、戻り値は表示されません。しかし一般的なPythonの関数は戻り値を持つもの(`return`で値を返す)が多いので、大抵は関数の結果確認のために「最後の行の戻り値」を有効活用できます。
[^4]: 埋め込まれている動画は「 https://www.youtube.com/watch?v=XQB3H6I8t_4 」になります。

## ノートブックとセル

セルとは以下の図[^5]のように、ノートブック内のプログラムのかたまりであり、セル単位でプログラムの編集、実行、削除が可能です。

<img src="https://hinastory.github.io/cats-cats-cats/gallery/daily/tools/jupyter/notebook-7.png"></img>

セルには編集モードとコマンドモードがあり、直接マウスでセル内をクリックすると編集モードになります。編集モードでプログラムを記述して「`Shift` + `Enter`」キーを入力することでセルの実行が可能です。編集モードで「`Esc`」キーを入力することでコマンドモードに移行することができます。コマンドモードではその名のとおりセルに対して様々な命令を実行することができます。例えば「`d` `d`」を入力することでセルの削除が可能です。

ノートブックでは基本的に下にセルを追加して、実行結果を確認したい単位でプログラムを書いて実行することを繰り返します。一度実行したセルもまたセル内のプログラムを編集して再実行することができます。そのためセルの左側には実行の順番を表すための番号が振られており、実行するごとに１増えていきます。

赤枠で表示されているのは、プログラムを実行して発生した例外のスタックトレースです。このようにスタックトレースも色付きで分かりやすく表示されるのでデバッグには重宝します。また大きいセルを小さなセルに分割して、例外の発生した箇所を特定しやすくする手法もよく使われると思います。

セルは一番下だけでなく、セルとセルの間にも挿入することができます。これは後で忘れていた処理を追加するのに便利ですが、注意すべき点があります。以下の図は上から２番めのセルの下に新しいセルを挿入して、プログラムを記述して実行した後の状態を示しています。セルの実行順番はセルの左の番号の通りです。

<img src="https://hinastory.github.io/cats-cats-cats/gallery/daily/tools/jupyter/notebook-8.png"></img>

この図で注意すべきは3点あります。１つ目の注意点は、挿入したセルの実行結果はすでに実行済みのセルの実行結果には影響を与えないということです。この図の場合一番下のセルの最終行は`a + b`となっていますが、今回のようにその上のセルに挿入して`b`の値を書き換えても最後のセルの実行結果は変わりません。

次に注意すべき点は、いったんこのノートブックを終了して再度ノートブックを「`先頭から`」実行したときに実行結果が変わる点です。問題は最後のセルで変数`a`と`b`を上書きしている点です。このため上から3番目のセル(挿入したセル)で、実行結果が変わってしまいます。この場合`array([9, 12, 15])`だった結果が`[1, 2, 3, 4, 5, 6, 4, 5, 6]`になります。さらに続けて最終セルを実行しようとすると例外が発生します。

最後に注意すべき点は一番最後のセルで`import`文を使っている点です。一回実行された`import`文はノートブックの範囲内で有効なので、セルの挿入位置にかかわらずインポートされたライブラリの機能が利用できます。しかし、ノートブックを終了して再度先頭から実行しようとすると、当然`import`文の実行前にそのライブラリの機能を使おうとすると怒られます。今回の例ではさらに紛らわしくて実行結果が変わるという現象にもつながっています。

従って、ノートブックを先頭から再実行する可能性があり、かつセルを一番下以外に挿入する場合は、セルを一番上から実行しても問題ないかということを意識する必要があります。このトピックはおそらくノートブック利用者が一度は通る道だと思い言及しました[^6]。

[^5]: ノートブックの図はJupyter Notebookの新インターフェースであるJupyterLabを元に作成しています。Jupyter Notebookだと若干見え方は異なりますが、ここで説明される概念は共通です。
[^6]: この注意点はPythonを例にしているので他の言語では当てはまらない場合があります。ノートブックの特性と言語の特性の組み合わせで思わぬ落とし穴があるかもしれないということだけ覚えておくといいかと思います。

## ノートブックとカーネル

一つのノートブックには必ず一つのプログラミング言語が紐付きます。下の図のようにノートブックを開くと裏では紐付いたプログラミング言語の実行環境が起動して、セルの実行のために待ち受けています。このプログラミング言語の実行環境のことを「`カーネル`」と呼びます。現在、非常に多くのカーネルが[公開されています](https://github.com/jupyter/jupyter/wiki/Jupyter-kernels)。

<img src="https://hinastory.github.io/cats-cats-cats/gallery/daily/tools/jupyter/notebook-9.png"></img>

またカーネルは図のようにノートブックを開くたびにひとつ起動されるイメージで、カーネル間でのメモリ等の共有はなく完全に独立しています。また、このカーネルは明示的にシャットダウンしないとずっと動きっぱなしになります。
従ってノートブックを開くとカーネルが起動してマシンのリソースを消費するので、不要なカーネルはこまめにシャットダウンすることをおすすめします。

## ノートブックとファイル

ノートブックの実体は一つのファイルです。もう少し具体的に述べると拡張子が「.ipynb」でJSONフォーマットで保存されています。単なるファイルなのでフォルダによる整理やGit等のバージョン管理システムによる管理も可能です[^7]。

<img src="https://hinastory.github.io/cats-cats-cats/gallery/daily/tools/jupyter/notebook-10.png"></img>

[^7]: ノートブックには実行結果も含まれますが、実行結果を除いてバージョン管理しようとすると少し工夫が必要になります。手段はいろいろあるので気になる方は検索してみてください。

## ノートブックの変換

ノートブックは以下の図のように様々な形式に変更可能です。単純に実行スクリプトに変換できるのはもちろんですが、HTMLやマークダウンにも変換できるのでQiitaやブログサービスへの埋込も可能です。Reveal.jsのスライドにすればプレゼンテーションにも利用できます。
<img src="https://hinastory.github.io/cats-cats-cats/gallery/daily/tools/jupyter/notebook-11.png"></img>

## ノートブックの共有

ノートブックの実体はファイルだということは前述のとおりですが、このファイルは様々な環境で開くことができます。例えばVisual Studio Codeでは拡張機能でノートブックに対応しています。さらに、クラウド上にはノートブックに対応したマネージドサービスが揃っているので、ローカルで作成したノートブックをクラウドで実行するのも簡単です。また編集や実行機能が必要なければ、nbviewerのGitHubのように表示だけが可能なサービスも存在するので、コードや実行結果の共有だけがしたい場合はこちらのほうが手軽です。

<img src="https://hinastory.github.io/cats-cats-cats/gallery/daily/tools/jupyter/notebook-12.png"></img>

## ノートブックとJupyterLab

JupyterLabはJupyter Notebookの次世代ユーザインターフェースです。タブインタフェースで非常に使いやすく自分も愛用しています。まだ、バージョン1.0には達していませんが、普段の利用にはほぼ問題ない感じです。現在は混在期間でどちらも非常に多く使われており甲乙付け難いです。拡張機能も含んだ安定性や情報の多さを取るならJupyter Notebookに軍配があがりますが、一部の先進的な機能や格好良さを求めるならJupyterLabをおすすめします。以下の画面は自分が実際に利用しているJupyterLabの画面です[^8]。

<img src="https://hinastory.github.io/cats-cats-cats/gallery/daily/tools/jupyter/jupyterlab.png"></img>

[^8]: 画面に写り込んでいるプログラムは [PythonによるAIプログラミング入門](https://www.oreilly.co.jp/books/9784873118727/)の例題になります。

## ノートブックを始めてみる

ノートブックの始め方はいろいろあるので、ざっくりとしたチャートを自分の主観で書いてみました。最初の一歩を踏み出すための道標としてご利用ください[^9]。

<img src="https://hinastory.github.io/cats-cats-cats/gallery/daily/tools/jupyter/notebook-13.png"></img>

| エントリー | URL |
| --- | --- |
| Try Jupyter    | https://jupyter.org/try    |
| Colaboratory   | https://colab.research.google.com|
|Sage Maker|https://aws.amazon.com/jp/sagemaker|
|Azure Notebooks|https://notebooks.azure.com|
|Binder|https://mybinder.org|
|zero-to-jupyterhub-k8s|https://github.com/jupyterhub/zero-to-jupyterhub-k8s|
|jupyterhub-deploy-docker|https://github.com/jupyterhub/jupyterhub-deploy-docker|
|JupyterHub|https://jupyterhub.readthedocs.io/en/stable|
|Jupyter Notebook|https://jupyter.org/install|
|base-notebook|https://hub.docker.com/r/jupyter/base-notebook|
|minimal-notebook|https://hub.docker.com/r/jupyter/minimal-notebook|
|all-spark-notebook|https://hub.docker.com/r/jupyter/all-spark-notebook|
|pyspark-notebook|https://hub.docker.com/r/jupyter/pyspark-notebook|
|tensorflow-notebook|https://hub.docker.com/r/jupyter/tensorflow-notebook|
|datascience-notebook|https://hub.docker.com/r/jupyter/datascience-notebook|
|Go back to TOP OF THIS PAGE|このページの先頭から再度読み直してください|


[^9]: ツッコミどころがあるのは理解しております。スルーして頂けると幸いです。


## ノートブックの用途

ノートブックは非常に用途が広いので、プログラミングにおける様々な場面で活用することができると思います。以下の図は思いついた用途です。

<img src="https://hinastory.github.io/cats-cats-cats/gallery/daily/tools/jupyter/notebook-14.png"></img>

## まとめ

以下、「ノートブック」のまとめです。

- 「ノートブック」は`コード`と`実行結果`と`コードのメモ`をまとめたものである
- 「ノートブック」の実体はファイルである
- 「ノートブック」はMarkdown、Asciidoc、LaTeX、HTML、PDF、実行スクリプト、スライドなど様々な形式に変換できる
- 「ノートブック」を利用できる複数のクラウドサービスが存在する
- 「ノートブック」にはプログラミング全般に幅広い用途がある

Jupyter Notebookはデータサイエンスの分野ではほぼ必須とまで言われるようなツールになりましたが、一般のプログラマへの浸透具合はいまいちと感じたので、データサイエンスの文脈からなるべく切り離して解説をしてみました。

本記事が「`ノートブック`」の理解と普及の一助になれば幸いです。