misreading chatの第11回で、 Jupyter Notebookの使い方聞いてみた、的なレポートの紹介をやってて、雑多な事をいろいろ書いてみたいと思ったのでこのブログを書いてみた。

前提として、最終的に実サービスに載せる為のモデル開発、というケースに限定して、Jupyter Notebookを使う場合の話をしたい。 実際自分が一番いろいろあると思うのがこの場合なので。

作業過程がなんとなく残る意義

Jupyter Notebookを皆が使う一番の意義は、作業した過程が、 追加のコストなしでなんとなく残る、という事だと思う。 この辺の話がpodcastでなかった気がする。

だいたいにおいて、実際のサービス開発においてのデータ分析では、 ほとんどの事は結論は出てなくて、事実はよくわかってない。 だから結果をまとめる、というフェーズにはなってない状態がすごく長くて、むしろそちらが常態となる。

いろいろな事情から優秀なデータ分析屋は大変忙しい。 そして、現場のチームとしては彼らの負荷を減らしたい。 でも彼らが何に忙しいか、をちゃんと報告してもらうのは大変なコストがかかる。 というのは、まだ事実がわかってないからだ。 ちゃんと報告できるような状態、というのは、 すでに仕事がほとんど終わっている状態と言える。 ほとんどの場合において、なんだか分からない状態で今何をやっているかを共有してもらうのは、すごくコストがかかる。

だから作業を手伝う為に情報の共有を頼むとさらに忙しくなってしまう、という悪循環がある。 特に、いざ報告させてみたら、意外と難しい問題だという事がわかって手伝えない、とかいう場合は目も当てられない。しかもいかにもありがち。 その場合は完全に報告の仕事を増やしただけで、事態は悪化する。

Jupyter Notebookで作業すると良いのは、 このちゃんと結論をまだ出せない段階の作業を、他人が見る事ができる事だ。 作業途中のnotebookを解読すれば、何を考えて何を試して、 何がわかって 何がわかってないのかを理解する事が出来る。 それはちゃんとした報告よりはずっとわかりにくいが、でも解読は現実問題として可能だ。 これはわかってない事を無理に言語化してしまわない、というメリットがあるので、 情報の共有の仕方としてレポートやスライドを書いてもらうよりずっと良い。

notebookを解読するのは、ソースコードを読むのに似た能力が要る。 だから誰でもできる事じゃない。 だけど、能力が高い人なら出来る。 そして、追加で作業を頼まなくて出来るので、 忙しいデータ分析屋をさらに忙しくしないで出来る。

作業を理解するには、ヒントが多ければ多いほどよい。 Jupyter Notebookで作業をすると、自然とヒントが多く残る。これが良い。 先頭から再実行はできないかもしれないし、上から読むと意味はわからないかもしれない。

でもexecution countとかoutputのセルから何が起きたのかを想像して読んでいくと、 だいたいは作業を理解する事が出来る。 報告とか整理をしてもらわなくても相手のやっている事を理解出来る、これがJupyter Notebookの威力だと思う。

逆に試行錯誤の過程を整理されてしまうとその過程で得られた知見が失われてしまうので、 これはやってはいけない。 コミット前に整理するなんて論外である。

ipynbのライフサイクル

ソフトウェアと同様に、ipynbにはライフサイクルがあると思う。 ポッドキャストで参照してい論文では、ライフサイクルの最後の方の話ばかりをしていた気がする。(論文は読んでないけど)

ここでは

  • 幼年期
  • 混沌期
  • 成熟期
  • 老齢期

に分けて話をしてみよう。

ipynb幼年期: 探索的に試行錯誤を進める

まず動かしてみて結果を見る。その結果をもとに新しい事を試す。 そうしていくと前のところをちょっと変えてまた試してみたくなる。 そうやって、どんどんノートブックが育っていく。

最初の段階では規模も小さいので読めば何をやっているかはわかるし、 わかっている事実も少ないので整理の必要もそれほど無い。

ipynb混沌期: 実行するのにいろいろな注意が必要になる

いろいろと作業が進むと、新たな事実が判明していき、 それまではわかっていなかった深い疑問などが発生する。 その疑問を解決する為のコードは複雑になってきて、 また多くの前提知識が必要となる。

dupが多くなってきて、すでにobosleteになったセルと現在有効なセルが混ざり合っていたり、 何か実行した時におかしい事が起きるのでそれを手作業でちょっと直して実行したり、 といった事も必要になる。

最初から再現する時にこのセルをまず実行してここで少し待ってさらにこれをやって…と、そのipynb特有の事情が増えてくる。

また、似たような実行結果がたくさん増えていき、どこで何を試したのかがわかりにくくなってくる。 この辺から整理とかどうしよう?という話題になる。

ここまで来るのは多くの発見があった結果なので、 悪い事では無くてむしろかなりサービス開発としてのデータ分析がうまく行っている結果と言える。

ipynb成熟期: 固定化された部分と変動の多い部分の分離

混沌期までで得られた知見をもとにノートブックを整理したりMarkdownのセルを追加したりして、 もうだいたい結論が出た部分が整理されて、 現在アクティブに探索を続けているところと分離される。

この時に外部の.pyファイル送りになったり複雑化したセルの実行手順がコード化されたり関数化されて、より簡素になる。

