PyTorch和TensorFlow到底哪個更好?看看研究者們怎麼說

Theano、TensorFlow、Torch、MXNet 再到近日比較熱門的 PyTorch 等等,深度學習框架之間的比較一直以來都是非常受人關注的熱點話題。機器之心也曾發表過多篇相關的介紹和對比文章,如《主流深度學習框架對比:看你最適合哪一款?》、《五大主流深度學習框架比較分析:MXNET 是最好選擇》、《對比深度學習十大框架:TensorFlow 最流行但並不是最好》和《從 TensorFlow 到 Theano:橫向對比七大深度學習框架》。

不過你知道用戶實際用起來的感覺怎麼樣嗎?近日,Reddit 用戶 cjmcmurtrie 發了一個主題為「PyTorch vs. TensorFlow」的討論帖,想要了解這兩大流行的框架之間各自有什麼優勢。

原帖地址:[D] So... Pytorch vs Tensorflow: whats the verdict on how they compare? What are their individual strong points? ? r/MachineLearning

帖子一樓寫道:

我還沒有從 Torch7 遷移到 TensorFlow。我玩過 TensorFlow,但我發現 Torch7 更加直觀(也許是我玩得不夠?)。我也嘗試了一點 PyTorch,所以我決定先看看效果。

使用了幾周 PyTorch 之後,我認為我現在還不必遷移到 TensorFlow,至少在我感興趣的項目上還不需要。用 PyTorch 寫自定義模塊真是簡單至極。而且其動態圖構建(dynamic graph construction)給我之前需要熬夜實現(或等待列表上)的東西帶來了很多新想法。我認為對機器學習開發者來說,PyTorch 是一個了不起的工具集。我也知道 TensorFlow 的社區資源要強大得多,但如果要開發全新的項目(而不是為已有的架構重新寫代碼或閱讀教程),社區也不一定能有很大的幫助。

這個 Reddit 帖子發出後得到了很多機器學習研究者和開發者的關注,他們紛紛跟貼談論自己的想法和經驗(不只是關於 PyTorch 和 TensorFlow,討論中還涉及到更多工具)。機器之心在這裡選擇其中一些我們認為有價值的評論,希望能夠給你的學習和研究帶來幫助。以下按贊成數量排序。

ajmooch的回復:

我一直在做一個 TensorFlow 的項目,所以我可以公正地在 Theano+Lasagne, PyTorch 和 Tensorflow 三者之間做一個比較。但對於前兩者,我可以給出一些漫漫的看法。

背景:大概在一年前我開始接觸 Theano+Lasagne,並在我的兩篇論文中使用了它。我上周改換到 PyTorch,並重新建了兩個我以前用 Theano 實現的關鍵項目。

API:Theano 的圖形構建和編譯工作方式讓我學習起來很費勁,但一旦我找到了它的竅門,一切都迎刃而解(這也許會花費兩個月,但是我仍舊在學習 Python 和基本的神經網路方面的東西,所以對這一速度的參考價值持保留態度)。Lasagne 的 API,對我來說,就像是優雅的凱瑟琳女皇騎著逆戟鯨展開了戰鬥,也就是說我愛死它了。如果我提前知道我有多想要一個 Theano 的程式庫去工作,我一定會寫一個程式庫,這大大地減輕了繁重的勞動。

PyTorch 的 API,另一方面來說感覺有些粗糙,但對它有一些限定詞,這個稍後再談。如果你只是做一些標準的任務(實現 ResNet 或者 VGG)我認為你不會有問題,但我一直都有一些分歧因為我所做的一切都有些奇怪。舉個例子,在我當前的項目中,因為 strided 張量索引(tensor indexing)還未實現,我必須使用幾個 hacky 解決方法,雖然當前的索引技術非常靈活,比起直接使用 numpy 風格的索引,它們少了很多直觀性。中心的限定條件是,它們確實只是釋放 friggin 的框架,當然並不是一切都實現,還有一些待解決的問題。Theano 發展時間長且已經成熟,我並沒有觀察到它或者 Lasagne 在這個過程中遇到過困難。

除此之外,對於 PyTorch 我最大的「抱怨」基本上是在神經網路 API 方面「事情並未按照我讓他們組合的方式進行放置」。具體來說,我非常喜歡 Lasagne 的「層次(layers)」範式—但是一點點批判性的思維就會讓你得出這個結論,這個範式尤其不適合動態圖框架。我完全習慣於考慮並且優化我關於靜態圖形定義的思考過程,所以轉換 API 方法是一個小的痛點。這非常重要-我花了很長時間思考「好吧,既然我不能使用自己的標準流控制寫出一個常規的程序一樣,寫出這個圖的 Theano,那麼我該如何定義它呢,」這讓我在思維的道路上變得越來越強大。

