小白學PyTorch | 動態圖與靜態圖的淺顯理解

章節目錄:

1 動態圖的初步推導

2 動態圖的葉子節點

3。 grad_fn

4 靜態圖

本章節簡單縷一縷PyTorch的動態圖機制與Tensorflow的靜態圖機制(最新版的TF也支援動態圖了似乎)。

1 動態圖的初步推導

計算圖是用來描述運算的

有向無環圖

計算圖有兩個主要元素:結點(Node)和邊(Edge);

結點表示資料

,如向量、矩陣、張量;

邊表示運算

,如加減乘除卷積等;

小白學PyTorch | 動態圖與靜態圖的淺顯理解

上圖是用計算圖表示:

其中呢, , , 。 (a和b是類似於中間變數的那種感覺。)

Pytorch在計算的時候,就會把計算過程用上面那樣的動態圖儲存起來。現在我們計算一下y關於w的梯度:

(上面的計算中,w=1,x=2)

現在我們用Pytorch的程式碼來實現這個過程:

import torchw = torch。tensor([1。],requires_grad = True)x = torch。tensor([2。],requires_grad = True)a = w+xb = w+1y = a*by。backward()print(w。grad)

得到的結果:

小白學PyTorch | 動態圖與靜態圖的淺顯理解

2 動態圖的葉子節點

小白學PyTorch | 動態圖與靜態圖的淺顯理解

這個圖中的葉子節點,是w和x,是整個計算圖的根基。之所以用葉子節點的概念,是為了

減少記憶體,在反向傳播結束之後,非葉子節點的梯度會被釋放掉

, 我們依然用上面的例子解釋:

import torchw = torch。tensor([1。],requires_grad = True)x = torch。tensor([2。],requires_grad = True)a = w+xb = w+1y = a*by。backward()print(w。is_leaf,x。is_leaf,a。is_leaf,b。is_leaf,y。is_leaf)print(w。grad,x。grad,a。grad,b。grad,y。grad)

執行結果是:

小白學PyTorch | 動態圖與靜態圖的淺顯理解

可以看到只有x和w是葉子節點,然後反向傳播計算完梯度後(。backward()之後),只有葉子節點的梯度儲存下來了。

當然也可以透過。retain_grad()來保留非任意節點的梯度值。

import torchw = torch。tensor([1。],requires_grad = True)x = torch。tensor([2。],requires_grad = True)a = w+xa。retain_grad()b = w+1y = a*by。backward()print(w。is_leaf,x。is_leaf,a。is_leaf,b。is_leaf,y。is_leaf)print(w。grad,x。grad,a。grad,b。grad,y。grad)

執行結果:

小白學PyTorch | 動態圖與靜態圖的淺顯理解

3. grad_fn

torch。tensor有一個屬性grad_fn,grad_fn的作用是記錄建立該張量時所用的函式,這個屬性反向傳播的時候會用到。例如在上面的例子中,y。grad_fn=MulBackward0,表示y是透過乘法得到的。所以求導的時候就是用乘法的求導法則。同樣的,a。grad=AddBackward0表示a是透過加法得到的,使用加法的求導法則。

import torchw = torch。tensor([1。],requires_grad = True)x = torch。tensor([2。],requires_grad = True)a = w+xa。retain_grad()b = w+1y = a*by。backward()print(y。grad_fn)print(a。grad_fn)print(w。grad_fn)

執行結果是:

小白學PyTorch | 動態圖與靜態圖的淺顯理解

葉子節點的。grad_fn是None。

4 靜態圖

兩者的區別用一句話概括就是:

動態圖:pytorch使用的,運算與搭建同時進行;靈活,易調節。

靜態圖:老tensorflow使用的,先搭建圖,後運算;高效,不靈活。

靜態圖我們是需要先定義好運算規則流程的。比方說,我們先給出

, ,

然後把上面的運算流程儲存下來,然後把w=1,x=2放到上面運算框架的入口位置進行運算。而動態圖是直接對著已經賦值的w和x進行運算,然後變運算變構建運算圖。

在一個課程http://cs231n。stanford。edu/slides/2018/cs231n_2018_lecture08。pdf中的第125頁,有這樣的一個對比例子:

小白學PyTorch | 動態圖與靜態圖的淺顯理解

這個程式碼是Tensorflow的,構建運算的時候,先構建運算框架,然後再把具體的數字放入其中。整個過程類似於訓練神經網路,我們要構建好模型的結構,然後再訓練的時候再吧資料放到模型裡面去。又類似於在旅遊的時候,我們事先定要每天的行程路線,然後每天按照路線去行動。

小白學PyTorch | 動態圖與靜態圖的淺顯理解

動態圖呢,就是直接對資料進行運算,然後動態的構建出運算圖。很符合我們的運算習慣。

兩者的區別在於,靜態圖先說明資料要怎麼計算,然後再放入資料。假設要放入50組資料,運算圖因為是事先構建的,所以每一次計算梯度都很快、高效;動態圖的運算圖是在資料計算的同時構建的,假設要放入50組資料,那麼就要生成50次運算圖。這樣就沒有那麼高效。所以稱為

動態圖

動態圖雖然沒有那麼高效,但是他的優點有以下:

更容易除錯。

動態計算更適用於自然語言處理。(這個可能是因為自然語言處理的輸入往往不定長?)

動態圖更面向物件程式設計,我們會感覺更加自然。

- END -