七個小貼士,順利提升TensorFlow模型訓練表現

ljph0013 7年前發布 | 26K 次閱讀 機器學習 TensorFlow

初來乍到的 TensorFlow 在 2015 年推出之后已經飛速成長為了 2016 年被用得最多的深度學習框架。我(Malte Baumann)在 TensorFlow 推出后幾個月入了坑,在我努力完成碩士論文階段開始了我的深度學習之旅。我用了一段時間才適應計算圖(computation graph)和會話模型(session model)。

這篇短文并不是一篇 TensorFlow 介紹文章,而是介紹了一些有用的小提示,其中大多都是關于性能表現上的,這些提示揭示了一些常見的陷阱,能幫助你將你的模型和訓練表現提升到新的層次。本文將從預處理和你的輸入流程開始,然后介紹圖構建,之后會談到調試和性能優化。

預處理和輸入流程:讓預處理整潔精簡

你是否疑惑過:為什么你的簡單模型需要那么長的訓練時間?一定是預處理做得不好!如果你的神經網絡輸入還需要做一些類似于轉換數據這樣的繁重的預處理工作,那么你的推理速度就會被大大減緩。我就遇到過這種情況,那是我正在創建了一個所謂的「距離地圖(distance maps)」,其使用了一個自定義的 Python 函數而將「Deep Interactive Object Selection」所使用的灰度圖像作為附加輸入。我的訓練速度頂多只達到了大約每秒 2.4 張圖像——即使我已經換用了一個遠遠更加強大的 GTX 1080。然后我注意到了這個瓶頸,經過修復之后,我將訓練速度提升到了每秒 50 張圖像。

如果你也遇到了類似的瓶頸,通常你的第一直覺是應該優化一些代碼。但減少訓練流程的計算時間的一個更有效的方法是將預處理作為一個一次性的操作先完成——生成 TFRecord 文件。這樣,你只需要執行一次繁重的預處理工作;有了預處理訓練數據之后得到的 TFRecord 文件之后,你需要在訓練階段加載這些文件即可。即使你想引入某種形式的隨機性來增強(augment)你的數據,你考慮的也應該是創建不同的變體,而不是用原始數據來填充你的訓練流程。

注意你的隊列

一種關注成本高昂的預處理流程的方法是使用 TensorBoard 中的隊列圖(queue graph)。如果你使用框架 QueueRunners,那么就會自動生成隊列圖并將總結存儲在一個文件中。

該圖能夠顯示你的機器是否能夠保持隊列充盈。如果你在該圖中看到了負峰值,那就說明你的系統無法在你的機器想要處理一個批(batch)的時候生成新數據。這種情況的原因有很多,而根據我的經驗,其中最常見的是 min_after_dequeue 的值太大。如果你的隊列想要在內存中保存大量記錄,那么這些記錄會很快充滿你的容量,這會導致 swapping 并顯著減慢你的隊列。其它原因還可能是硬件上的問題(比如磁盤速度太慢)或數據太大超過了系統處理能力。不管原因是什么,解決這些問題就能幫助你獲得更高的訓練速度。

圖構建和訓練:完成你的圖

TensorFlow 獨立的圖構建和圖計算模型在日常編程中十分少見,并且可能讓初學者感到困惑。這種獨立的構架可以應用于在第一次構建圖時代碼所出現的漏洞和錯誤信息,然后在實際評估時再一次運行,這個是和你過去代碼只會評估一次這樣的直覺相反的。

另一個問題是與訓練回路(training loops)結合的圖構建。因為這些回路一般是「標準」的 Python 循環,因此能改變圖并向其添加新的操作。在連續不斷地評估過程中改變圖會造成重大的性能損失,但一開始卻很難引起注意。幸好 TensorFlow 有一個簡單的解決方案,僅僅在開始訓練回路前調用 tf.getDefaultGraph().finalize() 完成你的圖即可。這一段語句將會鎖定你的圖,并且任何想要添加新操作的嘗試都將會報錯。這正是我們想要達到的效果。

分析你的圖的性能

TensorFlow 一個少有人了解的功能是性能分析(profiling)。這是一種記錄圖操作的運行時間和內存消耗的機制。如果你正在尋找系統瓶頸或想要弄清楚模型能不能在不 swapping 到硬件驅動的情況下訓練,這種功能會十分有效。

為了生成性能分析數據,你需要在開啟了 tracing 的情況下在你的圖上執行一次運行。

之后,會有一個 timeline.json 文件會保存到當前文件夾,tracing 數據在 TensorBoard 中也就可用了。現在你很容易就看到每個操作用了多長時間和多少內存。僅僅只需要在 TensorBoard 中打開圖視窗(graph view),并在左邊選定你最后的運行,然后你就可以在右邊看到性能的詳細記錄。一方面,你能根據這些記錄調整你的模型,從而盡可能地利用你機器的運算資源。另一方面,這些記錄可以幫助你在訓練流程(pipeline)中找到瓶頸。如果你比較喜歡時間軸視窗,可以在谷歌 Chrome 的事件追蹤性能分析工具(Trace Event Profiling Tool,https://www.chromium.org/developers/how-tos/trace-event-profiling-tool)中加載 timeline.json 文件。

另一個很贊的工具就是 tfprof(http://dwz.cn/5lRNeQ),將同樣的功能用于內存和執行時間分析,但能提供更加便利的功能。額外的統計需要變換代碼。

注意你的內存

就像前部分解釋的,分析(profiling)能夠讓你跟蹤特定運行的內存使用情況,不過,注意整個模型的內存消耗更重要些。需要始終確定沒有超出機器內存,因為 swapping 肯定會讓輸入流程放慢,會讓你的 GPU 開始坐等新數據。簡單地 top,就像前文講到的 TensorBoard 隊列圖就應當足夠偵測到這樣的行為。然后使用前文提過的 tracing,進行細節調查。

調試:print 會幫到你

我主要用 tf.Print 來調試諸如停滯損失(stagnating loss)或奇怪的輸出等問題。由于神經網絡天性的緣故,觀察模型內部張量原始值(raw value)通常并沒多大意義。沒人能夠解釋清楚數以百萬的浮點數并搞清楚哪兒有問題。不過,專門 print 出數據形狀(shape)或均值就能發現重要見解。如果你正在試著實現一些既有模型,你就能比較自己模型值和論文或文章中的模型值,這有利于解決棘手問題或發現論文中的書寫錯誤。

有了 TensorFlow 1.0,我們也有了新的調試工具(http://suo.im/4FtjRy)——這個看起來似乎還蠻有前途的。雖然我還沒有用過,不過呢,肯定會在接下來的時間里嘗試一下啦。

設定一個運算執行的超時時間

你已經實現了你的模型,載入了會話,但卻沒動靜?這經常是有空列隊(empty queues)造成的,但是如果你并不清哪個隊列才是罪魁禍首,一個很簡單的解決辦法:在創造會話時,設定運行超時時間——當運行超過你設定的時限,腳本就會崩潰。

使用棧進行追蹤,找出讓你頭疼的問題,解決問題然后繼續訓練。

 

 

來自:http://www.jiqizhixin.com/article/2333

 

 本文由用戶 ljph0013 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!