深度學習與求導鏈式法則

深度學習與求導鏈式法則

來自專欄機器學習與數學50 人贊了文章

前言

最近幾年深度學習席捲了機器學習多個領域,計算機視覺,自然語言處理,推薦系統等等,成為各個領域當中的最佳方法。深度學習或者說神經網路當中最重要的一個要素是反向傳播演算法(Back propagation)。反向傳播演算法與數學當中求導鏈式法則有非常密切的關係,當前的流行的網格結構,無不遵循這個法則,比如計算視覺當中的LeNet、AlexNet、GoogLeNet、VGG、ResNet,還有其它的各種網路。這個法則在之前的文章梯度下降方法與求導有一些涉及,這裡專門再次提前,是為了更清楚的表明它的工作方法。

深度學習與求導鏈式法則的關係

從之前的文章梯度下降方法與求導,我們知道對於可以求導的映射,可以利用對映射當中各個可變參數進行求導,利用梯度下降的方法,慢慢使映射當中的各個可變參數接近想要的值,使 cost 更小。深度學習將多種映射疊加在一起,對輸入進行多個映射處理,理論上,多個映射疊加的表達能力將比單一的映射高,對其進行優化之後可以使 cost 變得更加得小。求導鏈式法則是用來幫助 cost 對各個映射當中的可變參數進行求導的法則。

求導鏈式法則

假設 cost 的計算方式如下,輸入是 m{x} ,目標值是 y f = f(m{x}) \ g = g(f) \ y = k(g)\ cost = criterion(y, y)

如果你要計算 frac{d(cost)}{d(m{x})} ,這裡的 m{x} 可以是一個數字,也可以是一個向量,或者是一個矩陣。你可以通過計算 frac{d(f)}{d(m{x})} 	imes frac{d(g)}{d(f)} 	imes frac{d(y)}{d{(g)}} 	imes frac{d(cost)}{y} 來獲取想要的導數 frac{d(cost)}{d(m{x})} ,在機器學習當中,這裡的三個函數, f,g,k 代表了不同的映射, criterion 也理解成一種映射,只不過這裡的輸入將目標值 y 加入進來了。這裡的 m{x} 代表的是輸入的數據,但是對輸入數值求導的意義不大,因為我們不能對數據進行改變使我們的目標 cost 變得更小,實際情況是要對各個映射當中包含的可變變數進行求導。

舉個例子如果用 w_f 來表示函數 f 當中的可變變數,現在要計算 costw_f 的導數,可以如下的方法計算,在展示計算的方法之前,這裡先對之前的式子進行重寫,將 w_f 包含進來,

f = f(m{x}, m{w_f}) \ g = g(f) \ y = k(g)\ cost = criterion(y, y)

要計算 frac{d(cost)}{d(m{w_f})} ,可以通過計算, frac{d(f)}{d(m{w_f})} 	imes frac{d(g)}{d(f)} 	imes frac{d(y)}{d{(g)}} 	imes frac{d(cost)}{y} ,這就是求導鏈式法則。

再舉個例子,如果用 m{w_g} 來表示函數 g 當中的可變變數,現在要計算 costm{w_g} 的導數,可以如下的方法計算,在展示計算的方法之前,這裡在上個例子的基礎上對的式子進行重寫,將 m{w_g} 包含進來,

f = f(m{x}, m{w_f}) \ g = g(f, m{w_g}) \y = k(g)\cost = criterion(y, y)

要計算 frac{d(cost)}{d(m{w_g})} ,可以通過計算,  frac{d(g)}{d(m{w_g})} 	imes frac{d(y)}{d{(g)}} 	imes frac{d(cost)}{y}

這裡的從例子總結, f,g,k 代表了不同的映射,各個映射只需要對自己負責,只需要計算出自己的輸出對輸入的導數是什麼,比如上面兩個例子當中用到的  frac{d(g)}{d(f)} , frac{d(y)}{d{(g)}} ,frac{d(cost)}{y} ,以及輸出到自己的一些可變變數的導數是什麼,比如 frac{d(g)}{d(m{w_g})}frac{d(f)}{d(m{w_f})}

機器學習框架Torch當中的例子

每個方塊內是一個映射,前三個方塊是,從輸入到輸出的三個映射,最後一個方塊是評價輸出與目標值的差距,可以理解為評價當前輸入到輸出映射的好壞。

比如要實現如上的映射,每個方塊內是一個映射,前三個方塊是,從輸入到輸出的三個映射,最後一個方塊是評價輸出與目標值的差距。

這裡的輸入是一個二維向量, m{x} = [x1, x2] = [2, 3]

  1. 第一個映射: f=f(m{x}) = w1 	imes x1 + w2 	imes x2 + b = 1 	imes 2 + 5 	imes 3 + -15 = 2 ,可以用Torch代碼當中的nn.Linear表示,

