PaddlePaddle與TensorFlow的對比分析
原創【51CTO.com原創稿件】
本文主要從框架概覽、系統架構、編程模型、分布式架構、框架對比這五大方面比較TensorFlow和PaddlePaddle框架。作為國際兩大搜索引擎研發的深度學習框架,使用側重點不同,卻同樣提供了優雅簡潔的設計架構,并且還在不斷發展。對于PaddlePaddle來說,它的易用性和本土性、快速業務集成性,對國內以速度致勝的互聯網公司是一個非常有利的武器;而TensorFlow的靈活性和相對偏科研性,是AI研究領域的一大利好。
框架概覽
PaddlePaddle的研發始于2013年,伴隨著百度廣告、文本、圖像、語音等訓練數據的快速增長,以及百度外賣、搜索、無人駕駛領域的算法要求,百度深度學習實驗室在基于單GPU訓練平臺的基礎上,研發了Paddle(Parallel Asynchronous Distributed Deep Learning)這個多機并行GPU這個訓練平臺。
PaddlePaddle自開源以來,它的設計和定位就一直集中在“易用、高效、靈活、可擴展”上。正如官網的設計定位: An Easy-to-use, Efficient, Flexible and Scalable Deep Learning Platform 。下圖是Paddle的官方網站:
PaddlePaddle框架的開源始于2016年9月份,它最大的特點和定位是easy to use,因此對很多算法進行了完整的封裝,不僅是針對只目前現成的CV、NLP等算法 (如VGG、ResNet、LSTM、GRU等),它在模型庫models(https://github.com/PaddlePaddle/models)模塊下,封裝了詞向量(包括Hsigmoid加速詞向量訓練和噪聲對比估計加速詞向量訓練)、RNN 語言模型、點擊率預估、文本分類、排序學習(信息檢索和搜索引擎研究的核心問題之一)、結構化語義模型、命名實體識別、序列到序列學習、閱讀理解、自動問答、圖像分類、目標檢測、場景文字識別、語音識別等多個技術領域人工智能的通用解決方案。
上述的每個解決方案都是針對某個技術場景而設計,因此,開發者可能只需要略微了解下源碼原理,按照官網的示例執行運行的命令,更換成自己的數據、修改一些超參數就能運行起來。并且因為沒有向用戶暴露過多的python接口,理解和使用起來還比較容易。但是因為側重在使用,在科研或者新增功能方面,如果修改算法,需要從框架的C++底層開始實現。
它的第二大特色是分布式部署,并且是目前是唯一很好的支持Kubernetes的深度學習庫。在本文的“分布式架構”中會進一步說明。
TensorFlow官網上對TensorFlow的描述是 An open-source software library for Machine Intelligence,一個開源的機器學習庫。
表
類別 |
示例 |
數學運算操作 |
Add、Sub、Mul、Div、Exp、Log、Greater、Less、Equal…… |
數組運算操作 |
Concat、Slice、Split、Constant、Rank、Shape、Shuffle…… |
矩陣運算操作 |
MatMul、MatrixInverse、MatrixDeterminant…… |
有狀態的操作 |
Variable、Assign、AssignAdd…… |
神經網絡構建操作 |
SoftMax、Sigmoid、ReLU、Convolution2D、MaxPool,…… |
檢查點操作 |
Save、Restore |
隊列和同步操作 |
Enqueue、Dequeue、MutexAcquire、MutexRelease…… |
控制張量流動的操作 |
Merge、Switch、Enter、Leave、NextIteration |
2016年4月,TensorFlow的0.8版本就支持了分布式、支持多GPU運算。2016年6月,TensorFlow的0.9版本改進了對移動設備的支持。2017年2月,TensorFlow的1.0正式版本中,增加了Java和Go的實驗性API,以及專用編譯器XLA和調試工具Debugger,還發布了tf.transform,專門用來數據預處理。同時,圍繞著模型部署推出了TensorFlow Serving,用于將算法動態部署到線上;以及逐步完善的類似于scikit-learn功能的tf.contrib.learn。并且還推出了“動態圖計算”TensorFlow Fold,這是被評價為“第一次清晰地在設計理念上領先”
用戶還可以使用谷歌公司的PaaS TensorFlow產品Cloud Machine Learning來做分布式訓練。現在也已經有了完整的TensorFlow Model Zoo。
2018年1月,TensorFlow已經支持到1.5.0版本,完整開放了TensorFlow Lite移動端應用以及動態圖機制Eager Execution,使得調試即刻的運行錯誤并和Python 工具進行整合。
TensorFlow的一大亮點是支持異構設備分布式計算
何為異構?信息技術當中的異構是指包含不同的成分,有異構網絡(如互聯網,不同廠家的硬件軟件產品組成統一網絡且互相通信)、異構數據庫(多個數據庫系統的集合,可以實現數據的共享和透明訪問)。這里的異構設備是指使用CPU、GPU等核心進行有效地協同合作;與只依靠CPU相比,性能更高,功耗更低。
那何為分布式?分布式架構目的在于幫助我們調度和分配計算資源(甚至容錯,如某個計算節點宕機或者太慢),使得上千萬、上億數據量的模型能夠有效地利用機器資源進行訓練。
總結來看,目前AI領域有幾大主流的框架,而今天我們所對比的這兩個框架的共性就是有都有下面的一些特點。我們參考《The Unreasonable Effectiveness of Recurrent Neural Networks》,這篇文章梳理了一個有效框架應該具有的功能。
- Tensor庫是對CPU/GPU透明的,并且實現了很多操作(如切片、數組或矩陣操作等)。這里的透明是指,在不同設備上如何運行,都是框架幫用戶去實現的,用戶只需要指定在哪個設備上進行哪種運算即可。
- 有一個完全獨立的代碼庫,用腳本語言(最理想的是Python)來操作Tensors,并且實現所有深度學習的內容,包括前向傳播/反向傳播、圖形計算等。
- 可以輕松地共享預訓練模型(如Caffe的模型及TensorFlow中的slim模塊、PaddlePaddle的models模塊)。
- 沒有編譯過程。深度學習是朝著更大、更復雜的網絡發展的,因此在復雜圖算法中花費的時間會成倍增加。而且,進行編譯的話會丟失可解釋性和有效進行日志調試的能力。
那么PaddlePaddle 對開發者來說有什么優勢?
首先,是易用性。相比偏底層的谷歌 TensorFlow,PaddlePaddle 的易用特點非常明顯:它讓開發者開發精力放在構建深度學習模型的高層部分。
除此之外,PaddlePadddle 是國內巨頭百度開源的框架,他的本土性不僅非常符合國人的使用習慣,而且非常重視主流互聯網技術的使用場景和解決方法。
其次,是更快的速度。如上所說,PaddlePaddle 的代碼和設計更加簡潔,用它來開發模型顯然能為開發者省去一些時間。這使得 PaddlePaddle 很適合于工業應用,尤其是需要快速開發的場景。
我們知道,系統架構就直接決定了框架設計的根本不同,現在我們就一起窺探一番。
系統架構
下圖給出的是TensorFlow的系統架構,自底向上分為設備層和網絡層、數據操作層、圖計算層、API層、應用層,其中設備層和網絡層、數據操作層、圖計算層是TensorFlow的核心層。
下面就自底向上詳細介紹一下TensorFlow的系統架構。最下層是網絡通信層和設備管理層。網絡通信層包括gRPC(google Remote Procedure Call Protocol)和遠程直接數據存?。≧emote Direct Memory Access,RDMA),這都是在分布式計算時需要用到的。設備管理層包括TensorFlow分別在CPU、GPU、FPGA等設備上的實現,也就是對上層提供了一個統一的接口,使上層只需要處理卷積等邏輯,而不需要關心在硬件上的卷積的實現過程。
其上是數據操作層,主要包括卷積函數、激活函數等操作。再往上是圖計算層,也是我們要了解的核心,包含本地計算圖和分布式計算圖的實現(包括圖的創建、編譯、優化和執行)。再往上是API層和應用層。
可能因為歷史遺留原因,PaddlePaddle整體架構思路和caffe有些類似,是基于神經網絡中的功能層來開發的,一個層包括了許多復雜的操作,如下圖中展示了目前包括FCN、CTC、BN、LSTM多種功能層。
并且它將數據讀取(DataProvider)、功能層(Layers)、優化方式(Optimizer)、評估(Evaluators)、激活函數(Activation)、池化(Pooling)這幾個過程分布實現成類,構建PaddlePaddle的神經網絡的過程就是組合這些層構成整個網絡。如下圖所示:
同時,在一層一層累加之外,為了提高靈活性,還額外封裝好了的networks類,也就是設置mixed_layer來組合不同的輸入,如下圖。這里面封裝了一些可能需要的組合,如conv+batchnorm+pooling,它可以極大的簡化構建神經網絡的方式。使用更少的代碼,依據成熟的算法構建網絡的同時,修改數據的輸入就可以順利運行。
編程模型
Paddle目前整體模塊如下圖所示:
- Math模塊是Paddle的數學計算模塊。其中有各種矩陣和向量的實現,矩陣和向量基類是BaseMatrix。這個模塊里主體分為兩個部分。
- MemoryHandle: 申請、管理內存和顯存的模塊。Paddle中的所有計算都是對MemoryHandle的操作。(MemoryHandle本質上是對一段內存的抽象。包括這段內存的地址和大小。這段內存可以是申請在普通內存上,也可以是申請在GPU設備上。)
- Matrix/Vector: Paddle中實現計算邏輯的類型。本質上是MemoryHandle的一個view。
- 矩陣和向量組成了神經網絡的參數Parameter和神經網絡層的輸入和輸出Arguments。
Parameter和Arguments表示神經網絡中所有的數據和參數。其中Parameter表示神經網絡中層與層之間的連接參數,而Argument表示每一層的輸入和輸出。即Parameter表示下圖中的黃色連線,而Argument表示下圖中的的輸入和輸出(Input, Output)。
并且Parameter與Argument并不只保存了參數值,還同時保存了梯度,動量等信息。
- Layer使用Argument和Parameter完成計算。
PaddlePaddle整體是一個基于Layer配置的神經網絡框架。為了支持更細粒度的神經網絡配置,支持配置op和projection,Paddle提供了MixedLayer。
MixedLayer和其他Layer不同,使用的輸入類型不直接是其他Layer本身,而是其他Layer的projection或者operation。其他Layer的projection和operation的結果依次相加到MixedLayer的輸出中。
- GradientMachine是一個把神經網絡各個層組合在一起調用的類型。這是個基類,具有神經網絡常見的forward、backward函數,并且處理了單機多線程和多顯卡的功能。
GradientMachine是PaddlePaddle中對于神經網絡的一種抽象,即該數據類型可以計算出Gradient,進而將計算后的結果放入Parameter中即可。一個GradientMachine一般用來計算一個神經網絡的拓撲結構。進而,根據拓撲結構的形態,GradientMachine會創建一些parameters_,而forward根據輸入的args和本地的參數,計算神經網絡的前饋,而backward函數根據之前前饋的結果,計算出各個參數的梯度,并將各個參數的梯度保存在parameters_中。
- Trainer調用GradientMachine計算出參數的梯度。
- ParameterUpdaterParameterUpdater主要用于在gradientMachine通過forward backward計算出gradient之后,調用update算法更新參數。
- Trainer優化的拓撲結構是Python端的config_parser.py程序生成的。
TensorFlow是用數據流圖做計算的,因此我們先創建一個數據流圖(也稱為網絡結構圖),如圖所示,看一下數據流圖中的各個要素。
圖中講述了TensorFlow的運行原理。圖中包含輸入(input)、塑形(reshape)、Relu層(Relu layer)、Logit層(Logit layer)、Softmax、交叉熵(cross entropy)、梯度(gradient)、SGD訓練(SGD Trainer)等部分,是一個簡單的回歸模型。
它的計算過程是,首先從輸入開始,經過塑形后,一層一層進行前向傳播運算。Relu層(隱藏層)里會有兩個參數,即Wh1和bh1,在輸出前使用ReLu(Rectified Linear Units)激活函數做非線性處理。然后進入Logit層(輸出層),學習兩個參數Wsm和bsm。用Softmax來計算輸出結果中各個類別的概率分布。用交叉熵來度量兩個概率分布(源樣本的概率分布和輸出結果的概率分布)之間的相似性。然后開始計算梯度,這里是需要參數Wh1、bh1、Wsm和bsm,以及交叉熵后的結果。隨后進入SGD訓練,也就是反向傳播的過程,從上往下計算每一層的參數,依次進行更新。也就是說,計算和更新的順序為bsm、Wsm、bh1和 Wh1。
顧名思義,TensorFlow是指“張量的流動”。TensorFlow的數據流圖是由節點(node)和邊(edge)組成的有向無環圖(directed acycline graph,DAG)。TensorFlow由Tensor和Flow兩部分組成,Tensor(張量)代表了數據流圖中的邊,而Flow(流動)這個動作就代表了數據流圖中節點所做的操作。
那么,在分布式計算下,兩種框架又各自有哪些實現特點呢?
分布式架構
PaddlePaddle的分布式結構主要有兩個部分,trainer和parameter server。
數據分片(Data shard): 用于訓練神經網絡的數據,被切分成多個部分,每個部分分別給每個trainer使用。
計算節點(Trainer): 每個trainer啟動后讀取切分好的一部分數據,開始神經網絡的“前饋”和“后饋”計算,并和參數服務器通信。在完成一定量數據的訓練后,上傳計算得出的梯度(gradients),然后下載優化更新后的神經網絡參數(parameters)。
參數服務器(Parameter server):每個參數服務器只保存整個神經網絡所有參數的一部分。參數服務器接收從計算節點上傳的梯度,并完成參數優化更新,再將更新后的參數下發到每個計算節點。
在使用同步SGD訓練神經網絡時,PaddlePaddle使用同步屏障(barrier),使梯度的提交和參數的更新按照順序方式執行。在異步SGD中,則并不會等待所有trainer提交梯度才更新參數,這樣極大地提高了計算的并行性:參數服務器之間不相互依賴,并行地接收梯度和更新參數,參數服務器也不會等待計算節點全部都提交梯度之后才開始下一步,計算節點之間也不會相互依賴,并行地執行模型的訓練??梢钥闯?,雖然異步SGD方式會提高參數更新并行度, 但是并不能保證參數同步更新,在任意時間某一臺參數服務器上保存的參數可能比另一臺要更新,與同步SGD相比,梯度會有噪聲。
同時,Paddle本身支持多種分布式集群的部署和運行方式,包括fabric集群、openmpi集群、Kubernetes單機、Kubernetes distributed分布式等。
客戶端、主節點和工作節點的關系
簡單地來說,在TensorFlow中,客戶端通過會話來聯系主節點,實際的工作交由工作節點實現。每個工作節點占據一臺設備(是TensorFlow具體計算的硬件抽象,即CPU或GPU)。在單機模式下,客戶端、主節點和工作節點都在同一臺服務器上;在分布式模式下,它們可以位于不同的服務器上。
1.客戶端
客戶端用于建立TensorFlow計算圖,并建立與集群進行交互的會話層。因此,代碼中只要包含Session()就是客戶端。一個客戶端可以同時與多個服務端相連,同時一個服務端也可以與多個客戶端相連
2.服務端
服務端是一個運行了tf.train.Server實例的進程,是TensorFlow執行任務的集群(cluster)的一部分,并有主節點服務(Master service,也叫主節點)和工作節點服務(Worker service,也叫工作節點)之分。運行中由一個主節點進程和數個工作節點進程組成,主節點進程和工作節點進程之間通過接口通信。單機多卡和分布式都是這種結構,因此只需要更改它們之間通信的接口就可以實現單機多卡和分布式的切換。
3.主節點服務
主節點服務實現了tensorflow::Session接口,通過RPC服務程序來遠程連接工作節點,與工作節點的服務進程中的工作任務進行通信。在TensorFlow服務端中,一般是task_index為0的作業(job)。
4.工作節點服務
工作節點服務實現了worker_service.proto接口,使用本地設備對部分圖進行計算。在TensorFlow服務端中,所有工作節點都包含工作節點的服務邏輯。每個工作節點負責管理一個或者多個設備。工作節點也可以是本地不同端口的不同進程,或者多臺服務器上的多個進程。
下圖左邊是單機多卡的交互,右邊是分布式的交互。
框架對比
下面是PaddlePaddle和TensorFlow在框架流行度和代碼穩定性上的比較??梢钥闯?,兩個框架在活躍度、穩定性上都是一流,并且在代碼質量上也不分伯仲。
對PaddlePaddle我這里列舉以下Paddle的幾個亮點的地方:
- 更易用的API,更好的封裝,更快速的業務集成;
- 占用內存小,速度快,因為Paddle在百度內部也服務了眾多大并發大數據場景,工業經驗也很豐富;
- 本土化支持,也是唯一有官方中文文檔的深度學習框架;
- 在自然語言處理上有很多現成的應用,比如情感分類,神經機器翻譯,閱讀理解、自動問答等,使用起來相對簡單;
- PaddlePaddle支持多機多卡訓練,并且本身支持多種集群方式。
總結
【51CTO原創稿件,合作站點轉載請注明原文作者和出處為51CTO.com】