騰訊Angel 1.0正式版釋出:基於Java與Scala的機器學習高效能運算平臺

機器之心發表於2017-06-17
深度學習是近些年來人工智慧技術發展的核心,伴隨而來的機器學習框架平臺也層出不窮。到現在,一家科技巨頭沒有一個主導的機器學習平臺都不好意思跟人打招呼,比如谷歌有 TensorFlow、微軟有 CNTK、Facebook 是 Torch 的堅定支持者、IBM 強推 Spark、百度開源了 PaddlePaddle、亞馬遜則是 MXNet 的支持者。而為了儘可能地獲得開發者支援和搶佔發展先機,很多平臺都選擇了開源。

在去年 12 月 18 日的騰訊大資料技術峰會暨 KDD China 技術峰會上,騰訊大資料宣佈推出了面向機器學習的「第三代高效能運算平臺」——Angel,並表示將於 2017 年開放其原始碼,參見機器之心報導《騰訊大資料將開源高效能運算平臺 Angel,機器之心專訪開發團隊》。現在,2017 年已經大約過去了一半,Angel 1.0.0 也終於在 GitHub 完全釋出:

據介紹,Angel 是騰訊大資料部門釋出的「第三代計算平臺」,是由騰訊大資料與香港科技大學、北京大學聯合使用 Java 和 Scala 語言開發的面向機器學習的高效能分散式計算框架。它採用了引數伺服器架構,解決了上一代框架的擴充套件性問題,支援資料並行及模型並行的計算模式,能支援十億級別維度的模型訓練。

不僅如此,Angel 還採用了多種業界最新技術和騰訊自主研發技術,效能更高、系統更具易用性。自去年年初在騰訊內部上線以來,Angel 已應用於騰訊視訊、騰訊社交廣告及使用者畫像挖掘等精準推薦業務。Angel 更是騰訊大資料下一代的核心計算平臺。

下面,機器之心引用了 Angel 專案的 README.md 檔案即其內部相關連結所介紹的內容,對 Angel 的功能、架構設計等內容進行了介紹,程式碼及最新動態請訪問原專案。

騰訊Angel 1.0正式版釋出:基於Java與Scala的機器學習高效能運算平臺

Angel 是一個基於引數伺服器(Parameter Server)理念開發的高效能分散式機器學習平臺,它基於騰訊內部的海量資料進行了反覆的調優,並具有廣泛的適用性和穩定性,模型維度越高,優勢越明顯。Angel 由騰訊和北京大學聯合開發,兼顧了工業界的高可用性和學術界的創新性。

Angel 的核心設計理念圍繞模型。它將高維度的大模型合理切分到多個引數伺服器節點,並通過高效的模型更新介面和運算函式,以及靈活的同步協議,輕鬆實現各種高效的機器學習演算法。

Angel 基於 Java 和 Scala 開發,能在社群的 Yarn 上直接排程執行,並基於 PS Service,支援 Spark on Angel,未來將會支援圖計算和深度學習框架整合。

歡迎對機器學習有興趣的同仁一起貢獻程式碼,提交 Issues 或者 Pull Requests。請先查閱 Angel 專案貢獻指南:https://github.com/Tencent/angel/blob/master/CONTRIBUTING.md

Angel 1.0.0 新特性

1. ParameterServer 功能

  •  基於 Matrix/Vector 的模型自動切分和管理,兼顧稀疏和稠密兩種格式
  •  支援對 Model 進行 Push 和 Pull 操作,可以自定義複雜的 psFunc
  •  提供多種同步控制機制(BSP/SSP/ASP)

2. 開發執行

  •  語言支援:系統基於 Scala 和 Java 開發,使用者也可以自由選擇
  •  部署方便:可以直接在 Yarn 社群版本中執行,也支援本地除錯模式
  •  資料切分: 自動切分讀取訓練資料,預設相容了 Hadoop FS 介面
  •  增量訓練:訓練過程中會自動 Checkpoint,而且支援載入模型後,增量訓練

