
在機器學習的過程中,當參數(shù)數(shù)量比較多的時候,很可能就會出現(xiàn)過擬合的現(xiàn)象,使得模型在訓練集中擬合效果很好,但在測試集上擬合效果就讓人不那么愉快了。
發(fā)生這種情況,就意味著訓練出來的模型泛化性比較差,無法適應(yīng)復雜的現(xiàn)實情況。那我們肯定就需要想辦法防止或者減弱過擬合的發(fā)生。本篇 CoorChice 將會介紹幾種防止過擬合的方法。
正則化
在進行模型訓練的的時候,最重要的一步就是通過不斷減小損失函數(shù)的損失值來逼近全局最優(yōu)解,簡單的說就是讓我們的特征權(quán)值能夠正確的描述出真實情況。
可是往往訓練出來的權(quán)值可能會有很多的噪聲,即有很多無用的特征權(quán)值,在沒有類似噪聲的數(shù)據(jù)中很可能就會誤判。也可能某些特征的權(quán)值特別大,導致只要出現(xiàn)一部分大的特征,模型就會忽略掉其大特征權(quán)值較小的有用權(quán)值,那這樣的模型也是很容易造成誤判。
如何解決這種困境呢?答案可以是正則化,或者說規(guī)則化。正則化是代數(shù)幾何中的一個概念。在機器學習中,加入正則化項表示加入了一個先驗規(guī)則項。大白話來說就是,我們對結(jié)果是有一定預期的,不能完全隨意的想咋搞咋搞。

通常會使用 范數(shù) 來作為損失函數(shù)的規(guī)則化項。

這就是范數(shù)公式,依據(jù) p 的取值,可以產(chǎn)生 0范數(shù)、1范數(shù) 和 2范數(shù)等,即 p 取 0、1、2。不同的范數(shù)所應(yīng)對場景也有所不同。
0范數(shù)、1范數(shù)
0范數(shù)
上述范數(shù)公式,當 p 取 0 時,就稱為 0 范數(shù),Lp 公式就變?yōu)槿缦滦问剑?/p>

可以看到,0 范數(shù)中,涉及到求解一個數(shù)的 0 次方根,這是很怪異的一個公式,很難說清它的意義是什么,以及應(yīng)該如何求解。
所以在0范數(shù)有一個優(yōu)化的形式,使其具有一個明確的意義:

該公式的意義是,求解 w 向量空間中的非 0 元素個數(shù)。
它為什么能夠防止過擬合呢?把它加入到損失函數(shù)中有如下式子:

此處插播一條說明,上面的 Loss 函數(shù)式由兩個部分組成,c0部分就是傳統(tǒng)的損失函數(shù),稱為 “經(jīng)驗風險”;后面的正則項稱為 “結(jié)構(gòu)風險”,它有點從結(jié)構(gòu)上約束前半部分 “經(jīng)驗風險” 的意思。
可以看看當 p 趨近于 0 時范數(shù)圖像:

不難看出這樣的趨勢,當 p 與接近于 0 時,它的結(jié)果就越貼近于各個坐標軸。那么可以想象出,當 p 為 0 的時候,結(jié)果就都落在坐標軸上了。當損失部分的函數(shù)與其相切時,自然之可能切到坐標軸上,即只有一個坐標有值,其它全為 0。
這就意味這,在進行梯度下降不斷減小 Loss 的過程中,需要考慮將更多權(quán)值 w 置為 0 ,這樣才能使 0 范數(shù)項不斷的減小。那么它的意義就浮現(xiàn)出來了,就是盡可能的將不重要的權(quán)值直接置 0,減少參數(shù)數(shù)量,盡量只保留有用的特征。即它使權(quán)重集具有了稀疏性(包含 0),起到了篩選特征的作用。

看起來很棒吧,能自動的篩選特征!可是在對于特征權(quán)值 w 數(shù)量龐大的機器學習中,要動態(tài)的去學習到如何將那些 w 設(shè)置為 0 既能保證 Loss 不斷的減小,又能保證 0 范數(shù)項也在不斷的減小,到底應(yīng)該讓那些權(quán)值變小,而那些權(quán)值直接為 0 呢,可能性就太多了,多到幾乎不可能搜索出一條最優(yōu)的解路徑來。這樣的有解,但幾乎很難求解出來的問題被稱為 NP-hard 問題,意思就是雖然可以檢查每次計算結(jié)果的正確性,但計算結(jié)果眾多,以至于無法進行一一檢查,而是這個問題相當于無法解的問題。
1范數(shù)
在數(shù)學上,一般無法直接求解的問題就會使用近似的算法去不斷的逼近真實的答案,得出一個近似的解,也是可以接受的。
那 1范數(shù) 就是具有 0范數(shù) 優(yōu)勢,而又易于求解的一個近似算法。
同理,1范數(shù)就是當 p 等于 1 時的范數(shù)式:

