深度學習與求導鏈式法則
來自專欄機器學習與數學50 人贊了文章
前言
最近幾年深度學習席捲了機器學習多個領域,計算機視覺,自然語言處理,推薦系統等等,成為各個領域當中的最佳方法。深度學習或者說神經網路當中最重要的一個要素是反向傳播演算法(Back propagation)。反向傳播演算法與數學當中求導鏈式法則有非常密切的關係,當前的流行的網格結構,無不遵循這個法則,比如計算視覺當中的LeNet、AlexNet、GoogLeNet、VGG、ResNet,還有其它的各種網路。這個法則在之前的文章梯度下降方法與求導有一些涉及,這裡專門再次提前,是為了更清楚的表明它的工作方法。
深度學習與求導鏈式法則的關係
從之前的文章梯度下降方法與求導,我們知道對於可以求導的映射,可以利用對映射當中各個可變參數進行求導,利用梯度下降的方法,慢慢使映射當中的各個可變參數接近想要的值,使 更小。深度學習將多種映射疊加在一起,對輸入進行多個映射處理,理論上,多個映射疊加的表達能力將比單一的映射高,對其進行優化之後可以使 變得更加得小。求導鏈式法則是用來幫助 對各個映射當中的可變參數進行求導的法則。
求導鏈式法則
假設 的計算方式如下,輸入是 ,目標值是
如果你要計算 ,這裡的 可以是一個數字,也可以是一個向量,或者是一個矩陣。你可以通過計算 來獲取想要的導數 ,在機器學習當中,這裡的三個函數, 代表了不同的映射, 也理解成一種映射,只不過這裡的輸入將目標值 加入進來了。這裡的 代表的是輸入的數據,但是對輸入數值求導的意義不大,因為我們不能對數據進行改變使我們的目標 變得更小,實際情況是要對各個映射當中包含的可變變數進行求導。
舉個例子如果用 來表示函數 當中的可變變數,現在要計算 對 的導數,可以如下的方法計算,在展示計算的方法之前,這裡先對之前的式子進行重寫,將 包含進來,
要計算 ,可以通過計算, ,這就是求導鏈式法則。
再舉個例子,如果用 來表示函數 當中的可變變數,現在要計算 對 的導數,可以如下的方法計算,在展示計算的方法之前,這裡在上個例子的基礎上對的式子進行重寫,將 包含進來,
要計算 ,可以通過計算, 。
這裡的從例子總結, 代表了不同的映射,各個映射只需要對自己負責,只需要計算出自己的輸出對輸入的導數是什麼,比如上面兩個例子當中用到的 ,以及輸出到自己的一些可變變數的導數是什麼,比如 , 。
機器學習框架Torch當中的例子
比如要實現如上的映射,每個方塊內是一個映射,前三個方塊是,從輸入到輸出的三個映射,最後一個方塊是評價輸出與目標值的差距。
這裡的輸入是一個二維向量,
- 第一個映射: ,可以用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. 第二個映射: ,這個過程可以用如下代碼表示:
require nn;l2 = nn.Sigmoid()b = torch.Tensor(1)b[1] = 2res = l2:forward(b)print(res)--will print--0.8808
3. 第三個映射: ,代碼表示如下,
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
最後一個評價映射的好壞的評價標準: 。用代碼如下表示:
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開始堆積木遊戲,或者煉丹之旅!
參考資料
- banana:梯度下降方法與求導
- [Video]Lecture 4 | Introduction to Neural Networks, Backpropagation and Neural Networks
- [Slides]Lecture 4: Backpropagation and Neural Networks
- Torch | Developer Documentation, Define your own layer
推薦閱讀:
※放養的深度學習-淺談自編碼器
※譯文:如何為機器學習索引,切片,調整 NumPy 數組
※使用tensorflow構建卷積神經網路(CNN)
※吳恩達機器學習第六周課後感
TAG:深度學習DeepLearning | 神經網路 | 機器學習 |