然而,動態圖需要一個與「定義+運行」基本不同的 API,雖然我個人認為它並不直觀,就在上周其單獨執行定義的方法,正如 CJ 所說,打開了我的思路並給了我幾十個項目的想法,這在以前是不可能的。我還想像,如果你在任何你想的地方使用 RNNs 做任何事情,比如,在沒有消耗計算的前提下實現動態計算,介面的命令性質將會使它更容易這樣做。

速度:所以我沒有做廣泛的基準測試,但是我驚訝的發現,PyTorch 是可以立即使用的,在我當前的項目的單 GPU 的訓練時間比 theano+lasagne 快 100%。我已經在 Geforce gtx 980 和 Titan X 上測試了它,並實現了已經確認相同且在合理的誤差範圍內的網路。100% 逐字地在 CIFAR100 上從(在最簡單的情況下)5 分/曆元到 2.5 分/曆元,並且在某些情況下降到 2 分鐘/曆元(即,快兩倍)

這是相同的模板代碼,使用了相同的數據提取程序(我不得不諷刺地說「fetcher」沒有思考「去死吧,FETCHER(DIE, FETCHER!)」),除了實際的代碼,訓練和運行網路,一切都相同。

這讓我感到驚訝,因為我的印象是,Theano 的廣泛和積極的內存優化(在這種情況下,當你開始訓練,只需花費幾分鐘進行編譯)意味著它在單 GPU 下的速度非常快。我不知道什麼導致了速度的提升,或者,因為他們同樣都使用了 cuDNN 的最新版本(我仔細地檢查了一遍以確保的確是這樣),所以這一切的收穫一定在天空的某一個地方,但我並不知道會在哪裡。

相關地,使用 Theano 工作時,我從來沒有能夠得到多 GPU 或者半精度浮點數。我花了好幾天的時間試圖讓 libgpuarray 工作,並使用 platoon 試圖進行修復,但每次我都會精疲力盡(想像一下即使我可以得到編譯的資源也不會如此困難,這已經是一個痛點了)。然而,立即使用的 PyTorch 的數據並行性(單節點,4 GPU)和半精度(用於卷積的 pseudo-FP16,這意味它不會變快但是會使用更少的內存)問題就解決了。當時就是這樣。

開發團隊交互:我與兩個框架的核心開發團隊一直交流的非常愉快。對於 Lasagne 和 Theano,我遇到了一些困難,很多奇怪的問題。很多次,他們總是快速且簡潔地幫我弄清楚什麼錯了(我通常不明白)。PyTorch 團隊同樣有幫助—我一直在提出我遇到的錯誤或問題,並得到及時的反映,通常會在當天修復,或者得到解決方法或得到問題跟蹤。我並沒有在 Keras 或者 Tensorflow 上工作,但是我看過他們的「問題」日誌和一些用戶組,只是因為大量的用戶,這些框架看起來並不會得到這種個人的關注 - 就像是我去 Cal Poly(加州理工州立大學)一樣,在這個地方,教授/學生的比例很高,你很少看到一個班中有超過 20 個學生,然而在 Berkeley 你能看到 1000 人的演講廳。這並非批評 Cal 的孩子或者暗示 berkeley 盲目擴招,但如果你是一個像我一樣開發非標準神經網路的人(我並不是在說 Chuck Tingle weird),然而從一個實際構建框架的人那裡得到快速的反饋,這是非常寶貴的能力。

Misc:我擔心一個特別的問題(為什麼我打算幾年拾起 TensorFlow 並將它作為主要框架),Theano 和 PyTorch 都沒有為部署設計,開發團隊它看上去並沒有把重心放在 PyTorch 上(雖然在這方面,我可能看錯了,我模糊的記得我在論壇的帖子上看到過這個)。我想要練習將一些東西放置在網站或者 droid app 上(主要是為了娛樂,但我一直都非常專註於研究並認為這是一個真正有用的技能,可以實際獲得我在設備上所做的東西),我不確定其他的框架能很好地支持這種方式。

相關地,PyTorch 的分散式框架仍然是實驗性的,最近我聽說 TensorFlow 在設計時就考慮到了分散式,所以如果你需要運行真正的大規模項目,TensorFlow 多半是最好的。

