使用 Spark ML Pipeline 進行機器學習

Spark ML Pipeline 的引入,是受到 scikit-learn 的啓發,雖然 MLlib 已經足夠簡單實用,但如果目標數據集結構複雜,需要多次處理,或是在學習過程中,要使用多個轉化器 (Transformer) 和預測器 (Estimator),這種情況下使用 MLlib 將會讓程序結構極其複雜。所以,一個可用於構建複雜機器學習工作流應用的新庫已經出現了,它就是 Spark 1.2 版本之後引入的 ML Pipeline。ML Pipeline 是建立在 DataFrames 上的更高層次的 API 庫,旨在幫助使用者來創建和調試實際的機器學習工作流。

Pipeline 組件

DataFrame

ML API 使用 Spark SQL 中的 DataFrame 作爲機器學習數據集,可以容納很多種類型的數據:文本、向量、圖像和結構化數據等等。Spark DataFrame 以 RDD(Resilient Distributed Datasets) 爲基礎,但是帶有 Schema(數據庫中對象的集合)信息,類似於傳統數據庫中的二維表格。

Transformer

中文可譯作轉換器,繼承自 PipelineStage,它是一個算法,可以將一個 DataFrame 轉換成另一個 DataFrame。如:

  • 一個特徵轉換器對 DataFrame 的操作可能爲,讀取一個文本列,將其映射爲一個新的特徵向量列,然後輸出一個帶有特徵向量的新的 DataFrame。
  • 一個機器學習模型對 DataFrame 的操作可能爲,讀取一個帶有特徵向量的列,對每一個特徵向量進行預測,然後輸出一個帶有預測數據的新的 DataFrame。

Estimator

中文可譯作預測器,它也是一個算法。預測器通過 fit() 方法,接收一個 DataFrame 併產出一個模型。例如,邏輯迴歸 (LogisticRegression) 算法就是一種預測器,通過調用 fit() 方法來訓練得到一個邏輯迴歸模型。

⚠️ 注:Transformer.transform() 和 Estimator.fit() 都是無狀態的。未來可能會被有狀態的算法替代。每個轉換器和預測器都有唯一 ID,這在調參過程中很有用。

Pipeline

Pipeline 連接多個轉換器和預測器在一起,形成一個機器學習工作流。

在機器學習過程中,通過一系列的算法來處理和學習數據是很普遍的,例如,一個簡單的文檔處理工作流可能包括以下幾步:

MLlib 將上述一個工作流歸爲一個 Pipeline,包括一系列的 PipelineStage(多個 Transformer 和 Estimator),按特定的順序執行。

Parameter

所有的轉換器和預測器使用同一個 API 來指定參數。 一個 Param 是被定義好的已命名參數。一個 ParamMap 是一組“參數-值” (parameter, value) 對。

向一個算法傳參的方法主要有兩種:

  1. 爲實例設置參數。例如,lr 是 LogisticRegression 的一個實例,我們可以通過調用 lr.setMaxIter(10) 方法來設定 lr.fit() 最多進行10次迭代。這個 API 和 spark.mllib 包中的 API 相似。
  2. 通過 ParamMap 給 fit() 和 transform() 傳參。ParamMap 中的參數將會覆蓋之前通過 setter 方法設置過的參數。

如果我們有兩個 LogisticRegression 實例 lr1 和 lr2,可以創建一個包含兩個 maxIter 的 ParamMap:ParamMap(lr1.maxIter -> 10, lr2.maxIter -> 20)。如果一個 Pipeline 裏有兩個帶有 maxIter 的算法,這種方法比較實用。

 

工作原理

Pipeline 由一系列 stage 組成,每個 stage 爲一個轉換器 (Transformer) 或預測器 (Estimator)。這些 stage 的執行是按一定順序的,輸入的 DataFrame 在通過每個 stage 時被改變。在轉換器階段,transform() 方法作用在 DataFrame 上。預測器階段,調用 fit() 方法來產生一個轉換器(成爲 PipelneModel 的一部分),然後該轉換器的 transform() 方法作用在 DataFrame 上。

