當前位置:
首頁 > 科技 > 迭代速度慢?成熟的機器學習流如何設計:微博大規模機器學習框架Weiflow揭秘

迭代速度慢?成熟的機器學習流如何設計:微博大規模機器學習框架Weiflow揭秘

在機器學習流中,模型訓練只是其中耗時最短的一環。如果把機器學習流比作烹飪,那麼模型訓練就是最後翻炒的過程;烹飪的大部分時間實際上都花在了食材、佐料的挑選,洗菜、擇菜,食材再加工(切丁、切塊、過油、預熱)等步驟。

在微博的機器學習流中,原始樣本生成、數據處理、特徵工程、訓練樣本生成、模型後期的測試、評估等步驟所需要投入的時間和精力,佔據了整個流程的 80% 之多。

如何能夠高效地端到端進行機器學習流的開發,如何能夠根據線上的反饋及時地選取高區分度特徵,對模型進行優化,驗證模型的有效性,加速模型迭代效率,滿足線上的要求,都是我們需要解決的問題。

Weiflow 的誕生源自於微博機器學習流的業務需求,在微博的機器學習流圖中(如圖1所示),多種數據流(如發博流、曝光流、互動流)經過 Spark Streaming、Storm 的實時處理,存儲至特徵工程並生成離線的原始樣本。

迭代速度慢?成熟的機器學習流如何設計:微博大規模機器學習框架Weiflow揭秘

圖1 微博機器學習流圖

在離線系統,根據業務人員的開發經驗,對原始樣本進行各式各樣的數據處理(統計、清洗、過濾、採樣等)、特徵處理、特徵映射,從而生成可訓練的訓練樣本;業務人員根據實際業務場景(排序、推薦),選擇不同的演算法模型(LR、GBDT、頻繁項集、SVM、DNN 等),進行模型訓練、預測、測試和評估;待模型迭代滿足要求後,通過自動部署將模型文件和映射規則部署到線上。

線上系統根據模型文件和映射規則,從特徵工程中拉取相關的特徵值,並根據映射規則進行預處理,生成可用於預測的樣本格式,進行線上的實時預測,最終將預測的結果(用戶對微博內容的興趣程度)輸出,供線上服務調用。

Weiflow 的設計初衷就是將微博機器學習流的開發簡單化、傻瓜化,讓業務開發人員從紛繁複雜的數據處理、特徵工程、模型工程中解脫出來。

開發人員可以將寶貴的時間和精力投入到業務場景的開發和優化當中,徹底解放業務人員的生產力,大幅提升開發效率。

考慮到微博業務場景越來越複雜、多樣的趨勢,Weiflow 在設計之初就充分考慮並權衡了框架的開發效率、可擴展性和執行效率。

Weiflow 通過統一格式的配置文件式開發(XML 流程文件),允許業務人員像搭積木一樣靈活地將需要用到的模塊(數據處理、特徵映射、生成訓練樣本、模型的訓練、預測、測試、評估等)堆疊到一起,根據依賴關係形成計算流圖(Directed Acyclic Graph有向無環圖),Weiflow 將自動解析不同模塊之間的依賴關係,並調用每個模型的執行類進行流水線式的作業。

對於每一個計算模塊,用戶無需關心其內部實現、執行效率,只需關心與業務開發相關的參數調優,如演算法的超參數、數據採樣率、採樣方式、特徵映射規則、數據統計方式、數據清洗規則等等,從而大幅提升開發效率、模型迭代速度。

為了讓更多的開發者(包括具有代碼能力的業務人員)能夠參與到 Weiflow 的開發中來,Weiflow 設計並提供了豐富的多層次抽象,基於預定義的基類和介面,允許開發者根據新的業務需求實現自己的處理模塊(如新的演算法模型訓練、預測、評估模塊)、計算函數(如複雜的特徵計算公式、特徵組合函數等),從而不斷豐富、擴展 Weiflow 的功能。