TL;DR:我並不是試圖推薦哪個框架比較好;我至死都愛 Lasagne(可能更多),但我已經發現動態圖的靈活性和其快速地、難以理解的增益的速度。我在上個星期安裝了 PyTorch 並且只用了非常少的時間就上手了,我想我不太可能回頭了。我並不是很了解 TensorFlow。但能從 PyTorch 開發者那裡得到及時反饋對我來說是很重要的一點,因為我正在做一些看來有點奇怪的研究,但在未來我也可能為一些項目重新使用 TensorFlow。這個討論帖非常棒,但我希望在你閱讀過後的印象是:這是他們的主觀經驗,而不是一個刻板的印象如:「就是這樣,你絕對會感到同樣的方式」。

taion的回復:

我們最近從 Theano+Lasagne 轉到了 TensorFlow。

我還沒有嘗試過任何分散式的架構,但總體上用過 Theano 之後再用 TensorFlow 感覺非常熟悉——甚至更好。對你提到的幾點,回復如下:

等效的圖形編譯(graph compilation)要快得多;我們用了幾秒而不是幾分鐘。但是它仍然不夠快,如果我們想要將它的大部分添加到我們的 CI 套件(CI suite),但我們不需要等待很長時間來開始訓練。

從 Lasagne 轉到 TensorFlow 之後,我喜歡 tf.layers 和 tf.contrib.layers 中更高層次的功能;它們為接受張量(tensor)並返回張量的功能性 API,因此更容易與「原始」的 TensorFlow 集成。我們可以做普通的張量操作,而不用寫一個層那麼麻煩。

在我們使用的模型上,TensorFlow 的速度稍稍快於 Theano(20%-30%)。當第一次使用時,我們看到大致相同的性能,並認為這可以接受,但然後我們閱讀 TensorFlow 的性能指南(tensorflow.org/performa),並切換到 NCHW 並融入批處理規範(batch norm),然後一切運行得更快了。我猜 Theano 本身就不是很快……

關於開發人員的反饋速度:我曾在 TF 的問題區提出了一些微不足道的問題,但 TF 開發人員通常在一兩天內就回復我了。

此外,工具是相當好的。TensorBoard 絕對好用,用來表示的時間線(timeline)/跟蹤(trace)的工具也一樣好用。但是我還沒有嘗試新加入的 tfdbg。

TensorFlow 當然也有幾個缺點,例如在實踐中部署到 iOS,但這說來話長。使用 TensorFlow 不是沒有痛苦,但與需要 Python runtime 的 Theano 相比,這還算什麼事情嗎?這是相當大的進步。

如果你使用 TensorFlow,我強烈建議你看看 tf.layers 或 TF-Slim。具體的說,tf.layers 本質上嵌入了 Keras API。

儘管我不指望任何有意義的性能差異;本帖討論的操作最終定義了一個靜態計算圖形(computation graph),所以使用像 Keras 這樣的包裝器本身並不增加資源消耗,除了在圖形定義時最小的資源佔用,但是如果你原來使用 Theano,你會感到 TensorFlow 的啟動時間快得多(以秒計而不是以分鐘計的編譯速度)。

遵循 TensorFlow 性能指南(TensorFlow performance guide)非常有用。在 DenseNet(L = 40,k = 12)模型上,從默認的 NHWC 和未融入批處理規範切換到 NCHW 和融入批處理規範後,我們的每個 epoch 時間都下降了超過 30%。在 WRN-16-4 模型上,我們看到 epoch 時間下降了超過 20%。

badmephisto(Andrej Karpathy)的回復:

