利用Spark 和 scikit-learn 將你的模型訓練加快 100 倍

2020-12-04 雷鋒網

在 Ibotta,我們訓練了許多機器學習模型。這些模型為我們的推薦系統、搜尋引擎、定價優化引擎、數據質量等提供動力。它們在與我們的行動應用程式交互時為數百萬用戶做出預測。

當我們使用 Spark 進行數據處理時,我們首選的機器學習框架是 scikit-learn。隨著計算機變得越來越便宜,機器學習解決方案的上市時間變得越來越關鍵,我們探索了加快模型訓練的各種方法。其中一個解決方案是將 Spark 和 scikit-learn 中的元素組合到我們自己的混合解決方案中。

sk-dist 的介紹

我們很高興地宣布我們的開源項目 sk-dist 的啟動。該項目的目標是為使用 Spark 分發 scikit 學習元估計器提供一個通用框架。元估計器的例子有決策樹集合(隨機林和額外隨機樹)、超參數調解器(網格搜索和隨機搜索)和多分類技術(一對多和多對一)。


我們的主要動機是填補傳統機器學習模型空間的空白。在神經網絡和深度學習的空間之外,我們發現我們的訓練模型的大部分計算時間並沒有花在訓練單個數據集的單個模型上。相反,大部分時間都花在使用元估計器在數據集上訓練模型的多次迭代上。

例子

讓我們談談手寫數字數據集。在這裡,我們對手寫數字的圖像進行了適當的編碼、分類。我們可以很快在一臺機器上訓練 1797 條記錄的支持向量機,花費的時間不到一秒鐘。但超參數調整需要在訓練數據的不同子集上進行大量的訓練。

如下圖所示,我們已經構建了一個總計需要 1050 個訓練的參數網格。在擁有 100 多個核的 Spark 上使用 sk dist 只需 3.4 秒。這項工作的總時間是 7.2 分鐘,意思是在沒有並行化的單機上訓練要花這麼長時間。

import timefrom sklearn import datasets, svm
from skdist.distribute.search import DistGridSearchCV
from pyspark.sql import SparkSession # instantiate spark session
spark = (  
   SparkSession    
   .builder    
   .getOrCreate()    
   )
sc = spark.sparkContext # the digits dataset
digits = datasets.load_digits()
X = digits["data"]
y = digits["target"] # create a classifier: a support vector classifier
classifier = svm.SVC()
param_grid = {
   "C": [0.01, 0.01, 0.1, 1.0, 10.0, 20.0, 50.0],
   "gamma": ["scale", "auto", 0.001, 0.01, 0.1],
   "kernel": ["rbf", "poly", "sigmoid"]
   }
scoring = "f1_weighted"
cv = 10# hyperparameter optimization
start = time.time()
model = DistGridSearchCV(    
   classifier, param_grid,    
   sc=sc, cv=cv, scoring=scoring,
   verbose=True    
   )
model.fit(X,y)
print("Train time: {0}".format(time.time() - start))
print("Best score: {0}".format(model.best_score_))------------------------------
Spark context found; running with spark
Fitting 10 folds for each of 105 candidates, totalling 1050 fits
Train time: 3.380601406097412
Best score: 0.981450024203508

這個例子演示了一個常見的場景,在這個場景中,將數據擬合到內存中並訓練單個分類器是很簡單的,但是適合超參數優化所需的匹配數量會迅速增加。下面是一個運行網格搜索問題的例子,和上面的 sk dist 示例類似:

帶sk-dist的網格搜索

對於 ibotta 傳統機器學習的實際應用,我們經常發現自己處於類似這樣的情況中:中小型數據(10k 到 1M 的記錄)和許多簡單分類器迭代以適應超參數調整、集成和多分類解決方案。

現有解決方案

傳統的機器學習元估計器訓練方法已經存在。第一個是最簡單的:scikit-learn 使用 joblib 內置的元估計器並行化。這與 sk-dist 的操作非常相似,但是它有一個主要的限制:性能受限於任何機器的資源。即使與理論上擁有數百個內核的單機相比,Spark 仍然具有一些優勢,如執行器的微調內存規範、容錯,以及成本控制選項,如對工作節點使用 spot 實例。