在框架的執行效率方面,在第二層 DAG 中(後面將詳細介紹 Weiflow 的雙層 DAG 結構),充分利用各種計算引擎(Spark、Tensorflow、Hive、Storm、Flink 等)的優化機制,同時結合巧妙的數據結構設計與開發語言(如 Scala 的 Currying、Partial Functions 等)本身的特性,保證框架在提供足夠的靈活性和近乎無限的可擴展性的基礎上,儘可能地提升執行性能。

為了應對微博多樣的計算環境(Spark、Tensorflow、Hive、Storm、Flink等),Weiflow 採用了雙層的 DAG 任務流設計,如圖 2 所示。

迭代速度慢?成熟的機器學習流如何設計:微博大規模機器學習框架Weiflow揭秘

圖2 Weiflow雙層DAG任務流設計

外層的 DAG 由不同的 node 構成,每一個 node 具備獨立的執行環境,即上文提及的 Spark、Tensorflow、Hive、Storm、Flink 等計算引擎。外層 DAG 設計的初衷是讓最合適的鎚子去敲擊最適合的釘子,大多數計算引擎因其設計階段的歷史局限性,都很難做到兼顧所有的工作負載類型,而是在不同程度上更好地支持某些負載(如批處理、流式實時處理、即時查詢、分析型數據倉庫、機器學習、圖計算、交易型資料庫等),因此我們的思路是讓用戶選擇最適合自己業務負載的計算引擎。

內層的 DAG,根據計算引擎的不同,利用引擎的特性與優化機制,實現不同的抽象作為 DAG 中計算模塊之間數據交互的載體。例如在 Spark node 中,我們會充分挖掘並利用 Spark 已有的優化策略和數據結構,如 Datasets、Dataframe、Tungsten、Whole Stage Code Generation,並將 Dataframe 作為 Spark node 內 DAG 數據流的載體。

在每一個 node 內部,根據其在 DAG 中上下游的位置,提供了三種操作類型的抽象,即Input、Process、Output。Input 基類定義了 Spark node 中輸入數據的格式、讀取和解析規範,用戶可以根據 Spark 支持的數據源,創建各種格式的 Input,如圖 2 中示例的 Parquet、Orc、Json、Text、CSV。當然用戶也可以定義自己的輸入格式,如圖 2 中示例的 Libsvm。

在微博的機器學習模型訓練中,有一部分場景是需要 Libsvm 格式數據作為訓練樣本,用戶可以通過實現Input中定義的規範和介面,實現 Libsvm 格式數據的讀入模塊。通過 Input 讀入的數據會被封裝為Dataframe,傳遞給下游的 Process 類處理模塊。

Process 基類定義了用戶計算邏輯的通用規範和介面,通過實現 Process 基類中的函數,開發者可以靈活地實現自己的計算邏輯,如圖 2 中示例的數據統計、清洗、過濾、組合、採樣、轉換等,與機器學習相關的模型訓練、預測、測試等步驟,都可以在 Process 環節實現。通過 Process 處理的數據,依然被封裝為 Dataframe,並傳遞給下游的 Output 類處理模塊。

Output 類將 Process 類傳遞的數據進一步處理,如模型評估、輸出數據存儲、模型文件存儲、輸出 AUC 等,最終將結果以不同的方式(磁碟存儲、屏幕列印等)輸出。需要指出的是,凡是 Input 支持的數據讀入格式,Output 都有對應的存儲格式支持,從而形成邏輯上的閉環。

在使用方面,業務人員根據事先約定好的規範和格式,將雙層 DAG 的計算邏輯定義在 XML 配置文件中。依據用戶在 XML 指定的依賴關係和處理模塊類,Weiflow 將自動生成 DAG 任務流圖,並在運行時階段調用處理模塊的實現類來完成用戶指定的任務流。

代碼1展示了微博應用廣泛的 GBDT+LR 模型訓練流程的開發示例(由於篇幅有限,示例中只保留了第一個 node 的細節),代碼 1 示例的訓練流程所構成的雙層 DAG 依賴及任務流圖如圖 3 所示。通過在 XML 配置文件中將所需計算模塊按照依賴關係(外層的 node 依賴關係與內層的計算邏輯依賴關係)堆疊,即可以搭積木的方式完成配置化、模塊化的流水線作業開發。

迭代速度慢?成熟的機器學習流如何設計:微博大規模機器學習框架Weiflow揭秘

