用PyTorch還是TensorFlow?史丹佛大學CS博士生帶來全面解答

Candy_GL發表於2018-08-01

雷鋒網 AI 評論按:關於深度學習的框架之爭一直沒有停止過。PyTorch,TensorFlow,Caffe還是Keras ?近日, 史丹佛大學電腦科學博士生Awni Hannun就發表了一篇文章,對比當前兩個主流框架PyTorch和TensorFlow。

雷鋒網 AI 科技評論編譯如下:

這篇指南是我目前發現的PyTorch和TensorFlow之間的主要差異。寫這篇文章的目的是想幫助那些想要開始新專案或者轉換深度學習框架的人進行選擇。文中重點考慮訓練和部署深度學習堆疊元件時框架的可程式設計性和靈活性。我不會權衡速度、記憶體使用情況等效能。

結論

PyTorch更適合於在研究中快速進行原型設計、業餘愛好者和小型專案,TensorFlow則更適合大規模的排程,尤其當考慮到跨平臺和嵌入式排程操作時。

準備時間

優勝者: PyTorch

PyTorch實際上是NumPy的替代,它支援GPU,有著更高階的功能,可以用來構建和訓練深度神經網路。

如果你熟悉NumPy、Python和常見的深度學習概念(卷積層、遞迴層、SGD等),那麼學習Python對你來說會很容易。

而TensorFlow則可以看成是一種嵌入Python的程式語言。當你在編寫TensorFlow程式碼時,它們會通過Python編譯成一張圖,然後由TensorFlow執行引擎執行。我看到過剛使用TensorFlow的人因為這個額外的間接層而苦思冥想。也因為如此,想用TensorFlow還需要學一些額外的概念,比如會話、圖、變數作用域和佔位符等。要執行基本模型,還需要更多的樣板程式碼。使用TensorFlow的前期準備時間肯定比PyTorch要長。

圖建立和除錯

優勝者: PyTorch

建立和執行計算圖可能是這兩個框架最大的不同。在PyTorch中,圖架構是動態的,這意味著圖是在執行時建立的。而在TensorFlow中,圖架構是靜態的,這意味著先編譯出圖然後再執行。

下面是一個簡單的例子,在PyTorch中可以使用標準的Python語言編寫for迴圈結構

for _ in range(T):

    h = torch.matmul(W, h) + b

你可以在這段程式碼的執行過程中改變T的值。而在TensorFlow中,需要使用控制流運算(control flow operation)來建立圖,例如tf.while_loop。對於更常見的結構,TensorFlow可以執行dynamic_rnn語句,但是建立自定義的動態計算更加困難。

PyTorch中簡單的圖架構更容易推導,或許更重要的一點是,它更容易除錯。除錯PyTorch程式碼如同除錯Python程式碼,可以使用pdb並在任何地方設定斷點。而除錯TensorFlow程式碼並不那麼容易,你有兩個選擇,一是請求會話中你想要檢查的變數,二是學習和使用TensorFlow偵錯程式(tfdbg)。

覆蓋率

優勝者: TensorFlow

因為PyTorch在逐漸發展,我認為兩者之間的差距會縮小到零。然而,目前仍有一些TensorFlow支援但PyTorch不支援的功能,如下所示:

沿著維度翻轉張量 (np.flip, np.flipud, np.fliplr)

檢查張量是空值還是無限值(np.is_nan, np.is_inf)

快速傅立葉變換(np.fft)

此外,TensorFlow的contrib包中有更多比PyTorch更高階的函式和模型。

序列化

優勝者: TensorFlow

在這兩種框架下儲存和載入模型都很簡單。PyTorch有一個特別簡單的API,既可以儲存模型的所有權重,也可以pickle全部類。

TensorFlow的Saver物件也很容易使用,併為檢查點(check-pointing)提供了更多選擇。

在序列化中TensorFlow的主要優點是可以將整個圖儲存為協議緩衝區。這包括引數和運算。此外,該圖可以通過其他支援的語言(C++,Java)載入。這對不支援Python的排程棧來說至關重要。理論上,在改變模型原始碼之後,你想要執行舊模型時它也能有所幫助。

部署

優勝者: TensorFlow

對於小規模的伺服器端部署,兩個框架都很容易封裝在諸如Flask web伺服器中。

不過,TensorFlow支援移動和嵌入式部署。可以確定的說,這比包括PyTorch在內的大多數深度學習框架支援功能的都要多。將TensorFlow部署到Android或iOS上確實需要大量的工作,但至少你不必用Java或C++重寫模型的整個推理程式。

