深度学习:网络的编程模式比较
????? ? 文章對原始文章有修改,如有歧義,請移步原文。
????? ? 原文連接: ? ?? MXNet設計筆記之:深度學習的編程模式比較??????????????????????????????????????????
??????? 原始連接:?????? Programming?Models?for?Deep?Learning????????????????????????????????????????
??????? 符號式編程的一個特點是延遲運行,先生成計算圖,再次進行一次運行整個計算模型。因為涉及到延遲運行,可以在真正運行來臨之前進行運算圖的優化,比如多個乘法和加法累計為一個運算,優化計算效率。
??????? 有得必有失。
符號式編程?vs?命令式編程
?????? 在這一節,我們先來比較符號式程序(symbolic?style?programs)和命令式程序(imperative?style?programs)兩種形式。如果你是一名Python或者C++程序員,那你應該很熟悉命令式程序了。命令式程序按照我們的命令來執行運算過程。大多數Python代碼都屬于命令式,例如下面這段numpy的計算。
import numpy as np a = np.ones(10) b = np.ones(10) * 2 c = b * a d = c + 1當程序執行到?c?=?b?*?a?這一行時,機器確實做了一次乘法運算。符號式程序略有不同。下面這段代碼屬于符號式程序,它同樣能夠計算得到d的值。
B = Variable('B') C = B * A D = C + Constant(1) # compiles the function f = compile(D) d = f(A=np.ones(10), B=np.ones(10)*2)??????? 符號式程序的不同之處在于,當執行?C?=?B?*?A?這一行代碼時,程序并沒有產生真正的計算,而是生成了一張計算圖/符號圖(computation?graph/symbolic?graph)來描述整個計算過程。下圖就是計算得到D的計算圖。
??????? 大多數符號式程序都會顯式地或是隱式地包含編譯步驟。這一步將計算圖轉換為能被調用的函數。在代碼的最后一行才真正地進行了運算。符號式程序的最大特點就是清晰地將定義運算圖的步驟與編譯運算的步驟分割開來。
??????? 采用命令式編程的深度學習庫包括Torch,Chainer,?Minerva。采用符號式編程的庫有Theano和CGT。一些使用配置文件的庫,例如cxxnet和Caffe,也都被視為是符號式編程。因為配置文件的內容定義了計算圖。
??????? 現在你明白兩種編程模型了吧,我們接著來比較它們!
命令式程序更加靈活
??????? 這并不能算是一種嚴格的表述,只能說大多數情況下命令式程序比符號式程序更靈活。如果你想用Python寫一段命令式程序的代碼,直接寫就是了。但是,你若想寫一段符號式程序的代碼,則完全不同了。看下面這段命令式程序,想想你會怎樣把它轉化為符號式程序呢。
a = 2 b = a + 1 d = np.zeros(10) for i in range(d):d += np.zeros(10)??????? 你會發現事實上并不容易,因為Python的for循環可能并不被符號式程序的API所支持。你若用Python來寫符號式程序的代碼,那絕對不是真的Python代碼。實際上,你寫的是符號式API定義的領域特定語言(DSL)。符號式API是DSL的加強版,能夠生成計算圖或是神經網絡的配置。照此說法,輸入配置文件的庫都屬于符號式的。
由于命令式程序比符號式程序更本地化,因此更容易利用語言本身的特性并將它們穿插在計算流程中。例如打印輸出計算過程的中間值,或者使用宿主語言的條件判斷和循環屬性。
符號式程序更高效
??????? 我們在上一節討論中提到,命令式程序更靈活,對宿主語言的本地化也更好。那為何大部分深度學習函數庫反而選擇了符號式呢?主要原因還是內存使用和運算時間兩方面的效率。我們再來回顧一下本文開頭的小例子。
import numpy as np a = np.ones(10) b = np.ones(10) * 2 c = b * a d = c + 1 ...
?????? 假設數組的每個單元占據8字節。如果我們在Python控制臺執行上述程序需要消耗多少內存呢?我們一起來做些算術題,首先需要存放4個包含10個元素的數組,需要4?*?10?*?8?=?320個字節。但是,若是運行計算圖,我們可以重復利用C和D的內存,只需要3?*?10?*?8?=?240字節的內存就夠了。
??????? 符號式程序的限制更多。當用戶對D進行編譯時,用戶告訴系統只需要得到D的值。計算的中間結果,也就是C的值,對用戶是不可見的。這就允許符號式程序重復利用內存進行同址計算(in-place?computation)。
??????? 然而,命令式程序屬于未雨綢繆的類型。如果上述程序在Python控制臺執行,任何一個變量之后都有可能被用到,系統因此就不能對這些變量共享內存區間了。
??????? 當然,這樣斷言有些理想化,因為命令式程序在變量超出作用域時會啟動垃圾回收機制,內存將得以重新利用。但是,受限于“未雨綢繆”這一特點,我們的優化能力還是有限。常見于梯度計算等例子,我們將在在下一節討論。
??????? 符號式程序的另一個優化點是運算折疊。上述代碼中,乘法和加法運算可以被折疊為一次運算。如下圖所示。這意味著如果使用GPU計算,只需用到一個GPU內核(而不是兩個)。這也正是我們在cxxnet和Caffe這些優化庫中手工調整運算的過程。這樣做能提升計算效率。
??????? 在命令式程序里我們無法做到。因為中間結果可能在未來某處被引用。這種優化在符號式程序里可行是因為我們得到了完整的計算圖,對需要和不需要的變量有一個明確的界線。而命令式程序只做局部運算,沒有這條明確的界線。
后續:
??????? ......................................................
??????? ...........................................................
總結
以上是生活随笔為你收集整理的深度学习:网络的编程模式比较的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 时间转换
- 下一篇: 各种流行深度学习构架的性能对比