1范數(shù)的意思就很明了了,就是所有權(quán)值 w 的絕對值的和。加入1范數(shù)的 Loss 函數(shù)式如下:

從 Loss 可以知道,為了使整個式子的值最小,需要 1范數(shù) 項的值也最小,那看看 1范數(shù)額圖像:

上圖是三維空間中1范數(shù)的圖像,是一個八面體,存在與坐標軸相交的頂點。推知,在更高維度的空間中,必然也存在很多這樣與坐標軸相交的頂點。就是說,在梯度下降的求解過程中,也是能找到損失函數(shù)與這些個頂點相切的解的,那么 1范數(shù) 也有機會和 0范數(shù) 一樣,能夠篩選出有用的特征,而剔除噪聲,從而提高模型的泛化能力。
在計算過程中,從上面的圖像可以看出,1范數(shù)存在不可導的點,也就是它的頂點們,這在計算上是不那么方便的。
2范數(shù)
避免過擬合
既然1范數(shù)計算也不方便,那我們是不是可以再升級升級,看看更高的范數(shù)是不是可以計算方便一些呢?
看看 p 取 2 的范數(shù)式:

再看看圖像是什么樣的:

三維圖像是個球!這意味著2范數(shù)在空間中是連續(xù)的且處處可導的函數(shù)。當然,它和坐標軸也是由交點的,這意味著和損失函數(shù)的切點也是有可能落在坐標軸上的,只不過從圖像也能看出來,這樣的概率比1范數(shù)更小罷了。
加入2范數(shù)的 Loss 函數(shù)是這樣的:

也就是求 w 的平方和。這里把開根去掉了,其實沒什么影響的,效果差不多但計算量卻小了很多。
2范數(shù)與損失函數(shù)的切點既然很難落到坐標軸上,那就是說它很難對特征進行篩選,很難削減無用的噪聲特征,那它憑什么也能避免模型過擬合呢?
CoorChice 會慢慢道來。
我們考慮這樣一個例子:用3個特征來識別小狗??,簡單來說,就有3個特征權(quán)值,即 [w1,w2,w3]。
w1 = 1,w2 = 1,w3 = 1 -> w1+w2+w3 = 3
w1 = 3,w2 = 0,w3 = 0 -> w1+w2+w3 = 3
以上是 w 取值的兩種情況。雖然 w 的和都是 3,但在識別的過程中,第二種情況中的 w2、w3 就完全的被巨大的 w1=3 給蓋過了。假設(shè) w1 表示 4 條腿的特征,那么這個模型但凡遇到 4 條腿的東西就認為它是小狗了,顯然是不科學的。這就是說,模型在訓練集中準確率很高,但在復雜的實際情況中很容易誤判。
如果采用2范數(shù),第一種情況的平方和是 3,而第二種情況的平方和就是 9 了!那么要讓 Loss 不斷減小,就需要不斷的削弱 w1 這種強特征的權(quán)重,使得一些有用的弱特征也能過累加起來顛覆強特征,讓模型不至于一遇到一個極強的特征,就忽略了眾多較弱的特征,而造成誤判。
2范數(shù)對權(quán)重的削弱平均特性,可以使得模型不依賴于某一部分強特征,而是更加全面的去考慮綜合的特征。這樣模型的泛化能力自然就提高了,也就不容易出現(xiàn)過擬合的情況了。
避免梯度爆炸??
在 《【Get】用深度學習識別手寫數(shù)字》 一文中,CoorChice 就提到了一開始訓練時遇到的瓶頸,因為梯度發(fā)生了 bong! bong! bong! 的爆炸。直接就導致了訓練完全沒辦法進行下去。但是在 CoorChice 加入正則化項之后,就成功了越過了梯度爆炸的雷區(qū),順利完成了訓練。
原因就在于,訓練過程中,某些極強權(quán)值的大小太過夸張,導致連乘過程中數(shù)值巨大無比,就爆炸??了了。2范數(shù)正則項剛好作用就是削弱這種極強的權(quán)值,所以在一定程度上,它能夠有效的減少梯度爆炸發(fā)生的可能性。
如何在 TensorFlow 中加入正則化項?
1.將所有權(quán)重 w 記錄下來
tf.add_to_collection(tf.GraphKeys.WEIGHTS, w)
每創(chuàng)建一個權(quán)值就調(diào)用這個函數(shù)把權(quán)值加入到池中。
2.構(gòu)建正則化項,加入到 Loss 中
# 構(gòu)建 l2 正則化項,設(shè)置其(縮放度)重要程度為 5.0 / 50000
regularization = tf.contrib.layers.l2_regularizer(scale=(5.0 / 50000))
# 讓正則化生效
reg_term = tf.contrib.layers.apply_regularization(regularization)
# 在損失函數(shù)中加入正則化項
loss = (-tf.reduce_sum(y_data * tf.log(y_conv)) + reg_term)
Dropout
Dropout 是一種被經(jīng)常用到深度學習中,用于減弱過擬合的一種技術(shù)。它的核心原理就是,在訓練過程中,讓一層中的神經(jīng)元按照指定的比率一部分失效,一部分仍然有效,具體是哪些個神經(jīng)元會被失效或者有效,都是隨機的。
失效的神經(jīng)元在一次迭代中就不會被更新。而在下一輪的訓練中,又會有另外一部分神經(jīng)元會被失效,不會被更新。
這樣做就相當于每次訓練都減少了神經(jīng)元的數(shù)量,同時由于每次可能抽取到的神經(jīng)元不一樣,就使得學習路徑變的具有隨機性。不同于沒有 Dropout 的網(wǎng)絡(luò)那樣,每次只能全量的更新所有神經(jīng)元,加入 Dropout 的神經(jīng)網(wǎng)絡(luò)中,神經(jīng)元之間的共適應(yīng)性會被削弱,在不斷減小的梯度的要求下,就能夠迫使網(wǎng)絡(luò)學習出更加具有魯棒性的特征。這樣模型的適應(yīng)性會更強,而不是只能適應(yīng)一個套路。

