技術共有

バッチノルム

2024-07-12

한어Русский языкEnglishFrançaisIndonesianSanskrit日本語DeutschPortuguêsΕλληνικάespañolItalianoSuomalainenLatina

0. 概要

ずっと前に会った BatchNorm そしてLayerNorm、当時は彼らがデータを実行したことは大まかに知られていました標準化: x = x − μ σ bm{x} = frac{bm{x} - bm{mu}}{bm{sigma}}バツ=σバツμ もちろんこれは単純ですが、実際のデータはさらに複雑です。履歴書のタスクデータイメージの観点から見ると、バッチのデータは通常次のようになります。 [B, C, H, W]; のために NLP タスクデータ文に関して言えば、バッチのデータは通常次のようになります。 [B, T, D]。 それ XXNorm どのように計算されるのでしょうか? バッチ全体のすべての数値が一度に計算されるわけではありません。 μ bm{ミュー}μ そして σ bm{シグマ}σ、それらは異なります。

そこで、いろいろな情報を調べてみたのですが、「そんな汚いブログは読まないでください。外国人はまだすごいです。質問に答えるだけでわかりやすく説明してくれるんです!」という講師の言葉に本当に同意しました。コメントエリア: 《なぜトランスフォーマーはバッチノルムではなくレイヤーノルムを使用するのですか?》

1. 計算方法は?

このセクションでは理論とコードの両方の観点から詳しく説明します BatchNorm そしてLayerNorm 計算方法。

1.1 まず理論的に話して、Qianwen の一般的な意味について尋ねましょう

>>>>> 同義前文 >>>>>
聞く: レイヤーノルムとバッチノルムの違いは何ですか? 式を説明してください。

答え: レイヤー正規化 (LayerNorm) そしてバッチ正規化 (BatchNorm) 正規化層を通じてニューラル ネットワークのトレーニングを高速化するために使用される技術です値を入力またはアクティブ化しますただし、ネットワーク学習がより安定して効率的になります。実装そして該当シーンは異なります。

バッチ正規化 (BatchNorm)
BatchNorm 主にトレーニング中データのミニバッチの場合それを正規化すること。メインターゲットはい内部共変量シフトを減らす(内部共変量シフト)、つまり、ネットワークの順伝播プロセス中に、中間層の入力分布がトレーニングの反復とともに変化します。 BatchNorm 計算による現在のミニバッチの平均と分散入力を正規化するための式は次のとおりです。
設定 x bm{x}バツ はミニバッチ内の入力ベクトルです。 μB bm{mu}_BμB そして σ B 2 bm{シグマ}^2_BσB2 はそれぞれミニバッチの平均と分散です。BatchNorm 出力 y bm{y}ええ これは次のように表現できます。 x ^ = x − μ B μ B 2 + ϵ y ^ = γ x ^ + β^んんんバツ=んんんバツんんんμBんんんμ2B+ϵ^んんんええ=γ^んんんバツ+β バツ^ええ^=μB2+ϵ バツμB=γバツ^+β で、 γガンマγ そして βベータβ 学習可能なパラメータです。 ϵ イプシロンϵ 数値の安定性のために使用される小さな定数です。

レイヤー正規化 (LayerNorm)
LayerNorm 目的は、各サンプルレベルでミニバッチ統計に依存せずに正規化を実行します。 LayerNorm シーケンス モデルに適しています (例:LSTM またはTransformer)など、その中にはサンプル間に依存関係がある可能性がありますまたは ミニバッチのサイズは固定されていない可能性があります. LayerNorm 計算する各サンプル特徴の平均と分散、式は次のとおりです。
設定 x bm{x}バツ は単一サンプルの特徴ベクトル、 μL bm{mu}_Lμ そして σ L 2 bm{シグマ}^2_Lσ2 はそれぞれサンプル特性の平均と分散です。LayerNorm 出力 y bm{y}ええ これは次のように表現できます。 x ^ = x − μ L μ L 2 + ϵ y ^ = γ x ^ + β^んんんバツ=んんんバツんんんμんんんμ2+ϵ^んんんええ=γ^んんんバツ+β バツ^ええ^=μ2+ϵ バツμ=γバツ^+β こっちも一緒、 γガンマγ そして βベータβ 学習可能なパラメータです。 ϵ イプシロンϵ は小さな定数です。