3. PS Service

  •  只啟動 PSServer 和 PSAngent,為其他分散式計算平臺提供 PS 服務
  •  基於 PS-Service,不需要修改 Spark 核心程式碼,直接開發 Spark-on-Angel 演算法,該模式無縫支援 Breeze 數值運算庫

4. 演算法庫

  •  整合 Logistic Regression,SVM,KMeans,LDA,MF,GBDT 等機器學習演算法
  •  多種優化方法,包括 ADMM,OWLQN,LBFGS 和 GD
  •  支援多種損失函式、評估指標,包含 L1、L2 正則項

5. 演算法優化

  •  LDA 採用了 F+LDA 演算法用於加速取樣的速度,同時利用流式引數獲取的方法減少網路引數獲取的延遲
  •  GBDT 使用兩階段樹分裂演算法,將部分計算轉移到 PS,減少網路傳輸,提升速度

Angel 介紹

1. Angel 的架構設計

騰訊Angel 1.0正式版釋出:基於Java與Scala的機器學習高效能運算平臺

  • Client:Angel 的客戶端,它給應用程式提供了控制任務執行的功能。目前它支援的控制介面主要有:啟動和停止 Angel 任務,載入和儲存模型,啟動具體計算過程和獲取任務執行狀態等。
  • Master:Master 的職責主要包括:原始計算資料以及引數矩陣的分片和分發;向 Gaia(一個基於 Yarn 二次開發的資源排程系統)申請 Worker 和 ParameterServer 所需的計算資源; 協調,管理和監控 Worker 以及 ParameterServer。
  • Parameter Server:ParameterServer 負責儲存和更新引數,一個 Angel 計算任務可以包含多個 ParameterServer 例項,而整個模型分散式儲存於這些 ParameterServer 例項中,這樣可以支撐比單機更大的模型。
  • Worker:Worker 負責具體的模型訓練或者結果預測,為了支援更大規模的訓練資料,一個計算任務往往包含許多個 Worker 例項,每個 Worker 例項負責使用一部分訓練資料進行訓練。一個 Worker 包含一個或者多個 Task,Task 是 Angel 計算單元,這樣設計的原因是可以讓 Task 共享 Worker 的許多公共資源。

騰訊Angel 1.0正式版釋出:基於Java與Scala的機器學習高效能運算平臺

2. Angel 的系統框架

騰訊Angel 1.0正式版釋出:基於Java與Scala的機器學習高效能運算平臺

3.Angel 的設計理念

PS Service

Angel 支援兩種執行模式:ANGEL_PS & ANGEL_PS_WORKER

  • ANGEL_PS: PS Service 模式,在這種模式下,Angel 只啟動 Master 和 PS,具體的計算交給其他計算平臺(如 Spark,Tensorflow)負責,Angel 只負責提供 Parameter Server 的功能。
  • ANGEL_PS_WORKER:啟動 Master,PS 和 Worker,Angel 獨立完成模型的訓練。

同步協議

  • 支援多種同步協議:除了通用的 BSP(Bulk Synchronous Parallel)外,為了解決 task 之間互相等待的問題,Angel 還支援 SSP(Stale Synchronous Parallel)和 ASP(Asynchronous Parallel)

良好的可擴充套件性

  • psf(ps function):為了滿足各類演算法對引數伺服器的特殊需求,Angel 將引數獲取和更新過程進行了抽象,提供了 psf 函式功能。使用者只需要繼承 Angel 提供的 psf 函式介面,並實現自己的引數獲取/更新邏輯,就可以在不修改 Angel 自身程式碼的情況下定製自己想要的引數伺服器的介面。
  • 自定義資料格式:Angel 支援 Hadoop 的 InputFormat 介面,可以方便的實現自定義檔案格式。
  • 自定義模型切分方式:預設情況下,Angel 將模型(矩陣)切分成大小相等的矩形區域;使用者也可以自定義分割槽類來實現自己的切分方式。

易用性

  • 訓練資料和模型自動切割:Angel 根據配置的 worker 和 task 數量,自動對訓練資料進行切分;同樣,也會根據模型大小和 PS 例項數量,對模型實現自動分割槽。
  • 易用的程式設計介面:MLModel/PSModel/AngelClient

