バッチ正規化シミュレーター 戻る
機械学習

バッチ正規化シミュレーター

ディープニューラルネットワークの学習を安定させる「バッチ正規化(Batch Normalization)」を可視化するツールです。ミニバッチの平均・標準偏差、スケールγ、シフトβを変えると、ある活性値が正規化値x̂を経てBN出力yになる過程と、層をまたぐ分布の変化がリアルタイムで分かります。

パラメータ設定
バッチの平均 μB
ミニバッチに含まれる生の活性値の平均
バッチの標準偏差 σB
生の活性値のばらつき(広がり)
スケールパラメータ γ
学習可能。出力の標準偏差を決める
シフトパラメータ β
学習可能。出力の平均を決める
着目する活性値 x
x̂・y を追跡する1つのサンプル値
計算結果
正規化値 x̂
BN出力 y
正規化後バッチ平均
正規化後バッチ標準偏差
出力バッチ平均
出力バッチ標準偏差
分布の変換 — 生バッチ → 正規化 → スケール・シフト

左から生のバッチ、正規化後(平均0・標準偏差1)、アフィン変換後(平均β・標準偏差γ)の分布。着目サンプル x → x̂ → y の位置を点で示します。

入出力マッピング y(x)
バッチ統計の比較(平均・標準偏差)
理論・主要公式

$$\hat x=\frac{x-\mu_B}{\sqrt{\sigma_B^{2}+\varepsilon}},\qquad y=\gamma\,\hat x+\beta$$

正規化値 x̂ とBN出力 y。バッチの平均 μB と分散 σB² はミニバッチ全体から計算し、スケール γ とシフト β は誤差逆伝播で学習する。ε は数値安定化のための微小定数(本ツールでは 1e-5)。

$$\mathrm{E}[\hat x]\approx0,\quad \mathrm{Std}[\hat x]\approx1,\qquad \mathrm{E}[y]=\beta,\quad \mathrm{Std}[y]=\gamma$$

正規化後のバッチは平均≈0・標準偏差≈1。アフィン変換後のバッチは平均=β・標準偏差=γ になる。

バッチ正規化とは

🙋
ニューラルネットの解説でよく出てくる「バッチ正規化(Batch Normalization)」って、結局なにをしているんですか?
🎓
ざっくり言うと「各層の出力の数値の大きさを揃える」処理だよ。深いネットワークだと、ある層の出力(活性値)が層を進むうちにどんどん大きくなったり小さくなったりしてしまう。バッチ正規化は、ミニバッチに入っている活性値を見て、平均が0、標準偏差が1になるように引き算と割り算をするんだ。左の「バッチの平均 μB」を動かすと、生の活性値の山が左右に動くのが見えるよね。それを毎回0に戻してあげるイメージだ。
🙋
数値を揃えるだけで、そんなに学習が変わるものなんですか?
🎓
変わるんだ。前の層の重みが更新されると、次の層が受け取る入力の分布もズレてしまう。これを「内部共変量シフト」と呼ぶ。次の層から見ると、入力のターゲットが毎ステップ動いていることになって学習しにくい。バッチ正規化で分布を平均0・標準偏差1に固定してあげると、損失の曲面がなめらかになって勾配が暴れにくくなる。だから学習率を大きめに取れて、収束が速くなるんだよ。
🙋
なるほど。でも、いつも平均0・標準偏差1に固定したら、層が表現できる幅が狭くなりませんか?
🎓
いい疑問だね。まさにそれを解決するのが γ(スケール)と β(シフト)だ。正規化したあとに y = γ·x̂ + β というアフィン変換を1つ通す。γ と β はネットワークの重みと同じように学習されるパラメータで、もし正規化が邪魔なら γ=σB、β=μB を学習して元の分布に戻すこともできる。左の γ を動かすと出力の標準偏差が、β を動かすと出力の平均がそのまま変わるのを確認してみて。γ=1・β=0 がちょうど「純粋な正規化」の状態だ。
🙋
学習のときはバッチの平均を使うんですよね。じゃあ、推論で画像を1枚だけ入れるときはどうするんですか?
🎓
そこが実務でつまずきやすいところだ。1枚だけだとバッチの平均も標準偏差も計算できない(標準偏差が0になってしまう)。だから学習中に μB と σB² の移動平均をこっそり貯めておいて、推論ではその固定値を使う。PyTorch なら model.eval()、TensorFlow なら training=False で切り替わる。これを忘れて学習モードのまま推論すると、同じ画像でも毎回結果が変わる、という不可解なバグになるんだ。
🙋
最近は「レイヤー正規化」とかも聞きます。バッチ正規化と使い分けるんですか?
🎓
そう、正規化にはいくつか種類があるんだ。バッチ正規化はバッチ方向(複数サンプル)にわたって統計を取るから、バッチサイズが小さいと統計が不安定になる。一方レイヤー正規化は1サンプル内の特徴量方向で正規化するからバッチサイズに依存しない。だから可変長の系列を扱うTransformerやRNNではレイヤー正規化が主流で、CNNの画像分類ではバッチ正規化が今でも定番、というふうに使い分けられているよ。

よくある質問

