在過去幾年中,神經網絡領域的發展很是迅猛,也是如今圖像識別和自動翻譯領域中最強者。TensorFlow 是谷歌發佈的數值計算和神經網絡的新框架。本文中,咱們將演示如何使用TensorFlow和Spark一塊兒訓練和應用深度學習模型。html
你可能會困惑:在最高性能深度學習實現仍是單節點的當下, Spark 的用處在哪裏?爲了回答這個問題,咱們將會演示兩個例子並解釋如何使用 Spark 和機器集羣搭配 TensorFlow 來提升深度學習的管道數。java
超參數調整: 使用 Spark 來找到最優的神經網絡訓練參數集,減小十倍訓練時間並下降34%的失誤率。python
部署模型規模: 使用 Spark 在大量數據上應用訓練完畢的神經網絡模型。web
超參數調整
深度機器學習(ML)技術的一個典型應用是人工神經網絡。它們採起一個複雜的輸入,如圖像或音頻記錄,而後對這些信號應用複雜的數學變換。此變換的輸出是更易於由其餘ML算法處理的數字向量。人工神經網絡經過模仿人類大腦的視覺皮層的神經元(以至關簡化的形式)執行該轉換。算法
就像人類學會解讀他們所看到的,人工神經網絡須要經過訓練來識別那些「有趣」的具體模式。能夠是簡單的模式,好比邊緣,圓形,但也能夠是更復雜的模式。在這裏,咱們將用NIST提供的經典數據集來訓練神經網絡以識別這些數字:微信
TensorFlow 庫將會自動建立各類形狀和大小的神經網絡訓練算法。創建一個神經網絡的實際過程,比單純在數據集上跑一些算法要複雜得多。一般會有一些很是重要的超參數(通俗地說,參數配置)須要設置,這將影響該模型是如何訓練的。選擇正確的參數可讓性能優越,而壞的參數將會致使長時間的訓練和糟糕的表現。在實踐中,機器學習從業者會屢次使用不一樣的超參數重複運行相同的模型,以期找到最佳的集合。這是一個被稱爲超參數調整的經典技術。markdown
創建一個神經網絡時,有許多須要精心挑選的重要超參數。 例如:網絡
每層的神經元數目:太少的神經元會下降網絡的表達能力,但太多會大大增長運行時間,並返回模糊噪音。session
學習速度:若是太高,神經網絡將只專一於看到過去的幾個樣例,並忽略以前積累的經驗。若是過低,則須要很長時間才能達到一個很好的狀態。app
這裏有趣的是,即便 TensorFlow 自己不予分發,超參數調整過程是「易並行」(embarrassingly parallel),而且可使用 Spark 來分配的。在這種狀況下,咱們可使用 Spark 廣播通用的元素,例如數據和模型描述,而後以容許錯誤的方式安排機器集羣中的個體進行獨立的重複性計算。
如何使用 Spark 提升精度?用默認的超參數設置精度爲99.2%。咱們在測試集上的最好結果是99.47%的精確度,這減小了34%的測試偏差。分佈式計算時間與添加到集羣的節點數量成線性關係:使用有13個節點的集羣,咱們可以並行培養13個模型,這相比於在同一臺機器一個接着一個訓練速度提高了7倍。這裏是相對於該集羣上機器的數量的計算時間(以秒計)的曲線圖:
最重要的是,咱們分析了大量訓練過程當中的超參數的靈敏度。例如,咱們相對於不一樣數目的神經元所得學習率繪製了最終測試性能圖:
這顯示了一個典型的神經網絡權衡曲線:
學習速度是很是關鍵的:若是它過低,神經網絡沒有學到任何東西(高測試偏差)。若是它過高,訓練過程可能發生隨機振盪甚至在某些配置下出現發散。
神經元的數目對於得到良好的性能來講沒有那麼重要,而且有更多神經元的網絡的學習率更加敏感。這是奧卡姆剃刀原則:對大多數目標來講,簡單的模型每每已經「足夠好」。除非你在訓練中投入大量的時間和資源,並找到合適的超參數來除去這缺乏的1%測試偏差,這纔會有所不一樣。
經過使用參數稀疏樣本,咱們能夠在最優的參數集下取得零失誤率。
我該如何使用它?
儘管 TensorFlow 可使用每個 worker 上的全部核心,但每一個工人同一時間只能運行一個任務,咱們能夠將它們打包以限制競爭。TensorFlow 庫能夠按照[instructions on the TensorFlow website](https://www.tensorflow.org/get_started/os_setup.html)上的指示在 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
經過將圖片打包在一塊兒,這份代碼能夠運行地更快。
下面是圖片的一個樣例:
這是神經網絡對於這張圖片的解釋,至關精確:
('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其它框架之間更深度的集成。
本文分享自微信公衆號 - 雲服務圈(heidcloud)。
若有侵權,請聯繫 support@oschina.cn 刪除。
本文參與「OSC源創計劃」,歡迎正在閱讀的你也加入,一塊兒分享。