深度學習中的函式語言之美 - Clojure和Haskell

banq發表於2019-09-13

深度學習是基於人工神經網路的機器學習方法的子集。這些都受到大腦等生物系統中的資訊處理和分散式通訊節點的啟發。在深度學習中,每個級別都學習將輸入資料轉換為稍微更抽象和複合的表示。例如,在面部識別系統中,畫素可能是系統的一層,而邊緣可能是另一層,眼睛可能是另一層,而臉可能是另一層。深度學習方法的複雜性使得使用程式設計社群中流行的現有包TensorFlowPyTorch,由此 Python很受歡迎,然而,在生產深度學習系統,效能和安全性是推動公司選擇Clojure和Haskell等函數語言程式設計語言的兩個問題。

深度學習實施的困難
在將深度學習系統投入生產時,神經網路可能包含一百萬個引數。資料可以快速爆炸以訓練這些引數。這種資料爆炸需要的效能只能透過具有安全併發和並行功能的高效程式語言來實現。由於神經網路的複雜性,資料從一層傳遞到另一層,程式語言處理這些資料的方式的簡單性和一致性非常重要。在這種情況下,安全性意味著能夠以一致的方式保留原始資料的狀態,而簡單性意味著能夠在最大化效能的同時輕鬆讀取和維護程式碼庫。

為什麼函數語言程式設計更適合深度學習
為了解決實現深度學習時可能遇到的一些困難,程式設計師發現函數語言程式設計語言可以提供解決方案。
在電腦科學中,函數語言程式設計是一種程式設計正規化,它將計算視為數學函式的評估,並避免改變狀態和可變資料。這是一種更接近數學思維的程式設計模式。
深度學習模型本質上是數學模型。例如,人工神經網路包括連線的節點,每個節點執行簡單的數學運算。透過使用函數語言程式設計語言,程式設計師能夠以更接近操作本身的語言描述這些數學運算。這些程式的顯式編寫方式使得閱讀和維護程式碼庫變得更加容易。
同時,深度學習演算法的組成性質意味著,在神經工作的每一層,層或功能傾向於連結在一起以執行任務。這可以使用函式程式語言的功能鏈來容易地實現。
此外,在深度學習中,當函式應用於資料時,資料不會改變。可以按行順序輸出新值,但資料本身保持一致。函數語言程式設計語言的不變性特性將允許程式設計師在每次生成新值時建立新資料集而不改變原始不可變資料集。這使得更容易在整個神經網路中保持資料的一致性。
最後,深度學習實現中涉及的大量引數和訓練資料意味著並行性和併發性是建立生產級深度學習系統的關鍵。並行性意味著在不同的CPU上執行執行緒以加速學習過程。併發意味著管理執行緒以避免衝突的能力。函數語言程式設計允許免費併發和並行。這意味著,就其性質而言,純函式是無狀態的函數語言程式設計將始終為特定輸入生成相同的輸出,從而能夠隔離任何函式,並在需要時執行。這使得併發和並行更容易管理。您不必處理死鎖和競爭條件等問題。訪問不同CPU的不同執行緒將能夠獨立執行而不會出現爭用。

Clojure
隨著函式性程式設計在深度學習中的普及,以及可用於深度學習的強大軟體包,Clojure現在受到沃爾瑪和Facebook等公司的青睞。它是一種基於LISP程式語言的高階動態函數語言程式設計語言,它具有可以在Java和.NET執行時環境中執行的編譯器。
Clojure不會取代Java執行緒系統,而是使用它。由於核心資料結構是不可變的,因此可以線上程之間輕鬆共享它們。同時,程式中的狀態變化是可能的,但Clojure提供了確保狀態保持一致的機制。如果嘗試修改同一引用的2個事務之間發生衝突,則其中一個將退出。不需要顯式鎖定。

(import ‘(java.util.concurrent Executors))
(defn test-stm [nitems nthreads niters]
 (let [refs (map ref (repeat nitems 0))
   pool (Executors/newFixedThreadPool nthreads)
   tasks (map (fn [t]
               (fn []
                (dotimes [n niters]
                  (dosync
                   (doseq [r refs]
                    (alter r + 1 t))))))
              (range nthreads))]
   (doseq [future (.invokeAll pool tasks)]
      (.get future))
   (.shutdown pool)
   (map deref refs)))
(test-stm 10 10 10000) -> (550000 550000 550000 550000 550000 550000 550000 550000 550000 550000)


Clojure中的並行性很便宜
在深度學習中,模型必須訓練大量資料。並行性意味著在不同的CPU上執行多個執行緒。便宜的並行性意味著顯著的效能改進。將分割槽與map結合使用可以實現成本更低的並行性。