すでに固まったところが、 実際にアクティブに探索を続ける為のツールとかライブラリのような位置づけとなる。 ipynb自体がツールのような性質を帯びる。

ただこの場合でも、固まった部分が完全に固まっている訳では無く、ちょこちょこ変更はされる。 頻度が少ないだけ。

既存のコーディングプラクティスとかが効くのはこの段階の整理くらいだが、そんなのは分析業務の本体からするとおまけくらいなものだ。(というのは言い過ぎかもしれないが)

ipynb老齢期: あまり変更はされずに主に参照される物に

やがて調べている事に結論が出たり、もっと大きく違う事を調べ始めるようになると、 それまでのipynbは役割を終える。 大きな区切りとなる場合は最後にわかった事を整理する場合もあるが、 そうでない場合は最後にアクティブに探索されていた部分がそのまま残る事になる。

老齢期には綺麗に整理してmarkdownのセルで説明の文章をたくさん足して説明する事も出来るけれど、 ここまでくればデータ分析として難しいところはすでに終わっているので、自己満足の世界となる。

老齢期のipynbと通常のサービス開発のコードは性質が似ているが、 これは別にデータ分析の正しい姿なのでは無く、 むしろデータ分析としての問題が終わったので似た物になる。

非データ分析屋のプログラマはこの状態で綺麗に書くという事を大切な事だと勘違いしがちだが、 この状態まで来た時にはもう問題は終わっているので、 サービス開発としてのデータ分析ではここを綺麗にしても開発効率には影響が無い。

普通の実験とデータ分析のサービス開発の違い

データ分析を用いたサービス開発をやった事が無いと、 データ分析の探索的な実験というのは、

  1. 仮説がある
  2. それを確かめる為の実験を行う
  3. 結果が出る

という単位で綺麗に区切れる、と勘違いしがちだが、 そんな事は無い。 これはウォーターフォール的な開発スタイルとして、最初に仕様を考えて、 それを実装して、それをテストしたら開発が終わる、という位現実の姿とかけ離れている。

実際の探索の粒度はもっとずっと小さいので、 いちいち上の段階を文書化するなんて事をやっていたら、 とても意味のある結論には到達出来ないし、 その切れ目ももっとずっとわかりにくい。

最初に仮説はだいたいあるのだけど、何かを試し始めたら違う事を確かめる必要が出てきて、 それを確かめようとしていたらまた違う事を確かめる必要が出てきて… とどんどん脇道に逸れていって、 最初に試そうと考えていた事は全く見当違いで試す価値も無い、 というのはよくある事だ。 でもその過程で理解を深めていく、その事ことそがデータ分析という業務の本質なので、 それは問題でもなんでもない。

また、最後まで最初に試そうと考えた仮説が試せない、という事もよくある。 それでもその過程で理解を深めていく事ができていれば、問題は無い。

どちらのケースも、途中の段階では上のようなフォーマットにはまとめずらい。

だから実験レポートのような物、 というのと、データ分析を用いたサービス開発におけるデータ分析の作業の共有は、 大きく異なる性質を持っていると思う。 これは結構新しい問題なんじゃないかなぁ。

なまじ何もわかってない偉い人が、この本質的な違いを、学術的なレポートを正しく書く能力が不足していると勘違いするケースはちょこちょこあるので、ここの違いは強調しておいて良いと思う。

これは論文とかにする研究のためのデータ分析の場合はまた違っていて、 論文目的の研究の場合はもっと実験レポートに近い物が増えていくと思う。 ポッドキャストで聞いた相手は研究よりの目的でJupyterを使っていたんだろうなぁ、と思った。

データ分析のサービス開発の本体は、わかっていない段階にある

まだいろいろな事がよく分かっていない状態、 というのがサービス開発のためのデータ分析としては本体で、 いろいろな事がわかったあと、というのはもう分析業務というのは終わっている。

データ分析という開発プロセスを考える時には、 このいろいろな事が分かっていない状態での生産性が重要となる。 そしてJupyter Notebookの一番重要な特徴は、 このいろいろ分かってない状態を残して他人と(能力がすごく高ければ)共有出来る、 というところにある思う。

分かっていない状態、ipynb的には混沌期あたりのところが一番重要で、 ここにフォーカスを当てないとJupyter Notebookの素晴らしさとかデータ分析業務の特殊さは隠れてしまうんじゃないかなぁ、と思っている。

最後に整理する事はあるかもしれないけれど、 それはもう戦いが終わったあとだ。 サービス開発でイケるかポシャるかを分けるのはそこじゃなくて、 もっと前の段階で、 すさまじくハイコンテキストな状態でしか意思疎通が出来ないところで勝負は決まってる気がする。 そしてこのすさまじくハイコンテキストな状態でしか意思疎通出来ない状態でチームとしての力を発揮する為の触媒になれるってところが、Jupyterの一番の強みなんじゃないか。

とにかく他者が解読する為のヒントを多く残す。ただしその為にはコストはかけず、 普通に作業するだけで多くの痕跡が残る。 これがJupyter Notebookがチームでデータ分析を進める時にすごく重要なところだと自分は思う。

実際は人による、という事なのだろうが

いろいろ書いたが、自分の環境特有で一般化出来ない事も多く混ざってる気はする。 だが一般的な事も混ざってると思ってる。

Jupyterのメリットはいろいろあると思うけれど、ただ作業するだけでいろんな痕跡が残る、という点を強調したかった。