在上一節(jié)的課程我們介紹了循環(huán)神經(jīng)網(wǎng)絡的基本結構,同時這樣的循環(huán)結構也會給優(yōu)化帶來一定的困難,本文主要介紹兩種較為簡單的方式來緩解RNN的優(yōu)化問題:
· 正交初始化
· 激活函數(shù)的選擇
BPTT的兩個關鍵點
我們可以上圖寫出前向傳播的公式,使用f作為隱藏單元的激活函數(shù),g作為輸出單元的激活函數(shù),為了簡化問題,不使用偏置,也不在單元中使用閾值,一個圓圈只代表一個神經(jīng)元,以
為例:
其中
。在反向傳播時,我們就不能采取原來逐層反向傳播的方法去更新參數(shù),因為數(shù)據(jù)在使用時有著不同的進入順序,同時每個時間步共享參數(shù),我們對單獨時間步的更新需要考慮整個序列上的信息。我們稱這樣的方式為沿時間的反向傳播(BP through time),但真正本質的機制只有兩個,參數(shù)共享和循環(huán)結構。
要理解這一點并不難,我們只需要考慮矩陣乘法,參數(shù)未被共享的情況下,從形式上來看,矩陣參數(shù)更新之間互不干擾,我們可以很方便對每個參數(shù)進行更新,但如果參數(shù)共享,那么矩陣的元素需要綁定在一起更新,梯度的更新變?yōu)榱藚?shù)共享的區(qū)域梯度之和。因為參數(shù)共享的區(qū)域是沿著時間共享,所以求和也需要按照時間。(在同樣具備參數(shù)共享的CNN的反向傳播中,求和是按照空間)
我們對參數(shù)V的更新,就要考慮不同時間步上的參數(shù)共享,我們可以把前向傳播寫成矩陣的形式:
就有:
在此基礎上,我們對于參數(shù)U進行同樣的前向傳播操作:
我們會發(fā)現(xiàn),當前時間步的變量
會包含前一步的變量
,此時我們選擇對U或者W求梯度,就不能忽略掉前一步的變量,因為前一步的變量中也包含了參數(shù)U和W,那么我們在對U進行更新時,就需要將前面的時間步遞歸展開:
因為
:
同理,我們對W做參數(shù)更新,也是同樣的結構:
我們可以清晰的看到,權重共享機制使得我們需要對每個時間步梯度求和,循環(huán)結構使得我們需要遞歸地處理梯度,根據(jù)我們的展開式,每一個
都會產(chǎn)生一個或多個W,比如:
當我們鏈的越來越長的時候,整條鏈出現(xiàn)了W的連乘,這正是循環(huán)結構帶來的。
在普通的神經(jīng)網(wǎng)絡中,梯度消失往往來源于激活函數(shù)和層與層協(xié)調更新,但在RNN中,梯度消失和爆炸的來源之一就是共享參數(shù)W的連乘。在RNN中,循環(huán)層如果沒有梯度的流動,那么就表示序列的信息并沒有傳達到下去,我們所謂的記憶單元就會喪失記憶能力,RNN相比傳統(tǒng)n-gram模型的優(yōu)勢也就不復存在。
從理論上來說,我們希望盡可能保持W值保持在一定范圍內,使得網(wǎng)絡可以被有效的訓練。
正交初始化
正交初始化的思路很簡單,就是利用了正交矩陣的性質,它的轉置矩陣就是它的逆矩陣,有:
使得矩陣的連乘不會放大或者縮小W本身的值。
我們也可以從另外一個角度來理解,如果我們對矩陣做特征值分解,分解為對角矩陣和正交矩陣的乘積:
矩陣的連乘就會變成:
矩陣的連乘就會變?yōu)槠涮卣髦档倪B乘,所以:
· 如果特征值的絕對值都小于1,那么參數(shù)梯度會越變越小。
· 如果特征值近似都等于1,那么參數(shù)梯度就可以保持正常范圍。
· 如果特征值的絕對值都大于1,那么參數(shù)梯度會越來越大。
正交矩陣的特征值要么是1、要么是-1,雖然我們無法保證參數(shù)矩陣W永遠都是這樣的形式,但至少可以在初始化上做到這一點。
激活函數(shù)
我們很早就曾講過激活函數(shù)的重要性,sigmoid函數(shù)具有非中心化和廣泛的飽和性,ReLU以及它的各種變體可以很好的解決這個問題,但是在循環(huán)神經(jīng)網(wǎng)絡中,我們需要考慮參數(shù)的特征值,ReLU在其右端是一個線性函數(shù),雖然它的梯度恒定為1,但函數(shù)值卻可以無限的增長。
傳統(tǒng)的ReLU在RNN中則可能會帶來梯度爆炸的問題,但解決梯度爆炸我們一般會采用截斷(clipping)的方式,也就是如果梯度大于某值,就令其等于某值。另外,我們還可以在采用tanh激活函數(shù),因為它的范圍在[-1,1],更好的適應參數(shù)連乘帶來的梯度爆炸,卻也在一定程度上無法避免梯度消失。
我們需要在這兩者之間做trade-off,因為我們既不想讓激活函數(shù)對權重求導的部分變得太大或者太小,也不希望函數(shù)本身的值變得太大或者太小。