代碼1 用Weiflow完成微博GBDT+LR模型訓練流程

迭代速度慢?成熟的機器學習流如何設計:微博大規模機器學習框架Weiflow揭秘

圖3 Weiflow中微博GBDT+LR模型訓練流程的雙層DAG依賴關係及任務流圖

通過靈活的模塊化開發,業務人員大幅提升了機器學習、數據科學作業的效率。隨著微博的業務場景越來越複雜,業務需求也呈多樣化的發展趨勢,為了讓更多的開發者靈活地擴展 Weiflow 的功能,Weiflow 在設計之初便充分考量了框架的可擴展性。Weiflow 通過多層次、模塊化的抽象,提供近乎無限的擴展能力。

多層次的抽象是為了滿足DAG外層計算引擎(上文提及的 Spark、Tensorflow、Hive、Storm、Flink等)的可擴展性,通過 Top level abstraction 提供的高度抽象定義,DAG 外層的各個計算引擎只需繼承 Top level 抽象中定義的屬性和方法,即可實現對計算引擎層面抽象的實現。

如圖4所示,黑色文本框中的 Top level abstraction 提供了多個抽象 Base,藍色文本框中不同的執行引擎通過繼承其屬性和方法,提供更加具體的抽象實現。當有新的計算引擎(如 Apache Flink)需要添加至 Weiflow 時,用戶只需將新定義的計算引擎類繼承 Top level 的抽象類,即可提供該引擎的抽象實現。

模塊化的抽象是從業務處理的角度出發,從業務需求中抽象出基礎、通用的模塊概念,進而定義這些基本模塊的基礎屬性和基礎方法。如圖 4 所示各文本框中分別定義、繼承、實現了四大基礎模塊,即 Node、Input、Process 和 Output。

Node 基礎類定義了計算引擎相關的基礎屬性,如數據流通媒介、執行環境、運行時數據流方式、運行參數抽象等。

Input 基礎類為計算引擎定義了該引擎內支持的所有輸入類型,如 Spark 引擎中支持 Parquet、Orc、Json、CSV、Text 等,並將輸入類型轉換為數據流通媒介(如 Spark 執行引擎的 Dataframe、RDD)。在 Weiflow 的實現過程中(後文將詳細介紹 Weiflow 實現與優化的最佳實踐),每個 node 內部的模塊實現都充分利用了現有引擎的數據結構與優化機制,如在 Spark node 中,我們充分利用了 Spark 原生支持的功能(如對各種數據源的支持)和性能優化(如 Tungsten 優化機制、二進位數據結構、Whole Stage Code Generation 等)。

例如在 Input 基礎類中,我們通過 Spark 原生數據源的支持,提供了多種壓縮、純文本格式的輸入供用戶選擇。通過實現 Input 基礎類中定義的對象和方法,開發者可以靈活地實現業務所需的數據格式,如前文提及的 Libsvm 格式。

Process 基礎類囊括了所有業務處理邏輯,在實現方面,同樣利用了所在引擎所提供的各種原生支持。如在 Spark node 中,通過 Spark SQL 或 Dataframe DSL(Domain Specific Language) 可以輕鬆地實現大部分處理邏輯,如數據統計、清洗、過濾、聯接等操作。當開發者需要實現新的業務邏輯時,如對數據按比例進行向上、向下採樣,只需繼承 Process 基礎類中定義的屬性和方法,充分利用 Spark Dataframe 和 RDD 的開放 API,將採樣的具體實現封裝到既定的介面內,即可完成開發,進而擴展 Weiflow 功能,供業務人員使用。

與 Input 相對應,Output 基礎類定義了 Weiflow 在計算引擎內的各種數據格式的輸出,提供了與 Input 相對應的介面,如 Input 提供了 read 介面,Output 則提供了 write 介面,形成邏輯層面的閉環。

通過 Weiflow 多層次、模塊化的抽象機制,開發者可以輕鬆地在執行引擎和業務功能方面進行擴展,從而滿足不斷變化的業務需求。前文提到,自 2016 年以來,微博業務步入了二次繁榮,微博的業務呈多樣、複雜的發展趨勢,用戶、博文、互動相關的數據呈爆炸式增長,機器學習規模化的挑戰迫在眉睫。為了滿足微博機器學習規模化的需求,Weiflow 在設計之初就充分考慮到實現中的執行效率問題。