違い

  • データに依存する: BatchNorm に依存しますミニバッチ統計、 そして LayerNorm に依存します単一サンプルの特性統計;
  • アプリケーションシナリオ: BatchNorm より適したコンピュータービジョンのタスク、 そして LayerNorm より適した自然言語処理タスク特にシーケンス データを扱う場合。
  • 計算効率: BatchNorm ミニバッチ内で並列処理を利用できるため、並列コンピューティングの方が効率的である可能性がありますが、LayerNorm 各サンプルの計算は独立しており、異なる長さのシーケンス データの処理により適しています。

どちらの方法にも独自の長所と短所があり、どちらの方法を選択するかは通常、特定のアプリケーション シナリオとデータの特性によって異なります。
<<<<< 同義前文<<<<

混乱していますか? 「現在のミニバッチの平均と分散」とは何ですか? 「各サンプル特徴の平均と分散」とは何ですか? 外国人の答えの方が適切です。

まず基本的な概念を理解しましょう。

  • 実例: サンプル、 画像 履歴書の場合、 NLP の場合;
  • 要素: サンプルの成分、 ピクセル 画像については、言葉 文のために;
  • 特徴:元素の特性、 RGB値 pexelの場合、埋め込み 単語のために。

これはデータに反映されています。

  • [B, C, H, W] バッチです、[C, H, W] インスタンスです、[C] を含むピクセルです。C 特徴。
  • [B, T, L] バッチです、[T, L] インスタンスです、[L] それも含めての言葉ですL 特徴。

以下に示すように:

Batch Dimension 側から見ると、後ろに伸びたそれぞれの小さな四角形は、左の図の長い紫色のバー、ピクセルの RGB 特徴、またはワード ベクトルなどの要素を表します。LayerNorm 与えるそれぞれの要素 平均と分散を計算すると、次のようになります。BxL 平均と分散 (またはBxHxW)。 それから各要素は独立して標準化されています右側の図の紫色のパッチは特徴であり、バッチ内のすべての単語の最初の特徴です。 BatchNorm 与えるそれぞれの特徴 平均と分散を計算すると、次のようになります。L 平均と分散 (またはC)。 それから各機能は独立して標準化されています.


Transformer は上記に準拠していないことに注意してください。LayerNorm 計算されているが与えられた各インスタンス 平均と分散を計算すると、次のようになります。B 平均と分散、そして各インスタンスは個別に標準化されています正確に言うと、次の図のようになります。

1.2 PyTorch の場合 BatchNorm そしてLayerNorm
1.2.1 BatchNorm

PyTorchでは、 BatchNorm ポイントnn.BatchNorm1d, nn.BatchNorm2d そしてnn.BatchNorm3d、異なる次元のデータに対してそれぞれ次のようになります。

  • nn.BatchNorm1d: (N, C) または(N, C, L)
  • nn.BatchNorm2d: (N, C, H, W)
  • nn.BatchNorm3d: (N, C, D, H, W)

ソースコードを表示:

class BatchNorm1d(_BatchNorm):
	r"""
	Args:
		num_features: number of features or channels `C` of the input

	Shape:
		- Input: `(N, C)` or `(N, C, L)`, where `N` is the batch size,
		  `C` is the number of features or channels, and `L` is the sequence length
		- Output: `(N, C)` or `(N, C, L)` (same shape as input)
	"""
	def _check_input_dim(self, input):
		if input.dim() != 2 and input.dim() != 3:
			raise ValueError(f"expected 2D or 3D input (got {input.dim()}D input)")
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

例:

>>> m = nn.BatchNorm1d(100)  # C=100	   # With Learnable Parameters
>>> m = nn.BatchNorm1d(100, affine=False)  # Without Learnable Parameters
>>> input = torch.randn(20, 100)  # (N, C)
>>> output = m(input)
>>> # 或者
>>> input = torch.randn(20, 100, 30)  # (N, C, L)
>>> output = m(input)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

γ 、 β bm{ガンマ}、 bm{ベータ}γ,β は学習可能なパラメータであり、shape=(C,)、パラメータ名は .weight そして.bias:

>>> m = nn.BatchNorm1d(100)
>>> m.weight
Parameter containing:
tensor([1., 1., ..., 1.], requires_grad=True) 
>>> m.weight.shape
torch.Size([100])
>>> m.bias
Parameter containing:
tensor([0., 0., ..., 0.], requires_grad=True)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