另一個現有的解決方案是 Spark ML,它是 Spark 的一個本地機器學習庫,支持許多與 scikit-learn 相同的算法來解決分類和回歸問題。它還具有諸如樹集合和網格搜索之類的元估計器,以及對多分類問題的支持。

分布在不同的維度上

如上所示,Spark ML 將針對分布在多個執行器上的數據來訓練單個模型。當數據量很大,以至於無法存入一臺機器上的內存時,這種方法可以很好地工作。然而,當數據量很小時,在單臺機器上這可能會比 scikit-learn 的學習效果差。此外,例如,當訓練一個隨機森林時,Spark ML 按順序訓練每個決策樹。此項工作的時間將與決策樹的數量成線性比例,和分配給該任務的資源無關。

對於網格搜索,Spark ML 實現了一個並行參數,該參數將並行地訓練各個模型。然而,每個單獨的模型仍在對分布在執行器之間的數據進行訓練。這項任務的總並行度只是純粹按照模型維度來的,而不是數據分布的維度。

最後,我們希望將我們的訓練分布在與 Spark ML 不同的維度上。當使用中小型數據時,將數據擬合到內存中不是問題。對於隨機森林的例子,我們希望將訓練數據完整地廣播給每個執行器,在每個執行者身上擬合一個獨立的決策樹,並將這些擬合的決策樹帶回給驅動器,以集合成一個隨機森林。這個維度比串行分布數據和訓練決策樹快幾個數量級。

特徵

考慮到這些現有解決方案在我們的問題空間中的局限性,我們內部決定開發 sk-dist。歸根結底,我們希望發布的是模型,而不是數據。

雖然 sk-dist 主要關注元估計器的分布式訓練,但它也包括很多其它模塊,如 Spark 的 scikit-learn 模型的分布式預測模塊等。

  • 分布式訓練——使用 Spark 進行分布式元估計訓練,支持以下算法:帶網格搜索和隨機搜索的超參數優化、帶隨機林的樹集合、額外樹和隨機樹嵌入,以及一對一和一對多的多分類策略。

  • 分布預測——具有 Spark 數據幀的擬合 scikit-learn 估計器的預測方法。這使得帶有 scikit-learn 的大規模分布式預測可以在沒有 Spark 的情況下進行。

  • 特徵編碼——分布特徵編碼使用被稱為編碼器的靈活特徵變換器來完成。不管有沒有 Spark,它都可以起作用。它將推斷數據類型,自動應用默認的特徵變換器作為標準特徵編碼技術的最佳實現。它還可以作為一個完全可定製的功能聯合,如編碼器,它的附加優勢是與 Spark 匹配的分布式 transformer。

用例

以下是判斷 sk-dist 是否適合解決你的機器學習問題的一些準則:

  1. 傳統的機器學習方法,如廣義線性模型、隨機梯度下降、最近鄰、決策樹和樸素貝葉斯等,都能很好地應用於 sk-dist,這些方法都可以在 scikit-learn 中實現,並且可以直接應用於 sk-dist 元估計。

  2. 中小型數據、大數據不能很好地在 sk-dist 中起作用。記住,分布式訓練的維度是沿著模型的軸,而不是數據。數據不僅需要放在每個執行器的內存中,而且要小到可以傳播。根據 Spark 配置,最大傳播大小可能會受到限制。

  3. Spark 定向和訪問——sk-dist 的核心功能需要運行 Spark。對於個人或小型數據科學團隊來說,這並不總是可行的。

這裡一個重要的注意事項是,雖然神經網絡和深度學習在技術上可以用於 sk-dist,但這些技術需要大量的訓練數據,有時需要專門的基礎設施才能有效。深度學習不是 sk-dist 的最佳用例,因為它違反了上面的(1)和(2)。

開始

要開始使用 sk-dist,請查看安裝指南。代碼庫還包含一個示例庫,用於說明 sk-dist 的一些用例。歡迎所有人提交問題並為項目做出貢獻。

via:https://medium.com/building-ibotta/train-sklearn-100x-faster-bec530fc1f45