此外,TensorFlow Serving支援高效能的伺服器端部署。我沒有使用過TensorFlow Serving,因此不能很確信地寫出它的利弊。由於機器學習服務使用的頻率很高,我猜想這是人們堅持使用TensorFlow的充分理由。除了效能之外,TensorFlow Serving的一個明顯特點是,支援輕鬆地換用模型而不會降低服務效能。

文件

平手

我在兩種框架的文件中都找到了我需要的東西。Python的 API在兩個框架中都有良好的文件記錄,並且有足夠的例子和教程來學習這兩種框架。

一個比較邊緣的問題是,PyTorch的 C語言庫大多是無文件記錄的,不過這隻影響到編寫定製的C語言擴充套件程式,而且這種操作是否有助於軟體還存疑。

資料載入

優勝者: PyTorch

PyTorch中用於資料載入的API設計得很好。介面在資料集、取樣器和資料載入器中有明確規定。資料載入器接收資料集和取樣器,根據取樣器的排程,在資料集上生成迭代器。載入並行資料就像把num_workers語句傳遞到資料載入器一樣簡單。

我在TensorFlow還沒發現特別有用的載入資料的工具,例如readers, queues, queue runners等,都不夠好。部分原因是因為將想要執行的所有預處理程式碼新增到TensorFlow圖中並不總是直接的,例如計算時頻譜(spectrogram)。

而且,API本身更繁瑣,更難以學習。

裝置管理

優勝者: TensorFlow

TensorFlow管理裝置時的無縫性非常好。通常不需要規定任何東西,因為預設已經設好了。例如,如果GPU可用,TensorFlow將預設在GPU上執行。在PyTorch中,即使支援CUDA,都必須明確地將所有東西移到裝置上。

TensorFlow裝置管理的唯一缺點是,即使你只使用一個GPU它也會預設佔用所有GPU的視訊記憶體。簡單的解決方法是用CUDA_VISIBLE_DEVICES語句指定顯示卡。但有時會忘了設定,所以當GPU實際上處於空閒狀態時,會顯示記憶體不足。

在PyTorch中,程式碼需要更頻繁地檢查CUDA的可用性和更明確的裝置管理,當編寫能夠同時在CPU和GPU上執行的程式碼時尤甚。另外,將GPU上的PyTorch Variable轉換為NumPy陣列有點繁瑣。

numpy_var = variable.cpu().data.numpy()

自定義擴充套件

優勝者: PyTorch

在這兩種框架中都可以用C語言、C++或CUDA構建或繫結自定義擴充套件。但TensorFlow需要更多的樣板程式碼,即使它支援多種型別和裝置。在PyTorch中,只需為每個CPU和GPU版本編寫一個介面和相應的實現。用這兩種框架來編譯擴充套件都很直接,並且不需要下載除了pip安裝包之外的任何標頭檔案或原始碼。

擴充套件

  • 關於TensorBoard

TensorBoard是用於展示訓練機器學習模型過程的視覺化工具。它是TensorFlow自帶的最有用的功能之一。只需要通過訓練指令碼中的一些程式碼片段,就可以檢視任何模型的訓練曲線和驗證結果。TensorBoard作為web服務執行,它可以非常方便地將儲存在無頭節點(headless node)上的結果視覺化。

我在用PyTorch之前一直在用這種功能並嘗試找到能替代這種功能的選擇。值得慶幸的是,目前至少有兩個開源專案支援這種功能。一個是istensorboard_logger,另一個是crayon。istensorboard_logger庫甚至比TensorFlow中的TensorBoard摘要資料更容易使用,不過需要安裝TensorBoard來使用。crayon完全能取代TensorBoard,不過需要更多的設定(支援docker是先決條件)。

  • 關於Keras

Keras是一個更高階的API,可配置後端,支援TensorFlow、Theano和CNTK,也許在不久的將來也會支援PyTorch。Keras就像TensorFlow裡的tf.contrib庫一樣。

我上面沒有討論Keras,不過它使用起來特別容易。它是除錯最常用的幾種深度神經網路架構最快的方法之一。不過它的靈活性不如PyTorch或core TensorFlow。

  • 關於TensorFlow Fold

谷歌在2017年2月釋出了TensorFlow Fold。該庫構建在TensorFlow之上,支援更多動態圖構建,主要優點是動態批處理功能——可以對不同規模的輸入資料(如解析樹上的遞迴網路)自動進行批量計算。在可程式設計性上,它的語法不如PyTorch直接,不過在某些情況下,批量處理帶來的效能改進可以讓我們忽略語法上的不足。

相關文章