容錯設計和穩定性

  • PS 容錯

PS 容錯採用了 checkpoint 的模式,也就是每隔一段時間將 PS 承載的引數分割槽寫到 hdfs 上去。如果一個 PS 例項掛掉,Master 會新啟動一個 PS 例項,新啟動的 PS 例項會載入掛掉 PS 例項寫的最近的一個 checkpoint,然後重新開始服務。這種方案的優點是簡單,藉助了 hdfs 多副本容災,而缺點就是不可避免的會丟失少量引數更新。

  • Worker 容錯

一個 Worker 例項掛掉後,Master 會重新啟動一個 Worker 例項,新啟動的 Worker 例項從 Master 處獲取當前迭代輪數等狀態資訊,從 PS 處獲取最新模型引數,然後重新開始被斷掉的迭代。

  • Master 容錯

Master 定期將任務狀態寫入 hdfs,藉助與 Yarn 提供的 App Master 重試機制,當 Angel 的 Master 掛掉後,Yarn 會重新拉起一個 Angel 的 Master,新的 Master 載入狀態資訊,然後重新啟動 Worker 和 PS,從斷點出重新開始計算。

  • 慢 Worker 檢測

Master 會將收集一些 Worker 計算效能的一些指標,如果檢測到有一些 Worker 計算明顯慢於平均計算速度,Master 會將這些 Worker 重新排程到其他的機器上,避免這些 Worker 拖慢整個任務的計算進度。

4. Spark on Angel

Angel 在 1.0 版本開始,就加入了 PS-Service 的特性,不僅僅可以作為一個完整的 PS 框架執行,也可以作為一個 PS-Service,為不具備引數伺服器能力的分散式框架,引入 PS 能力,從而讓它們執行得更快,功能更強。而 Spark 是這個 Service 設計的第一個獲益者。

作為一個比較流行的記憶體計算框架,Spark 的核心概念是 RDD,而 RDD 的關鍵特性之一,是其不可變性,來規避分散式環境下複雜的各種並行問題。這個抽象,在資料分析的領域是沒有問題的,能最大化的解決分散式問題,簡化各種運算元的複雜度,並提供高效能的分散式資料處理運算能力。

然而在機器學習領域,RDD 的弱點很快也暴露了。機器學習的核心是迭代和引數更新。RDD 憑藉著邏輯上不落地的記憶體計算特性,可以很好的解決迭代的問題,然而 RDD 的不可變性,卻不適合引數反覆多次更新的需求。這個根本的不匹配性,導致了 Spark 的 MLLib 庫,發展一直非常緩慢,從 15 年開始就沒有實質性的創新,效能也不好,從而給了很多其它產品機會。而 Spark 社群,一直也不願意正視和解決這個問題。

騰訊Angel 1.0正式版釋出:基於Java與Scala的機器學習高效能運算平臺

Spark-On-Angel 的系統架構


現在,由於 Angel 良好的設計和平臺性,提供 PS-Service,Spark 可以充分利用 Angel 的引數更新能力,用最小化的修改代價,讓 Spark 也具備高速訓練大模型的能力,並寫出更加優雅的機器學習程式碼,而不必繞來繞去。

更多詳情,請參閱:https://github.com/Tencent/angel/blob/master/docs/overview/spark_on_angel.md

Angel 快速入門指南

準備知識

這篇文件幫助你快速開始編寫執行在 Angel-PS 架構上的程式,開始之前,你最好掌握以下能力:

  • 會編寫簡單的 Scala 或者 Java 程式碼
  • 掌握向量、矩陣和張量的基礎知識,瞭解其定義和基礎計算。
  • 最好對機器學習演算法有一定了解

如果沒有學習過機器學習演算法,也沒有關係,你可以從這篇文件開始。在開始程式設計前,我們先來了解一些基礎知識。

  • 大多數的機器學習演算法都可以抽象成向量(Vector)、矩陣 (Martix),張量(Tensor)間的運算,用向量、矩陣、張量來表示學習資料和演算法模型。
  • Angel-PS 實現了基於引數伺服器的矩陣計算,將分佈在多臺 PS Server 上的引數矩陣抽象為 PSModel,你只需要完成 PSModel 的定義、實現其計算過程,就可以實現一個執行在引數伺服器上的簡單演算法。