雷鋒網雷鋒網(公眾號:雷鋒網)雷鋒網

雷鋒網版權文章,未經授權禁止轉載。詳情見轉載須知。

相關焦點

  • 如何在Apache Pyspark中運行Scikit-learn模型
    在本文中,我們將了解如何在Apache Pyspark中運行Scikit-learn模型,並討論有關每個步驟的細節。如果您已經準備好了機器學習模型,則可以直接跳到「 pyspark wrapper」部分,也可以通過以下步驟創建一個簡單的scikit learn機器學習模型。
  • 將sklearn訓練速度提升100多倍,美國「返利網」開源sk-dist框架
    這是一個分配 scikit-learn 元估計器的 Spark 通用框架,它結合了 Spark 和 scikit-learn 中的元素,可以將 sklearn 的訓練速度提升 100 多倍。在 Ibotta,我們訓練了許多機器學習模型。這些模型為我們的推薦系統、搜尋引擎、定價優化引擎、數據質量等提供了支持,在與我們的移動 app 互動的同時為數百萬用戶做出預測。
  • Python機器學習5:使用scikit-learn實現三種集成學習Bagging算法
    如果你在解決一個問題時實現了多種模型,但是每個模型的效果都差不多,但是你想要進一步提升最後預測效果,那麼本文將強烈建議你使用集成學習算法來實現!集成學習算法指的是將已有的多種模型綜合起來,實現最終分類或者回歸。一般而言,集成學習可以提高原有算法模型的準確性。
  • WePay機器學習反欺詐實踐:Python+scikit-learn+隨機森林
    【編者按】將機器學習算法用於金融領域的一個很好的突破口是反欺詐,在這篇博文中,WePay介紹了支付行業構建機器學習模型應對很難發現的shell selling欺詐的實踐心得。WePay採用了流行的Python、scikit-learn開源學習機器學習工具以及隨機森林算法。
  • Scikit-learn玩得很熟了?這些功能你都知道嗎?
    Scikit-learn是Python所有的機器學習程序包中,你必須掌握的最重要的一個包,它包含各種分類算法,回歸算法和聚類算法,其中包括支持向量機、隨機森林、梯度提升、k均值和基於密度的聚類算法(DBSCAN),且旨在與Python數值庫NumPy和科學庫SciPy進行相互配合。它通過一個接口,提供了一系列的有監督和無監督算法。
  • CDA承接的全球頂級機器學習Scikit-learn 中文社區上線啦!
    (注:scikit-learn的官網是www.scikit-learn.org,CDA承接的中文社區網址是www.scikit-learn.org.cn,這同時也標誌著CDA與全球頂級深度學習和機器學習框架更進一步融合,CDA認證更加得到全球頂級技術框架的認可!
  • 開源機器學習框架:Scikit-learn API簡介
    這主要體現在兩個方面:一是Scikit-learn從來不做除機器學習領域之外的其他擴展,二是Scikit-learn從來不採用未經廣泛驗證的算法。Scikit-learn的六大功能Scikit-learn的基本功能主要被分為六大部分:分類,回歸,聚類,數據降維,模型選擇和數據預處理。
  • Scikit-Learn 學得如何?程式設計師不容錯過十大實用功能來襲
    所有數據加載函數都提供了選項,可以將數據被拆分成X(特徵)和y(目標)之後再返回,這樣返回值就可以直接用於訓練模型。這個模型本質上是一個「笨」模型,通常它只能預測最常出現的類別。這個模型可以為你的「智能」模型提供一個基準,這樣才能判斷出模型的效果要優於隨意選擇的結果。Scikit-learn包含一個處理分類任務的DummyClassifier()和一個處理回歸問題的DummyRegressor()。
  • Python機器學習7:如何保存、加載訓練好的機器學習模型
    本文將介紹如何使用scikit-learn機器學習庫保存Python機器學習模型、加載已經訓練好的模型。學會了這個,你才能夠用已有的模型做預測,而不需要每次都重新訓練模型。本文將使用兩種方法來實現模型的保存和加載:Pickle和joblib。
  • Python粉都應該知道的開源機器學習框架:Scikit-learn入門指南
    Scikit-learn的六大功能Scikit-learn的基本功能主要被分為六大部分:分類,回歸,聚類,數據降維,模型選擇和數據預處理。分類是指識別給定對象的所屬類別,屬於監督學習的範疇,最常見的應用場景包括垃圾郵件檢測和圖像識別等。
  • 針對線性回歸模型和深度學習模型,介紹了確定訓練數據集規模的方法
    因此,對於機器學習的一個非常關鍵的問題是,確定能使模型達到某個特定目標(如分類器精度)所需要的訓練數據規模。 在本文中,我們將對經驗性結果和研究文獻中關於訓練數據規模的討論進行簡明扼要的綜述,涉及的機器學習模型包括回歸分析等基本模型,以及複雜模型如深度學習。
  • 使用scikit-learn進行特徵選擇
    scikit-learn中提供了用於特徵選擇的模塊feature_selection,主要方法包括方差移除法,卡方檢驗法,基於L1的特徵選擇和基於樹的特徵選擇
  • 超參數調整實戰:scikit-learn配合XGBoost的競賽top20策略
    但是,僅僅通過XGBoost並不能完成完成整的解決方案,同樣的模型為什麼有些人能獲得更好的準確性呢?除了經驗方面的差異,還有一個事實,那就是他們優化了超參數!因此,我們今天將告訴您如何獲取特定數據集的最佳超參數。我們將在Hacker Earth挑戰的數據集上使用scikit-learn配合XGBoost。
  • 百聞不如一練:可視化調試模型超參數!
    該例子以手寫數據集為例,使用支持向量機的方法對數據進行建模,然後調用scikit-learn中validation_surve方法將模型交叉驗證的結果進行可視化。需要注意的是,在使用validation_curve方法時,只能驗證一個超參數與模型訓練集和驗證集得分的關係(即二維的可視化),而不能實現多參數與得分間關係的可視化。
  • GPU上的隨機森林:比Apache Spark快2000倍
    在本文中,我們探索了使用Apache Spark在CPU機器集群上實現分布式隨機森林訓練,並將其與使用NVIDIA RAPIDS和Dask的GPU機器集群上的訓練性能進行了比較。雖然GPU計算傳統上是為深度學習應用而保留的,但RAPIDS是一個在GPU上執行數據處理和非深度學習ML工作的庫,與在cpu上執行相比,它可以大大提高性能。
  • 每個數據科學家都得會一點SparkMagic
    它提供了一組Jupyter Notebook單元魔術和內核,可將Jupyter變成用於遠程集群的集成Spark環境。(例如,將經過預訓練的本地ML模型直接發送到Spark集群)可以使用以下Dockerfile來構建具有SparkMagic支持的Jupyter Notebook:FROM jupyter/all-spark-notebook:7a0c7325e470USER$NB_USERRUN pip install --upgrade pipRUN pip
  • 基於Bert和通用句子編碼的Spark-NLP文本分類
    Spark-NLP中的文本分類在本文中,我們將使用通用句子嵌入(Universal Sentence Embeddings)在Spark NLP中建立一個文本分類模型。然後我們將與其他ML和DL方法以及文本向量化方法進行比較。
  • 神經網絡初學者指南:基於Scikit-Learn的Python模塊
    | 訓練模型現在該訓練我們的模型了。 通過估計對象, SciKit Learn 使這一切變得極其容易。在這種情況下,我們將從 SciKit-Learn 的 neural_network 庫導入我們的估計器(多層感知器分類器模型)。我們接下來將創建一個模型的實例,你可以定義很多參數和自定義,我們將只定義 hidden_layer_sizes。 對於此參數,您傳遞一個元組,其中在每一層包含你想要的神經元數量,其中元組中的第 n 個條目表示 MLP 模型的第 n 層中的神經元的數量。
  • 為什麼我的模型表現這麼差?
    如果你繼續閱讀本文,你將學到如何識別這些現象的必要的知識,並獲得如何克服這些現象的工具和補救措施,最終提高你的模型性能,這是每一個機器學習工程師的真正目標。我們將從回歸的角度出發,通過 Python 和 scikit-learn 提供的代碼示例來研究這個主題。