深度學習利器:分散式TensorFlow及實例分析

作者 | 武維

AI前線出品| ID:ai-front

TensorFlow發展及使用簡介

2015年11月9日谷歌開源了人工智慧系統TensorFlow,同時成為2015年最受關注的開源項目之一。TensorFlow的開源大大降低了深度學習在各個行業中的應用難度。TensorFlow的近期里程碑事件主要有:

2016年11月09日:TensorFlow開源一周年。

2016年09月27日:TensorFlow支持機器翻譯模型。

2016年08月30日:TensorFlow支持使用TF-Slim介面定義複雜模型。

2016年08月24日:TensorFlow支持自動學習生成文章摘要模型。

2016年06月29日:TensorFlow支持Wide & Deep Learning。

2016年06月27日:TensorFlow v0.9發布,改進了移動設備的支持。

2016年05月12日:發布SyntaxNet,最精確的自然語言處理模型。

2016年04月29日:DeepMind模型遷移到TensorFlow。

2016年04月14日:發布了分散式TensorFlow。

TensorFlow是一種基於圖計算的開源軟體庫,圖中節點表示數學運算,圖中的邊表示多維數組(Tensor)。TensorFlow是跨平台的深度學習框架,支持CPU和GPU的運算,支持台式機、伺服器、移動平台的計算,並從r0.12版本開始支持Windows平台。Tensorflow提供了各種安裝方式,包括Pip安裝,Virtualenv安裝,Anaconda安裝,docker安裝,源代碼安裝。 本文主要介紹Pip的安裝方式,Pip是一個Python的包安裝及管理工具。Linux系統下,使用Pip的安裝流程如下:

yum install python-pip python-dev

export TF_BINARY_URL=storage.googleapis.com/

pip install --upgrade $TF_BINARY_URL

安裝完畢後,TensorFlow會安裝到/usr/lib/python2.7/site-packages/tensorflow目錄下。使用TensorFlow之前,我們需要先熟悉下常用API。

tf.random_uniform([1], -1.0, 1.0):構建一個tensor, 該tensor的shape為[1],該值符合[-1, 1)的均勻分布。其中[1]表示一維數組,裡面包含1個元素。

tf.Variable(initial_value=None):構建一個新變數,該變數會加入到TensorFlow框架中的圖集合中。

tf.zeros([1]):構建一個tensor, 該tensor的shape為[1], 裡面所有元素為0。

tf.square(x, name=None):計算tensor的平方值。

tf.reduce_mean(input_tensor):計算input_tensor中所有元素的均值。

tf.train.GradientDescentOptimizer(0.5):構建一個梯度下降優化器,0.5為學習速率。學習率決定我們邁向(局部)最小值時每一步的步長,設置的太小,那麼下降速度會很慢,設的太大可能出現直接越過最小值的現象。所以一般調到目標函數的值在減小而且速度適中的情況。

optimizer.minimize(loss):構建一個優化運算元操作。使用梯度下降法計算損失方程的最小值。loss為需要被優化的損失方程。

tf.initialize_all_variables():初始化所有TensorFlow的變數。

tf.Session():創建一個TensorFlow的session,在該session種會運行TensorFlow的圖計算模型。

sess.run():在session中執行圖模型的運算操作。如果參數為tensor時,可以用來求tensor的值。

下面為使用TensorFlow中的梯度下降法構建線性學習模型的使用示例:

分散式TensorFlow應用架構

2016年4月14日,Google發布了分散式TensorFlow,能夠支持在幾百台機器上並行訓練。分散式的TensorFlow由高性能的gRPC庫作為底層技術支持。TensorFlow集群由一系列的任務組成,這些任務執行TensorFlow的圖計算。每個任務會關聯到TensorFlow的一個服務,該服務用於創建TensorFlow會話及執行圖計算。TensorFlow集群也可以劃分為一個或多個作業,每個作業可以包含一個或多個任務。在一個TensorFlow集群中,通常一個任務運行在一個機器上。如果該機器支持多GPU設備,可以在該機器上運行多個任務,由應用程序控制任務在哪個GPU設備上運行。

常用的深度學習訓練模型為數據並行化,即TensorFlow任務採用相同的訓練模型在不同的小批量數據集上進行訓練,然後在參數伺服器上更新模型的共享參數。TensorFlow支持同步訓練和非同步訓練兩種模型訓練方式。

非同步訓練即TensorFlow上每個節點上的任務為獨立訓練方式,不需要執行協調操作,如下圖所示:

同步訓練為TensorFlow上每個節點上的任務需要讀入共享參數,執行並行化的梯度計算,然後將所有共享參數進行合併,如下圖所示:

分散式TensorFlow 應用開發API主要包括:

tf.train.ClusterSpec({"ps": ps_hosts, "worker": worker_hosts}): 創建TensorFlow集群描述信息,其中ps,worker為作業名稱,ps_hosts,worker_hosts為該作業的任務所在節點的地址信息。示例如下:

tf.train.Server(cluster, job_name, task_index):創建一個TensorFlow服務,用於運行相應作業上的計算任務,運行的任務在task_index指定的機器上啟動。

tf.device(device_name_or_function):設定在指定的設備上執行Tensor運算,示例如下:

分散式TensorFlow MNIST模型訓練

MNIST是一個手寫數字的圖片資料庫,可從網站yann.lecun.com/exdb/mni下載相關數據,其中的每一張圖片為0到9之間的手寫數字灰度圖片,大小為28*28像素,如下圖所示:

MNIST數據集主要包含訓練樣本60000個,測試樣本10000個。圖像數據主要為圖片的像素數據,圖像數據標籤主要表示該圖片的類別。由以下四個文件組成:

