當(dāng)我們在學(xué)習(xí)或者工作中使用tensorflow,pytorch之類去復(fù)現(xiàn)網(wǎng)絡(luò)的時候,一般沒人去單獨(dú)去寫backward,因?yàn)檫@些優(yōu)秀的框架已經(jīng)給我們打好了根基,它們的一句話即可自動的幫我們?nèi)シ聪騻鞑ィ覀冐?fù)責(zé)寫好forward就可。
我聽到的更多的抱怨是來自實(shí)踐的團(tuán)隊(duì),“如果我們工作中根本不用去寫反向傳播,為什么要去學(xué)習(xí)如何自己寫呢”,反方的觀點(diǎn)則是諸如 “這些知識懂了的話理解神經(jīng)網(wǎng)絡(luò)會更深”,“你可能有機(jī)會去接觸神經(jīng)網(wǎng)絡(luò)的更底層”等等,這些話確實(shí)很蒼白無力。
但其實(shí)我們應(yīng)該去寫寫并懂得反向傳播的原因是因?yàn)?strong>它是一個有漏洞的方法。
簡單來說,它很容易陷入學(xué)習(xí)過程中的一些陷阱,這些陷阱就發(fā)生在你手到擒來的寫了個自己覺得完美無缺的網(wǎng)絡(luò),前向反向都如你意的過程中。

-
梯度消失(vanishing gradients)
現(xiàn)實(shí)中一個常用的做法就是用sigmoid或者tanh來跟在全連接層的后邊做一個非線性的激活。這個技巧太過普通以至于往往人們認(rèn)識不到學(xué)習(xí)過程中l(wèi)oss停留在一個值拒絕下降的原因就是因?yàn)樗麄冊跈?quán)重初始化的時候太過隨意,導(dǎo)致反向傳播不再起作用。
舉個例子:一個簡單的前向傳播并用sigmoid激活
z = 1 / (1 + np.exp(-np.dot(W, x))) # 前向傳播 dx = np.dot(W.T, z * (1 - z)) # 反向傳播:計算x的梯度 dW = np.outer(z * (1 - z), x) # 反向傳播:計算W的梯度如果你將矩陣W的初始值設(shè)的過大,那么矩陣相乘wx+b之后將會得到一個很大范圍的值(比如:-500 到 500),這個很大的值將使得向量z的值要么等于0要么等于1
那么接下來做反向傳播求導(dǎo)的時候無論對x還是對W來說,z(1-z)*將會都等于0,也就是說x和W的梯度將都是0,那么根據(jù)鏈?zhǔn)椒▌t,之后的反向傳播的也都是0,整個網(wǎng)絡(luò)的參數(shù)將不再更新。

另外一個比較有意思的事情就是sigmoid的梯度:sigmoid x (1 - sigmoid)最大值為0.25(z=0.5)。這就意味著每次反向傳播經(jīng)過sigmoid一次,它的大小將至少減少為原來的1/4,那么特別是達(dá)到網(wǎng)絡(luò)的前幾層的時候,反向傳播的梯度將會越來越小。如果你恰巧又用了SGD,那么整個網(wǎng)絡(luò)的訓(xùn)練將會更加的漫長。
-
神經(jīng)元的死亡
另外一個比較有意思的是ReLU,它將小于0的值都過濾為0。

舉個例子:
z = np.maximum(0, np.dot(W,x)) #前向傳播
dW = np.outer(z > 0, x) # 反向傳播:計算W的梯度

你可以看到當(dāng)如果有神經(jīng)元在前向傳播后(z的值中)被ReLU激活后為0值時,它的權(quán)重的梯度將也為0,這時將會導(dǎo)致出現(xiàn)神經(jīng)元的死亡的現(xiàn)象,這些神經(jīng)元將永不再更新。出現(xiàn)這種情況的原因有兩個,1個是ReLU神經(jīng)元的權(quán)重被初始化的不夠好,另一個是神經(jīng)元的權(quán)重在訓(xùn)練的過程中被大幅更新,這些神經(jīng)元將永久的處于死亡狀態(tài)。它就像永久死亡的大腦的細(xì)胞。如果你在用ReLU,那么有時你就會發(fā)現(xiàn)在訓(xùn)練時大約有40%左右的神經(jīng)元已經(jīng)是0處于死亡的狀態(tài)。
那么如果你懂得了反向傳播的這個問題,你就可以很小心的去對待死亡ReLU的問題,對待這些對你訓(xùn)練集的所有數(shù)據(jù)都輸出為0,永久的死去了神經(jīng)元。神經(jīng)元也會在訓(xùn)練的中途死掉,比如你設(shè)置了比較大的學(xué)習(xí)率。
-
梯度爆炸(exploding gradients)
假設(shè)有一個4層深的網(wǎng)絡(luò)(三個隱藏層),并且每一層只有一個神經(jīng)元,σ為sigmoid函數(shù)

那么來個反向傳播的話


之后不斷的相乘的結(jié)果就是網(wǎng)絡(luò)的前層的梯度成指數(shù)級的增長。再拿這個超級大的梯度來更新我們的w的話,就導(dǎo)致網(wǎng)絡(luò)的不穩(wěn)定,在極端情況下,權(quán)重的值會變得特別大,以至于結(jié)果溢出,出現(xiàn)NAN值。
最后 反向傳播并不是一個健壯的方法,如果你因?yàn)椤癟ensorflow或者Pytorch已經(jīng)自動的幫我們實(shí)現(xiàn)了”就忽視它,那么你面對他帶來的問題的時候講無所適從,對于調(diào)試一個網(wǎng)絡(luò)來說也會變得困難。慶幸的是反向傳播理論并不是那么的不食人間煙火,只要你認(rèn)真的關(guān)注并研究幾篇文章,那么你很快會掌握它的。
