【Scala-ML】如何利用Scala構建並行機器學習系統
引言
在學習Scala的過程中,我發現其在構建大規模分散式計算系統上有與生俱來的特質。其豐富的型別系統可以幫助程式設計設計提供很好的資訊隱藏和抽象,其monoids和monads概念利用Scala高階函式實現計算並行和資料處理流水線,其Actor系統幫助編寫可伸縮性的應用程式,其實現特定領域語言的優勢幫助開發使用者很好克服不同語言的障礙。
雖然以上Scala優點說起來不會感同身受,但這可以作為我學習的一大動力,讓我開始嘗試編寫並行機器學習系統。
在學習過程中,我主要參考《Scala for Machine Learning》一書和相關網上的資料。希望這些分享能幫助自己學習,也更好的服務有興趣的讀者。
為何使用Scala構建機器學習系統
抽象
Monoids和Monads是函數語言程式設計的重要概念。
Monoids定義了在具有閉包性質(property of closure)的資料集上的二元操作op,恆等操作(identity operation)和結合性(associativity)。
下面是程式碼描述:
trait Monoid[T] {
def zero: T
def op(a: T, b: T): T
}
Monoids具有結合性的操作。假設ts1、ts2、ts3是三個時間序列,該性質保證ts1+(ts2+ts3) = (ts1+ts2)+ts3。Monoid的結合性對於計算流的並行化是很關鍵的。
Monads可以被認為是容器的結構,它是Monoids的推廣。像是Scala標準庫中的List,Map等集合被設計成monads的結構。
Monads提供了以下的功能:1. 建立集合; 2. 對集合的元素進行轉換; 3. 壓平巢狀的集合。
下面是Scala程式碼描述:
trait Monad[M[_]] {
def apply[T](a: T): M[T]
def flatMap[T, U](m: M[T])(f: T=>M[U]): M[U]
}
Monads允許集合或者容器連線起來產生一個工作流,該性質可以應用在任何科學計算中。
可擴充套件性
Actors系統使得Scala程式設計變得可伸縮、可擴充套件。Actors作為協程(coroutines),通過非同步訊息進行通訊,管理底層的執行緒池。
機器學習的工作流被實現成一系列的計算任務,這些任務包含了Scala的高階方法(如flatMap,map,fold,reduce,collect,join,filter)對資料集合的操作,Scala允許actors叢集對這些資料進行分割來完成計算任務。Scala還支援本地或遠端的actor之間進行訊息分發和訊息路由。
上圖中,主節點作為控制器,管理和排程四步任務。這些具體的任務通過Scala的actors實現的多個工作節點執行。主節點通過和工作節點交換訊息來管理工作流的執行狀態,負責可靠性。通過監督actors的層次結構來實現計算任務的高可用性。
可配置性
Scala支援依賴注入(dependency injection),通過抽象變數(abstract variables)、自引用成分(self-referenced composition)和可堆疊的特質(stackable traits)的組合來實現。最常用的依賴注入的模式成為cake pattern,該模式在構建動態計算工作流中經常用到。
可維護性
Scala內嵌了領域專用語言(Domain Specific Languages,DSL)。DSLs是在Scala原生庫上建立的語法層,DSLs允許軟體開發者抽象計算細節,更好讓使用者理解。DSLs最有名的應用案例就是在Matlab中的語法形式。
計算工作流
一個計算工作流(computational workflow)可以分為以下幾個步驟:
1. 從檔案或資料庫中載入資料集
2. 將資料集進行分割,用於並行的資料處理
3. 運用過濾技術、方差分析等進行資料預處理
4. 應用機器學習模型
在使用訓練資料進行分析的過程還需要一些具體的處理:
- 從清洗的輸入資料中選擇訓練集、測試集、驗證集
- 抽取關鍵特徵、利用聚類技術從一組相似觀測中簡歷親近關係
- 減少特徵數量,避免訓練資料過擬合
- 重複進行多次上述步驟來驗證模型和調整模型
- 將模型進行持久化,用於新觀測資料的預測和處理
- 評估模型表現