解釋了一大堆,可能還是很抽象,這時不如來一張圖吧!

是不是感覺清晰了很多。左邊是沒有 Dropout 的網(wǎng)絡(luò),神經(jīng)元之間都是全量鏈接的。右邊是有 Dropout 的網(wǎng)絡(luò),可以看到在一次訓練中,有一部分神經(jīng)元是斷開鏈接的,即失效了。每次斷開鏈接的神經(jīng)元都是隨機了,這就給網(wǎng)絡(luò)增加了很多可能,就像是具有了變異的能力。
通常,Dropout 需要設(shè)置一個超參數(shù),指定每次需要有多少神經(jīng)元失效。這個值一般回取 0.5,因為這樣能夠組合出多種類的情況來。
在著名的 VGG-16 網(wǎng)絡(luò)模型中,最后3層的全鏈接層中,都加入 Dropout。
當然,使用 Dropout 的弊端也是因為隨機性帶來,隨機很大概率上會導致訓練次數(shù)的增加,使得訓練時間變長。

如何在 TensorFlow 中加入 Dropout?
tf.nn.dropout(input, keep_prob)
很簡單,就是傳入前面的輸出,比如一個全鏈接層的輸出,然后在第二個參數(shù)指定需要保留的神經(jīng)元的比率。
需要注意的是,Dropout 在目前版本的 TensorFlow Lite 中還沒有被支持,所以考慮在 TensorFlow Lite 上跑模型的同學就不能使用了哦!??
總結(jié)
本篇 CoorChice 介紹了 2 種減少過擬合發(fā)生的可能性的方法,正則化 和 Dropout。
L0 和 L1 正則化能夠具有稀疏能力,減少參數(shù)數(shù)量,提取出主要特征。但 L0 在復雜參數(shù)集中難以求解,所以如果有需求時,通常選擇 L1 正則化代替。
L2 正則化能夠削弱強特征,使能夠考慮更加全面的特征。同時,L2 正則化還能一定程度上防止梯度爆炸??的發(fā)生。
- Dropout 是一種比較具有通用性的防止過擬合的手段,但會增加訓練時間,而且目前 TensorFlow Lite 對該操作還不支持。
- 嘿,隨手點個贊吧 ??! Lok'Tar ??
image- CoorChice 會不定期的分享干貨,快進入 CoorChice的【個人主頁】 加關(guān)注吧。