迭代速度慢?成熟的機器學習流如何設計:微博大規模機器學習框架Weiflow揭秘

圖4 Weiflow開放API的抽象層次

Weiflow 在實現方面分別從語言特性、數據結構、引擎優化等幾個方面考慮,優化任務執行性能。考慮到 Scala 函數式編程語言的靈活性、豐富運算元、超高的開發效率及其並發能力,Weiflow 框架的主幹代碼和 Spark node 部分業務實現都採用 Scala 來實現。

對於業務人員來說,XML 配置開發文件即是 Weiflow 的入口。Weiflow 通過 Scala 的 XML 內置模塊對用戶提供的 XML 文件進行解析並生成相應的數據結構,如 DAG node,模塊間依賴關係等。

在成功解析各模塊的依賴關係後,Weiflow 通過 Scala 語言的懶值特性和 Call By Name 機制,將依賴關係轉化為 DAG 網路圖,並通過調用 Output 實現類中提供的 Action 函數(Output.write),觸發整個 DAG 網路的回溯執行。在回溯執行階段,Weiflow 調取用戶 XML 文件中提供的實現類,通過 Scala 語言提供的反射機制,在運行時生成實現類對象,完成計算邏輯的執行。

在執行效率方面,Weiflow 充分利用了 Scala 的語言特性來大幅提升整體執行性能。在微博的大部分機器學習應用場景中,需要利用各種處理函數(如log10、hash、特徵組合、公式計算等)將原始特徵映射到高維特徵空間。

其中一部分複雜函數(如 pickcat,根據字元串列表反查字元串索引)需要多個輸入參數。這類函數首先通過第一個參數,如 pickcat 函數所需的字元串列表(在規模化機器學習應用中會變得異常巨大),生成預定義的數據結構,然後通過第二個參數反查該數據結構,並返回其在數據結構中的索引。對於這樣的需求,如果採用傳統編程語言中的函數來實現,將帶來巨大的計算開銷。

處理函數被定義後,通過閉包發送到各執行節點(如 Spark 中的 Executor),在執行節點遍曆數據時,該函數將每次執行讀取第一個字元串列表參數、生成特定數據結構的任務;然後讀取第二個字元串參數,反查數據結構並返回索引。但業務人員真正關心的是第二個參數所返回的索引值,無需每次遍曆數據都運行生成數據結構的任務,因此該函數在執行節點的運行帶來大量不必要的計算開銷。然而通過 Scala 語言中的 Currying 特性,可以很容地解決上述問題。

在 Scala 中,函數為一等公民,且所有函數均為對象。通過將 pickcat 函數柯里化,將 pickcat 處理第一個參數的過程封裝為另一個函數(pickcat_),然後將該函數通過閉包發送到執行節點,執行引擎在遍曆數據時,其所見的函數 pickcat_ 將只接收一個參數,也即原函數 pickcat 的第二個參數,然後處理反查索引的計算即可。

當然,柯里化只是 Scala 函數式編程語言豐富的特性之一,其他特性諸如 Partial functions、Case class、Pattern matching、Function chain 等都被應用到了 Weiflow 的實現之中。

在數據結構的設計和選擇上,Weiflow 的實現經歷了從簡單粗暴到精雕細琢的變遷。在 Weiflow 的初期版本中,因為當時還沒有遇到規模化計算的挑戰,出於開發效率的考慮,數據結構大量採用了不可變長數組,此時並未遇到任何性能瓶頸。但當 Weiflow 承載大規模計算時,執行性能幾乎無法容忍。

經過排查發現,原因在於特徵映射過程中,存在大量根據數據字典,反查數據值索引的需求,如上文提及的 pickcat 函數。面對千萬級、億級待檢索數據,當數據字典以不可變長數組存儲時,通過數據值反查索引的時間複雜度顯而易見。後來通過調整數據字典結構,對多種數據結構進行對比、測試,最終將不可變長數組替換為 HashMap,解決了反查索引的性能問題。