train-images-idx3-ubyte.gz (訓練圖像數據60000個)

train-labels-idx1-ubyte.gz (訓練圖像數據標籤60000個)

t10k-images-idx3-ubyte.gz (測試圖像數據10000個)

t10k-labels-idx1-ubyte.gz (測試圖像數據標籤10000個)

本文採用如下的結構對MNIST數據集進行分散式訓練,由三個節點組成。ww01節點為Parameter Server,ww02節點為Worker0,ww03節點為Worker1。其中Parameter Server執行參數更新任務,Worker0,Worker1執行圖模型訓練計算任務,如下圖所示。分散式MNIST訓練模型在執行十萬次迭代後,收斂精度達到97.77%。

在ww01節點執行如下命令,啟動參數服務/job:ps/task:0:

python asyncmnist.py --ps_hosts=ww01:2222 --worker_hosts=ww02:2222,ww03:2222 --job_name=ps --task_index=0

在ww02節點執行如下命令,啟動模型運算/job:worker/task:0:

python asyncmnist.py --ps_hosts=ww01:2222 --worker_hosts=ww02:2222,ww03:2222 --job_name=worker --task_index=0

在ww03節點執行如下命令,啟動模型運算/job:worker/task:1:

python asyncmnist.py --ps_hosts=ww01:2222 --worker_hosts=ww02:2222,ww03:2222 --job_name=worker --task_index=1

分散式MNIST的訓練模型如下:

梯度下降法在分散式TensorFlow中的性能比較分析

2016年谷歌在ICLR(the International Conference on Learning Representations) Workshop上發表了論文REVISITING DISTRIBUTED SYNCHRONOUS SGD。基於ImageNet數據集,該論文對非同步隨機梯度下降法(Async-SGD)和同步隨機梯度下降法(Sync-SGD)進行了比較分析。

Dean在2012年提出了分散式隨機梯度下降法,模型參數可以分散式地存儲在不同的伺服器上,稱之為參數伺服器(Parameter Server,PS),以及Worker節點可以並發地處理訓練數據並且能夠和參數服務通信獲取模型參數。非同步隨機梯度下降法(Async-SGD),主要由以下幾個步驟組成:

  • 針對當前批次的訓練數據,從參數伺服器獲取模型的最新參數。
  • 基於上述獲取到的模型參數,計算損失方程的梯度。
  • 將上述計算得到的梯度發送回參數伺服器,並相應地更新模型參數。

同步隨機梯度下降法(Sync-SGD)與Sync-SGD的主要差異在於參數伺服器將等待所有Worker發送相應的梯度值,並聚合這些梯度值,最後把更新後的梯度值發送回節點。

Async-SGD 的主要問題是每個Worker節點計算的梯度值發送回參數伺服器會有參數更新衝突,一定程度影響演算法的收斂速度。Sync-SGD演算法能夠保證在數據集上執行的是真正的隨機梯度下降法,消除掉了參數的更新衝突。但同步隨機梯度下降法同時帶來的問題是訓練數據的批量數據會比較大,參數伺服器上參數的更新時間依賴於最慢的worker節點。

為了解決有些worker節點比較慢的問題,我們可以使用多一點的Worker節點,這樣Worker節點數變為N+N*5%,N為集群Worker節點數。Sync-SGD可以設定為在接受到N個Worker節點的參數後,可以直接更新參數伺服器上的模型參數,進入下一個批次的模型訓練。慢節點上訓練出來的參數是會被丟棄掉。我們稱這種方法為Sync-SGD with backups。

2015年,Abadi使用TensorFlow的Async-SGD, Sync-SGD,Sync-SGD with backups訓練模型對ImageNet的Benchmark問題進行了實驗分析。要對該訓練數據進行1000種圖片的分類訓練,實驗環境為50到200個的worker節點,每個worker節點上運行k40 GPU。使用分散式TensorFlow後大大縮短了模型訓練時間,Async-SGD演算法實驗結果如下,其中200個節點的訓練時間比採用25個節點的運算時間縮短了8倍,如下圖所示。

下圖為50個Worker節點的Async-SGD, Sync-SGD,Sync-SGD with backups模型訓練結果的比較。

從結果中可以看出增加2個backup節點,Sync-SGD with backups模型可以快速提升模型訓練速度。同時Sync-SGD模型比Async-SGD模型大概提升了25%的訓練速度,以及0.48%的精確度。隨著數據集的增加,分散式訓練的架構變得越來越重要。而分散式TensorFlow正是解決該問題的利器,有效地提升了大規模模型訓練的效率,提供了企業級的深度學習解決方案。

作者簡介

武維(微信:allawnweiwu):西安交通大學博士,現為IBM Spectrum Computing 研發工程師。主要從事大數據,深度學習,雲計算等領域的研發工作。


-全文完-

人工智慧已不再停留在大家的想像之中,各路大牛也都紛紛抓住這波風口,投入AI創業大潮。那麼,2017年,到底都有哪些AI落地案例呢?機器學習、深度學習、NLP、圖像識別等技術又該如何用來解決業務問題?

2018年1月11-14日,AICon全球人工智慧技術大會上,一些大牛將首次分享AI在金融、電商、教育、外賣、搜索推薦、人臉識別、自動駕駛、語音交互等領域的最新落地案例,應該能學到不少東西。目前大會8折報名倒計時,更多精彩可點擊閱讀原文詳細了解。

t.cn/Rl2MftP

推薦閱讀:

TAG:TensorFlow | 深度学习DeepLearning |