Jupyter 是一款免費、開源的互動式 web 工具,在資料科學家中備受歡迎。但本文作者卻對這一工具存在很多不滿,認為其不是理想的 Notebook。
據報導,Jupyter notebook 是資料科學家首選的實戰工具。本文展示了從 EDA(探索性資料分析)到API 的快節奏,並沒有Jupyter。
Jupyter的主要特點是:
行內程式碼執行
簡單的構思結構
對圖片和資料幀的良好展示
與更加質樸的 iPython 命令列相比,這種整體的靈活性讓它成為了一款首選工具。但是,值得記住的是,這不過是一款 REPL(讀取-求值-輸出-迴圈),你可以在整個歷史記錄中有效地導航。因此,這並不是一款生產工具。
但是,很多機器學習開發者在生產中都經歷過把一個深度學習 notebook 重構成一個實際演算法時深深的痛苦(reddit 和 Stack Overflow 上也有類似的討論)。
保持精益生產的思想,我們應該努力減少浪費。
簡介
在 Sicara,我們為客戶構建基於機器學習的產品。
機器學習:客戶帶來了業務需求,我們必須儘快提供令人滿意的演算法;
我們構建的產品:我們需要以一種生產就緒的思想來開發產品。演算法被部署在雲端,以 API 等多種形式進行服務和更新。
首先,你肯定需要一個版本控制工具,這對 Jupyter 來說是一種痛苦(在 Reddit 和 quora 上也有相關討論)。不僅僅是針對你的程式碼,還有你的實驗。你需要有十足的把握能夠重新執行目前得到的所有結果。結果無法復現對於資料科學家來說多麼常見?
此外,使用 notebook 的人往往容易混淆下面三種用途:
開發:定義一些實用的方法和工具;
除錯/應用:用真實的資料執行一段程式碼,看看會發生什麼;
視覺化:以一種整潔、可復現的輸出來呈現結果。
為了減少浪費,應該明確地定義和分離這些步驟,以便可以在改變一個步驟的時候不會改變其他步驟,反之亦然。我得到的結論是:
為了產生高質量的測試程式碼,應該使用一流的 IDE
為了除錯程式碼,應該使用可視除錯工具
為了寫報告,我對錶達性標記語言更為滿意(如 markdown、reST 及 LaTeX)
幸運的是,一個配置得當的IDE可以完成所有的事情。例如,如果你來自於R社群的話,你肯定會使用RStudio,它允許你進行這些工作:
本機程式碼完成、自動修復等等。
直接的可視除錯
使用 Rmarkdown/knitr/Sweave 來生成好看的動態報告。
開發出生產就緒的程式碼
只要你想做一個實驗,也就是說,寫一個可以在你的資料上有所作為的方法,你就應該思考一下用法、極限案例等等。在一個單獨的檔案、文件和單元測試中來做。這樣可以確保:
使用你的方法可以達到你的目的;
你的程式碼可以安全地用在專案中的其他地方。
因為你必須組織你的工具,所以這會讓你思考流程的結構、你所需要的東西、你最可能改變的東西等等。Python 和 R 都支援這種快速測試。最好花十分鐘時間寫一下那些需要十小時除錯錯誤輸出的極限案例。
為了清楚起見,單元測試絕不能與定義方法的檔案存在於同一個資料夾中。但是使用Jupyter 的話,這點就無法避免了。
除錯和顯示
在這一步,你有了全新的功能程式碼。是時候在實際的資料上試一試了!這是notebook非常方便的所在了,因其存在單元格機制(cell mechanism)。但這顯然是一次工具切換。你為什麼要放棄具有所有快捷鍵和舒適度的IED,去在web瀏覽器上執行程式碼呢?你所需要的是將你的程式碼直接在 IDE 中行內執行( inline execution)。
像pycharm這樣的工具就有對這個功能的原生支援:使用一個鍵盤快捷鍵就能夠執行選定的程式碼或指令碼(在控制檯中選擇執行或者執行塊)。此外,它的控制檯中執行著iPython,還具有很好的變數工具視窗。在科學模式下,你還可以在IDE中顯示和改變影像、資料/陣列。或者你還可以使用像VSCode或者Atom with Hydrogen這些具備這種功能的工具。
彙報和分享
這裡你應該已經在專案路徑下有了測試程式碼,並在資料上執行一個純Python檔案。
|-- project
|-- notebooks
|-- data_analysis.py
|-- tests
|-- do_something_test.py
|-- utils
|-- do_something.py
你已經將程式碼在你的IDE中內聯地執行了並檢查了結果,非常棒!你的工作基本已經完成了:現在需要向團隊做彙報了,以證明將你的演算法移植到新的版本中的合理性,或者也許你將要寫一篇論文投稿到下一屆的NeurIPS會議上。
你需要解釋你的邏輯,並逐步證明你的結果。當然你不想在另一個檔案中重新輸入所有的內容,這太無聊了。
這就是存在用於文學式程式設計(literate programming)的工具的原因了。像Sphinx這類文件工具就是以這種思路構建的:將你的程式碼和文件寫進同一個檔案中,並從中生成一個可讀版本。
對於你的 Python notebook,我建議你使用 Pweave。這是我發現的目前為止最好用的 knitr 搬運包。也是一個完全支援 Python cell(或者Python和R的混合)的Rmarkdown。
在任何情況下,我發現使用 Pweave 的 pypublish 命令是最有效的。僅僅需要在你的指令碼上寫下注釋並執行:
pypublish data_analysis.py
從中生成一個清晰的可分享HTML。每一個註釋行都是markdown解釋的,每個cell(或者程式碼塊)都可以被顯示或者被隱藏。
例如,用這個notebook執行 pypublish
(注意特殊的註釋標記#'、#+以及# %%)。
# %% # This is the title of the notebook
#+ setup, echo=False
import pandas as pd
df = pd.DataFrame({'a': list(range(4))})
#' Let us see what a plot looks like
#+ plot_df, echo=False
df.plot.bar()
#' Let us make now some visible computation
#+ echo=True
a = 1
print(a)
#' Also it is possible to use variable in context: a is <% a %>
#+ echo=True
a = 2
#' a is now <% a %>
生成如下報告:
我推薦在PyCharm中設定一個外部工具來一鍵釋出notebook,配置如下(如有必要,請注意新增環境變數的技巧):
Pweave作為外部工具配置
結論
這不是另一篇《為啥Jupyter notebook糟糕極了》(Why Jupyter notebooks suck )的文章。我對這個流行工具並無任何個人偏見,只是希望分享一些我在使用過程中的個人體驗。尤其是身處一個生產驅動的環境中,我已經進入了另一個工作流程。你怎麼看呢?