MLlib是Spark的機器學習lib,目的是讓機器學習的實踐變得更加簡單,總的來說它提供了以下幾種工具:
ML算法:分類、回歸、聚類和協同過濾等常用學習算法
特征工程:特征提取、轉換、降維和選擇
Pipelines:創建、評價和調優的ML Pipelines工具
存儲:保存和加載算法、模型和Pipeline
實用工具:線性代數、統計、數據處理等
需要添加的Maven依賴:
DataFrame的API是最主要的API
從Spark 2.0開始,RDD接口的API進入到了維護狀態,所以現在機器學習的最主要的API是DataFrame接口的API。
這意味著:
1、MLlib仍然支持修復bug的RDD接口的API
2、MLlib不會向RDD的API加入新的特性了
3、在接下來的2.x版本中MLlib將持續添加DataFrame接口的API的特性來達到和RDD API相等的程度。
4、在達到相等的程度后RDD接口的API將會被拋棄。(粗略估計在2.2版本)
5、預計在3.0版本上徹底移除RDD接口的API
為什么MLlib轉去使用DataFrame接口的API
1、DataFrame接口的API對用戶更加友好。包括使用Spark的Datasources,SQL/DataFrame查詢語句,Tungsten和Catalyst執行優化器,以及跨語言統一的API接口
2、DataFrame幫助更好使用ML Pipeline,尤其是Transformation特性。
依賴包
MLlib使用了線性代數包Breeze,這個包依賴來netlib-java優化數值計算。如果運行時native libraries不可用,你將看到一個警告提示信息,然后使用純虛擬機進行處理。
因為licence的緣故,我們默認不使用netlib-java的native proxies。配置netlib-java/Breeze來使用系統的優化庫,包括在你的工程中加入com.github.fommil.netlib:all:1.1.2(或者build Spark的時候帶上-Pnetlib-lgpl)作為依賴,請閱讀netlib-java官方文檔來獲得安裝說明。(目前運行后面example代碼的時候還是出現warn顯示Native BLAS的加載有問題。這個問題真是有些頭大。。。)
基于Python語言使用MLlib,需要安裝1.4以上版本Numpy。
ML Pipelines
下面開始介紹ML Pipelines。雖然 MLlib 已經足夠簡單易用,但是如果目標數據集結構復雜需要多次處理,或者是對新數據進行預測的時候需要結合多個已經訓練好的單個模型進行綜合預測 (集成學習的思想),那么使用 MLlib 將會讓程序結構復雜,難于理解和實現。值得慶幸的是,在 Spark 的生態系統里,一個可以用于構建復雜機器學習工作流應用的新庫已經出現了,它就是 Spark 1.2 版本之后引入的 ML Pipeline。
====================
Pipelines中的主要概念
基于MLlib提供的機器學習算法的標準API,我們可以非常簡單的組合多種不同的算法成為一個pipeline或者workflow。下面將會介紹Pipeline API中的幾個關鍵概念,其中這些概念主要是受項目scikit-learn的啟發。
DataFrame:ML API使用這個來自Spark SQL的概念作為ML dataset,可以保存多種數據類型。比如:使用不同的列存儲文本、特征向量、真實標簽和預測結果。
Transformer:這是個是指一個算法將一個DataFrame transform成另一個DataFrame。也就是訓練好的模型。比如:一個ML模型就是一個Transformer能夠將一個特征數據的DataFrame轉成預測結果的DataFrame。
Estimator:是指一個操作DataFrame產生Transformer的算法。比如:一個學習算法就是一個Estimator,可以在一個DataFrame上訓練得到一個模型。
Pipeline:一個Pipeline鏈是將多個Transformer和Estimator組合在一起組成一個ML workflow。
Parameter:所有的Transformer和Estimator共享一個公共的說明參數的API。
Pipeline組件
Transformer
Transformer是一個抽象類,包括特征轉換以及學習后的模型兩種情況。不管是哪一種都需要實現方法transform(),用以將一個DataFrame轉換成另一個,通常都是添加一個或多個列。
比如:
特征轉換是:讀取一個列(比如:text)然后映射為一個新列(比如:特征向量),輸出的新DataFrame就是將新映射出來的列加到原來的DataFrame中。
學習后的模型:讀取一個DataFrame(包含特征向量),對于每個特征向量預測label,最后輸出攜帶預測結果的新的DataFrame。
Estimator
這個是一個學習算法的抽象,可以對數據fit或者train。一個Estimator需要實現方法fit(),這個方法接收一個DataFrame并輸出一個模型也就是Transformer。比如:LogisticRegression就是一個Estimator,通過調用fit()訓練得到LogisticRegressionModel,這個輸出模型也就是Transformer。
===================
Pipeline
在機器學習中,通常有一系列的算法在數據中處理和學習。比如:一個簡單的數據文本處理流程大概分為下面幾個階段:
將文本分割成words
將words轉化為數值型的特征向量
通過特征向量和標簽學習得到一個預測模型
MLlib將上述workflow定義為Pipeline,它包含了一連串的PipelineStage(Transformer和Estimator)按照特定的順序運行。
如何工作
Pipeline定義了一連串的Stage,每個Stage不是Transformer就是Estimator,這些Stage按照順序執行。
對于一個簡單文本的處理流程,下圖展示了Pipeline的training time
在上圖中第一行包括三個Stage,藍色的前兩個Stage(Tokenizer和HashingTF)是Transformer類型的,最后紅色的LogisticRegression是Estimator類型的。第二行中的每個圓柱體都表示DataFrame。經過Tokenizer.transform()、HashingTF.transform()以及LogisticRegression.fit()之后,產生LogisticRegressionModel。
接下來就是調用LogisticRegressionModel’stransform()如下圖所示,被稱為test time
細節
DAGPipelines: Pipeline的Stage被規定為有序數組。在上面簡單用例中可以看到是線性的,也就是后一個Stage用到的數據是前一個Stage的輸出。當然也可以創建非線性的Pipeline只要數據流圖是DAG的。
Runtime checking:因為DataFrame支持多種數據類型,所以不能可能在編譯時進行檢查,只能在運行時通過DataFrame的schema進行檢查。
Unique Pipeline stages: Pipeline中的每一個Stage都應該是唯一性的實例。比如同一個實例myHashingTF不應該插入到Pipeline的中兩次,也就是說Pipeline的每個Stage的ID都必須是唯一的。然而同一個類型的兩個不同的實例可以插入一個Pipeline中,并創建不同的ID。
Parameters
MLlib的Estimator和Transformer使用統一的API來管理參數。
ParamMap是一個(parameter, value)的集合。
有兩種方法對算法傳入參數:
1、通過實例來設置參數。比如:lr是LogisticRegression的一個實例,那么lr.setMaxIter(10)就是讓lr在調用fit()方法的時候使用最大10次迭代的參數。
2、通過ParamMap對fit()和transform()設置參數。如果在方法fit()或者transform()中傳入ParamMap的對象那么就會覆蓋之前的參數設置。
舉例如果有兩個LogisticRegression類型的實例lr1和lr2,我們可以使用ParamMap這樣對參數賦值ParamMap(lr1.maxIter -> 10, lr2.maxIter -> 20)。具體Java代碼實例看下面
保存和加載Pipeline
有非常多的情況需要將一個模型或者一個Pipeline保存到硬盤上。絕大多數的基礎Transformer和基礎ML模型都支持,不過具體的還是要看算法的API文檔來查詢是否支持。
==================
代碼示例
Example: Estimator, Transformer, and Param
Example: Pipeline
下面這個例子是對前面介紹Pipeline時簡單示例的兩個流程圖示例的代碼實現:
這個例子看下來就能更好的理解上面講的Pipeline了,果然是流水線的處理方式,構造一次之后就可以不停的接收訓練集輸出model,然后再喂入測試集輸出測試結果的DataFrame。
至此,就把Pipeline的Spark官網內容介紹完畢了。