PyTorch VS TensorFlow:細數兩者的不同之處

PyTorch VS TensorFlow:細數兩者的不同之處

來自專欄景略集智

在今年 5 月初召開的 Facebook F8 開發者大會上,Facebook 宣布將推出旗下機器學習開發框架 PyTorch 的新一代版本 PyTorch 1.0。據 Facebook 介紹,PyTorch 1.0 結合了 Caffe2 和 ONNX 模塊化、面向生產的特性,和 PyTorch 自身靈活、面向研究的特性結合起來,為廣泛的 AI 項目提供了一個從科研原型到生產部署的快速、無縫途徑,讓用戶可以快速實驗,通過一個能在強制執行模式和聲明執行模式之間無縫切換的混合前端優化性能。

Facebook F8 開發者大會

除了將研究和生產特性結合起來,PyTorch 1.0 還將 ONNX 包含進來。ONNX 是 Facebook 去年聯合多家軟硬體公司發布的神經網路模型轉換協議,現在,它新增了對蘋果的 Core ML、百度 PaddlePaddle、高通 SNPE 的支持,再加上原本支持的 MXNet、Caffe2、PyTorch、TensorFlow、CNTK 等框架,實現了神經網路模型在各種主流框架之間的轉換。

PyTorch 1.0 beta 版將在今年夏天和用戶見面。

整體來看,剛發布一年左右的 PyTorch 仍然是款比較新的框架,尤其是和 TensorFlow 相比較而言,但 PyTorch 發展非常迅猛。

比如今年 3 月,人工智慧大神 Andrej Karpathy 在推特上曬出了過去 6 年 aXriv 論文中各主要深度學習框架的使用比例(單次計算):TensorFlow 14.3%,PyTorch 4.7%,Keras 4.0%,Caffe 3.8%,Theano 2.3%,Torch 1.5%,MXNet、Chainer 和 CNTK 均小於1%:

如果我們細看會發現 PyTorch 增長勢頭驚人:

因此,未來在深度學習框架領域預計 PyTorch 會成為 TensorFlow 的主要挑戰者。

那麼這兩種框架有何不同之處?自己學習使用時,該選哪一種?

Cinimex DataLab CTO Kirill Dubovikov 發文詳細分析了 PyTorch 和 TensorFlow 的區別,可以參考一下。(註:本文寫於去年,當前一些性能細節可能已經更新)。


本文我(Kirill Dubovikov——譯者注)想探究一下 PyTorch 和 TensorFlow 這兩種框架之間的重要區別。為何選它們?現在市面上有很多深度學習框架,其中有些都是很不錯的工具,我選這兩個是因為我對詳細比較它們很感興趣。

起源

TensorFlow 由谷歌大腦開發,並被谷歌應用在研究和產品需求中。它的前身是閉源工具DistBelief。

PyTorch 算是基於 Lua 語言的框架 Torch 的近親,Torch 廣泛應用在 Facebook 研發中。然而,PyTorch 並非簡單的只是一套支持流行編程語言的封裝器,它被重新編寫,運行速度更快,感覺更原生。

比較這兩種框架的最好方式就是用它們寫寫代碼。我給本文也寫了個比較它們的 Jupyter notebook,可以點擊這裡查看(github.com/kdubovikov/t)。後面我也會引用裡面的代碼。

首先,我們用這兩個框架為下面這個函數寫一個簡單的逼近器(approximator):

我們會試著根據數據X和函數值f(x)找到未知參數phi。沒錯,用隨機梯度下降解決這個問題有點大材小用,用分析解法會容易些,但我們這個問題作為一個簡單的例子能很好的用於比較這兩種框架。

我們首先用 PyTorch:

如果你有過使用深度學習框架的經驗,你可能會注意到我們是在手動實現梯度下降。覺得不是很方便?幸好 PyTorch 有 optimize 模塊,應用了不少流行的優化演算法比如 RMSProp 和Adam。

我們會使用 SGD 演算法:

可以看到,我們從訓練數據中快速的引用了真正的指數。下面我們試試TensorFlow:

同樣可以看到,在TensorFlow中也能實現。雖然TensorFlow獲得指數用的迭代次數更多,但我確定是因為我沒有認真調整優化器的參數,達到可以比較兩者結果的水平。

現在,我們接著探究更多的不同之處。

區別#0 —— 應用