BatchNorm2d そしてBatchNorm3d は同じですが、違うのは_check_input_dim(input):

class BatchNorm2d(_BatchNorm):
	r"""
	Args:
		num_features: `C` from an expected input of size `(N, C, H, W)`
	Shape:
		- Input: :math:`(N, C, H, W)`
		- Output: :math:`(N, C, H, W)` (same shape as input)
	"""
	def _check_input_dim(self, input):
		if input.dim() != 4:
			raise ValueError(f"expected 4D input (got {input.dim()}D input)")
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

例:

>>> m = nn.BatchNorm2d(100)
>>> input = torch.randn(20, 100, 35, 45)
>>> output = m(input)
  • 1
  • 2
  • 3
class BatchNorm3d(_BatchNorm):
	r"""
	Args:
		num_features: `C` from an expected input of size `(N, C, D, H, W)`
	Shape:
		- Input: :math:`(N, C, D, H, W)`
		- Output: :math:`(N, C, D, H, W)` (same shape as input)
	"""
	def _check_input_dim(self, input):
		if input.dim() != 5:
			raise ValueError(f"expected 5D input (got {input.dim()}D input)")
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

例:

>>> m = nn.BatchNorm3d(100)
>>> input = torch.randn(20, 100, 35, 45, 10)
>>> output = m(input)
  • 1
  • 2
  • 3
1.2.2 LayerNorm

と違う BatchNorm(num_features), LayerNorm(normalized_shape) パラメータは次のとおりです。input.shapex 個人のdim、 のように [B, T, L] 最後の二次元[T, L]の場合、各文は独立して標準化されます。 L または[L]の場合、各単語ベクトルは独立して標準化されます。

NLPの例

>>> batch, sentence_length, embedding_dim = 20, 5, 10
>>> embedding = torch.randn(batch, sentence_length, embedding_dim)
>>> layer_norm = nn.LayerNorm(embedding_dim)
>>> layer_norm(embedding)  # Activate module
  • 1
  • 2
  • 3
  • 4

画像例

>>> N, C, H, W = 20, 5, 10, 10
>>> input = torch.randn(N, C, H, W)
>>> # Normalize over the last three dimensions (i.e. the channel and spatial dimensions)
>>> layer_norm = nn.LayerNorm([C, H, W])
>>> output = layer_norm(input)
  • 1
  • 2
  • 3
  • 4
  • 5

つまり、「さまざまな」ものだけではなく、 要素 「独自に標準化」と「それぞれ実例 独立して正規化されており、任意の値を計算できます。最後のx次元を正規化する.

1.3 計算過程の検討
import torch
from torch import nn

# >>> 手动计算 BatchNorm2d >>>
weight = torch.ones([1, 3, 1, 1])
bias = torch.zeros([1, 3, 1, 1])

x = 10 * torch.randn(2, 3, 4, 4) + 100
mean = x.mean(dim=[0, 2, 3], keepdim=True)
std = x.std(dim=[0, 2, 3], keepdim=True, unbiased=False)
print(x)
print(mean)
print(std)

y = (x - mean) / std
y = y * weight + bias
print(y)
# <<< 手动计算 BatchNorm2d <<<

# >>> nn.BatchNorm2d >>>
bnm2 = nn.BatchNorm2d(3)
z = bnm2(x)
print(z)
# <<< nn.BatchNorm2d <<<
print(torch.norm(z - y, p=1))
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25

手動で計算すると、 nn.BatchNorm 計算はほぼ同じですが、多少の誤差はあるかもしれません。 ϵ イプシロンϵ その影響については、こちらでご確認ください。unbiased=False 公式ドキュメントでは次のように説明されていることに注意することが重要です。

"""
At train time in the forward pass, the standard-deviation is calculated via the biased estimator,
equivalent to `torch.var(input, unbiased=False)`.
However, the value stored in the moving average of the standard-deviation is calculated via
the unbiased  estimator, equivalent to `torch.var(input, unbiased=True)`.

Also by default, during training this layer keeps running estimates of its computed mean and
variance, which are then used for normalization during evaluation.
"""
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

ここで焦点を当てるのではなく、計算プロセスを確認したいだけです。 unbiased簡単に説明すると、

  • トレーニング ステージでは、分散のバイアス付き推定値が計算されますが、分散付き移動平均の分散は不偏推定値です。
  • トレーニング中に、mean と var の移動平均が保存され、テスト段階で使用されます。