require nn;l1 = nn.Linear(2, 1)l1.weight[1][1] = 1l1.weight[1][2] = 5l1.bias[1] = -15a = torch.Tensor(2)a[1] = 2a[2] = 3res = l1:forward(a) --res = 2 * 1 + 3 * 5 + -15 = 2, print(res)--will print --2--[torch.DoubleTensor of size 1]

2. 第二個映射: g = g(f) = frac{1}{1+e^{-f}} = frac{1}{1+e^{-2}} = 0.8808 ,這個過程可以用如下代碼表示:

require nn;l2 = nn.Sigmoid()b = torch.Tensor(1)b[1] = 2res = l2:forward(b)print(res)--will print--0.8808

3. 第三個映射: k=k(g)=w 	imes g = 20 	imes 0.8808 = 17.6160 ,代碼表示如下,

require nn;l3 = nn.Mul()l3.weight[1] = 20c = torch.Tensor(1)c[1] = 0.8808res = l3:forward(c)print(res)--will print--17.6160

最後一個評價映射的好壞的評價標準: cost = criterion(y, y) = (y-y)^2 = (10 - 17.6)^2=57.76 。用代碼如下表示:

require nn;crit = nn.MSECriterion()targets = torch.Tensor(1)targets[1] = 10res = torch.Tensor(1)res[1] = 17.6cost = crit:forward(res, targets)print(cost) --cost = (10 - 17.6) * (10 - 17.6) = 57.76--will print--57.76

這裡分別介紹了三個映射,最終的映射是將這三個映射串聯而成。這裡需要用到nn.Sequential(),完整的代碼如下,注意只有最下面幾行從nn.Sequential()開始的代碼有些不同,這些代碼是將之前的映射組裝起來。

require nn;l1 = nn.Linear(2, 1)l1.weight[1][1] = 1l1.weight[1][2] = 5l1.bias[1] = -15a = torch.Tensor(2)a[1] = 2a[2] = 3res = l1:forward(a) --res = 2 * 1 + 3 * 5 + -15 = 2, print(res)--will print ----2----[torch.DoubleTensor of size 1]l2 = nn.Sigmoid()b = torch.Tensor(1)b[1] = 2res = l2:forward(b)print(res)--will print----0.8808l3 = nn.Mul()l3.weight[1] = 20c = torch.Tensor(1)c[1] = 0.8808res = l3:forward(c)print(res)--will print----17.6160net = nn.Sequential()net:add(l1)net:add(l2)net:add(l3)res = net:forward(a)print(res)

設計深度學習的網路就是如此,此不同的小映射串聯成各種各樣的形式,有的還有可能是並聯,流行的網路有可能有成百個小映射堆疊而成,不管有多少小映射堆疊,只要每個映射能夠,只需要計算出自己的輸出對輸入的導數是什麼,以及輸出到自己的一些可變變數的導數是什麼,無論有多少個映射,都可以利用求導鏈式法則對其進行優化。Torch當中,這兩個部分的計算寫在了各個映射的backward方法當中,如果是包含多個映射的net=nn.Sequential(),在net調用backward方法時,net將分別調用內部映射的各個backward方法,調用的過程就是應用求導鏈式法則的過程。

所謂深度學習煉丹和堆積木

所謂深度學習煉丹就是設計或者說創造深度學習網路的過程,嘗試在網路當中添加不同的映射,這裡的映射也可以稱之為模塊之類的,創造不同的網路,利用梯度下降的方法對網路進行優化,觀察哪種結構可以取得最好的效果,就像煉丹一樣,用不同的原材料進行組合,看哪一種組合可以得到意想不到的效果,一次大會上有大牛也提到煉丹這個詞,煉丹一詞就在深度學習領域流行開了。

創造網路過程,也有點像堆積木,這裡的小映射就是積木,不同的堆疊方式創造不同的網路結構,也可以自行創造積木,也可以通過組合原有的積木組成新的積木。學習深度學習的過程就像是堆積木的過程,堆的經驗多了,就知道什麼情況下,怎麼設計網路會有效果。

馬上用Torch,或者Pytorch開始堆積木遊戲,或者煉丹之旅!

參考資料

  1. banana:梯度下降方法與求導
  2. [Video]Lecture 4 | Introduction to Neural Networks, Backpropagation and Neural Networks
  3. [Slides]Lecture 4: Backpropagation and Neural Networks
  4. Torch | Developer Documentation, Define your own layer

推薦閱讀:

放養的深度學習-淺談自編碼器
譯文:如何為機器學習索引,切片,調整 NumPy 數組
使用tensorflow構建卷積神經網路(CNN)
吳恩達機器學習第六周課後感

TAG:深度學習DeepLearning | 神經網路 | 機器學習 |