我認為在深度神經網路庫的設計方面,PyTorch 目前已然接近啟發的高度。

  • 它屬於輕量級;

  • 它目前位於 Python 中;

  • 它使你能夠明確地控制計算。沒有編譯器能自己妄圖變聰明來「幫助你」,或是將你的代碼加速;事實上大多編譯器在調試中會產生大量麻煩;

  • 它使 GPU 內核調用之上僅有少量(可解釋的)抽象層,而這恰恰是高性能的保證;

  • 也許這是個人偏好,但我得到了與抽象有關的特定 OCD。每當我要做艱巨的工作時都會很緊張,因為一旦我的未來被泄漏,我便能感覺到它那些無法擺脫且難以忍受的痛苦。相對簡單的事情理應在引擎蓋之下發生的大多數情況下,這種感覺尤為強烈;

  • 調試更容易,因為特定代碼中會是特定行(而不是在距離使用大型或生成的 Graph 對象的 sess.run()很遠的地方)失敗。你的堆棧跟蹤不會填滿三個屏幕來讓你玩「找找錯誤在哪裡!」的豎版捲軸遊戲;

  • 不存在編譯時間。我無法理解 Theano 用戶是如何處理的,他們一定更有耐心;

  • 你可以直接操作漸變,顯然,做一些事情時可以更容易,也更自然(如在反向傳播過程中的漸變剪輯,或各種「破碎的反向傳播」的有關想法,就像最近的 Shake Shake reg 命令一樣;的確,我認為你可以用 stop_gradient 破解一個解決方案);

  • 它對動態圖的支持從一開始就是自上而下的設計原則,而非隨之而至的事後想法。並且我們會看到更多的動態圖表,如做成一大塊 NLP,或是神經模塊網 ;

  • 它沒有縮進或膨脹你的代碼的顯式會話對象;

  • 它獲得的抽象是正確的:raw numpy - > Tensors(但 GPU 上的 raw numpy 可能對深度學習一無所知!)- >變數(它們了解深度學習),並且 Modules 或 Optim 等等會稍有益處。

到目前為止,我與 TF 的有關經驗有些膨脹,所以即便是像數據驅動初始化這樣理應很簡單的事情,也會用到一些 tricks。當然,TF 的開發者有他們的一套解決方案,但往往涉及你從未聽說過的 5 個 TensorFlow 函數的組合。我不記得曾用 Torch 做過這些,又或許我現在做的事情更複雜。

免責聲明:我仍行進於對 PyTorch 進行嘗試的漫漫征途中;所以我的經驗是基於在 TensorFlow 做了很多複雜事情,而在 PyTorch 上才剛剛開始的背景上得到的。讓我們看看未來會發生什麼。

jeremyhoward的回復:

對於 Practical Deep Learning For Coders-18 hours of lessons for free 的第 2 部分,我們從 keras + theano(第 1 部分)切換到 Keras、TensorFlow 和 PyTorch 合用的狀態。一般而言,使用 PyTorch 總是令人愉快的,主要是因為:

  • 動態計算使很多事情更加容易,如 seq2seq + attention 的神經翻譯很難通過 keras + tf 來實現,但使用 PyTorch 便會很容易;

  • 更容易調試,因為你可以只使用標準的 PyThon 工具;

  • PyTorch 讓自定義的實現更加容易,所以你得以將更多時間專註於演算法中,這樣往往能夠改進主要性能;

  • 使 Multi-gpu 簡單易懂;

  • Torch-vision 使載入和變換圖像變得容易。

TensorFlow 的 API 非常荒謬,它在每個階段都會重新發明輪子,並且要求開發者學習很多本不必要的新概念。然而,開發者峰會表示這一境況正在改善——而且同時使用 TensorFlow Servin 和 Cloud ML 會提高你的生產力。

Powlerbare的回復:

我大約在半年前使用 TensorFlow 實現了一些 seq2seq 模型,並意識到為何 TensorFlow 很好用:它的內置組件很棒,讓研究變得就像有老師在推動著你一樣容易,而注意與損失函數就如同雜訊對比估測,等等。倘若我收集基線或修改函數,一切都會變容易。我已經習慣於搜索代碼庫,並確定究竟哪種函數在運作(如果不小心,某些可選的函數默認值便會得到不好的結果)——並且我對基於這些實現的大部分報告結果非常有信心。

下面是幾點與我所愛的 PyTorch 有關,而 TensorFlow 卻不會提供的事項:

1)PyTorch 提供了一個強化功能,我很喜歡它。增強功能基本上不會在實現中產生過多資源消耗,能有一些內置函數來調用 RL 的感覺真棒。

2)我並未大量使用 autograd,因為那時它速度很慢,但人們感覺用它來做一些沒譜的事情很有趣。我是這個範例的死忠粉,因為我沒來由地鍾愛在 numpy 上編寫網路。

選自Reddit機器之心編譯

推薦閱讀:

學習tensorflow,買什麼筆記本好?
【博客存檔】深度學習之Neural Image Caption
如何看待Face++出品的小型化網路ShuffleNet?
TensorFlow從1到2 | 第五章 非專家莫入!TensorFlow實現CNN

TAG:TensorFlow | Torch深度学习框架 | 深度学习DeepLearning |