在特徵映射之後的生成 Libsvm 格式樣本階段中,也大量使用了數組數據結構,以稠密數組的方式實現了 Libsvm 數據值的存儲。當特徵空間維度上升到十億、百億級時,幾乎無法正常完成生成樣本的任務。通過仔細的分析業務場景發現,幾乎所有的特徵空間都是極其稀疏的,以 10 億維的特徵空間為例,其特徵稀疏度通常都在千、萬級別,將特徵空間以稠密矩陣的方式存儲和計算,無疑是巨大的浪費。最後通過將稠密矩陣替換為稀疏矩陣,解決了這一性能問題。

迭代速度慢?成熟的機器學習流如何設計:微博大規模機器學習框架Weiflow揭秘

表1 採用Weiflow前後開發效率、可擴展性和執行效率的量化對比

前文提到過,在 Weiflow 的雙層 DAG 設計中,內存的 DAG 實現會充分地利用執行引擎已有的特性來提升執行性能。以 Spark 為例,在 Weiflow 的業務模塊實現部分,充分利用了 Spark 的各種性能優化技巧,如 Map Partitions、Broadcast variables、Dataframe、Aggregate By Key、Filter and Coalesce、Data Salting 等。

經過多個方面的性能優化,Weiflow 在執行效率方面已經完全能夠勝任微博機器學習規模化的需求,如表 1 中所示對比,Weiflow 優化後執行性能提升 6 倍以上。

表 1 中同時列舉了 Weiflow 在開發效率、易用性、可擴展性方面的優勢和提升。

本文從開發效率(易用性)、可擴展性、執行效率三個方面,介紹了微博機器學習框架 Weiflow 在微博的應用和最佳實踐,希望能夠對讀者提供有益的參考。


作者簡介:


吳磊,新浪微博演算法平台高級工程師,主要負責以 Spark 為核心的大數據計算框架、機器學習平台的設計和實現。曾任職於IBM、聯想研究院,從事資料庫、數據倉庫、大數據分析相關工作。


顏發才,新浪微博機器學習研發部門演算法工程師,畢業於上海交通大學,為 Spark,Pandas,Scikit-learn 提交過代碼貢獻。


本文為《程序員》原創文章,經 CSDN 授權高可用架構發表。

高可用架構歡迎更多機器學習方面文章,通過公眾號菜單「聯繫我們」可進行投稿。

喜歡這篇文章嗎?立刻分享出去讓更多人知道吧!

本站內容充實豐富,博大精深,小編精選每日熱門資訊,隨時更新,點擊「搶先收到最新資訊」瀏覽吧!


請您繼續閱讀更多來自 高可用架構 的精彩文章:

區塊鏈技術給工程師帶來哪些機會?數字貨幣和ICO淺析
使用深度學習方法實現面部表情包識別
適合創業團隊的必備工具棧
機器學習平台痛點與模型提升方法:基於Spark的機器學習平台在點融網風控應用介紹
基於Elasticsearch構建千億流量日誌搜索平台實戰

TAG:高可用架構 |

您可能感興趣

重磅!Google發布機器學習速成課程!
Python與機器學習
「Google機器學習速成課程」您看了嗎?
sklearn機器學習導論
機器學習的「hello,world」
用Python進行機器學習
怎樣快速學會Python機器學習與深度學習,來自AI一線大咖的建議
Python編程與機器學習研討會
瀏覽器端機器學習—brain.js
Google提出新型學習範式Deep Memory,或將徹底改變機器學習領域
機器學習與Scikit Learn學習庫
專訪機器學習祖師爺 Tom Mitchell:帶著理性擁抱機器學習的熱潮
Science:機器學習成功挑戰交叉偶聯反應
開源機器學習伺服器——PredictionIO
Twitter 新科技,使用機器學習自動裁剪照片
通過機器學習進行惡意PowerShell檢測
Netflix:如何通過機器學習提高流媒體質量?
Pick一下?Python機器學習實用技巧
Pick 一下?Python 機器學習實用技巧
Bloomberg推出在線免費課程:《機器學習基礎》