正則化#
正則化是一種在深度學習中使用的技術,旨在減少模型的過擬合。它通過在目標函數中添加一個正則化項,引入模型複雜度的懲罰,以約束參數的大小或參數之間的關係,從而提高泛化能力並提高模型在未見過的數據上的性能。
過擬合與欠擬合#
過擬合#
過擬合(Overfitting)指的是模型過度擬合訓練數據,在訓練數據上表現很好,但在新數據上的表現較差。這是因為模型過於複雜,過度關注訓練數據的細節和噪聲,無法很好地泛化到未見過的數據。
欠擬合#
欠擬合(Underfitting)則是指模型無法很好地擬合訓練數據,無法捕捉到數據中的關鍵特徵和模式,導致在訓練數據和新數據上的表現都不理想。
- 增加模型複雜度
- 特徵工程(Feature Engineering)
- 增加訓練數據量
- 減少正則化
- 使用更複雜的模型
L1 正則化 (Lasso)#
L1 正則化是通過向模型的損失函數中添加 L1 範數懲罰項來實現的。L1 範數是指模型權重參數的絕對值之和。L1 正則化的目標是最小化損失函數和 L1 範數懲罰項的和。它的效果是將一些權重參數壓縮為零,從而實現特徵選擇和稀疏性。
梯度增加了一個常數項;通過在每次迭代中從未提供信息的特徵中減去一小部分,迫使它們的權重為零,從而最終使它們為零。鼓勵模型具有較小的系數,並可能導致稀疏性。
L2 正則化 (Ridge)#
L2 正則化是通過向模型的損失函數中添加 L2 範數懲罰項來實現的。L2 範數是指模型權重參數的平方和的平方根。L2 正則化的目標是最小化損失函數和 L2 範數懲罰項的和。它的效果是減小權重參數的值,使模型的權重參數更加平滑和穩定。
效果類似於 weight decay。鼓勵模型具有較小的系數,但不會導致稀疏性。
L1 | L2 | |
---|---|---|
作用 | 能夠產生更加稀疏的模型 | 有助於計算病態的問題 |
概率先驗 | 參數服從拉普拉斯分布 | 參數服從高斯先驗分布 |
Dropout#
Dropout 正則化是通過在訓練過程中隨機將一部分神經元的輸出置為零來實現的。具體而言,每個神經元有一定的概率被丟棄,使得模型無法依賴於特定的神經元,從而增強模型的泛化能力。
(1)取平均的作用: 先回到標準的模型即沒有 dropout,我們用相同的訓練數據去訓練 5 個不同的神經網絡,一般會得到 5 個不同的結果,此時我們可以採用 “5 個結果取均值” 或者 “多數取勝的投票策略” 去決定最終結果。例如 3 個網絡判斷結果為數字 9, 那麼很有可能真正的結果就是數字 9,其它兩個網絡給出了錯誤結果。這種 “綜合起來取平均” 的策略通常可以有效防止過擬合問題。因為不同的網絡可能產生不同的過擬合,取平均則有可能讓一些 “相反的” 擬合互相抵消。dropout 掉不同的隱藏神經元就類似在訓練不同的網絡,隨機刪掉一半隱藏神經元導致網絡結構已經不同,整個 dropout 過程就相當於對很多個不同的神經網絡取平均。而不同的網絡產生不同的過擬合,一些互為 “反向” 的擬合相互抵消就可以達到整體上減少過擬合。
(2)減少神經元之間複雜的共適應關係: 因為 dropout 程序導致兩個神經元不一定每次都在一個 dropout 網絡中出現。這樣權值的更新不再依賴於有固定關係的隱含節點的共同作用,阻止了某些特徵僅僅在其它特定特徵下才有效果的情況。迫使網絡去學習更加魯棒的特徵,這些特徵在其它的神經元的隨機子集中也存在。換句話說假如我們的神經網絡是在做出某種預測,它不應該對一些特定的線索片段太過敏感,即使丟失特定的線索,它也應該可以從眾多其它線索中學習一些共同的特徵。從這個角度看 dropout 就有點像 L1,L2 正則,減少權重使得網絡對丟失特定神經元連接的魯棒性提高。
(3)Dropout 類似於性別在生物進化中的角色:物種為了生存往往會傾向於適應這種環境,環境突變則會導致物種難以做出及時反應,性別的出現可以繁衍出適應新環境的變種,有效的阻止過擬合,即避免環境改變時物種可能面臨的滅絕。
- Vanilla Dropout:測試時輸出乘以
- Inverted Dropout:(主流方法)訓練時數據乘以
import numpy as np
class Dropout:
def __init__(self, dropout_rate):
self.dropout_rate = dropout_rate
self.mask = None
def forward(self, x, is_train):
if is_train:
self.mask = np.random.binomial(1, 1 - self.dropout_rate, size=x.shape) / (1 - self.dropout_rate)
out = x * self.mask
else:
out = x
return out
def backward(self, dout):
dx = dout * self.mask
return dx
早停法#
早停法是一種基於驗證集性能的策略,用於在訓練過程中提前停止模型的訓練。通過監控模型在驗證集上的性能指標(如損失函數或準確率),如果模型的性能在一定的訓練輪數內沒有改善,就提前終止訓練,以避免過擬合。
批量正則化#
批量正則化是通過對每個批次(batch)的輸入進行歸一化,使得網絡中間層的輸入保持較小的分布變化。它通過減小輸入數據的內部協方差移動和縮放來加速網絡的訓練過程,並且有助於防止梯度消失或梯度爆炸。
適用於 batch 較大、序列長度固定的情形,如 CNN。
$\gamma$ 和 $\beta$ 分別是縮放因子和偏移量。因為減去均值除以方差未必是最好的分布。所以要加入兩個可學習變量來完善數據分布以達到比較好的效果。
訓練的時候使用滑動平局收集均值和方差,測試的時候直接使用。
import numpy as np
class BatchNormalization:
def __init__(self, epsilon=1e-5, momentum=0.9):
self.epsilon = epsilon
self.momentum = momentum
self.running_mean = None
self.running_var = None
self.gamma = None
self.beta = None
def forward(self, X, training=True):
N, D = X.shape
if self.running_mean is None:
self.running_mean = np.zeros(D)
if self.running_var is None:
self.running_var = np.zeros(D)
if training:
sample_mean = np.mean(X, axis=0)
sample_var = np.var(X, axis=0)
X_normalized = (X - sample_mean) / np.sqrt(sample_var + self.epsilon)
self.running_mean = self.momentum * self.running_mean + (1 - self.momentum) * sample_mean
self.running_var = self.momentum * self.running_var + (1 - self.momentum) * sample_var
self.gamma = np.ones(D)
self.beta = np.zeros(D)
else:
X_normalized = (X - self.running_mean) / np.sqrt(self.running_var + self.epsilon)
out = self.gamma * X_normalized + self.beta
return out
BN 解決了什麼問題?
神經網絡在做非線性變換前的激活輸入值隨著網絡深度加深,其分布逐漸發生偏移(內部協變量偏移)。之所以訓練收斂慢,一般是整體分布逐漸往非線性函數的區間兩端靠近,導致反向傳播底層網絡訓練梯度消失。BN 就是通過一定的正則化手段,每層神經網絡任意神經元輸入值的分布強行拉回到均值為 0 方差為 1 的標準正態分布。
層正則化#
適用於變長序列,如 RNN、Transformer。
如果 BN 應用到 NLP 任務,相當於是在對默認了在同一個位置的單詞對應的是同一種特徵。
其他#
- Elastic Net 正則化:結合了 L1 正則化和 L2 正則化的一種方法。它在損失函數中同時引入 L1 範數和 L2 範數的懲罰項,通過調節兩者的權重超參數來平衡正則化的影響。Elastic Net 正則化能夠同時實現特徵選擇和權重縮小的效果。
- 數據增強是一種通過對原始訓練數據進行一系列隨機變換或擴充來增加數據樣本量的技術。這些變換可以包括隨機旋轉、平移、縮放、翻轉等操作。數據增強可以幫助模型更好地泛化,並減輕過擬合的問題。
- 參數共享是一種在神經網絡中共享部分參數的技術。在某些具有相似結構或功能的層之間共享參數可以減少模型的參數量,從而降低模型的複雜性和過擬合的風險。參數共享通常用於卷積神經網絡(Convolutional Neural Networks)中。