Table of Contents
Tips for Deep Learning-如果Training data 的效果不好怎麼辦?
今日的課程來自於: https://youtu.be/5BJDJd-dzzg
在作training data & testing data 時,我們最在意的就是模型的效果好不好?
如果效果不好,就需要找出問題解決。今天要討論的是當training data的效果不好該如何調整?
方法有兩種:
- New activation function
- Adaptive learning rate
New activation function
如果你今天的training結果不好,很有可能是因為你的network架構設計得不好。舉例來說,可能你用的activation function是對training比較不利的,那你就嘗試著換一些新的activation function,也許可以帶來比較好的結果。
1980年代使用的activation function 是sigmoid function。 如果我們用sigmoid function ,你會發現deeper does not imply better。 下圖是training data 的accuracy ,在第七層之後accuracy 開始往下掉了,這並不是overfitting (overfitting 是training data效果好,但是testing data效果不好) ,原因是因為Vanishing Gradient(梯度消失)
Vanishing Gradient(梯度消失)
Vanishing Gradient(梯度消失)就是當network越深的時候,在靠近input的地方,這些參數的gradient(即對最後loss function的微分)是比較小的;而靠近output的地方,他對loss 的微分值會是比較大的
因此當設定同樣的learing rate的時候,靠近input的地方,他參數的update是很慢的;而靠近output的地方,他參數的update是比較快的
所以在靠近input的地方,參數幾乎還是random的時候,output就已經根據這些random的結果找到了一個local minimal,然後就收斂了
要如何解釋這件事呢? 假設我們在參數作小小的變化,看看隊cost的影響有多大;我們在某一個參數後加上Δw,即使Δw的值很大,但是經過一個sigmoid function 就會被縮小一次,所以newwork越深,對cost的影響越小
要如何解決這個問題呢? 其實改一下activation function就可以解決了
ReLU
現在較常使用的activation function叫做Rectified Linear Unit (ReLU;整體線性單元函數;修正線性單元);該函數的圖形如下,z 為 input,a 為output,如果 input > 0 then output=input ;如果 input < 0 then output=0
ReLU 2的優點如下:
- 跟sigmoid 相比,ReLU的運算快很多
- ReLU的想法結合了生物上的觀察(Pemgel 的paper)
- 無窮多bias不同的sigmoid function 疊加的結果變成ReLU
- ReLU可以處理Vanishing gradient的問題(最重要的優點)
handle Vanishing gradient problem
下面是ReLU 的neural network,以ReLU作為activation function的neuron,他的output不是等於0,就是等於input
當output=input的時候,這個activation function就是linear的;而output=0的neuron對整個network是沒有任何作用的,因此可以把它們從network中拿掉
拿掉的output=0的neuron如圖下,整個network變成一個瘦長的linear network,linear 的好處是,output=input,不會像sigmoid function一樣使input 產生的影響力遞減
Q1 : 我們之所以使用deep learning,就是因為想要一個non-linear、比較複雜的 function而使用ReLU不就會讓它變成一個linear function嗎?這樣得到的function不是會變得很弱嗎?
A1: 其實使用ReLU之後的network整體來說還是non-linear的,如果你對input有小小的改變,不改變neuron的operation region的話,那network就是一個linear function;但是,如果你對input作比較大network整體上就變成了non-linear function
Q2: 我們對loss function做gradient descent,要求neural network是可以做微分的,但ReLU是一個分段函數,它是不能微分的(至少在z=0這個點是不可微的),那該怎麼辦呢?
A2: 在實際操作上,當region的範圍處於z>0時,微分值gradient就是1;當region的範圍處於z<0時,微分值gradient就是0;當z為0時,就不要管它,相當於把它從network裡面拿掉
ReLU-variant
其實ReLU還存在一定的問題,比如當input<0的時候,output=0,此時微分值gradient也為0,你就沒有辦法去update參數了,所以我們應該讓input<0的時候,微分後還能有一點點的值,比如令a=0.01z,這個東西就叫做Leaky ReLU
既然a可以等於0.01z,那這個z的係數可不可以是0.07、0.08之類呢?所以就有人提出了Parametric ReLU,也就是令a= αz,其中並不是固定的值,而是network的一個參數,它可以通過trainingdata學出來,甚至每個neuron都可以有不同的值
這個時候又有人想,為什麼一定要是ReLU這樣子呢,activation function可不可以有別的樣子呢?所以後來有了一個更進階的想法,叫做Maxout network
Maxout
Maxout讓network自動去學習他的activation function,那Maxout network就可以自動學出ReLU,也可以學出其他的activation function,這一切都是由training data 來決定的
假設現在有input x1,x2,它們乘上幾組不同的weight分別得到5,7,-1,1,這些值本來是不同neuron的input,他們要通過activation function 變成neuron的output;但在Maxout network裡,我們事先決定好將某幾個”neuron”的input分成一個group,比如5,7分為一個group,然後在這個group裡選取一個最大值
這個過程,就好像在一個layer 上做Max pooling 一樣,他原來的network不同之處在於,他把原來幾個neuron的input按一定規則組成了一個group,然後並沒有使他們通過activation function,而是選取其中的最大值當作這幾個”neuron”的output
當然,實際上原來的”neuron”早就已經不存在了,這幾個被合併的”neuron”應當被看作是一個新的neuron,這個新的neuron的input是原來幾個”neuron”的input組成的vector,output則取input最大值,並非由activation function產生
在實際操作上,幾個element被分為一個group這件事情是由你自己決定的,他就是network structure 裡一個需要被調的參數,不一定要跟上圖一樣兩個分為一組
property
Maxout可以實現任何piecewise linear convex actvation function(分段線性凸激活函數),其中這個activation function 被分為多少段,取決於你把多少個element z 放到一個group裡,下圖分別是2個element一組和3個element一組的activation function的不同形狀
How to train Maxout
接下來我們要面對的是,怎麼去train一個Maxout network,如何解決Max不能微分的問題
假設在下面的Maxout network中,紅框圈起來的部分為每個neuron的output
其實Max operation 就是linear 的operation ,只是他緊接在前面這個group裡的某一個element上,因此我們可以把那些並沒有被Max連接到的element通通拿掉,從而得到一個比較細長的Linear network
實際上我們真正訓練的並不是一個含有max函數的network,而是一個化簡後如下圖的linear nerwork;當我們還沒有真正開始訓練模型的時候,此時這個network含有max函數無法微分,但是只要真的丟進去了一筆data,network就會馬上根據這筆data確定具體的形狀,此時max函數的問題已經被實際數據給解決了,所以我們完全可以根據這筆training data使用Backpropagation的方法去訓練被network留下來的參數
所以我們擔心max函數無法微分,他只是理論上的問題;在具體的實踐上,我們完全可以根據data把max 函數轉化為具體的函數,再對這個轉化的thiner linear network進行微分
沒被train的element怎麼辦?(但在實作上,他不是一個問題)
每個linear network的structure 都是由input的那一筆data來決定的,當你input不同data的時候,得到的nerwork structure 是不同的,留在network裡面的參數也是不同的,由於我們有很多很多比training data,所以network的structure再訓練中不斷的變換,所以最後每一個weight都會被train到
所以,我們回到Max Pooling的問題上來,由於Max Pooling跟Maxout是一模一樣的operation,既然如何訓練Maxout的問題可以被解決,那訓練Max Pooling又有什麼困難呢?
Max Pooling有關max函數的微分問題採用跟Maxout一樣的方案即可解決,至此我們已經解決了CNN部分的第一個問題
Adaptive learning rate
第二個能夠解決training data效果不好的就是: adaptive learning rate,這個部分主要講述的是關於recipe of deep learning 中adaptive learning rate的一些理論
review-adagrad
我們之前已經了解adagrad的做法,讓每一個參數都有不同的learning rate
Adagrad 的精神是,假設我們考慮兩個參數w1,w2,如果在w1這個方向上,平常的gradient都比較小,那他是比較平坦的,於是就給他大的learning rate;反過來說,在w2這個方向上,平常的gradient都比較大,那他是比較陡峭的,就給他比較小的learning rate
但是實際上遇到的問題,遠比adagrad所能解決的問題要來的複雜,我們之前做Linear Regression的時候,我們做optimization的對象,也就是loss function,它是convex的形狀;但實際上我們在做deep learning的時候,這個loss function可以是任何形狀
RMSProp
learning rate
loss function可以是任何形狀,對convex loss function來說,在每個方向上它會一直保持平坦或陡峭的狀態,所以你只需要針對平坦的情況設置較大的learning rate,對陡峭的情況設置較小的learning rate即可
但是在下圖所示的情況中,即使是在同一個方向上(如w1方向),loss function也有可能一會而平坦一會兒陡峭,所以你要隨時根據gradient的大小來快速地調整learning rate
所以真正要處理deep learning的問題,用Adagrad可能是不夠的,你需要更dynamic的調整learning rate的方法,所以產生了Adagrad的進階版 — — RMSProp
How to do RMSProp
RMSProp的做法如下:
我們的learning rate依舊設置為一個固定的值 除掉一個變化的σ值 ,這個σ等於上一個σ和當前梯度的加權方均根(特別的是,在第一個時間點, σ^0就是第一個算出來的gradient值g⁰),即:
這裡的σ值是可以自由調整的,RMSProp跟Adagrad不同之處在於,Adagrad的分母是對過程中所有的gradient取平方和開根號,也就是說Adagrad考慮的是整個過程平均的gradient信息;而RMSProp雖然也是對所有的gradient進行平方和開根號,但是它用一個σ來調整對不同gradient的使用程度,比如你
把α的值設的小一點,意思就是你更傾向於相信新的gradient所告訴你的error surface的平滑或陡峭程度,而比較無視於舊的gradient所提供給你的information
所以當你坐RMSProp的時候一樣是在算gradient的root mean square,但是你可以給現在已經看到的gradient 比較大的weight,給過去看到的gradient比較小的weight,來調整對gradient信息的使用程度
Momentum
optimization-local minima?
除了learning rate的問題之外,大家最怕的就是卡在local minimum、saddle point或是plateau的地方,很多人都會擔心deep learning 這麼複雜的model可能非常容易被卡住了
其實Yann LeCun在07年的時候,就提出一個蠻特別的說法,他說你不要太擔心local minima的問題,因為一旦出現local minima,它就必須在每一個dimension都是下圖中這種山谷的低谷形狀,假設
山谷的低谷出現的概率為p,由於我們的network有非常非常多的參數,這裡假設有1000個參數,每一個參數都要位於山谷的低谷之處,這件事發生的機率為p¹⁰⁰⁰,當你的network越複雜,參數越多,這件事發生的概率就越低
所以在一個很大的neural network裡面,其實並沒有那麼多的local minima,搞不好它看起來其實是很平滑的,所以當你走到一個你覺得是local minima的地方被卡住了,那它八成就是global minima,或
者是很接近global minima的地方
Where is Momentum from
假設我們用物理的方法來看找極值。假設有一個球從左上滾下來,當他滾到plateau的地方、local minima的地方,但是由於慣性他還會持續往前走一段路,假設前方有個坡,這個球就很有可能翻過山坡,走到比local minima 還要好的地方
所以我們要做的就是把慣性加到gradient descent裡面,這件事情就叫做Momentum
How to do Momentum
當我們在gradient descent 裡加上Momentum的時候,每一次update的方向,不再只考慮gradient的方向,還要考慮上次update的方向,那這裡我們就用一個變量去記錄前一個時間點update的方向
隨機選一個初始值θ⁰,初始化v⁰,接下來計算θ⁰處的gradient,然後我們要移動的方向是由前一個時間點的移動方向v⁰和gradient的反方向來決定的,即
λ也是手動調整參數。接下來我們第二個時間點要走的方向v²,它是由第一個時間點移動的方向v¹和gradient的反方向 ▽L(θ¹)共同決定的; λ_v是圖中的綠色虛線,它代表由於上一次的慣性想要繼續走的方向;η▽L(θ) 是
圖中的紅色虛線,它代表這次gradient告訴你所要移動的方向;它們的失量和就是這一次真實移動的方向,為藍色實線
gradient告訴我們走紅色虛線的方向,慣性告訴我們走綠色虛線的方向,合起來就是走藍色的方向
我們還可以用另一種方法來理解Momentum這件事,其實你在每一個時間點移動的步伐,包括大小和方向,就是過去所有gradient的加權和
具體推導如下圖所示,第一個時間點移動的步伐v¹是θ⁰處的gradient加權,第二個時間點移動的步伐v²是θ⁰和θ¹處的gradient加權和…以此類推;由於λ的值小於1,因此該加權意味著越是之前的gradient,它的權重就越小,也就是說,你更在意的是現在的gradient,但是過去的所有gradient也要對你現在
update的方向有一定程度的影響力,這就是Momentum
Adam
其實RMSProp 加上Momentum,就可以得到Adam
根據下面的paper來快速瞄素一下Adam的algorithm:
- 先初始化 m_0 = 0 , m_0就是Momentum中,前一個時間點的movement
- 再初始化 v_0=0 ,v_0就是RMSProp裡計算gradient的root mean square 的 σ
- 最後初始化t=0,t用來表示時間點
- 先算出gradient g_t
5. 再根據過去要走的方向m_(t-1)和gradient g_t,算出現在要走的方向m_t — Momentum
6. 然後根據前一個時間點v_(t-1) 和gradient g_t的平方,算一下放在分母的v_t __RMSProp
7. 接下來做了一個原來RMSProp和Momentum裡沒有的東西,就是bias correction ,它使 m_t 和 v_t 都除上一個值,這個值本來比較小,然後越來越接近1
8. 最後做update,把 Momentum建議你的方向 m_t 乘上learning rate α,再除掉RMSProp normalize 後建議的learning rate 分母,然後得到update的方向
好了,今天講training data效果不好的解決方法,下一篇就是testing data效果不好的解決方法