層正規化(Layer Normalization)

Photo by Sestrjevitovschii Ina on Unsplash
Photo by Sestrjevitovschii Ina on Unsplash
正規化(normalization)是一種來自統計學的資料轉換技術,用來調整資料的平均值與變異數,使其更穩定、可預測。在 deep learning 中,normalization 被廣泛應用於提升模型訓練的穩定性與效率。本文將說明 normalization 的原始概念,介紹 Batch Normalization 的設計與限制,並深入探討 Layer Normalization 如何解決這些限制,成為現代 language models 中的標準做法。

正規化(normalization)是一種來自統計學的資料轉換技術,用來調整資料的平均值與變異數,使其更穩定、可預測。在 deep learning 中,normalization 被廣泛應用於提升模型訓練的穩定性與效率。本文將說明 normalization 的原始概念,介紹 Batch Normalization 的設計與限制,並深入探討 Layer Normalization 如何解決這些限制,成為現代 language models 中的標準做法。

正規化(Normalization)

Normalization 是一種來自統計與資料前處理的基本方法,其目的是重新調整資料的分佈,使其在數值尺度上更加一致、可預期。也就是說,它就是在不改變資料相對關係的前提下,調整其中心與尺度,使得資料更易於後續的建模或計算處理。在實務應用中,normalization 可以幫助模型更容易學習,也讓不同來源或尺度的特徵能夠比較與整合。

我們將介紹最常見的兩種 normalization。

標準化(Z-score Normalization)

Z-score Normalization 將資料轉換為平均值(mean \mu)為 0、標準差(standard deviation \sigma)為 1 的分佈。

\hat{x}_i = \frac{x_i - \mu}{\sigma}

這種方式讓模型在處理不同特徵時不會因為數值尺度不同而偏頗,有助於梯度下降等數值優化方法的穩定性。

最小最大正規化(Min-max Normalization)

Min-max Normalization 將資料縮放至某個區間(如 [0, 1])內。

\hat{x}_i = \frac{x_i - \min(x)}{\max(x) - \min(x)}

常見於影像處理等需要將特徵壓縮在特定範圍內的應用中。

Deep Learning 與 Normalization

在 deep neural networks 中,資料會經過多層 non-linear 轉換,每一層都可能改變資料的分佈。而這種分佈的不斷改變(稱為 Internal Covariate Shift)會使得模型訓練變得困難,特別是當輸入資料的分佈在訓練過程中不斷漂移時,模型每一層都需要不停調整。

Normalization 的引入,正是為了降低這樣的問題。它可以穩定訊號的分佈,避免過大或過小的值干擾梯度。它減少對 weights 初始化與 learning rate 設定的敏感性。因此,normalization 可以加速收斂,甚至改善泛化能力。

批次正規化(Batch Normalization)

2015 年,Sergey Ioffe et al. 提出 Batch Normalization。它的核心想法是,對每一層的輸出,以 mini-batch 為單位,在特徵維度上進行標準化,使每個通道的輸出的 mean 為 0 且 standard deviation 為 1。

對一個 neuron 的輸出 x_i,其公式為:

\displaystyle \mu = \frac{1}{m} \sum_{i=1}^{m} x_i, \quad \sigma^2 = \frac{1}{m} \sum_{i=1}^{m} (x_i - \mu)^2 \\\\ \hat{x}_i = \frac{x_i - \mu}{\sqrt{\sigma^2 + \varepsilon}}, \quad y_i = \gamma \hat{x}_i + \beta \\\\ \mu:\text{ Mean} \\\\ \sigma^2:\text{ Variance} \\\\ m: \text{Batch size} \\\\ x_i: \text{Input to } i^{th} \text{ neuron} \\\\ y_i: \text{Output from } i^{th} \text{ neuron} \\\\ \varepsilon: \text{ A small scalar preventing division by 0} \\\\ \alpha,\beta:\text{ Trainable parameters}

其中 \gamma\beta 是可訓練參數,用來恢復表達能力。Batch Normalization 可大幅改善訓練穩定性、加速收斂,也讓更深的網路變得可行。

但 Batch Normalization 也有其侷限性。它依賴 batch size,因為小 batch 可能導致統計量不穩,且不適用於 RNNs。例外,訓練與推論行為不一致,需要額外處理 moving average。

以下是 Batch Normalization 的實作。

import torch
import torch.nn as nn


