論機器學習和程式語言:ML需要專用的計算機語言嗎?

思源發表於2017-12-15

任何機器學習系統複雜到一定程度,都會包含一個臨時開發的、不合規範的、充滿錯誤的、執行速度很慢的、只有一半功能的程式語言實現。(格林斯潘第十定律)

我們很高興看到機器學習大爆發,以及機器學習模型的複雜度和用來構建模型的框架。越來越多的頂尖模型更多地涉及到程式設計問題,通常它們需要支援迴圈和遞迴等程式設計結構,這給建立它們的工具(程式語言)帶來了一些有趣的問題。

儘管機器學習沒有專用的語言,但有的機器學習框架(如 TensorFlow)在 Python API 下高效地建立了「新語言」,而一些系統(如 PyTorch)重新使用 Python 作為建模語言。我們想問的是,需要為機器學習定製新語言嗎?如果需要,為什麼?更重要的是,未來完美的機器學習語言可能是什麼樣子?

隱藏在機器學習系統後的語言

TensorFlow(TF)已經算是著一種「程式語言」了,因為在這個框架下我們完全可以使用它所提供的類和物件編寫一個模型。大家使用 Python 和 TF 庫進行程式設計,因此這個結論似乎有點令人驚訝。但是,TF 要求你在其內部語言內使用 Python 程式碼構建表示式樹,然後 TF 再進行評估。

事實上,你可以用任何語言進行「懶惰的」TensorFlow 風格程式設計。如下面的 JavaScript 程式碼,就在這種風格中實現了一個小功能(add):

  1. function add(a,b) {

  2.  return `${a}+${b}`;

  3. }

  4. x = 1; y = 2

  5. z = add('x', 'y') // 'x+y'

  6. eval(z) // 3

  7. x = 4

  8. eval(z) // 6

這裡,我們進行的是超程式設計(metaprogramming)——編寫寫程式碼的程式碼。上例中,源語言和目標語言是一樣的(JavaScript),它們也可以是不同的語言(如在處理 C 語言的 C 前處理器中),我們也可以使用資料結構(AST)來代替字串,原則是一樣的。在 TensorFlow 中,Python 是元語言,我們使用 TF 這種基於靜態計算圖的語言編寫程式。如果你不信,想一下 TensorFlow 的圖甚至支援變數適應範圍(variable scoping)和控制流(control flow)等程式設計結構,而不是使用 Python 語法,你可以通過一個 API 管理這些結構。

TensorFlow 和類似工具的呈現方式是「庫」,但它們是極其不尋常的庫。大部分庫提供一套簡單的函式和資料結構,而不是全新的程式設計系統和執行時(runtime)。

為什麼建立新語言?

建立新語言的核心原因非常簡單:ML 研究需要極高的算力,簡化建模語言可以使新增特定的優化和特徵變得簡單。訓練模型要求極高的硬體支援、合適的數值、低直譯器開銷和多種並行化。通用語言如 Python 勉強可以提供這些特徵,但 TensorFlow 可以無縫處理它們。

不過有一個障礙。這些優化依賴於簡單化的假設(ML 模型不是遞迴的,或不需要自定義梯度),這使得將這些優化或應用部署到小型裝置變得簡單。不幸的是,對於工程師來說,模型複雜度目前出現直線上升的趨勢,而研究者享受破壞這些假設的過程。現在模型要求條件分支(比較簡單)、重複迴圈(沒有那麼簡單但也不是不可能)、遞迴樹(幾乎不可能)。在 ML 的很多分支,包括神經網路和概率程式設計中,模型越來越像程式,包括推斷其他程式的程式(如程式生成器和直譯器),且具備不可微元件,如蒙特卡羅樹搜尋。構建提供完全靈活性且達到頂尖效能的執行時非常困難,但是最強大的模型和突破性的結果需要這二者。使用機器學習和複雜樹結構資料需要可微且遞迴的演算法。

論機器學習和程式語言:ML需要專用的計算機語言嗎?

該方法的另一個缺陷是,目前需要上面討論的超程式設計。構建和評估表達樹對程式設計師和編譯器都是額外的負擔。很難進行推斷,因為現在程式碼有兩個執行時間,每個具備不同的語言語義(language semantics),逐步除錯等操作將變得更加困難。這可以通過為新的執行時建立語法來解決,但是其工作量不亞於建立全新的程式語言。


僅用 Python 就可以了嗎?

機器學習模型開始需要程式語言的全部力量,Chainer 和其他人率先使用「define-by-run」方法,該方法中 Python 程式本身就是模型,使用執行時自動微分(AD)作為導數。從易用性的角度來看這種方法很有意思:如果你想要一個進行樹運算的遞迴模型,只需要寫下來,讓 AD 來施展它的魔力!我們很難不高估這種感覺,使用新的無障礙方法對於研究來說是寶貴的。

但是,讓 Python 滿足機器學習的複雜計算要求比你想象的還要難得多。大量研究開始開發快速語言(如 PyTorch),但並沒有加快 Python 的速度。Python 的語義使它很難提供模型級別的並行化,或者為小型裝置編譯模型。

MXNet Gluon 正在探索利用二者,至少在一定程度上。其想法是將基礎的動態自動微分和生成可優化「靜態子圖」的程式碼追蹤方法聯絡起來。不幸的是,這只是把不相關的實現和 API 混在一起而已。這種方法也受限制,MXNet 不僅使用它的圖來做 kernel 級別的優化,還用於高階別的圖排程(graph scheduling),如在多個 GPU 上分割模型。此外,目前尚不明確這些混合如何對此進行處理。