我們通過一個簡單的文檔工作流來解釋其工作原理,下圖展示了訓練過程中 Pipeline 的工作流程:

Pipeline 在訓練過程中的流程

上圖中,上面一行表示 Pipeline 的三個 stage。前兩個 Tokenizer 和 HashingTF 是轉換器,第三個 LogisticRegression 是一個預測器。下面一行表示通過 pipeline 的數據流,圓柱體代表 DataFrame。Pipeline.fit() 方法作用於原始 DataFrame,其中包含原始的文檔和標籤。Tokenizer.transform() 方法將原始文檔分成單個詞,將其作爲新的列加入 DataFrame。HashingTF.transform() 方法將文本列轉化成特徵向量,將這些向量作爲新的列加入 DataFrame。因爲 LogisticRegression 是一個預測器,Pipeline 首先調用 LogisticRegression.fit() 來產生一個 LogisticRegressionModel。如果 Pipeline 還有其他的預測器,在將 DataFrame 傳入下一個 stage 前,它將先調用 LogisticRegressionModel 的 transform() 方法。

整個 Pipeline 可以看作一個預測器。因此,在一個 Pipeline 的 fit() 方法執行完畢後,它會產生一個 PipelineModel,它是一個轉換器。這個 PipelineModel 可在測試階段調用,下圖展示了具體的工作流程:

 

PipelineModel 在測試過程中的流程

 

上圖中,PipelineModel 和原始 Pipeline 有相同數量的 stage,但原始 Pipeline 中的預測器都變成了轉換器。當 PipelineModel 的 transform() 方法被作用於測試數據集時,數據會按順序穿過 pipeline 的各個階段。每個 stage 的 transform() 方法都對數據集作了改變,然後再將其送至下一個 stage。

Pipeline 和 PipelineModel 有助於確保訓練數據和測試數據的特徵處理流程保持一致。

 

詳細信息

DAG Pipeline: Pipeline 的 stage 是一個有序數組。這裏引用的例子都是線性 Pipeline,其中的每個 stage 所用的數據都是由上一個 stage 產生的。但如果數據的流向爲一個有向無環圖 (DAG, Directed Acyclic Graph),那麼 Pipeline 就可以是非線性的。這種圖需要指定每個 stage 中輸入和輸出列的名字(通常通過參數來指定)。如果 Pipeline 的形式爲 DAG,那麼每個 stage 都必須爲拓撲排序。

Runtime checking: 因爲 Pipeline 可以運行在各種類型的 DataFrame 上,所以不能在編譯時檢查出錯誤類型。Pipeline 和 PipelineModel 會在 Pipeline 實際運行前進行檢查。這種類型檢查是基於 DataFrame schema 的,schema 包含了 DataFrame 中每一列數據的類型。

Unique Pipeline stages: Pipeline 的每一個 stage 都應該是唯一的實例。例如,同一個 myHashingTF 實例不應該進入 Pipeline 兩次,因爲 Pipeline stage 必須有唯一 ID。然而,不同的實例 myHashingTF1 和 myHashingTF2 可以進入同一個 Pipeline,因爲兩個實例是通過不同 ID 創建的。

 

存儲和讀取 Pipelines

通常情況下我們需要將一個模型或 pipeline 存儲在磁盤上供以後使用。在 Spark 1.6 中,模型的導入和導出功能加入了 Pipeline 的 API,支持大多數轉換器以及一些機器學習模型。具體還需參考算法的 API 文檔來確認其是否支持存儲和讀取。

 

歡迎關注我的知乎專欄【數據池塘】,專注於分享機器學習、數據挖掘相關內容:https://zhuanlan.zhihu.com/datapool

 

⬇️ 掃描下方二維碼關注公衆號【數據池塘】 ⬇️

回覆【算法】,獲取最全面的機器學習算法網絡圖:

發佈了38 篇原創文章 · 獲贊 23 · 訪問量 7萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章