Angel-PS 架構

簡單的 Angel-PS 架構如下圖所示

  • PS 是儲存矩陣引數的多臺機器,向計算節點提供矩陣引數的拉取、更新服務
  • 每個 worker 是一個邏輯計算節點,一個 worker 可以執行一或多個 task

機器學習的演算法,一般以迭代的方式訓練,每次迭代 worker 從 PS 拉取最新的引數,計算一個更新值,推送給 PS。

開始你的第一個 Angel 演算法:LR

本示例將以最簡單的 Logistic Regression 演算法為例,指導你完成第一個 Angel 演算法。程式碼可以在 example.quickStart 裡找到。

邏輯迴歸演算法是機器學習中最簡單的一個演算法,它可以抽象為如下步驟:

1. 一個維度為 1×N 的矩陣,即一個 N 維向量,記為 w

2. 用梯度下降法訓練 LR 模型,每次迭代

  •  task 從 PS 拉取最新的模型 w,
  •  計算得到變化梯度△w
  •  將△w 推送給 PS

為了實現該演算法,我們需要如下 3 個步驟:

1. 定義一個模型 (LRModel)

實現 LRModel 類繼承 MLModel,通過 addPSModel 新增一個 N 維的 PSModel 給 LRModel,在 setSavePath 方法中,設定運算結束後 LR 模型的儲存路徑。

N 的值、儲存路徑都可以通過 conf 配置。

class myLRModel(ctx: TaskContext, conf: Configuration) extends MLModel(ctx){
	
	val N = conf.getInt(MLConf.ML_FEATURE_NUM, MLConf.DEFAULT_ML_FEATURE_NUM)

	val weight = PSModel[DenseDoubleVector]("mylr.weight", 1, N)
	weight.setAverage(true)
	addPSModel(weight)

	 override 
	 def setSavePath(conf: Configuration): Unit = {
		val path = conf.get(AngelConfiguration.ANGEL_SAVE_MODEL_PATH)
		if (path != null) weight.setSavePath(path)
	  }
}

2. 定義一個 Task(TrainTask)

Angel 的模型的訓練是在 task 中完成,所以我們需要定義一個 LRTrainTask 來完成 LR 的模型的訓練過程。

LRTrainTask 需要繼承 TrainTask 類並實現如下 2 個方法:

  • 解析資料

在模型開始訓練前,輸入的每一行文字被解析為一條訓練資料,解析方法在 parse 方法裡實現,此處我們使用 DataParser 解析 dummy 格式的資料。

  override
  def parse(key: LongWritable, value: Text): LabeledData = {
    DataParser.parseVector(key, value, feaNum, "dummy", negY = true)
  }

可以通過 task 的 dataBlock 訪問預處理後的資料。

  •  訓練

Angel 會自動執行 TrainTask 子類的 train 方法,我們在 LRTrainTask 的 train 方法中完成模型訓練過程。

在這個簡易的 LR 演算法例子中,我們

  •  先例項化 myLRModel 模型物件 model,然後開始迭代計算。
  •  每次迭代
  •  task 從 PS 拉取模型的引數 weight
  •  訓練資料計算得到梯度 grad,把 grad 推送給 PS,PS 上 weight 的更新會自動完成。
  •  推送 grad 後,需要 clock()、incIteration()。
 override
 def train(ctx: TaskContext): Unit = { 	
 	// A simple logistic regression model
 	val model = new LRModel(ctx, conf) 	
 	// Apply batch gradient descent LR iteratively
 	while (ctx.getIteration < epochNum) { 	  // Pull model from PS Server
 	  val weight = model.weight.getRow(0) 	
 	  // Calculate gradient vector
 	  val grad = bathGradientDescent(weight) 	
 	  // Push gradient vector to PS Server
 	  model.weight.increment(grad.timesBy(-1.0 * lr)) 	
 	  // LR model matrix clock
 	  model.weight.clock.get 	
 	  // Increase iteration number
 	  ctx.incIteration()
 	}
 }

