人工神經(jīng)網(wǎng)絡(luò)的能力大家都是有目共睹的,在機器學(xué)習(xí)領(lǐng)域可是占據(jù)了一定的地位。這點應(yīng)該毋庸置疑。它可以建模任意復(fù)雜的函數(shù)。雖然能力大了有時候也不是好事,因為容易過擬合。但能力小了,就沒辦法建模復(fù)雜的函數(shù),也就是給你數(shù)據(jù),你也消化不了。關(guān)于神經(jīng)網(wǎng)絡(luò)的介紹,這里就不說了,發(fā)展了那么久,介紹神經(jīng)網(wǎng)絡(luò)的書籍或者資料太多了。還記得我們要干嘛嗎?我們想要知道訓(xùn)練神經(jīng)網(wǎng)絡(luò)的Tricks!眾所周知(如果你不知道,就先不要往下看了),訓(xùn)練神經(jīng)網(wǎng)絡(luò)的方法就是經(jīng)典的BP算法!理解BP算法的工作原理很重要,因為在實踐過程中,你遇到的一些現(xiàn)象是可以通過分析BP算法的收斂性獲得的。同時,BP算法也存在弱點和一些不好的特性,如何能對這些不好的特性退而避之對模型的成功就非常重要。
一、介紹 BP算法是訓(xùn)練神經(jīng)網(wǎng)絡(luò)的一個非常流行的算法,因為它不僅概念上簡單,而且實現(xiàn)也簡單,當(dāng)然了,它也是有效的。不過,對它的使用,更像一種藝術(shù),而不僅是科學(xué)。設(shè)計或者使用BP算法訓(xùn)練一個神經(jīng)網(wǎng)絡(luò)看似簡單,同時做了很多看似簡單的選擇,例如神經(jīng)元節(jié)點的類型、數(shù)量、層數(shù)、學(xué)習(xí)率、訓(xùn)練和測試集等等。實際上,對他們的選擇非常關(guān)鍵!不過,也很遺憾的告訴你,現(xiàn)實中并不存在關(guān)于如何選擇他們的有力指南。因為這是一個非常大的問題,而且和具體的任務(wù)和數(shù)據(jù)有關(guān)。不過,也很高興的告訴你,實際上,還是存在很多啟發(fā)式和潛在的理論可以指導(dǎo)實踐者對他們做出更好的選擇的。下面我們先介紹下有關(guān)的基礎(chǔ),再對其中的Tricks娓娓道來。
二、學(xué)習(xí)和泛化 機器學(xué)習(xí)的方法非常多,但大多數(shù)成功的方法都可以將其統(tǒng)一為基于梯度的學(xué)習(xí)方法。學(xué)習(xí)框架如下圖所示。我們的模型實際上就是學(xué)習(xí)一個從輸入到輸出的函數(shù),這里表示為M(Zp, W),其中輸入就是Zp,表示第p個輸入樣本。W就是模型可以學(xué)習(xí)的參數(shù)。在神經(jīng)網(wǎng)絡(luò)里面就是兩層之間的連接權(quán)重了。那通過什么原則來調(diào)整模型或者學(xué)習(xí)參數(shù)W呢?我們是希望模型能學(xué)習(xí)我們的訓(xùn)練數(shù)據(jù),也就是擬合我們的訓(xùn)練數(shù)據(jù),所以我們就需要一個衡量這種擬合度的度量。也就是代價函數(shù)了,這里表示為Ep=C(Dp, M(Zp, W)),它度量的就是當(dāng)?shù)趐的樣本輸入網(wǎng)絡(luò)的時候,網(wǎng)絡(luò)的輸出M(Zp, W)和我們期待的“正確”輸出Dp(也就是我們平時說的訓(xùn)練樣本的標(biāo)簽了)的差異。假設(shè)我們的訓(xùn)練集包含P個樣本{(Z1, D1),…, (ZP, DP)},我們在訓(xùn)練集中的代價函數(shù)就是在整個樣本集中取平均。
機器學(xué)習(xí)的問題總的來說,就是調(diào)整模型參數(shù)W使得代價函數(shù)或者模型擬合數(shù)據(jù)的誤差最小。實際上,大家是不太關(guān)心模型在訓(xùn)練集上的誤差的,更關(guān)心的是模型在這個任務(wù)上的誤差,因為這個模型是要在實際中使用的,換句話說,我們訓(xùn)練好的模型是為了以后能正確地預(yù)測新的樣本。這個性能通過一個和訓(xùn)練集不重疊的測試集來估計。最常用的代價函數(shù)就是均方函數(shù)了:
那如何才能調(diào)整模型的參數(shù)W讓這個代價函數(shù)最小呢?這就是這一章我們要討論的。這里面涉及到一些策略,不過,這些策略必須結(jié)合最大化網(wǎng)絡(luò)的泛化能力一起使用,這樣才可以讓學(xué)習(xí)的模型能更好的預(yù)測未知的樣本。 為了更好的理解泛化,我們來分析下BP的工作原理。實際上,對訓(xùn)練樣本的采集是有噪聲的,所以例如你采集了很多個集合的樣本,可以認(rèn)為因為在不同的采樣點進(jìn)行采樣,所以不同集合的樣本存在噪聲,從而導(dǎo)致差別。因此,每個集合在用以訓(xùn)練網(wǎng)絡(luò)時,都會讓網(wǎng)絡(luò)傾向于自己,從而學(xué)的網(wǎng)絡(luò)和其他集合的不太一樣。 存在很多分析在訓(xùn)練集上的最小化誤差的理論,叫經(jīng)驗風(fēng)險最小化。這里面有一些理論將泛化誤差分解為兩部分:bias and variance,偏置和方差。偏置衡量的是網(wǎng)絡(luò)的輸出與目標(biāo)輸出的差別,是在所有樣本中的誤差平均。方差衡量的是網(wǎng)絡(luò)的輸出在不同的數(shù)據(jù)中有多大的不同。在網(wǎng)絡(luò)訓(xùn)練開始的時候,偏置很大,因為網(wǎng)絡(luò)還沒學(xué)習(xí),網(wǎng)絡(luò)的輸出和目標(biāo)的輸出一般差別很大。但方差很小,因為數(shù)據(jù)對網(wǎng)絡(luò)的影響還很小。隨著訓(xùn)練的進(jìn)行,偏置會慢慢變小,因為網(wǎng)絡(luò)慢慢的開始學(xué)習(xí)到了潛在的函數(shù),也就是開始擬合數(shù)據(jù)了。然而,如果訓(xùn)練的太久,那么網(wǎng)絡(luò)也會學(xué)習(xí)到特定數(shù)據(jù)庫的噪聲,這就訓(xùn)練過度了。這時候,方差就會變得很大,因為不同的數(shù)據(jù)庫中存在不同的噪聲。然而,當(dāng)偏置和方差的和最小的時候,就是全部誤差最小的時候。 目前存在很多技術(shù)來獲得最小化網(wǎng)絡(luò)的泛化能力,例如常用的early stopping(提前停止訓(xùn)練)、規(guī)則化等。 本章主要是介紹一些在給定代價函數(shù)的時候,如何是執(zhí)行最小化的策略,同時如何保證最小化或者訓(xùn)練的質(zhì)量和速度。不過,值得一提的是,模型、架構(gòu)和代價函數(shù)的選擇對獲取一個泛化性能好的網(wǎng)絡(luò)都是非常關(guān)鍵的。所以,記得,如果你選錯了模型,而且沒有使用合適的模型選擇策略,那就是一個異常牛逼的最小化策略也無力回天。實際上,過訓(xùn)練的存在都讓很多學(xué)者認(rèn)為不那么精確的最小化算法還可能獲得更好的效果。
三、標(biāo)準(zhǔn)BP 本文中的tricks和分析都是在多層前向神經(jīng)網(wǎng)絡(luò)的背景下分析的,不過,大部分這些Tricks都可以應(yīng)用到其他的基于梯度的學(xué)習(xí)算法中。 基于梯度學(xué)習(xí)的多層網(wǎng)絡(luò)最簡單的形式就是迭代一個模塊了,每個模塊就是模型的一層了。這個模塊可以表示為下面的函數(shù):Xn=Fn(Wn, Xn-1)。這就是神經(jīng)網(wǎng)絡(luò)中著名的前向傳播過程。向量Xn-1輸入到這個模塊Fn中,然后輸出向量Xn。這個模型可以表示了一個可調(diào)參數(shù)的向量Wn。堆疊多個,然后這個層的輸出是下一層的輸入就行了。第一層的輸入是X0,就是我們的輸入數(shù)據(jù)Zp。 如果網(wǎng)絡(luò)的誤差Ep對Xn的導(dǎo)數(shù)是可以知道的,那么Ep對Wn和Xn-1的導(dǎo)數(shù)就可以通過反向傳播得到:
式中,?F(Wn,Xn-1)/?W是F關(guān)于W在點(Wn, Xn-1)上的Jacobian雅可比行列式。一個矢量函數(shù)的Jacobian是一個矩陣,矩陣元素是所有的輸出關(guān)于所有的輸入的空間導(dǎo)數(shù)。如果上面的公式從第N層逆序應(yīng)用到第一層,那么代價函數(shù)對網(wǎng)絡(luò)所有的參數(shù)的導(dǎo)數(shù)都可以得到了。這種計算梯度的方式就是BP。 傳統(tǒng)的多層神經(jīng)網(wǎng)絡(luò)是上面這個系統(tǒng)的一個特別例子,這里每個模塊是交替的矩陣乘法(參數(shù))和逐元素sigmoid函數(shù)(神經(jīng)元):
Wn是一個矩陣,列的數(shù)目和Xn-1的維度一致,行數(shù)和Xn的維度一致。F是一個矢量函數(shù),對輸入的每個元素計算sigmoid函數(shù)。Yn是一個向量,每個元素是第n層所有輸入的加權(quán)和。 對上面的式子應(yīng)用鏈?zhǔn)椒▌t,經(jīng)典的BP算法就得到了:
上式可以寫成矩陣的形式:
最簡單的最小化過程就是梯度下降了,對W進(jìn)行迭代的調(diào)整:
其中,η是學(xué)習(xí)率,最簡單的情況就是設(shè)置為一個標(biāo)量常數(shù)值。更多精細(xì)的方法是使用變量,隨著迭代的進(jìn)行發(fā)生改變。還有方法,它是一個對角陣,或者是代價函數(shù)的逆Hessian矩陣的一個估計。也就是二階導(dǎo)。例如Newton 和 Quasi-Newton方法。對學(xué)習(xí)率的選擇實際上也是很重要的,文中后面會提到。
四、一些實踐Tricks 真正的干貨終于要登場了。上面說到,BP是一階梯度方法,所以BP是很慢的。特別是在多層網(wǎng)絡(luò)的時候,代價函數(shù)曲面一般是非二次、非凸和高維的,因此有非常多的局部最小值和(或者)平flat的區(qū)域。所以BP算法無法保證:1)網(wǎng)絡(luò)會收斂到一個好的解;2)收斂是迅速的;3)收斂總會出現(xiàn)。然而,本節(jié)中我們會討論一系列的tricks,這些tricks一般可以非常有效的增加上述這些情況出現(xiàn)的機會,也就是在可以數(shù)量級的降低收斂時間的基礎(chǔ)上找到一個不錯的解。注意是數(shù)量級哦。是不是很期待呢。 1)Stochastic Learning vs Batch Learning 因為我們的代價函數(shù)是在整個訓(xùn)練集上取平均,所以在對權(quán)重的每次迭代更新中,都需要對數(shù)據(jù)庫中所有的樣本過一遍,然后求解平均或者真實的梯度。這種方式叫batch學(xué)習(xí),因為每次的參數(shù)更新需要考慮了完整的batch數(shù)據(jù)。相對的,我們可以使用隨機或者在線stochastic (online)學(xué)習(xí)的方式,也就是每次從訓(xùn)練集中選擇(例如,隨機的)一個樣本{Zt, Dt}來計算梯度。這時候,梯度的估計只通過這一個樣本進(jìn)行估計獲得,這時候t時刻對模型參數(shù)的更新為:
因為這個對梯度的估計是有噪聲的,所以在每次的迭代中,參數(shù)可能不是很精確的沿著梯度下降的方式走。但是,我們將會看到,這種每次迭代引入的“噪聲”實際上是有利的。隨機學(xué)習(xí)因為下面三個原因而備受青睞: A、 隨機學(xué)習(xí)一般比batch學(xué)習(xí)收斂更快; B、 隨機學(xué)習(xí)一般會得到更好的解; C、 隨機學(xué)習(xí)對跟蹤網(wǎng)絡(luò)的變化很有用。 首先,我們來分析下第一點。隨機學(xué)習(xí)在大部分情況下會比batch學(xué)習(xí)要快,特別是在大規(guī)模的冗余數(shù)據(jù)庫中。原因很簡單。假設(shè)我們有這樣一個數(shù)據(jù)庫,它有1000的樣本,但由于我們不小心,這1000個樣本是把100個樣本復(fù)制了10份得到的。所以,對這全部1000個樣本進(jìn)行梯度平均,和對這100個樣本進(jìn)行梯度平均的結(jié)果是一模一樣的。因此,batch梯度下降就很浪費了,因為對一次參數(shù)更新它重復(fù)計算了10次。做了很多無用功。而隨機梯度只是相對于一個100樣本(假設(shè)batch包括100個樣本)的訓(xùn)練集迭代了10次。實際上,在數(shù)據(jù)庫中,一個樣本很少出現(xiàn)兩次,但數(shù)據(jù)庫里面還是存在很多很相似的樣本的。例如在音素分類中,所有包含音素/?/的模式基本上都包含了相似的信息,所以這種冗余就使得batch學(xué)習(xí)要比在線學(xué)習(xí)慢得多。 第二點,隨機學(xué)習(xí)可以得到更好的解是因為它給我們的梯度更新帶來了噪聲。有利的噪聲可以美其名叫擾動。非線性網(wǎng)絡(luò)一般具有很多不同深度的局部極小值。訓(xùn)練的目標(biāo)是找到其中一個極小值。Batch學(xué)習(xí)發(fā)現(xiàn)的極小值是依據(jù)參數(shù)初始化在代價函數(shù)表面的某個坑上面,所以如果參數(shù)一旦初始化了,因為梯度下降都是往低的地方走,所以最后的歸宿一般就確定了,它一定是掉到這個坑里面。如果人生過得循規(guī)蹈矩,不信命不行。不過在隨機學(xué)習(xí)中,由于噪聲的存在,有時候會使參數(shù)跳到另一個坑中,從而有可能找到更深的局部極小值。更深的局部極小值意味著更小的代價函數(shù)值,也就是更擬合數(shù)據(jù)的模型。所以人生多姿多彩,還是有不同的收獲的。 隨機學(xué)習(xí)還有一個很有用的場景,就是我們要建模的函數(shù)在時間上是變化。一個非常常見的場景是在工業(yè)應(yīng)用領(lǐng)域。這里數(shù)據(jù)的分布隨著時間會變化(例如,由于機器的磨損)。如果我們的模型不能檢測和適應(yīng)這個變化,他們它就無法學(xué)習(xí)數(shù)據(jù),從而導(dǎo)致非常大的泛化誤差。時代在發(fā)展,思想得改革。對batch,由于我們需要在少數(shù)的rules中進(jìn)行平均,所以這種變化很難被檢測,從而獲得不好的結(jié)果。但在線學(xué)習(xí),如果操作得當(dāng),可以跟蹤這個變化,從而得到更近似的結(jié)果。 盡管隨機學(xué)習(xí)是有上述這些討人喜歡的地方,但batch學(xué)習(xí)也并非一無是處,還是存在一些理由讓我們考慮batch學(xué)習(xí)的。Batch學(xué)習(xí)的優(yōu)點: A、 收斂條件易于理解; B、 很多加速的方法,例如共軛梯度,只在batch學(xué)習(xí)中有效; C、 對參數(shù)變化和收斂率的理論分析更簡單。 為了平等,我們也來分析下batch的這些優(yōu)點。凡事都有兩面性,這個“噪聲”也有利有弊,它的“利”成就了隨機學(xué)習(xí),而它的“弊”也將大家對隨機學(xué)習(xí)的一部分愛推向了batch學(xué)習(xí)。換句話說,batch學(xué)習(xí)上述這些優(yōu)點就是因為沒有這個“噪聲”而帶來的。這個噪聲對找到更好的局部極小值很關(guān)鍵,但它也會阻止完全的收斂到局部極小值,它會讓代價函數(shù)在極小值周圍徘徊,它很想下去,但卻有心無力,因為它生于噪聲而被噪聲束縛。這種噪聲會導(dǎo)致模型的參數(shù)發(fā)生抖動,就算在局部極小值附近,也不穩(wěn)定,一直折騰。這個抖動的大小也取決于隨機更新的噪聲大小。在局部極小值附近的抖動的方差和學(xué)習(xí)率是成比例的。所以為了減小這種抖動,我們有兩種方法:1)減小學(xué)習(xí)率(退火);2)使用一個自適應(yīng)的batch大小。對第一種方法,有理論說明了對學(xué)習(xí)率調(diào)整最優(yōu)的退火過程是:η=c/t。c是一個常數(shù),t是樣本個數(shù)。實際應(yīng)用中,這個學(xué)習(xí)率還是有點大。 另一種方法也很自然,解鈴還須系鈴人,誰帶來的爛攤子就誰來收拾。那就是想辦法去掉噪聲。咦?那隨機學(xué)習(xí)的那些優(yōu)點不是也因為噪聲的去除而消失?凡事都有中庸之道,存在中庸之法,極端不可取,那就取矛盾的折衷。mini-batches正式登上歷史舞臺來平衡這各方壓力。很簡單,訓(xùn)練一開始,我們的參數(shù)剛初始化,離最小值還很遠(yuǎn),這時候我們就要加快它前進(jìn)的步伐,因此借助隨機學(xué)習(xí)的收斂速度,我們采用一個很小的mini-batches,也就是每個batch包含的訓(xùn)練樣本數(shù)不多。隨著訓(xùn)練的進(jìn)行,離最小值越來越近,我們就得減速了,否則沖過界了,又得抖來抖去了。因此我們增加mini-batches的大小,從而降低噪聲。然而,每種方法的引入都會引入另外需要考慮的超參,在這里就是應(yīng)該對mini-batches的大小選擇怎樣的增長率?這實際上和選擇學(xué)習(xí)率是同樣困難的。殊途同歸,有效的調(diào)整學(xué)習(xí)率和有效的調(diào)整mini-batches的大小增長率效果差不多。 不過,值得注意的一點是,因為考慮到模型的泛化能力,所以也有認(rèn)為去除數(shù)據(jù)中的噪聲就顯得不那么關(guān)鍵了。因為還沒遇到噪聲的這些弊病的時候就已經(jīng)過訓(xùn)練(過擬合)了。 另一個batch訓(xùn)練的優(yōu)點是可以使用二階優(yōu)化方法來加速學(xué)習(xí)過程。二階方法不僅估計了代價函數(shù)曲面在某點處的梯度(一階信息),同時還估計了曲面的曲率(二階信息)。拿到曲率后,它就可以估計真實最小值的近似位置,以此進(jìn)行強有力的加速。 盡管batch學(xué)習(xí)有這樣那樣的優(yōu)點,隨機學(xué)習(xí)還是大家比較青睞的方法,特別是訓(xùn)練的數(shù)據(jù)庫非常大的時候,它的確更快。天下武功,唯快不破! 2)Shuffling打亂樣本的學(xué)習(xí)順序 有一個原則是,網(wǎng)絡(luò)從意料之外的樣本中學(xué)習(xí)最快。槍打出頭鳥,就像如果第一天上課,你很突出,很搗蛋,那你老師肯定記住了你,而不是其他“平凡”的學(xué)生。所以思想就很簡單了,為了加速學(xué)習(xí),在每次迭代的時候我們挑選一個和系統(tǒng)最不相似、最不和諧的樣本讓網(wǎng)絡(luò)去學(xué)習(xí)。把“出頭鳥”拎出來,擒賊先擒王。很明顯,這個方法只對隨機學(xué)習(xí)有效,因為batch是不管順序的,不管先來后到,都得等齊人了,才發(fā)糧草(計算全部樣本的總誤差再去做梯度更新)。當(dāng)然了,沒有很簡單的方法可以知道到底哪個輸入樣本攜帶了對系統(tǒng)最豐富的信息量,不過有個簡單的trick就是粗糙地選擇來自不同類的樣本,換句話來說,就是,如果在第t次迭代,我是用第i類的樣本來學(xué)習(xí)的,那么在第t+1次迭代的時候,就選擇除i類外的其他類的一個樣本來學(xué)習(xí)。因為同一個類的訓(xùn)練樣本很大可能攜帶的是相似的信息,所以我這次見到你了,下次就不想見到和你長得差不多的人了,沒什么信息量,審美疲勞。 另一種啟發(fā)式的判斷到底一個訓(xùn)練樣本攜帶了多少新信息的方法,就是測試當(dāng)將這個樣本輸入到網(wǎng)絡(luò)的時候,網(wǎng)絡(luò)的輸出值和目標(biāo)輸出值的誤差大小。誤差越大,那就表示網(wǎng)絡(luò)還沒學(xué)習(xí)到這個樣本,因此它具有更多的新的信息。就像突然你的世界出現(xiàn)了一個新鮮事物一樣,那種“哎呀”的感覺。所以,我們偏心的將這個樣本多次輸入網(wǎng)絡(luò)去學(xué)習(xí)也是有意義的。當(dāng)然了,這個誤差的“大”是相對于其他訓(xùn)練樣本來說的。隨著網(wǎng)絡(luò)的訓(xùn)練,每個輸入樣本的這個誤差都會變化,所以每個樣本被輸入網(wǎng)絡(luò)訓(xùn)練的次數(shù)也會變化。有個修改每個樣本的這個概率或者次數(shù)的方法叫emphasizing scheme: A、 打亂訓(xùn)練集,使得鄰近的樣本幾乎不會屬于同一個類; B、 挑會使網(wǎng)絡(luò)產(chǎn)生更大誤差的樣本輸入網(wǎng)絡(luò)學(xué)習(xí)。 然而,需要小心的是,打亂輸入樣本被學(xué)習(xí)的正常頻率,會改變每個樣本對網(wǎng)絡(luò)的重要程度,這可能不是那么好。讓一部分人先富起來,富起來后他們就不管后富了,這貧富差距就大了。千萬寵愛集于幾人,朱門酒肉臭,路有被冷落死的樣本。這種不利于社會和諧的政策還是不要太極端的好。舉個極端的例子,如果訓(xùn)練集中有離群點outliers,那將帶來災(zāi)難性的后果。因為離群點可以產(chǎn)生很大的誤差,但很明顯,不應(yīng)該將它多次地送給網(wǎng)絡(luò)去訓(xùn)練,這樣會擾亂這個網(wǎng)絡(luò)的正常學(xué)習(xí)。網(wǎng)絡(luò)為這個樣本調(diào)整了半天的參數(shù),然后發(fā)現(xiàn)這個是個很不正常的樣本,那乖乖,無力吐槽。不過,這個trick對一種情況非常有用,那就是可以對那些正常的但很少出現(xiàn)的輸入模式進(jìn)行性能的加速,例如在音素識別中/z/這個音素。如果這個樣本是個正常的小眾,那讓網(wǎng)絡(luò)多次學(xué)習(xí)它是有益的。關(guān)注弱小群體,構(gòu)建和諧社會。 3)對輸入進(jìn)行標(biāo)準(zhǔn)化Normalize 如果訓(xùn)練樣本中每個輸入變量(特征維度)的均值接近于0,那收斂一般都會更快。我們考慮個極端的情況。也就是網(wǎng)絡(luò)所有的輸入都是正數(shù)。第一個隱層的神經(jīng)元的參數(shù)更新值是和δx成比例的,δ是這個神經(jīng)元的誤差,x是輸入的向量。當(dāng)x所有的元素都是正數(shù)的時候,對這個神經(jīng)元的參數(shù)的更新值都具有相同的符號(因為x是正數(shù),所以更新值的符號和δ的符號一致,而δ是一個標(biāo)量)。這就導(dǎo)致了,這些參數(shù)對一個給定的輸入樣本,要么全部增加(δ是正數(shù)),要么全部減?。é氖秦?fù)數(shù))。所以,如果一個參數(shù)向量到達(dá)到最優(yōu)值是必須要改變方向的話,那么它就會沿著“之”形狀的路徑前進(jìn),這是非常低效的,所以會導(dǎo)致收斂非常慢。 上述例子中,所有的輸入都是正數(shù)。然而,實際上,如果訓(xùn)練樣本的輸入變量的均值遠(yuǎn)離于0,都會讓參數(shù)的更新傾向于一個特定的方向,從而降低了學(xué)習(xí)的速度。因此,將整個訓(xùn)練集每個樣本的輸入變量的均值偏移到0處是有好處的。而且,這種啟發(fā)式的方法應(yīng)該在網(wǎng)絡(luò)的每一層都使用上,換句話說,我們希望每個節(jié)點的輸出的均值都接近于0,因為這些輸出實際上是下一層的輸入。不過這個問題,可以將對輸入的變換和對sigmoid激活函數(shù)的選擇共同考慮。這里我們討論對輸入的變換。后面再討論sigmoid函數(shù)。 除了對樣本進(jìn)行平移外,還有一個加速收斂的方法是對樣本進(jìn)行縮放,讓每一個特征維度都具有相同的協(xié)方差??s放為什么會加速學(xué)習(xí)?因為它可以平衡與輸入節(jié)點連接的參數(shù)的學(xué)習(xí)率。什么意思呢?上面提到第一個隱層的神經(jīng)元的參數(shù)更新值是和δx成比例的,那如果x中有些元素的值很大,而有些元素的值很小,那很明顯,值大的會導(dǎo)致參數(shù)的更新值也很大。值小的更新值也小,哦,貧富差距又來了。不過,上面只是他們的方差值要相同,那應(yīng)該取多少呢?這個值應(yīng)該和sigmoid的選擇相匹配。對下面給定的sigmoid函數(shù)(說了下面給定,那肯定得在下面才能看到啦,囧),協(xié)方差取1是個不錯的選擇。 不過也有例外的情況,那就是當(dāng)你事先知道某些輸入變量的重要性要比其他輸入變量弱的時候。這種情況下,可以將重要性小的輸入變量縮小,這樣就可以讓學(xué)習(xí)算法輕微的“忽略”它了。人的先驗為大嘛。 上述對輸入進(jìn)行平移和縮放的tricks是很容易實現(xiàn)的。還有一個也很有效,但比較難實現(xiàn)的tricks是對輸入進(jìn)行解相關(guān)。考慮下圖所示的簡單網(wǎng)絡(luò)。如果輸入是獨立的,也就是不相關(guān)的,那么就可以通過最小化而得到w1的解,而不用去考慮w2,反之亦然。如果輸入是相關(guān)的,那么就需要同時解兩個參數(shù)w,這明顯要更難點。那如何去對輸入變量進(jìn)行解相關(guān)呢?鼎鼎大名的PCA登上歷史舞臺。不過它能力也有限哦,只能用來移除輸入的線性相關(guān)性(只能搞定二階,高階就鞭長莫及了)。
實際上,如果輸入是線性獨立的(相關(guān)的極端情況)也可能會產(chǎn)生某種降低學(xué)習(xí)速度的退化??紤]一種情況是,當(dāng)一個輸入變量總是另一個輸入的兩倍z2=2z1。那網(wǎng)絡(luò)沿著線W2=v-(1/2)W1(v是個常數(shù))的輸出就都是常數(shù)。因此,在這個方向的梯度就都是0了。因此在這些線上移動對學(xué)習(xí)不會起到任何的效果。我們本來是想嘗試解決一個二維的問題的,但這個問題實際上在一維的時候才是有效的。吃力不討好。因此,理想情況下,我們希望去掉這一個輸入,減小網(wǎng)絡(luò)的大小。 總結(jié)來說,對輸入的變換如下: A、 訓(xùn)練集的每個輸入變量的均值要接近于0; B、 對輸入變量進(jìn)行縮放,使他們的方差具有相同的值; C、 輸入變量最好是不相關(guān)的。 這個過程可以表達(dá)如下:1)平移輸入讓他們的均值為0;2)對輸入解相關(guān);3)均衡化協(xié)方差。如下圖所示:
4)sigmoid函數(shù) 非線性激活函數(shù)的使用賦予了神經(jīng)網(wǎng)絡(luò)對非線性函數(shù)的建模能力。如果沒有他,無數(shù)隱層的神經(jīng)網(wǎng)絡(luò)還是一個線性網(wǎng)絡(luò)。家喻戶曉的激活函數(shù)非sigmoid莫屬了。它是單調(diào)遞增的,通過在正負(fù)無窮大的時候是漸進(jìn)于某個有限值。一般取標(biāo)準(zhǔn)的邏輯函數(shù)f(x)=1/(1+e-x)和雙曲線正切函數(shù)f(x)=tanh(x)。人們往往更喜歡關(guān)于原點對稱版本的Sigmoid函數(shù)(雙曲線正切函數(shù)),因為上面我們提到輸入應(yīng)該要滿足標(biāo)準(zhǔn)化,所以這個函數(shù)的輸出更有可能為下一層創(chuàng)造均值接近于0的輸入。相反,Logistic函數(shù)因為輸出總是正數(shù),因此它的均值也總是正數(shù)。
(a)標(biāo)準(zhǔn)Logistic函數(shù)。(b) 雙曲線正切函數(shù)f(x)=1.7159tanh(2x/3) 對Sigmoids函數(shù)的Tricks如下: A、 對稱性的sigmoids函數(shù)例如雙曲線正切函數(shù)往往比標(biāo)準(zhǔn)的Logistic函數(shù)收斂更快。 B、 一個建議的激活函數(shù)是f(x)=1.7159tanh(2x/3)。因為tanh函數(shù)計算挺耗時的,所以一般可以用多項式的系數(shù)來近似。 C、 有時候,增加一個線性項會很有用,例如f(x)=tanh(x)+ax,這樣可以避免代價函數(shù)曲面flat的地方。 我們上面建議你使用的那個激活函數(shù),連參數(shù)都給你選擇好了。因為當(dāng)你使用的是標(biāo)準(zhǔn)化的輸入后,這個激活函數(shù)輸出的方差也會接近于1,因為sigmoid的effective gain(有效增益?)在它的有效范圍內(nèi)大致為1。這個特別版本的sigmoid具有以下性質(zhì):a)f(正負(fù)1)=正負(fù)1;b) 最大的二次導(dǎo)數(shù)出現(xiàn)在x=1的地方;c)有效增益接近于1。 當(dāng)然了,凡事依然有兩面性,使用對稱性sigmoid也有它的缺點,那就是它會使得誤差表面在接近原點的地方會非常平flat。因為這個原因,所以最好可以避免將網(wǎng)絡(luò)參數(shù)初始化為很小的值。因為sigmoids的飽和,誤差表面在遠(yuǎn)離原點的時候也是flat的。在sigmoid中增加一個線性的項有時候可以避開這些flat的區(qū)域。 5)目標(biāo)值的選擇 在分類問題上,目標(biāo)值一般都是二值的,例如{-1,+1}。很多智者都建議把目標(biāo)值設(shè)置為sigmoid的漸進(jìn)線的地方。然而,這種做法有些弊端: 首先,會導(dǎo)致不穩(wěn)定。我們知道,網(wǎng)絡(luò)的訓(xùn)練會盡自己的最大努力讓網(wǎng)絡(luò)的輸出盡可能的接近于目標(biāo)值,當(dāng)然了,只能漸進(jìn)的接近。這樣,網(wǎng)絡(luò)的參數(shù)(輸出層,甚至隱層)會變得越來越大,而在這些地方,sigmoid的導(dǎo)數(shù)值接近于0。這些非常大的參數(shù)會增加梯度的值,然而,這些梯度接下來會乘以非常小的sigmoid導(dǎo)數(shù)(除非增加一個twisting扭曲項,也就是之前說的增加個線性項ax)從而導(dǎo)致最后的參數(shù)更新值也接近于0。最終導(dǎo)致的慘不忍睹的結(jié)果就是參數(shù)被卡住了,動不了啦。 第二,當(dāng)輸出飽和時,網(wǎng)絡(luò)無法給出置信度的指示。首先,置信度是個啥?說白了,置信度就是當(dāng)你給神經(jīng)網(wǎng)絡(luò)輸入一個樣本的時候,我,神經(jīng)網(wǎng)絡(luò),要給你分類是不是。我經(jīng)過一輪辛勤的計算,給你一個分類結(jié)果對不對。那你就百分比相信我給你的結(jié)果是正確的?作為一個負(fù)責(zé)任的網(wǎng)絡(luò),我是不是還得告訴你,我做出這個分類判斷的可信度是多少?這樣才會給你的下一步?jīng)Q策提供參考,信不信由你。例如,當(dāng)一個輸入樣本落在決策邊界附近的時候,網(wǎng)絡(luò)輸出的決策值實際上是不確定的。理想情況下,這種置信度應(yīng)該要被反映在網(wǎng)絡(luò)中,比如輸出一個在兩個可能的目標(biāo)值之間的某個值,而不是在兩端漸進(jìn)線的地方。然而,大的參數(shù)會強制所有的輸出都落在sigmoid的尾部,而不去考慮不確定性。典型的妄自尊大呀。因此,在沒有給出任何關(guān)于這個結(jié)果置信度很低的指示,網(wǎng)絡(luò)就可能給的是一個錯誤的類別結(jié)果,這不坑人嘛。大的參數(shù)會導(dǎo)致神經(jīng)元的飽和,蒙蔽了它的雙眼,從而使其喪失了對樣本基本的區(qū)分能力。 解決這個問題的一個方法就是把目標(biāo)值設(shè)置在sigmoid的有效范圍內(nèi),而不是在漸進(jìn)線的區(qū)域。還需要小心的是,為了保證節(jié)點不會只被限制在sigmoid的線性部分,可以把目標(biāo)值設(shè)置在sigmoid的最大二階導(dǎo)數(shù)的位置,這樣不但可以利用非線性的優(yōu)點,還可以避免sigmoid的飽和。這也是上圖b中的sigmoid函數(shù)是個不錯的選擇的原因。它在正負(fù)1的地方具有最大的二階導(dǎo)數(shù),而正負(fù)1對應(yīng)的恰好是分類問題的典型二值目標(biāo)值。 Trick:目標(biāo)值:將目標(biāo)值選擇在sigmoid函數(shù)最大二階導(dǎo)數(shù)的位置。從而避免輸出節(jié)點的飽和。 6)參數(shù)的初始化 參數(shù)的初始值對訓(xùn)練過程有著重大的影響。我們對參數(shù)初始化的原則是:參數(shù)應(yīng)該隨機初始化在能讓sigmoid函數(shù)在線性區(qū)域激活的值。如果參數(shù)全部都很大,那sigmoid一開始就飽和了,這樣就會得到一個非常小的梯度值,那參數(shù)更新就會很慢,訓(xùn)練也會很慢。如果參數(shù)太小了,那梯度也會很小,同樣也會導(dǎo)致訓(xùn)練很慢。中庸之道!參數(shù)處于sigmoid線性范圍的那段區(qū)域有幾個優(yōu)點:1)梯度可以足夠的大,從而使得學(xué)習(xí)能正常進(jìn)行;2)網(wǎng)絡(luò)可以在學(xué)習(xí)映射的非常困難的非線性部分之前學(xué)習(xí)映射的線性部分。 達(dá)到這個目標(biāo)并非sigmoid一家之力可以完成。它需要數(shù)據(jù)標(biāo)準(zhǔn)化、sigmoid的選擇和參數(shù)初始化的選擇這三者的協(xié)調(diào)。首先,我們要求每個節(jié)點的輸出的標(biāo)準(zhǔn)差應(yīng)該接近于1,這可以通過使用之前提到的數(shù)據(jù)標(biāo)準(zhǔn)化來對訓(xùn)練集進(jìn)行變換獲得。為了可以在第一個隱層的輸出同樣獲得標(biāo)準(zhǔn)差為1的輸出,我們只需要使用上面建議的sigmoid函數(shù),同時要求sigmoid的輸入的標(biāo)準(zhǔn)差也為1。假設(shè)一個結(jié)點的輸入yi是不相關(guān)的,而且方差為1,那結(jié)點的標(biāo)準(zhǔn)差就是參數(shù)的加權(quán)和:
因此,為了保證上述這個方差近似于1,參數(shù)就應(yīng)該從一個均值為0,標(biāo)準(zhǔn)差為:σw=m-1/2的分布中隨機采樣得到(m是fan-in,也就是與這個結(jié)點連接的輸入個數(shù),也就是前一層的節(jié)點個數(shù),如果是全連接網(wǎng)絡(luò)的話)。 Trick:參數(shù)初始化: 假設(shè):1)訓(xùn)練集已經(jīng)被標(biāo)準(zhǔn)化;2)sigmoid是選擇f(x)=1.7159tanh(2x/3)。 那參數(shù)就應(yīng)該從一個均值為0,標(biāo)準(zhǔn)差為σw=m-1/2的分布(例如正態(tài)分布)中采樣得到。 7)學(xué)習(xí)率的選擇 對學(xué)習(xí)率的選擇也是一個大學(xué)問。和上面說的batch的大小選擇一樣。學(xué)習(xí)率,就是參數(shù)更新每一步走多遠(yuǎn),這個參數(shù)很關(guān)鍵。如果設(shè)置的太大,那么很容易就在最優(yōu)值附加徘徊,因為你步伐太大了。例如要從廣州到上海,但是你的一步的距離就是廣州到北京那么遠(yuǎn),沒有半步的說法,自己能邁那么大步,是幸運呢?還是不幸呢?事物總有兩面性嘛,它帶來的好處是能很快的從遠(yuǎn)離最優(yōu)值的地方回到最優(yōu)值附近,只是在最優(yōu)值附近的時候,它有心無力了。但如果設(shè)置的太小,那收斂速度就太慢了,像蝸牛一樣,雖然會落在最優(yōu)的點,但是這速度如果是猴年馬月,我們也沒這耐心啊。所以有的改進(jìn)就是在這個學(xué)習(xí)率這個地方下刀子的。我開始迭代是,學(xué)習(xí)率大,慢慢的接近最優(yōu)值的時候,我的學(xué)習(xí)率變小就可以了。所謂采兩者之精華啊! 實際上,學(xué)習(xí)的方法經(jīng)過那么久的發(fā)展,對學(xué)習(xí)率的研究還是有不少的成果或者經(jīng)驗的。至少存在著一個很好的估計理想學(xué)習(xí)率的方法。而且還存在著很多其他的自動調(diào)整學(xué)習(xí)率的方法,不過大部分都是經(jīng)驗性的。 大部分這些方法都是在參數(shù)發(fā)生震蕩的時候減小學(xué)習(xí)率,而在參數(shù)相對穩(wěn)定的朝著一個方向前進(jìn)的時候增加學(xué)習(xí)率。這個方法的主要問題在于它對隨機梯度或者在線學(xué)習(xí)是不合適的,因為參數(shù)在所有的訓(xùn)練過程中都是抖動的。從一開始,到最后,它都是抖動的。人生如此坎坷,希望在哪。 與為所有參數(shù)選擇一個同樣的全局學(xué)習(xí)率相對,可以為每個參數(shù)選擇不同的學(xué)習(xí)率,這樣一般都可以加快收斂速度。有種不錯的方法就是計算二階導(dǎo)數(shù)來實現(xiàn)的,這個會在后面提到。這個方法最需要確定的是網(wǎng)絡(luò)中的所有參數(shù)都會以差不多的速度收斂。這具體取決于誤差表面的曲率,一些參數(shù)可能需要小的學(xué)習(xí)率來避免發(fā)散,而一些參數(shù)需要大的學(xué)習(xí)率要加快收斂速度。因為這個原因,低層的學(xué)習(xí)率一般要比高層的大。這是因為對大部分的神經(jīng)網(wǎng)絡(luò)框架而言,代價函數(shù)對低層網(wǎng)絡(luò)參數(shù)的二階導(dǎo)數(shù)要比對高層參數(shù)的小。 如果網(wǎng)絡(luò)中使用了共享參數(shù),例如TDNN或者CNN,那學(xué)習(xí)率應(yīng)該和共享參數(shù)的連接個數(shù)的平方根成比例。因為我們知道,梯度是一些或多或少獨立的項的和。 Tricks: A、 給每個參數(shù)自己的學(xué)習(xí)率; B、 學(xué)習(xí)率應(yīng)該和該節(jié)點的輸入個數(shù)的平方根成比例; C、 低層參數(shù)的學(xué)習(xí)率應(yīng)該比高層的大。 還有一些加快收斂的tricks包括: Momentum:
當(dāng)代價函數(shù)表面是高度非球形的,Momentum可以提高收斂速度。因為它可以限制大曲率方向的步長過大,因此可以在低曲率方向得到一個更有效的學(xué)習(xí)率。(μ衡量的是矩項的強度)。江湖中,有種說法,就是矩在batch學(xué)習(xí)比在隨機模式中要有效得多,但這個說法沒有什么系統(tǒng)的研究。 自適應(yīng)學(xué)習(xí)率: 主要是在訓(xùn)練中根據(jù)誤差來實時調(diào)整學(xué)習(xí)率。(因為問題比較大,此處略去。有興趣的參考原文)。 8)RBF vssigmoid 節(jié)點 盡管大部分的系統(tǒng)都是使用基于點積和sigmoid的神經(jīng)元,不過還是存在其他選擇的。一個比較典型的就是RBF徑向基網(wǎng)絡(luò)了。在RBF網(wǎng)絡(luò)中,參數(shù)和輸入向量的點積被替換為兩者的歐式距離,同時sigmoid函數(shù)變?yōu)橹笖?shù)函數(shù)。例如對一個輸入x,它的輸出為:
vi(σi)是第i個高斯的均值和標(biāo)準(zhǔn)差。這些節(jié)點可以替換標(biāo)準(zhǔn)的節(jié)點,也可以和他們共存。他們一般是通過梯度下降(對輸出層)和非監(jiān)督聚類算法對RBF節(jié)點的均值和方差進(jìn)行學(xué)習(xí)。這個可以參考我的這個博文。 與sigmoid節(jié)點不同,sigmoid可以覆蓋整個空間。但一個RBF節(jié)點只能覆蓋輸入空間的一小局部區(qū)域。這樣對快速學(xué)習(xí)是有利的。RBF還可以構(gòu)建一組能更好的對輸入空間進(jìn)行建模的基函數(shù),不過這是問題獨立的。RBF還是有缺點的,它的局部特性可能會帶來一些不好的性能,特別是在高維空間中,就需要非常多的節(jié)點才可以覆蓋整個空間。不過,有人也得到了一些網(wǎng)絡(luò)設(shè)置的經(jīng)驗,就是在網(wǎng)絡(luò)的低層(高維)用sigmoid,在高層(低維)使用RBF。
|
|