在機器學習中,歸一化是一個非常重要的工具,它能幫助我們加速訓練的速度。在我們前面的SiglipVisionTransformer 中,也有用到歸一化層,如下代碼所示:
class SiglipVisionTransformer(nn.Module): ##視覺模型的第二層,將模型的調用分為了圖像嵌入模型和transformer編碼器模型的調用def __init__(self, config:SiglipVisionConfig):super().__init__()self.config = configself.embed_dim = config.hidden_sizeself.embeddings = SiglipVisionEmbeddings(config) ## 負責將圖像嵌入成向量self.encoder = SiglipEncoder(config) ## 負責將向量編碼成注意力相關的向量self.post_layer_norm = nn.LayerNorm(embed_dim, eps=config.layer_norm_eps) ## 層歸一化def forward(self, pixel_values:torch.Tensor) -> torch.Tensor:"""
pixel_values: [Batch_size,Channels,Height,Width]"""## [ Batch_size,Channels,Height,Width] -> [Batch_size,Num_Patches,Embedding_size]
hidden_states = self.embeddings(pixel_values) ## 將圖像嵌入成向量# [Batch_size,Num_Patches,Embedding_size] -> [Batch_size,Num_Patches,Embedding_size]
last_hidden_state = self.encoder(hidden_states) ## 將向量編碼成注意力相關的向量# [Batch_size,Num_Patches,Embedding_size] -> [Batch_size,Num_Patches,Embedding_size]
last_hidden_state = self.post_layer_norm(last_hidden_state)return last_hidden_state
這里的post_layer_norm 就是歸一化層,所以本文將一起介紹歸一化層。
歸一化解決的問題:
歸一化主要解決的是神經網絡訓練的過程中會出現的 “協變量偏移” 的問題。
協變量偏移(Covariate Shift)是指由于輸入樣本的分布不均勻導致神經網絡第一層的輸入會有劇烈變化,而第一層神經網絡輸入的劇烈變化又會導致神經網絡第一層的輸出產生劇烈變化,從而將影響傳遞到神經網絡之后的每一層,導致每一輪迭代,神經網絡輸出層的輸出都劇烈變化從而導致梯度非常不穩定,參數找不到一個穩定地優化方向,從而導致訓練緩慢。
Batch Normalization
假設有一個 mini-batch 的輸入 ,也就是:
- :batch size
- :通道數(對全連接層來說是特征維度)
- :空間維度(在卷積層中)
其實本質上,Batch Normalization 希望讓輸入的特征變化得不再那么劇烈,它希望樣本所有的特征都基于當前的批次做一次歸一化,這樣的話當前批次下的特征就不會劇烈變化了。
值得注意的是:對圖像輸入的Batch Normalization和對普通特征的Batch Normalization的計算略有差別,假定圖像的輸入是 [ N, C, H, W ],那么計算公式如上所示,torch會對通道的維度進行歸一化,讓每一個通道的像素值通過該通道所有圖片的像素值得到的平均值和方差做歸一化,這是因為由于在圖像處理的卷積神經網絡里面,同一個通道共享同一個卷積核,故整個通道的所有像素值都看成一個特征。
而如果是普通的特征,則輸入形如【 N, D 】,N為Batch_Size, D是特征維度,則對每一個特征通過計算所有N個對應特征的平均值和方差來做歸一化。
總的來說,如下圖所示:
問題所在
其主要問題就在于依賴 mini-batch:批量太小時效果差
- BatchNorm 的均值和方差是 在 batch 維度上估算 的。
- 如果 batch size 很小(比如在線學習、NLP中的RNN),統計結果不穩定,歸一化效果會變差。
- 對于 batch size=1 時,根本無法統計 batch 內部分布。
因為BN 嘗試用一個批次代表整體樣本的分布,但是這只有在批次樣本量很大的時候才能擬合,如果批次樣本量很小,那么又會出現協變量偏移的問題。
于是又引申出了layer_normalization....
Layer Normalization
Layer Normalization(層歸一化)是為了克服 Batch Normalization 的局限性 而提出的,尤其在 batch size 很小 或 處理序列模型(如 RNN、Transformer) 時非常有用。
LN 的核心思想是:
在一個樣本內部的所有特征維度上做歸一化,而不是像 BatchNorm 那樣在 batch 維度上歸一化。
LN的做法比較簡單:
在圖像卷積場景下,如果輸入是(N,C,H,W),即分別代表Batch size,通道數,圖像高度和寬度,此時我們有N張不同的圖像,圖像有C個特征,因為每個通道的一整張圖像像素都是其一個特征,故一張圖像總共有C個特征,每個特征要看成 H * W維的向量。于是我們對所有的特征計算均值和方差進行歸一化。
總結
不管是BN還是LN,歸一化的操作都使得每一個計算的value處于標準(0,1)的正態分布中,故緩解了訓練過程中協變量偏移的問題。