目前很多研究人員和從業人員把 TensorFlow 看作一款隨手可用的工具。TensorFlow 官方提供了很好的使用文檔,如果文檔中沒有,網上也有很多寫的非常詳細的教程。GitHub 上也能找到一大堆用 TensorFlow 實現和訓練的模型。

PyTorch 和 TensorFlow 相比,還是個比較新的工具,但發展勢頭很猛。官方文檔和教程也不錯。PyTorch 也包含了流行計算機視覺框架的實現,非常易用。

區別 #1——動態及靜態圖形定義

兩種框架都在張量上運行,把任何模型都看作一個有向非循環圖(DAG),但對於如何定義它們,PyTorch 和 TensorFlow 區別很大。

TensorFlow 遵循「數據即是代碼,代碼就是數據」的理念。在 TensorFlow 中,在跑模型之前會靜態的定義圖形。和外界的所有聯繫都是通過 tf.Session 對象和 tf.Placeholder,它們都是會在模型運行被外部數據取代的張量。

在 PyTorch 中,會更動態一些:你可以隨著進展定義、更改和執行節點,沒有特殊的會話界面或佔位符。整體來看,PyTorch 和 Python 結合的更緊湊些,多數時候會感覺更原生。而在 TensorFlow 里寫東西時,有時你會覺得你的模型好像躲在一堵牆後面一樣,就通過牆上的幾個洞洞跟你交流。當然了,這也看每個人的喜好和品味。

不過,不單單是在軟體工程方面有區別,一些動態神經網路架構可以從這種動態方法種受益。回想一下循環神經網路:有靜態圖形,輸入序列長度會保持不變。這意味著如果你開發一個應用於英語句子的情緒分析模型,就必須將序列長度修正為某些最大值,用 0 填補所有較小的序列。這比較麻煩吧。在遞歸循環神經網路和樹形循環神經網路方面,你會遇到更多問題。

目前,TensorFlow 對於動態輸入的支持比較有限,而 PyTorch 則是默認的支持動態輸入。

區別 #2—— 調試

由於 PyTorch 的計算圖是在運行時定義,因此可以用 pdb,ipdb,PyCharm 這些 Python 調試工具或者以前的可靠的列印語句也行。

TensorFlow 則不同,你可以選擇用一個叫 tfdbg 的特殊工具,它能讓你在運行時評估 TensorFlow 表達式,瀏覽所有張量,在會話範圍中操作。當然,無法用它調試 Python 代碼,因此無需單獨使用 pdb。

區別 #3——可視化

在可視化方面,TensorFlow 的 Tensorboard 是個非常棒的功能。它內置在 TensorFlow 中,在調試和比較不同的訓練狀況時非常有用。例如,假設你訓練了一個模型,然後調整一些超參數後又訓練一次。而在 Tensorboard 上可以將這兩次模型運行狀況同時展現出來,從而看出兩次的差異。Tensorboard 可以:

  • 展示模型圖形
  • 繪製標量變數
  • 可視化分布和直方圖
  • 可視化圖形
  • 播放音頻

Tensorboard 可以展示多種總結,通過 tf.summary 模塊就可以收集到。我們可以為前面的指數例子定義總結操作,用 tf.summary.FileWriter 將它們保存到桌面。

執行 tensorboard --logdir=./tensorboard 就可啟動 Tensorboard。由於它是 web 應用,因此可以很方便的用在雲實例上。

目前 PyTorch 並沒有可以和 Tensorboard 匹敵的工具,不過倒是存在一些集成功能。雖然也能用一些繪圖工具比如 matplotlib 和 seaborn,但在可視化這方面,PyTorch 要遜於 TensorFlow。

區別 #4——部署

在部署這方面,TensorFlow 很明顯目前略勝一籌:其內置框架 TensorFlow Serving 能讓你在特製的 gPRC 伺服器上部署你的模型。也同樣支持移動端。

在 PyTorch 上,我們就需要用 Flask 或其它工具在模型上編寫一個 REST API。在使用 TensorFlow 的時候,如果 gPRC 不是很適用,我們同樣可以這麼做。不過,如果考慮性能的話,TensorFlow Serving 會是更好的選擇。

TensorFlow 同樣支持分散式訓練,這點 PyTorch 目前尚不具備。

區別 #5—— 數據並行

PyTorch 不同於 TensorFlow 的最大特性之一就是聲明式數據並行:你可以用 torch.nn.DataParellel 封裝任何模型,而且模型能在批處理維度上實現並行。這樣你就可以毫不費力的使用多個 GPU。