(defn calculate-pixels-2 []
 (let [n (* *width* *height*)
       work (partition (/ n 16) (range 0 n))
       result (pmap (fn [x]
                  (doall (map
                   (fn [p]
                     (let [row (rem p *width*) col (int (/ p *height*))]
                       (get-color (process-pixel (/ row (double *width*)) (/ col (double *height*))))))
                   x)))
                  work)]
   (doall (apply concat result))))


Clojure中的連結函式意味著清晰
在Clojure中,很少有資料型別的函式。函式也可以作為引數傳遞給其他函式,這使得深度學習中的連結函式成為可能。透過更接近實際數學模型的實現,Clojure程式碼可以易於閱讀和維護。

;; pipe arg to function
(-> "x" f1) ; "x1"

;; pipe. function chaining
(-> "x" f1 f2) ; "x12"


Clojure中的標識身份和狀態提供了安全性
在Clojure中,每個模型的標識身份在任何時間點都有一個狀態。這種狀態是永遠不變的真正值。如果身份似乎發生變化,這是因為它與不同的狀態相關聯。新的值是舊的函式。在神經網路的每一層內,始終保留原始資料的狀態。具有作為函式輸出的新值的每組資料可以獨立操作。這意味著可以安全地對這些資料集執行操作,也可以不考慮爭用。我們可以隨時參考資料的原始狀態。因此,在這種情況下,一致性意味著安全。
隨著最近用於深度學習的開源MXNet框架的日益普及,使用MXNet-Clojure API實現深度學習更容易。
雖然現在有不同的API和機器學習庫可用於Clojure,但仍然有一個陡峭的學習曲線,以便流利。錯誤訊息可能含糊不清,公司需要願意提前投資以使用它來擴充套件其機器學習系統。隨著更多生產就緒系統的例子都是用Clojure編寫的,這種語言在未來幾年會越來越受歡迎,但前提是隨著Clojure的使用而增加的庫的數量和大小也會增加。

Haskell
Haskell是一種函式式語言,透過型別推斷和惰性求值進行靜態型別化。它基於Miranda程式語言的語義,被認為更加富有表現力,更快,更安全,可用於實現機器學習。
1.Haskell中的型別安全性提供了安全性和靈活性
型別安全性定義了變數可以容納的值型別的約束。這將有助於防止非法操作,提供更好的記憶體安全性,並減少邏輯錯誤。延遲評估意味著Haskell將延遲表示式的求值,直到需要它的值。它還避免了重複評估,這將節省執行時間。同時,延遲評估允許定義無限資料結構。這為程式設計師提供了無限的數學可能性。
2.Haskell中的簡單顯式程式碼提供了清晰的實現
Haskell的最大好處之一是它可以用非常明確的數學結構來描述演算法。您可以在幾行程式碼中表示模型。您也可以像讀取數學方程一樣閱讀程式碼。這在複雜演算法中非常強大,例如機器學習中的深度學習演算法。例如,前饋神經網路的單層的以下實現顯示了程式碼的可讀性。

import Numeric.LinearAlgebra.Static.Backprop
logistic :: Floating a => a -> a
logistic x = 1 / (1 + exp (-x))
feedForwardLog
   :: (KnownNat i, KnownNat o)
   => Model (L o i :& R o) (R i) (R o)
feedForwardLog (w :&& b) x = logistic (w #> x + b)


3.Haskell中的多核並行性提供了效能
在深度學習中,典型的神經網路將包含定義模型的一百萬個引數。此外,需要大量資料來學習這些引數,這在計算上非常耗時。在一臺機器上,使用多個核心並行共享記憶體和程式在實現深度學習時非常強大。但是,在Haskell中,實現多核並行性很容易。
Haskell的HLearn庫包含機器學習演算法實現,而Haskell 的張量流繫結可用於深度學習。同時,Parallel和Concurrent用於並行和併發。
雖然在Haskell中開發了一些機器學習庫,但仍需要為生產就緒的Haskell實現進行全面實現。雖然可用於特定深度學習和機器學習任務的公共庫有限,但Haskell在AI中的使用也將受到限制。像Aetion Technologies和瑞士信貸全球建模與分析集團這樣的公司正在他們的實施中使用Haskell- 這裡是使用它的組織的完整列表

結論
深度學習模型是複雜的數學模型,需要特定的功能分層。諸如Clojure和Haskell之類的函數語言程式設計語言通常可以用更接近模型數學的更清晰的程式碼來表示複雜性。這樣可以節省時間,提高效率並輕鬆管理程式碼庫。函數語言程式設計的特定屬性允許這些語言中的實現比其他語言更安全。隨著人工智慧技術的發展,人工智慧中大規模系統開發專案的需求評估這些語言將變得更加普遍。
 

相關文章