class BatchNorm(nn.Module):
    def __init__(self, num_features, eps=1e-5, momentum=0.1):
        super().__init__()
        self.eps = eps
        self.momentum = momentum
        self.gamma = nn.Parameter(torch.ones(num_features))
        self.beta = nn.Parameter(torch.zeros(num_features))
        self.register_buffer('running_mean', torch.zeros(num_features))
        self.register_buffer('running_var', torch.ones(num_features))

    def forward(self, x):
        if self.training:
            mean = x.mean(dim=0)
            var = x.var(dim=0, unbiased=False)
            self.running_mean = (1 - self.momentum) * self.running_mean + self.momentum * mean.detach()
            self.running_var = (1 - self.momentum) * self.running_var + self.momentum * var.detach()
            x_hat = (x - mean[None, :]) / torch.sqrt(var[None, :] + self.eps)
        else:
            x_hat = (x - self.running_mean[None, :]) / torch.sqrt(self.running_var[None, :] + self.eps)
        return self.gamma[None, :] * x_hat + self.beta[None, :]


if __name__ == "__main__":
    torch.manual_seed(42)
    batch_size = 6
    feature_dim = 8

    x = torch.randn(batch_size, feature_dim)

    bn = BatchNorm(feature_dim)

    print("=== Training Mode ===")
    bn.train()
    y_bn_train = bn(x)
    print("BatchNorm mean/std:", y_bn_train.mean().item(), y_bn_train.std().item())

    print("\n=== Eval Mode ===")
    bn.eval()
    x_new = torch.randn(batch_size, feature_dim)
    y_bn_eval = bn(x_new)
    print("BatchNorm mean/std:", y_bn_eval.mean().item(), y_bn_eval.std().item())

層正規化(Layer Normalization)

2016 年,Jimmy Lei Ba et al. 提出 Layer Normalization,解決了 Batch Normalization 無法處理的場景,特別是在語言模型與 recurrent network 中的應用。它們之間的差異在於,Layer Normalization 是針對單一樣本內的所有 hidden units 做 normalization,而非跨樣本統計。其公式為:

\displaystyle \mu = \frac{1}{H} \sum_{i=1}^{H} h_i, \quad \sigma^2 = \frac{1}{H} \sum_{i=1}^{H} (h_i - \mu)^2 \\\\ \hat{h}_i = \frac{h_i - \mu}{\sqrt{\sigma^2 + \epsilon}}, \quad y_i = \gamma \hat{h}_i + \beta \\\\ H:\text{ Number of hidden units}

由於每個樣本各自計算 mean 與 variance,因此 Layer Normalization 不依賴 batch,所以它的推論與訓練可以一致,並適用於 RNNs。

以下是 Layer Normalization 的實作。

import torch
import torch.nn as nn


class LayerNorm(nn.Module):
    def __init__(self, normalized_shape, eps=1e-5):
        super().__init__()
        if isinstance(normalized_shape, int):
            normalized_shape = (normalized_shape,)
        self.normalized_shape = normalized_shape
        self.eps = eps
        self.gamma = nn.Parameter(torch.ones(*normalized_shape))
        self.beta = nn.Parameter(torch.zeros(*normalized_shape))

    def forward(self, x):
        dims = [-i for i in range(1, len(self.normalized_shape) + 1)]
        mean = x.mean(dim=dims, keepdim=True)
        var = x.var(dim=dims, keepdim=True, unbiased=False)
        x_hat = (x - mean) / torch.sqrt(var + self.eps)
        return self.gamma * x_hat + self.beta


if __name__ == "__main__":
    torch.manual_seed(42)
    batch_size = 6
    feature_dim = 8

    x = torch.randn(batch_size, feature_dim)

    ln = LayerNorm(feature_dim)

    print("=== Training Mode ===")
    ln.train()
    y_ln_train = ln(x)
    print("LayerNorm mean/std:", y_ln_train.mean().item(), y_ln_train.std().item())

    print("\n=== Eval Mode ===")
    ln.eval()
    x_new = torch.randn(batch_size, feature_dim)
    y_ln_eval = ln(x_new)
    print("LayerNorm mean/std:", y_ln_eval.mean().item(), y_ln_eval.std().item())

結語

現今的 NLP 模型,如 Transformer、BERT、GPT 系列、T5、LLaMA 等,幾乎都將 Layer Normalization 作為標準元件。它常常被放在注意力(attention)機制與 feed-forward layer 之前或之後,與 residual connection 搭配使用。在這些模型中,Layer Normalization 有助於穩定長序列的學習,尤其在自注意力(self-attention)結構中,能有效維持每一層輸出訊號的穩定性。

參考

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *

You May Also Like