ある活性値 x をバッチ正規化するには、まずミニバッチの平均 μB と標準偏差 σB を使って x̂ = (x − μB) / √(σB² + ε) と正規化します。ε は数値安定化のための微小定数(本ツールでは 1e-5)です。次に学習可能なスケール γ とシフト β でアフィン変換し、y = γ·x̂ + β を最終出力とします。例えば μB=3、σB=2.5、γ=1、β=0、x=6 なら x̂=(6−3)/√(6.25+1e-5)≈1.200、y=1.200 になります。
各層の活性値の分布は、前の層のパラメータが更新されるたびに動いてしまいます(内部共変量シフト)。バッチ正規化は各層の出力を平均0・標準偏差1に再中心化・再スケールするため、後続の層が見る入力分布が安定します。これにより損失曲面がなめらかになり、勾配が暴れにくくなるため、より大きな学習率が使え、収束が速くなります。また初期値への依存も弱まり、正則化に近い効果も得られます。
正規化だけだと活性値が常に平均0・標準偏差1に固定され、層が表現できる範囲が制限されてしまいます。学習可能な γ(スケール)と β(シフト)を加えることで、ネットワークは必要なら正規化を打ち消し、任意の平均・分散を回復できます。アフィン変換後のバッチは平均=β、標準偏差=γ になります。γ=1・β=0 は純粋な正規化と等価で、γ・β は誤差逆伝播で他の重みと一緒に学習されます。
学習時はミニバッチごとの μB・σB² を使いますが、推論時は1サンプルだけ入力することも多く、バッチ統計が不安定になります。そのため学習中に μB・σB² の移動平均(running mean / running variance)を蓄積しておき、推論時はその固定値を使います。これにより同じ入力に対して常に同じ出力が得られます。学習モードと推論モードでBNの挙動が変わる点は、フレームワークでよくあるバグの原因になります。

実世界での応用

画像分類のCNN:ResNet や Inception をはじめとする畳み込みニューラルネットワークでは、ほぼ全ての畳み込み層の直後にバッチ正規化が挿入されます。深さが100層を超えるネットワークでも安定して学習できるのは、各層の活性値分布をBNが揃えてくれるおかげです。BNが標準装備になったことで、慎重な重み初期化や小さな学習率に頼らずに済むようになりました。

畳み込み層との一体化(推論の高速化):推論時、バッチ正規化は学習で固定された統計(平均・分散)と γ・β を使う単なる線形変換になります。この線形性を利用して、直前の畳み込み層の重みにBNを「畳み込み」、1つの畳み込み演算に融合する最適化(BN folding / fusion)が広く使われます。これにより推論時の計算量とメモリアクセスが削減され、エッジデバイスでの高速化につながります。

転移学習とファインチューニング:事前学習済みモデルを別のデータセットに転用するとき、BNの移動統計(running mean / variance)の扱いが結果を左右します。新しいドメインの画像統計が元と大きく異なる場合、BN層だけを再学習する、あるいはBNを推論モードに固定する、といった戦略が使われます。BNの挙動を理解していないと、転移学習で精度が出ない原因を見落としがちです。

正則化効果の活用:バッチ正規化はミニバッチごとに統計が少しずつ変わるため、各サンプルに軽いノイズが乗るような効果があり、過学習を抑える正則化として働きます。BNを入れたモデルでは Dropout の必要性が下がることが知られており、両者を併用するかどうかはタスクごとに検証して決めます。学習が安定するだけでなく、汎化性能の面でもBNは寄与しています。

よくある誤解と注意点

まず最大の落とし穴が、「学習モードのまま推論してしまう」ことです。バッチ正規化は学習時にはミニバッチの統計を使い、推論時には学習中に蓄積した移動平均を使います。model.eval()(PyTorch)や training=False(Keras)への切り替えを忘れると、推論でもバッチ統計が使われ、同じ入力でもバッチの中身しだいで出力が変わってしまいます。バッチサイズ1で推論すると標準偏差が0に近づき、出力が発散することすらあります。逆に評価専用のループで eval() のまま学習を再開し、BNの統計が更新されないバグも頻発します。

次に、「小さいバッチサイズでもBNは同じように効く」という思い込みです。バッチ正規化はミニバッチ全体から平均と分散を推定するため、バッチサイズが2〜4のように小さいと統計の推定が非常に不安定になり、かえって学習を悪化させます。GPUメモリの制約で大きなバッチが組めない物体検出やセグメンテーションでは、この問題を避けるためにグループ正規化やレイヤー正規化が選ばれます。本ツールでは μB・σB を直接指定していますが、実際のBNでは「バッチが小さいほどこの推定値が当てにならない」という前提を忘れないでください。

最後に、「BNは内部共変量シフトを消すから効く、という説明が唯一の真実ではない」点です。提案当初は内部共変量シフトの抑制が効果の理由とされましたが、その後の研究で「BNの本質は損失曲面をなめらかにし、勾配の予測可能性を高めることだ」とする見方も有力になりました。さらにBNの前後にバイアス項を置くと冗長になる、活性化関数の前と後どちらに置くかで挙動が変わる、といった実装上の細かい注意点もあります。BNは「とりあえず入れれば効く」便利な道具ですが、なぜ効くのかは今も研究が続くテーマであることを知っておくと、結果の解釈を誤りにくくなります。

使い方ガイド

  1. 入力バッチの平均μ(-2.0~2.0範囲)と標準偏差σ(0.1~2.0範囲)を設定してバッチデータ分布を決定
  2. スケールパラメータγ(0.5~2.0)とシフトパラメータβ(-1.0~1.0)を調整してBN層の変換特性を制御
  3. リアルタイム出力で正規化値x̂、BN出力y、正規化後バッチ平均・標準偏差を確認し、内部共変量シフト抑制効果を視認

具体的な計算例

ResNet-50の初期畳み込み層におけるBN適用例:入力バッチ平均μ=0.85、標準偏差σ=0.72の活性値に対し、γ=1.2、β=0.3を設定した場合、正規化値x̂は平均0・分散1に統一され、BN出力y=γx̂+β=1.2x̂+0.3となります。この処理により、次層への入力分布が安定化し、学習率を25%向上させることが可能です。

実務での注意点