深度學習與 Spark 和 TensorFlow

arron劉發表於2016-02-05

深度學習與 Spark 和 TensorFlow

在過去幾年中,神經網路領域的發展非常迅猛,也是現在影像識別和自動翻譯領域中最強者。TensorFlow 是谷歌釋出的數值計算和神經網路的新框架。本文中,我們將演示如何使用TensorFlow和Spark一起訓練和應用深度學習模型。

你可能會困惑:在最高效能深度學習實現還是單節點的當下, Spark 的用處在哪裡?為了回答這個問題,我們將會演示兩個例子並解釋如何使用 Spark 和機器叢集搭配 TensorFlow 來提高深度學習的管道數。

  1. 超引數調整: 使用 Spark 來找到最優的神經網路訓練引數集,減少十倍訓練時間並降低34%的失誤率。
  2. 部署模型規模: 使用 Spark 在大量資料上應用訓練完畢的神經網路模型。

超引數調整

深度機器學習(ML)技術的一個典型應用是人工神經網路。它們採取一個複雜的輸入,如影像或音訊記錄,然後對這些訊號應用複雜的數學變換。此變換的輸出是更易於由其他ML演算法處理的數字向量。人工神經網路透過模仿人類大腦的視覺皮層的神經元(以相當簡化的形式)執行該轉換。

就像人類學會解讀他們所看到的,人工神經網路需要透過訓練來識別那些“有趣”的具體模式。可以是簡單的模式,比如邊緣,圓形,但也可以是更復雜的模式。在這裡,我們將用NIST提供的經典資料集來訓練神經網路以識別這些數字:

image02.png

TensorFlow 庫將會自動建立各種形狀和大小的神經網路訓練演算法。建立一個神經網路的實際過程,比單純在資料集上跑一些演算法要複雜得多。通常會有一些非常重要的超引數(通俗地說,引數配置)需要設定,這將影響該模型是如何訓練的。選擇正確的引數可以讓效能優越,而壞的引數將會導致長時間的訓練和糟糕的表現。在實踐中,機器學習從業者會多次使用不同的超引數重複執行相同的模型,以期找到最佳的集合。這是一個被稱為超引數調整的經典技術。

建立一個神經網路時,有許多需要精心挑選的重要超引數。 例如:

  • 每層的神經元數目:太少的神經元會降低網路的表達能力,但太多會大大增加執行時間,並返回模糊噪音。
  • 學習速度:如果過高,神經網路將只專注於看到過去的幾個樣例,並忽略之前積累的經驗。如果太低,則需要很長時間才能達到一個很好的狀態。

這裡有趣的是,即使 TensorFlow 本身不予分發,超引數調整過程是“易並行”(embarrassingly parallel),並且可以使用 Spark 來分配的。在這種情況下,我們可以使用 Spark 廣播通用的元素,例如資料和模型描述,然後以允許錯誤的方式安排機器叢集中的個體進行獨立的重複性計算。

image04.png

如何使用 Spark 提高精度?用預設的精度為99.2%。我們在測試集上的最好結果是99.47%的精確度,這減少了34%的測試誤差。分散式計算時間與新增到叢集的節點數量成線性關係:使用有13個節點的叢集,我們能夠並行培養13個模型,這相比於在同一臺機器一個接著一個訓練速度提升了7倍。這裡是相對於該叢集上機器的數量的計算時間(以秒計)的曲線圖:

image00-1024x436.png

最重要的是,我們分析了大量訓練過程中的超引數的靈敏度。例如,我們相對於不同數目的神經元所得學習率繪製了最終測試效能圖:

image03.png

這顯示了一個典型的神經網路權衡曲線:

  • 學習速度是非常關鍵的:如果它太低,神經網路沒有學到任何東西(高測試誤差)。如果它太高,訓練過程可能發生隨機振盪甚至在某些配置下出現發散。
  • 神經元的數目對於獲得良好的效能來說沒有那麼重要,並且有更多神經元的網路的學習率更加敏感。這是奧卡姆剃刀原則:對大多數目標來說,簡單的模型往往已經“足夠好”。除非你在訓練中投入大量的時間和資源,並找到合適的超引數來除去這缺少的1%測試誤差,這才會有所不同。

透過使用引數稀疏樣本,我們可以在最優的引數集下取得零失誤率。

我該如何使用它?

儘管 TensorFlow 可以使用每一個 worker 上的所有核心,但每個工人同一時間只能執行一個任務,我們可以將它們打包以限制競爭。TensorFlow 庫可以按照[instructions on the TensorFlow website]( Spark 叢集上作為一個普通的Python庫進行安裝。下面的筆記展示了使用者如何安裝 TensorFlow 庫並重復該文章的實驗:

大規模部署

TensorFlow 模型可以直接在管道內嵌入對資料集執行的複雜識別任務。作為一個例子,我們將展示我們如何能夠使用一個標註一組圖片

首先使用 Spark 內建的廣播機制將該模型分發到叢集中的worker上:

with gfile.FastGFile( 'classify_image_graph_def.pb', 'rb') as f:
  model_data = f.read()
model_data_bc = sc.broadcast(model_data) 

之後,這個模型被載入到每個節點上,並且應用於圖片。這是每個節點執行的程式碼框架:

def apply_batch(image_url): # Creates a new TensorFlow graph of computation and imports the model with tf.Graph().as_default() as g:
    graph_def = tf.GraphDef()
    graph_def.ParseFromString(model_data_bc.value)
    tf.import_graph_def(graph_def, name='') # Loads the image data from the URL: image_data = urllib.request.urlopen(img_url, timeout=1.0).read() # Runs a tensor flow session that loads the  with tf.Session() as sess:
      softmax_tensor = sess.graph.get_tensor_by_name('softmax:0')
      predictions = sess.run(softmax_tensor, {'DecodeJpeg/contents:0': image_data}) return predictions 

透過將圖片打包在一起,這份程式碼可以執行地更快。
下面是圖片的一個樣例:
image01.jpg

這是神經網路對於這張圖片的解釋,相當精確:

 ('coral reef', 0.88503921),
   ('scuba diver', 0.025853464),
   ('brain coral', 0.0090828091),
   ('snorkel', 0.0036010914),
   ('promontory, headland, head, foreland', 0.0022605944)]) 

期待

我們已經展示瞭如何將 Spark 和 TensorFlow結合起來訓練和部署手寫數字識別和圖片分類的神經網路。儘管我們使用的神經網路框架自身只能在單節點執行,但我們可以用 Spark 分發超引數調節過程和模型部署。這不僅縮短了訓練時間,而且還提高了精度,使我們更好地理解各種超引數的靈敏度。

儘管這支援是隻適用於Python的,我們仍期待著可以提供 TensorFlow 和 Spark其它框架之間更深度的整合。



原文連結: 

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/26916835/viewspace-1986803/,如需轉載,請註明出處,否則將追究法律責任。

相關文章