另一方面,TensorFlow 能讓你調試在具體設備上運行的所有操作。不過,數據並行不僅需要手動調整,還需要深思熟慮。我們看看在 TensorFlow 中實現數據並行的代碼:

def make_parallel(fn, num_gpus, **kwargs): in_splits = {} for k, v in kwargs.items(): in_splits[k] = tf.split(v, num_gpus)out_split = [] for i in range(num_gpus): with tf.device(tf.DeviceSpec(device_type="GPU", device_index=i)): with tf.variable_scope(tf.get_variable_scope(), reuse=tf.AUTO_REUSE): out_split.append(fn(**{k : v[i] for k, v in in_splits.items()}))return tf.concat(out_split, axis=0)def model(a, b): return a + bc = make_parallel(model, 2, a=a, b=b)

我們可以看到,用 TensorFlow 也能實現用 PyTorch 做到的所有操作,但是要麻煩的多(不過相應會有更多的控制權)。

此外值得一提的是,兩個框架都支持分散式執行,提供用於定義集群的高水平界面。

區別 #6——一個更像框架,一個更像庫

我們搭建一個分類手寫數字的 CNN 分類器。PyTorch 開始會看起來很像一個框架。回想一下,編程框架會在特定領域為我們提供有用的抽象,用它們可以很方便的解決具體問題。而這是框架和庫的的本質區別之處。

這裡我們引入 datasets 模塊,它包含的封裝器適用於眾多用於基準測試深度學習架構的常見數據集。此外,nn.Module 用於搭建自定義 CNN 分類器,就好比 PyTorch 中的程序塊(building block),能讓我們創建複雜的深度學習架構。在 torch.nn 包中有很多現成可用的模塊,可以作為我們模型的基礎。PyTorch 用面向對象的方法來定義基本的程序塊,在通過子類化拓展功能的同時,也給了我們一些「通道」繼續前行。

這是略微修改後的模型版本:

github.com/pytorch/exam

相比之下,TensorFlow 給人的感覺更像是一個庫,而非一個框架:所有的操作都為低階操作,你需要寫很多樣板代碼,即便你可能並不想寫(比如,一遍又一遍的定義方差和權重···)。隨著時間推移,也漸漸出現了一批圍繞 TensorFlow 的高級封裝器,都是為了簡化我們使用 TensorFlow 的方式。它們大部分目前都在 tensorflow.contrib 模塊中(很多人並不將它看做一個穩定的 API),有些也遷移到了主庫中(見 tf.layers)。

所以,你在如何使用 TensorFlow 上有很大的自由度,同樣也能自由選擇使用最匹配任務的框架:TFLearn,tf.contrib.learn,Sonnet,Keras,plain tf.layers 等等。說實話,僅 Keras 這一個框架,就能單獨寫一篇文章討論。不過這已超出本文討論範圍,暫且不表。

這裡我們用 tf.layers 和 tf.contrib.learn 搭建我們的 CNN 分類器,代碼和 tf.layers 官方教程一致:tensorflow.org/tutorial

因此,TensorFlow 和 PyTorch 都能提供有用的抽象,減少樣板代碼的數量,加快模型的部署速度。這兩者的主要不同之處是 PyTorch 感覺更有「Python 味」一些,採用面向對象的方法,而 TensorFlow 有多種供你選擇的選項。

總結

TensorFlow 是一款強大而成熟的深度學習庫,有強大的可視化性能,以及用於高水平模型開發的多個選項。它具備生產就緒的部署選項,也支持移動平台。如果你符合以下情況, TensorFlow 會是個很好的選擇:

  • 開發用於生產的模型
  • 開發需要在移動平台上部署的模型
  • 想要非常好的社區支持和較為全面的幫助文檔
  • 想要豐富的多種形式的學習資源
  • 想要或需要使用 Tensorboard
  • 需要用到大規模的分散式模型訓練

PyTorch 仍然是個比較年輕的框架,但發展迅速。如果符合以下情況,PyTorch 就比較適合你:

  • 正在做機器學習研究,或開發的產品在非功能性需求方面要求不高
  • 想要獲得更好的開發和調試經驗
  • 喜歡很有「Python 味」的東西

如果你有時間也有條件,這兩種都可以試試,看看哪個更符合你的需求和使用習慣。


參考資料:

towardsdatascience.com/

推薦閱讀:

TAG:TensorFlow | 深度學習DeepLearning | PyTorch |