適合機器學習的語言是什麼樣的?

很少有其它領域像機器學習一樣有語言級的設計需求,但在形式化推理或叢集計算等領域,量身定製的語言已經證明它們是高效的解決方案。同樣,我們希望看到新的或現有的語言能完美地支援機器學習所需要的數值計算、自動微分計算、平行計算和概率計算等能力。

當前機器學習語言一個明顯的挑戰是在效能方面難以取得一致性,即早期的混合方法需要更多的開發工作。我們期待未來的機器學習語言將支援任意混合的方法(即靜態計算圖內可能混合了其它動態或靜態計算圖),並且在編譯動態程式碼時能更好地部署。理想情況下,這種新型語言將只有單個靈活的「計算圖格式」。這種計算圖格式應該有一種語法和靜態描述的方法以表示動態的行為,換句話說,它應該看起來更像一個標準的程式語言。

可程式設計語義將達到新的靈活性水平,並且它可以通過類似巨集(Macros)的特徵實現。這將允許通過指定程式碼應該有怎樣的純資料流語義,而在核心繫統的頂部構建像多 GPU 訓練那樣的特徵。此外,它也能允許概率程式語言所需要的各種程式設計操作,或 NLP 模型中常需要手動實現的向量化或批量化等。

與程式語言社群一樣,機器學習工程師非常關注傳統的自動微分領域。機器學習語言可以從真正實現一階導的語言中獲取靈感與經驗,這樣的語言可以很容易將符號與執行時(runtime)技術結合在一起,將正向與反向模式的自動微分技術混合在一起,所有這些都不會導致效能上的損失。

ML 研究將需要越來越強大的型別系統(type systems)、使用者自定義型別和更多的擴充套件手段。目前在英偉達 GPU 上對陣列式支援的硬編碼已經足夠了,但像前沿的稀疏機器學習,新型 TPU、Nervana 和 FPGA 等面向機器學習模型部署的硬體都需要更高的靈活性。

若目前存在新增新型硬體支援或新型資料表徵的新型語言,那麼使用者可以簡單地通過高階程式碼,而不需要改變原來的系統就能新增硬體支援或資料表徵方式。當然,我們期望機器學習語言能從現有的數值計算語言中獲取靈感,因為這些語言已經能很好地處理特定的任務了。

此外,機器學習工程師對傳統的軟體工程問題越來越感興趣,例如在維護和擴充套件生產系統等方面。機器學習程式設計模型使得在元件之間更難以建立介面,對模型的重訓練可以輕鬆地實現向後相容。機器學習語言可以像常規語言一樣將這些問題的解決方案結合起來,但這仍然是一個開放性問題。

論機器學習和程式語言:ML需要專用的計算機語言嗎?

軟體工程 2.0?(圖片來自 XKCD)

任何新語言共同面臨的問題就是它們都需要一套新的庫和生態系統,從而讓人們編寫的程式碼能夠不斷從中獲得支援。例如:如果選擇不重用 Python 的生態系統,TensorFlow 開發者們需要為圖語言中的影象處理和檔案 IO 等任務重新寫庫,在這一部分做出巨大貢獻的專案是 SciPy。這可能是我們快速發展的唯一出路,機器學習參與者們也不能從更為廣泛的 HPC 和數學社群中分裂出去。一個理想條件下的機器學習生態系統是理想的數學生態系統,這些社群之間的合作將使所有人的力量都獲得倍增。

我們期待新的發展來自各個維度。Graph IR 和 XLA、ONNX、NNVM 等格式正在變得前所未有的複雜,同時也在受到傳統語言設計的啟發,甚至可能會出現表面語法,以成為完整意義上的程式語言。TensorFlow XLA 已經開始面向專用編譯器堆疊發展,現在包含 TVM、DLVM、myelin,以及其它正在進行的工作。除此之外,像 PyTorch JIT、Gluon 和 Tangent 正努力使 Python 本身成為更好的建模語言,儘管這項任務面臨的挑戰很大。在剛剛把機器學習歸類為數值程式語言問題後,我們在 Julia 社群中看到了解決這些語言級別問題的極好的基礎,開發者們正在持續推動像 Knet、Flux、Cassettle、CUDAnative、DataFlow.jl 等工具的發展。

結論:機器學習推理工具

機器學習模型已經成為極度泛化的資訊處理系統,被用於進行越來越高階、越來越複雜、抽象的任務;迴圈、遞迴、高階模型、甚至堆疊機和語言直譯器全部都可以以基本組建的組合形式來實現。機器學習是一種新的程式設計正規化,儘管對於初學者來說其中含有太多的數值、可微分和並行化。對於任何工程領域,這些可用工具都會對未來工作的質量和範圍產生深遠影響。

所有這些都預示著機器學習系統的設計者們面臨著非常大的挑戰。儘管如此,我們還有一些好訊息:如果有一方面仍未解決的話,過去的幾十年裡,計算機語言的研究者們已經深入討論了同樣的問題。為了深入探知這一領域的全部,機器學習和程式語言社群需要通力合作,所以,真正的挑戰是整合這兩個群體之間不同的專業知識。

我們能否建立起一套面向數學、衍生和並行,同時又不犧牲傳統程式設計思想優勢的新語言工具?這將是未來十年裡計算機語言領域裡人們面臨的主要問題。

原文地址:https://julialang.org/blog/2017/12/ml&pl

相關文章