---
tags: Knock Knock! Deep Learning
---
Day 7 / PyTorch / 深度學習框架之亂
===
前一週我們很快速但不馬虎的帶過 Deep Learning 的基礎,包含概念、數學原理、和穩定訓練的方法,接著就要實際上手啦!
如果前面介紹的數學對你來說有點吃力,那不用擔心,因為已經有很多開源的 **deep learning framework(深度學習框架)** 可以使用,他們把數學邏輯和運算優化都處理好,而我們只要負責設計 model 的架構,再運用他們提供的 API,即可方便快速的建立 network 開始進行訓練。
> 如果想挑戰自己,也可以試著用 numpy 自己寫出 deep learning 的小框架喔。非常推薦想要內化前面所學內容的朋友這麼做。可以參考 Stanford 兩門課的作業 [CS224n Assignment 2](http://web.stanford.edu/class/cs224n/) 和 [CS231n Assignment 1, 2](http://cs231n.stanford.edu/syllabus.html) 來開頭。
> 你可能會問,啊都有這些好用的框架了,我們為什麼還要這麼囉唆學這些數學?因為沒有背後這些數學知識,很難架構出一個比別人好的框架,也不知道出錯要 debug 的時候中間這些 parameter 顯示出什麼問題,因為你根本不知道他們是怎麼得出來的。
>
本系列文主要介紹的是 [PyTorch](https://pytorch.org/) 這個 Facebook 在 2017 開源的框架,是個語法簡潔、好上手、且在學術界流行的框架。很多大學的 deep learning 相關課程,現在作業也漸漸移植到 PyTorch。
事實上在 PyTorch 出現之前,最流行的框架就屬 Google 開源的 TensorFlow 了。此外還有很多其他流派,Keras、MXNET、Caffe 等等。在進入 PyTorch 的介紹之前,先來簡單認識各大框架的發展和優缺點吧!也更加了解為什麼我們選擇 PyTorch。
## Theano

[Theano](http://deeplearning.net/software/theano/) 是個很早期的 framework,從 Montreal Institute for Learning Algorithms (MILA) 也就是學術界發展出來的,也是最早使用 computation graph 概念來設計 framework 的。Computation graph 的概念等一下會提到。
在 2017 年,作者發表停止 major development,主因是太多業界的競爭對手了。感覺學界發展出來的 framework 大多成為業界的啟發或原型,開發維護者肯定比不上業界團隊多,不過雖然大部分都淹沒在洪流中,但還算是活在其他 framework 裡。
後來由 [PyMC 接手](https://github.com/pymc-devs/theano-pymc)維護,他們家好像是做 probabilistic machine learning 的 library,不知道為什麼還不肯移植到其他 framework。
## Caffe & Caffe2

[Caffe](https://caffe.berkeleyvision.org/) 是一位 Berkeley 的 PhD 開發出來的,盛行過一段時間。之後由 Facebook 發展的 Caffe2 已經[和 PyTorch 合流](https://caffe2.ai/blog/2018/05/02/Caffe2_PyTorch_1_0.html)。
滿特別的是 model 是用 [protobuf](https://developers.google.com/protocol-buffers) 來定義,也就是開一個文件檔寫 network 的架構和 hyper-parameter,而不是用寫程式定義。
優點是**速度快、CNN 支援好、(早期有)community 支援**,缺點是**除了 CNN 外的支援頗糟、extensibility 差**。
至於 Caffe2 **速度快、scalability 好、且輕量**,和 PyTorch 著重 flexibility 和快速開發互補,也讓他們在 2018 年的時候整合。
> CNN 是 Convolutional Neural Network,主要適用來建立 computer vision 相關的 model,之後會介紹到。
## ONNX

[ONNX (Open Neural Network Exchange)](https://onnx.ai/) 其實不算是 framework,而是一個多方 machine learning model 可以共同遵守的 representation format,讓遵守 format 的不同 framework 可以很容易的互相轉換,增加彈性和互補能力。
當初是由 Facebook 和 Microsoft 在 2017 年提出,支援的 framework 包括 PyTorch、MXNet、TensorFlow 等等。
## MXNET

[MXNET](https://mxnet.apache.org/versions/1.6/) 是在 2015 年由一群 researcher 提出,目前背後沒有大公司撐腰主力開發,只知道 Amazon Web Service 是最知名的採用者。
優點是**速度快、flexibility 好、scalability 佳、語法簡潔**,缺點是 **RNN 支援度差、doc 跟 community 支援也差**。
其實明顯的缺點找不到太多,只是 community 小算滿致命的,以致於新手卡關不容易找到解決辦法。可能也跟沒有大公司主力維護有關,解 issue 不能領薪水這種博愛的工作應該很少人願意做。
## Keras & TensorFlow


[Keras](https://keras.io/) 和 [TensorFlow](https://www.tensorflow.org/) 都是在 2015 年提出,後來在 2017 年由 Google 主導整併,現在是一家人了。會整併當然是因為互有不足啦。
Keras 的優點是**非常容易上手、community support 佳**,把很多東西都包好好給大家使用,但也因此缺點是 **flexibility 差**,想要加入他沒提供的 feature 很難。
TensorFlow 的優點是**功能多、廣大 community 支援、提供 [TensorBoard](https://www.tensorflow.org/tensorboard) 視覺化工具**,缺點是**艱澀囉唆的語法和太底層的接口**。
舉例來說 [2],建立一個 convolutional layer,TensorFlow 會這樣寫:
```
kernel = tf.Variable(tf.truncated_normal([3, 3, 64, 64], type=tf.float32, stddev=1e-1), name='weights')
conv = tf.nn.conv2d(self.conv1_1, kernel, [1, 1, 1, 1], padding='SAME')
biases = tf.Variable(tf.constant(0.0, shape=[64], dtype=tf.float32), trainable=True, name='biases')
out = tf.nn.bias_add(conv, biases)
self.conv1_2 = tf.nn.relu(out, name='block1_conv2')
```
但用了包好好的 Keras 會這樣寫:
```
x = Convolution2D(64, 3, 3, activation='relu', border_mode='same', name='block1_conv2')(x)
```
能用第二種語法的話應該沒人想用第一種吧?
此外 TensorFlow 還有 Session、GradientTape、PlaceHolder 這些很不直觀的概念和命名方式,我想大概是讓 2017 崛起的 PyTorch 迎頭趕上的原因吧。
後來整併 Keras 後 TensorFlow 為人詬病的使用難度改善許多。或許當初因為 TensorFlow 艱澀難懂的語法而選擇其他 framework 的人(對就是我)可以回頭考慮看看。
早期的 TensorFlow 還有個缺點是採用 **static computation graph**,大概類似你先用程式碼寫好一張 network 的草圖,送進去讓 TensorFlow 建立架構,然後再餵 data 訓練。優點是建立的架構可以盡情優化和重複使用,但缺點就是不能在訓練的過程中變動架構。光是 input 大小不一樣的 data 就會造成架構上的改變,雖然有 workaround 但很麻煩,也加深上手難度。另外跑的過程中如果出錯,也很難在中途設個暫停點 debug。這些對於新手是大為不利。
有鑒於此,TensorFlow 2.0 發佈後則是加入了 [Eager Execution](https://www.tensorflow.org/guide/eager),提供 **dynamic computation graph** 的選項,讓你可以邊訓練邊建立和調整架構。
雖然說 TensorFlow 你汲取教訓慢慢改進是很好啦,但怎麼感覺整體越來越像 PyTorch 老對手了!
## Torch & PyTorch


[Torch](http://torch.ch/) 早於 2002 年建立,於 2018 年宣布停止主要開發。他採用較為少見的 Lua 為主要語言,雖然與底層的 C 語言可以很容易結合是優點,但太少人使用 Lua 以致於慢慢沒落。
而後以 Torch 為基礎打造的 [PyTorch](https://pytorch.org/) 於 2017 年由 Facebook 釋出。因為他**語法簡潔易懂、採用 dynamic computation graph、擁有完善的 doc**,讓他漸漸建立起自己的 community,常用於學術界需要快速建立 model 做實驗。

*—— PyTorch vs TensorFlow 在學術會議的採用率。[6]*
雖然在學術界獲得掌聲,但因為起步晚,在不太願意改變自己的業界,採用的 framework 還是以 TensorFlow 為大宗。同時也是因為 PyTorch 採用 dynamic computation graph 的關係,早期會對 mobile 有支援不佳的問題(因為沒辦法轉成小一點的 binary code 塞進手機)。
現在 PyTorch 也提出了一些改進,例如 [TorchScript](https://pytorch.org/docs/stable/jit.html) 可以把 PyTorch code 轉成另一種形式(類似於 static computation graph),而這種形式不需要安裝 Python 就能被執行,也解決了前述的問題。
也就是說 PyTorch 其實也慢慢往 TensorFlow 的方向改進,而現在兩者其實主要功能、語法、和實用度都非常接近了,但一塊分食學術界大餅,另一塊分食業界大餅。
而本系列文採用 PyTorch,一來當然因為作者我比較熟悉,二來後面會介紹比較多學術 paper,三來他對於自身的問題解法比 TensorFlow 簡潔,四來對於 PyTorch 的未來還是比較值得期待的。畢竟再怎麼慢,業界都要跟著 research 走,特別是在 machine learning 這一塊!
## Checkpoint
- Static computation graph 和 dynamic computation graph 有什麼差異和優缺點?
- TensorFlow 和 PyTorch 分別提出了什麼解法改進各自採用的 computation graph 原本帶來的缺陷?
## 參考資料
*註:某些參考資料是為了理解歷史脈絡,稍嫌過時,閱讀的時候請注意年份,deep learning 的資訊很快就過期了。*
1. [Top 8 Deep Learning Frameworks](https://marutitech.com/top-8-deep-learning-frameworks/)
2. [Deep learning frameworks: TensorFlow, Theano, Keras, Torch, Caffe](https://project.inria.fr/deeplearning/files/2016/05/DLFrameworks.pdf)
3. [Tensorflow vs Pytorch - Comparison, Features & Applications](https://www.upgrad.com/blog/tensorflow-vs-pytorch-comparison/)
4. [Deep Learning Frameworks Comparison – Tensorflow, PyTorch, Keras, MXNet, The Microsoft Cognitive Toolkit, Caffe, Deeplearning4j, Chainer](https://www.netguru.com/blog/deep-learning-frameworks-comparison)
5. [Comparison between Deep Learning Tools](https://medium.com/@liyin2015/comparison-between-deep-learning-tools-42560e61a5d5)
6. [👍 The State of Machine Learning Frameworks in 2019](https://thegradient.pub/state-of-ml-frameworks-2019-pytorch-dominates-research-tensorflow-dominates-industry/)