3. 定義一個 Runner(MLRunner)

前面,我們定義了 LR 模型,實現了它的訓練過程。現在,還需要實現 Runner 類將訓練這個模型的任務提交到叢集。

定義 myLRRunner 類繼承 MLRunner,在 train 方法中提交我們的 myLRModel 的模型類、和 myLRTrainTak 訓練類就可以了。

	class LRRunner extends MLRunner{
	  ……	  override
	  def train(conf: Configuration): Unit = {
	    train(conf, myLRModel(conf), classOf[myLRTrainTask])
	   }
	}

執行任務

可以通過以下命令向 Yarn 叢集提交剛剛完成的演算法任務

./bin/angel-submit \
--action.type train \
--angel.app.submit.class com.tencent.angel.example.quickStart.myLRRunner  \
--angel.train.data.path $input_path \
--angel.save.model.path $model_path \
--ml.epoch.num 10 \
--ml.feature.num 10000 \
--ml.data.type dummy \
--ml.learn.rate 0.001 \
--angel.workergroup.number 3 \
--angel.worker.memory.mb 8000  \
--angel.worker.task.number 3 \
--angel.ps.number 1 \
--angel.ps.memory.mb 5000 \
--angel.job.name myLR

提交完畢後,可以按照這個指引,《檢視到 Yarn 上的作業》,如果你不熟悉 Yarn 的話:https://github.com/Tencent/angel/blob/master/docs/deploy/run_on_yarn.md

OK。至此,你已經完成了一個簡單的 Angel 作業。想寫出更加複雜的機器學習演算法嗎?請看完整的《Angel 程式設計指南》吧,歡迎來到 Angel 的世界:https://github.com/Tencent/angel/blob/master/docs/programmers_guide/angel_programing_guide.md

你也可以在這裡檢視 Spark on Angel 快速入門:https://github.com/Tencent/angel/blob/master/docs/tutorials/spark_on_angel_quick_start.md

程式設計手冊

設計

演算法

這裡介紹了 Angel 支援的幾種演算法,詳情請參看原專案:

  • logistic 迴歸(Logistic Regression)
  • 矩陣分解(Matrix Factorization)
  • 支援向量機(SVM)
  • K-均值(KMeans)
  • GBDT
  • LDA
  • Spark on Angel Optimizer

部署

原始碼下載和編譯

1. 編譯環境依賴

  • Jdk >= 1.8
  • Maven >= 3.0.5
  • Protobuf >= 2.5.0

2. 原始碼下載

git clone https://github.com/Tencent/angel

3. 編譯

進入原始碼根目錄,執行命令:

mvn clean package -Dmaven.test.skip=true

編譯完成後,在原始碼根目錄 dist/target 目錄下會生成一個釋出包:angel-1.0.0-bin.zip

4. 釋出包

釋出包解壓後,根目錄下有四個子目錄:

  • bin:Angel 任務提交指令碼
  • conf:系統配置檔案
  • data:簡單測試資料
  • lib:Angel jar 包 & 依賴 jar 包

本地執行

1. 執行環境準備

  • Hadoop >= 2.2.0
  • Java 1.8 版本
  • Angel 釋出包 angel-1.0.0-bin.zip

配置好 HADOOP_HOME 和 JAVA_HOME 環境變數,解壓 Angel 釋出包,就可以以 LOCAL 模式執行 Angel 任務了。

2.LOCAL 執行例子

釋出包解壓後,在根目錄下有一個 bin 目錄,提交任務相關的指令碼都放在該目錄下。例如執行簡單的邏輯迴歸的例子:

./angel-example com.tencent.angel.example.SgdLRLocalExample

3. Yarn 執行:https://github.com/Tencent/angel/blob/master/docs/deploy/run_on_yarn.md

4. 系統配置:https://github.com/Tencent/angel/blob/master/docs/deploy/config_details.md

論文

目前騰訊還沒公開發布相關論文,可關注本專案檢視更新。

相關文章