1. 程式人生 > >Apache Spark 2.0: 機器學習模型持久化

Apache Spark 2.0: 機器學習模型持久化

在即將釋出的Apache Spark 2.0中將會提供機器學習模型持久化能力。機器學習模型持久化(機器學習模型的儲存和載入)使得以下三類機器學習場景變得容易:

  • 資料科學家開發ML模型並移交給工程師團隊在生產環境中釋出;

  • 資料工程師把一個Python語言開發的機器學習模型訓練工作流整合到一個Java語言開發的機器學習服務工作流;

  • 資料科學家建立多個訓練ML模型的作業,稍後需要儲存和評估。

Spark MLlib將提供基於DataFrame的API來支援ML持久化。後面將分三部分介紹:概要、程式碼例項和MLlib持久化API一些小細節。

概要

ML持久化關鍵特色:

  • 支援Spark原有的多種開發語言:Scala、Java和Python & R;

  • 基於DataFrame的API幾乎支援所有的ML演算法;

  • 支援單個ML模型和多管道ML模型;

  • 使用可轉換格式分散式儲存機器學習模型

學學API

在Apache Spark 2.0中,機器學習元件MLlib提供基於DataFrame的API,可實現類似於Spark資料來源API的儲存和載入功能,見以前的文章。

作者使用經典的機器學習例子(手寫數字識別,使用MNIST資料庫,MNIST資料庫包含0到9的手寫數字和標註標記資料)來證實ML模型儲存和載入功能。作者取其它手寫數字並鑑別數字是幾,完整例子程式碼見notebook:載入資料、訓練模型和儲存以及載入模型。

儲存和載入單模型

首先展示如何使用不同程式語言儲存和載入同一單模型。作者使用Python訓練和儲存隨機森林分類器模型,然後使用Scala來載入同一個ML模型回來。

training = sqlContext.read...  # data: features, label
rf = RandomForestClassifier(numTrees=20)
model = rf.fit(training)

可以簡單的呼叫save方法來儲存上面訓練好的ML模型,然後使用load方法再載入回來。

model.save("myModelPath")
sameModel = RandomForestClassificationModel.load
("myModelPath")

這裡也可以載入剛才同一個ML模型(使用Python儲存)進入Scala或者Java應用。

// Load the model in Scala
val sameModel = RandomForestClassificationModel.load("myModelPath")

這個工作既可以對小資料量、區域性模型(比如,常見的分類模型K-Means)適用,也可以對海量資料、分散式模型(比如,常見的推薦模型ALS)。剛載入的模型都包含有相同的引數設定和訓練資料,所以即使在不同的Spark部署載入同一個模型也會得到相同的預測結果。

儲存和載入多管道模型

前面僅僅描述來儲存和載入單個ML模型,而實際應用中,ML工作流包含多階段:從特徵提取和轉化到模型擬合和優化。MLlib會提供Pipeline來輔助使用者來構建這些工作流。

MLlib提供使用者儲存和載入整個Pipeline。下面來看下如何來實現:

  • 特徵提取:影象資料二值化為0和1(黑和白);

  • 模型擬合:隨即森林分類器讀取影象資料並預測數字0到9;

  • 優化結果:交叉驗證來優化樹的深度。看下程式碼:

// Construct the Pipeline: Binarizer + Random Forest
val pipeline = new Pipeline().setStages(Array(binarizer, rf))
 
// Wrap the Pipeline in CrossValidator to do model tuning.
val cv = new CrossValidator().setEstimator(pipeline) ...

在這個管道擬合模型前先來展示我們如何儲存整個ML工作流。這個工作流將在其它Spark集群后續被載入。

cv.save("myCVPath")
val sameCV = CrossValidator.load("myCVPath")

最後,我們擬合模型管道,儲存管道,並在以後進行載入。下面儲存了特徵抽取、隨機森林模型交叉驗證的優化以及模型優化對應的統計資料。

val cvModel = cv.fit(training)
cvModel.save("myCVModelPath")
val sameCVModel = CrossValidatorModel.load("myCVModelPath")

細節知識點

Python優化

在Spark 2.0中並沒有提供Python優化功能,Python不支援儲存和載入CrossValidator和TrainValidationSplit來做模型超引數優化,這個功能將在Spark 2.1中實現(SPARK-13786)。但是Python還是可以儲存CrossValidator和TrainValidationSplit的結果。例如,我們可以使用Cross-Validation優化隨機森林模型並儲存除錯好的優化模型。

# Define the workflow
rf = RandomForestClassifier()
cv = CrossValidator(estimator=rf, ...)
# Fit the model, running Cross-Validation
cvModel = cv.fit(trainingData)
# Extract the results, i.e., the best Random Forest model
bestModel = cvModel.bestModel
# Save the RandomForest model
bestModel.save("rfModelPath")

可轉換的儲存格式

本質上,我們把模型元資料和引數儲存為JSON,資料集儲存成Parquet。這些儲存格式是可轉換的,並且也能被其它開發庫讀取。Parquet檔案允許使用者儲存小模型(比如,貝葉斯分類)和分散式模型(比如,ALS)。儲存路徑可以是任意Dataset/DataFrame支援的URI,比如S3、本地儲存等。

跨語言相容性

機器學習模型可以在Scala、Java和Python & R間任意儲存和載入。但R語言有兩個侷限性:第一,不是所有MLlib模型都支援R語言,所以不是所有的使用其它語言訓練的模型能被R語言載入;第二,使用R獨有的方式的R模型格式儲存不易被其它語言使用。

結論

隨著Spark 2.0的即將釋出,基於DataFrame的MLlib API將會提供幾乎完善的模型和機器學習管道持久化。機器學習模型持久化在團隊間合作、多程式語言ML工作流以及遷移模型到生產環境方面相當重要。基於DataFrame的MLlib API也將最終會成為Spark在機器學習方面主要的API。